mod_dav.c revision b980ad7fdc218b4855cde9f75a747527f50c554d
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye/* ====================================================================
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * The Apache Software License, Version 1.1
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * Copyright (c) 2000 The Apache Software Foundation. All rights
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * Redistribution and use in source and binary forms, with or without
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * modification, are permitted provided that the following conditions
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * 1. Redistributions of source code must retain the above copyright
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * notice, this list of conditions and the following disclaimer.
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * 2. Redistributions in binary form must reproduce the above copyright
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * notice, this list of conditions and the following disclaimer in
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * the documentation and/or other materials provided with the
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * distribution.
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * 3. The end-user documentation included with the redistribution,
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * if any, must include the following acknowledgment:
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * "This product includes software developed by the
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * Apache Software Foundation (http://www.apache.org/)."
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * Alternately, this acknowledgment may appear in the software itself,
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * if and wherever such third-party acknowledgments normally appear.
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * 4. The names "Apache" and "Apache Software Foundation" must
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * not be used to endorse or promote products derived from this
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * software without prior written permission. For written
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * permission, please contact apache@apache.org.
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * 5. Products derived from this software may not be called "Apache",
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * nor may "Apache" appear in their name, without prior written
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * permission of the Apache Software Foundation.
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * SUCH DAMAGE.
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * ====================================================================
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * This software consists of voluntary contributions made by many
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * individuals on behalf of the Apache Software Foundation. For more
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye * information on the Apache Software Foundation, please see
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye** DAV extension module for Apache 2.0.*
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye** This module is repository-independent. It depends on hooks provided by a
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye** repository implementation.
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye** APACHE ISSUES:
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye** - within a DAV hierarchy, if an unknown method is used and we default
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye** to Apache's implementation, it sends back an OPTIONS with the wrong
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye** set of methods -- there is NO HOOK for us.
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye** therefore: we need to manually handle the HTTP_METHOD_NOT_ALLOWED
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye** and HTTP_NOT_IMPLEMENTED responses (not ap_send_error_response).
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye** - process_mkcol_body() had to dup code from ap_setup_client_block().
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye** - it would be nice to get status lines from Apache for arbitrary
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye** status codes
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye** - it would be nice to be able to extend Apache's set of response
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye** codes so that it doesn't return 500 when an unknown code is placed
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye** into r->status.
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye** - http_vhost functions should apply "const" to their params
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye** DESIGN NOTES:
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye** - For PROPFIND, we batch up the entire response in memory before
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye** sending it. We may want to reorganize around sending the information
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye** as we suck it in from the propdb. Alternatively, we should at least
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye** generate a total Content-Length if we're going to buffer in memory
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye** so that we can keep the connection open.
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik/* ### what is the best way to set this? */
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen/* per-dir configuration */
5a0c5ad4116f5a4dd0dd5a0a4e6d02973cd5eef9Lubos Koscotypedef struct {
5a0c5ad4116f5a4dd0dd5a0a4e6d02973cd5eef9Lubos Kosco apr_table_t *d_params; /* per-directory DAV config parameters */
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik/* per-server configuration */
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Koscotypedef struct {
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvik#define DAV_INHERIT_VALUE(parent, child, field) \
5a0c5ad4116f5a4dd0dd5a0a4e6d02973cd5eef9Lubos Kosco ((child)->field ? (child)->field : (parent)->field)
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik/* forward-declare for use in configuration lookup */
5a0c5ad4116f5a4dd0dd5a0a4e6d02973cd5eef9Lubos Koscostatic void dav_init_handler(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik /* DBG0("dav_init_handler"); */
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvikstatic void *dav_create_server_config(apr_pool_t *p, server_rec *s)
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik newconf = (dav_server_conf *) apr_pcalloc(p, sizeof(*newconf));
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco /* ### this isn't used at the moment... */
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Koscostatic void *dav_merge_server_config(apr_pool_t *p, void *base, void *overrides)
45909b3ef8c6e568a87482cb890fec7b5dbb7733Lubos Kosco newconf = (dav_server_conf *) apr_pcalloc(p, sizeof(*newconf));
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco /* ### nothing to merge right now... */
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Koscostatic void *dav_create_dir_config(apr_pool_t *p, char *dir)
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco /* NOTE: dir==NULL creates the default per-dir config */
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco conf = (dav_dir_conf *) apr_pcalloc(p, sizeof(*conf));
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco /* clean up the directory to remove any trailing slash */
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbyestatic void *dav_merge_dir_config(apr_pool_t *p, void *base, void *overrides)
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen dav_dir_conf *newconf = (dav_dir_conf *) apr_pcalloc(p, sizeof(*newconf));
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen /* DBG3("dav_merge_dir_config: new=%08lx base=%08lx overrides=%08lx",
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen (long)newconf, (long)base, (long)overrides); */
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen newconf->provider_name = DAV_INHERIT_VALUE(parent, child, provider_name);
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen newconf->provider = DAV_INHERIT_VALUE(parent, child, provider);
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, NULL,
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen "\"DAV Off\" cannot be used to turn off a subtree "
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen "of a DAV-enabled location.");
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen else if (strcasecmp(child->provider_name,
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, NULL,
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen "A subtree cannot specify a different DAV provider "
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen "than its parent.");
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen newconf->locktimeout = DAV_INHERIT_VALUE(parent, child, locktimeout);
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye newconf->dir = DAV_INHERIT_VALUE(parent, child, dir);
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye newconf->allow_depthinfinity = DAV_INHERIT_VALUE(parent, child,
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye newconf->d_params = apr_copy_table(p, parent->d_params);
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye apr_overlap_tables(newconf->d_params, child->d_params,
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Koscoapr_table_t *dav_get_dir_params(const request_rec *r)
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye conf = ap_get_module_config(r->per_dir_config, &dav_module);
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlenstatic const dav_provider * dav_get_provider(request_rec *r)
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen conf = ap_get_module_config(r->per_dir_config, &dav_module);
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen /* assert: conf->provider_name != NULL
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen (otherwise, DAV is disabled, and we wouldn't be here) */
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen /* assert: conf->provider != NULL
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen (checked when conf->provider_name is set) */
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlenconst dav_hooks_locks *dav_get_lock_hooks(request_rec *r)
9cf297d9a579835e9336d587eaee187ca0954767Knut Anders Hatlenconst dav_hooks_propdb *dav_get_propdb_hooks(request_rec *r)
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlenconst dav_hooks_vsn *dav_get_vsn_hooks(request_rec *r)
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlenconst dav_hooks_binding *dav_get_binding_hooks(request_rec *r)
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen * Command handler for the DAV directive, which is TAKE1.
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlenstatic const char *dav_cmd_dav(cmd_parms *cmd, void *config, const char *arg1)
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen dav_dir_conf *conf = (dav_dir_conf *) config;
9661674ed58ba62a40e43d1a4b38d5e77c3c6545Knut Anders Hatlen conf->provider_name = DAV_DEFAULT_PROVIDER;
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco conf->provider_name = apr_pstrdup(cmd->pool, arg1);
c0550b01024b910b8c1468811c0ea663b10b1372Trond Norbye /* lookup and cache the actual provider now */
523201f786f6b12b7cf54091c6e5be167878cbeeTrond Norbye conf->provider = dav_lookup_provider(conf->provider_name);
523201f786f6b12b7cf54091c6e5be167878cbeeTrond Norbye /* by the time they use it, the provider should be loaded and
523201f786f6b12b7cf54091c6e5be167878cbeeTrond Norbye registered with us. */
523201f786f6b12b7cf54091c6e5be167878cbeeTrond Norbye "Unknown DAV provider: %s",
0a0811923cbbd2976425db6f4c78eed811c2825bKnut Anders Hatlen * Command handler for the DAVDepthInfinity directive, which is FLAG.
0a0811923cbbd2976425db6f4c78eed811c2825bKnut Anders Hatlenstatic const char *dav_cmd_davdepthinfinity(cmd_parms *cmd, void *config,
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen dav_dir_conf *conf = (dav_dir_conf *) config;
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen conf->allow_depthinfinity = DAV_ENABLED_ON;
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen conf->allow_depthinfinity = DAV_ENABLED_OFF;
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen * Command handler for DAVMinTimeout directive, which is TAKE1
5e6c91d7e77062129cd0b6ac8aaa546dff216419Lubos Koscostatic const char *dav_cmd_davmintimeout(cmd_parms *cmd, void *config,
5e6c91d7e77062129cd0b6ac8aaa546dff216419Lubos Kosco const char *arg1)
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen dav_dir_conf *conf = (dav_dir_conf *) config;
5e6c91d7e77062129cd0b6ac8aaa546dff216419Lubos Kosco return "DAVMinTimeout requires a non-negative integer.";
a7f25b0d188e4ea80ddcabf3ac52ade1bdb4ebecLubos Kosco * Command handler for DAVParam directive, which is TAKE2
a7f25b0d188e4ea80ddcabf3ac52ade1bdb4ebecLubos Koscostatic const char *dav_cmd_davparam(cmd_parms *cmd, void *config,
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen dav_dir_conf *conf = (dav_dir_conf *) config;
edcb01bf549171673fd0bb4239f2edfc7a810397Knut Anders Hatlen apr_table_set(conf->d_params, arg1, arg2);
a7f25b0d188e4ea80ddcabf3ac52ade1bdb4ebecLubos Kosco** dav_error_response()
edcb01bf549171673fd0bb4239f2edfc7a810397Knut Anders Hatlen** Send a nice response back to the user. In most cases, Apache doesn't
edcb01bf549171673fd0bb4239f2edfc7a810397Knut Anders Hatlen** allow us to provide details in the body about what happened. This
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik** function allows us to completely specify the response body.
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvikstatic int dav_error_response(request_rec *r, int status, const char *body)
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik /* since we're returning DONE, ensure the request body is consumed. */
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvik /* begin the response now... */
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik ap_rputs(ap_psignature("\n<P><HR>\n", r), r);
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik /* the response has been sent. */
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik * ### Use of DONE obviates logging..!
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvik** Apache's URI escaping does not replace '&' since that is a valid character
1f17ba9e3c026d75f488227451416bd72a222afeTrond Norbye** in a URI (to form a query section). We must explicitly handle it so that
1f17ba9e3c026d75f488227451416bd72a222afeTrond Norbye** we can embed the URI into an XML document.
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvikstatic const char *dav_xml_escape_uri(apr_pool_t *p, const char *uri)
1f17ba9e3c026d75f488227451416bd72a222afeTrond Norbye /* check the easy case... */
1f17ba9e3c026d75f488227451416bd72a222afeTrond Norbye /* more work needed... sigh. */
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik ** Note: this is a teeny bit of overkill since we know there are no
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik ** '<' or '>' characters, but who cares.
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvikstatic void dav_send_multistatus(request_rec *r, int status,
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik /* Set the correct status and Content-Type */
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik /* Send all of the headers now */
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik /* Send the actual multistatus response now... */
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik "<D:multistatus xmlns:D=\"DAV:\"", r);
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik /* ap_rputc('>', r); */
30637745bf5a7db2ff9684a2536cc9f8c9df2218Lubos Kosco for (t = first->propresult.xmlns; t; t = t->next) {
30637745bf5a7db2ff9684a2536cc9f8c9df2218Lubos Kosco ap_rputs(dav_xml_escape_uri(r->pool, first->href), r);
30637745bf5a7db2ff9684a2536cc9f8c9df2218Lubos Kosco /* use the Status-Line text from Apache. Note, this will
30637745bf5a7db2ff9684a2536cc9f8c9df2218Lubos Kosco * default to 500 Internal Server Error if first->status
30637745bf5a7db2ff9684a2536cc9f8c9df2218Lubos Kosco * is not a known (or valid) status code. */
30637745bf5a7db2ff9684a2536cc9f8c9df2218Lubos Kosco /* assume this includes <propstat> and is quoted properly */
30637745bf5a7db2ff9684a2536cc9f8c9df2218Lubos Kosco for (t = first->propresult.propstats; t; t = t->next) {
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik ** We supply the description, so we know it doesn't have to
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik ** have any escaping/encoding applied to it.
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik ap_rputs("</D:responsedescription>" DEBUG_CR, r);
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik** dav_log_err()
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik** Write error information to the log.
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvikstatic void dav_log_err(request_rec *r, dav_error *err, int level)
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik /* Log the errors */
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik /* ### should have a directive to log the first or all */
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik for (errscan = err; errscan != NULL; errscan = errscan->prev) {
ede8ae04a015c7d2ae4916e5bb36813b81cb7c30Jorgen Austvik ap_log_rerror(APLOG_MARK, level, errno, r, "%s [%d, #%d]",
afb218f076cae538126a5f931299a82a114a075aKnut Anders Hatlen errscan->desc, errscan->status, errscan->error_id);
780cc7d1b57609ff15fb283201e93cb501ebe9e6Jorgen Austvik ap_log_rerror(APLOG_MARK, level | APLOG_NOERRNO, 0, r,
2f93a8465131cf5f18613f02f25a3663575bfe57Lubos Kosco "%s [%d, #%d]",
780cc7d1b57609ff15fb283201e93cb501ebe9e6Jorgen Austvik errscan->desc, errscan->status, errscan->error_id);
629f5f1dc42d96d37676b093b89f011f143dad0aJorgen Austvik** dav_handle_err()
780cc7d1b57609ff15fb283201e93cb501ebe9e6Jorgen Austvik** Handle the standard error processing. <err> must be non-NULL.
d5734522e5d6f8e329d005a0f93f8c2f30df9516Trond Norbye** <response> is set by the following:
629f5f1dc42d96d37676b093b89f011f143dad0aJorgen Austvik** - dav_validate_request()
780cc7d1b57609ff15fb283201e93cb501ebe9e6Jorgen Austvik** - dav_add_lock()
629f5f1dc42d96d37676b093b89f011f143dad0aJorgen Austvik** - repos_hooks->remove_resource
d5734522e5d6f8e329d005a0f93f8c2f30df9516Trond Norbye** - repos_hooks->move_resource
d5734522e5d6f8e329d005a0f93f8c2f30df9516Trond Norbye** - repos_hooks->copy_resource
d3d2404f9a49bf70b124053feabe666f85ef5361Knut Anders Hatlenstatic int dav_handle_err(request_rec *r, dav_error *err,
afb218f076cae538126a5f931299a82a114a075aKnut Anders Hatlen /* log the errors */
65899d6f2ff5dfa9153c5df8c655728a19d27a4bJorgen Austvik /* our error messages are safe; tell Apache this */
afb218f076cae538126a5f931299a82a114a075aKnut Anders Hatlen apr_table_setn(r->notes, "verbose-error-to", "*");
bcae302a5f4b516d2f3c05f657df054e1a0efde7Knut Anders Hatlen /* since we're returning DONE, ensure the request body is consumed. */
bcae302a5f4b516d2f3c05f657df054e1a0efde7Knut Anders Hatlen /* send the multistatus and tell Apache the request/response is DONE. */
bcae302a5f4b516d2f3c05f657df054e1a0efde7Knut Anders Hatlen dav_send_multistatus(r, err->status, response, NULL);
780cc7d1b57609ff15fb283201e93cb501ebe9e6Jorgen Austvik/* handy function for return values of methods that (may) create things */
bcae302a5f4b516d2f3c05f657df054e1a0efde7Knut Anders Hatlenstatic int dav_created(request_rec *r, const char *locn, const char *what,
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik /* did the target resource already exist? */
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen /* Apache will supply a default message */
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen /* Per HTTP/1.1, S10.2.2: add a Location header to contain the
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen * URI that was created. */
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen /* Convert locn to an absolute URI, and return in Location header */
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen apr_table_setn(r->headers_out, "Location", ap_construct_url(r->pool, locn, r));
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen /* ### insert an ETag header? see HTTP/1.1 S10.2.2 */
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen /* Apache doesn't allow us to set a variable body for HTTP_CREATED, so
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen * we must manufacture the entire response. */
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen body = apr_psprintf(r->pool, "%s %s has been created.",
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen return dav_error_response(r, HTTP_CREATED, body);
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen/* ### move to dav_util? */
d3d2404f9a49bf70b124053feabe666f85ef5361Knut Anders Hatlenint dav_get_depth(request_rec *r, int def_depth)
b8cabd0296e9adcd3cd5db090d292ad75d36fbf8Knut Anders Hatlen const char *depth = apr_table_get(r->headers_in, "Depth");
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen if (strcasecmp(depth, "infinity") == 0) {
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik /* The caller will return an HTTP_BAD_REQUEST. This will augment the
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik * default message that Apache provides. */
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik "An invalid Depth header was specified.");
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik const char *overwrite = apr_table_get(r->headers_in, "Overwrite");
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik if ((*overwrite == 'F' || *overwrite == 'f') && overwrite[1] == '\0') {
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik if ((*overwrite == 'T' || *overwrite == 't') && overwrite[1] == '\0') {
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik /* The caller will return an HTTP_BAD_REQUEST. This will augment the
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik * default message that Apache provides. */
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
92ed85d851c9108d821e93d3aacc9faf3588e17eJorgen Austvik "An invalid Overwrite header was specified.");
8a667c39dc64db336c7bd14db6bde1e38fb5c117Knut Anders Hatlen/* resolve a request URI to a resource descriptor.
8a667c39dc64db336c7bd14db6bde1e38fb5c117Knut Anders Hatlen * If target_allowed != 0, then allow the request target to be overridden
8a667c39dc64db336c7bd14db6bde1e38fb5c117Knut Anders Hatlen * by either a DAV:version or DAV:label-name element (passed as
8a667c39dc64db336c7bd14db6bde1e38fb5c117Knut Anders Hatlen * the target argument), or any Target-Selector header in the request.
8a667c39dc64db336c7bd14db6bde1e38fb5c117Knut Anders Hatlenstatic int dav_get_resource(request_rec *r, int target_allowed,
8a667c39dc64db336c7bd14db6bde1e38fb5c117Knut Anders Hatlen ap_xml_elem *target, dav_resource **res_p)
int is_label = 0;
int result;
return OK;
if (target_allowed) {
return result;
return HTTP_NOT_FOUND;
r->pool);
return OK;
return NULL;
const char *range_c;
char *range;
char *dash;
char *slash;
int result;
return result;
return HTTP_NOT_FOUND;
const char *pathname;
void *fhandle;
return HTTP_NOT_FOUND;
return HTTP_INTERNAL_SERVER_ERROR;
return result;
void *buffer;
int has_range;
err);
if (has_range) {
if (r->header_only) {
return DONE;
err);
if (has_range
if (!has_range)
if (amt == 0) {
if (has_range) {
return DONE;
int result;
return result;
return DECLINED;
int resource_state;
const char *body;
int result;
int has_range;
return result;
return result;
if (has_range) {
err);
if (ap_should_client_block(r)) {
long len;
DAV_READ_BLOCKSIZE)) > 0) {
** ### then the resource might NOT exist (e.g. dav_fs_repos.c)
&av_info);
err2);
err);
err);
if (propstats) {
int result;
int depth;
return result;
return result;
return HTTP_NOT_FOUND;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
** multistatus response -- only internal members/collections.
err);
return result;
&av_info);
err);
err2);
return HTTP_NO_CONTENT;
const char *options;
const char *dav_level;
const char *vsn_level;
int result;
const char *uris;
return result;
ap_set_content_length(r, 0);
return result;
if (*uris) {
case DAV_RESOURCE_EXISTS:
NULL);
NULL);
case DAV_RESOURCE_LOCK_NULL:
NULL);
case DAV_RESOURCE_NULL:
NULL);
else if (vsn_control)
else if (mkworkspace) {
return DONE;
/* some props were expected on this collection/resource */
/* no props on this collection/resource */
return NULL;
return NULL;
int depth;
int result;
return result;
return HTTP_NOT_FOUND;
return HTTP_BAD_REQUEST;
&dav_module);
r->uri)));
return result;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
ctx.r = r;
err);
return DONE;
for ( ; i-- > 0; ++ctx ) {
s = apr_psprintf(p,
for ( ; i-- > 0; ++ctx ) {
int reverse)
if (reverse)
ctx += i;
if (reverse)
--ctx;
if (!reverse)
++ctx;
int result;
int failure = 0;
return result;
return HTTP_NOT_FOUND;
return result;
return HTTP_BAD_REQUEST;
err);
int is_remove;
return HTTP_BAD_REQUEST;
if (failure) {
return DONE;
r->read_chunked = 0;
r->remaining = 0;
if (tenc) {
return HTTP_NOT_IMPLEMENTED;
else if (lenp) {
++pos;
return HTTP_BAD_REQUEST;
return HTTP_UNSUPPORTED_MEDIA_TYPE;
return ap_discard_request_body(r);
int resource_state;
int result;
return result;
&dav_module);
return result;
return HTTP_METHOD_NOT_ALLOWED;
&av_info);
err2);
err);
err);
const char *body;
const char *dest;
int is_dir;
int overwrite;
int depth;
int result;
int replaced;
int resource_state;
return result;
return HTTP_NOT_FOUND;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
return result;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
if (is_move
err);
err);
if (is_dir
if (is_dir
return result;
if (is_move) {
if (is_move) {
&src_av_info);
if (is_move)
&dst_av_info);
if (is_move) {
&src_av_info);
err);
err2);
err3);
err);
int result;
int depth;
int new_lock_request = 0;
int resource_state;
return DECLINED;
return result;
return HTTP_BAD_REQUEST;
return result;
goto error;
err);
goto error;
if (new_lock_request == 0) {
err);
goto error;
dav_get_timeout(r),
goto error;
char *locktoken_txt;
&dav_module);
goto error;
ap_rprintf(r,
return DONE;
int result;
const char *const_locktoken_txt;
char *locktoken_txt;
int resource_state;
return DECLINED;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
err);
return result;
return result;
return HTTP_NO_CONTENT;
int resource_state;
int result;
return DECLINED;
return result;
return result;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
if (tsize == 0) {
return HTTP_BAD_REQUEST;
ap_set_content_length(r, 0);
return DONE;
err);
err);
err);
err);
int result;
return DECLINED;
return result;
return HTTP_BAD_REQUEST;
return result;
return HTTP_NOT_FOUND;
err);
int result;
return DECLINED;
return result;
return result;
return HTTP_NOT_FOUND;
err);
ap_set_content_length(r, 0);
return DONE;
int result;
return DECLINED;
return result;
return result;
return HTTP_NOT_FOUND;
err);
typedef struct dav_set_target_walker_ctx
const char *target;
int is_label;
return NULL;
int depth;
int result;
return DECLINED;
return result;
return HTTP_NOT_FOUND;
return HTTP_BAD_REQUEST;
return result;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
if (tsize == 0) {
return HTTP_BAD_REQUEST;
err);
if (depth == 0) {
ap_set_content_length(r, 0);
return DONE;
typedef struct dav_label_walker_ctx
const char *label;
int label_op;
return NULL;
int depth;
int result;
return DECLINED;
return result;
return HTTP_NOT_FOUND;
return HTTP_BAD_REQUEST;
return result;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
if (tsize == 0) {
return HTTP_BAD_REQUEST;
err);
if (depth == 0) {
ap_set_content_length(r, 0);
return DONE;
int result;
int target_allowed;
ap_text *t;
return DECLINED;
return result;
return HTTP_BAD_REQUEST;
return result;
return HTTP_NOT_FOUND;
return DONE;
int result;
return DECLINED;
return result;
return result;
return HTTP_BAD_REQUEST;
err);
return HTTP_METHOD_NOT_ALLOWED;
return HTTP_METHOD_NOT_ALLOWED;
return HTTP_METHOD_NOT_ALLOWED;
const char *dest;
int overwrite;
int result;
return DECLINED;
return result;
return HTTP_NOT_FOUND;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
return result;
return HTTP_BAD_REQUEST;
err);
&av_info);
err);
err2);
return DECLINED;
if (r->assbackwards) {
return DECLINED;
&dav_module);
r->allowed = 0
r->allowed |= 0
r->allowed |= 0
return dav_method_get(r);
return dav_method_put(r);
return dav_method_post(r);
return dav_method_delete(r);
return dav_method_options(r);
return dav_method_propfind(r);
return dav_method_proppatch(r);
return dav_method_mkcol(r);
return dav_method_lock(r);
return dav_method_unlock(r);
return DECLINED;
return dav_method_vsn_control(r);
return dav_method_checkout(r);
return dav_method_uncheckout(r);
return dav_method_checkin(r);
return dav_method_set_target(r);
return dav_method_label(r);
return dav_method_report(r);
return dav_method_make_workspace(r);
return dav_method_make_activity(r);
return dav_method_baseline_control(r);
return dav_method_merge(r);
return dav_method_bind(r);
return DECLINED;
&dav_module);
return DECLINED;
return DECLINED;
return OK;
return DECLINED;
{ NULL }
(uris))