You are viewing a plain text version of this content. The canonical link for it is here.
Posted to axis-cvs@ws.apache.org by di...@apache.org on 2008/07/22 06:35:46 UTC

svn commit: r678637 [41/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/request.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/request.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/request.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/request.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,1171 @@
+#include <sys/stat.h>
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "request.h"
+#include "keyvalue.h"
+#include "log.h"
+
+static int request_check_hostname(server *srv, connection *con, buffer *host) {
+	enum { DOMAINLABEL, TOPLABEL } stage = TOPLABEL;
+	size_t i;
+	int label_len = 0;
+	size_t host_len;
+	char *colon;
+	int is_ip = -1; /* -1 don't know yet, 0 no, 1 yes */
+	int level = 0;
+
+	UNUSED(srv);
+	UNUSED(con);
+
+	/*
+	 *       hostport      = host [ ":" port ]
+	 *       host          = hostname | IPv4address | IPv6address
+	 *       hostname      = *( domainlabel "." ) toplabel [ "." ]
+	 *       domainlabel   = alphanum | alphanum *( alphanum | "-" ) alphanum
+	 *       toplabel      = alpha | alpha *( alphanum | "-" ) alphanum
+	 *       IPv4address   = 1*digit "." 1*digit "." 1*digit "." 1*digit
+	 *       IPv6address   = "[" ... "]"
+	 *       port          = *digit
+	 */
+
+	/* no Host: */
+	if (!host || host->used == 0) return 0;
+
+	host_len = host->used - 1;
+
+	/* IPv6 adress */
+	if (host->ptr[0] == '[') {
+		char *c = host->ptr + 1;
+		int colon_cnt = 0;
+
+		/* check portnumber */
+		for (; *c && *c != ']'; c++) {
+			if (*c == ':') {
+				if (++colon_cnt > 7) {
+					return -1;
+				}
+			} else if (!light_isxdigit(*c)) {
+				return -1;
+			}
+		}
+
+		/* missing ] */
+		if (!*c) {
+			return -1;
+		}
+
+		/* check port */
+		if (*(c+1) == ':') {
+			for (c += 2; *c; c++) {
+				if (!light_isdigit(*c)) {
+					return -1;
+				}
+			}
+		}
+		return 0;
+	}
+
+	if (NULL != (colon = memchr(host->ptr, ':', host_len))) {
+		char *c = colon + 1;
+
+		/* check portnumber */
+		for (; *c; c++) {
+			if (!light_isdigit(*c)) return -1;
+		}
+
+		/* remove the port from the host-len */
+		host_len = colon - host->ptr;
+	}
+
+	/* Host is empty */
+	if (host_len == 0) return -1;
+
+	/* if the hostname ends in a "." strip it */
+	if (host->ptr[host_len-1] == '.') host_len -= 1;
+
+	/* scan from the right and skip the \0 */
+	for (i = host_len - 1; i + 1 > 0; i--) {
+		const char c = host->ptr[i];
+
+		switch (stage) {
+		case TOPLABEL:
+			if (c == '.') {
+				/* only switch stage, if this is not the last character */
+				if (i != host_len - 1) {
+					if (label_len == 0) {
+						return -1;
+					}
+
+					/* check the first character at right of the dot */
+					if (is_ip == 0) {
+						if (!light_isalpha(host->ptr[i+1])) {
+							return -1;
+						}
+					} else if (!light_isdigit(host->ptr[i+1])) {
+						is_ip = 0;
+					} else if ('-' == host->ptr[i+1]) {
+						return -1;
+					} else {
+						/* just digits */
+						is_ip = 1;
+					}
+
+					stage = DOMAINLABEL;
+
+					label_len = 0;
+					level++;
+				} else if (i == 0) {
+					/* just a dot and nothing else is evil */
+					return -1;
+				}
+			} else if (i == 0) {
+				/* the first character of the hostname */
+				if (!light_isalpha(c)) {
+					return -1;
+				}
+				label_len++;
+			} else {
+				if (c != '-' && !light_isalnum(c)) {
+					return -1;
+				}
+				if (is_ip == -1) {
+					if (!light_isdigit(c)) is_ip = 0;
+				}
+				label_len++;
+			}
+
+			break;
+		case DOMAINLABEL:
+			if (is_ip == 1) {
+				if (c == '.') {
+					if (label_len == 0) {
+						return -1;
+					}
+
+					label_len = 0;
+					level++;
+				} else if (!light_isdigit(c)) {
+					return -1;
+				} else {
+					label_len++;
+				}
+			} else {
+				if (c == '.') {
+					if (label_len == 0) {
+						return -1;
+					}
+
+					/* c is either - or alphanum here */
+					if ('-' == host->ptr[i+1]) {
+						return -1;
+					}
+
+					label_len = 0;
+					level++;
+				} else if (i == 0) {
+					if (!light_isalnum(c)) {
+						return -1;
+					}
+					label_len++;
+				} else {
+					if (c != '-' && !light_isalnum(c)) {
+						return -1;
+					}
+					label_len++;
+				}
+			}
+
+			break;
+		}
+	}
+
+	/* a IP has to consist of 4 parts */
+	if (is_ip == 1 && level != 3) {
+		return -1;
+	}
+
+	if (label_len == 0) {
+		return -1;
+	}
+
+	return 0;
+}
+
+#if 0
+#define DUMP_HEADER
+#endif
+
+int http_request_split_value(array *vals, buffer *b) {
+	char *s;
+	size_t i;
+	int state = 0;
+	/*
+	 * parse
+	 *
+	 * val1, val2, val3, val4
+	 *
+	 * into a array (more or less a explode() incl. striping of whitespaces
+	 */
+
+	if (b->used == 0) return 0;
+
+	s = b->ptr;
+
+	for (i =0; i < b->used - 1; ) {
+		char *start = NULL, *end = NULL;
+		data_string *ds;
+
+		switch (state) {
+		case 0: /* ws */
+
+			/* skip ws */
+			for (; (*s == ' ' || *s == '\t') && i < b->used - 1; i++, s++);
+
+
+			state = 1;
+			break;
+		case 1: /* value */
+			start = s;
+
+			for (; *s != ',' && i < b->used - 1; i++, s++);
+			end = s - 1;
+
+			for (; (*end == ' ' || *end == '\t') && end > start; end--);
+
+			if (NULL == (ds = (data_string *)array_get_unused_element(vals, TYPE_STRING))) {
+				ds = data_string_init();
+			}
+
+			buffer_copy_string_len(ds->value, start, end-start+1);
+			array_insert_unique(vals, (data_unset *)ds);
+
+			if (*s == ',') {
+				state = 0;
+				i++;
+				s++;
+			} else {
+				/* end of string */
+
+				state = 2;
+			}
+			break;
+		default:
+			i++;
+			break;
+		}
+	}
+	return 0;
+}
+
+int request_uri_is_valid_char(unsigned char c) {
+	if (c <= 32) return 0;
+	if (c == 127) return 0;
+	if (c == 255) return 0;
+
+	return 1;
+}
+
+int http_request_parse(server *srv, connection *con) {
+	char *uri = NULL, *proto = NULL, *method = NULL, con_length_set;
+	int is_key = 1, key_len = 0, is_ws_after_key = 0, in_folding;
+	char *value = NULL, *key = NULL;
+
+	enum { HTTP_CONNECTION_UNSET, HTTP_CONNECTION_KEEPALIVE, HTTP_CONNECTION_CLOSE } keep_alive_set = HTTP_CONNECTION_UNSET;
+
+	int line = 0;
+
+	int request_line_stage = 0;
+	size_t i, first;
+
+	int done = 0;
+
+	/*
+	 * Request: "^(GET|POST|HEAD) ([^ ]+(\\?[^ ]+|)) (HTTP/1\\.[01])$"
+	 * Option : "^([-a-zA-Z]+): (.+)$"
+	 * End    : "^$"
+	 */
+
+	if (con->conf.log_request_header) {
+		log_error_write(srv, __FILE__, __LINE__, "sdsdSb",
+				"fd:", con->fd,
+				"request-len:", con->request.request->used,
+				"\n", con->request.request);
+	}
+
+	if (con->request_count > 1 &&
+	    con->request.request->ptr[0] == '\r' &&
+	    con->request.request->ptr[1] == '\n') {
+		/* we are in keep-alive and might get \r\n after a previous POST request.*/
+
+		buffer_copy_string_len(con->parse_request, con->request.request->ptr + 2, con->request.request->used - 1 - 2);
+	} else {
+		/* fill the local request buffer */
+		buffer_copy_string_buffer(con->parse_request, con->request.request);
+	}
+
+	keep_alive_set = 0;
+	con_length_set = 0;
+
+	/* parse the first line of the request
+	 *
+	 * should be:
+	 *
+	 * <method> <uri> <protocol>\r\n
+	 * */
+	for (i = 0, first = 0; i < con->parse_request->used && line == 0; i++) {
+		char *cur = con->parse_request->ptr + i;
+
+		switch(*cur) {
+		case '\r':
+			if (con->parse_request->ptr[i+1] == '\n') {
+				http_method_t r;
+				char *nuri = NULL;
+				size_t j;
+
+				/* \r\n -> \0\0 */
+				con->parse_request->ptr[i] = '\0';
+				con->parse_request->ptr[i+1] = '\0';
+
+				buffer_copy_string_len(con->request.request_line, con->parse_request->ptr, i);
+
+				if (request_line_stage != 2) {
+					con->http_status = 400;
+					con->response.keep_alive = 0;
+					con->keep_alive = 0;
+
+					if (srv->srvconf.log_request_header_on_error) {
+						log_error_write(srv, __FILE__, __LINE__, "s", "incomplete request line -> 400");
+						log_error_write(srv, __FILE__, __LINE__, "Sb",
+								"request-header:\n",
+								con->request.request);
+					}
+					return 0;
+				}
+
+				proto = con->parse_request->ptr + first;
+
+				*(uri - 1) = '\0';
+				*(proto - 1) = '\0';
+
+				/* we got the first one :) */
+				if (-1 == (r = get_http_method_key(method))) {
+					con->http_status = 501;
+					con->response.keep_alive = 0;
+					con->keep_alive = 0;
+
+					if (srv->srvconf.log_request_header_on_error) {
+						log_error_write(srv, __FILE__, __LINE__, "s", "unknown http-method -> 501");
+						log_error_write(srv, __FILE__, __LINE__, "Sb",
+								"request-header:\n",
+								con->request.request);
+					}
+
+					return 0;
+				}
+
+				con->request.http_method = r;
+
+				/*
+				 * RFC2616 says:
+				 *
+				 * HTTP-Version   = "HTTP" "/" 1*DIGIT "." 1*DIGIT
+				 *
+				 * */
+				if (0 == strncmp(proto, "HTTP/", sizeof("HTTP/") - 1)) {
+					char * major = proto + sizeof("HTTP/") - 1;
+					char * minor = strchr(major, '.');
+					char *err = NULL;
+					int major_num = 0, minor_num = 0;
+
+					int invalid_version = 0;
+
+					if (NULL == minor || /* no dot */
+					    minor == major || /* no major */
+					    *(minor + 1) == '\0' /* no minor */) {
+						invalid_version = 1;
+					} else {
+						*minor = '\0';
+						major_num = strtol(major, &err, 10);
+
+						if (*err != '\0') invalid_version = 1;
+
+						*minor++ = '.';
+						minor_num = strtol(minor, &err, 10);
+
+						if (*err != '\0') invalid_version = 1;
+					}
+
+					if (invalid_version) {
+						con->http_status = 400;
+						con->keep_alive = 0;
+
+						if (srv->srvconf.log_request_header_on_error) {
+							log_error_write(srv, __FILE__, __LINE__, "s", "unknown protocol -> 400");
+							log_error_write(srv, __FILE__, __LINE__, "Sb",
+									"request-header:\n",
+									con->request.request);
+						}
+						return 0;
+					}
+
+					if (major_num == 1 && minor_num == 1) {
+						con->request.http_version = con->conf.allow_http11 ? HTTP_VERSION_1_1 : HTTP_VERSION_1_0;
+					} else if (major_num == 1 && minor_num == 0) {
+						con->request.http_version = HTTP_VERSION_1_0;
+					} else {
+						con->http_status = 505;
+
+						if (srv->srvconf.log_request_header_on_error) {
+							log_error_write(srv, __FILE__, __LINE__, "s", "unknown HTTP version -> 505");
+							log_error_write(srv, __FILE__, __LINE__, "Sb",
+									"request-header:\n",
+									con->request.request);
+						}
+						return 0;
+					}
+				} else {
+					con->http_status = 400;
+					con->keep_alive = 0;
+
+					if (srv->srvconf.log_request_header_on_error) {
+						log_error_write(srv, __FILE__, __LINE__, "s", "unknown protocol -> 400");
+						log_error_write(srv, __FILE__, __LINE__, "Sb",
+								"request-header:\n",
+								con->request.request);
+					}
+					return 0;
+				}
+
+				if (0 == strncmp(uri, "http://", 7) &&
+				    NULL != (nuri = strchr(uri + 7, '/'))) {
+					/* ignore the host-part */
+
+					buffer_copy_string_len(con->request.uri, nuri, proto - nuri - 1);
+				} else {
+					/* everything looks good so far */
+					buffer_copy_string_len(con->request.uri, uri, proto - uri - 1);
+				}
+
+				/* check uri for invalid characters */
+				for (j = 0; j < con->request.uri->used - 1; j++) {
+					if (!request_uri_is_valid_char(con->request.uri->ptr[j])) {
+						unsigned char buf[2];
+						con->http_status = 400;
+						con->keep_alive = 0;
+
+						if (srv->srvconf.log_request_header_on_error) {
+							buf[0] = con->request.uri->ptr[j];
+							buf[1] = '\0';
+
+							if (con->request.uri->ptr[j] > 32 &&
+							    con->request.uri->ptr[j] != 127) {
+								/* the character is printable -> print it */
+								log_error_write(srv, __FILE__, __LINE__, "ss",
+										"invalid character in URI -> 400",
+										buf);
+							} else {
+								/* a control-character, print ascii-code */
+								log_error_write(srv, __FILE__, __LINE__, "sd",
+										"invalid character in URI -> 400",
+										con->request.uri->ptr[j]);
+							}
+
+							log_error_write(srv, __FILE__, __LINE__, "Sb",
+									"request-header:\n",
+									con->request.request);
+						}
+
+						return 0;
+					}
+				}
+
+				buffer_copy_string_buffer(con->request.orig_uri, con->request.uri);
+
+				con->http_status = 0;
+
+				i++;
+				line++;
+				first = i+1;
+			}
+			break;
+		case ' ':
+			switch(request_line_stage) {
+			case 0:
+				/* GET|POST|... */
+				method = con->parse_request->ptr + first;
+				first = i + 1;
+				break;
+			case 1:
+				/* /foobar/... */
+				uri = con->parse_request->ptr + first;
+				first = i + 1;
+				break;
+			default:
+				/* ERROR, one space to much */
+				con->http_status = 400;
+				con->response.keep_alive = 0;
+				con->keep_alive = 0;
+
+				if (srv->srvconf.log_request_header_on_error) {
+					log_error_write(srv, __FILE__, __LINE__, "s", "overlong request line -> 400");
+					log_error_write(srv, __FILE__, __LINE__, "Sb",
+							"request-header:\n",
+							con->request.request);
+				}
+				return 0;
+			}
+
+			request_line_stage++;
+			break;
+		}
+	}
+
+	in_folding = 0;
+
+	if (con->request.uri->used == 1) {
+		con->http_status = 400;
+		con->response.keep_alive = 0;
+		con->keep_alive = 0;
+
+		log_error_write(srv, __FILE__, __LINE__, "s", "no uri specified -> 400");
+		if (srv->srvconf.log_request_header_on_error) {
+			log_error_write(srv, __FILE__, __LINE__, "Sb",
+							"request-header:\n",
+							con->request.request);
+		}
+		return 0;
+	}
+
+
+	for (; i < con->parse_request->used && !done; i++) {
+		char *cur = con->parse_request->ptr + i;
+
+		if (is_key) {
+			size_t j;
+			int got_colon = 0;
+
+			/**
+			 * 1*<any CHAR except CTLs or separators>
+			 * CTLs == 0-31 + 127
+			 *
+			 */
+			switch(*cur) {
+			case ':':
+				is_key = 0;
+
+				value = cur + 1;
+
+				if (is_ws_after_key == 0) {
+					key_len = i - first;
+				}
+				is_ws_after_key = 0;
+
+				break;
+			case '(':
+			case ')':
+			case '<':
+			case '>':
+			case '@':
+			case ',':
+			case ';':
+			case '\\':
+			case '\"':
+			case '/':
+			case '[':
+			case ']':
+			case '?':
+			case '=':
+			case '{':
+			case '}':
+				con->http_status = 400;
+				con->keep_alive = 0;
+				con->response.keep_alive = 0;
+
+				log_error_write(srv, __FILE__, __LINE__, "sbsds",
+						"invalid character in key", con->request.request, cur, *cur, "-> 400");
+				return 0;
+			case ' ':
+			case '\t':
+				if (i == first) {
+					is_key = 0;
+					in_folding = 1;
+					value = cur;
+
+					break;
+				}
+
+
+				key_len = i - first;
+
+				/* skip every thing up to the : */
+				for (j = 1; !got_colon; j++) {
+					switch(con->parse_request->ptr[j + i]) {
+					case ' ':
+					case '\t':
+						/* skip WS */
+						continue;
+					case ':':
+						/* ok, done */
+
+						i += j - 1;
+						got_colon = 1;
+
+						break;
+					default:
+						/* error */
+
+						if (srv->srvconf.log_request_header_on_error) {
+							log_error_write(srv, __FILE__, __LINE__, "s", "WS character in key -> 400");
+							log_error_write(srv, __FILE__, __LINE__, "Sb",
+								"request-header:\n",
+								con->request.request);
+						}
+
+						con->http_status = 400;
+						con->response.keep_alive = 0;
+						con->keep_alive = 0;
+
+						return 0;
+					}
+				}
+
+				break;
+			case '\r':
+				if (con->parse_request->ptr[i+1] == '\n' && i == first) {
+					/* End of Header */
+					con->parse_request->ptr[i] = '\0';
+					con->parse_request->ptr[i+1] = '\0';
+
+					i++;
+
+					done = 1;
+
+					break;
+				} else {
+					if (srv->srvconf.log_request_header_on_error) {
+						log_error_write(srv, __FILE__, __LINE__, "s", "CR without LF -> 400");
+						log_error_write(srv, __FILE__, __LINE__, "Sb",
+							"request-header:\n",
+							con->request.request);
+					}
+
+					con->http_status = 400;
+					con->keep_alive = 0;
+					con->response.keep_alive = 0;
+					return 0;
+				}
+				/* fall thru */
+			case 0: /* illegal characters (faster than a if () :) */
+			case 1:
+			case 2:
+			case 3:
+			case 4:
+			case 5:
+			case 6:
+			case 7:
+			case 8:
+			case 10:
+			case 11:
+			case 12:
+			case 14:
+			case 15:
+			case 16:
+			case 17:
+			case 18:
+			case 19:
+			case 20:
+			case 21:
+			case 22:
+			case 23:
+			case 24:
+			case 25:
+			case 26:
+			case 27:
+			case 28:
+			case 29:
+			case 30:
+			case 31:
+			case 127:
+				con->http_status = 400;
+				con->keep_alive = 0;
+				con->response.keep_alive = 0;
+
+				if (srv->srvconf.log_request_header_on_error) {
+					log_error_write(srv, __FILE__, __LINE__, "sbsds",
+						"CTL character in key", con->request.request, cur, *cur, "-> 400");
+
+					log_error_write(srv, __FILE__, __LINE__, "Sb",
+						"request-header:\n",
+						con->request.request);
+				}
+
+				return 0;
+			default:
+				/* ok */
+				break;
+			}
+		} else {
+			switch(*cur) {
+			case '\r':
+				if (con->parse_request->ptr[i+1] == '\n') {
+					data_string *ds = NULL;
+
+					/* End of Headerline */
+					con->parse_request->ptr[i] = '\0';
+					con->parse_request->ptr[i+1] = '\0';
+
+					if (in_folding) {
+						buffer *key_b;
+						/**
+						 * we use a evil hack to handle the line-folding
+						 * 
+						 * As array_insert_unique() deletes 'ds' in the case of a duplicate
+						 * ds points somewhere and we get a evil crash. As a solution we keep the old
+						 * "key" and get the current value from the hash and append us
+						 *
+						 * */
+
+						if (!key || !key_len) {
+							/* 400 */
+
+							if (srv->srvconf.log_request_header_on_error) {
+								log_error_write(srv, __FILE__, __LINE__, "s", "WS at the start of first line -> 400");
+
+								log_error_write(srv, __FILE__, __LINE__, "Sb",
+									"request-header:\n",
+									con->request.request);
+							}
+
+
+							con->http_status = 400;
+							con->keep_alive = 0;
+							con->response.keep_alive = 0;
+							return 0;
+						}
+
+						key_b = buffer_init();
+						buffer_copy_string_len(key_b, key, key_len);
+
+						if (NULL != (ds = (data_string *)array_get_element(con->request.headers, key_b->ptr))) {
+							buffer_append_string(ds->value, value);
+						}
+
+						buffer_free(key_b);
+					} else {
+						int s_len;
+						key = con->parse_request->ptr + first;
+
+						s_len = cur - value;
+
+						/* strip trailing white-spaces */
+						for (; s_len > 0 && 
+								(value[s_len - 1] == ' ' || 
+								 value[s_len - 1] == '\t'); s_len--);
+
+						value[s_len] = '\0';
+
+						if (s_len > 0) {
+							int cmp = 0;
+							if (NULL == (ds = (data_string *)array_get_unused_element(con->request.headers, TYPE_STRING))) {
+								ds = data_string_init();
+							}
+							buffer_copy_string_len(ds->key, key, key_len);
+							buffer_copy_string_len(ds->value, value, s_len);
+
+							/* retreive values
+							 *
+							 *
+							 * the list of options is sorted to simplify the search
+							 */
+
+							if (0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Connection")))) {
+								array *vals;
+								size_t vi;
+
+								/* split on , */
+
+								vals = srv->split_vals;
+
+								array_reset(vals);
+
+								http_request_split_value(vals, ds->value);
+
+								for (vi = 0; vi < vals->used; vi++) {
+									data_string *dsv = (data_string *)vals->data[vi];
+
+									if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("keep-alive"))) {
+										keep_alive_set = HTTP_CONNECTION_KEEPALIVE;
+
+										break;
+									} else if (0 == buffer_caseless_compare(CONST_BUF_LEN(dsv->value), CONST_STR_LEN("close"))) {
+										keep_alive_set = HTTP_CONNECTION_CLOSE;
+
+										break;
+									}
+								}
+
+							} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Content-Length")))) {
+								char *err;
+								unsigned long int r;
+								size_t j;
+
+								if (con_length_set) {
+									con->http_status = 400;
+									con->keep_alive = 0;
+
+									if (srv->srvconf.log_request_header_on_error) {
+										log_error_write(srv, __FILE__, __LINE__, "s",
+												"duplicate Content-Length-header -> 400");
+										log_error_write(srv, __FILE__, __LINE__, "Sb",
+												"request-header:\n",
+												con->request.request);
+									}
+									return 0;
+								}
+
+								if (ds->value->used == 0) SEGFAULT();
+
+								for (j = 0; j < ds->value->used - 1; j++) {
+									char c = ds->value->ptr[j];
+									if (!isdigit((unsigned char)c)) {
+										log_error_write(srv, __FILE__, __LINE__, "sbs",
+												"content-length broken:", ds->value, "-> 400");
+
+										con->http_status = 400;
+										con->keep_alive = 0;
+
+										array_insert_unique(con->request.headers, (data_unset *)ds);
+										return 0;
+									}
+								}
+
+								r = strtoul(ds->value->ptr, &err, 10);
+
+								if (*err == '\0') {
+									con_length_set = 1;
+									con->request.content_length = r;
+								} else {
+									log_error_write(srv, __FILE__, __LINE__, "sbs",
+											"content-length broken:", ds->value, "-> 400");
+
+									con->http_status = 400;
+									con->keep_alive = 0;
+
+									array_insert_unique(con->request.headers, (data_unset *)ds);
+									return 0;
+								}
+							} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Content-Type")))) {
+								/* if dup, only the first one will survive */
+								if (!con->request.http_content_type) {
+									con->request.http_content_type = ds->value->ptr;
+								} else {
+									con->http_status = 400;
+									con->keep_alive = 0;
+
+									if (srv->srvconf.log_request_header_on_error) {
+										log_error_write(srv, __FILE__, __LINE__, "s",
+												"duplicate Content-Type-header -> 400");
+										log_error_write(srv, __FILE__, __LINE__, "Sb",
+												"request-header:\n",
+												con->request.request);
+									}
+									return 0;
+								}
+							} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Expect")))) {
+								/* HTTP 2616 8.2.3
+								 * Expect: 100-continue
+								 *
+								 *   -> (10.1.1)  100 (read content, process request, send final status-code)
+								 *   -> (10.4.18) 417 (close)
+								 *
+								 * (not handled at all yet, we always send 417 here)
+								 *
+								 * What has to be added ?
+								 * 1. handling of chunked request body
+								 * 2. out-of-order sending from the HTTP/1.1 100 Continue
+								 *    header
+								 *
+								 */
+
+								con->http_status = 417;
+								con->keep_alive = 0;
+
+								array_insert_unique(con->request.headers, (data_unset *)ds);
+								return 0;
+							} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Host")))) {
+								if (!con->request.http_host) {
+									con->request.http_host = ds->value;
+								} else {
+									con->http_status = 400;
+									con->keep_alive = 0;
+
+									if (srv->srvconf.log_request_header_on_error) {
+										log_error_write(srv, __FILE__, __LINE__, "s",
+												"duplicate Host-header -> 400");
+										log_error_write(srv, __FILE__, __LINE__, "Sb",
+												"request-header:\n",
+												con->request.request);
+									}
+									return 0;
+								}
+							} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-Modified-Since")))) {
+								/* Proxies sometimes send dup headers
+								 * if they are the same we ignore the second
+								 * if not, we raise an error */
+								if (!con->request.http_if_modified_since) {
+									con->request.http_if_modified_since = ds->value->ptr;
+								} else if (0 == strcasecmp(con->request.http_if_modified_since,
+											ds->value->ptr)) {
+									/* ignore it if they are the same */
+
+									ds->free((data_unset *)ds);
+									ds = NULL;
+								} else {
+									con->http_status = 400;
+									con->keep_alive = 0;
+
+									if (srv->srvconf.log_request_header_on_error) {
+										log_error_write(srv, __FILE__, __LINE__, "s",
+												"duplicate If-Modified-Since header -> 400");
+										log_error_write(srv, __FILE__, __LINE__, "Sb",
+												"request-header:\n",
+												con->request.request);
+									}
+									return 0;
+								}
+							} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("If-None-Match")))) {
+								/* if dup, only the first one will survive */
+								if (!con->request.http_if_none_match) {
+									con->request.http_if_none_match = ds->value->ptr;
+								} else {
+									con->http_status = 400;
+									con->keep_alive = 0;
+
+									if (srv->srvconf.log_request_header_on_error) {
+										log_error_write(srv, __FILE__, __LINE__, "s",
+												"duplicate If-None-Match-header -> 400");
+										log_error_write(srv, __FILE__, __LINE__, "Sb",
+												"request-header:\n",
+												con->request.request);
+									}
+									return 0;
+								}
+							} else if (cmp > 0 && 0 == (cmp = buffer_caseless_compare(CONST_BUF_LEN(ds->key), CONST_STR_LEN("Range")))) {
+								if (!con->request.http_range) {
+									/* bytes=.*-.* */
+
+									if (0 == strncasecmp(ds->value->ptr, "bytes=", 6) &&
+									    NULL != strchr(ds->value->ptr+6, '-')) {
+
+										/* if dup, only the first one will survive */
+										con->request.http_range = ds->value->ptr + 6;
+									}
+								} else {
+									con->http_status = 400;
+									con->keep_alive = 0;
+
+									if (srv->srvconf.log_request_header_on_error) {
+										log_error_write(srv, __FILE__, __LINE__, "s",
+												"duplicate Range-header -> 400");
+										log_error_write(srv, __FILE__, __LINE__, "Sb",
+												"request-header:\n",
+												con->request.request);
+									}
+									return 0;
+								}
+							}
+
+							if (ds) array_insert_unique(con->request.headers, (data_unset *)ds);
+						} else {
+							/* empty header-fields are not allowed by HTTP-RFC, we just ignore them */
+						}
+					}
+
+					i++;
+					first = i+1;
+					is_key = 1;
+					value = 0;
+#if 0
+					/**
+					 * for Bug 1230 keep the key_len a live
+					 */
+					key_len = 0; 
+#endif
+					in_folding = 0;
+				} else {
+					if (srv->srvconf.log_request_header_on_error) {
+						log_error_write(srv, __FILE__, __LINE__, "sbs",
+								"CR without LF", con->request.request, "-> 400");
+					}
+
+					con->http_status = 400;
+					con->keep_alive = 0;
+					con->response.keep_alive = 0;
+					return 0;
+				}
+				break;
+			case ' ':
+			case '\t':
+				/* strip leading WS */
+				if (value == cur) value = cur+1;
+			default:
+				if (*cur >= 0 && *cur < 32) {
+					if (srv->srvconf.log_request_header_on_error) {
+						log_error_write(srv, __FILE__, __LINE__, "sds",
+								"invalid char in header", (int)*cur, "-> 400");
+					}
+
+					con->http_status = 400;
+					con->keep_alive = 0;
+
+					return 0;
+				}
+				break;
+			}
+		}
+	}
+
+	con->header_len = i;
+
+	/* do some post-processing */
+
+	if (con->request.http_version == HTTP_VERSION_1_1) {
+		if (keep_alive_set != HTTP_CONNECTION_CLOSE) {
+			/* no Connection-Header sent */
+
+			/* HTTP/1.1 -> keep-alive default TRUE */
+			con->keep_alive = 1;
+		} else {
+			con->keep_alive = 0;
+		}
+
+		/* RFC 2616, 14.23 */
+		if (con->request.http_host == NULL ||
+		    buffer_is_empty(con->request.http_host)) {
+			con->http_status = 400;
+			con->response.keep_alive = 0;
+			con->keep_alive = 0;
+
+			if (srv->srvconf.log_request_header_on_error) {
+				log_error_write(srv, __FILE__, __LINE__, "s", "HTTP/1.1 but Host missing -> 400");
+				log_error_write(srv, __FILE__, __LINE__, "Sb",
+						"request-header:\n",
+						con->request.request);
+			}
+			return 0;
+		}
+	} else {
+		if (keep_alive_set == HTTP_CONNECTION_KEEPALIVE) {
+			/* no Connection-Header sent */
+
+			/* HTTP/1.0 -> keep-alive default FALSE  */
+			con->keep_alive = 1;
+		} else {
+			con->keep_alive = 0;
+		}
+	}
+
+	/* check hostname field if it is set */
+	if (NULL != con->request.http_host &&
+	    0 != request_check_hostname(srv, con, con->request.http_host)) {
+
+		if (srv->srvconf.log_request_header_on_error) {
+			log_error_write(srv, __FILE__, __LINE__, "s",
+					"Invalid Hostname -> 400");
+			log_error_write(srv, __FILE__, __LINE__, "Sb",
+					"request-header:\n",
+					con->request.request);
+		}
+
+		con->http_status = 400;
+		con->response.keep_alive = 0;
+		con->keep_alive = 0;
+
+		return 0;
+	}
+
+	switch(con->request.http_method) {
+	case HTTP_METHOD_GET:
+	case HTTP_METHOD_HEAD:
+		/* content-length is forbidden for those */
+		if (con_length_set && con->request.content_length != 0) {
+			/* content-length is missing */
+			log_error_write(srv, __FILE__, __LINE__, "s",
+					"GET/HEAD with content-length -> 400");
+
+			con->keep_alive = 0;
+			con->http_status = 400;
+			return 0;
+		}
+		break;
+	case HTTP_METHOD_POST:
+		/* content-length is required for them */
+		if (!con_length_set) {
+			/* content-length is missing */
+			log_error_write(srv, __FILE__, __LINE__, "s",
+					"POST-request, but content-length missing -> 411");
+
+			con->keep_alive = 0;
+			con->http_status = 411;
+			return 0;
+
+		}
+		break;
+	default:
+		/* the may have a content-length */
+		break;
+	}
+
+
+	/* check if we have read post data */
+	if (con_length_set) {
+		/* don't handle more the SSIZE_MAX bytes in content-length */
+		if (con->request.content_length > SSIZE_MAX) {
+			con->http_status = 413;
+			con->keep_alive = 0;
+
+			log_error_write(srv, __FILE__, __LINE__, "sds",
+					"request-size too long:", con->request.content_length, "-> 413");
+			return 0;
+		}
+
+		/* divide by 1024 as srvconf.max_request_size is in kBytes */
+		if (srv->srvconf.max_request_size != 0 &&
+		    (con->request.content_length >> 10) > srv->srvconf.max_request_size) {
+			/* the request body itself is larger then
+			 * our our max_request_size
+			 */
+
+			con->http_status = 413;
+			con->keep_alive = 0;
+
+			log_error_write(srv, __FILE__, __LINE__, "sds",
+					"request-size too long:", con->request.content_length, "-> 413");
+			return 0;
+		}
+
+
+		/* we have content */
+		if (con->request.content_length != 0) {
+			return 1;
+		}
+	}
+
+	return 0;
+}
+
+int http_request_header_finished(server *srv, connection *con) {
+	UNUSED(srv);
+
+	if (con->request.request->used < 5) return 0;
+
+	if (0 == memcmp(con->request.request->ptr + con->request.request->used - 5, "\r\n\r\n", 4)) return 1;
+	if (NULL != strstr(con->request.request->ptr, "\r\n\r\n")) return 1;
+
+	return 0;
+}

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/request.h
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/request.h?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/request.h (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/request.h Mon Jul 21 21:35:35 2008
@@ -0,0 +1,9 @@
+#ifndef _REQUEST_H_
+#define _REQUEST_H_
+
+#include "server.h"
+
+int http_request_parse(server *srv, connection *con);
+int http_request_header_finished(server *srv, connection *con);
+
+#endif

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/response.c
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/response.c?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/response.c (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/response.c Mon Jul 21 21:35:35 2008
@@ -0,0 +1,682 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <limits.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include <stdio.h>
+
+#include "response.h"
+#include "keyvalue.h"
+#include "log.h"
+#include "stat_cache.h"
+#include "chunk.h"
+
+#include "configfile.h"
+#include "connections.h"
+
+#include "plugin.h"
+
+#include "sys-socket.h"
+
+int http_response_write_header(server *srv, connection *con) {
+	buffer *b;
+	size_t i;
+	int have_date = 0;
+	int have_server = 0;
+
+	b = chunkqueue_get_prepend_buffer(con->write_queue);
+
+	if (con->request.http_version == HTTP_VERSION_1_1) {
+		BUFFER_COPY_STRING_CONST(b, "HTTP/1.1 ");
+	} else {
+		BUFFER_COPY_STRING_CONST(b, "HTTP/1.0 ");
+	}
+	buffer_append_long(b, con->http_status);
+	BUFFER_APPEND_STRING_CONST(b, " ");
+	buffer_append_string(b, get_http_status_name(con->http_status));
+
+	if (con->request.http_version != HTTP_VERSION_1_1 || con->keep_alive == 0) {
+		BUFFER_APPEND_STRING_CONST(b, "\r\nConnection: ");
+		buffer_append_string(b, con->keep_alive ? "keep-alive" : "close");
+	}
+
+	if (con->response.transfer_encoding & HTTP_TRANSFER_ENCODING_CHUNKED) {
+		BUFFER_APPEND_STRING_CONST(b, "\r\nTransfer-Encoding: chunked");
+	}
+
+
+	/* add all headers */
+	for (i = 0; i < con->response.headers->used; i++) {
+		data_string *ds;
+
+		ds = (data_string *)con->response.headers->data[i];
+
+		if (ds->value->used && ds->key->used &&
+		    0 != strncmp(ds->key->ptr, "X-LIGHTTPD-", sizeof("X-LIGHTTPD-") - 1) &&
+			0 != strncmp(ds->key->ptr, "X-Sendfile", sizeof("X-Sendfile") - 1)) {
+			if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Date"))) have_date = 1;
+			if (buffer_is_equal_string(ds->key, CONST_STR_LEN("Server"))) have_server = 1;
+
+			BUFFER_APPEND_STRING_CONST(b, "\r\n");
+			buffer_append_string_buffer(b, ds->key);
+			BUFFER_APPEND_STRING_CONST(b, ": ");
+#if 0
+			/** 
+			 * the value might contain newlines, encode them with at least one white-space
+			 */
+			buffer_append_string_encoded(b, CONST_BUF_LEN(ds->value), ENCODING_HTTP_HEADER);
+#else
+			buffer_append_string_buffer(b, ds->value);
+#endif
+		}
+	}
+
+	if (!have_date) {
+		/* HTTP/1.1 requires a Date: header */
+		BUFFER_APPEND_STRING_CONST(b, "\r\nDate: ");
+
+		/* cache the generated timestamp */
+		if (srv->cur_ts != srv->last_generated_date_ts) {
+			buffer_prepare_copy(srv->ts_date_str, 255);
+
+			strftime(srv->ts_date_str->ptr, srv->ts_date_str->size - 1,
+				 "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(srv->cur_ts)));
+
+			srv->ts_date_str->used = strlen(srv->ts_date_str->ptr) + 1;
+
+			srv->last_generated_date_ts = srv->cur_ts;
+		}
+
+		buffer_append_string_buffer(b, srv->ts_date_str);
+	}
+
+	if (!have_server) {
+		if (buffer_is_empty(con->conf.server_tag)) {
+			BUFFER_APPEND_STRING_CONST(b, "\r\nServer: " PACKAGE_NAME "/" PACKAGE_VERSION);
+		} else {
+			BUFFER_APPEND_STRING_CONST(b, "\r\nServer: ");
+			buffer_append_string_encoded(b, CONST_BUF_LEN(con->conf.server_tag), ENCODING_HTTP_HEADER);
+		}
+	}
+
+	BUFFER_APPEND_STRING_CONST(b, "\r\n\r\n");
+
+
+	con->bytes_header = b->used - 1;
+
+	if (con->conf.log_response_header) {
+		log_error_write(srv, __FILE__, __LINE__, "sSb", "Response-Header:", "\n", b);
+	}
+
+	return 0;
+}
+
+
+
+handler_t http_response_prepare(server *srv, connection *con) {
+	handler_t r;
+
+	/* looks like someone has already done a decision */
+	if (con->mode == DIRECT &&
+	    (con->http_status != 0 && con->http_status != 200)) {
+		/* remove a packets in the queue */
+		if (con->file_finished == 0) {
+			chunkqueue_reset(con->write_queue);
+		}
+
+		return HANDLER_FINISHED;
+	}
+
+	/* no decision yet, build conf->filename */
+	if (con->mode == DIRECT && con->physical.path->used == 0) {
+		char *qstr;
+
+		/* we only come here when we have the parse the full request again
+		 *
+		 * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a
+		 * problem here as mod_setenv might get called multiple times
+		 *
+		 * fastcgi-auth might lead to a COMEBACK too
+		 * fastcgi again dead server too
+		 *
+		 * mod_compress might add headers twice too
+		 *
+		 *  */
+
+		config_cond_cache_reset(srv, con);
+		config_setup_connection(srv, con); // Perhaps this could be removed at other places.
+
+		if (con->conf.log_condition_handling) {
+			log_error_write(srv, __FILE__, __LINE__,  "s",  "run condition");
+		}
+		config_patch_connection(srv, con, COMP_SERVER_SOCKET); /* SERVERsocket */
+
+		/**
+		 * prepare strings
+		 *
+		 * - uri.path_raw
+		 * - uri.path (secure)
+		 * - uri.query
+		 *
+		 */
+
+		/**
+		 * Name according to RFC 2396
+		 *
+		 * - scheme
+		 * - authority
+		 * - path
+		 * - query
+		 *
+		 * (scheme)://(authority)(path)?(query)#fragment
+		 *
+		 *
+		 */
+
+		buffer_copy_string(con->uri.scheme, con->conf.is_ssl ? "https" : "http");
+		buffer_copy_string_buffer(con->uri.authority, con->request.http_host);
+		buffer_to_lower(con->uri.authority);
+
+		config_patch_connection(srv, con, COMP_HTTP_SCHEME);    /* Scheme:      */
+		config_patch_connection(srv, con, COMP_HTTP_HOST);      /* Host:        */
+		config_patch_connection(srv, con, COMP_HTTP_REMOTE_IP); /* Client-IP */
+		config_patch_connection(srv, con, COMP_HTTP_REFERER);   /* Referer:     */
+		config_patch_connection(srv, con, COMP_HTTP_USER_AGENT);/* User-Agent:  */
+		config_patch_connection(srv, con, COMP_HTTP_COOKIE);    /* Cookie:  */
+		config_patch_connection(srv, con, COMP_HTTP_REQUEST_METHOD); /* REQUEST_METHOD */
+
+		/** their might be a fragment which has to be cut away */
+		if (NULL != (qstr = strchr(con->request.uri->ptr, '#'))) {
+			con->request.uri->used = qstr - con->request.uri->ptr;
+			con->request.uri->ptr[con->request.uri->used++] = '\0';
+		}
+
+		/** extract query string from request.uri */
+		if (NULL != (qstr = strchr(con->request.uri->ptr, '?'))) {
+			buffer_copy_string    (con->uri.query, qstr + 1);
+			buffer_copy_string_len(con->uri.path_raw, con->request.uri->ptr, qstr - con->request.uri->ptr);
+		} else {
+			buffer_reset     (con->uri.query);
+			buffer_copy_string_buffer(con->uri.path_raw, con->request.uri);
+		}
+
+		if (con->conf.log_request_handling) {
+			log_error_write(srv, __FILE__, __LINE__,  "s",  "-- splitting Request-URI");
+			log_error_write(srv, __FILE__, __LINE__,  "sb", "Request-URI  : ", con->request.uri);
+			log_error_write(srv, __FILE__, __LINE__,  "sb", "URI-scheme   : ", con->uri.scheme);
+			log_error_write(srv, __FILE__, __LINE__,  "sb", "URI-authority: ", con->uri.authority);
+			log_error_write(srv, __FILE__, __LINE__,  "sb", "URI-path     : ", con->uri.path_raw);
+			log_error_write(srv, __FILE__, __LINE__,  "sb", "URI-query    : ", con->uri.query);
+		}
+
+		/* disable keep-alive if requested */
+
+		if (con->request_count > con->conf.max_keep_alive_requests) {
+			con->keep_alive = 0;
+		}
+
+
+		/**
+		 *
+		 * call plugins
+		 *
+		 * - based on the raw URL
+		 *
+		 */
+
+		switch(r = plugins_call_handle_uri_raw(srv, con)) {
+		case HANDLER_GO_ON:
+			break;
+		case HANDLER_FINISHED:
+		case HANDLER_COMEBACK:
+		case HANDLER_WAIT_FOR_EVENT:
+		case HANDLER_ERROR:
+			return r;
+		default:
+			log_error_write(srv, __FILE__, __LINE__, "sd", "handle_uri_raw: unknown return value", r);
+			break;
+		}
+
+		/* build filename
+		 *
+		 * - decode url-encodings  (e.g. %20 -> ' ')
+		 * - remove path-modifiers (e.g. /../)
+		 */
+
+
+
+		if (con->request.http_method == HTTP_METHOD_OPTIONS &&
+		    con->uri.path_raw->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
+			/* OPTIONS * ... */
+			buffer_copy_string_buffer(con->uri.path, con->uri.path_raw);
+		} else {
+			buffer_copy_string_buffer(srv->tmp_buf, con->uri.path_raw);
+			buffer_urldecode_path(srv->tmp_buf);
+			buffer_path_simplify(con->uri.path, srv->tmp_buf);
+		}
+
+		if (con->conf.log_request_handling) {
+			log_error_write(srv, __FILE__, __LINE__,  "s",  "-- sanatising URI");
+			log_error_write(srv, __FILE__, __LINE__,  "sb", "URI-path     : ", con->uri.path);
+		}
+
+		/**
+		 *
+		 * call plugins
+		 *
+		 * - based on the clean URL
+		 *
+		 */
+
+		config_patch_connection(srv, con, COMP_HTTP_URL); /* HTTPurl */
+		config_patch_connection(srv, con, COMP_HTTP_QUERY_STRING); /* HTTPqs */
+
+		/* do we have to downgrade to 1.0 ? */
+		if (!con->conf.allow_http11) {
+			con->request.http_version = HTTP_VERSION_1_0;
+		}
+
+		switch(r = plugins_call_handle_uri_clean(srv, con)) {
+		case HANDLER_GO_ON:
+			break;
+		case HANDLER_FINISHED:
+		case HANDLER_COMEBACK:
+		case HANDLER_WAIT_FOR_EVENT:
+		case HANDLER_ERROR:
+			return r;
+		default:
+			log_error_write(srv, __FILE__, __LINE__, "");
+			break;
+		}
+
+		if (con->request.http_method == HTTP_METHOD_OPTIONS &&
+		    con->uri.path->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
+			/* option requests are handled directly without checking of the path */
+
+			response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
+
+			con->http_status = 200;
+			con->file_finished = 1;
+
+			return HANDLER_FINISHED;
+		}
+
+		/***
+		 *
+		 * border
+		 *
+		 * logical filename (URI) becomes a physical filename here
+		 *
+		 *
+		 *
+		 */
+
+
+
+
+		/* 1. stat()
+		 * ... ISREG() -> ok, go on
+		 * ... ISDIR() -> index-file -> redirect
+		 *
+		 * 2. pathinfo()
+		 * ... ISREG()
+		 *
+		 * 3. -> 404
+		 *
+		 */
+
+		/*
+		 * SEARCH DOCUMENT ROOT
+		 */
+
+		/* set a default */
+
+		buffer_copy_string_buffer(con->physical.doc_root, con->conf.document_root);
+		buffer_copy_string_buffer(con->physical.rel_path, con->uri.path);
+
+#if defined(__WIN32) || defined(__CYGWIN__)
+		/* strip dots from the end and spaces
+		 *
+		 * windows/dos handle those filenames as the same file
+		 *
+		 * foo == foo. == foo..... == "foo...   " == "foo..  ./"
+		 *
+		 * This will affect in some cases PATHINFO
+		 *
+		 * on native windows we could prepend the filename with \\?\ to circumvent
+		 * this behaviour. I have no idea how to push this through cygwin
+		 *
+		 * */
+
+		if (con->physical.rel_path->used > 1) {
+			buffer *b = con->physical.rel_path;
+			size_t i;
+
+			if (b->used > 2 &&
+			    b->ptr[b->used-2] == '/' &&
+			    (b->ptr[b->used-3] == ' ' ||
+			     b->ptr[b->used-3] == '.')) {
+				b->ptr[b->used--] = '\0';
+			}
+
+			for (i = b->used - 2; b->used > 1; i--) {
+				if (b->ptr[i] == ' ' ||
+				    b->ptr[i] == '.') {
+					b->ptr[b->used--] = '\0';
+				} else {
+					break;
+				}
+			}
+		}
+#endif
+
+		if (con->conf.log_request_handling) {
+			log_error_write(srv, __FILE__, __LINE__,  "s",  "-- before doc_root");
+			log_error_write(srv, __FILE__, __LINE__,  "sb", "Doc-Root     :", con->physical.doc_root);
+			log_error_write(srv, __FILE__, __LINE__,  "sb", "Rel-Path     :", con->physical.rel_path);
+			log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
+		}
+		/* the docroot plugin should set the doc_root and might also set the physical.path
+		 * for us (all vhost-plugins are supposed to set the doc_root)
+		 * */
+		switch(r = plugins_call_handle_docroot(srv, con)) {
+		case HANDLER_GO_ON:
+			break;
+		case HANDLER_FINISHED:
+		case HANDLER_COMEBACK:
+		case HANDLER_WAIT_FOR_EVENT:
+		case HANDLER_ERROR:
+			return r;
+		default:
+			log_error_write(srv, __FILE__, __LINE__, "");
+			break;
+		}
+
+		/* MacOS X and Windows can't distiguish between upper and lower-case
+		 *
+		 * convert to lower-case
+		 */
+		if (con->conf.force_lowercase_filenames) {
+			buffer_to_lower(con->physical.rel_path);
+		}
+
+		/* the docroot plugins might set the servername, if they don't we take http-host */
+		if (buffer_is_empty(con->server_name)) {
+			buffer_copy_string_buffer(con->server_name, con->uri.authority);
+		}
+
+		/**
+		 * create physical filename
+		 * -> physical.path = docroot + rel_path
+		 *
+		 */
+
+		buffer_copy_string_buffer(con->physical.path, con->physical.doc_root);
+		BUFFER_APPEND_SLASH(con->physical.path);
+		buffer_copy_string_buffer(con->physical.basedir, con->physical.path);
+		if (con->physical.rel_path->used &&
+		    con->physical.rel_path->ptr[0] == '/') {
+			buffer_append_string_len(con->physical.path, con->physical.rel_path->ptr + 1, con->physical.rel_path->used - 2);
+		} else {
+			buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
+		}
+
+		if (con->conf.log_request_handling) {
+			log_error_write(srv, __FILE__, __LINE__,  "s",  "-- after doc_root");
+			log_error_write(srv, __FILE__, __LINE__,  "sb", "Doc-Root     :", con->physical.doc_root);
+			log_error_write(srv, __FILE__, __LINE__,  "sb", "Rel-Path     :", con->physical.rel_path);
+			log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
+		}
+
+		switch(r = plugins_call_handle_physical(srv, con)) {
+		case HANDLER_GO_ON:
+			break;
+		case HANDLER_FINISHED:
+		case HANDLER_COMEBACK:
+		case HANDLER_WAIT_FOR_EVENT:
+		case HANDLER_ERROR:
+			return r;
+		default:
+			log_error_write(srv, __FILE__, __LINE__, "");
+			break;
+		}
+
+		if (con->conf.log_request_handling) {
+			log_error_write(srv, __FILE__, __LINE__,  "s",  "-- logical -> physical");
+			log_error_write(srv, __FILE__, __LINE__,  "sb", "Doc-Root     :", con->physical.doc_root);
+			log_error_write(srv, __FILE__, __LINE__,  "sb", "Rel-Path     :", con->physical.rel_path);
+			log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
+		}
+	}
+
+	/*
+	 * Noone catched away the file from normal path of execution yet (like mod_access)
+	 *
+	 * Go on and check of the file exists at all
+	 */
+
+	if (con->mode == DIRECT) {
+		char *slash = NULL;
+		char *pathinfo = NULL;
+		int found = 0;
+		stat_cache_entry *sce = NULL;
+
+		if (con->conf.log_request_handling) {
+			log_error_write(srv, __FILE__, __LINE__,  "s",  "-- handling physical path");
+			log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
+		}
+
+		if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
+			/* file exists */
+
+			if (con->conf.log_request_handling) {
+				log_error_write(srv, __FILE__, __LINE__,  "s",  "-- file found");
+				log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
+			}
+#ifdef HAVE_LSTAT
+			if ((sce->is_symlink != 0) && !con->conf.follow_symlink) {
+				con->http_status = 403;
+
+				if (con->conf.log_request_handling) {
+					log_error_write(srv, __FILE__, __LINE__,  "s",  "-- access denied due symlink restriction");
+					log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
+				}
+
+				buffer_reset(con->physical.path);
+				return HANDLER_FINISHED;
+			};
+#endif
+			if (S_ISDIR(sce->st.st_mode)) {
+				if (con->physical.path->ptr[con->physical.path->used - 2] != '/') {
+					/* redirect to .../ */
+
+					http_response_redirect_to_directory(srv, con);
+
+					return HANDLER_FINISHED;
+				}
+#ifdef HAVE_LSTAT
+			} else if (!S_ISREG(sce->st.st_mode) && !sce->is_symlink) {
+#else
+			} else if (!S_ISREG(sce->st.st_mode)) {
+#endif
+				/* any special handling of non-reg files ?*/
+
+
+			}
+		} else {
+			switch (errno) {
+			case EACCES:
+				con->http_status = 403;
+
+				if (con->conf.log_request_handling) {
+					log_error_write(srv, __FILE__, __LINE__,  "s",  "-- access denied");
+					log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
+				}
+
+				buffer_reset(con->physical.path);
+				return HANDLER_FINISHED;
+			case ENOENT:
+				con->http_status = 404;
+
+				if (con->conf.log_request_handling) {
+					log_error_write(srv, __FILE__, __LINE__,  "s",  "-- file not found");
+					log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
+				}
+
+				buffer_reset(con->physical.path);
+				return HANDLER_FINISHED;
+			case ENOTDIR:
+				/* PATH_INFO ! :) */
+				break;
+			default:
+				/* we have no idea what happend. let's tell the user so. */
+				con->http_status = 500;
+				buffer_reset(con->physical.path);
+
+				log_error_write(srv, __FILE__, __LINE__, "ssbsb",
+						"file not found ... or so: ", strerror(errno),
+						con->uri.path,
+						"->", con->physical.path);
+
+				return HANDLER_FINISHED;
+			}
+
+			/* not found, perhaps PATHINFO */
+
+			buffer_copy_string_buffer(srv->tmp_buf, con->physical.path);
+
+			do {
+				if (slash) {
+					buffer_copy_string_len(con->physical.path, srv->tmp_buf->ptr, slash - srv->tmp_buf->ptr);
+				} else {
+					buffer_copy_string_buffer(con->physical.path, srv->tmp_buf);
+				}
+
+				if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
+					found = S_ISREG(sce->st.st_mode);
+					break;
+				}
+
+				if (pathinfo != NULL) {
+					*pathinfo = '\0';
+				}
+				slash = strrchr(srv->tmp_buf->ptr, '/');
+
+				if (pathinfo != NULL) {
+					/* restore '/' */
+					*pathinfo = '/';
+				}
+
+				if (slash) pathinfo = slash;
+			} while ((found == 0) && (slash != NULL) && ((size_t)(slash - srv->tmp_buf->ptr) > (con->physical.basedir->used - 2)));
+
+			if (found == 0) {
+				/* no it really doesn't exists */
+				con->http_status = 404;
+
+				if (con->conf.log_file_not_found) {
+					log_error_write(srv, __FILE__, __LINE__, "sbsb",
+							"file not found:", con->uri.path,
+							"->", con->physical.path);
+				}
+
+				buffer_reset(con->physical.path);
+
+				return HANDLER_FINISHED;
+			}
+
+#ifdef HAVE_LSTAT
+			if ((sce->is_symlink != 0) && !con->conf.follow_symlink) {
+				con->http_status = 403;
+
+				if (con->conf.log_request_handling) {
+					log_error_write(srv, __FILE__, __LINE__,  "s",  "-- access denied due symlink restriction");
+					log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
+				}
+
+				buffer_reset(con->physical.path);
+				return HANDLER_FINISHED;
+			};
+#endif
+
+			/* we have a PATHINFO */
+			if (pathinfo) {
+				buffer_copy_string(con->request.pathinfo, pathinfo);
+
+				/*
+				 * shorten uri.path
+				 */
+
+				con->uri.path->used -= strlen(pathinfo);
+				con->uri.path->ptr[con->uri.path->used - 1] = '\0';
+			}
+
+			if (con->conf.log_request_handling) {
+				log_error_write(srv, __FILE__, __LINE__,  "s",  "-- after pathinfo check");
+				log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
+				log_error_write(srv, __FILE__, __LINE__,  "sb", "URI          :", con->uri.path);
+				log_error_write(srv, __FILE__, __LINE__,  "sb", "Pathinfo     :", con->request.pathinfo);
+			}
+		}
+
+		if (con->conf.log_request_handling) {
+			log_error_write(srv, __FILE__, __LINE__,  "s",  "-- handling subrequest");
+			log_error_write(srv, __FILE__, __LINE__,  "sb", "Path         :", con->physical.path);
+		}
+
+		/* call the handlers */
+		switch(r = plugins_call_handle_subrequest_start(srv, con)) {
+		case HANDLER_GO_ON:
+			/* request was not handled */
+			break;
+		case HANDLER_FINISHED:
+		default:
+			if (con->conf.log_request_handling) {
+				log_error_write(srv, __FILE__, __LINE__,  "s",  "-- subrequest finished");
+			}
+
+			/* something strange happend */
+			return r;
+		}
+
+		/* if we are still here, no one wanted the file, status 403 is ok I think */
+
+		if (con->mode == DIRECT && con->http_status == 0) {
+			switch (con->request.http_method) {
+			case HTTP_METHOD_OPTIONS:
+				con->http_status = 200;
+				break;
+			default:
+				con->http_status = 403;
+			}
+
+			return HANDLER_FINISHED;
+		}
+
+	}
+
+	switch(r = plugins_call_handle_subrequest(srv, con)) {
+	case HANDLER_GO_ON:
+		/* request was not handled, looks like we are done */
+		return HANDLER_FINISHED;
+	case HANDLER_FINISHED:
+		/* request is finished */
+	default:
+		/* something strange happend */
+		return r;
+	}
+
+	/* can't happen */
+	return HANDLER_COMEBACK;
+}
+
+
+

Added: webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/response.h
URL: http://svn.apache.org/viewvc/webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/response.h?rev=678637&view=auto
==============================================================================
--- webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/response.h (added)
+++ webservices/axis2/branches/c/lighttpd_mod_axis2/lighttpd/src/response.h Mon Jul 21 21:35:35 2008
@@ -0,0 +1,19 @@
+#ifndef _RESPONSE_H_
+#define _RESPONSE_H_
+
+#include <time.h>
+
+#include "server.h"
+
+int http_response_parse(server *srv, connection *con);
+int http_response_write_header(server *srv, connection *con);
+
+int response_header_insert(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen);
+int response_header_overwrite(server *srv, connection *con, const char *key, size_t keylen, const char *value, size_t vallen);
+
+handler_t http_response_prepare(server *srv, connection *con);
+int http_response_redirect_to_directory(server *srv, connection *con);
+int http_response_handle_cachable(server *srv, connection *con, buffer * mtime);
+
+buffer * strftime_cache_get(server *srv, time_t last_mod);
+#endif