You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by mi...@apache.org on 2021/07/05 10:23:29 UTC
svn commit: r1891280 - in /httpd/httpd/patches/2.4.x:
httpd-2.4-dav-functions5.patch httpd-2.4-dav-hooks1.patch
httpd-2.4-dav-preconditions1.patch
Author: minfrin
Date: Mon Jul 5 10:23:29 2021
New Revision: 1891280
URL: http://svn.apache.org/viewvc?rev=1891280&view=rev
Log:
Add patches.
Added:
httpd/httpd/patches/2.4.x/httpd-2.4-dav-functions5.patch
httpd/httpd/patches/2.4.x/httpd-2.4-dav-hooks1.patch
httpd/httpd/patches/2.4.x/httpd-2.4-dav-preconditions1.patch
Added: httpd/httpd/patches/2.4.x/httpd-2.4-dav-functions5.patch
URL: http://svn.apache.org/viewvc/httpd/httpd/patches/2.4.x/httpd-2.4-dav-functions5.patch?rev=1891280&view=auto
==============================================================================
--- httpd/httpd/patches/2.4.x/httpd-2.4-dav-functions5.patch (added)
+++ httpd/httpd/patches/2.4.x/httpd-2.4-dav-functions5.patch Mon Jul 5 10:23:29 2021
@@ -0,0 +1,125 @@
+Index: CHANGES
+===================================================================
+--- CHANGES (revision 1891278)
++++ CHANGES (working copy)
+@@ -1,6 +1,9 @@
+ -*- coding: utf-8 -*-
+ Changes with Apache 2.4.49
+
++ *) Add dav_get_provider(), dav_open_lockdb(), dav_close_lockdb() and
++ dav_get_resource() to mod_dav.h. [Graham Leggett]
++
+ *) Add CPING to health check logic. [Jean-Frederic Clere]
+
+ *) core: Split ap_create_request() from ap_read_request(). [Graham Leggett]
+Index: include/ap_mmn.h
+===================================================================
+--- include/ap_mmn.h (revision 1891278)
++++ include/ap_mmn.h (working copy)
+@@ -563,6 +563,9 @@
+ * 20120211.107 (2.4.49-dev) Add ap_parse_request_line() and
+ * ap_check_request_header()
+ * 20120211.108 (2.4.49-dev) Add ajp_handle_cping_cpong
++ * 20120211.109 (2.4.49-dev) Add dav_get_provider(), dav_open_lockdb(),
++ * dav_close_lockdb() and dav_get_resource() to
++ * mod_dav.h.
+ */
+
+ #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
+@@ -570,7 +573,7 @@
+ #ifndef MODULE_MAGIC_NUMBER_MAJOR
+ #define MODULE_MAGIC_NUMBER_MAJOR 20120211
+ #endif
+-#define MODULE_MAGIC_NUMBER_MINOR 108 /* 0...n */
++#define MODULE_MAGIC_NUMBER_MINOR 109 /* 0...n */
+
+ /**
+ * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
+Index: modules/dav/main/mod_dav.c
+===================================================================
+--- modules/dav/main/mod_dav.c (revision 1891278)
++++ modules/dav/main/mod_dav.c (working copy)
+@@ -207,7 +207,7 @@
+ return conf ? conf->provider_name : NULL;
+ }
+
+-static const dav_provider *dav_get_provider(request_rec *r)
++DAV_DECLARE(const dav_provider *) dav_get_provider(request_rec *r)
+ {
+ dav_dir_conf *conf;
+
+@@ -726,7 +726,7 @@
+ * the resource identified by the DAV:checked-in property of the resource
+ * identified by the Request-URI.
+ */
+-static dav_error *dav_get_resource(request_rec *r, int label_allowed,
++DAV_DECLARE(dav_error *) dav_get_resource(request_rec *r, int label_allowed,
+ int use_checked_in, dav_resource **res_p)
+ {
+ dav_dir_conf *conf;
+@@ -775,7 +775,9 @@
+ return NULL;
+ }
+
+-static dav_error * dav_open_lockdb(request_rec *r, int ro, dav_lockdb **lockdb)
++DAV_DECLARE(dav_error *) dav_open_lockdb(request_rec *r,
++ int ro,
++ dav_lockdb **lockdb)
+ {
+ const dav_hooks_locks *hooks = DAV_GET_HOOKS_LOCKS(r);
+
+@@ -788,6 +790,11 @@
+ return (*hooks->open_lockdb)(r, ro, 0, lockdb);
+ }
+
++DAV_DECLARE(void) dav_close_lockdb(dav_lockdb *lockdb)
++{
++ (lockdb->hooks->close_lockdb)(lockdb);
++}
++
+ /**
+ * @return 1 if valid content-range,
+ * 0 if no content-range,
+Index: modules/dav/main/mod_dav.h
+===================================================================
+--- modules/dav/main/mod_dav.h (revision 1891278)
++++ modules/dav/main/mod_dav.h (working copy)
+@@ -50,7 +50,7 @@
+
+ #define DAV_READ_BLOCKSIZE 2048 /* used for reading input blocks */
+
+-#define DAV_RESPONSE_BODY_1 "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n<title>"
++#define DAV_RESPONSE_BODY_1 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n<html>\n<head>\n<title>"
+ #define DAV_RESPONSE_BODY_2 "</title>\n</head><body>\n<h1>"
+ #define DAV_RESPONSE_BODY_3 "</h1>\n<p>"
+ #define DAV_RESPONSE_BODY_4 "</p>\n"
+@@ -427,7 +427,10 @@
+ */
+ typedef struct dav_locktoken dav_locktoken;
+
++DAV_DECLARE(dav_error *) dav_get_resource(request_rec *r, int label_allowed,
++ int use_checked_in, dav_resource **res_p);
+
++
+ /* --------------------------------------------------------------------
+ **
+ ** BUFFER HANDLING
+@@ -721,6 +724,7 @@
+ const dav_provider *hooks);
+ DAV_DECLARE(const dav_provider *) dav_lookup_provider(const char *name);
+ DAV_DECLARE(const char *) dav_get_provider_name(request_rec *r);
++DAV_DECLARE(const dav_provider *) dav_get_provider(request_rec *r);
+
+
+ /* ### deprecated */
+@@ -1314,6 +1318,10 @@
+ dav_buffer *pbuf);
+
+ /* LockDB-related public lock functions */
++DAV_DECLARE(dav_error *) dav_open_lockdb(request_rec *r,
++ int ro,
++ dav_lockdb **lockdb);
++DAV_DECLARE(void) dav_close_lockdb(dav_lockdb *lockdb);
+ DAV_DECLARE(dav_error *) dav_lock_parse_lockinfo(request_rec *r,
+ const dav_resource *resrouce,
+ dav_lockdb *lockdb,
Added: httpd/httpd/patches/2.4.x/httpd-2.4-dav-hooks1.patch
URL: http://svn.apache.org/viewvc/httpd/httpd/patches/2.4.x/httpd-2.4-dav-hooks1.patch?rev=1891280&view=auto
==============================================================================
--- httpd/httpd/patches/2.4.x/httpd-2.4-dav-hooks1.patch (added)
+++ httpd/httpd/patches/2.4.x/httpd-2.4-dav-hooks1.patch Mon Jul 5 10:23:29 2021
@@ -0,0 +1,438 @@
+--- httpd-2.4.x-4/CHANGES 2021-07-05 11:07:07.000000000 +0200
++++ httpd-2.4.x-5/CHANGES 2021-07-05 11:27:31.000000000 +0200
+@@ -1,6 +1,10 @@
+ -*- coding: utf-8 -*-
+ Changes with Apache 2.4.49
+
++ *) Add hooks deliver_report and gather_reports to mod_dav.h. Allows other
++ modules apart from versioning implementations to handle the REPORT method.
++ [Graham Leggett]
++
+ *) Add dav_get_provider(), dav_open_lockdb(), dav_close_lockdb() and
+ dav_get_resource() to mod_dav.h. [Graham Leggett]
+
+--- httpd-2.4.x-4/include/ap_mmn.h 2021-07-05 11:42:51.000000000 +0200
++++ httpd-2.4.x-5/include/ap_mmn.h 2021-07-05 11:42:29.000000000 +0200
+@@ -566,6 +566,7 @@
+ * 20120211.109 (2.4.49-dev) Add dav_get_provider(), dav_open_lockdb(),
+ * dav_close_lockdb() and dav_get_resource() to
+ * mod_dav.h.
++ * 20120211.110 (2.4.49-dev) Add deliver_report and gather_reports hooks.
+ */
+
+ #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
+@@ -573,7 +574,7 @@
+ #ifndef MODULE_MAGIC_NUMBER_MAJOR
+ #define MODULE_MAGIC_NUMBER_MAJOR 20120211
+ #endif
+-#define MODULE_MAGIC_NUMBER_MINOR 109 /* 0...n */
++#define MODULE_MAGIC_NUMBER_MINOR 110 /* 0...n */
+
+ /**
+ * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
+--- httpd-2.4.x-4/modules/dav/main/mod_dav.h 2021-06-22 13:06:14.000000000 +0200
++++ httpd-2.4.x-5/modules/dav/main/mod_dav.h 2021-07-05 11:37:06.000000000 +0200
+@@ -647,10 +647,10 @@
+ ** mod_dav 1.0). There are too many dependencies between a dav_resource
+ ** (defined by <repos>) and the other functionality.
+ **
+-** Live properties are not part of the dav_provider structure because they
+-** are handled through the APR_HOOK interface (to allow for multiple liveprop
+-** providers). The core always provides some properties, and then a given
+-** provider will add more properties.
++** Live properties and report extensions are not part of the dav_provider
++** structure because they are handled through the APR_HOOK interface (to
++** allow for multiple providers). The core always provides some
++** properties, and then a given provider will add more properties.
+ **
+ ** Some providers may need to associate a context with the dav_provider
+ ** structure -- the ctx field is available for storing this context. Just
+@@ -714,6 +714,34 @@
+ (request_rec *r, const dav_resource *resource,
+ dav_prop_insert what, apr_text_header *phdr))
+
++/*
++** deliver_report: given a parsed report request, process the request
++** an deliver the resulting report.
++**
++** The hook implementer should decide whether it should handle the given
++** report, and if so, write the response to the output filter. If the
++** report is not relevant, return DECLINED.
++*/
++APR_DECLARE_EXTERNAL_HOOK(dav, DAV, int, deliver_report,
++ (request_rec *r,
++ const dav_resource *resource,
++ const apr_xml_doc *doc,
++ ap_filter_t *output, dav_error **err))
++
++/*
++** gather_reports: get all reports.
++**
++** The hook implementor should push one or more dav_report_elem structures
++** containing report names into the specified array. These names are returned
++** in the DAV:supported-reports-set property to let clients know
++** what reports are supported by the installation.
++**
++*/
++APR_DECLARE_EXTERNAL_HOOK(dav, DAV, void, gather_reports,
++ (request_rec *r, const dav_resource *resource,
++ apr_array_header_t *reports, dav_error **err))
++
++
+ DAV_DECLARE(const dav_hooks_locks *) dav_get_lock_hooks(request_rec *r);
+ DAV_DECLARE(const dav_hooks_propdb *) dav_get_propdb_hooks(request_rec *r);
+ DAV_DECLARE(const dav_hooks_vsn *) dav_get_vsn_hooks(request_rec *r);
+--- httpd-2.4.x-4/modules/dav/main/mod_dav.c 2021-06-22 13:06:14.000000000 +0200
++++ httpd-2.4.x-5/modules/dav/main/mod_dav.c 2021-07-05 11:37:13.000000000 +0200
+@@ -1456,92 +1456,95 @@
+ return err;
+ }
+
++
+ /* generate DAV:supported-report-set OPTIONS response */
+ static dav_error *dav_gen_supported_reports(request_rec *r,
+ const dav_resource *resource,
+ const apr_xml_elem *elem,
+- const dav_hooks_vsn *vsn_hooks,
+ apr_text_header *body)
+ {
+ apr_xml_elem *child;
+ apr_xml_attr *attr;
+- dav_error *err;
++ dav_error *err = NULL;
+ char *s;
++ apr_array_header_t *reports;
++ const dav_report_elem *rp;
+
+ apr_text_append(r->pool, body, "<D:supported-report-set>" DEBUG_CR);
+
+- if (vsn_hooks != NULL) {
+- const dav_report_elem *reports;
+- const dav_report_elem *rp;
++ reports = apr_array_make(r->pool, 5, sizeof(const char *));
++ dav_run_gather_reports(r, resource, reports, &err);
++ if (err != NULL) {
++ return dav_push_error(r->pool, err->status, 0,
++ "DAV:supported-report-set could not be "
++ "determined due to a problem fetching the "
++ "available reports for this resource.",
++ err);
++ }
++
++ if (elem->first_child == NULL) {
++ int i;
++
++ /* show all supported reports */
++ rp = (const dav_report_elem *)reports->elts;
++ for (i = 0; i < reports->nelts; i++, rp++) {
++ /* Note: we presume reports->namespace is
++ * properly XML/URL quoted */
++ s = apr_pstrcat(r->pool,
++ "<D:supported-report D:name=\"",
++ rp->name,
++ "\" D:namespace=\"",
++ rp->nmspace,
++ "\"/>" DEBUG_CR, NULL);
++ apr_text_append(r->pool, body, s);
++ }
++ }
++ else {
++ /* check for support of specific report */
++ for (child = elem->first_child; child != NULL; child = child->next) {
++ if (child->ns == APR_XML_NS_DAV_ID
++ && strcmp(child->name, "supported-report") == 0) {
++ const char *name = NULL;
++ const char *nmspace = NULL;
++ int i;
++
++ /* go through attributes to find name and namespace */
++ for (attr = child->attr; attr != NULL; attr = attr->next) {
++ if (attr->ns == APR_XML_NS_DAV_ID) {
++ if (strcmp(attr->name, "name") == 0)
++ name = attr->value;
++ else if (strcmp(attr->name, "namespace") == 0)
++ nmspace = attr->value;
++ }
++ }
+
+- if ((err = (*vsn_hooks->avail_reports)(resource, &reports)) != NULL) {
+- return dav_push_error(r->pool, err->status, 0,
+- "DAV:supported-report-set could not be "
+- "determined due to a problem fetching the "
+- "available reports for this resource.",
+- err);
+- }
+-
+- if (reports != NULL) {
+- if (elem->first_child == NULL) {
+- /* show all supported reports */
+- for (rp = reports; rp->nmspace != NULL; ++rp) {
+- /* Note: we presume reports->namespace is
+- * properly XML/URL quoted */
+- s = apr_pstrcat(r->pool,
+- "<D:supported-report D:name=\"",
+- rp->name,
+- "\" D:namespace=\"",
+- rp->nmspace,
+- "\"/>" DEBUG_CR, NULL);
+- apr_text_append(r->pool, body, s);
++ if (name == NULL) {
++ return dav_new_error(r->pool, HTTP_BAD_REQUEST, 0, 0,
++ "A DAV:supported-report element "
++ "does not have a \"name\" attribute");
+ }
+- }
+- else {
+- /* check for support of specific report */
+- for (child = elem->first_child; child != NULL; child = child->next) {
+- if (child->ns == APR_XML_NS_DAV_ID
+- && strcmp(child->name, "supported-report") == 0) {
+- const char *name = NULL;
+- const char *nmspace = NULL;
+-
+- /* go through attributes to find name and namespace */
+- for (attr = child->attr; attr != NULL; attr = attr->next) {
+- if (attr->ns == APR_XML_NS_DAV_ID) {
+- if (strcmp(attr->name, "name") == 0)
+- name = attr->value;
+- else if (strcmp(attr->name, "namespace") == 0)
+- nmspace = attr->value;
+- }
+- }
+-
+- if (name == NULL) {
+- return dav_new_error(r->pool, HTTP_BAD_REQUEST, 0, 0,
+- "A DAV:supported-report element "
+- "does not have a \"name\" attribute");
+- }
+-
+- /* default namespace to DAV: */
+- if (nmspace == NULL)
+- nmspace = "DAV:";
+-
+- for (rp = reports; rp->nmspace != NULL; ++rp) {
+- if (strcmp(name, rp->name) == 0
+- && strcmp(nmspace, rp->nmspace) == 0) {
+- /* Note: we presume reports->nmspace is
+- * properly XML/URL quoted
+- */
+- s = apr_pstrcat(r->pool,
+- "<D:supported-report "
+- "D:name=\"",
+- rp->name,
+- "\" D:namespace=\"",
+- rp->nmspace,
+- "\"/>" DEBUG_CR, NULL);
+- apr_text_append(r->pool, body, s);
+- break;
+- }
+- }
++
++ /* default namespace to DAV: */
++ if (nmspace == NULL) {
++ nmspace = "DAV:";
++ }
++
++ rp = (const dav_report_elem *)reports->elts;
++ for (i = 0; i < reports->nelts; i++, rp++) {
++ if (strcmp(name, rp->name) == 0
++ && strcmp(nmspace, rp->nmspace) == 0) {
++ /* Note: we presume reports->nmspace is
++ * properly XML/URL quoted
++ */
++ s = apr_pstrcat(r->pool,
++ "<D:supported-report "
++ "D:name=\"",
++ rp->name,
++ "\" D:namespace=\"",
++ rp->nmspace,
++ "\"/>" DEBUG_CR, NULL);
++ apr_text_append(r->pool, body, s);
++ break;
+ }
+ }
+ }
+@@ -1911,7 +1914,7 @@
+ core_option = 1;
+ }
+ else if (strcmp(elem->name, "supported-report-set") == 0) {
+- err = dav_gen_supported_reports(r, resource, elem, vsn_hooks, &body);
++ err = dav_gen_supported_reports(r, resource, elem, &body);
+ core_option = 1;
+ }
+ }
+@@ -4112,21 +4115,60 @@
+ return DONE;
+ }
+
++static int dav_core_deliver_report(request_rec *r,
++ const dav_resource *resource,
++ const apr_xml_doc *doc,
++ ap_filter_t *output, dav_error **err)
++{
++ const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
++
++ if (vsn_hooks) {
++ *err = (*vsn_hooks->deliver_report)(r, resource, doc,
++ r->output_filters);
++ return OK;
++ }
++
++ return DECLINED;
++}
++
++static void dav_core_gather_reports(
++ request_rec *r,
++ const dav_resource *resource,
++ apr_array_header_t *reports,
++ dav_error **err)
++{
++ const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
++
++ if (vsn_hooks) {
++ const dav_report_elem *rp;
++
++ (*err) = (*vsn_hooks->avail_reports)(resource, &rp);
++ while (rp && rp->name) {
++
++ dav_report_elem *report = apr_array_push(reports);
++
++ report->nmspace = rp->nmspace;
++ report->name = rp->name;
++
++ rp++;
++ }
++ }
++
++}
++
+ static int dav_method_report(request_rec *r)
+ {
+ dav_resource *resource;
+ const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
+- int result;
+- int label_allowed;
+ apr_xml_doc *doc;
+- dav_error *err;
++ dav_error *err = NULL;
+
+- /* If no versioning provider, decline the request */
+- if (vsn_hooks == NULL)
+- return DECLINED;
++ int result;
++ int label_allowed;
+
+- if ((result = ap_xml_parse_input(r, &doc)) != OK)
++ if ((result = ap_xml_parse_input(r, &doc)) != OK) {
+ return result;
++ }
+ if (doc == NULL) {
+ /* This supplies additional information for the default msg. */
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00614)
+@@ -4138,11 +4180,12 @@
+ * First determine whether a Target-Selector header is allowed
+ * for this report.
+ */
+- label_allowed = (*vsn_hooks->report_label_header_allowed)(doc);
++ label_allowed = vsn_hooks ? (*vsn_hooks->report_label_header_allowed)(doc) : 0;
+ err = dav_get_resource(r, label_allowed, 0 /* use_checked_in */,
+ &resource);
+- if (err != NULL)
++ if (err != NULL) {
+ return dav_handle_err(r, err, NULL);
++ }
+
+ if (!resource->exists) {
+ /* Apache will supply a default error for this. */
+@@ -4154,24 +4197,36 @@
+ ap_set_content_type(r, DAV_XML_CONTENT_TYPE);
+
+ /* run report hook */
+- if ((err = (*vsn_hooks->deliver_report)(r, resource, doc,
+- r->output_filters)) != NULL) {
+- if (! r->sent_bodyct)
+- /* No data has been sent to client yet; throw normal error. */
+- return dav_handle_err(r, err, NULL);
+-
+- /* If an error occurred during the report delivery, there's
+- basically nothing we can do but abort the connection and
+- log an error. This is one of the limitations of HTTP; it
+- needs to "know" the entire status of the response before
+- generating it, which is just impossible in these streamy
+- response situations. */
+- err = dav_push_error(r->pool, err->status, 0,
+- "Provider encountered an error while streaming"
+- " a REPORT response.", err);
+- dav_log_err(r, err, APLOG_ERR);
+- r->connection->aborted = 1;
++ result = dav_run_deliver_report(r, resource, doc,
++ r->output_filters, &err);
++ switch (result) {
++ case OK:
+ return DONE;
++ case DECLINED:
++ /* No one handled the report */
++ return HTTP_NOT_IMPLEMENTED;
++ default:
++ if ((err) != NULL) {
++
++ if (! r->sent_bodyct) {
++ /* No data has been sent to client yet; throw normal error. */
++ return dav_handle_err(r, err, NULL);
++ }
++
++ /* If an error occurred during the report delivery, there's
++ basically nothing we can do but abort the connection and
++ log an error. This is one of the limitations of HTTP; it
++ needs to "know" the entire status of the response before
++ generating it, which is just impossible in these streamy
++ response situations. */
++ err = dav_push_error(r->pool, err->status, 0,
++ "Provider encountered an error while streaming"
++ " a REPORT response.", err);
++ dav_log_err(r, err, APLOG_ERR);
++ r->connection->aborted = 1;
++
++ return DONE;
++ }
+ }
+
+ return DONE;
+@@ -4889,6 +4944,11 @@
+ dav_hook_insert_all_liveprops(dav_core_insert_all_liveprops,
+ NULL, NULL, APR_HOOK_MIDDLE);
+
++ dav_hook_deliver_report(dav_core_deliver_report,
++ NULL, NULL, APR_HOOK_LAST);
++ dav_hook_gather_reports(dav_core_gather_reports,
++ NULL, NULL, APR_HOOK_LAST);
++
+ dav_core_register_uris(p);
+ }
+
+@@ -4931,6 +4991,8 @@
+ APR_HOOK_LINK(gather_propsets)
+ APR_HOOK_LINK(find_liveprop)
+ APR_HOOK_LINK(insert_all_liveprops)
++ APR_HOOK_LINK(deliver_report)
++ APR_HOOK_LINK(gather_reports)
+ )
+
+ APR_IMPLEMENT_EXTERNAL_HOOK_VOID(dav, DAV, gather_propsets,
+@@ -4947,3 +5009,16 @@
+ (request_rec *r, const dav_resource *resource,
+ dav_prop_insert what, apr_text_header *phdr),
+ (r, resource, what, phdr))
++
++APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(dav, DAV, int, deliver_report,
++ (request_rec *r,
++ const dav_resource *resource,
++ const apr_xml_doc *doc,
++ ap_filter_t *output, dav_error **err),
++ (r, resource, doc, output, err), DECLINED)
++
++APR_IMPLEMENT_EXTERNAL_HOOK_VOID(dav, DAV, gather_reports,
++ (request_rec *r, const dav_resource *resource,
++ apr_array_header_t *reports, dav_error **err),
++ (r, resource, reports, err))
++
Added: httpd/httpd/patches/2.4.x/httpd-2.4-dav-preconditions1.patch
URL: http://svn.apache.org/viewvc/httpd/httpd/patches/2.4.x/httpd-2.4-dav-preconditions1.patch?rev=1891280&view=auto
==============================================================================
--- httpd/httpd/patches/2.4.x/httpd-2.4-dav-preconditions1.patch (added)
+++ httpd/httpd/patches/2.4.x/httpd-2.4-dav-preconditions1.patch Mon Jul 5 10:23:29 2021
@@ -0,0 +1,543 @@
+--- httpd-2.4.x-5/CHANGES 2021-07-05 11:27:31.000000000 +0200
++++ httpd-2.4.x-6/CHANGES 2021-07-05 12:05:39.000000000 +0200
+@@ -1,6 +1,11 @@
+ -*- coding: utf-8 -*-
+ Changes with Apache 2.4.49
+
++ *) mod_dav: Add method_precondition hook. WebDAV extensions define
++ conditions that must exist before a WebDAV method can be executed.
++ This hook allows a WebDAV extension to verify these preconditions.
++ [Graham Leggett]
++
+ *) Add hooks deliver_report and gather_reports to mod_dav.h. Allows other
+ modules apart from versioning implementations to handle the REPORT method.
+ [Graham Leggett]
+--- httpd-2.4.x-5/include/ap_mmn.h 2021-07-05 11:42:29.000000000 +0200
++++ httpd-2.4.x-6/include/ap_mmn.h 2021-07-05 12:04:38.000000000 +0200
+@@ -567,6 +567,7 @@
+ * dav_close_lockdb() and dav_get_resource() to
+ * mod_dav.h.
+ * 20120211.110 (2.4.49-dev) Add deliver_report and gather_reports hooks.
++ * 20120211.111 (2.4.49-dev) Add method_precondition hook.
+ */
+
+ #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
+@@ -574,7 +575,7 @@
+ #ifndef MODULE_MAGIC_NUMBER_MAJOR
+ #define MODULE_MAGIC_NUMBER_MAJOR 20120211
+ #endif
+-#define MODULE_MAGIC_NUMBER_MINOR 110 /* 0...n */
++#define MODULE_MAGIC_NUMBER_MINOR 111 /* 0...n */
+
+ /**
+ * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
+--- httpd-2.4.x-5/modules/dav/main/mod_dav.h 2021-07-05 11:37:06.000000000 +0200
++++ httpd-2.4.x-6/modules/dav/main/mod_dav.h 2021-07-05 12:01:14.000000000 +0200
+@@ -741,6 +741,40 @@
+ (request_rec *r, const dav_resource *resource,
+ apr_array_header_t *reports, dav_error **err))
+
++/*
++ ** method_precondition: check method preconditions.
++ **
++ ** If a WebDAV extension needs to set any preconditions on a method, this
++ ** hook is where to do it. If the precondition fails, return an error
++ ** response with the tagname set to the value of the failed precondition.
++ **
++ ** If the method requires an XML body, this will be read and provided as
++ ** the doc value. If not, doc is NULL. An extension that needs to verify
++ ** the non-XML body of a request should register an input filter to do so
++ ** within this hook.
++ **
++ ** Methods like PUT will supply a single src resource, and the dst will
++ ** be NULL.
++ **
++ ** Methods like COPY or MOVE will trigger this hook twice. The first
++ ** invocation will supply just the source resource. The second invocation
++ ** will supply a source and destination. This allows preconditions on the
++ ** source resource to be verified before making an attempt to get the
++ ** destination resource.
++ **
++ ** Methods like PROPFIND and LABEL will trigger this hook initially for
++ ** the src resource, and then subsequently for each resource that has
++ ** been walked during processing, with the walked resource passed in dst,
++ ** and NULL passed in src.
++ **
++ ** As a rule, the src resource originates from a request that has passed
++ ** through httpd's authn/authz hooks, while the dst resource has not.
++ */
++APR_DECLARE_EXTERNAL_HOOK(dav, DAV, int, method_precondition,
++ (request_rec *r,
++ dav_resource *src, const dav_resource *dst,
++ const apr_xml_doc *doc, dav_error **err))
++
+
+ DAV_DECLARE(const dav_hooks_locks *) dav_get_lock_hooks(request_rec *r);
+ DAV_DECLARE(const dav_hooks_propdb *) dav_get_propdb_hooks(request_rec *r);
+--- httpd-2.4.x-5/modules/dav/main/mod_dav.c 2021-07-05 11:37:13.000000000 +0200
++++ httpd-2.4.x-6/modules/dav/main/mod_dav.c 2021-07-05 12:19:32.000000000 +0200
+@@ -860,6 +860,12 @@
+ if (err != NULL)
+ return dav_handle_err(r, err, NULL);
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, NULL, NULL, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ if (!resource->exists) {
+ /* Apache will supply a default error for this. */
+ return HTTP_NOT_FOUND;
+@@ -907,6 +913,12 @@
+ if (err != NULL)
+ return dav_handle_err(r, err, NULL);
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, NULL, NULL, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ /* Note: depth == 0. Implies no need for a multistatus response. */
+ if ((err = dav_validate_request(r, resource, 0, NULL, NULL,
+ DAV_VALIDATE_RESOURCE, NULL)) != NULL) {
+@@ -940,6 +952,12 @@
+ if (err != NULL)
+ return dav_handle_err(r, err, NULL);
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, NULL, NULL, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ /* If not a file or collection resource, PUT not allowed */
+ if (resource->type != DAV_RESOURCE_TYPE_REGULAR
+ && resource->type != DAV_RESOURCE_TYPE_WORKING) {
+@@ -1210,6 +1228,13 @@
+ &resource);
+ if (err != NULL)
+ return dav_handle_err(r, err, NULL);
++
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, NULL, NULL, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ if (!resource->exists) {
+ /* Apache will supply a default error for this. */
+ return HTTP_NOT_FOUND;
+@@ -1651,6 +1676,12 @@
+ }
+ /* note: doc == NULL if no request body */
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, NULL, doc, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ if (doc && !dav_validate_root(doc, "options")) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00584)
+ "The \"options\" element was not found.");
+@@ -1983,6 +2014,13 @@
+ dav_propdb *propdb;
+ dav_get_props_result propstats = { 0 };
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(ctx->r, NULL, wres->resource, ctx->doc, &err) != DECLINED
++ && err) {
++ apr_pool_clear(ctx->scratchpool);
++ return NULL;
++ }
++
+ /*
+ ** Note: ctx->doc can only be NULL for DAV_PROPFIND_IS_ALLPROP. Since
+ ** dav_get_allprops() does not need to do namespace translation,
+@@ -2054,6 +2092,17 @@
+ if (err != NULL)
+ return dav_handle_err(r, err, NULL);
+
++ if ((result = ap_xml_parse_input(r, &doc)) != OK) {
++ return result;
++ }
++ /* note: doc == NULL if no request body */
++
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, NULL, doc, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ if (dav_get_resource_state(r, resource) == DAV_RESOURCE_NULL) {
+ /* Apache will supply a default error for this. */
+ return HTTP_NOT_FOUND;
+@@ -2081,11 +2130,6 @@
+ }
+ }
+
+- if ((result = ap_xml_parse_input(r, &doc)) != OK) {
+- return result;
+- }
+- /* note: doc == NULL if no request body */
+-
+ if (doc && !dav_validate_root(doc, "propfind")) {
+ /* This supplies additional information for the default message. */
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00585)
+@@ -2331,16 +2375,23 @@
+ &resource);
+ if (err != NULL)
+ return dav_handle_err(r, err, NULL);
+- if (!resource->exists) {
+- /* Apache will supply a default error for this. */
+- return HTTP_NOT_FOUND;
+- }
+
+ if ((result = ap_xml_parse_input(r, &doc)) != OK) {
+ return result;
+ }
+ /* note: doc == NULL if no request body */
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, NULL, doc, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
++ if (!resource->exists) {
++ /* Apache will supply a default error for this. */
++ return HTTP_NOT_FOUND;
++ }
++
+ if (doc == NULL || !dav_validate_root(doc, "propertyupdate")) {
+ /* This supplies additional information for the default message. */
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00587)
+@@ -2540,6 +2591,12 @@
+ if (err != NULL)
+ return dav_handle_err(r, err, NULL);
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, NULL, NULL, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ if (resource->exists) {
+ /* oops. something was already there! */
+
+@@ -2660,6 +2717,12 @@
+ if (err != NULL)
+ return dav_handle_err(r, err, NULL);
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, NULL, NULL, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ if (!resource->exists) {
+ /* Apache will supply a default error for this. */
+ return HTTP_NOT_FOUND;
+@@ -2726,6 +2789,12 @@
+ if (err != NULL)
+ return dav_handle_err(r, err, NULL);
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, resnew, NULL, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ /* are the two resources handled by the same repository? */
+ if (resource->hooks != resnew->hooks) {
+ /* ### this message exposes some backend config, but screw it... */
+@@ -3077,6 +3146,12 @@
+ if (err != NULL)
+ return dav_handle_err(r, err, NULL);
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, NULL, doc, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ /* Check if parent collection exists */
+ if ((err = resource->hooks->get_parent_resource(resource, &parent)) != NULL) {
+ /* ### add a higher-level description? */
+@@ -3276,6 +3351,12 @@
+ if (err != NULL)
+ return dav_handle_err(r, err, NULL);
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, NULL, NULL, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ resource_state = dav_get_resource_state(r, resource);
+
+ /*
+@@ -3335,15 +3416,21 @@
+ if (err != NULL)
+ return dav_handle_err(r, err, NULL);
+
+- /* remember the pre-creation resource state */
+- resource_state = dav_get_resource_state(r, resource);
+-
+ /* parse the request body (may be a version-control element) */
+ if ((result = ap_xml_parse_input(r, &doc)) != OK) {
+ return result;
+ }
+ /* note: doc == NULL if no request body */
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, NULL, doc, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
++ /* remember the pre-creation resource state */
++ resource_state = dav_get_resource_state(r, resource);
++
+ if (doc != NULL) {
+ const apr_xml_elem *child;
+ apr_size_t tsize;
+@@ -3588,6 +3675,12 @@
+ if (err != NULL)
+ return dav_handle_err(r, err, NULL);
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, NULL, doc, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ if (!resource->exists) {
+ /* Apache will supply a default error for this. */
+ return HTTP_NOT_FOUND;
+@@ -3664,6 +3757,12 @@
+ if (err != NULL)
+ return dav_handle_err(r, err, NULL);
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, NULL, NULL, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ if (!resource->exists) {
+ /* Apache will supply a default error for this. */
+ return HTTP_NOT_FOUND;
+@@ -3741,6 +3840,12 @@
+ if (err != NULL)
+ return dav_handle_err(r, err, NULL);
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, NULL, doc, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ if (!resource->exists) {
+ /* Apache will supply a default error for this. */
+ return HTTP_NOT_FOUND;
+@@ -3862,6 +3967,12 @@
+ if (err != NULL)
+ return dav_handle_err(r, err, NULL);
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, NULL, doc, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ if (!resource->exists) {
+ /* Apache will supply a default error for this. */
+ return HTTP_NOT_FOUND;
+@@ -3936,6 +4047,9 @@
+ /* input: */
+ dav_walk_params w;
+
++ /* original request */
++ request_rec *r;
++
+ /* label being manipulated */
+ const char *label;
+
+@@ -3955,13 +4069,19 @@
+ dav_label_walker_ctx *ctx = wres->walk_ctx;
+ dav_error *err = NULL;
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(ctx->r, NULL, wres->resource, NULL, &err) != DECLINED
++ && err) {
++ /* precondition failed, dropping through */
++ }
++
+ /* Check the state of the resource: must be a version or
+ * non-checkedout version selector
+ */
+ /* ### need a general mechanism for reporting precondition violations
+ * ### (should be returning XML document for 403/409 responses)
+ */
+- if (wres->resource->type != DAV_RESOURCE_TYPE_VERSION &&
++ else if (wres->resource->type != DAV_RESOURCE_TYPE_VERSION &&
+ (wres->resource->type != DAV_RESOURCE_TYPE_REGULAR
+ || !wres->resource->versioned)) {
+ err = dav_new_error(ctx->w.pool, HTTP_CONFLICT, 0, 0,
+@@ -4007,11 +4127,23 @@
+ if (vsn_hooks == NULL || vsn_hooks->add_label == NULL)
+ return DECLINED;
+
++ /* parse the request body */
++ if ((result = ap_xml_parse_input(r, &doc)) != OK) {
++ return result;
++ }
++
+ /* Ask repository module to resolve the resource */
+ err = dav_get_resource(r, 1 /* label_allowed */, 0 /* use_checked_in */,
+ &resource);
+ if (err != NULL)
+ return dav_handle_err(r, err, NULL);
++
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, NULL, doc, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ if (!resource->exists) {
+ /* Apache will supply a default error for this. */
+ return HTTP_NOT_FOUND;
+@@ -4023,11 +4155,6 @@
+ return HTTP_BAD_REQUEST;
+ }
+
+- /* parse the request body */
+- if ((result = ap_xml_parse_input(r, &doc)) != OK) {
+- return result;
+- }
+-
+ if (doc == NULL || !dav_validate_root(doc, "label")) {
+ /* This supplies additional information for the default message. */
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00610)
+@@ -4076,6 +4203,7 @@
+ ctx.w.walk_ctx = &ctx;
+ ctx.w.pool = r->pool;
+ ctx.w.root = resource;
++ ctx.r = r;
+ ctx.vsn_hooks = vsn_hooks;
+
+ err = (*resource->hooks->walk)(&ctx.w, depth, &multi_status);
+@@ -4187,6 +4315,12 @@
+ return dav_handle_err(r, err, NULL);
+ }
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, NULL, doc, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ if (!resource->exists) {
+ /* Apache will supply a default error for this. */
+ return HTTP_NOT_FOUND;
+@@ -4257,6 +4391,12 @@
+ return result;
+ }
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, NULL, doc, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ if (doc == NULL
+ || !dav_validate_root(doc, "mkworkspace")) {
+ ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00615)
+@@ -4316,6 +4456,12 @@
+ if (err != NULL)
+ return dav_handle_err(r, err, NULL);
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, NULL, NULL, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ /* MKACTIVITY does not have a defined request body. */
+ if ((result = ap_discard_request_body(r)) != OK) {
+ return result;
+@@ -4441,6 +4587,12 @@
+ if (err != NULL)
+ return dav_handle_err(r, err, NULL);
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, source_resource, NULL, doc, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ no_auto_merge = dav_find_child(doc->root, "no-auto-merge") != NULL;
+ no_checkout = dav_find_child(doc->root, "no-checkout") != NULL;
+
+@@ -4458,6 +4610,13 @@
+ &resource);
+ if (err != NULL)
+ return dav_handle_err(r, err, NULL);
++
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, source_resource, resource, doc, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ if (!resource->exists) {
+ /* Apache will supply a default error for this. */
+ return HTTP_NOT_FOUND;
+@@ -4525,6 +4684,12 @@
+ if (err != NULL)
+ return dav_handle_err(r, err, NULL);
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, NULL, NULL, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ if (!resource->exists) {
+ /* Apache will supply a default error for this. */
+ return HTTP_NOT_FOUND;
+@@ -4575,6 +4740,12 @@
+ if (err != NULL)
+ return dav_handle_err(r, err, NULL);
+
++ /* check for any method preconditions */
++ if (dav_run_method_precondition(r, resource, binding, NULL, &err) != DECLINED
++ && err) {
++ return dav_handle_err(r, err, NULL);
++ }
++
+ /* are the two resources handled by the same repository? */
+ if (resource->hooks != binding->hooks) {
+ /* ### this message exposes some backend config, but screw it... */
+@@ -4993,6 +5164,7 @@
+ APR_HOOK_LINK(insert_all_liveprops)
+ APR_HOOK_LINK(deliver_report)
+ APR_HOOK_LINK(gather_reports)
++ APR_HOOK_LINK(method_precondition)
+ )
+
+ APR_IMPLEMENT_EXTERNAL_HOOK_VOID(dav, DAV, gather_propsets,
+@@ -5022,3 +5194,9 @@
+ apr_array_header_t *reports, dav_error **err),
+ (r, resource, reports, err))
+
++APR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(dav, DAV, int, method_precondition,
++ (request_rec *r,
++ dav_resource *src, const dav_resource *dest,
++ const apr_xml_doc *doc,
++ dav_error **err),
++ (r, src, dest, doc, err), DECLINED)