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)