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