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 [32/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/mod_dirlisting.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/mod_dirlisting.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/mod_dirlisting.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/mod_dirlisting.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,909 @@
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <time.h>
+
+#include "base.h"
+#include "log.h"
+#include "buffer.h"
+
+#include "plugin.h"
+
+#include "response.h"
+#include "stat_cache.h"
+#include "stream.h"
+
+/**
+ * this is a dirlisting for a lighttpd plugin
+ */
+
+
+#ifdef HAVE_SYS_SYSLIMITS_H
+#include <sys/syslimits.h>
+#endif
+
+#ifdef HAVE_ATTR_ATTRIBUTES_H
+#include <attr/attributes.h>
+#endif
+
+/* plugin config for all request/connections */
+
+typedef struct {
+#ifdef HAVE_PCRE_H
+	pcre *regex;
+#endif
+	buffer *string;
+} excludes;
+
+typedef struct {
+	excludes **ptr;
+
+	size_t used;
+	size_t size;
+} excludes_buffer;
+
+typedef struct {
+	unsigned short dir_listing;
+	unsigned short hide_dot_files;
+	unsigned short show_readme;
+	unsigned short hide_readme_file;
+	unsigned short show_header;
+	unsigned short hide_header_file;
+
+	excludes_buffer *excludes;
+
+	buffer *external_css;
+	buffer *encoding;
+	buffer *set_footer;
+} plugin_config;
+
+typedef struct {
+	PLUGIN_DATA;
+
+	buffer *tmp_buf;
+	buffer *content_charset;
+
+	plugin_config **config_storage;
+
+	plugin_config conf;
+} plugin_data;
+
+excludes_buffer *excludes_buffer_init(void) {
+	excludes_buffer *exb;
+
+	exb = calloc(1, sizeof(*exb));
+
+	return exb;
+}
+
+int excludes_buffer_append(excludes_buffer *exb, buffer *string) {
+#ifdef HAVE_PCRE_H
+	size_t i;
+	const char *errptr;
+	int erroff;
+
+	if (!string) return -1;
+
+	if (exb->size == 0) {
+		exb->size = 4;
+		exb->used = 0;
+
+		exb->ptr = malloc(exb->size * sizeof(*exb->ptr));
+
+		for(i = 0; i < exb->size ; i++) {
+			exb->ptr[i] = calloc(1, sizeof(**exb->ptr));
+		}
+	} else if (exb->used == exb->size) {
+		exb->size += 4;
+
+		exb->ptr = realloc(exb->ptr, exb->size * sizeof(*exb->ptr));
+
+		for(i = exb->used; i < exb->size; i++) {
+			exb->ptr[i] = calloc(1, sizeof(**exb->ptr));
+		}
+	}
+
+
+	if (NULL == (exb->ptr[exb->used]->regex = pcre_compile(string->ptr, 0,
+						    &errptr, &erroff, NULL))) {
+		return -1;
+	}
+
+	exb->ptr[exb->used]->string = buffer_init();
+	buffer_copy_string_buffer(exb->ptr[exb->used]->string, string);
+
+	exb->used++;
+
+	return 0;
+#else
+	UNUSED(exb);
+	UNUSED(string);
+
+	return -1;
+#endif
+}
+
+void excludes_buffer_free(excludes_buffer *exb) {
+#ifdef HAVE_PCRE_H
+	size_t i;
+
+	for (i = 0; i < exb->size; i++) {
+		if (exb->ptr[i]->regex) pcre_free(exb->ptr[i]->regex);
+		if (exb->ptr[i]->string) buffer_free(exb->ptr[i]->string);
+		free(exb->ptr[i]);
+	}
+
+	if (exb->ptr) free(exb->ptr);
+#endif
+
+	free(exb);
+}
+
+/* init the plugin data */
+INIT_FUNC(mod_dirlisting_init) {
+	plugin_data *p;
+
+	p = calloc(1, sizeof(*p));
+
+	p->tmp_buf = buffer_init();
+	p->content_charset = buffer_init();
+
+	return p;
+}
+
+/* detroy the plugin data */
+FREE_FUNC(mod_dirlisting_free) {
+	plugin_data *p = p_d;
+
+	UNUSED(srv);
+
+	if (!p) return HANDLER_GO_ON;
+
+	if (p->config_storage) {
+		size_t i;
+		for (i = 0; i < srv->config_context->used; i++) {
+			plugin_config *s = p->config_storage[i];
+
+			if (!s) continue;
+
+			excludes_buffer_free(s->excludes);
+			buffer_free(s->external_css);
+			buffer_free(s->encoding);
+			buffer_free(s->set_footer);
+
+			free(s);
+		}
+		free(p->config_storage);
+	}
+
+	buffer_free(p->tmp_buf);
+	buffer_free(p->content_charset);
+
+	free(p);
+
+	return HANDLER_GO_ON;
+}
+
+static int parse_config_entry(server *srv, plugin_config *s, array *ca, const char *option) {
+	data_unset *du;
+
+	if (NULL != (du = array_get_element(ca, option))) {
+		data_array *da = (data_array *)du;
+		size_t j;
+
+		if (du->type != TYPE_ARRAY) {
+			log_error_write(srv, __FILE__, __LINE__, "sss",
+				"unexpected type for key: ", option, "array of strings");
+
+			return HANDLER_ERROR;
+		}
+
+		da = (data_array *)du;
+
+		for (j = 0; j < da->value->used; j++) {
+			if (da->value->data[j]->type != TYPE_STRING) {
+				log_error_write(srv, __FILE__, __LINE__, "sssbs",
+					"unexpected type for key: ", option, "[",
+					da->value->data[j]->key, "](string)");
+
+				return HANDLER_ERROR;
+			}
+
+			if (0 != excludes_buffer_append(s->excludes,
+				    ((data_string *)(da->value->data[j]))->value)) {
+#ifdef HAVE_PCRE_H
+				log_error_write(srv, __FILE__, __LINE__, "sb",
+						"pcre-compile failed for", ((data_string *)(da->value->data[j]))->value);
+#else
+				log_error_write(srv, __FILE__, __LINE__, "s",
+						"pcre support is missing, please install libpcre and the headers");
+#endif
+			}
+		}
+	}
+
+	return 0;
+}
+
+/* handle plugin config and check values */
+
+#define CONFIG_EXCLUDE          "dir-listing.exclude"
+#define CONFIG_ACTIVATE         "dir-listing.activate"
+#define CONFIG_HIDE_DOTFILES    "dir-listing.hide-dotfiles"
+#define CONFIG_EXTERNAL_CSS     "dir-listing.external-css"
+#define CONFIG_ENCODING         "dir-listing.encoding"
+#define CONFIG_SHOW_README      "dir-listing.show-readme"
+#define CONFIG_HIDE_README_FILE "dir-listing.hide-readme-file"
+#define CONFIG_SHOW_HEADER      "dir-listing.show-header"
+#define CONFIG_HIDE_HEADER_FILE "dir-listing.hide-header-file"
+#define CONFIG_DIR_LISTING      "server.dir-listing"
+#define CONFIG_SET_FOOTER       "dir-listing.set-footer"
+
+
+SETDEFAULTS_FUNC(mod_dirlisting_set_defaults) {
+	plugin_data *p = p_d;
+	size_t i = 0;
+
+	config_values_t cv[] = {
+		{ CONFIG_EXCLUDE,          NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION },   /* 0 */
+		{ CONFIG_ACTIVATE,         NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
+		{ CONFIG_HIDE_DOTFILES,    NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
+		{ CONFIG_EXTERNAL_CSS,     NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },  /* 3 */
+		{ CONFIG_ENCODING,         NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },  /* 4 */
+		{ CONFIG_SHOW_README,      NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 5 */
+		{ CONFIG_HIDE_README_FILE, NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 6 */
+		{ CONFIG_SHOW_HEADER,      NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
+		{ CONFIG_HIDE_HEADER_FILE, NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
+		{ CONFIG_DIR_LISTING,      NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
+		{ CONFIG_SET_FOOTER,       NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 10 */
+
+		{ NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+	};
+
+	if (!p) return HANDLER_ERROR;
+
+	p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+
+	for (i = 0; i < srv->config_context->used; i++) {
+		plugin_config *s;
+		array *ca;
+
+		s = calloc(1, sizeof(plugin_config));
+		s->excludes = excludes_buffer_init();
+		s->dir_listing = 0;
+		s->external_css = buffer_init();
+		s->hide_dot_files = 0;
+		s->show_readme = 0;
+		s->hide_readme_file = 0;
+		s->show_header = 0;
+		s->hide_header_file = 0;
+		s->encoding = buffer_init();
+		s->set_footer = buffer_init();
+
+		cv[0].destination = s->excludes;
+		cv[1].destination = &(s->dir_listing);
+		cv[2].destination = &(s->hide_dot_files);
+		cv[3].destination = s->external_css;
+		cv[4].destination = s->encoding;
+		cv[5].destination = &(s->show_readme);
+		cv[6].destination = &(s->hide_readme_file);
+		cv[7].destination = &(s->show_header);
+		cv[8].destination = &(s->hide_header_file);
+		cv[9].destination = &(s->dir_listing); /* old name */
+		cv[10].destination = s->set_footer;
+
+		p->config_storage[i] = s;
+		ca = ((data_config *)srv->config_context->data[i])->value;
+
+		if (0 != config_insert_values_global(srv, ca, cv)) {
+			return HANDLER_ERROR;
+		}
+
+		parse_config_entry(srv, s, ca, CONFIG_EXCLUDE);
+	}
+
+	return HANDLER_GO_ON;
+}
+
+#define PATCH(x) \
+	p->conf.x = s->x;
+static int mod_dirlisting_patch_connection(server *srv, connection *con, plugin_data *p) {
+	size_t i, j;
+	plugin_config *s = p->config_storage[0];
+
+	PATCH(dir_listing);
+	PATCH(external_css);
+	PATCH(hide_dot_files);
+	PATCH(encoding);
+	PATCH(show_readme);
+	PATCH(hide_readme_file);
+	PATCH(show_header);
+	PATCH(hide_header_file);
+	PATCH(excludes);
+	PATCH(set_footer);
+
+	/* 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];
+		s = p->config_storage[i];
+
+		/* 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(CONFIG_ACTIVATE)) ||
+			    buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_DIR_LISTING))) {
+				PATCH(dir_listing);
+			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_HIDE_DOTFILES))) {
+				PATCH(hide_dot_files);
+			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_EXTERNAL_CSS))) {
+				PATCH(external_css);
+			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_ENCODING))) {
+				PATCH(encoding);
+			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_SHOW_README))) {
+				PATCH(show_readme);
+			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_HIDE_README_FILE))) {
+				PATCH(hide_readme_file);
+			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_SHOW_HEADER))) {
+				PATCH(show_header);
+			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_HIDE_HEADER_FILE))) {
+				PATCH(hide_header_file);
+			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_SET_FOOTER))) {
+				PATCH(set_footer);
+			} else if (buffer_is_equal_string(du->key, CONST_STR_LEN(CONFIG_EXCLUDE))) {
+				PATCH(excludes);
+			}
+		}
+	}
+
+	return 0;
+}
+#undef PATCH
+
+typedef struct {
+	size_t  namelen;
+	time_t  mtime;
+	off_t   size;
+} dirls_entry_t;
+
+typedef struct {
+	dirls_entry_t **ent;
+	size_t used;
+	size_t size;
+} dirls_list_t;
+
+#define DIRLIST_ENT_NAME(ent)	((char*)(ent) + sizeof(dirls_entry_t))
+#define DIRLIST_BLOB_SIZE		16
+
+/* simple combsort algorithm */
+static void http_dirls_sort(dirls_entry_t **ent, int num) {
+	int gap = num;
+	int i, j;
+	int swapped;
+	dirls_entry_t *tmp;
+
+	do {
+		gap = (gap * 10) / 13;
+		if (gap == 9 || gap == 10)
+			gap = 11;
+		if (gap < 1)
+			gap = 1;
+		swapped = 0;
+
+		for (i = 0; i < num - gap; i++) {
+			j = i + gap;
+			if (strcmp(DIRLIST_ENT_NAME(ent[i]), DIRLIST_ENT_NAME(ent[j])) > 0) {
+				tmp = ent[i];
+				ent[i] = ent[j];
+				ent[j] = tmp;
+				swapped = 1;
+			}
+		}
+
+	} while (gap > 1 || swapped);
+}
+
+/* buffer must be able to hold "999.9K"
+ * conversion is simple but not perfect
+ */
+static int http_list_directory_sizefmt(char *buf, off_t size) {
+	const char unit[] = "KMGTPE";	/* Kilo, Mega, Tera, Peta, Exa */
+	const char *u = unit - 1;		/* u will always increment at least once */
+	int remain;
+	char *out = buf;
+
+	if (size < 100)
+		size += 99;
+	if (size < 100)
+		size = 0;
+
+	while (1) {
+		remain = (int) size & 1023;
+		size >>= 10;
+		u++;
+		if ((size & (~0 ^ 1023)) == 0)
+			break;
+	}
+
+	remain /= 100;
+	if (remain > 9)
+		remain = 9;
+	if (size > 999) {
+		size   = 0;
+		remain = 9;
+		u++;
+	}
+
+	out   += LI_ltostr(out, size);
+	out[0] = '.';
+	out[1] = remain + '0';
+	out[2] = *u;
+	out[3] = '\0';
+
+	return (out + 3 - buf);
+}
+
+static void http_list_directory_header(server *srv, connection *con, plugin_data *p, buffer *out) {
+	UNUSED(srv);
+
+	BUFFER_APPEND_STRING_CONST(out,
+		"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\n"
+		"<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\">\n"
+		"<head>\n"
+		"<title>Index of "
+	);
+	buffer_append_string_encoded(out, CONST_BUF_LEN(con->uri.path), ENCODING_MINIMAL_XML);
+	BUFFER_APPEND_STRING_CONST(out, "</title>\n");
+
+	if (p->conf.external_css->used > 1) {
+		BUFFER_APPEND_STRING_CONST(out, "<link rel=\"stylesheet\" type=\"text/css\" href=\"");
+		buffer_append_string_buffer(out, p->conf.external_css);
+		BUFFER_APPEND_STRING_CONST(out, "\" />\n");
+	} else {
+		BUFFER_APPEND_STRING_CONST(out,
+			"<style type=\"text/css\">\n"
+			"a, a:active {text-decoration: none; color: blue;}\n"
+			"a:visited {color: #48468F;}\n"
+			"a:hover, a:focus {text-decoration: underline; color: red;}\n"
+			"body {background-color: #F5F5F5;}\n"
+			"h2 {margin-bottom: 12px;}\n"
+			"table {margin-left: 12px;}\n"
+			"th, td {"
+			" font: 90% monospace;"
+			" text-align: left;"
+			"}\n"
+			"th {"
+			" font-weight: bold;"
+			" padding-right: 14px;"
+			" padding-bottom: 3px;"
+			"}\n"
+		);
+		BUFFER_APPEND_STRING_CONST(out,
+			"td {padding-right: 14px;}\n"
+			"td.s, th.s {text-align: right;}\n"
+			"div.list {"
+			" background-color: white;"
+			" border-top: 1px solid #646464;"
+			" border-bottom: 1px solid #646464;"
+			" padding-top: 10px;"
+			" padding-bottom: 14px;"
+			"}\n"
+			"div.foot {"
+			" font: 90% monospace;"
+			" color: #787878;"
+			" padding-top: 4px;"
+			"}\n"
+			"</style>\n"
+		);
+	}
+
+	BUFFER_APPEND_STRING_CONST(out, "</head>\n<body>\n");
+
+	/* HEADER.txt */
+	if (p->conf.show_header) {
+		stream s;
+		/* if we have a HEADER file, display it in <pre class="header"></pre> */
+
+		buffer_copy_string_buffer(p->tmp_buf, con->physical.path);
+		BUFFER_APPEND_SLASH(p->tmp_buf);
+		BUFFER_APPEND_STRING_CONST(p->tmp_buf, "HEADER.txt");
+
+		if (-1 != stream_open(&s, p->tmp_buf)) {
+			BUFFER_APPEND_STRING_CONST(out, "<pre class=\"header\">");
+			buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
+			BUFFER_APPEND_STRING_CONST(out, "</pre>");
+		}
+		stream_close(&s);
+	}
+
+	BUFFER_APPEND_STRING_CONST(out, "<h2>Index of ");
+	buffer_append_string_encoded(out, CONST_BUF_LEN(con->uri.path), ENCODING_MINIMAL_XML);
+	BUFFER_APPEND_STRING_CONST(out,
+		"</h2>\n"
+		"<div class=\"list\">\n"
+		"<table summary=\"Directory Listing\" cellpadding=\"0\" cellspacing=\"0\">\n"
+		"<thead>"
+		"<tr>"
+			"<th class=\"n\">Name</th>"
+			"<th class=\"m\">Last Modified</th>"
+			"<th class=\"s\">Size</th>"
+			"<th class=\"t\">Type</th>"
+		"</tr>"
+		"</thead>\n"
+		"<tbody>\n"
+		"<tr>"
+			"<td class=\"n\"><a href=\"../\">Parent Directory</a>/</td>"
+			"<td class=\"m\">&nbsp;</td>"
+			"<td class=\"s\">- &nbsp;</td>"
+			"<td class=\"t\">Directory</td>"
+		"</tr>\n"
+	);
+}
+
+static void http_list_directory_footer(server *srv, connection *con, plugin_data *p, buffer *out) {
+	UNUSED(srv);
+
+	BUFFER_APPEND_STRING_CONST(out,
+		"</tbody>\n"
+		"</table>\n"
+		"</div>\n"
+	);
+
+	if (p->conf.show_readme) {
+		stream s;
+		/* if we have a README file, display it in <pre class="readme"></pre> */
+
+		buffer_copy_string_buffer(p->tmp_buf,  con->physical.path);
+		BUFFER_APPEND_SLASH(p->tmp_buf);
+		BUFFER_APPEND_STRING_CONST(p->tmp_buf, "README.txt");
+
+		if (-1 != stream_open(&s, p->tmp_buf)) {
+			BUFFER_APPEND_STRING_CONST(out, "<pre class=\"readme\">");
+			buffer_append_string_encoded(out, s.start, s.size, ENCODING_MINIMAL_XML);
+			BUFFER_APPEND_STRING_CONST(out, "</pre>");
+		}
+		stream_close(&s);
+	}
+
+	BUFFER_APPEND_STRING_CONST(out,
+		"<div class=\"foot\">"
+	);
+
+	if (p->conf.set_footer->used > 1) {
+		buffer_append_string_buffer(out, p->conf.set_footer);
+	} else if (buffer_is_empty(con->conf.server_tag)) {
+		BUFFER_APPEND_STRING_CONST(out, PACKAGE_NAME "/" PACKAGE_VERSION);
+	} else {
+		buffer_append_string_buffer(out, con->conf.server_tag);
+	}
+
+	BUFFER_APPEND_STRING_CONST(out,
+		"</div>\n"
+		"</body>\n"
+		"</html>\n"
+	);
+}
+
+static int http_list_directory(server *srv, connection *con, plugin_data *p, buffer *dir) {
+	DIR *dp;
+	buffer *out;
+	struct dirent *dent;
+	struct stat st;
+	char *path, *path_file;
+	size_t i;
+	int hide_dotfiles = p->conf.hide_dot_files;
+	dirls_list_t dirs, files, *list;
+	dirls_entry_t *tmp;
+	char sizebuf[sizeof("999.9K")];
+	char datebuf[sizeof("2005-Jan-01 22:23:24")];
+	size_t k;
+	const char *content_type;
+	long name_max;
+#ifdef HAVE_XATTR
+	char attrval[128];
+	int attrlen;
+#endif
+#ifdef HAVE_LOCALTIME_R
+	struct tm tm;
+#endif
+
+	if (dir->used == 0) return -1;
+
+	i = dir->used - 1;
+
+#ifdef HAVE_PATHCONF
+	if (-1 == (name_max = pathconf(dir->ptr, _PC_NAME_MAX))) {
+#ifdef NAME_MAX
+		name_max = NAME_MAX;
+#else
+		name_max = 255; /* stupid default */
+#endif
+	}
+#elif defined __WIN32
+	name_max = FILENAME_MAX;
+#else
+	name_max = NAME_MAX;
+#endif
+
+	path = malloc(dir->used + name_max);
+	assert(path);
+	strcpy(path, dir->ptr);
+	path_file = path + i;
+
+	if (NULL == (dp = opendir(path))) {
+		log_error_write(srv, __FILE__, __LINE__, "sbs",
+			"opendir failed:", dir, strerror(errno));
+
+		free(path);
+		return -1;
+	}
+
+	dirs.ent   = (dirls_entry_t**) malloc(sizeof(dirls_entry_t*) * DIRLIST_BLOB_SIZE);
+	assert(dirs.ent);
+	dirs.size  = DIRLIST_BLOB_SIZE;
+	dirs.used  = 0;
+	files.ent  = (dirls_entry_t**) malloc(sizeof(dirls_entry_t*) * DIRLIST_BLOB_SIZE);
+	assert(files.ent);
+	files.size = DIRLIST_BLOB_SIZE;
+	files.used = 0;
+
+	while ((dent = readdir(dp)) != NULL) {
+		unsigned short exclude_match = 0;
+
+		if (dent->d_name[0] == '.') {
+			if (hide_dotfiles)
+				continue;
+			if (dent->d_name[1] == '\0')
+				continue;
+			if (dent->d_name[1] == '.' && dent->d_name[2] == '\0')
+				continue;
+		}
+
+		if (p->conf.hide_readme_file) {
+			if (strcmp(dent->d_name, "README.txt") == 0)
+				continue;
+		}
+		if (p->conf.hide_header_file) {
+			if (strcmp(dent->d_name, "HEADER.txt") == 0)
+				continue;
+		}
+
+		/* compare d_name against excludes array
+		 * elements, skipping any that match.
+		 */
+#ifdef HAVE_PCRE_H
+		for(i = 0; i < p->conf.excludes->used; i++) {
+			int n;
+#define N 10
+			int ovec[N * 3];
+			pcre *regex = p->conf.excludes->ptr[i]->regex;
+
+			if ((n = pcre_exec(regex, NULL, dent->d_name,
+				    strlen(dent->d_name), 0, 0, ovec, 3 * N)) < 0) {
+				if (n != PCRE_ERROR_NOMATCH) {
+					log_error_write(srv, __FILE__, __LINE__, "sd",
+						"execution error while matching:", n);
+
+					return -1;
+				}
+			}
+			else {
+				exclude_match = 1;
+				break;
+			}
+		}
+
+		if (exclude_match) {
+			continue;
+		}
+#endif
+
+		i = strlen(dent->d_name);
+
+		/* NOTE: the manual says, d_name is never more than NAME_MAX
+		 *       so this should actually not be a buffer-overflow-risk
+		 */
+		if (i > (size_t)name_max) continue;
+
+		memcpy(path_file, dent->d_name, i + 1);
+		if (stat(path, &st) != 0)
+			continue;
+
+		list = &files;
+		if (S_ISDIR(st.st_mode))
+			list = &dirs;
+
+		if (list->used == list->size) {
+			list->size += DIRLIST_BLOB_SIZE;
+			list->ent   = (dirls_entry_t**) realloc(list->ent, sizeof(dirls_entry_t*) * list->size);
+			assert(list->ent);
+		}
+
+		tmp = (dirls_entry_t*) malloc(sizeof(dirls_entry_t) + 1 + i);
+		tmp->mtime = st.st_mtime;
+		tmp->size  = st.st_size;
+		tmp->namelen = i;
+		memcpy(DIRLIST_ENT_NAME(tmp), dent->d_name, i + 1);
+
+		list->ent[list->used++] = tmp;
+	}
+	closedir(dp);
+
+	if (dirs.used) http_dirls_sort(dirs.ent, dirs.used);
+
+	if (files.used) http_dirls_sort(files.ent, files.used);
+
+	out = chunkqueue_get_append_buffer(con->write_queue);
+	BUFFER_COPY_STRING_CONST(out, "<?xml version=\"1.0\" encoding=\"");
+	if (buffer_is_empty(p->conf.encoding)) {
+		BUFFER_APPEND_STRING_CONST(out, "iso-8859-1");
+	} else {
+		buffer_append_string_buffer(out, p->conf.encoding);
+	}
+	BUFFER_APPEND_STRING_CONST(out, "\"?>\n");
+	http_list_directory_header(srv, con, p, out);
+
+	/* directories */
+	for (i = 0; i < dirs.used; i++) {
+		tmp = dirs.ent[i];
+
+#ifdef HAVE_LOCALTIME_R
+		localtime_r(&(tmp->mtime), &tm);
+		strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", &tm);
+#else
+		strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", localtime(&(tmp->mtime)));
+#endif
+
+		BUFFER_APPEND_STRING_CONST(out, "<tr><td class=\"n\"><a href=\"");
+		buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_REL_URI_PART);
+		BUFFER_APPEND_STRING_CONST(out, "/\">");
+		buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_MINIMAL_XML);
+		BUFFER_APPEND_STRING_CONST(out, "</a>/</td><td class=\"m\">");
+		buffer_append_string_len(out, datebuf, sizeof(datebuf) - 1);
+		BUFFER_APPEND_STRING_CONST(out, "</td><td class=\"s\">- &nbsp;</td><td class=\"t\">Directory</td></tr>\n");
+
+		free(tmp);
+	}
+
+	/* files */
+	for (i = 0; i < files.used; i++) {
+		tmp = files.ent[i];
+
+		content_type = NULL;
+#ifdef HAVE_XATTR
+
+		if (con->conf.use_xattr) {
+			memcpy(path_file, DIRLIST_ENT_NAME(tmp), tmp->namelen + 1);
+			attrlen = sizeof(attrval) - 1;
+			if (attr_get(path, "Content-Type", attrval, &attrlen, 0) == 0) {
+				attrval[attrlen] = '\0';
+				content_type = attrval;
+			}
+		}
+#endif
+
+		if (content_type == NULL) {
+			content_type = "application/octet-stream";
+			for (k = 0; k < con->conf.mimetypes->used; k++) {
+				data_string *ds = (data_string *)con->conf.mimetypes->data[k];
+				size_t ct_len;
+
+				if (ds->key->used == 0)
+					continue;
+
+				ct_len = ds->key->used - 1;
+				if (tmp->namelen < ct_len)
+					continue;
+
+				if (0 == strncasecmp(DIRLIST_ENT_NAME(tmp) + tmp->namelen - ct_len, ds->key->ptr, ct_len)) {
+					content_type = ds->value->ptr;
+					break;
+				}
+			}
+		}
+
+#ifdef HAVE_LOCALTIME_R
+		localtime_r(&(tmp->mtime), &tm);
+		strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", &tm);
+#else
+		strftime(datebuf, sizeof(datebuf), "%Y-%b-%d %H:%M:%S", localtime(&(tmp->mtime)));
+#endif
+		http_list_directory_sizefmt(sizebuf, tmp->size);
+
+		BUFFER_APPEND_STRING_CONST(out, "<tr><td class=\"n\"><a href=\"");
+		buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_REL_URI_PART);
+		BUFFER_APPEND_STRING_CONST(out, "\">");
+		buffer_append_string_encoded(out, DIRLIST_ENT_NAME(tmp), tmp->namelen, ENCODING_MINIMAL_XML);
+		BUFFER_APPEND_STRING_CONST(out, "</a></td><td class=\"m\">");
+		buffer_append_string_len(out, datebuf, sizeof(datebuf) - 1);
+		BUFFER_APPEND_STRING_CONST(out, "</td><td class=\"s\">");
+		buffer_append_string(out, sizebuf);
+		BUFFER_APPEND_STRING_CONST(out, "</td><td class=\"t\">");
+		buffer_append_string(out, content_type);
+		BUFFER_APPEND_STRING_CONST(out, "</td></tr>\n");
+
+		free(tmp);
+	}
+
+	free(files.ent);
+	free(dirs.ent);
+	free(path);
+
+	http_list_directory_footer(srv, con, p, out);
+
+	/* Insert possible charset to Content-Type */
+	if (buffer_is_empty(p->conf.encoding)) {
+		response_header_insert(srv, con, CONST_STR_LEN("Content-Type"), CONST_STR_LEN("text/html"));
+	} else {
+		buffer_copy_string(p->content_charset, "text/html; charset=");
+		buffer_append_string_buffer(p->content_charset, p->conf.encoding);
+		response_header_insert(srv, con, CONST_STR_LEN("Content-Type"), CONST_BUF_LEN(p->content_charset));
+	}
+
+	con->file_finished = 1;
+
+	return 0;
+}
+
+
+
+URIHANDLER_FUNC(mod_dirlisting_subrequest) {
+	plugin_data *p = p_d;
+	stat_cache_entry *sce = NULL;
+
+	UNUSED(srv);
+
+	if (con->physical.path->used == 0) return HANDLER_GO_ON;
+	if (con->uri.path->used == 0) return HANDLER_GO_ON;
+	if (con->uri.path->ptr[con->uri.path->used - 2] != '/') return HANDLER_GO_ON;
+
+	mod_dirlisting_patch_connection(srv, con, p);
+
+	if (!p->conf.dir_listing) return HANDLER_GO_ON;
+
+	if (con->conf.log_request_handling) {
+		log_error_write(srv, __FILE__, __LINE__,  "s",  "-- handling the request as Dir-Listing");
+		log_error_write(srv, __FILE__, __LINE__,  "sb", "URI          :", con->uri.path);
+	}
+
+	if (HANDLER_ERROR == stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
+		fprintf(stderr, "%s.%d: %s\n", __FILE__, __LINE__, con->physical.path->ptr);
+		SEGFAULT();
+	}
+
+	if (!S_ISDIR(sce->st.st_mode)) return HANDLER_GO_ON;
+
+	if (http_list_directory(srv, con, p, con->physical.path)) {
+		/* dirlisting failed */
+		con->http_status = 403;
+	}
+
+	buffer_reset(con->physical.path);
+
+	/* not found */
+	return HANDLER_FINISHED;
+}
+
+/* this function is called at dlopen() time and inits the callbacks */
+
+int mod_dirlisting_plugin_init(plugin *p) {
+	p->version     = LIGHTTPD_VERSION_ID;
+	p->name        = buffer_init_string("dirlisting");
+
+	p->init        = mod_dirlisting_init;
+	p->handle_subrequest_start  = mod_dirlisting_subrequest;
+	p->set_defaults  = mod_dirlisting_set_defaults;
+	p->cleanup     = mod_dirlisting_free;
+
+	p->data        = NULL;
+
+	return 0;
+}

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/mod_evasive.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/mod_evasive.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/mod_evasive.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/mod_evasive.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,178 @@
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "base.h"
+#include "log.h"
+#include "buffer.h"
+
+#include "plugin.h"
+
+#include "inet_ntop_cache.h"
+
+/**
+ * mod_evasive
+ *
+ * we indent to implement all features the mod_evasive from apache has
+ *
+ * - limit of connections per IP
+ * - provide a list of block-listed ip/networks (no access)
+ * - provide a white-list of ips/network which is not affected by the limit
+ *   (hmm, conditionals might be enough)
+ * - provide a bandwidth limiter per IP
+ *
+ * started by:
+ * - w1zzard@techpowerup.com
+ */
+
+typedef struct {
+	unsigned short max_conns;
+} plugin_config;
+
+typedef struct {
+	PLUGIN_DATA;
+
+	plugin_config **config_storage;
+
+	plugin_config conf;
+} plugin_data;
+
+INIT_FUNC(mod_evasive_init) {
+	plugin_data *p;
+
+	p = calloc(1, sizeof(*p));
+
+	return p;
+}
+
+FREE_FUNC(mod_evasive_free) {
+	plugin_data *p = p_d;
+
+	UNUSED(srv);
+
+	if (!p) return HANDLER_GO_ON;
+
+	if (p->config_storage) {
+		size_t i;
+		for (i = 0; i < srv->config_context->used; i++) {
+			plugin_config *s = p->config_storage[i];
+
+			free(s);
+		}
+		free(p->config_storage);
+	}
+
+	free(p);
+
+	return HANDLER_GO_ON;
+}
+
+SETDEFAULTS_FUNC(mod_evasive_set_defaults) {
+	plugin_data *p = p_d;
+	size_t i = 0;
+
+	config_values_t cv[] = {
+		{ "evasive.max-conns-per-ip",    NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },
+		{ NULL,                          NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+	};
+
+	p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+
+	for (i = 0; i < srv->config_context->used; i++) {
+		plugin_config *s;
+
+		s = calloc(1, sizeof(plugin_config));
+		s->max_conns       = 0;
+
+		cv[0].destination = &(s->max_conns);
+
+		p->config_storage[i] = s;
+
+		if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+			return HANDLER_ERROR;
+		}
+	}
+
+	return HANDLER_GO_ON;
+}
+
+#define PATCH(x) \
+	p->conf.x = s->x;
+static int mod_evasive_patch_connection(server *srv, connection *con, plugin_data *p) {
+	size_t i, j;
+	plugin_config *s = p->config_storage[0];
+
+	PATCH(max_conns);
+
+	/* 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];
+		s = p->config_storage[i];
+
+		/* 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("evasive.max-conns-per-ip"))) {
+				PATCH(max_conns);
+			}
+		}
+	}
+
+	return 0;
+}
+#undef PATCH
+
+URIHANDLER_FUNC(mod_evasive_uri_handler) {
+	plugin_data *p = p_d;
+	size_t conns_by_ip = 0;
+	size_t j;
+
+	if (con->uri.path->used == 0) return HANDLER_GO_ON;
+
+	mod_evasive_patch_connection(srv, con, p);
+
+	/* no limit set, nothing to block */
+	if (p->conf.max_conns == 0) return HANDLER_GO_ON;
+
+	for (j = 0; j < srv->conns->used; j++) {
+		connection *c = srv->conns->ptr[j];
+
+		/* check if other connections are already actively serving data for the same IP
+		 * we can only ban connections which are already behind the 'read request' state
+		 * */
+		if (c->dst_addr.ipv4.sin_addr.s_addr == con->dst_addr.ipv4.sin_addr.s_addr &&
+		    c->state > CON_STATE_REQUEST_END) {
+			conns_by_ip++;
+
+			if (conns_by_ip > p->conf.max_conns) {
+				log_error_write(srv, __FILE__, __LINE__, "ss",
+					inet_ntop_cache_get_ip(srv, &(con->dst_addr)),
+					"turned away. Too many connections.");
+
+				con->http_status = 403;
+				return HANDLER_FINISHED;
+			}
+		}
+	}
+
+	return HANDLER_GO_ON;
+}
+
+
+int mod_evasive_plugin_init(plugin *p) {
+	p->version     = LIGHTTPD_VERSION_ID;
+	p->name        = buffer_init_string("evasive");
+
+	p->init        = mod_evasive_init;
+	p->set_defaults = mod_evasive_set_defaults;
+	p->handle_uri_clean  = mod_evasive_uri_handler;
+	p->cleanup     = mod_evasive_free;
+
+	p->data        = NULL;
+
+	return 0;
+}

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/mod_evhost.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/mod_evhost.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/mod_evhost.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/mod_evhost.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,334 @@
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+
+#include "plugin.h"
+#include "log.h"
+#include "response.h"
+#include "stat_cache.h"
+
+typedef struct {
+	/* unparsed pieces */
+	buffer *path_pieces_raw;
+
+	/* pieces for path creation */
+	size_t len;
+	buffer **path_pieces;
+} plugin_config;
+
+typedef struct {
+	PLUGIN_DATA;
+	buffer *tmp_buf;
+
+	plugin_config **config_storage;
+	plugin_config conf;
+} plugin_data;
+
+INIT_FUNC(mod_evhost_init) {
+	plugin_data *p;
+
+	p = calloc(1, sizeof(*p));
+
+	p->tmp_buf = buffer_init();
+
+	return p;
+}
+
+FREE_FUNC(mod_evhost_free) {
+	plugin_data *p = p_d;
+
+	UNUSED(srv);
+
+	if (!p) return HANDLER_GO_ON;
+
+	if (p->config_storage) {
+		size_t i;
+		for (i = 0; i < srv->config_context->used; i++) {
+			plugin_config *s = p->config_storage[i];
+
+			if (!s) continue;
+
+			if(s->path_pieces) {
+				size_t j;
+				for (j = 0; j < s->len; j++) {
+					buffer_free(s->path_pieces[j]);
+				}
+
+				free(s->path_pieces);
+			}
+
+			buffer_free(s->path_pieces_raw);
+
+			free(s);
+		}
+		free(p->config_storage);
+	}
+
+	buffer_free(p->tmp_buf);
+
+	free(p);
+
+	return HANDLER_GO_ON;
+}
+
+static void mod_evhost_parse_pattern(plugin_config *s) {
+	char *ptr = s->path_pieces_raw->ptr,*pos;
+
+	s->path_pieces = NULL;
+
+	for(pos=ptr;*ptr;ptr++) {
+		if(*ptr == '%') {
+			s->path_pieces = realloc(s->path_pieces,(s->len+2) * sizeof(*s->path_pieces));
+			s->path_pieces[s->len] = buffer_init();
+			s->path_pieces[s->len+1] = buffer_init();
+
+			buffer_copy_string_len(s->path_pieces[s->len],pos,ptr-pos);
+			pos = ptr + 2;
+
+			buffer_copy_string_len(s->path_pieces[s->len+1],ptr++,2);
+
+			s->len += 2;
+		}
+	}
+
+	if(*pos != '\0') {
+		s->path_pieces = realloc(s->path_pieces,(s->len+1) * sizeof(*s->path_pieces));
+		s->path_pieces[s->len] = buffer_init();
+
+		buffer_append_memory(s->path_pieces[s->len],pos,ptr-pos);
+
+		s->len += 1;
+	}
+}
+
+SETDEFAULTS_FUNC(mod_evhost_set_defaults) {
+	plugin_data *p = p_d;
+	size_t i;
+
+	/**
+	 *
+	 * #
+	 * # define a pattern for the host url finding
+	 * # %% => % sign
+	 * # %0 => domain name + tld
+	 * # %1 => tld
+	 * # %2 => domain name without tld
+	 * # %3 => subdomain 1 name
+	 * # %4 => subdomain 2 name
+	 * #
+	 * evhost.path-pattern = "/home/ckruse/dev/www/%3/htdocs/"
+	 *
+	 */
+
+	config_values_t cv[] = {
+		{ "evhost.path-pattern",            NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
+		{ NULL,                             NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+	};
+
+	if (!p) return HANDLER_ERROR;
+
+	p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+
+	for (i = 0; i < srv->config_context->used; i++) {
+		plugin_config *s;
+
+		s = calloc(1, sizeof(plugin_config));
+		s->path_pieces_raw = buffer_init();
+		s->path_pieces     = NULL;
+		s->len             = 0;
+
+		cv[0].destination = s->path_pieces_raw;
+
+		p->config_storage[i] = s;
+
+		if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value,  cv)) {
+			return HANDLER_ERROR;
+		}
+
+		if (s->path_pieces_raw->used != 0) {
+			mod_evhost_parse_pattern(s);
+		}
+	}
+
+	return HANDLER_GO_ON;
+}
+
+/**
+ * assign the different parts of the domain to array-indezes
+ * - %0 - full hostname (authority w/o port)
+ * - %1 - tld
+ * - %2 - domain.tld
+ * - %3 -
+ */
+
+static int mod_evhost_parse_host(connection *con,array *host) {
+	/* con->uri.authority->used is always > 0 if we come here */
+	register char *ptr = con->uri.authority->ptr + con->uri.authority->used - 1;
+	char *colon = ptr; /* needed to filter out the colon (if exists) */
+	int first = 1;
+	data_string *ds;
+	int i;
+
+	/* first, find the domain + tld */
+	for(;ptr > con->uri.authority->ptr;ptr--) {
+		if(*ptr == '.') {
+			if(first) first = 0;
+			else      break;
+		} else if(*ptr == ':') {
+			colon = ptr;
+			first = 1;
+		}
+	}
+
+	ds = data_string_init();
+	buffer_copy_string(ds->key,"%0");
+
+	/* if we stopped at a dot, skip the dot */
+	if (*ptr == '.') ptr++;
+	buffer_copy_string_len(ds->value, ptr, colon-ptr);
+
+	array_insert_unique(host,(data_unset *)ds);
+
+	/* if the : is not the start of the authority, go on parsing the hostname */
+
+	if (colon != con->uri.authority->ptr) {
+		for(ptr = colon - 1, i = 1; ptr > con->uri.authority->ptr; ptr--) {
+			if(*ptr == '.') {
+				if (ptr != colon - 1) {
+					/* is something between the dots */
+					ds = data_string_init();
+					buffer_copy_string(ds->key,"%");
+					buffer_append_long(ds->key, i++);
+					buffer_copy_string_len(ds->value,ptr+1,colon-ptr-1);
+
+					array_insert_unique(host,(data_unset *)ds);
+				}
+				colon = ptr;
+			}
+		}
+
+		/* if the . is not the first charactor of the hostname */
+		if (colon != ptr) {
+			ds = data_string_init();
+			buffer_copy_string(ds->key,"%");
+			buffer_append_long(ds->key, i++);
+			buffer_copy_string_len(ds->value,ptr,colon-ptr);
+
+			array_insert_unique(host,(data_unset *)ds);
+		}
+	}
+
+	return 0;
+}
+
+#define PATCH(x) \
+	p->conf.x = s->x;
+static int mod_evhost_patch_connection(server *srv, connection *con, plugin_data *p) {
+	size_t i, j;
+	plugin_config *s = p->config_storage[0];
+
+	PATCH(path_pieces);
+	PATCH(len);
+
+	/* 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];
+		s = p->config_storage[i];
+
+		/* 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("evhost.path-pattern"))) {
+				PATCH(path_pieces);
+				PATCH(len);
+			}
+		}
+	}
+
+	return 0;
+}
+#undef PATCH
+
+
+static handler_t mod_evhost_uri_handler(server *srv, connection *con, void *p_d) {
+	plugin_data *p = p_d;
+	size_t i;
+	array *parsed_host;
+	register char *ptr;
+	int not_good = 0;
+	stat_cache_entry *sce = NULL;
+
+	/* not authority set */
+	if (con->uri.authority->used == 0) return HANDLER_GO_ON;
+
+	mod_evhost_patch_connection(srv, con, p);
+
+	/* missing even default(global) conf */
+	if (0 == p->conf.len) {
+		return HANDLER_GO_ON;
+	}
+
+	parsed_host = array_init();
+
+	mod_evhost_parse_host(con, parsed_host);
+
+	/* build document-root */
+	buffer_reset(p->tmp_buf);
+
+	for (i = 0; i < p->conf.len; i++) {
+		ptr = p->conf.path_pieces[i]->ptr;
+		if (*ptr == '%') {
+			data_string *ds;
+
+			if (*(ptr+1) == '%') {
+				/* %% */
+				BUFFER_APPEND_STRING_CONST(p->tmp_buf,"%");
+			} else if (NULL != (ds = (data_string *)array_get_element(parsed_host,p->conf.path_pieces[i]->ptr))) {
+				if (ds->value->used) {
+					buffer_append_string_buffer(p->tmp_buf,ds->value);
+				}
+			} else {
+				/* unhandled %-sequence */
+			}
+		} else {
+			buffer_append_string_buffer(p->tmp_buf,p->conf.path_pieces[i]);
+		}
+	}
+
+	BUFFER_APPEND_SLASH(p->tmp_buf);
+
+	array_free(parsed_host);
+
+	if (HANDLER_ERROR == stat_cache_get_entry(srv, con, p->tmp_buf, &sce)) {
+		log_error_write(srv, __FILE__, __LINE__, "sb", strerror(errno), p->tmp_buf);
+		not_good = 1;
+	} else if(!S_ISDIR(sce->st.st_mode)) {
+		log_error_write(srv, __FILE__, __LINE__, "sb", "not a directory:", p->tmp_buf);
+		not_good = 1;
+	}
+
+	if (!not_good) {
+		buffer_copy_string_buffer(con->physical.doc_root, p->tmp_buf);
+	}
+
+	return HANDLER_GO_ON;
+}
+
+int mod_evhost_plugin_init(plugin *p) {
+	p->version     = LIGHTTPD_VERSION_ID;
+	p->name                    = buffer_init_string("evhost");
+	p->init                    = mod_evhost_init;
+	p->set_defaults            = mod_evhost_set_defaults;
+	p->handle_docroot          = mod_evhost_uri_handler;
+	p->cleanup                 = mod_evhost_free;
+
+	p->data                    = NULL;
+
+	return 0;
+}
+
+/* eof */

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/mod_expire.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/mod_expire.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/mod_expire.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/mod_expire.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,369 @@
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "base.h"
+#include "log.h"
+#include "buffer.h"
+#include "response.h"
+
+#include "plugin.h"
+#include "stat_cache.h"
+
+/**
+ * this is a expire module for a lighttpd
+ *
+ * set 'Expires:' HTTP Headers on demand
+ */
+
+
+
+/* plugin config for all request/connections */
+
+typedef struct {
+	array *expire_url;
+} plugin_config;
+
+typedef struct {
+	PLUGIN_DATA;
+
+	buffer *expire_tstmp;
+
+	plugin_config **config_storage;
+
+	plugin_config conf;
+} plugin_data;
+
+/* init the plugin data */
+INIT_FUNC(mod_expire_init) {
+	plugin_data *p;
+
+	p = calloc(1, sizeof(*p));
+
+	p->expire_tstmp = buffer_init();
+
+	buffer_prepare_copy(p->expire_tstmp, 255);
+
+	return p;
+}
+
+/* detroy the plugin data */
+FREE_FUNC(mod_expire_free) {
+	plugin_data *p = p_d;
+
+	UNUSED(srv);
+
+	if (!p) return HANDLER_GO_ON;
+
+	buffer_free(p->expire_tstmp);
+
+	if (p->config_storage) {
+		size_t i;
+		for (i = 0; i < srv->config_context->used; i++) {
+			plugin_config *s = p->config_storage[i];
+
+			array_free(s->expire_url);
+
+			free(s);
+		}
+		free(p->config_storage);
+	}
+
+	free(p);
+
+	return HANDLER_GO_ON;
+}
+
+static int mod_expire_get_offset(server *srv, plugin_data *p, buffer *expire, int *offset) {
+	char *ts;
+	int type = -1;
+	int retts = 0;
+
+	UNUSED(p);
+
+	/*
+	 * parse
+	 *
+	 * '(access|now|modification) [plus] {<num> <type>}*'
+	 *
+	 * e.g. 'access 1 years'
+	 */
+
+	if (expire->used == 0) {
+		log_error_write(srv, __FILE__, __LINE__, "s",
+				"empty:");
+		return -1;
+	}
+
+	ts = expire->ptr;
+
+	if (0 == strncmp(ts, "access ", 7)) {
+		type  = 0;
+		ts   += 7;
+	} else if (0 == strncmp(ts, "now ", 4)) {
+		type  = 0;
+		ts   += 4;
+	} else if (0 == strncmp(ts, "modification ", 13)) {
+		type  = 1;
+		ts   += 13;
+	} else {
+		/* invalid type-prefix */
+		log_error_write(srv, __FILE__, __LINE__, "ss",
+				"invalid <base>:", ts);
+		return -1;
+	}
+
+	if (0 == strncmp(ts, "plus ", 5)) {
+		/* skip the optional plus */
+		ts   += 5;
+	}
+
+	/* the rest is just <number> (years|months|weeks|days|hours|minutes|seconds) */
+	while (1) {
+		char *space, *err;
+		int num;
+
+		if (NULL == (space = strchr(ts, ' '))) {
+			log_error_write(srv, __FILE__, __LINE__, "ss",
+					"missing space after <num>:", ts);
+			return -1;
+		}
+
+		num = strtol(ts, &err, 10);
+		if (*err != ' ') {
+			log_error_write(srv, __FILE__, __LINE__, "ss",
+					"missing <type> after <num>:", ts);
+			return -1;
+		}
+
+		ts = space + 1;
+
+		if (NULL != (space = strchr(ts, ' '))) {
+			int slen;
+			/* */
+
+			slen = space - ts;
+
+			if (slen == 5 &&
+			    0 == strncmp(ts, "years", slen)) {
+				num *= 60 * 60 * 24 * 30 * 12;
+			} else if (slen == 6 &&
+				   0 == strncmp(ts, "months", slen)) {
+				num *= 60 * 60 * 24 * 30;
+			} else if (slen == 5 &&
+				   0 == strncmp(ts, "weeks", slen)) {
+				num *= 60 * 60 * 24 * 7;
+			} else if (slen == 4 &&
+				   0 == strncmp(ts, "days", slen)) {
+				num *= 60 * 60 * 24;
+			} else if (slen == 5 &&
+				   0 == strncmp(ts, "hours", slen)) {
+				num *= 60 * 60;
+			} else if (slen == 7 &&
+				   0 == strncmp(ts, "minutes", slen)) {
+				num *= 60;
+			} else if (slen == 7 &&
+				   0 == strncmp(ts, "seconds", slen)) {
+				num *= 1;
+			} else {
+				log_error_write(srv, __FILE__, __LINE__, "ss",
+						"unknown type:", ts);
+				return -1;
+			}
+
+			retts += num;
+
+			ts = space + 1;
+		} else {
+			if (0 == strcmp(ts, "years")) {
+				num *= 60 * 60 * 24 * 30 * 12;
+			} else if (0 == strcmp(ts, "months")) {
+				num *= 60 * 60 * 24 * 30;
+			} else if (0 == strcmp(ts, "weeks")) {
+				num *= 60 * 60 * 24 * 7;
+			} else if (0 == strcmp(ts, "days")) {
+				num *= 60 * 60 * 24;
+			} else if (0 == strcmp(ts, "hours")) {
+				num *= 60 * 60;
+			} else if (0 == strcmp(ts, "minutes")) {
+				num *= 60;
+			} else if (0 == strcmp(ts, "seconds")) {
+				num *= 1;
+			} else {
+				log_error_write(srv, __FILE__, __LINE__, "ss",
+						"unknown type:", ts);
+				return -1;
+			}
+
+			retts += num;
+
+			break;
+		}
+	}
+
+	if (offset != NULL) *offset = retts;
+
+	return type;
+}
+
+
+/* handle plugin config and check values */
+
+SETDEFAULTS_FUNC(mod_expire_set_defaults) {
+	plugin_data *p = p_d;
+	size_t i = 0, k;
+
+	config_values_t cv[] = {
+		{ "expire.url",                 NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
+		{ NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+	};
+
+	if (!p) return HANDLER_ERROR;
+
+	p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+
+	for (i = 0; i < srv->config_context->used; i++) {
+		plugin_config *s;
+
+		s = calloc(1, sizeof(plugin_config));
+		s->expire_url    = array_init();
+
+		cv[0].destination = s->expire_url;
+
+		p->config_storage[i] = s;
+
+		if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+			return HANDLER_ERROR;
+		}
+
+		for (k = 0; k < s->expire_url->used; k++) {
+			data_string *ds = (data_string *)s->expire_url->data[k];
+
+			/* parse lines */
+			if (-1 == mod_expire_get_offset(srv, p, ds->value, NULL)) {
+				log_error_write(srv, __FILE__, __LINE__, "sb",
+						"parsing expire.url failed:", ds->value);
+				return HANDLER_ERROR;
+			}
+		}
+	}
+
+
+	return HANDLER_GO_ON;
+}
+
+#define PATCH(x) \
+	p->conf.x = s->x;
+static int mod_expire_patch_connection(server *srv, connection *con, plugin_data *p) {
+	size_t i, j;
+	plugin_config *s = p->config_storage[0];
+
+	PATCH(expire_url);
+
+	/* 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];
+		s = p->config_storage[i];
+
+		/* 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("expire.url"))) {
+				PATCH(expire_url);
+			}
+		}
+	}
+
+	return 0;
+}
+#undef PATCH
+
+URIHANDLER_FUNC(mod_expire_path_handler) {
+	plugin_data *p = p_d;
+	int s_len;
+	size_t k;
+
+	if (con->uri.path->used == 0) return HANDLER_GO_ON;
+
+	mod_expire_patch_connection(srv, con, p);
+
+	s_len = con->uri.path->used - 1;
+
+	for (k = 0; k < p->conf.expire_url->used; k++) {
+		data_string *ds = (data_string *)p->conf.expire_url->data[k];
+		int ct_len = ds->key->used - 1;
+
+		if (ct_len > s_len) continue;
+		if (ds->key->used == 0) continue;
+
+		if (0 == strncmp(con->uri.path->ptr, ds->key->ptr, ct_len)) {
+			int ts;
+			time_t t;
+			size_t len;
+			stat_cache_entry *sce = NULL;
+
+			stat_cache_get_entry(srv, con, con->physical.path, &sce);
+
+			switch(mod_expire_get_offset(srv, p, ds->value, &ts)) {
+			case 0:
+				/* access */
+				t = (ts + srv->cur_ts);
+				break;
+			case 1:
+				/* modification */
+
+				t = (ts + sce->st.st_mtime);
+				break;
+			default:
+				/* -1 is handled at parse-time */
+				break;
+			}
+
+
+			if (0 == (len = strftime(p->expire_tstmp->ptr, p->expire_tstmp->size - 1,
+					   "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(t))))) {
+				/* could not set expire header, out of mem */
+
+				return HANDLER_GO_ON;
+
+			}
+
+			p->expire_tstmp->used = len + 1;
+
+			/* HTTP/1.0 */
+			response_header_overwrite(srv, con, CONST_STR_LEN("Expires"), CONST_BUF_LEN(p->expire_tstmp));
+
+			/* HTTP/1.1 */
+			buffer_copy_string(p->expire_tstmp, "max-age=");
+			buffer_append_long(p->expire_tstmp, ts);
+
+			response_header_overwrite(srv, con, CONST_STR_LEN("Cache-Control"), CONST_BUF_LEN(p->expire_tstmp));
+
+			return HANDLER_GO_ON;
+		}
+	}
+
+	/* not found */
+	return HANDLER_GO_ON;
+}
+
+/* this function is called at dlopen() time and inits the callbacks */
+
+int mod_expire_plugin_init(plugin *p) {
+	p->version     = LIGHTTPD_VERSION_ID;
+	p->name        = buffer_init_string("expire");
+
+	p->init        = mod_expire_init;
+	p->handle_subrequest_start = mod_expire_path_handler;
+	p->set_defaults  = mod_expire_set_defaults;
+	p->cleanup     = mod_expire_free;
+
+	p->data        = NULL;
+
+	return 0;
+}

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/mod_extforward.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/mod_extforward.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/mod_extforward.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/mod_extforward.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,496 @@
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <netinet/in.h>
+
+#include "base.h"
+#include "log.h"
+#include "buffer.h"
+
+#include "plugin.h"
+
+#include "inet_ntop_cache.h"
+#include "configfile.h"
+
+/**
+ * mod_extforward.c for lighttpd, by comman.kang <at> gmail <dot> com
+ *                  extended, modified by Lionel Elie Mamane (LEM), lionel <at> mamane <dot> lu
+ *                  support chained proxies by glen@delfi.ee, #1528
+ *
+ * Config example:
+ *
+ *       Trust proxy 10.0.0.232 and 10.0.0.232
+ *       extforward.forwarder = ( "10.0.0.232" => "trust",
+ *                                "10.0.0.233" => "trust" )
+ *
+ *       Trust all proxies  (NOT RECOMMENDED!)
+ *       extforward.forwarder = ( "all" => "trust")
+ *
+ *       Note that "all" has precedence over specific entries,
+ *       so "all except" setups will not work.
+ *
+ *       In case you have chained proxies, you can add all their IP's to the
+ *       config. However "all" has effect only on connecting IP, as the
+ *       X-Forwarded-For header can not be trusted.
+ *
+ * Note: The effect of this module is variable on $HTTP["remotip"] directives and
+ *       other module's remote ip dependent actions.
+ *  Things done by modules before we change the remoteip or after we reset it will match on the proxy's IP.
+ *  Things done in between these two moments will match on the real client's IP.
+ *  The moment things are done by a module depends on in which hook it does things and within the same hook
+ *  on whether they are before/after us in the module loading order
+ *  (order in the server.modules directive in the config file).
+ *
+ * Tested behaviours:
+ *
+ *  mod_access: Will match on the real client.
+ *
+ *  mod_accesslog:
+ *   In order to see the "real" ip address in access log ,
+ *   you'll have to load mod_extforward after mod_accesslog.
+ *   like this:
+ *
+ *    server.modules  = (
+ *       .....
+ *       mod_accesslog,
+ *       mod_extforward
+ *    )
+ *
+ * Known issues:
+ *      seems causing segfault with mod_ssl and $HTTP{"socket"} directives
+ *      LEM 2006.05.26: Fixed segfault $SERVER["socket"] directive. Untested with SSL.
+ *
+ * ChangeLog:
+ *     2005.12.19   Initial Version
+ *     2005.12.19   fixed conflict with conditional directives
+ *     2006.05.26   LEM: IPv6 support
+ *     2006.05.26   LEM: Fix a segfault with $SERVER["socket"] directive.
+ *     2006.05.26   LEM: Run at uri_raw time, as we don't need to see the URI
+ *                       In this manner, we run before mod_access and $HTTP["remoteip"] directives work!
+ *     2006.05.26   LEM: Clean config_cond cache of tests whose result we probably change.
+ */
+
+
+/* plugin config for all request/connections */
+
+typedef struct {
+	array *forwarder;
+} plugin_config;
+
+typedef struct {
+	PLUGIN_DATA;
+
+	plugin_config **config_storage;
+
+	plugin_config conf;
+} plugin_data;
+
+
+/* context , used for restore remote ip */
+
+typedef struct {
+	sock_addr saved_remote_addr;
+	buffer *saved_remote_addr_buf;
+} handler_ctx;
+
+
+static handler_ctx * handler_ctx_init(sock_addr oldaddr, buffer *oldaddr_buf) {
+	handler_ctx * hctx;
+	hctx = calloc(1, sizeof(*hctx));
+	hctx->saved_remote_addr = oldaddr;
+	hctx->saved_remote_addr_buf = oldaddr_buf;
+	return hctx;
+}
+
+static void handler_ctx_free(handler_ctx *hctx) {
+	free(hctx);
+}
+
+/* init the plugin data */
+INIT_FUNC(mod_extforward_init) {
+	plugin_data *p;
+	p = calloc(1, sizeof(*p));
+	return p;
+}
+
+/* destroy the plugin data */
+FREE_FUNC(mod_extforward_free) {
+	plugin_data *p = p_d;
+
+	UNUSED(srv);
+
+	if (!p) return HANDLER_GO_ON;
+
+	if (p->config_storage) {
+		size_t i;
+
+		for (i = 0; i < srv->config_context->used; i++) {
+			plugin_config *s = p->config_storage[i];
+
+			if (!s) continue;
+
+			array_free(s->forwarder);
+
+			free(s);
+		}
+		free(p->config_storage);
+	}
+
+
+	free(p);
+
+	return HANDLER_GO_ON;
+}
+
+/* handle plugin config and check values */
+
+SETDEFAULTS_FUNC(mod_extforward_set_defaults) {
+	plugin_data *p = p_d;
+	size_t i = 0;
+
+	config_values_t cv[] = {
+		{ "extforward.forwarder",             NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
+		{ NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
+	};
+
+	if (!p) return HANDLER_ERROR;
+
+	p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
+
+	for (i = 0; i < srv->config_context->used; i++) {
+		plugin_config *s;
+
+		s = calloc(1, sizeof(plugin_config));
+		s->forwarder    = array_init();
+
+		cv[0].destination = s->forwarder;
+
+		p->config_storage[i] = s;
+
+		if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
+			return HANDLER_ERROR;
+		}
+	}
+
+	return HANDLER_GO_ON;
+}
+
+#define PATCH(x) \
+	p->conf.x = s->x;
+static int mod_extforward_patch_connection(server *srv, connection *con, plugin_data *p) {
+	size_t i, j;
+	plugin_config *s = p->config_storage[0];
+
+	PATCH(forwarder);
+
+	/* 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];
+		s = p->config_storage[i];
+
+		/* 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("extforward.forwarder"))) {
+				PATCH(forwarder);
+			}
+		}
+	}
+
+	return 0;
+}
+#undef PATCH
+
+
+static void put_string_into_array_len(array *ary, const char *str, int len)
+{
+	data_string *tempdata;
+	if (len == 0)
+		return;
+	tempdata = data_string_init();
+	buffer_copy_string_len(tempdata->value,str,len);
+	array_insert_unique(ary,(data_unset *)tempdata);
+}
+/*
+   extract a forward array from the environment
+*/
+static array *extract_forward_array(buffer *pbuffer)
+{
+	array *result = array_init();
+	if (pbuffer->used > 0) {
+		char *base, *curr;
+		/* state variable, 0 means not in string, 1 means in string */
+		int in_str = 0;
+		for (base = pbuffer->ptr, curr = pbuffer->ptr; *curr; curr++) {
+			if (in_str) {
+				if ((*curr > '9' || *curr < '0') && *curr != '.' && *curr != ':') {
+					/* found an separator , insert value into result array */
+					put_string_into_array_len(result, base, curr - base);
+					/* change state to not in string */
+					in_str = 0;
+				}
+			} else {
+				if (*curr >= '0' && *curr <= '9') {
+					/* found leading char of an IP address, move base pointer and change state */
+					base = curr;
+					in_str = 1;
+				}
+			}
+		}
+		/* if breaking out while in str, we got to the end of string, so add it */
+		if (in_str) {
+			put_string_into_array_len(result, base, curr - base);
+		}
+	}
+	return result;
+}
+
+#define IP_TRUSTED 1
+#define IP_UNTRUSTED 0
+/*
+ * check whether ip is trusted, return 1 for trusted , 0 for untrusted
+ */
+static int is_proxy_trusted(const char *ipstr, plugin_data *p)
+{
+	data_string* allds = (data_string *)array_get_element(p->conf.forwarder, "all");
+
+	if (allds) {
+		if (strcasecmp(allds->value->ptr, "trust") == 0) {
+			return IP_TRUSTED;
+		} else {
+			return IP_UNTRUSTED;
+		}
+	}
+
+	return (data_string *)array_get_element(p->conf.forwarder, ipstr) ? IP_TRUSTED : IP_UNTRUSTED;
+}
+
+/*
+ * Return char *ip of last address of proxy that is not trusted.
+ * Do not accept "all" keyword here.
+ */
+static const char *last_not_in_array(array *a, plugin_data *p)
+{
+	array *forwarder = p->conf.forwarder;
+
+	for (int i = a->used - 1; i >= 0; i--) {
+		data_string *ds = (data_string *)a->data[i];
+		const char *ip = ds->value->ptr;
+
+		if (!array_get_element(forwarder, ip)) {
+			return ip;
+		}
+	}
+	return NULL;
+}
+
+struct addrinfo *ipstr_to_sockaddr(const char *host)
+{
+   struct addrinfo hints, *res0;
+   int result;
+
+   memset(&hints, 0, sizeof(hints));
+#ifndef AI_NUMERICSERV
+/** 
+ * quoting $ man getaddrinfo
+ *
+ * NOTES
+ *        AI_ADDRCONFIG, AI_ALL, and AI_V4MAPPED are available since glibc 2.3.3.  
+ *        AI_NUMERICSERV is available since glibc 2.3.4.
+ */
+#define AI_NUMERICSERV 0
+#endif
+   hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
+
+   result = getaddrinfo(host, NULL, &hints, &res0);
+   if ( result != 0 )
+   {
+      fprintf(stderr,"could not resolve hostname %s because %s\n", host,gai_strerror(result));
+      if (result == EAI_SYSTEM)
+         perror("The system error is ");
+      return NULL;
+   }
+   else
+      if (res0==0)
+         fprintf(stderr, "Problem in resolving hostname %s: succeeded, but no information returned\n", host);
+
+   return res0;
+}
+
+
+
+static void clean_cond_cache(server *srv, connection *con) {
+	config_cond_cache_reset_item(srv, con, COMP_HTTP_REMOTE_IP);
+}
+
+URIHANDLER_FUNC(mod_extforward_uri_handler) {
+	plugin_data *p = p_d;
+	data_string *forwarded = NULL;
+#ifdef HAVE_IPV6
+	char b2[INET6_ADDRSTRLEN + 1];
+	struct addrinfo *addrlist = NULL;
+#endif
+	const char *dst_addr_str = NULL;
+	array *forward_array = NULL;
+	const char *real_remote_addr = NULL;
+#ifdef HAVE_IPV6
+#endif
+
+	if (!con->request.headers) return HANDLER_GO_ON;
+
+	mod_extforward_patch_connection(srv, con, p);
+
+	if (con->conf.log_request_handling) {
+ 		log_error_write(srv, __FILE__, __LINE__, "s", 
+				"-- mod_extforward_uri_handler called");
+	}
+
+	if ((NULL == (forwarded = (data_string *) array_get_element(con->request.headers,"X-Forwarded-For")) &&
+	     NULL == (forwarded = (data_string *) array_get_element(con->request.headers,  "Forwarded-For")))) {
+
+		if (con->conf.log_request_handling) {
+			log_error_write(srv, __FILE__, __LINE__, "s", 
+					"no X-Forwarded-For|Forwarded-For: found, skipping");
+		}
+
+		return HANDLER_GO_ON;
+	}
+
+#ifdef HAVE_IPV6
+	dst_addr_str = inet_ntop(con->dst_addr.plain.sa_family,
+		      con->dst_addr.plain.sa_family == AF_INET6 ?
+		       (struct sockaddr *)&(con->dst_addr.ipv6.sin6_addr) :
+		       (struct sockaddr *)&(con->dst_addr.ipv4.sin_addr),
+		      b2,
+		      (sizeof b2) - 1);
+#else
+	dst_addr_str = inet_ntoa(con->dst_addr.ipv4.sin_addr);
+#endif
+
+	/* if the remote ip itself is not trusted, then do nothing */
+	if (IP_UNTRUSTED == is_proxy_trusted(dst_addr_str, p)) {
+		if (con->conf.log_request_handling) {
+			log_error_write(srv, __FILE__, __LINE__, "s",
+					"remote address is NOT a trusted proxy, skipping");
+		}
+
+		return HANDLER_GO_ON;
+	}
+
+	/* build forward_array from forwarded data_string */
+	forward_array = extract_forward_array(forwarded->value);
+	real_remote_addr = last_not_in_array(forward_array, p);
+
+	if (real_remote_addr != NULL) { /* parsed */
+		sock_addr sock;
+		struct addrinfo *addrs_left;
+		server_socket *srv_sock = con->srv_socket;
+		data_string *forwarded_proto = (data_string *)array_get_element(con->request.headers, "X-Forwarded-Proto");
+
+		if (forwarded_proto && !strcmp(forwarded_proto->value->ptr, "https")) {
+			srv_sock->is_proxy_ssl = 1;
+		} else {
+			srv_sock->is_proxy_ssl = 0;
+		}
+
+		if (con->conf.log_request_handling) {
+ 			log_error_write(srv, __FILE__, __LINE__, "ss", "using address:", real_remote_addr);
+		}
+#ifdef HAVE_IPV6
+		addrlist = ipstr_to_sockaddr(real_remote_addr);
+		sock.plain.sa_family = AF_UNSPEC;
+		for (addrs_left = addrlist; addrs_left != NULL; addrs_left = addrs_left -> ai_next) {
+			sock.plain.sa_family = addrs_left->ai_family;
+			if (sock.plain.sa_family == AF_INET) {
+				sock.ipv4.sin_addr = ((struct sockaddr_in*)addrs_left->ai_addr)->sin_addr;
+				break;
+			} else if (sock.plain.sa_family == AF_INET6) {
+				sock.ipv6.sin6_addr = ((struct sockaddr_in6*)addrs_left->ai_addr)->sin6_addr;
+				break;
+			}
+		}
+#else
+		sock.ipv4.sin_addr.s_addr = inet_addr(real_remote_addr);
+		sock.plain.sa_family = (sock.ipv4.sin_addr.s_addr == 0xFFFFFFFF) ? AF_UNSPEC : AF_INET;
+#endif
+		if (sock.plain.sa_family != AF_UNSPEC) {
+			/* we found the remote address, modify current connection and save the old address */
+			if (con->plugin_ctx[p->id]) {
+				log_error_write(srv, __FILE__, __LINE__, "s", 
+						"patching an already patched connection!");
+				handler_ctx_free(con->plugin_ctx[p->id]);
+				con->plugin_ctx[p->id] = NULL;
+			}
+			/* save old address */
+			con->plugin_ctx[p->id] = handler_ctx_init(con->dst_addr, con->dst_addr_buf);
+			/* patch connection address */
+			con->dst_addr = sock;
+			con->dst_addr_buf = buffer_init();
+			buffer_copy_string(con->dst_addr_buf, real_remote_addr);
+		
+			if (con->conf.log_request_handling) {
+ 				log_error_write(srv, __FILE__, __LINE__, "ss",
+						"patching con->dst_addr_buf for the accesslog:", real_remote_addr);
+			}
+			/* Now, clean the conf_cond cache, because we may have changed the results of tests */
+			clean_cond_cache(srv, con);
+		}
+#ifdef HAVE_IPV6
+		if (addrlist != NULL ) freeaddrinfo(addrlist);
+#endif
+	}
+	array_free(forward_array);
+
+	/* not found */
+	return HANDLER_GO_ON;
+}
+
+CONNECTION_FUNC(mod_extforward_restore) {
+	plugin_data *p = p_d;
+	handler_ctx *hctx = con->plugin_ctx[p->id];
+
+	if (!hctx) return HANDLER_GO_ON;
+	
+	con->dst_addr = hctx->saved_remote_addr;
+	buffer_free(con->dst_addr_buf);
+
+	con->dst_addr_buf = hctx->saved_remote_addr_buf;
+	
+	handler_ctx_free(hctx);
+
+	con->plugin_ctx[p->id] = NULL;
+
+	/* Now, clean the conf_cond cache, because we may have changed the results of tests */
+	clean_cond_cache(srv, con);
+
+	return HANDLER_GO_ON;
+}
+
+
+/* this function is called at dlopen() time and inits the callbacks */
+
+int mod_extforward_plugin_init(plugin *p) {
+	p->version     = LIGHTTPD_VERSION_ID;
+	p->name        = buffer_init_string("extforward");
+
+	p->init        = mod_extforward_init;
+	p->handle_uri_raw = mod_extforward_uri_handler;
+	p->handle_request_done = mod_extforward_restore;
+	p->connection_reset = mod_extforward_restore;
+	p->set_defaults  = mod_extforward_set_defaults;
+	p->cleanup     = mod_extforward_free;
+
+	p->data        = NULL;
+
+	return 0;
+}
+