mod_dav.c revision 766b0a4793197ccef3dfa202d1fee1e1f929ffa7
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* Licensed to the Apache Software Foundation (ASF) under one or more
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * contributor license agreements. See the NOTICE file distributed with
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * this work for additional information regarding copyright ownership.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * The ASF licenses this file to You under the Apache License, Version 2.0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * (the "License"); you may not use this file except in compliance with
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * the License. You may obtain a copy of the License at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Unless required by applicable law or agreed to in writing, software
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * distributed under the License is distributed on an "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * See the License for the specific language governing permissions and
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * limitations under the License.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * DAV extension module for Apache 2.0.*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * This module is repository-independent. It depends on hooks provided by a
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * repository implementation.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * APACHE ISSUES:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * - within a DAV hierarchy, if an unknown method is used and we default
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * to Apache's implementation, it sends back an OPTIONS with the wrong
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * set of methods -- there is NO HOOK for us.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * therefore: we need to manually handle the HTTP_METHOD_NOT_ALLOWED
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * and HTTP_NOT_IMPLEMENTED responses (not ap_send_error_response).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * - process_mkcol_body() had to dup code from ap_setup_client_block().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * - it would be nice to get status lines from Apache for arbitrary
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * status codes
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * - it would be nice to be able to extend Apache's set of response
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * codes so that it doesn't return 500 when an unknown code is placed
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * into r->status.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * - http_vhost functions should apply "const" to their params
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * DESIGN NOTES:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * - For PROPFIND, we batch up the entire response in memory before
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * sending it. We may want to reorganize around sending the information
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * as we suck it in from the propdb. Alternatively, we should at least
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * generate a total Content-Length if we're going to buffer in memory
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * so that we can keep the connection open.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* ### what is the best way to set this? */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* used to denote that mod_dav will be handling this request */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* per-dir configuration */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef struct {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const char *dir;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* per-server configuration */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef struct {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ((child)->field ? (child)->field : (parent)->field)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* forward-declare for use in configuration lookup */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* DAV methods */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int dav_init_handler(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* DBG0("dav_init_handler"); */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Register DAV methods */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dav_methods[DAV_M_BIND] = ap_method_register(p, "BIND");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dav_methods[DAV_M_SEARCH] = ap_method_register(p, "SEARCH");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void *dav_create_server_config(apr_pool_t *p, server_rec *s)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync newconf = (dav_server_conf *)apr_pcalloc(p, sizeof(*newconf));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* ### this isn't used at the moment... */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void *dav_merge_server_config(apr_pool_t *p, void *base, void *overrides)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync newconf = (dav_server_conf *)apr_pcalloc(p, sizeof(*newconf));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* ### nothing to merge right now... */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void *dav_create_dir_config(apr_pool_t *p, char *dir)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* NOTE: dir==NULL creates the default per-dir config */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync conf = (dav_dir_conf *)apr_pcalloc(p, sizeof(*conf));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* clean up the directory to remove any trailing slash */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void *dav_merge_dir_config(apr_pool_t *p, void *base, void *overrides)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dav_dir_conf *newconf = (dav_dir_conf *)apr_pcalloc(p, sizeof(*newconf));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* DBG3("dav_merge_dir_config: new=%08lx base=%08lx overrides=%08lx",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (long)newconf, (long)base, (long)overrides); */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync newconf->provider_name = DAV_INHERIT_VALUE(parent, child, provider_name);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync newconf->provider = DAV_INHERIT_VALUE(parent, child, provider);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "\"DAV Off\" cannot be used to turn off a subtree "
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "of a DAV-enabled location.");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "A subtree cannot specify a different DAV provider "
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "than its parent.");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync newconf->locktimeout = DAV_INHERIT_VALUE(parent, child, locktimeout);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync newconf->dir = DAV_INHERIT_VALUE(parent, child, dir);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync newconf->allow_depthinfinity = DAV_INHERIT_VALUE(parent, child,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const dav_provider *dav_get_provider(request_rec *r)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync conf = ap_get_module_config(r->per_dir_config, &dav_module);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* assert: conf->provider_name != NULL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (otherwise, DAV is disabled, and we wouldn't be here) */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* assert: conf->provider != NULL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (checked when conf->provider_name is set) */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDAV_DECLARE(const dav_hooks_locks *) dav_get_lock_hooks(request_rec *r)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDAV_DECLARE(const dav_hooks_propdb *) dav_get_propdb_hooks(request_rec *r)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDAV_DECLARE(const dav_hooks_vsn *) dav_get_vsn_hooks(request_rec *r)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDAV_DECLARE(const dav_hooks_binding *) dav_get_binding_hooks(request_rec *r)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDAV_DECLARE(const dav_hooks_search *) dav_get_search_hooks(request_rec *r)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Command handler for the DAV directive, which is TAKE1.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const char *dav_cmd_dav(cmd_parms *cmd, void *config, const char *arg1)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync conf->provider_name = apr_pstrdup(cmd->pool, arg1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* lookup and cache the actual provider now */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync conf->provider = dav_lookup_provider(conf->provider_name);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* by the time they use it, the provider should be loaded and
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync registered with us. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "Unknown DAV provider: %s",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Command handler for the DAVDepthInfinity directive, which is FLAG.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const char *dav_cmd_davdepthinfinity(cmd_parms *cmd, void *config,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Command handler for DAVMinTimeout directive, which is TAKE1
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const char *dav_cmd_davmintimeout(cmd_parms *cmd, void *config,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const char *arg1)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return "DAVMinTimeout requires a non-negative integer.";
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** dav_error_response()
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** Send a nice response back to the user. In most cases, Apache doesn't
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** allow us to provide details in the body about what happened. This
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** function allows us to completely specify the response body.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync** ### this function is not logging any errors! (e.g. the body)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int dav_error_response(request_rec *r, int status, const char *body)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ap_set_content_type(r, "text/html; charset=ISO-8859-1");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* begin the response now... */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* the response has been sent. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * ### Use of DONE obviates logging..!
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Send a "standardized" error response based on the error's namespace & tag
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "<D:error xmlns:D=\"DAV:\"", r);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* ### should move this namespace somewhere (with the others!) */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ap_rputs(" xmlns:m=\"http://apache.org/dav/xmlns\"", r);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* here's our mod_dav specific tag: */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* the response has been sent. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * ### Use of DONE obviates logging..!
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Apache's URI escaping does not replace '&' since that is a valid character
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * in a URI (to form a query section). We must explicitly handle it so that
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * we can embed the URI into an XML document.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const char *dav_xml_escape_uri(apr_pool_t *p, const char *uri)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* check the easy case... */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* there was a '&', so more work is needed... sigh. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Note: this is a teeny bit of overkill since we know there are no
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * '<' or '>' characters, but who cares.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* Write a complete RESPONSE object out as a <DAV:repsonse> xml
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync element. Data is sent into brigade BB, which is auto-flushed into
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUTPUT filter stack. Use POOL for any temporary allocations.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync [Presumably the <multistatus> tag has already been written; this
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync routine is shared by dav_send_multistatus and dav_stream_response.]
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void dav_send_one_response(dav_response *response,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (t = response->propresult.xmlns; t; t = t->next) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* use the Status-Line text from Apache. Note, this will
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * default to 500 Internal Server Error if first->status
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * is not a known (or valid) status code.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "<D:status>HTTP/1.1 ",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* assume this includes <propstat> and is quoted properly */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (t = response->propresult.propstats; t; t = t->next) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * We supply the description, so we know it doesn't have to
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * have any escaping/encoding applied to it.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "<D:responsedescription>",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* Factorized helper function: prep request_rec R for a multistatus
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync response and write <multistatus> tag into BB, destined for
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync R->output_filters. Use xml NAMESPACES in initial tag, if
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync non-NULL. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void dav_begin_multistatus(apr_bucket_brigade *bb,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Set the correct status and Content-Type */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Send the headers and actual multistatus response now... */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ap_fputs(r->output_filters, bb, DAV_XML_HEADER DEBUG_CR
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "<D:multistatus xmlns:D=\"DAV:\"");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ap_fprintf(r->output_filters, bb, " xmlns:ns%d=\"%s\"", i,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* Finish a multistatus response started by dav_begin_multistatus: */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic apr_status_t dav_finish_multistatus(request_rec *r,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ap_fputs(r->output_filters, bb, "</D:multistatus>" DEBUG_CR);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* indicate the end of the response body */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync b = apr_bucket_eos_create(r->connection->bucket_alloc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* deliver whatever might be remaining in the brigade */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void dav_send_multistatus(request_rec *r, int status,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync apr_bucket_brigade *bb = apr_brigade_create(r->pool,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dav_send_one_response(first, bb, r->output_filters, subpool);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * dav_log_err()
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Write error information to the log.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic void dav_log_err(request_rec *r, dav_error *err, int level)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Log the errors */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* ### should have a directive to log the first or all */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (errscan = err; errscan != NULL; errscan = errscan->prev) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ap_log_rerror(APLOG_MARK, level, errscan->aprerr, r, "%s [%d, #%d]",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync errscan->desc, errscan->status, errscan->error_id);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * dav_handle_err()
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Handle the standard error processing. <err> must be non-NULL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * <response> is set by the following:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * - dav_validate_request()
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * - dav_add_lock()
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * - repos_hooks->remove_resource
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * - repos_hooks->move_resource
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * - repos_hooks->copy_resource
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * - vsn_hooks->update
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int dav_handle_err(request_rec *r, dav_error *err,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* log the errors */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* our error messages are safe; tell Apache this */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Didn't get a multistatus response passed in, but we still
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync might be able to generate a standard <D:error> response.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Search the error stack for an errortag. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync while (stackerr != NULL && stackerr->tagname == NULL)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* send the multistatus and tell Apache the request/response is DONE. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync dav_send_multistatus(r, err->status, response, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* handy function for return values of methods that (may) create things */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic int dav_created(request_rec *r, const char *locn, const char *what,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const char *body;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* did the target resource already exist? */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Apache will supply a default message */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Per HTTP/1.1, S10.2.2: add a Location header to contain the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * URI that was created. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Convert locn to an absolute URI, and return in Location header */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync apr_table_setn(r->headers_out, "Location", ap_construct_url(r->pool, locn, r));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* ### insert an ETag header? see HTTP/1.1 S10.2.2 */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Apache doesn't allow us to set a variable body for HTTP_CREATED, so
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * we must manufacture the entire response. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync body = apr_psprintf(r->pool, "%s %s has been created.",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* ### move to dav_util? */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDAV_DECLARE(int) dav_get_depth(request_rec *r, int def_depth)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const char *depth = apr_table_get(r->headers_in, "Depth");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* The caller will return an HTTP_BAD_REQUEST. This will augment the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * default message that Apache provides. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "An invalid Depth header was specified.");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const char *overwrite = apr_table_get(r->headers_in, "Overwrite");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((*overwrite == 'F' || *overwrite == 'f') && overwrite[1] == '\0') {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((*overwrite == 'T' || *overwrite == 't') && overwrite[1] == '\0') {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* The caller will return an HTTP_BAD_REQUEST. This will augment the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * default message that Apache provides. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "An invalid Overwrite header was specified.");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* resolve a request URI to a resource descriptor.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * If label_allowed != 0, then allow the request target to be altered by
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * a Label: header.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * If use_checked_in is true, then the repository provider should return
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * the resource identified by the DAV:checked-in property of the resource
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * identified by the Request-URI.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic dav_error *dav_get_resource(request_rec *r, int label_allowed,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* if the request target can be overridden, get any target selector */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync conf = ap_get_module_config(r->per_dir_config, &dav_module);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* assert: conf->provider != NULL */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* resolve the resource */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync err = (*conf->provider->repos->get_resource)(r, conf->dir,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Note: this shouldn't happen, but just be sure... */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* ### maybe use HTTP_INTERNAL_SERVER_ERROR */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return dav_new_error(r->pool, HTTP_NOT_FOUND, 0, 0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "The provider did not define a "
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "resource for %s.",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* ### hmm. this doesn't feel like the right place or thing to do */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* if there were any input headers requiring a Vary header in the response,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * add it now */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic dav_error * dav_open_lockdb(request_rec *r, int ro, dav_lockdb **lockdb)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const dav_hooks_locks *hooks = DAV_GET_HOOKS_LOCKS(r);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* open the thing lazily */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @return 1 if valid content-range,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * 0 if no content-range,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * -1 if malformed content-range
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const char *range_c;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync range_c = apr_table_get(r->headers_in, "content-range");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* malformed header */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* detect invalid ranges */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync || *errp || *range_end < 0 || *range_end < *range_start) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* we now have a valid range */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstatic const char *dav_validate_content_headers(request_rec *r)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const apr_array_header_t *arr = apr_table_elts(r->headers_in);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const apr_table_entry_t *elts = (const apr_table_entry_t *)arr->elts;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (strncasecmp(elts[i].key, "content-", prefix_len) == 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync && strcasecmp(elts[i].key + prefix_len, "length") != 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync && strcasecmp(elts[i].key + prefix_len, "range") != 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Content-Location may be ignored per RFC 2616 14.14 */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync && strcasecmp(elts[i].key + prefix_len, "location") != 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync && strcasecmp(elts[i].key + prefix_len, "type") != 0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* XXX: content-md5? content-language? content-encoding? */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return apr_psprintf(r->pool, "Support for %s is not implemented.",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* handle the GET method */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* This method should only be called when the resource is not
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * visible to Apache. We will fetch the resource from the repository,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * then create a subrequest for Apache to handle.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync err = dav_get_resource(r, 1 /* label_allowed */, 0 /* use_checked_in */,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Apache will supply a default error for this. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* set up the HTTP headers for the response */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((err = (*resource->hooks->set_headers)(r, resource)) != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "Unable to set up HTTP headers.",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Handle conditional requests */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* okay... time to deliver the content */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "Unable to deliver content.",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* validate resource/locks on POST, then pass to the default handler */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Ask repository module to resolve the resource */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Note: depth == 0. Implies no need for a multistatus response. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((err = dav_validate_request(r, resource, 0, NULL, NULL,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* ### add a higher-level description? */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* handle the PUT method */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const dav_hooks_locks *locks_hooks = DAV_GET_HOOKS_LOCKS(r);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const char *body;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Ask repository module to resolve the resource */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* If not a file or collection resource, PUT not allowed */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "Cannot create resource %s with PUT.",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Cannot PUT a collection */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "Cannot PUT to a collection.");
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync resource_state = dav_get_resource_state(r, resource);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Note: depth == 0 normally requires no multistatus response. However,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * if we pass DAV_VALIDATE_PARENT, then we could get an error on a URI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * other than the Request-URI, thereby requiring a multistatus.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * If the resource does not exist (DAV_RESOURCE_NULL), then we must
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * check the resource *and* its parent. If the resource exists or is
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * a locknull resource, then we check only the resource.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((err = dav_validate_request(r, resource, 0, NULL, &multi_response,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* ### add a higher-level description? */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync has_range = dav_parse_range(r, &range_start, &range_end);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* RFC 2616 14.16: If we receive an invalid Content-Range we must
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * not use the content.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "Malformed Content-Range header for PUT %s.",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return dav_error_response(r, HTTP_BAD_REQUEST, body);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (has_range) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((body = dav_validate_content_headers(r)) != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* RFC 2616 9.6: We must not ignore any Content-* headers we do not
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * understand.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * XXX: Relax this for HTTP 1.0 requests?
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return dav_error_response(r, HTTP_NOT_IMPLEMENTED, body);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* make sure the resource can be modified (if versioning repository) */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0 /* not parent_only */,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* ### add a higher-level description? */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* Create the new file in the repository */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((err = (*resource->hooks->open_stream)(resource, mode,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* ### assuming FORBIDDEN is probably not quite right... */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "Unable to PUT new contents for %s.",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* a range was provided. seek to the start */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync err = (*resource->hooks->seek_stream)(stream, range_start);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync err = dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0, rc,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "Could not get next bucket "
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "brigade (URI: %s)",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync const char *data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync rc = apr_bucket_read(b, &data, &len, APR_BLOCK_READ);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync err = dav_new_error(r->pool, HTTP_BAD_REQUEST, 0, rc,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "An error occurred while reading"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync " the request body (URI: %s)",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* write whatever we read, until we see an error */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync err = (*resource->hooks->write_stream)(stream, data, len);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* no error during the write, but we hit one at close. use it. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Ensure that we think the resource exists now.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * ### eek. if an error occurred during the write and we did not commit,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * ### then the resource might NOT exist (e.g. dav_fs_repos.c)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* restore modifiability of resources back to what they were */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync err2 = dav_auto_checkin(r, resource, err != NULL /* undo if error */,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* check for errors now */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* just log a warning */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "The PUT was successful, but there "
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "was a problem automatically checking in "
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "the resource or its parent collection.",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* ### place the Content-Type and Content-Language into the propdb */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((err = (*locks_hooks->open_lockdb)(r, 0, 0, &lockdb)) != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* The file creation was successful, but the locking failed. */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "The file was PUT successfully, but there "
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "was a problem opening the lock database "
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "which prevents inheriting locks from the "
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync "parent resources.",
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync /* notify lock system that we have created/replaced a resource */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync err = dav_notify_created(r, lockdb, resource, resource_state, 0);
err);
int status,
if (propstats) {
if (propstats) {
int result;
int depth;
return result;
&resource);
return HTTP_NOT_FOUND;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
** multistatus response -- only internal members/collections.
err);
return result;
err);
err2);
return HTTP_NO_CONTENT;
name);
return NULL;
err);
err);
return err;
err);
return NULL;
return DECLINED;
&resource);
return HTTP_NOT_FOUND;
err);
if (r->header_only) {
return DONE;
return DONE;
const char *dav_level;
char *allow;
apr_text *t;
int text_size;
int result;
&resource);
return result;
return HTTP_BAD_REQUEST;
case DAV_RESOURCE_EXISTS:
case DAV_RESOURCE_LOCK_NULL:
case DAV_RESOURCE_NULL:
text_size = 0;
if (s != allow)
s += strlen(s);
* DASL: <http://foo.bar.com/syntax1>
* DASL: <http://akuma.com/syntax2>
ap_set_content_length(r, 0);
return DONE;
int core_option = 0;
!= NULL) {
return DONE;
/* some props were expected on this collection/resource */
/* no props on this collection/resource */
return NULL;
return NULL;
int depth;
int result;
&resource);
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;
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;
&resource);
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;
&resource);
return HTTP_METHOD_NOT_ALLOWED;
err2);
err);
err);
const char *body;
const char *dest;
int is_dir;
int overwrite;
int depth;
int result;
int replace_dest;
int resnew_state;
return HTTP_NOT_FOUND;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
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) {
replace_dest = 0;
replace_dest = 0;
if (is_move) {
if (replace_dest)
if (is_move)
if (is_move) {
err);
err2);
err3);
err);
int result;
int depth;
int new_lock_request = 0;
int resource_state;
return DECLINED;
return result;
return HTTP_BAD_REQUEST;
&resource);
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);
&resource);
return result;
return HTTP_NO_CONTENT;
int resource_state;
int result;
return DECLINED;
&resource);
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;
int apply_to_vsn = 0;
int is_unreserved = 0;
int is_fork_ok = 0;
int create_activity = 0;
return DECLINED;
return result;
return HTTP_BAD_REQUEST;
const char *href;
return HTTP_BAD_REQUEST;
return HTTP_NOT_FOUND;
err);
ap_set_content_length(r, 0);
return DONE;
int result;
return DECLINED;
return result;
&resource);
return HTTP_NOT_FOUND;
err);
ap_set_content_length(r, 0);
return DONE;
int result;
int keep_checked_out = 0;
return DECLINED;
return result;
return HTTP_BAD_REQUEST;
&resource);
return HTTP_NOT_FOUND;
!= NULL) {
err);
int is_label = 0;
int depth;
int result;
const char *target;
return DECLINED;
return HTTP_BAD_REQUEST;
return result;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
if (tsize == 0) {
return HTTP_BAD_REQUEST;
&resource);
return HTTP_NOT_FOUND;
if (!is_label) {
return HTTP_BAD_REQUEST;
err);
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;
&resource);
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 label_allowed;
return DECLINED;
return result;
return HTTP_BAD_REQUEST;
&resource);
return HTTP_NOT_FOUND;
if (! r->sent_bodyct)
return DONE;
return DONE;
int result;
return DECLINED;
&resource);
return result;
return HTTP_BAD_REQUEST;
err);
int result;
return DECLINED;
&resource);
return result;
err);
return HTTP_METHOD_NOT_ALLOWED;
int result;
const char *source;
int no_auto_merge;
int no_checkout;
return DECLINED;
return result;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
&resource);
return HTTP_NOT_FOUND;
err);
return DONE;
const char *dest;
int overwrite;
return DECLINED;
&resource);
return HTTP_NOT_FOUND;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
return HTTP_BAD_REQUEST;
err);
err);
err2);
return DECLINED;
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 dav_method_vsn_control(r);
return dav_method_checkout(r);
return dav_method_uncheckout(r);
return dav_method_checkin(r);
return dav_method_update(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 dav_method_search(r);
return DECLINED;
return DECLINED;
&dav_module);
return DECLINED;
return DECLINED;
return OK;
return DECLINED;
{ NULL }
(uris))