From: Ruediger Pluem Date: Sat, 5 Jan 2008 09:45:07 +0000 (+0000) Subject: Merge r607466, r607472, r607838 from trunk: X-Git-Tag: 2.2.8~20 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7b70806f5d1163141c2091deb20625618947ac53;p=thirdparty%2Fapache%2Fhttpd.git Merge r607466, r607472, r607838 from trunk: mod_dav: Fix evaluation of If-Match * and If-None-Match * conditionals. PR 38034 Patch by Paritosh Shah Explanation by Werner Baumann * Style police. No functional changes. * Avoid SEGFAULT as hooks->set_headers can be NULL. Furthermore do not set the ETag header permanently as setting it may not be desired for all responses. Submitted by: niq, rpluem Reviewed by: niq, rpluem, chrisd git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.2.x@609113 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 650b9691aa2..83ef49017db 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,8 @@ -*- coding: utf-8 -*- Changes with Apache 2.2.8 + *) mod_dav: Fix evaluation of If-Match * and If-None-Match * conditionals. + PR 38034 [Paritosh Shah ] Changes with Apache 2.2.7 diff --git a/STATUS b/STATUS index 8be9ae8ff8f..0294c4586ce 100644 --- a/STATUS +++ b/STATUS @@ -80,14 +80,6 @@ RELEASE SHOWSTOPPERS: PATCHES ACCEPTED TO BACKPORT FROM TRUNK: [ start all new proposals below, under PATCHES PROPOSED. ] - * mod_dav: Fix evaluation of If-Match * and If-None-Match * conditionals. - PR 38034 - http://svn.apache.org/viewvc?view=rev&revision=607466 - http://svn.apache.org/viewvc?view=rev&revision=607472 - http://svn.apache.org/viewvc?view=rev&revision=607838 - +1: niq, rpluem, chrisd - - PATCHES PROPOSED TO BACKPORT FROM TRUNK: [ New proposals should be added at the end of the list ] diff --git a/modules/dav/main/util.c b/modules/dav/main/util.c index 153f25d45ac..5297b908489 100644 --- a/modules/dav/main/util.c +++ b/modules/dav/main/util.c @@ -1404,6 +1404,39 @@ static dav_error * dav_validate_walker(dav_walk_resource *wres, int calltype) return NULL; } +/* If-* header checking */ +static int dav_meets_conditions(request_rec *r, int resource_state) +{ + const char *if_match, *if_none_match; + int retVal; + + /* If-Match '*' fix. Resource existence not checked by ap_meets_conditions. + * If-Match '*' request should succeed only if the resource exists. */ + if ((if_match = apr_table_get(r->headers_in, "If-Match")) != NULL) { + if (if_match[0] == '*' && resource_state != DAV_RESOURCE_EXISTS) + return HTTP_PRECONDITION_FAILED; + } + + retVal = ap_meets_conditions(r); + + /* If-None-Match '*' fix. If-None-Match '*' request should succeed + * if the resource does not exist. */ + if (retVal == HTTP_PRECONDITION_FAILED) { + /* Note. If if_none_match != NULL, if_none_match is the culprit. + * Since, in presence of If-None-Match, + * other If-* headers are undefined. */ + if ((if_none_match = + apr_table_get(r->headers_in, "If-None-Match")) != NULL) { + if (if_none_match[0] == '*' + && resource_state != DAV_RESOURCE_EXISTS) { + return OK; + } + } + } + + return retVal; +} + /* ** dav_validate_request: Validate if-headers (and check for locks) on: ** (1) r->filename @ depth; @@ -1433,6 +1466,9 @@ DAV_DECLARE(dav_error *) dav_validate_request(request_rec *r, const dav_hooks_repository *repos_hooks = resource->hooks; dav_buffer work_buf = { 0 }; dav_response *new_response; + int resource_state; + const char *etag; + int set_etag = 0; #if DAV_DEBUG if (depth && response == NULL) { @@ -1449,10 +1485,29 @@ DAV_DECLARE(dav_error *) dav_validate_request(request_rec *r, if (response != NULL) *response = NULL; + /* Set the ETag header required by dav_meets_conditions() */ + etag = apr_table_get(r->headers_out, "ETag"); + if (!etag) { + etag = (*resource->hooks->getetag)(resource); + if (etag && *etag) { + apr_table_set(r->headers_out, "ETag", etag); + set_etag = 1; + } + } /* Do the standard checks for conditional requests using * If-..-Since, If-Match etc */ - if ((result = ap_meets_conditions(r)) != OK) { - /* ### fix this up... how? */ + resource_state = dav_get_resource_state(r, resource); + result = dav_meets_conditions(r, resource_state); + if (set_etag) { + /* + * If we have set an ETag to headers out above for + * dav_meets_conditions() revert this here as we do not want to set + * the ETag in responses to requests with methods where this might not + * be desired. + */ + apr_table_unset(r->headers_out, "ETag"); + } + if (result != OK) { return dav_new_error(r->pool, result, 0, NULL); }