You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by di...@apache.org on 2008/07/22 06:35:46 UTC
svn commit: r678637 [23/46] - in
/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd: ./
autom4te.cache/ cygwin/ doc/ openwrt/ src/ tests/ tests/docroot/
tests/docroot/123/ tests/docroot/www/ tests/docroot/www/dummydir/
tests/docroot/www/expire/ ...
Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/configfile-glue.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/configfile-glue.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/configfile-glue.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/configfile-glue.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,542 @@
+#include <string.h>
+
+#include "base.h"
+#include "buffer.h"
+#include "array.h"
+#include "log.h"
+#include "plugin.h"
+
+#include "configfile.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);
+ if (!da->is_index_key) {
+ /* the id's were generated automaticly, as we copy now we might have to renumber them
+ * this is used to prepend server.modules by mod_indexfiles as it has to be loaded
+ * before mod_fastcgi and friends */
+ 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__, "sssd",
+ "the key of an array can only be a string or a integer, variable:",
+ cv[i].key, "type:", da->value->data[j]->type);
+
+ return -1;
+ }
+ }
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "ss", cv[i].key, "should have been a array of strings like ... = ( \"...\" )");
+
+ 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", cv[i].key, "should have been a string like ... = \"...\"");
+
+ 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__, "ssb", "got a string but expected a short:", cv[i].key, ds->value);
+
+ return -1;
+ }
+ default:
+ log_error_write(srv, __FILE__, __LINE__, "ssds", "unexpected type for key:", cv[i].key, du->type, "expected a integer, range 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_UNSUPPORTED:
+ log_error_write(srv, __FILE__, __LINE__, "ssss", "ERROR: found unsupported key:", cv[i].key, "-", (char *)(cv[i].destination));
+
+ srv->config_unsupported = 1;
+
+ 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);
+}
+
+unsigned short sock_addr_get_port(sock_addr *addr) {
+#ifdef HAVE_IPV6
+ return ntohs(addr->plain.sa_family ? addr->ipv6.sin6_port : addr->ipv4.sin_port);
+#else
+ return ntohs(addr->ipv4.sin_port);
+#endif
+}
+
+static cond_result_t config_check_cond_cached(server *srv, connection *con, data_config *dc);
+
+static cond_result_t config_check_cond_nocache(server *srv, connection *con, data_config *dc) {
+ buffer *l;
+ server_socket *srv_sock = con->srv_socket;
+
+ /* check parent first */
+ if (dc->parent && dc->parent->context_ndx) {
+ /**
+ * a nested conditional
+ *
+ * if the parent is not decided yet or false, we can't be true either
+ */
+ if (con->conf.log_condition_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "sb", "go parent", dc->parent->key);
+ }
+
+ switch (config_check_cond_cached(srv, con, dc->parent)) {
+ case COND_RESULT_FALSE:
+ return COND_RESULT_FALSE;
+ case COND_RESULT_UNSET:
+ return COND_RESULT_UNSET;
+ default:
+ break;
+ }
+ }
+
+ if (dc->prev) {
+ /**
+ * a else branch
+ *
+ * we can only be executed, if all of our previous brothers
+ * are false
+ */
+ if (con->conf.log_condition_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "sb", "go prev", dc->prev->key);
+ }
+
+ /* make sure prev is checked first */
+ config_check_cond_cached(srv, con, dc->prev);
+
+ /* one of prev set me to FALSE */
+ switch (con->cond_cache[dc->context_ndx].result) {
+ case COND_RESULT_FALSE:
+ return con->cond_cache[dc->context_ndx].result;
+ default:
+ break;
+ }
+ }
+
+ if (!con->conditional_is_valid[dc->comp]) {
+ if (con->conf.log_condition_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "dss",
+ dc->comp,
+ dc->key->ptr,
+ con->conditional_is_valid[dc->comp] ? "yeah" : "nej");
+ }
+
+ return COND_RESULT_UNSET;
+ }
+
+ /* pass the rules */
+
+ switch (dc->comp) {
+ case COMP_HTTP_HOST: {
+ char *ck_colon = NULL, *val_colon = NULL;
+
+ if (!buffer_is_empty(con->uri.authority)) {
+
+ /*
+ * append server-port to the HTTP_POST if necessary
+ */
+
+ l = con->uri.authority;
+
+ switch(dc->cond) {
+ case CONFIG_COND_NE:
+ case CONFIG_COND_EQ:
+ ck_colon = strchr(dc->string->ptr, ':');
+ val_colon = strchr(l->ptr, ':');
+
+ if (ck_colon == val_colon) {
+ /* nothing to do with it */
+ break;
+ }
+ if (ck_colon) {
+ /* condition "host:port" but client send "host" */
+ buffer_copy_string_buffer(srv->cond_check_buf, l);
+ BUFFER_APPEND_STRING_CONST(srv->cond_check_buf, ":");
+ buffer_append_long(srv->cond_check_buf, sock_addr_get_port(&(srv_sock->addr)));
+ l = srv->cond_check_buf;
+ } else if (!ck_colon) {
+ /* condition "host" but client send "host:port" */
+ buffer_copy_string_len(srv->cond_check_buf, l->ptr, val_colon - l->ptr);
+ l = srv->cond_check_buf;
+ }
+ break;
+ default:
+ break;
+ }
+ } else {
+ l = srv->empty_string;
+ }
+ break;
+ }
+ case COMP_HTTP_REMOTE_IP: {
+ char *nm_slash;
+ /* handle remoteip limitations
+ *
+ * "10.0.0.1" is provided for all comparisions
+ *
+ * only for == and != we support
+ *
+ * "10.0.0.1/24"
+ */
+
+ if ((dc->cond == CONFIG_COND_EQ ||
+ dc->cond == CONFIG_COND_NE) &&
+ (con->dst_addr.plain.sa_family == AF_INET) &&
+ (NULL != (nm_slash = strchr(dc->string->ptr, '/')))) {
+ int nm_bits;
+ long nm;
+ char *err;
+ struct in_addr val_inp;
+
+ if (*(nm_slash+1) == '\0') {
+ log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: no number after / ", dc->string);
+
+ return COND_RESULT_FALSE;
+ }
+
+ nm_bits = strtol(nm_slash + 1, &err, 10);
+
+ if (*err) {
+ log_error_write(srv, __FILE__, __LINE__, "sbs", "ERROR: non-digit found in netmask:", dc->string, err);
+
+ return COND_RESULT_FALSE;
+ }
+
+ /* take IP convert to the native */
+ buffer_copy_string_len(srv->cond_check_buf, dc->string->ptr, nm_slash - dc->string->ptr);
+#ifdef __WIN32
+ if (INADDR_NONE == (val_inp.s_addr = inet_addr(srv->cond_check_buf->ptr))) {
+ log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf);
+
+ return COND_RESULT_FALSE;
+ }
+
+#else
+ if (0 == inet_aton(srv->cond_check_buf->ptr, &val_inp)) {
+ log_error_write(srv, __FILE__, __LINE__, "sb", "ERROR: ip addr is invalid:", srv->cond_check_buf);
+
+ return COND_RESULT_FALSE;
+ }
+#endif
+
+ /* build netmask */
+ nm = htonl(~((1 << (32 - nm_bits)) - 1));
+
+ if ((val_inp.s_addr & nm) == (con->dst_addr.ipv4.sin_addr.s_addr & nm)) {
+ return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE;
+ } else {
+ return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_FALSE : COND_RESULT_TRUE;
+ }
+ } else {
+ l = con->dst_addr_buf;
+ }
+ break;
+ }
+ case COMP_HTTP_SCHEME:
+ l = con->uri.scheme;
+ break;
+
+ case COMP_HTTP_URL:
+ l = con->uri.path;
+ break;
+
+ case COMP_HTTP_QUERY_STRING:
+ l = con->uri.query;
+ break;
+
+ case COMP_SERVER_SOCKET:
+ l = srv_sock->srv_token;
+ break;
+
+ case COMP_HTTP_REFERER: {
+ data_string *ds;
+
+ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Referer"))) {
+ l = ds->value;
+ } else {
+ l = srv->empty_string;
+ }
+ break;
+ }
+ case COMP_HTTP_COOKIE: {
+ data_string *ds;
+ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Cookie"))) {
+ l = ds->value;
+ } else {
+ l = srv->empty_string;
+ }
+ break;
+ }
+ case COMP_HTTP_USER_AGENT: {
+ data_string *ds;
+ if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "User-Agent"))) {
+ l = ds->value;
+ } else {
+ l = srv->empty_string;
+ }
+ break;
+ }
+ case COMP_HTTP_REQUEST_METHOD: {
+ const char *method = get_http_method_name(con->request.http_method);
+
+ /* we only have the request method as const char but we need a buffer for comparing */
+
+ buffer_copy_string(srv->tmp_buf, method);
+
+ l = srv->tmp_buf;
+
+ break;
+ }
+ default:
+ return COND_RESULT_FALSE;
+ }
+
+ if (NULL == l) {
+ if (con->conf.log_condition_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "bsbs", dc->comp_key,
+ "(", l, ") compare to NULL");
+ }
+ return COND_RESULT_FALSE;
+ }
+
+ if (con->conf.log_condition_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "bsbsb", dc->comp_key,
+ "(", l, ") compare to ", dc->string);
+ }
+ switch(dc->cond) {
+ case CONFIG_COND_NE:
+ case CONFIG_COND_EQ:
+ if (buffer_is_equal(l, dc->string)) {
+ return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_TRUE : COND_RESULT_FALSE;
+ } else {
+ return (dc->cond == CONFIG_COND_EQ) ? COND_RESULT_FALSE : COND_RESULT_TRUE;
+ }
+ break;
+#ifdef HAVE_PCRE_H
+ case CONFIG_COND_NOMATCH:
+ case CONFIG_COND_MATCH: {
+ cond_cache_t *cache = &con->cond_cache[dc->context_ndx];
+ int n;
+
+#ifndef elementsof
+#define elementsof(x) (sizeof(x) / sizeof(x[0]))
+#endif
+ n = pcre_exec(dc->regex, dc->regex_study, l->ptr, l->used - 1, 0, 0,
+ cache->matches, elementsof(cache->matches));
+
+ cache->patterncount = n;
+ if (n > 0) {
+ cache->comp_value = l;
+ cache->comp_type = dc->comp;
+ return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_TRUE : COND_RESULT_FALSE;
+ } else {
+ /* cache is already cleared */
+ return (dc->cond == CONFIG_COND_MATCH) ? COND_RESULT_FALSE : COND_RESULT_TRUE;
+ }
+ break;
+ }
+#endif
+ default:
+ /* no way */
+ break;
+ }
+
+ return COND_RESULT_FALSE;
+}
+
+static cond_result_t config_check_cond_cached(server *srv, connection *con, data_config *dc) {
+ cond_cache_t *caches = con->cond_cache;
+
+ if (COND_RESULT_UNSET == caches[dc->context_ndx].result) {
+ if (COND_RESULT_TRUE == (caches[dc->context_ndx].result = config_check_cond_nocache(srv, con, dc))) {
+ if (dc->next) {
+ data_config *c;
+ if (con->conf.log_condition_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "setting remains of chaining to false");
+ }
+ for (c = dc->next; c; c = c->next) {
+ caches[c->context_ndx].result = COND_RESULT_FALSE;
+ }
+ }
+ }
+ caches[dc->context_ndx].comp_type = dc->comp;
+
+ if (con->conf.log_condition_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx,
+ "(uncached) result:",
+ caches[dc->context_ndx].result == COND_RESULT_UNSET ? "unknown" :
+ (caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false"));
+ }
+ } else {
+ if (con->conf.log_condition_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "dss", dc->context_ndx,
+ "(cached) result:",
+ caches[dc->context_ndx].result == COND_RESULT_UNSET ? "unknown" :
+ (caches[dc->context_ndx].result == COND_RESULT_TRUE ? "true" : "false"));
+ }
+ }
+ return caches[dc->context_ndx].result;
+}
+
+/**
+ * reset the config-cache for a named item
+ *
+ * if the item is COND_LAST_ELEMENT we reset all items
+ */
+void config_cond_cache_reset_item(server *srv, connection *con, comp_key_t item) {
+ size_t i;
+
+ for (i = 0; i < srv->config_context->used; i++) {
+ if (item == COMP_LAST_ELEMENT ||
+ con->cond_cache[i].comp_type == item) {
+ con->cond_cache[i].result = COND_RESULT_UNSET;
+ con->cond_cache[i].patterncount = 0;
+ con->cond_cache[i].comp_value = NULL;
+ }
+ }
+}
+
+/**
+ * reset the config cache to its initial state at connection start
+ */
+void config_cond_cache_reset(server *srv, connection *con) {
+ size_t i;
+
+ config_cond_cache_reset_all_items(srv, con);
+
+ for (i = 0; i < COMP_LAST_ELEMENT; i++) {
+ con->conditional_is_valid[i] = 0;
+ }
+}
+
+int config_check_cond(server *srv, connection *con, data_config *dc) {
+ if (con->conf.log_condition_handling) {
+ log_error_write(srv, __FILE__, __LINE__, "s", "=== start of condition block ===");
+ }
+ return (config_check_cond_cached(srv, con, dc) == COND_RESULT_TRUE);
+}
+
+int config_append_cond_match_buffer(connection *con, data_config *dc, buffer *buf, int n)
+{
+ cond_cache_t *cache = &con->cond_cache[dc->context_ndx];
+ if (n > cache->patterncount) {
+ return 0;
+ }
+
+ n <<= 1; /* n *= 2 */
+ buffer_append_string_len(buf,
+ cache->comp_value->ptr + cache->matches[n],
+ cache->matches[n + 1] - cache->matches[n]);
+ return 1;
+}
+
Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/configfile.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/configfile.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/configfile.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/configfile.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,1249 @@
+#include <sys/stat.h>
+
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "server.h"
+#include "log.h"
+#include "stream.h"
+#include "plugin.h"
+#ifdef USE_LICENSE
+#include "license.h"
+#endif
+
+#include "configparser.h"
+#include "configfile.h"
+#include "proc_open.h"
+
+
+static int config_insert(server *srv) {
+ size_t i;
+ int ret = 0;
+ buffer *stat_cache_string;
+
+ config_values_t cv[] = {
+ { "server.bind", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 0 */
+ { "server.errorlog", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 1 */
+ { "server.errorfile-prefix", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 2 */
+ { "server.chroot", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 3 */
+ { "server.username", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 4 */
+ { "server.groupname", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 5 */
+ { "server.port", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 6 */
+ { "server.tag", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
+ { "server.use-ipv6", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
+ { "server.modules", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_SERVER }, /* 9 */
+
+ { "server.event-handler", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 10 */
+ { "server.pid-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 11 */
+ { "server.max-request-size", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
+ { "server.max-worker", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 13 */
+ { "server.document-root", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 14 */
+ { "server.force-lowercase-filenames", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 15 */
+ { "debug.log-condition-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 16 */
+ { "server.max-keep-alive-requests", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 17 */
+ { "server.name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 18 */
+ { "server.max-keep-alive-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 19 */
+
+ { "server.max-read-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 20 */
+ { "server.max-write-idle", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 21 */
+ { "server.error-handler-404", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 22 */
+ { "server.max-fds", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 23 */
+#ifdef HAVE_LSTAT
+ { "server.follow-symlink", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 24 */
+#else
+ { "server.follow-symlink",
+ "Your system lacks lstat(). We can not differ symlinks from files."
+ "Please remove server.follow-symlinks from your config.",
+ T_CONFIG_UNSUPPORTED, T_CONFIG_SCOPE_UNSET }, /* 24 */
+#endif
+ { "server.kbytes-per-second", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 25 */
+ { "connection.kbytes-per-second", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 26 */
+ { "mimetype.use-xattr", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 27 */
+ { "mimetype.assign", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 28 */
+ { "ssl.pemfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 29 */
+
+ { "ssl.engine", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 30 */
+
+ { "debug.log-file-not-found", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 31 */
+ { "debug.log-request-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 32 */
+ { "debug.log-response-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 33 */
+ { "debug.log-request-header", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 34 */
+
+ { "server.protocol-http11", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 35 */
+ { "debug.log-request-header-on-error", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 36 */
+ { "debug.log-state-handling", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 37 */
+ { "ssl.ca-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 38 */
+
+ { "server.errorlog-use-syslog", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 39 */
+ { "server.range-requests", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 40 */
+ { "server.stat-cache-engine", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 41 */
+ { "server.max-connections", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 42 */
+ { "server.network-backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 43 */
+ { "server.upload-dirs", NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION }, /* 44 */
+ { "server.core-files", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 45 */
+ { "ssl.cipher-list", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 46 */
+ { "ssl.use-sslv2", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 47 */
+ { "etag.use-inode", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 48 */
+ { "etag.use-mtime", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 49 */
+ { "etag.use-size", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 50 */
+ { "server.host", "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
+ { "server.docroot", "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
+ { "server.virtual-root", "load mod_simple_vhost and use simple-vhost.server-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
+ { "server.virtual-default-host", "load mod_simple_vhost and use simple-vhost.default-host instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
+ { "server.virtual-docroot", "load mod_simple_vhost and use simple-vhost.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
+ { "server.userid", "use server.username instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
+ { "server.groupid", "use server.groupname instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
+ { "server.use-keep-alive", "use server.max-keep-alive-requests = 0 instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
+ { "server.force-lower-case-files", "use server.force-lowercase-filenames instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
+
+ { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+ };
+
+
+ /* 0 */
+ cv[0].destination = srv->srvconf.bindhost;
+ cv[1].destination = srv->srvconf.errorlog_file;
+ cv[3].destination = srv->srvconf.changeroot;
+ cv[4].destination = srv->srvconf.username;
+ cv[5].destination = srv->srvconf.groupname;
+ cv[6].destination = &(srv->srvconf.port);
+
+ cv[9].destination = srv->srvconf.modules;
+ cv[10].destination = srv->srvconf.event_handler;
+ cv[11].destination = srv->srvconf.pid_file;
+
+ cv[13].destination = &(srv->srvconf.max_worker);
+ cv[23].destination = &(srv->srvconf.max_fds);
+ cv[36].destination = &(srv->srvconf.log_request_header_on_error);
+ cv[37].destination = &(srv->srvconf.log_state_handling);
+
+ cv[39].destination = &(srv->srvconf.errorlog_use_syslog);
+
+ stat_cache_string = buffer_init();
+ cv[41].destination = stat_cache_string;
+ cv[43].destination = srv->srvconf.network_backend;
+ cv[44].destination = srv->srvconf.upload_tempdirs;
+ cv[45].destination = &(srv->srvconf.enable_cores);
+
+ cv[42].destination = &(srv->srvconf.max_conns);
+ cv[12].destination = &(srv->srvconf.max_request_size);
+ srv->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+
+ assert(srv->config_storage);
+
+ for (i = 0; i < srv->config_context->used; i++) {
+ specific_config *s;
+
+ s = calloc(1, sizeof(specific_config));
+ assert(s);
+ s->document_root = buffer_init();
+ s->mimetypes = array_init();
+ s->server_name = buffer_init();
+ s->ssl_pemfile = buffer_init();
+ s->ssl_ca_file = buffer_init();
+ s->error_handler = buffer_init();
+ s->server_tag = buffer_init();
+ s->ssl_cipher_list = buffer_init();
+ s->errorfile_prefix = buffer_init();
+ s->max_keep_alive_requests = 16;
+ s->max_keep_alive_idle = 5;
+ s->max_read_idle = 60;
+ s->max_write_idle = 360;
+ s->use_xattr = 0;
+ s->is_ssl = 0;
+ s->ssl_use_sslv2 = 1;
+ s->use_ipv6 = 0;
+#ifdef HAVE_LSTAT
+ s->follow_symlink = 1;
+#endif
+ s->kbytes_per_second = 0;
+ s->allow_http11 = 1;
+ s->etag_use_inode = 1;
+ s->etag_use_mtime = 1;
+ s->etag_use_size = 1;
+ s->range_requests = 1;
+ s->force_lowercase_filenames = 0;
+ s->global_kbytes_per_second = 0;
+ s->global_bytes_per_second_cnt = 0;
+ s->global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
+
+ cv[2].destination = s->errorfile_prefix;
+
+ cv[7].destination = s->server_tag;
+ cv[8].destination = &(s->use_ipv6);
+
+
+ /* 13 max-worker */
+ cv[14].destination = s->document_root;
+ cv[15].destination = &(s->force_lowercase_filenames);
+ cv[16].destination = &(s->log_condition_handling);
+ cv[17].destination = &(s->max_keep_alive_requests);
+ cv[18].destination = s->server_name;
+ cv[19].destination = &(s->max_keep_alive_idle);
+ cv[20].destination = &(s->max_read_idle);
+ cv[21].destination = &(s->max_write_idle);
+ cv[22].destination = s->error_handler;
+#ifdef HAVE_LSTAT
+ cv[24].destination = &(s->follow_symlink);
+#endif
+ /* 23 -> max-fds */
+ cv[25].destination = &(s->global_kbytes_per_second);
+ cv[26].destination = &(s->kbytes_per_second);
+ cv[27].destination = &(s->use_xattr);
+ cv[28].destination = s->mimetypes;
+ cv[29].destination = s->ssl_pemfile;
+ cv[30].destination = &(s->is_ssl);
+
+ cv[31].destination = &(s->log_file_not_found);
+ cv[32].destination = &(s->log_request_handling);
+ cv[33].destination = &(s->log_response_header);
+ cv[34].destination = &(s->log_request_header);
+
+ cv[35].destination = &(s->allow_http11);
+ cv[38].destination = s->ssl_ca_file;
+ cv[40].destination = &(s->range_requests);
+
+ cv[46].destination = s->ssl_cipher_list;
+ cv[47].destination = &(s->ssl_use_sslv2);
+ cv[48].destination = &(s->etag_use_inode);
+ cv[49].destination = &(s->etag_use_mtime);
+ cv[50].destination = &(s->etag_use_size);
+
+ srv->config_storage[i] = s;
+
+ if (0 != (ret = config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv))) {
+ break;
+ }
+ }
+
+ if (buffer_is_empty(stat_cache_string)) {
+ srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_SIMPLE;
+ } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("simple"))) {
+ srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_SIMPLE;
+#ifdef HAVE_FAM_H
+ } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("fam"))) {
+ srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_FAM;
+#endif
+ } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("disable"))) {
+ srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_NONE;
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "server.stat-cache-engine can be one of \"disable\", \"simple\","
+#ifdef HAVE_FAM_H
+ " \"fam\","
+#endif
+ " but not:", stat_cache_string);
+ ret = HANDLER_ERROR;
+ }
+
+ buffer_free(stat_cache_string);
+
+ return ret;
+
+}
+
+
+#define PATCH(x) con->conf.x = s->x
+int config_setup_connection(server *srv, connection *con) {
+ specific_config *s = srv->config_storage[0];
+
+ PATCH(allow_http11);
+ PATCH(mimetypes);
+ PATCH(document_root);
+ PATCH(max_keep_alive_requests);
+ PATCH(max_keep_alive_idle);
+ PATCH(max_read_idle);
+ PATCH(max_write_idle);
+ PATCH(use_xattr);
+ PATCH(error_handler);
+ PATCH(errorfile_prefix);
+#ifdef HAVE_LSTAT
+ PATCH(follow_symlink);
+#endif
+ PATCH(server_tag);
+ PATCH(kbytes_per_second);
+ PATCH(global_kbytes_per_second);
+ PATCH(global_bytes_per_second_cnt);
+
+ con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
+ buffer_copy_string_buffer(con->server_name, s->server_name);
+
+ PATCH(log_request_header);
+ PATCH(log_response_header);
+ PATCH(log_request_handling);
+ PATCH(log_condition_handling);
+ PATCH(log_file_not_found);
+
+ PATCH(range_requests);
+ PATCH(force_lowercase_filenames);
+ PATCH(is_ssl);
+
+ PATCH(ssl_pemfile);
+ PATCH(ssl_ca_file);
+ PATCH(ssl_cipher_list);
+ PATCH(ssl_use_sslv2);
+ PATCH(etag_use_inode);
+ PATCH(etag_use_mtime);
+ PATCH(etag_use_size);
+
+ return 0;
+}
+
+int config_patch_connection(server *srv, connection *con, comp_key_t comp) {
+ size_t i, j;
+
+ con->conditional_is_valid[comp] = 1;
+
+ /* skip the first, the global context */
+ for (i = 1; i < srv->config_context->used; i++) {
+ data_config *dc = (data_config *)srv->config_context->data[i];
+ specific_config *s = srv->config_storage[i];
+
+ /* not our stage */
+ if (comp != dc->comp) continue;
+
+ /* condition didn't match */
+ if (!config_check_cond(srv, con, dc)) continue;
+
+ /* merge config */
+ for (j = 0; j < dc->value->used; j++) {
+ data_unset *du = dc->value->data[j];
+
+ if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.document-root"))) {
+ PATCH(document_root);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.range-requests"))) {
+ PATCH(range_requests);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.error-handler-404"))) {
+ PATCH(error_handler);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.errorfile-prefix"))) {
+ PATCH(errorfile_prefix);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("mimetype.assign"))) {
+ PATCH(mimetypes);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-keep-alive-requests"))) {
+ PATCH(max_keep_alive_requests);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-keep-alive-idle"))) {
+ PATCH(max_keep_alive_idle);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-write-idle"))) {
+ PATCH(max_write_idle);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.max-read-idle"))) {
+ PATCH(max_read_idle);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("mimetype.use-xattr"))) {
+ PATCH(use_xattr);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-inode"))) {
+ PATCH(etag_use_inode);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-mtime"))) {
+ PATCH(etag_use_mtime);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("etag.use-size"))) {
+ PATCH(etag_use_size);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.pemfile"))) {
+ PATCH(ssl_pemfile);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.ca-file"))) {
+ PATCH(ssl_ca_file);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.use-sslv2"))) {
+ PATCH(ssl_use_sslv2);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.cipher-list"))) {
+ PATCH(ssl_cipher_list);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.engine"))) {
+ PATCH(is_ssl);
+#ifdef HAVE_LSTAT
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.follow-symlink"))) {
+ PATCH(follow_symlink);
+#endif
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.name"))) {
+ buffer_copy_string_buffer(con->server_name, s->server_name);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.tag"))) {
+ PATCH(server_tag);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("connection.kbytes-per-second"))) {
+ PATCH(kbytes_per_second);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-request-handling"))) {
+ PATCH(log_request_handling);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-request-header"))) {
+ PATCH(log_request_header);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-response-header"))) {
+ PATCH(log_response_header);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-condition-handling"))) {
+ PATCH(log_condition_handling);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("debug.log-file-not-found"))) {
+ PATCH(log_file_not_found);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.protocol-http11"))) {
+ PATCH(allow_http11);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.force-lowercase-filenames"))) {
+ PATCH(force_lowercase_filenames);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("server.kbytes-per-second"))) {
+ PATCH(global_kbytes_per_second);
+ PATCH(global_bytes_per_second_cnt);
+ con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
+ }
+ }
+ }
+
+ con->etag_flags = (con->conf.etag_use_mtime ? ETAG_USE_MTIME : 0) |
+ (con->conf.etag_use_inode ? ETAG_USE_INODE : 0) |
+ (con->conf.etag_use_size ? ETAG_USE_SIZE : 0);
+
+ return 0;
+}
+#undef PATCH
+
+typedef struct {
+ int foo;
+ int bar;
+
+ const buffer *source;
+ const char *input;
+ size_t offset;
+ size_t size;
+
+ int line_pos;
+ int line;
+
+ int in_key;
+ int in_brace;
+ int in_cond;
+} tokenizer_t;
+
+#if 0
+static int tokenizer_open(server *srv, tokenizer_t *t, buffer *basedir, const char *fn) {
+ if (buffer_is_empty(basedir) &&
+ (fn[0] == '/' || fn[0] == '\\') &&
+ (fn[0] == '.' && (fn[1] == '/' || fn[1] == '\\'))) {
+ t->file = buffer_init_string(fn);
+ } else {
+ t->file = buffer_init_buffer(basedir);
+ buffer_append_string(t->file, fn);
+ }
+
+ if (0 != stream_open(&(t->s), t->file)) {
+ log_error_write(srv, __FILE__, __LINE__, "sbss",
+ "opening configfile ", t->file, "failed:", strerror(errno));
+ buffer_free(t->file);
+ return -1;
+ }
+
+ t->input = t->s.start;
+ t->offset = 0;
+ t->size = t->s.size;
+ t->line = 1;
+ t->line_pos = 1;
+
+ t->in_key = 1;
+ t->in_brace = 0;
+ t->in_cond = 0;
+ return 0;
+}
+
+static int tokenizer_close(server *srv, tokenizer_t *t) {
+ UNUSED(srv);
+
+ buffer_free(t->file);
+ return stream_close(&(t->s));
+}
+#endif
+static int config_skip_newline(tokenizer_t *t) {
+ int skipped = 1;
+ assert(t->input[t->offset] == '\r' || t->input[t->offset] == '\n');
+ if (t->input[t->offset] == '\r' && t->input[t->offset + 1] == '\n') {
+ skipped ++;
+ t->offset ++;
+ }
+ t->offset ++;
+ return skipped;
+}
+
+static int config_skip_comment(tokenizer_t *t) {
+ int i;
+ assert(t->input[t->offset] == '#');
+ for (i = 1; t->input[t->offset + i] &&
+ (t->input[t->offset + i] != '\n' && t->input[t->offset + i] != '\r');
+ i++);
+ t->offset += i;
+ return i;
+}
+
+static int config_tokenizer(server *srv, tokenizer_t *t, int *token_id, buffer *token) {
+ int tid = 0;
+ size_t i;
+
+ for (tid = 0; tid == 0 && t->offset < t->size && t->input[t->offset] ; ) {
+ char c = t->input[t->offset];
+ const char *start = NULL;
+
+ switch (c) {
+ case '=':
+ if (t->in_brace) {
+ if (t->input[t->offset + 1] == '>') {
+ t->offset += 2;
+
+ buffer_copy_string(token, "=>");
+
+ tid = TK_ARRAY_ASSIGN;
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
+ "source:", t->source,
+ "line:", t->line, "pos:", t->line_pos,
+ "use => for assignments in arrays");
+ return -1;
+ }
+ } else if (t->in_cond) {
+ if (t->input[t->offset + 1] == '=') {
+ t->offset += 2;
+
+ buffer_copy_string(token, "==");
+
+ tid = TK_EQ;
+ } else if (t->input[t->offset + 1] == '~') {
+ t->offset += 2;
+
+ buffer_copy_string(token, "=~");
+
+ tid = TK_MATCH;
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
+ "source:", t->source,
+ "line:", t->line, "pos:", t->line_pos,
+ "only =~ and == are allowed in the condition");
+ return -1;
+ }
+ t->in_key = 1;
+ t->in_cond = 0;
+ } else if (t->in_key) {
+ tid = TK_ASSIGN;
+
+ buffer_copy_string_len(token, t->input + t->offset, 1);
+
+ t->offset++;
+ t->line_pos++;
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
+ "source:", t->source,
+ "line:", t->line, "pos:", t->line_pos,
+ "unexpected equal-sign: =");
+ return -1;
+ }
+
+ break;
+ case '!':
+ if (t->in_cond) {
+ if (t->input[t->offset + 1] == '=') {
+ t->offset += 2;
+
+ buffer_copy_string(token, "!=");
+
+ tid = TK_NE;
+ } else if (t->input[t->offset + 1] == '~') {
+ t->offset += 2;
+
+ buffer_copy_string(token, "!~");
+
+ tid = TK_NOMATCH;
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
+ "source:", t->source,
+ "line:", t->line, "pos:", t->line_pos,
+ "only !~ and != are allowed in the condition");
+ return -1;
+ }
+ t->in_key = 1;
+ t->in_cond = 0;
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
+ "source:", t->source,
+ "line:", t->line, "pos:", t->line_pos,
+ "unexpected exclamation-marks: !");
+ return -1;
+ }
+
+ break;
+ case '\t':
+ case ' ':
+ t->offset++;
+ t->line_pos++;
+ break;
+ case '\n':
+ case '\r':
+ if (t->in_brace == 0) {
+ int done = 0;
+ while (!done && t->offset < t->size) {
+ switch (t->input[t->offset]) {
+ case '\r':
+ case '\n':
+ config_skip_newline(t);
+ t->line_pos = 1;
+ t->line++;
+ break;
+
+ case '#':
+ t->line_pos += config_skip_comment(t);
+ break;
+
+ case '\t':
+ case ' ':
+ t->offset++;
+ t->line_pos++;
+ break;
+
+ default:
+ done = 1;
+ }
+ }
+ t->in_key = 1;
+ tid = TK_EOL;
+ buffer_copy_string(token, "(EOL)");
+ } else {
+ config_skip_newline(t);
+ t->line_pos = 1;
+ t->line++;
+ }
+ break;
+ case ',':
+ if (t->in_brace > 0) {
+ tid = TK_COMMA;
+
+ buffer_copy_string(token, "(COMMA)");
+ }
+
+ t->offset++;
+ t->line_pos++;
+ break;
+ case '"':
+ /* search for the terminating " */
+ start = t->input + t->offset + 1;
+ buffer_copy_string(token, "");
+
+ for (i = 1; t->input[t->offset + i]; i++) {
+ if (t->input[t->offset + i] == '\\' &&
+ t->input[t->offset + i + 1] == '"') {
+
+ buffer_append_string_len(token, start, t->input + t->offset + i - start);
+
+ start = t->input + t->offset + i + 1;
+
+ /* skip the " */
+ i++;
+ continue;
+ }
+
+
+ if (t->input[t->offset + i] == '"') {
+ tid = TK_STRING;
+
+ buffer_append_string_len(token, start, t->input + t->offset + i - start);
+
+ break;
+ }
+ }
+
+ if (t->input[t->offset + i] == '\0') {
+ /* ERROR */
+
+ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
+ "source:", t->source,
+ "line:", t->line, "pos:", t->line_pos,
+ "missing closing quote");
+
+ return -1;
+ }
+
+ t->offset += i + 1;
+ t->line_pos += i + 1;
+
+ break;
+ case '(':
+ t->offset++;
+ t->in_brace++;
+
+ tid = TK_LPARAN;
+
+ buffer_copy_string(token, "(");
+ break;
+ case ')':
+ t->offset++;
+ t->in_brace--;
+
+ tid = TK_RPARAN;
+
+ buffer_copy_string(token, ")");
+ break;
+ case '$':
+ t->offset++;
+
+ tid = TK_DOLLAR;
+ t->in_cond = 1;
+ t->in_key = 0;
+
+ buffer_copy_string(token, "$");
+
+ break;
+
+ case '+':
+ if (t->input[t->offset + 1] == '=') {
+ t->offset += 2;
+ buffer_copy_string(token, "+=");
+ tid = TK_APPEND;
+ } else {
+ t->offset++;
+ tid = TK_PLUS;
+ buffer_copy_string(token, "+");
+ }
+ break;
+
+ case '{':
+ t->offset++;
+
+ tid = TK_LCURLY;
+
+ buffer_copy_string(token, "{");
+
+ break;
+
+ case '}':
+ t->offset++;
+
+ tid = TK_RCURLY;
+
+ buffer_copy_string(token, "}");
+
+ break;
+
+ case '[':
+ t->offset++;
+
+ tid = TK_LBRACKET;
+
+ buffer_copy_string(token, "[");
+
+ break;
+
+ case ']':
+ t->offset++;
+
+ tid = TK_RBRACKET;
+
+ buffer_copy_string(token, "]");
+
+ break;
+ case '#':
+ t->line_pos += config_skip_comment(t);
+
+ break;
+ default:
+ if (t->in_cond) {
+ for (i = 0; t->input[t->offset + i] &&
+ (isalpha((unsigned char)t->input[t->offset + i])
+ ); i++);
+
+ if (i && t->input[t->offset + i]) {
+ tid = TK_SRVVARNAME;
+ buffer_copy_string_len(token, t->input + t->offset, i);
+
+ t->offset += i;
+ t->line_pos += i;
+ } else {
+ /* ERROR */
+ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
+ "source:", t->source,
+ "line:", t->line, "pos:", t->line_pos,
+ "invalid character in condition");
+ return -1;
+ }
+ } else if (isdigit((unsigned char)c)) {
+ /* take all digits */
+ for (i = 0; t->input[t->offset + i] && isdigit((unsigned char)t->input[t->offset + i]); i++);
+
+ /* was there it least a digit ? */
+ if (i) {
+ tid = TK_INTEGER;
+
+ buffer_copy_string_len(token, t->input + t->offset, i);
+
+ t->offset += i;
+ t->line_pos += i;
+ }
+ } else {
+ /* the key might consist of [-.0-9a-z] */
+ for (i = 0; t->input[t->offset + i] &&
+ (isalnum((unsigned char)t->input[t->offset + i]) ||
+ t->input[t->offset + i] == '.' ||
+ t->input[t->offset + i] == '_' || /* for env.* */
+ t->input[t->offset + i] == '-'
+ ); i++);
+
+ if (i && t->input[t->offset + i]) {
+ buffer_copy_string_len(token, t->input + t->offset, i);
+
+ if (strcmp(token->ptr, "include") == 0) {
+ tid = TK_INCLUDE;
+ } else if (strcmp(token->ptr, "include_shell") == 0) {
+ tid = TK_INCLUDE_SHELL;
+ } else if (strcmp(token->ptr, "global") == 0) {
+ tid = TK_GLOBAL;
+ } else if (strcmp(token->ptr, "else") == 0) {
+ tid = TK_ELSE;
+ } else {
+ tid = TK_LKEY;
+ }
+
+ t->offset += i;
+ t->line_pos += i;
+ } else {
+ /* ERROR */
+ log_error_write(srv, __FILE__, __LINE__, "sbsdsds",
+ "source:", t->source,
+ "line:", t->line, "pos:", t->line_pos,
+ "invalid character in variable name");
+ return -1;
+ }
+ }
+ break;
+ }
+ }
+
+ if (tid) {
+ *token_id = tid;
+#if 0
+ log_error_write(srv, __FILE__, __LINE__, "sbsdsdbdd",
+ "source:", t->source,
+ "line:", t->line, "pos:", t->line_pos,
+ token, token->used - 1, tid);
+#endif
+
+ return 1;
+ } else if (t->offset < t->size) {
+ fprintf(stderr, "%s.%d: %d, %s\n",
+ __FILE__, __LINE__,
+ tid, token->ptr);
+ }
+ return 0;
+}
+
+static int config_parse(server *srv, config_t *context, tokenizer_t *t) {
+ void *pParser;
+ int token_id;
+ buffer *token, *lasttoken;
+ int ret;
+
+ pParser = configparserAlloc( malloc );
+ lasttoken = buffer_init();
+ token = buffer_init();
+ while((1 == (ret = config_tokenizer(srv, t, &token_id, token))) && context->ok) {
+ buffer_copy_string_buffer(lasttoken, token);
+ configparser(pParser, token_id, token, context);
+
+ token = buffer_init();
+ }
+ buffer_free(token);
+
+ if (ret != -1 && context->ok) {
+ /* add an EOL at EOF, better than say sorry */
+ configparser(pParser, TK_EOL, buffer_init_string("(EOL)"), context);
+ if (context->ok) {
+ configparser(pParser, 0, NULL, context);
+ }
+ }
+ configparserFree(pParser, free);
+
+ if (ret == -1) {
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "configfile parser failed at:", lasttoken);
+ } else if (context->ok == 0) {
+ log_error_write(srv, __FILE__, __LINE__, "sbsdsdsb",
+ "source:", t->source,
+ "line:", t->line, "pos:", t->line_pos,
+ "parser failed somehow near here:", lasttoken);
+ ret = -1;
+ }
+ buffer_free(lasttoken);
+
+ return ret == -1 ? -1 : 0;
+}
+
+static int tokenizer_init(tokenizer_t *t, const buffer *source, const char *input, size_t size) {
+
+ t->source = source;
+ t->input = input;
+ t->size = size;
+ t->offset = 0;
+ t->line = 1;
+ t->line_pos = 1;
+
+ t->in_key = 1;
+ t->in_brace = 0;
+ t->in_cond = 0;
+ return 0;
+}
+
+int config_parse_file(server *srv, config_t *context, const char *fn) {
+ tokenizer_t t;
+ stream s;
+ int ret;
+ buffer *filename;
+
+ if (buffer_is_empty(context->basedir) &&
+ (fn[0] == '/' || fn[0] == '\\') &&
+ (fn[0] == '.' && (fn[1] == '/' || fn[1] == '\\'))) {
+ filename = buffer_init_string(fn);
+ } else {
+ filename = buffer_init_buffer(context->basedir);
+ buffer_append_string(filename, fn);
+ }
+
+ if (0 != stream_open(&s, filename)) {
+ if (s.size == 0) {
+ /* the file was empty, nothing to parse */
+ ret = 0;
+ } else {
+ log_error_write(srv, __FILE__, __LINE__, "sbss",
+ "opening configfile ", filename, "failed:", strerror(errno));
+ ret = -1;
+ }
+ } else {
+ tokenizer_init(&t, filename, s.start, s.size);
+ ret = config_parse(srv, context, &t);
+ }
+
+ stream_close(&s);
+ buffer_free(filename);
+ return ret;
+}
+
+int config_parse_cmd(server *srv, config_t *context, const char *cmd) {
+ proc_handler_t proc;
+ tokenizer_t t;
+ int ret;
+ buffer *source;
+ buffer *out;
+ char oldpwd[PATH_MAX];
+
+ if (NULL == getcwd(oldpwd, sizeof(oldpwd))) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "cannot get cwd", strerror(errno));
+ return -1;
+ }
+
+ source = buffer_init_string(cmd);
+ out = buffer_init();
+
+ if (!buffer_is_empty(context->basedir)) {
+ chdir(context->basedir->ptr);
+ }
+
+ if (0 != proc_open_buffer(&proc, cmd, NULL, out, NULL)) {
+ log_error_write(srv, __FILE__, __LINE__, "sbss",
+ "opening", source, "failed:", strerror(errno));
+ ret = -1;
+ } else {
+ tokenizer_init(&t, source, out->ptr, out->used);
+ ret = config_parse(srv, context, &t);
+ }
+
+ buffer_free(source);
+ buffer_free(out);
+ chdir(oldpwd);
+ return ret;
+}
+
+static void context_init(server *srv, config_t *context) {
+ context->srv = srv;
+ context->ok = 1;
+ context->configs_stack = array_init();
+ context->configs_stack->is_weakref = 1;
+ context->basedir = buffer_init();
+}
+
+static void context_free(config_t *context) {
+ array_free(context->configs_stack);
+ buffer_free(context->basedir);
+}
+
+int config_read(server *srv, const char *fn) {
+ config_t context;
+ data_config *dc;
+ data_integer *dpid;
+ data_string *dcwd;
+ int ret;
+ char *pos;
+ data_array *modules;
+
+ context_init(srv, &context);
+ context.all_configs = srv->config_context;
+
+ pos = strrchr(fn,
+#ifdef __WIN32
+ '\\'
+#else
+ '/'
+#endif
+ );
+ if (pos) {
+ buffer_copy_string_len(context.basedir, fn, pos - fn + 1);
+ fn = pos + 1;
+ }
+
+ dc = data_config_init();
+ buffer_copy_string(dc->key, "global");
+
+ assert(context.all_configs->used == 0);
+ dc->context_ndx = context.all_configs->used;
+ array_insert_unique(context.all_configs, (data_unset *)dc);
+ context.current = dc;
+
+ /* default context */
+ srv->config = dc->value;
+ dpid = data_integer_init();
+ dpid->value = getpid();
+ buffer_copy_string(dpid->key, "var.PID");
+ array_insert_unique(srv->config, (data_unset *)dpid);
+
+ dcwd = data_string_init();
+ buffer_prepare_copy(dcwd->value, 1024);
+ if (NULL != getcwd(dcwd->value->ptr, dcwd->value->size - 1)) {
+ dcwd->value->used = strlen(dcwd->value->ptr) + 1;
+ buffer_copy_string(dcwd->key, "var.CWD");
+ array_insert_unique(srv->config, (data_unset *)dcwd);
+ }
+
+ ret = config_parse_file(srv, &context, fn);
+
+ /* remains nothing if parser is ok */
+ assert(!(0 == ret && context.ok && 0 != context.configs_stack->used));
+ context_free(&context);
+
+ if (0 != ret) {
+ return ret;
+ }
+
+ if (NULL != (dc = (data_config *)array_get_element(srv->config_context, "global"))) {
+ srv->config = dc->value;
+ } else {
+ return -1;
+ }
+
+ if (NULL != (modules = (data_array *)array_get_element(srv->config, "server.modules"))) {
+ data_string *ds;
+ data_array *prepends;
+
+ if (modules->type != TYPE_ARRAY) {
+ fprintf(stderr, "server.modules must be an array");
+ return -1;
+ }
+
+ prepends = data_array_init();
+
+ /* prepend default modules */
+ if (NULL == array_get_element(modules->value, "mod_indexfile")) {
+ ds = data_string_init();
+ buffer_copy_string(ds->value, "mod_indexfile");
+ array_insert_unique(prepends->value, (data_unset *)ds);
+ }
+
+ prepends = (data_array *)configparser_merge_data((data_unset *)prepends, (data_unset *)modules);
+ buffer_copy_string_buffer(prepends->key, modules->key);
+ array_replace(srv->config, (data_unset *)prepends);
+ modules->free((data_unset *)modules);
+ modules = prepends;
+
+ /* append default modules */
+ if (NULL == array_get_element(modules->value, "mod_dirlisting")) {
+ ds = data_string_init();
+ buffer_copy_string(ds->value, "mod_dirlisting");
+ array_insert_unique(modules->value, (data_unset *)ds);
+ }
+
+ if (NULL == array_get_element(modules->value, "mod_staticfile")) {
+ ds = data_string_init();
+ buffer_copy_string(ds->value, "mod_staticfile");
+ array_insert_unique(modules->value, (data_unset *)ds);
+ }
+ } else {
+ data_string *ds;
+
+ modules = data_array_init();
+
+ /* server.modules is not set */
+ ds = data_string_init();
+ buffer_copy_string(ds->value, "mod_indexfile");
+ array_insert_unique(modules->value, (data_unset *)ds);
+
+ ds = data_string_init();
+ buffer_copy_string(ds->value, "mod_dirlisting");
+ array_insert_unique(modules->value, (data_unset *)ds);
+
+ ds = data_string_init();
+ buffer_copy_string(ds->value, "mod_staticfile");
+ array_insert_unique(modules->value, (data_unset *)ds);
+
+ buffer_copy_string(modules->key, "server.modules");
+ array_insert_unique(srv->config, (data_unset *)modules);
+ }
+
+
+ if (0 != config_insert(srv)) {
+ return -1;
+ }
+
+ return 0;
+}
+
+int config_set_defaults(server *srv) {
+ size_t i;
+ specific_config *s = srv->config_storage[0];
+ struct stat st1, st2;
+
+ struct ev_map { fdevent_handler_t et; const char *name; } event_handlers[] =
+ {
+ /* - poll is most reliable
+ * - select works everywhere
+ * - linux-* are experimental
+ */
+#ifdef USE_POLL
+ { FDEVENT_HANDLER_POLL, "poll" },
+#endif
+#ifdef USE_SELECT
+ { FDEVENT_HANDLER_SELECT, "select" },
+#endif
+#ifdef USE_LINUX_EPOLL
+ { FDEVENT_HANDLER_LINUX_SYSEPOLL, "linux-sysepoll" },
+#endif
+#ifdef USE_LINUX_SIGIO
+ { FDEVENT_HANDLER_LINUX_RTSIG, "linux-rtsig" },
+#endif
+#ifdef USE_SOLARIS_DEVPOLL
+ { FDEVENT_HANDLER_SOLARIS_DEVPOLL,"solaris-devpoll" },
+#endif
+#ifdef USE_FREEBSD_KQUEUE
+ { FDEVENT_HANDLER_FREEBSD_KQUEUE, "freebsd-kqueue" },
+ { FDEVENT_HANDLER_FREEBSD_KQUEUE, "kqueue" },
+#endif
+ { FDEVENT_HANDLER_UNSET, NULL }
+ };
+
+
+ if (buffer_is_empty(s->document_root)) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "a default document-root has to be set");
+
+ return -1;
+ }
+
+ if (buffer_is_empty(srv->srvconf.changeroot)) {
+ if (-1 == stat(s->document_root->ptr, &st1)) {
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "base-docroot doesn't exist:",
+ s->document_root);
+ return -1;
+ }
+
+ } else {
+ buffer_copy_string_buffer(srv->tmp_buf, srv->srvconf.changeroot);
+ buffer_append_string_buffer(srv->tmp_buf, s->document_root);
+
+ if (-1 == stat(srv->tmp_buf->ptr, &st1)) {
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "base-docroot doesn't exist:",
+ srv->tmp_buf);
+ return -1;
+ }
+
+ }
+
+ buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
+
+ buffer_to_lower(srv->tmp_buf);
+
+ if (0 == stat(srv->tmp_buf->ptr, &st1)) {
+ int is_lower = 0;
+
+ is_lower = buffer_is_equal(srv->tmp_buf, s->document_root);
+
+ /* lower-case existed, check upper-case */
+ buffer_copy_string_buffer(srv->tmp_buf, s->document_root);
+
+ buffer_to_upper(srv->tmp_buf);
+
+ /* we have to handle the special case that upper and lower-casing results in the same filename
+ * as in server.document-root = "/" or "/12345/" */
+
+ if (is_lower && buffer_is_equal(srv->tmp_buf, s->document_root)) {
+ /* lower-casing and upper-casing didn't result in
+ * an other filename, no need to stat(),
+ * just assume it is case-sensitive. */
+
+ s->force_lowercase_filenames = 0;
+ } else if (0 == stat(srv->tmp_buf->ptr, &st2)) {
+
+ /* upper case exists too, doesn't the FS handle this ? */
+
+ /* upper and lower have the same inode -> case-insensitve FS */
+
+ if (st1.st_ino == st2.st_ino) {
+ /* upper and lower have the same inode -> case-insensitve FS */
+
+ s->force_lowercase_filenames = 1;
+ }
+ }
+ }
+
+ if (srv->srvconf.port == 0) {
+ srv->srvconf.port = s->is_ssl ? 443 : 80;
+ }
+
+ if (srv->srvconf.event_handler->used == 0) {
+ /* choose a good default
+ *
+ * the event_handler list is sorted by 'goodness'
+ * taking the first available should be the best solution
+ */
+ srv->event_handler = event_handlers[0].et;
+
+ if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "sorry, there is no event handler for this system");
+
+ return -1;
+ }
+ } else {
+ /*
+ * User override
+ */
+
+ for (i = 0; event_handlers[i].name; i++) {
+ if (0 == strcmp(event_handlers[i].name, srv->srvconf.event_handler->ptr)) {
+ srv->event_handler = event_handlers[i].et;
+ break;
+ }
+ }
+
+ if (FDEVENT_HANDLER_UNSET == srv->event_handler) {
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "the selected event-handler in unknown or not supported:",
+ srv->srvconf.event_handler );
+
+ return -1;
+ }
+ }
+
+ if (s->is_ssl) {
+ if (buffer_is_empty(s->ssl_pemfile)) {
+ /* PEM file is require */
+
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "ssl.pemfile has to be set");
+ return -1;
+ }
+
+#ifndef USE_OPENSSL
+ log_error_write(srv, __FILE__, __LINE__, "s",
+ "ssl support is missing, recompile with --with-openssl");
+
+ return -1;
+#endif
+ }
+
+ return 0;
+}
Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/configfile.h
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/configfile.h?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/configfile.h (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/configfile.h Mon Jul 21 21:35:35 2008
@@ -0,0 +1,30 @@
+#ifndef _CONFIG_PARSER_H_
+#define _CONFIG_PARSER_H_
+
+#include "array.h"
+#include "buffer.h"
+#include "server.h"
+
+typedef struct {
+ server *srv;
+ int ok;
+ array *all_configs;
+ array *configs_stack; /* to parse nested block */
+ data_config *current; /* current started with { */
+ buffer *basedir;
+} config_t;
+
+void *configparserAlloc(void *(*mallocProc)(size_t));
+void configparserFree(void *p, void (*freeProc)(void*));
+void configparser(void *yyp, int yymajor, buffer *yyminor, config_t *ctx);
+int config_parse_file(server *srv, config_t *context, const char *fn);
+int config_parse_cmd(server *srv, config_t *context, const char *cmd);
+data_unset *configparser_merge_data(data_unset *op1, const data_unset *op2);
+
+void config_cond_cache_reset(server *srv, connection *con);
+void config_cond_cache_reset_item(server *srv, connection *con, comp_key_t item);
+
+#define config_cond_cache_reset_all_items(srv, con) \
+ config_cond_cache_reset_item(srv, con, COMP_LAST_ELEMENT);
+
+#endif