moved external functions to *-glue.c
this simplifies the linkage on windows and macosx which can't reference the binary for symbols git-svn-id: svn+ssh://svn.lighttpd.net/lighttpd/trunk@49 152afb58-edef-0310-8abb-c4023f1b3aa9
parent
a578a36169
commit
9219fc4eda
@ -0,0 +1,216 @@
|
||||
|
||||
#include "base.h"
|
||||
#include "buffer.h"
|
||||
#include "array.h"
|
||||
#include "log.h"
|
||||
|
||||
/**
|
||||
* like all glue code this file contains functions which
|
||||
* are the external interface of lighttpd. The functions
|
||||
* are used by the server itself and the plugins.
|
||||
*
|
||||
* The main-goal is to have a small library in the end
|
||||
* which is linked against both and which will define
|
||||
* the interface itself in the end.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/* handle global options */
|
||||
|
||||
/* parse config array */
|
||||
int config_insert_values_internal(server *srv, array *ca, const config_values_t cv[]) {
|
||||
size_t i;
|
||||
data_unset *du;
|
||||
|
||||
for (i = 0; cv[i].key; i++) {
|
||||
|
||||
if (NULL == (du = array_get_element(ca, cv[i].key))) {
|
||||
/* no found */
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (cv[i].type) {
|
||||
case T_CONFIG_ARRAY:
|
||||
if (du->type == TYPE_ARRAY) {
|
||||
size_t j;
|
||||
data_array *da = (data_array *)du;
|
||||
|
||||
for (j = 0; j < da->value->used; j++) {
|
||||
if (da->value->data[j]->type == TYPE_STRING) {
|
||||
data_string *ds = data_string_init();
|
||||
|
||||
buffer_copy_string_buffer(ds->value, ((data_string *)(da->value->data[j]))->value);
|
||||
buffer_copy_string_buffer(ds->key, ((data_string *)(da->value->data[j]))->key);
|
||||
|
||||
array_insert_unique(cv[i].destination, (data_unset *)ds);
|
||||
} else {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sssbs", "unexpected type for key: ", cv[i].key, "[", da->value->data[i]->key, "](string)");
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log_error_write(srv, __FILE__, __LINE__, "sss", "unexpected type for key: ", cv[i].key, "array of strings");
|
||||
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case T_CONFIG_STRING:
|
||||
if (du->type == TYPE_STRING) {
|
||||
data_string *ds = (data_string *)du;
|
||||
|
||||
buffer_copy_string_buffer(cv[i].destination, ds->value);
|
||||
} else {
|
||||
log_error_write(srv, __FILE__, __LINE__, "ssss", "unexpected type for key: ", cv[i].key, "(string)", "\"...\"");
|
||||
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case T_CONFIG_SHORT:
|
||||
switch(du->type) {
|
||||
case TYPE_INTEGER: {
|
||||
data_integer *di = (data_integer *)du;
|
||||
|
||||
*((unsigned short *)(cv[i].destination)) = di->value;
|
||||
break;
|
||||
}
|
||||
case TYPE_STRING: {
|
||||
data_string *ds = (data_string *)du;
|
||||
|
||||
log_error_write(srv, __FILE__, __LINE__, "ssbss", "unexpected type for key: ", cv[i].key, ds->value, "(short)", "0 ... 65535");
|
||||
|
||||
return -1;
|
||||
}
|
||||
default:
|
||||
log_error_write(srv, __FILE__, __LINE__, "ssdss", "unexpected type for key: ", cv[i].key, du->type, "(short)", "0 ... 65535");
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case T_CONFIG_BOOLEAN:
|
||||
if (du->type == TYPE_STRING) {
|
||||
data_string *ds = (data_string *)du;
|
||||
|
||||
if (buffer_is_equal_string(ds->value, CONST_STR_LEN("enable"))) {
|
||||
*((unsigned short *)(cv[i].destination)) = 1;
|
||||
} else if (buffer_is_equal_string(ds->value, CONST_STR_LEN("disable"))) {
|
||||
*((unsigned short *)(cv[i].destination)) = 0;
|
||||
} else {
|
||||
log_error_write(srv, __FILE__, __LINE__, "ssbs", "ERROR: unexpected value for key:", cv[i].key, ds->value, "(enable|disable)");
|
||||
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: unexpected type for key:", cv[i].key, "(string)", "\"(enable|disable)\"");
|
||||
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case T_CONFIG_LOCAL:
|
||||
case T_CONFIG_UNSET:
|
||||
break;
|
||||
case T_CONFIG_DEPRECATED:
|
||||
log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found deprecated key:", cv[i].key, "-", (char *)(cv[i].destination));
|
||||
|
||||
srv->config_deprecated = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int config_insert_values_global(server *srv, array *ca, const config_values_t cv[]) {
|
||||
size_t i;
|
||||
data_unset *du;
|
||||
|
||||
for (i = 0; cv[i].key; i++) {
|
||||
data_string *touched;
|
||||
|
||||
if (NULL == (du = array_get_element(ca, cv[i].key))) {
|
||||
/* no found */
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
/* touched */
|
||||
touched = data_string_init();
|
||||
|
||||
buffer_copy_string(touched->value, "");
|
||||
buffer_copy_string_buffer(touched->key, du->key);
|
||||
|
||||
array_insert_unique(srv->config_touched, (data_unset *)touched);
|
||||
}
|
||||
|
||||
return config_insert_values_internal(srv, ca, cv);
|
||||
}
|
||||
|
||||
int config_check_cond(server *srv, connection *con, data_config *dc) {
|
||||
buffer *l;
|
||||
server_socket *srv_sock = con->srv_socket;
|
||||
/* pass the rules */
|
||||
|
||||
l = srv->empty_string;
|
||||
|
||||
if (buffer_is_equal_string(dc->comp_key, CONST_STR_LEN("HTTPhost"))) {
|
||||
l = con->uri.authority;
|
||||
} else if (buffer_is_equal_string(dc->comp_key, CONST_STR_LEN("HTTPurl"))) {
|
||||
l = con->uri.path;
|
||||
} else if (buffer_is_equal_string(dc->comp_key, CONST_STR_LEN("SERVERsocket"))) {
|
||||
l = srv_sock->srv_token;
|
||||
} else if (buffer_is_equal_string(dc->comp_key, CONST_STR_LEN("HTTPreferer"))) {
|
||||
data_string *ds;
|
||||
|
||||
if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Referer"))) {
|
||||
l = ds->value;
|
||||
}
|
||||
} else if (buffer_is_equal_string(dc->comp_key, CONST_STR_LEN("HTTPcookie"))) {
|
||||
data_string *ds;
|
||||
if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Cookie"))) {
|
||||
l = ds->value;
|
||||
}
|
||||
} else if (buffer_is_equal_string(dc->comp_key, CONST_STR_LEN("HTTPuseragent"))) {
|
||||
data_string *ds;
|
||||
if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "User-Agent"))) {
|
||||
l = ds->value;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(dc->cond) {
|
||||
case CONFIG_COND_NE:
|
||||
case CONFIG_COND_EQ:
|
||||
if (buffer_is_equal(l, dc->match.string)) {
|
||||
return (dc->cond == CONFIG_COND_EQ) ? 1 : 0;
|
||||
} else {
|
||||
return (dc->cond == CONFIG_COND_EQ) ? 0 : 1;
|
||||
}
|
||||
break;
|
||||
#ifdef HAVE_PCRE_H
|
||||
case CONFIG_COND_NOMATCH:
|
||||
case CONFIG_COND_MATCH: {
|
||||
#define N 10
|
||||
int ovec[N * 3];
|
||||
int n;
|
||||
|
||||
n = pcre_exec(dc->match.regex, NULL, l->ptr, l->used - 1, 0, 0, ovec, N * 3);
|
||||
|
||||
if (n > 0) {
|
||||
return (dc->cond == CONFIG_COND_MATCH) ? 1 : 0;
|
||||
} else {
|
||||
return (dc->cond == CONFIG_COND_MATCH) ? 0 : 1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default:
|
||||
/* no way */
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
#include "base.h"
|
||||
|
||||
const char *connection_get_state(connection_state_t state) {
|
||||
switch (state) {
|
||||
case CON_STATE_CONNECT: return "connect";
|
||||
case CON_STATE_READ: return "read";
|
||||
case CON_STATE_READ_POST: return "readpost";
|
||||
case CON_STATE_WRITE: return "write";
|
||||
case CON_STATE_CLOSE: return "close";
|
||||
case CON_STATE_ERROR: return "error";
|
||||
case CON_STATE_HANDLE_REQUEST: return "handle-req";
|
||||
case CON_STATE_REQUEST_START: return "req-start";
|
||||
case CON_STATE_REQUEST_END: return "req-end";
|
||||
case CON_STATE_RESPONSE_START: return "resp-start";
|
||||
case CON_STATE_RESPONSE_END: return "resp-end";
|
||||
default: return "(unknown)";
|
||||
}
|
||||
}
|
||||
|
||||
const char *connection_get_short_state(connection_state_t state) {
|
||||
switch (state) {
|
||||
case CON_STATE_CONNECT: return ".";
|
||||
case CON_STATE_READ: return "r";
|
||||
case CON_STATE_READ_POST: return "R";
|
||||
case CON_STATE_WRITE: return "W";
|
||||
case CON_STATE_CLOSE: return "C";
|
||||
case CON_STATE_ERROR: return "E";
|
||||
case CON_STATE_HANDLE_REQUEST: return "h";
|
||||
case CON_STATE_REQUEST_START: return "q";
|
||||
case CON_STATE_REQUEST_END: return "Q";
|
||||
case CON_STATE_RESPONSE_START: return "s";
|
||||
case CON_STATE_RESPONSE_END: return "S";
|
||||
default: return "x";
|
||||
}
|
||||
}
|
||||
|
||||
int connection_set_state(server *srv, connection *con, connection_state_t state) {
|
||||
UNUSED(srv);
|
||||
|
||||
con->state = state;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -0,0 +1,136 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "base.h"
|
||||
#include "array.h"
|
||||
#include "buffer.h"
|
||||
#include "log.h"
|
||||
|
||||
int response_header_insert(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
|
||||
data_string *ds;
|
||||
|
||||
UNUSED(srv);
|
||||
|
||||
if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
|
||||
ds = data_response_init();
|
||||
}
|
||||
buffer_copy_string_len(ds->key, key, keylen);
|
||||
buffer_copy_string_len(ds->value, value, vallen);
|
||||
|
||||
array_insert_unique(con->response.headers, (data_unset *)ds);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int response_header_overwrite(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen) {
|
||||
data_string *ds;
|
||||
|
||||
UNUSED(srv);
|
||||
|
||||
/* if there already is a key by this name overwrite the value */
|
||||
if (NULL != (ds = (data_string *)array_get_element(con->response.headers, key))) {
|
||||
buffer_copy_string(ds->value, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return response_header_insert(srv, con, key, keylen, value, vallen);
|
||||
}
|
||||
|
||||
int http_response_redirect_to_directory(server *srv, connection *con) {
|
||||
buffer *o;
|
||||
|
||||
o = buffer_init();
|
||||
|
||||
if (con->conf.is_ssl) {
|
||||
buffer_copy_string(o, "https://");
|
||||
} else {
|
||||
buffer_copy_string(o, "http://");
|
||||
}
|
||||
if (con->uri.authority->used) {
|
||||
buffer_append_string_buffer(o, con->uri.authority);
|
||||
} else {
|
||||
/* get the name of the currently connected socket */
|
||||
struct hostent *he;
|
||||
#ifdef HAVE_IPV6
|
||||
char hbuf[256];
|
||||
#endif
|
||||
sock_addr our_addr;
|
||||
socklen_t our_addr_len;
|
||||
|
||||
our_addr_len = sizeof(our_addr);
|
||||
|
||||
if (-1 == getsockname(con->fd, &(our_addr.plain), &our_addr_len)) {
|
||||
con->http_status = 500;
|
||||
|
||||
log_error_write(srv, __FILE__, __LINE__, "ss",
|
||||
"can't get sockname", strerror(errno));
|
||||
|
||||
buffer_free(o);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Lookup name: secondly try to get hostname for bind address */
|
||||
switch(our_addr.plain.sa_family) {
|
||||
#ifdef HAVE_IPV6
|
||||
case AF_INET6:
|
||||
if (0 != getnameinfo((const struct sockaddr *)(&our_addr.ipv6),
|
||||
SA_LEN((const struct sockaddr *)&our_addr.ipv6),
|
||||
hbuf, sizeof(hbuf), NULL, 0, 0)) {
|
||||
|
||||
char dst[INET6_ADDRSTRLEN];
|
||||
|
||||
log_error_write(srv, __FILE__, __LINE__,
|
||||
"SSSS", "NOTICE: getnameinfo failed: ",
|
||||
strerror(errno), ", using ip-address instead");
|
||||
|
||||
buffer_append_string(o,
|
||||
inet_ntop(AF_INET6, (char *)&our_addr.ipv6.sin6_addr,
|
||||
dst, sizeof(dst)));
|
||||
} else {
|
||||
buffer_append_string(o, hbuf);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case AF_INET:
|
||||
if (NULL == (he = gethostbyaddr((char *)&our_addr.ipv4.sin_addr, sizeof(struct in_addr), AF_INET))) {
|
||||
log_error_write(srv, __FILE__, __LINE__,
|
||||
"SSSS", "NOTICE: gethostbyaddr failed: ",
|
||||
hstrerror(h_errno), ", using ip-address instead");
|
||||
|
||||
buffer_append_string(o, inet_ntoa(our_addr.ipv4.sin_addr));
|
||||
} else {
|
||||
buffer_append_string(o, he->h_name);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
log_error_write(srv, __FILE__, __LINE__,
|
||||
"S", "ERROR: unsupported address-type");
|
||||
|
||||
buffer_free(o);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!((con->conf.is_ssl == 0 && srv->srvconf.port == 80) ||
|
||||
(con->conf.is_ssl == 1 && srv->srvconf.port == 443))) {
|
||||
buffer_append_string(o, ":");
|
||||
buffer_append_long(o, srv->srvconf.port);
|
||||
}
|
||||
}
|
||||
buffer_append_string_buffer(o, con->uri.path);
|
||||
buffer_append_string(o, "/");
|
||||
if (!buffer_is_empty(con->uri.query)) {
|
||||
buffer_append_string(o, "?");
|
||||
buffer_append_string_buffer(o, con->uri.query);
|
||||
}
|
||||
|
||||
response_header_insert(srv, con, CONST_STR_LEN("Location"), CONST_BUF_LEN(o));
|
||||
|
||||
con->http_status = 301;
|
||||
|
||||
buffer_free(o);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue