diff --git a/src/mod_cgi.c b/src/mod_cgi.c index 3c6b449a..9e834456 100644 --- a/src/mod_cgi.c +++ b/src/mod_cgi.c @@ -1339,6 +1339,11 @@ SUBREQUEST_FUNC(mod_cgi_handle_subrequest) { if (con->mode != p->id) return HANDLER_GO_ON; if (NULL == hctx) return HANDLER_GO_ON; + if (con->state == CON_STATE_READ_POST) { + handler_t r = connection_handle_read_post_state(srv, con); + if (r != HANDLER_GO_ON) return r; + } + if (-1 == hctx->fd) { buffer *handler = cgi_get_handler(p->conf.cgi, con->physical.path); if (!handler) return HANDLER_GO_ON; /*(should not happen; checked in cgi_is_handled())*/ diff --git a/src/mod_fastcgi.c b/src/mod_fastcgi.c index a87152e9..7a62c21f 100644 --- a/src/mod_fastcgi.c +++ b/src/mod_fastcgi.c @@ -3096,6 +3096,11 @@ SUBREQUEST_FUNC(mod_fastcgi_handle_subrequest) { /* not my job */ if (con->mode != p->id) return HANDLER_GO_ON; + if (con->state == CON_STATE_READ_POST) { + handler_t r = connection_handle_read_post_state(srv, con); + if (r != HANDLER_GO_ON) return r; + } + return (hctx->state != FCGI_STATE_READ) ? fcgi_send_request(srv, hctx) : HANDLER_WAIT_FOR_EVENT; diff --git a/src/mod_proxy.c b/src/mod_proxy.c index 0bc98eed..17435e0a 100644 --- a/src/mod_proxy.c +++ b/src/mod_proxy.c @@ -908,6 +908,11 @@ SUBREQUEST_FUNC(mod_proxy_handle_subrequest) { /* not my job */ if (con->mode != p->id) return HANDLER_GO_ON; + if (con->state == CON_STATE_READ_POST) { + handler_t r = connection_handle_read_post_state(srv, con); + if (r != HANDLER_GO_ON) return r; + } + return (hctx->state != PROXY_STATE_READ) ? proxy_send_request(srv, hctx) : HANDLER_WAIT_FOR_EVENT; diff --git a/src/mod_scgi.c b/src/mod_scgi.c index 9c81de2d..500b8ddb 100644 --- a/src/mod_scgi.c +++ b/src/mod_scgi.c @@ -2453,6 +2453,11 @@ SUBREQUEST_FUNC(mod_scgi_handle_subrequest) { /* not my job */ if (con->mode != p->id) return HANDLER_GO_ON; + if (con->state == CON_STATE_READ_POST) { + handler_t r = connection_handle_read_post_state(srv, con); + if (r != HANDLER_GO_ON) return r; + } + return (hctx->state != FCGI_STATE_READ) ? scgi_send_request(srv, hctx) : HANDLER_WAIT_FOR_EVENT; diff --git a/src/mod_webdav.c b/src/mod_webdav.c index 5e5dcaaf..af4f0b62 100644 --- a/src/mod_webdav.c +++ b/src/mod_webdav.c @@ -4,6 +4,7 @@ #include "log.h" #include "buffer.h" #include "response.h" +#include "connections.h" #include "plugin.h" @@ -1199,7 +1200,8 @@ static int webdav_has_lock(server *srv, connection *con, plugin_data *p, buffer return has_lock; } -URIHANDLER_FUNC(mod_webdav_subrequest_handler) { + +SUBREQUEST_FUNC(mod_webdav_subrequest_handler_huge) { plugin_data *p = p_d; buffer *b; DIR *dir; @@ -1250,6 +1252,11 @@ URIHANDLER_FUNC(mod_webdav_subrequest_handler) { if (con->request.content_length) { xmlDocPtr xml; + if (con->state == CON_STATE_READ_POST) { + handler_t r = connection_handle_read_post_state(srv, con); + if (r != HANDLER_GO_ON) return r; + } + if (1 == webdav_parse_chunkqueue(srv, con, p, con->request_content_queue, &xml)) { xmlNode *rootnode = xmlDocGetRootElement(xml); @@ -1616,13 +1623,16 @@ URIHANDLER_FUNC(mod_webdav_subrequest_handler) { } /* is a exclusive lock set on the source */ - if (!webdav_has_lock(srv, con, p, con->uri.path)) { + /* (check for lock once before potentially reading large input) */ + if (0 == cq->bytes_in && !webdav_has_lock(srv, con, p, con->uri.path)) { con->http_status = 423; return HANDLER_FINISHED; } - - assert(chunkqueue_length(cq) == (off_t)con->request.content_length); + if (con->state == CON_STATE_READ_POST) { + handler_t r = connection_handle_read_post_state(srv, con); + if (r != HANDLER_GO_ON) return r; + } /* RFC2616 Section 9.6 PUT requires us to send 501 on all Content-* we don't support * - most important Content-Range @@ -2054,6 +2064,11 @@ URIHANDLER_FUNC(mod_webdav_subrequest_handler) { if (con->request.content_length) { xmlDocPtr xml; + if (con->state == CON_STATE_READ_POST) { + handler_t r = connection_handle_read_post_state(srv, con); + if (r != HANDLER_GO_ON) return r; + } + if (1 == webdav_parse_chunkqueue(srv, con, p, con->request_content_queue, &xml)) { xmlNode *rootnode = xmlDocGetRootElement(xml); @@ -2210,6 +2225,11 @@ propmatch_cleanup: xmlDocPtr xml; buffer *hdr_if = NULL; + if (con->state == CON_STATE_READ_POST) { + handler_t r = connection_handle_read_post_state(srv, con); + if (r != HANDLER_GO_ON) return r; + } + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "If"))) { hdr_if = ds->value; } @@ -2482,6 +2502,46 @@ propmatch_cleanup: } +SUBREQUEST_FUNC(mod_webdav_subrequest_handler) { + handler_t r; + plugin_data *p = p_d; + if (con->mode != p->id) return HANDLER_GO_ON; + + r = mod_webdav_subrequest_handler_huge(srv, con, p_d); + if (con->http_status >= 400) con->mode = DIRECT; + return r; +} + + +PHYSICALPATH_FUNC(mod_webdav_physical_handler) { + plugin_data *p = p_d; + if (!p->conf.enabled) return HANDLER_GO_ON; + + /* physical path is setup */ + if (buffer_is_empty(con->physical.path)) return HANDLER_GO_ON; + + UNUSED(srv); + + switch (con->request.http_method) { + case HTTP_METHOD_PROPFIND: + case HTTP_METHOD_PROPPATCH: + case HTTP_METHOD_PUT: + case HTTP_METHOD_COPY: + case HTTP_METHOD_MOVE: + case HTTP_METHOD_MKCOL: + case HTTP_METHOD_DELETE: + case HTTP_METHOD_LOCK: + case HTTP_METHOD_UNLOCK: + con->mode = p->id; + break; + default: + break; + } + + return HANDLER_GO_ON; +} + + /* this function is called at dlopen() time and inits the callbacks */ int mod_webdav_plugin_init(plugin *p); @@ -2491,7 +2551,8 @@ int mod_webdav_plugin_init(plugin *p) { p->init = mod_webdav_init; p->handle_uri_clean = mod_webdav_uri_handler; - p->handle_physical = mod_webdav_subrequest_handler; + p->handle_physical = mod_webdav_physical_handler; + p->handle_subrequest = mod_webdav_subrequest_handler; p->set_defaults = mod_webdav_set_defaults; p->cleanup = mod_webdav_free; diff --git a/src/response.c b/src/response.c index bf7b676c..51cc4e38 100644 --- a/src/response.c +++ b/src/response.c @@ -7,7 +7,6 @@ #include "chunk.h" #include "configfile.h" -#include "connections.h" #include "plugin.h" @@ -750,11 +749,6 @@ handler_t http_response_prepare(server *srv, connection *con) { } - if (con->state == CON_STATE_READ_POST) { - r = connection_handle_read_post_state(srv, con); - if (r != HANDLER_GO_ON) return r; - } - switch(r = plugins_call_handle_subrequest(srv, con)) { case HANDLER_GO_ON: /* request was not handled, looks like we are done */