mod_dav.c revision f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbda
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* ====================================================================
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * The Apache Software License, Version 1.1
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Copyright (c) 2000 The Apache Software Foundation. All rights
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * reserved.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Redistribution and use in source and binary forms, with or without
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * modification, are permitted provided that the following conditions
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * are met:
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * 1. Redistributions of source code must retain the above copyright
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * notice, this list of conditions and the following disclaimer.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * 2. Redistributions in binary form must reproduce the above copyright
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * notice, this list of conditions and the following disclaimer in
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * the documentation and/or other materials provided with the
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * distribution.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * 3. The end-user documentation included with the redistribution,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * if any, must include the following acknowledgment:
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * "This product includes software developed by the
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Apache Software Foundation (http://www.apache.org/)."
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Alternately, this acknowledgment may appear in the software itself,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * if and wherever such third-party acknowledgments normally appear.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * 4. The names "Apache" and "Apache Software Foundation" must
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * not be used to endorse or promote products derived from this
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * software without prior written permission. For written
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * permission, please contact apache@apache.org.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * 5. Products derived from this software may not be called "Apache",
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * nor may "Apache" appear in their name, without prior written
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * permission of the Apache Software Foundation.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * SUCH DAMAGE.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * ====================================================================
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * This software consists of voluntary contributions made by many
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * individuals on behalf of the Apache Software Foundation. For more
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * information on the Apache Software Foundation, please see
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** DAV extension module for Apache 2.0.*
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** This module is repository-independent. It depends on hooks provided by a
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** repository implementation.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** APACHE ISSUES:
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** - within a DAV hierarchy, if an unknown method is used and we default
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** to Apache's implementation, it sends back an OPTIONS with the wrong
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** set of methods -- there is NO HOOK for us.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** therefore: we need to manually handle the HTTP_METHOD_NOT_ALLOWED
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** and HTTP_NOT_IMPLEMENTED responses (not ap_send_error_response).
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** - process_mkcol_body() had to dup code from ap_setup_client_block().
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** - it would be nice to get status lines from Apache for arbitrary
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** status codes
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** - it would be nice to be able to extend Apache's set of response
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** codes so that it doesn't return 500 when an unknown code is placed
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** into r->status.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** - http_vhost functions should apply "const" to their params
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** DESIGN NOTES:
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** - For PROPFIND, we batch up the entire response in memory before
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** sending it. We may want to reorganize around sending the information
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** as we suck it in from the propdb. Alternatively, we should at least
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** generate a total Content-Length if we're going to buffer in memory
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** so that we can keep the connection open.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* per-dir configuration */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbtypedef struct {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb const char *dir;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb int handle_get; /* cached from repository hook structure */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ap_table_t *d_params; /* per-directory DAV config parameters */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* per-server configuration */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbtypedef struct {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* LimitXMLRequestBody handling */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* forward-declare for use in configuration lookup */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* copy a module's providers into our per-directory configuration state */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic void dav_copy_providers(ap_pool_t *p, const char *name, dav_dir_conf *conf)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* ### if NULL? need to error out somehow... */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Set hooks for any providers in the module */
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe /* ### how to signal an error? */
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe /* ### not yet defined */
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe /* ### not yet defined */
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe conf->handle_get = DAV_AS_HOOKS_REPOSITORY(&hooks)->handle_get;
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe /* ### need to error out somehow... */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic void dav_init_handler(ap_pool_t *p, ap_pool_t *plog, ap_pool_t *ptemp,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* DBG0("dav_init_handler"); */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic void *dav_create_server_config(ap_pool_t *p, server_rec *s)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb newconf = (dav_server_conf *) ap_pcalloc(p, sizeof(*newconf));
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic void *dav_merge_server_config(ap_pool_t *p, void *base, void *overrides)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb newconf = (dav_server_conf *) ap_pcalloc(p, sizeof(*newconf));
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb newconf->lockdb_path = DAV_INHERIT_VALUE(parent, child, lockdb_path);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic void *dav_create_dir_config(ap_pool_t *p, char *dir)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* NOTE: dir==NULL creates the default per-dir config */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* DBG1("dav_create_dir_config: %08lx", (long)conf); */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** Locate the appropriate module (NULL == default) and copy the module's
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** providers' hooks into our configuration state.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic void *dav_merge_dir_config(ap_pool_t *p, void *base, void *overrides)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb dav_dir_conf *newconf = (dav_dir_conf *) ap_pcalloc(p, sizeof(*newconf));
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* DBG3("dav_merge_dir_config: new=%08lx base=%08lx overrides=%08lx",
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb (long)newconf, (long)base, (long)overrides); */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb newconf->enabled = DAV_INHERIT_VALUE(parent, child, enabled);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb newconf->locktimeout = DAV_INHERIT_VALUE(parent, child, locktimeout);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb newconf->allow_depthinfinity = DAV_INHERIT_VALUE(parent, child,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb && DAV_AS_HOOKS_REPOSITORY(&newconf->repository)->handle_get;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb conf = ap_get_module_config(r->server->module_config, &dav_module);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb conf = ap_get_module_config(r->server->module_config, &dav_module);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb conf = ap_get_module_config(r->per_dir_config, &dav_module);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb conf = ap_get_module_config(r->per_dir_config, &dav_module);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbconst dav_dyn_hooks *dav_get_provider_hooks(request_rec *r, int provider_type)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Call repository hook to resolve resource */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb conf = (dav_dir_conf *) ap_get_module_config(r->per_dir_config,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* ### not yet defined */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* ### not yet defined */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* unknown provider type */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Command handler for the DAV directive, which is FLAG.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic const char *dav_cmd_dav(cmd_parms *cmd, void *config, int arg)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Command handler for the DAVDepthInfinity directive, which is FLAG.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic const char *dav_cmd_davdepthinfinity(cmd_parms *cmd, void *config,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Command handler for the DAVLockDB directive, which is TAKE1
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic const char *dav_cmd_davlockdb(cmd_parms *cmd, void *config, char *arg1)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb conf = (dav_server_conf *) ap_get_module_config(cmd->server->module_config,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb conf->lockdb_path = ap_server_root_relative(cmd->pool, arg1);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Command handler for DAVMinTimeout directive, which is TAKE1
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic const char *dav_cmd_davmintimeout(cmd_parms *cmd, void *config,
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowe return "DAVMinTimeout requires a non-negative integer.";
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * Command handler for DAVParam directive, which is TAKE2
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowestatic const char *dav_cmd_davparam(cmd_parms *cmd, void *config,
6fed20de38221f6f8a60c0ab1d907f1173c443f4wrowe * Command handler for LimitXMLRequestBody directive, which is TAKE1
6fed20de38221f6f8a60c0ab1d907f1173c443f4wrowestatic const char *dav_cmd_limitxmlrequestbody(cmd_parms *cmd, void *config,
6fed20de38221f6f8a60c0ab1d907f1173c443f4wrowe return "LimitXMLRequestBody requires a non-negative integer.";
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowe** dav_error_response()
6fed20de38221f6f8a60c0ab1d907f1173c443f4wrowe** Send a nice response back to the user. In most cases, Apache doesn't
6fed20de38221f6f8a60c0ab1d907f1173c443f4wrowe** allow us to provide details in the body about what happened. This
6fed20de38221f6f8a60c0ab1d907f1173c443f4wrowe** function allows us to completely specify the response body.
6fed20de38221f6f8a60c0ab1d907f1173c443f4wrowestatic int dav_error_response(request_rec *r, int status, const char *body)
6fed20de38221f6f8a60c0ab1d907f1173c443f4wrowe /* since we're returning DONE, ensure the request body is consumed. */
580786e253bbe2fa462fdb24af47e52e1ef3dd83wrowe /* begin the response now... */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* the response has been sent. */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * ### Use of DONE obviates logging..!
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** Apache's URI escaping does not replace '&' since that is a valid character
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** in a URI (to form a query section). We must explicitly handle it so that
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** we can embed the URI into an XML document.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic const char *dav_xml_escape_uri(ap_pool_t *p, const char *uri)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* check the easy case... */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* more work needed... sigh. */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** Note: this is a teeny bit of overkill since we know there are no
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** '<' or '>' characters, but who cares.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic void dav_send_multistatus(request_rec *r, int status,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Set the correct status and Content-Type */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Send all of the headers now */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Send the actual multistatus response now... */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "<D:multistatus xmlns:D=\"DAV:\"", r);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* ap_rputc('>', r); */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* ### it would be nice to get a status line from Apache */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "<D:status>HTTP/1.1 %d status text goes here</D:status>"
4fca95918a9c0ae93593806544b425d0adc2fcc3wrowe /* assume this includes <propstat> and is quoted properly */
4fca95918a9c0ae93593806544b425d0adc2fcc3wrowe for (t = first->propresult.propstats; t; t = t->next) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** We supply the description, so we know it doesn't have to
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** have any escaping/encoding applied to it.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** dav_log_err()
4fca95918a9c0ae93593806544b425d0adc2fcc3wrowe** Write error information to the log.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic void dav_log_err(request_rec *r, dav_error *err, int level)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Log the errors */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* ### should have a directive to log the first or all */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb for (errscan = err; errscan != NULL; errscan = errscan->prev) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ap_log_rerror(APLOG_MARK, level, errno, r, "%s [%d, #%d]",
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "%s [%d, #%d]",
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** dav_handle_err()
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** Handle the standard error processing. <err> must be non-NULL.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** <response> is set by the following:
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** - dav_validate_request()
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** - dav_add_lock()
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** - repos_hooks->remove_resource
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** - repos_hooks->move_resource
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb** - repos_hooks->copy_resource
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic int dav_handle_err(request_rec *r, dav_error *err,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* log the errors */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* our error messages are safe; tell Apache this */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* since we're returning DONE, ensure the request body is consumed. */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* send the multistatus and tell Apache the request/response is DONE. */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* handy function for return values of methods that (may) create things */
8aefbd756763807188d2e3ce336a8680e4893066wrowestatic int dav_created(request_rec *r, request_rec *rnew,
8aefbd756763807188d2e3ce336a8680e4893066wrowe const char *body;
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* did the target resource already exist? */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Apache will supply a default message */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Per HTTP/1.1, S10.2.2: add a Location header to contain the
8aefbd756763807188d2e3ce336a8680e4893066wrowe * URI that was created. */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* ### rnew->uri does not contain an absoluteURI. S14.30 states that
8aefbd756763807188d2e3ce336a8680e4893066wrowe * ### the Location header requires an absoluteURI. where to get it? */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* ### disable until we get the right value */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* ### insert an ETag header? see HTTP/1.1 S10.2.2 */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Apache doesn't allow us to set a variable body for HTTP_CREATED, so
8aefbd756763807188d2e3ce336a8680e4893066wrowe * we must manufacture the entire response. */
8aefbd756763807188d2e3ce336a8680e4893066wrowe body = ap_psprintf(r->pool, "%s %s has been created.",
8aefbd756763807188d2e3ce336a8680e4893066wrowe/* ### move to dav_util? */
8aefbd756763807188d2e3ce336a8680e4893066wrowe const char *depth = ap_table_get(r->headers_in, "Depth");
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* The caller will return an HTTP_BAD_REQUEST. This will augment the
8aefbd756763807188d2e3ce336a8680e4893066wrowe * default message that Apache provides. */
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
8aefbd756763807188d2e3ce336a8680e4893066wrowe "An invalid Depth header was specified.");
8aefbd756763807188d2e3ce336a8680e4893066wrowe const char *overwrite = ap_table_get(r->headers_in, "Overwrite");
8aefbd756763807188d2e3ce336a8680e4893066wrowe if ((*overwrite == 'F' || *overwrite == 'f') && overwrite[1] == '\0') {
8aefbd756763807188d2e3ce336a8680e4893066wrowe if ((*overwrite == 'T' || *overwrite == 't') && overwrite[1] == '\0') {
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* The caller will return an HTTP_BAD_REQUEST. This will augment the
8aefbd756763807188d2e3ce336a8680e4893066wrowe * default message that Apache provides. */
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
4fca95918a9c0ae93593806544b425d0adc2fcc3wrowe "An invalid Overwrite header was specified.");
4fca95918a9c0ae93593806544b425d0adc2fcc3wrowe/* resolve a request URI to a resource descriptor */
4fca95918a9c0ae93593806544b425d0adc2fcc3wrowestatic int dav_get_resource(request_rec *r, dav_resource **res_p)
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Call repository hook to resolve resource */
8aefbd756763807188d2e3ce336a8680e4893066wrowe conf = (dav_dir_conf *) ap_get_module_config(r->per_dir_config,
8aefbd756763807188d2e3ce336a8680e4893066wrowe repos_hooks = DAV_AS_HOOKS_REPOSITORY(&conf->repository);
8aefbd756763807188d2e3ce336a8680e4893066wrowe if (repos_hooks == NULL || repos_hooks->get_resource == NULL) {
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* ### this should happen at startup rather than per-request */
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
8aefbd756763807188d2e3ce336a8680e4893066wrowe "No %s has been configured.",
8aefbd756763807188d2e3ce336a8680e4893066wrowe ? "repository module"
8aefbd756763807188d2e3ce336a8680e4893066wrowe : "GET handler");
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Apache will supply a default error for this. */
8aefbd756763807188d2e3ce336a8680e4893066wrowestatic dav_error * dav_open_lockdb(request_rec *r, int ro, dav_lockdb **lockdb)
8aefbd756763807188d2e3ce336a8680e4893066wrowe const dav_hooks_locks *hooks = DAV_GET_HOOKS_LOCKS(r);
4fca95918a9c0ae93593806544b425d0adc2fcc3wrowe /* open the thing lazily */
8aefbd756763807188d2e3ce336a8680e4893066wrowe const char *range;
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* malformed header. ignore it (per S14.16 of RFC2616) */
8aefbd756763807188d2e3ce336a8680e4893066wrowe || (slash[1] != '*' && atol(slash + 1) <= *range_end)) {
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* invalid range. ignore it (per S14.16 of RFC2616) */
4fca95918a9c0ae93593806544b425d0adc2fcc3wrowe /* we now have a valid range */
4fca95918a9c0ae93593806544b425d0adc2fcc3wrowe/* handle the GET method */
4fca95918a9c0ae93593806544b425d0adc2fcc3wrowe /* This method should only be called when the resource is not
4fca95918a9c0ae93593806544b425d0adc2fcc3wrowe * visible to Apache. We will fetch the resource from the repository,
4fca95918a9c0ae93593806544b425d0adc2fcc3wrowe * then create a subrequest for Apache to handle.
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Apache will supply a default error for this. */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Check resource type */
8aefbd756763807188d2e3ce336a8680e4893066wrowe "Cannot GET this type of resource.");
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe /* Cannot handle GET of a collection from a repository */
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe "No default response to GET for a "
8aefbd756763807188d2e3ce336a8680e4893066wrowe "collection.");
8aefbd756763807188d2e3ce336a8680e4893066wrowe ** We can use two different approaches for a GET.
8aefbd756763807188d2e3ce336a8680e4893066wrowe ** 1) get_pathname will return a pathname to a file which should be
8aefbd756763807188d2e3ce336a8680e4893066wrowe ** sent to the client. If the repository provides this, then we
8aefbd756763807188d2e3ce336a8680e4893066wrowe ** This is the best alternative since it allows us to do a sub-
8aefbd756763807188d2e3ce336a8680e4893066wrowe ** request on the file, which gives the Apache framework a chance
8aefbd756763807188d2e3ce336a8680e4893066wrowe ** to deal with negotiation, MIME types, or whatever.
8aefbd756763807188d2e3ce336a8680e4893066wrowe ** 2) open_stream and read_stream.
8aefbd756763807188d2e3ce336a8680e4893066wrowe const char *pathname;
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Ask repository for copy of file */
8aefbd756763807188d2e3ce336a8680e4893066wrowe pathname = (*resource->hooks->get_pathname)(resource, &fhandle);
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Convert to canonical filename, so Apache detects component
8aefbd756763807188d2e3ce336a8680e4893066wrowe * separators (on Windows, it only looks for '/', not '\')
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe pathname = ap_os_case_canonical_filename(r->pool, pathname);
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Create a sub-request with the new filename */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* This may be a HEAD request */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* ### this enables header generation */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Run the sub-request */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* Free resources */
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe /* set up the HTTP headers for the response */
8aefbd756763807188d2e3ce336a8680e4893066wrowe if ((err = (*resource->hooks->set_headers)(r, resource)) != NULL) {
8aefbd756763807188d2e3ce336a8680e4893066wrowe "Unable to set up HTTP headers.",
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* use plain READ mode unless we see a Content-Range */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* process the Content-Range header (if present) */
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe has_range = dav_parse_range(r, &range_start, &range_end);
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe /* use a read mode which is seekable */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* prep the output */
8aefbd756763807188d2e3ce336a8680e4893066wrowe "Content-Range",
8aefbd756763807188d2e3ce336a8680e4893066wrowe ap_set_content_length(r, range_end - range_start + 1);
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe if ((err = (*resource->hooks->open_stream)(resource, mode,
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* ### assuming FORBIDDEN is probably not quite right... */
8aefbd756763807188d2e3ce336a8680e4893066wrowe "Unable to GET contents for %s.",
8aefbd756763807188d2e3ce336a8680e4893066wrowe "Could not seek to beginning of the "
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* all set. send the headers now. */
8aefbd756763807188d2e3ce336a8680e4893066wrowe while (1) {
8aefbd756763807188d2e3ce336a8680e4893066wrowe else if ((range_end - range_start + 1) > DAV_READ_BLOCKSIZE)
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* note: range_end - range_start is an ssize_t */
8aefbd756763807188d2e3ce336a8680e4893066wrowe if ((err = (*resource->hooks->read_stream)(stream, buffer,
8aefbd756763807188d2e3ce336a8680e4893066wrowe if (amt == 0) {
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* no more content */
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* ### what to do with this error? */
8aefbd756763807188d2e3ce336a8680e4893066wrowe ** ### range_start should equal range_end+1. if it doesn't, then
8aefbd756763807188d2e3ce336a8680e4893066wrowe ** ### we did not send enough data to the client. the client will
8aefbd756763807188d2e3ce336a8680e4893066wrowe ** ### hang (and timeout) waiting for the data.
8aefbd756763807188d2e3ce336a8680e4893066wrowe ** ### what to do? abort the connection?
8aefbd756763807188d2e3ce336a8680e4893066wrowe /* NOTREACHED */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* validate resource on POST, then pass it off to the default handler */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Ask repository module to resolve the resource */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Note: depth == 0. Implies no need for a multistatus response. */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if ((err = dav_validate_request(r, resource, 0, NULL, NULL,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* ### add a higher-level description? */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* handle the PUT method */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb const dav_hooks_locks *locks_hooks = DAV_GET_HOOKS_LOCKS(r);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb const char *body;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if ((result = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)) != OK) {
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Ask repository module to resolve the resource */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* If not a file or collection resource, PUT not allowed */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "Cannot create resource %s with PUT.",
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Cannot PUT a collection */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "Cannot PUT to a collection.");
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** Note: depth == 0 normally requires no multistatus response. However,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** if we pass DAV_VALIDATE_PARENT, then we could get an error on a URI
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** other than the Request-URI, thereby requiring a multistatus.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** If the resource does not exist (DAV_RESOURCE_NULL), then we must
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** check the resource *and* its parent. If the resource exists or is
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** a locknull resource, then we check only the resource.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if ((err = dav_validate_request(r, resource, 0, NULL, &multi_response,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* ### add a higher-level description? */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* make sure the resource can be modified (if versioning repository) */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb 0 /* not parent_only */,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* ### add a higher-level description? */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* truncate and rewrite the file unless we see a Content-Range */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb has_range = dav_parse_range(r, &range_start, &range_end);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Create the new file in the repository */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if ((err = (*resource->hooks->open_stream)(resource, mode,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* ### assuming FORBIDDEN is probably not quite right... */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "Unable to PUT new contents for %s.",
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* a range was provided. seek to the start */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb err = (*resource->hooks->seek_stream)(stream, range_start);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** Once we start reading the request, then we must read the
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** whole darn thing. ap_discard_request_body() won't do anything
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** for a partially-read request.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* write whatever we read, until we see an error */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** ### what happens if we read more/less than the amount
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** ### specified in the Content-Range? eek...
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** Error reading request body. This has precedence over
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** prior errors.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "An error occurred while reading the "
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "request body.");
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe /* no error during the write, but we hit one at close. use it. */
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe ** Ensure that we think the resource exists now.
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe ** ### eek. if an error occurred during the write and we did not commit,
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe ** ### then the resource might NOT exist (e.g. dav_fs_repos.c)
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe /* restore modifiability of resources back to what they were */
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe err2 = dav_revert_resource_writability(r, resource, resource_parent,
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe /* check for errors now */
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe /* just log a warning */
1067418d9ed9ed9daeb3ca4f74e72db810c49833wrowe "The PUT was successful, but there "
1067418d9ed9ed9daeb3ca4f74e72db810c49833wrowe "was a problem reverting the writability of "
1067418d9ed9ed9daeb3ca4f74e72db810c49833wrowe "the resource or its parent collection.",
1067418d9ed9ed9daeb3ca4f74e72db810c49833wrowe /* ### place the Content-Type and Content-Language into the propdb */
1067418d9ed9ed9daeb3ca4f74e72db810c49833wrowe if ((err = (*locks_hooks->open_lockdb)(r, 0, 0, &lockdb)) != NULL) {
1067418d9ed9ed9daeb3ca4f74e72db810c49833wrowe /* The file creation was successful, but the locking failed. */
1067418d9ed9ed9daeb3ca4f74e72db810c49833wrowe "The file was PUT successfully, but there "
1067418d9ed9ed9daeb3ca4f74e72db810c49833wrowe "was a problem opening the lock database "
1067418d9ed9ed9daeb3ca4f74e72db810c49833wrowe "which prevents inheriting locks from the "
1067418d9ed9ed9daeb3ca4f74e72db810c49833wrowe "parent resources.",
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* notify lock system that we have created/replaced a resource */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb err = dav_notify_created(r, lockdb, resource, resource_state, 0);
4ca6cbe768b4e0917ac0b76333c26a7d5396d454trawick /* The file creation was successful, but the locking failed. */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "The file was PUT successfully, but there "
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "was a problem updating its lock "
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "information.",
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* NOTE: WebDAV spec, S8.7.1 states properties should be unaffected */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* return an appropriate response (HTTP_CREATED or HTTP_NO_CONTENT) */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb return dav_created(r, NULL, resource, "Resource", resource_existed);
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* ### move this to dav_util? */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbvoid dav_add_response(dav_walker_ctx *ctx, const char *href, int status,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* just drop some data into an dav_response */
1b839c67d5c0e4b1f22b44a4217f9860b420d47cwrowe/* handle the DELETE method */
b45c1c292ff1fa635004ae81fa691f8cb3cdda85rbb const char *body;
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* We don't use the request body right now, so torch it. */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Ask repository module to resolve the resource */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Apache will supply a default error for this. */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* 2518 says that depth must be infinity only for collections.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * For non-collections, depth is ignored, unless it is an illegal value (1).
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* This supplies additional information for the default message. */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "Depth must be \"infinity\" for DELETE of a collection.");
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* This supplies additional information for the default message. */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "Depth of \"1\" is not allowed for DELETE.");
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* Check for valid resource type */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* ### allow DAV_RESOURCE_TYPE_REVISION with All-Bindings header */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb "Cannot delete resource %s.",
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** If any resources fail the lock/If: conditions, then we must fail
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** the delete. Each of the failing resources will be listed within
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** a DAV:multistatus body, wrapped into a 424 response.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** Note that a failure on the resource itself does not generate a
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** multistatus response -- only internal members/collections.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb if ((err = dav_validate_request(r, resource, depth, NULL,
117026201e6d8fe7d82416b8a7324830f5a87292wrowe "Could not DELETE %s due to a failed "
117026201e6d8fe7d82416b8a7324830f5a87292wrowe "precondition (e.g. locks).",
117026201e6d8fe7d82416b8a7324830f5a87292wrowe /* ### RFC 2518 s. 8.10.5 says to remove _all_ locks, not just those
117026201e6d8fe7d82416b8a7324830f5a87292wrowe * locked by the token(s) in the if_header.
117026201e6d8fe7d82416b8a7324830f5a87292wrowe /* if versioned resource, make sure parent is checked out */
117026201e6d8fe7d82416b8a7324830f5a87292wrowe if ((err = dav_ensure_resource_writable(r, resource, 1 /* parent_only */,
117026201e6d8fe7d82416b8a7324830f5a87292wrowe /* ### add a higher-level description? */
117026201e6d8fe7d82416b8a7324830f5a87292wrowe /* try to remove the resource */
117026201e6d8fe7d82416b8a7324830f5a87292wrowe err = (*resource->hooks->remove_resource)(resource, &multi_response);
117026201e6d8fe7d82416b8a7324830f5a87292wrowe /* restore writability of parent back to what it was */
117026201e6d8fe7d82416b8a7324830f5a87292wrowe err2 = dav_revert_resource_writability(r, NULL, resource_parent,
e7505ba54ac56ae30e4e250f912f3dbaf92ca45fwrowe /* check for errors now */
117026201e6d8fe7d82416b8a7324830f5a87292wrowe "Could not DELETE %s.",
beda1fb2f11c52ca4612460a5d5ba47398143efbwrowe /* just log a warning */
beda1fb2f11c52ca4612460a5d5ba47398143efbwrowe "The DELETE was successful, but there "
beda1fb2f11c52ca4612460a5d5ba47398143efbwrowe "was a problem reverting the writability of "
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe "its parent collection.",
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe /* ### HTTP_NO_CONTENT if no body, HTTP_OK if there is a body (some day) */
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe /* Apache will supply a default error for this. */
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe/* handle the OPTIONS method */
efa1a34b0a7785fc72863eff175b0cfc1ecb0e38wrowe const dav_hooks_locks *locks_hooks = DAV_GET_HOOKS_LOCKS(r);
117026201e6d8fe7d82416b8a7324830f5a87292wrowe const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
117026201e6d8fe7d82416b8a7324830f5a87292wrowe const char *options;
117026201e6d8fe7d82416b8a7324830f5a87292wrowe const char *dav_level;
117026201e6d8fe7d82416b8a7324830f5a87292wrowe const char *vsn_level;
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe /* per HTTP/1.1 S9.2, we can discard this body */
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe /* no body */
117026201e6d8fe7d82416b8a7324830f5a87292wrowe /* resolve the resource */
73fbb0a2e9cb209173d6c319c57260cbf29c8cc7wrowe /* determine which providers are available */
73fbb0a2e9cb209173d6c319c57260cbf29c8cc7wrowe ** Iterate through the live property providers; add their URIs to
73fbb0a2e9cb209173d6c319c57260cbf29c8cc7wrowe ** the dav_level string.
650ac07cba9ab3ad9bdeda50b78c278442604814wrowe conf = (dav_dir_conf *) ap_get_module_config(r->per_dir_config,
650ac07cba9ab3ad9bdeda50b78c278442604814wrowe for (lp = conf->liveprop; lp != NULL; lp = lp->next) {
117026201e6d8fe7d82416b8a7324830f5a87292wrowe const char *uri = DAV_AS_HOOKS_LIVEPROP(lp)->propset_uri;
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe dav_level = ap_pstrcat(r->pool, dav_level, ",<", uri, ">", NULL);
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe /* this tells MSFT products to skip looking for FrontPage extensions */
1067418d9ed9ed9daeb3ca4f74e72db810c49833wrowe ap_table_setn(r->headers_out, "MS-Author-Via", "DAV");
1067418d9ed9ed9daeb3ca4f74e72db810c49833wrowe ** Three cases: resource is null (3), is lock-null (7.4), or exists.
117026201e6d8fe7d82416b8a7324830f5a87292wrowe ** All cases support OPTIONS and LOCK.
117026201e6d8fe7d82416b8a7324830f5a87292wrowe ** (Lock-) null resources also support MKCOL and PUT.
b67fb549910fa0faf4cdd8aeaf9aeab51d4b6a92wrowe ** Lock-null support PROPFIND and UNLOCK.
b67fb549910fa0faf4cdd8aeaf9aeab51d4b6a92wrowe ** Existing resources support lots of stuff.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* ### take into account resource type */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* resource exists */
b45c1c292ff1fa635004ae81fa691f8cb3cdda85rbb "OPTIONS, "
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe "GET, HEAD, POST, DELETE, TRACE, "
e68544ae924174ca227ede8e2e722cefa00ea0d3wrowe "PROPFIND, PROPPATCH, COPY, MOVE",
b45c1c292ff1fa635004ae81fa691f8cb3cdda85rbb /* files also support PUT */
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowe "OPTIONS, "
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowe "GET, HEAD, POST, DELETE, TRACE, "
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowe "PROPFIND, PROPPATCH, COPY, MOVE, PUT",
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* resource is lock-null. */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb options = ap_pstrcat(r->pool, "OPTIONS, MKCOL, PUT, PROPFIND",
5bb29f57ae0184d2b3c1cdf35132f8ceb011f882wrowe /* resource is null. */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* ### internal error! */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* If there is a versioning provider, add versioning options */
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe /* ### take into account resource type */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb options = ap_pstrcat(r->pool, options, vsn_options, NULL);
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe ap_table_setn(r->headers_out, "Versioning", vsn_level);
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe /* ### this will send a Content-Type. the default OPTIONS does not. */
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe /* ### the default (ap_send_http_options) returns OK, but I believe
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe * ### that is because it is the default handler and nothing else
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb * ### will run after the thing. */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* we've sent everything necessary to the client. */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* just return if we built the thing already */
73fbb0a2e9cb209173d6c319c57260cbf29c8cc7wrowe for (elem = elem->first_child; elem; elem = elem->next) {
73fbb0a2e9cb209173d6c319c57260cbf29c8cc7wrowe dav_text_append(ctx->pool, &hdr, dav_empty_elem(ctx->pool, elem));
290ecc1ddceca1ed49bc1a5338921264b5c3e07cwrowe "<D:status>HTTP/1.1 404 Not Found</D:status>" DEBUG_CR
b38846b15c8891c6dec44dcc4f96ca40721bf663rbbstatic dav_error * dav_propfind_walker(dav_walker_ctx *ctx, int calltype)
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** Note: ctx->doc can only be NULL for DAV_PROPFIND_IS_ALLPROP. Since
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** dav_get_allprops() does not need to do namespace translation,
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** we're okay.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** Note: we cast to lose the "const". The propdb won't try to change
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb ** the resource, however, since we are opening readonly.
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* ### do something with err! */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* some props were expected on this collection/resource */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* no props on this collection/resource */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb /* ### what to do about closing the propdb on server failure? */
b38846b15c8891c6dec44dcc4f96ca40721bf663rbb/* handle the PROPFIND method */
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 = ap_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;
int parent_was_writable = 0;
return result;
&dav_module);
return result;
return HTTP_METHOD_NOT_ALLOWED;
0, 0, parent_was_writable);
err2);
err);
err);
const char *body;
const char *dest;
int is_dir;
int overwrite;
int depth;
int result;
int replaced;
int src_parent_was_writable = 0;
int dst_parent_was_writable = 0;
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) {
if (is_move)
0, 0, dst_parent_was_writable);
if (is_move) {
0, 0, src_parent_was_writable);
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;
return HTTP_METHOD_NOT_ALLOWED;
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);
ap_set_content_length(r, 0);
return DONE;
int result;
return DECLINED;
return result;
return result;
return HTTP_NOT_FOUND;
err);
ap_set_content_length(r, 0);
return DONE;
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_search(r);
return dav_method_checkout(r);
return dav_method_uncheckout(r);
return dav_method_checkin(r);
return dav_method_mkresource(r);
return dav_method_report(r);
return DECLINED;
&dav_module);
return DECLINED;
return DECLINED;
return OK;
return DECLINED;
static void register_hooks(void)
NULL,
FLAG,
NULL,
NULL,
NULL,
FLAG,
NULL,
NULL,
{ NULL }
{ NULL }