mod_dav.c revision f958dac1550254a59b45f4655138bb34dad5e76e
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein/* ====================================================================
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * The Apache Software License, Version 1.1
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * Copyright (c) 2000 The Apache Software Foundation. All rights
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * reserved.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * Redistribution and use in source and binary forms, with or without
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * modification, are permitted provided that the following conditions
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * are met:
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * 1. Redistributions of source code must retain the above copyright
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * notice, this list of conditions and the following disclaimer.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * 2. Redistributions in binary form must reproduce the above copyright
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * notice, this list of conditions and the following disclaimer in
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * the documentation and/or other materials provided with the
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * distribution.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * 3. The end-user documentation included with the redistribution,
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * if any, must include the following acknowledgment:
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * "This product includes software developed by the
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * Apache Software Foundation (http://www.apache.org/)."
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * Alternately, this acknowledgment may appear in the software itself,
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * if and wherever such third-party acknowledgments normally appear.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * 4. The names "Apache" and "Apache Software Foundation" must
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * not be used to endorse or promote products derived from this
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * software without prior written permission. For written
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * permission, please contact apache@apache.org.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * 5. Products derived from this software may not be called "Apache",
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * nor may "Apache" appear in their name, without prior written
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * permission of the Apache Software Foundation.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * SUCH DAMAGE.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * ====================================================================
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * This software consists of voluntary contributions made by many
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * individuals on behalf of the Apache Software Foundation. For more
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * information on the Apache Software Foundation, please see
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein * <http://www.apache.org/>.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein** DAV extension module for Apache 2.0.*
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein**
f4c310fd2555c6faca1f980f00b161eadb089023gstein** This module is repository-independent. It depends on hooks provided by a
f4c310fd2555c6faca1f980f00b161eadb089023gstein** repository implementation.
f4c310fd2555c6faca1f980f00b161eadb089023gstein**
f4c310fd2555c6faca1f980f00b161eadb089023gstein** APACHE ISSUES:
f4c310fd2555c6faca1f980f00b161eadb089023gstein** - within a DAV hierarchy, if an unknown method is used and we default
f4c310fd2555c6faca1f980f00b161eadb089023gstein** to Apache's implementation, it sends back an OPTIONS with the wrong
f4c310fd2555c6faca1f980f00b161eadb089023gstein** set of methods -- there is NO HOOK for us.
f4c310fd2555c6faca1f980f00b161eadb089023gstein** therefore: we need to manually handle the HTTP_METHOD_NOT_ALLOWED
f4c310fd2555c6faca1f980f00b161eadb089023gstein** and HTTP_NOT_IMPLEMENTED responses (not ap_send_error_response).
f4c310fd2555c6faca1f980f00b161eadb089023gstein** - process_mkcol_body() had to dup code from ap_setup_client_block().
f4c310fd2555c6faca1f980f00b161eadb089023gstein** - it would be nice to get status lines from Apache for arbitrary
f4c310fd2555c6faca1f980f00b161eadb089023gstein** status codes
f4c310fd2555c6faca1f980f00b161eadb089023gstein** - it would be nice to be able to extend Apache's set of response
f4c310fd2555c6faca1f980f00b161eadb089023gstein** codes so that it doesn't return 500 when an unknown code is placed
f4c310fd2555c6faca1f980f00b161eadb089023gstein** into r->status.
f4c310fd2555c6faca1f980f00b161eadb089023gstein** - http_vhost functions should apply "const" to their params
f4c310fd2555c6faca1f980f00b161eadb089023gstein**
f4c310fd2555c6faca1f980f00b161eadb089023gstein** DESIGN NOTES:
f4c310fd2555c6faca1f980f00b161eadb089023gstein** - For PROPFIND, we batch up the entire response in memory before
f4c310fd2555c6faca1f980f00b161eadb089023gstein** sending it. We may want to reorganize around sending the information
f4c310fd2555c6faca1f980f00b161eadb089023gstein** as we suck it in from the propdb. Alternatively, we should at least
f4c310fd2555c6faca1f980f00b161eadb089023gstein** generate a total Content-Length if we're going to buffer in memory
f4c310fd2555c6faca1f980f00b161eadb089023gstein** so that we can keep the connection open.
f4c310fd2555c6faca1f980f00b161eadb089023gstein*/
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "httpd.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "http_config.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "http_core.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "http_log.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "http_main.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "http_protocol.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "http_request.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "util_script.h"
8a46775d163c06a8c51d1b0a3f2edfde945cb1d8stoddard#include "apr_strings.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "mod_dav.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein
000397350b42c6266351bd618fa07df929fa7c79gstein/* ### what is the best way to set this? */
000397350b42c6266351bd618fa07df929fa7c79gstein#define DAV_DEFAULT_PROVIDER "filesystem"
000397350b42c6266351bd618fa07df929fa7c79gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinenum {
f4c310fd2555c6faca1f980f00b161eadb089023gstein DAV_ENABLED_UNSET = 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein DAV_ENABLED_OFF,
f4c310fd2555c6faca1f980f00b161eadb089023gstein DAV_ENABLED_ON
f4c310fd2555c6faca1f980f00b161eadb089023gstein};
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* per-dir configuration */
f4c310fd2555c6faca1f980f00b161eadb089023gsteintypedef struct {
9f18c80269be35c0b5653e84b0db0a24044722c4gstein const char *provider_name;
9f18c80269be35c0b5653e84b0db0a24044722c4gstein const dav_provider *provider;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *dir;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int locktimeout;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int allow_depthinfinity;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_table_t *d_params; /* per-directory DAV config parameters */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein} dav_dir_conf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* per-server configuration */
f4c310fd2555c6faca1f980f00b161eadb089023gsteintypedef struct {
b47464a901075041e800be2de098a603923fa4f9gstein int unused;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein} dav_server_conf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein#define DAV_INHERIT_VALUE(parent, child, field) \
f4c310fd2555c6faca1f980f00b161eadb089023gstein ((child)->field ? (child)->field : (parent)->field)
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* forward-declare for use in configuration lookup */
98e9c4a310bb623ff788680f88b6bd200ff36a24wroweextern module DAV_DECLARE_DATA dav_module;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic void dav_init_handler(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp,
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein server_rec *s)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* DBG0("dav_init_handler"); */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
9f18c80269be35c0b5653e84b0db0a24044722c4gstein ap_add_version_component(p, "DAV/2");
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic void *dav_create_server_config(apr_pool_t *p, server_rec *s)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_server_conf *newconf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm newconf = (dav_server_conf *) apr_pcalloc(p, sizeof(*newconf));
f4c310fd2555c6faca1f980f00b161eadb089023gstein
b47464a901075041e800be2de098a603923fa4f9gstein /* ### this isn't used at the moment... */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return newconf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic void *dav_merge_server_config(apr_pool_t *p, void *base, void *overrides)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
b47464a901075041e800be2de098a603923fa4f9gstein#if 0
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_server_conf *child = overrides;
b47464a901075041e800be2de098a603923fa4f9gstein#endif
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_server_conf *newconf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm newconf = (dav_server_conf *) apr_pcalloc(p, sizeof(*newconf));
f4c310fd2555c6faca1f980f00b161eadb089023gstein
b47464a901075041e800be2de098a603923fa4f9gstein /* ### nothing to merge right now... */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return newconf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic void *dav_create_dir_config(apr_pool_t *p, char *dir)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* NOTE: dir==NULL creates the default per-dir config */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_dir_conf *conf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm conf = (dav_dir_conf *) apr_pcalloc(p, sizeof(*conf));
de18a9e85398b9c79c422f578633ed56c2747bbbgstein
de18a9e85398b9c79c422f578633ed56c2747bbbgstein /* clean up the directory to remove any trailing slash */
de18a9e85398b9c79c422f578633ed56c2747bbbgstein if (dir != NULL) {
de18a9e85398b9c79c422f578633ed56c2747bbbgstein char *d;
de18a9e85398b9c79c422f578633ed56c2747bbbgstein apr_size_t l;
de18a9e85398b9c79c422f578633ed56c2747bbbgstein
de18a9e85398b9c79c422f578633ed56c2747bbbgstein d = apr_pstrdup(p, dir);
de18a9e85398b9c79c422f578633ed56c2747bbbgstein l = strlen(d);
de18a9e85398b9c79c422f578633ed56c2747bbbgstein if (l > 1 && d[l - 1] == '/')
de18a9e85398b9c79c422f578633ed56c2747bbbgstein d[l - 1] = '\0';
de18a9e85398b9c79c422f578633ed56c2747bbbgstein conf->dir = d;
de18a9e85398b9c79c422f578633ed56c2747bbbgstein }
de18a9e85398b9c79c422f578633ed56c2747bbbgstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm conf->d_params = apr_make_table(p, 1);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return conf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic void *dav_merge_dir_config(apr_pool_t *p, void *base, void *overrides)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_dir_conf *parent = base;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_dir_conf *child = overrides;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm dav_dir_conf *newconf = (dav_dir_conf *) apr_pcalloc(p, sizeof(*newconf));
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* DBG3("dav_merge_dir_config: new=%08lx base=%08lx overrides=%08lx",
f4c310fd2555c6faca1f980f00b161eadb089023gstein (long)newconf, (long)base, (long)overrides); */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
de18a9e85398b9c79c422f578633ed56c2747bbbgstein newconf->provider_name = DAV_INHERIT_VALUE(parent, child, provider_name);
de18a9e85398b9c79c422f578633ed56c2747bbbgstein newconf->provider = DAV_INHERIT_VALUE(parent, child, provider);
9f18c80269be35c0b5653e84b0db0a24044722c4gstein if (parent->provider_name != NULL) {
9f18c80269be35c0b5653e84b0db0a24044722c4gstein if (child->provider_name == NULL) {
000397350b42c6266351bd618fa07df929fa7c79gstein ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, NULL,
000397350b42c6266351bd618fa07df929fa7c79gstein "\"DAV Off\" cannot be used to turn off a subtree "
000397350b42c6266351bd618fa07df929fa7c79gstein "of a DAV-enabled location.");
000397350b42c6266351bd618fa07df929fa7c79gstein }
9f18c80269be35c0b5653e84b0db0a24044722c4gstein else if (strcasecmp(child->provider_name,
9f18c80269be35c0b5653e84b0db0a24044722c4gstein parent->provider_name) != 0) {
000397350b42c6266351bd618fa07df929fa7c79gstein ap_log_error(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, NULL,
000397350b42c6266351bd618fa07df929fa7c79gstein "A subtree cannot specify a different DAV provider "
000397350b42c6266351bd618fa07df929fa7c79gstein "than its parent.");
000397350b42c6266351bd618fa07df929fa7c79gstein }
000397350b42c6266351bd618fa07df929fa7c79gstein }
000397350b42c6266351bd618fa07df929fa7c79gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein newconf->locktimeout = DAV_INHERIT_VALUE(parent, child, locktimeout);
f4c310fd2555c6faca1f980f00b161eadb089023gstein newconf->dir = DAV_INHERIT_VALUE(parent, child, dir);
f4c310fd2555c6faca1f980f00b161eadb089023gstein newconf->allow_depthinfinity = DAV_INHERIT_VALUE(parent, child,
f4c310fd2555c6faca1f980f00b161eadb089023gstein allow_depthinfinity);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm newconf->d_params = apr_copy_table(p, parent->d_params);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_overlap_tables(newconf->d_params, child->d_params,
10a4cdd68ef1ca0e54af296fe1d08ac00150c90bwrowe APR_OVERLAP_TABLES_SET);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return newconf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmapr_table_t *dav_get_dir_params(const request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_dir_conf *conf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein conf = ap_get_module_config(r->per_dir_config, &dav_module);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return conf->d_params;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gsteinstatic const dav_provider * dav_get_provider(request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gstein dav_dir_conf *conf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gstein conf = ap_get_module_config(r->per_dir_config, &dav_module);
9f18c80269be35c0b5653e84b0db0a24044722c4gstein /* assert: conf->provider_name != NULL
9f18c80269be35c0b5653e84b0db0a24044722c4gstein (otherwise, DAV is disabled, and we wouldn't be here) */
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gstein
9f18c80269be35c0b5653e84b0db0a24044722c4gstein /* assert: conf->provider != NULL
9f18c80269be35c0b5653e84b0db0a24044722c4gstein (checked when conf->provider_name is set) */
9f18c80269be35c0b5653e84b0db0a24044722c4gstein return conf->provider;
709df1e1c2e1710570f8cb4209497e88662829c3gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gsteinconst dav_hooks_locks *dav_get_lock_hooks(request_rec *r)
709df1e1c2e1710570f8cb4209497e88662829c3gstein{
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gstein return dav_get_provider(r)->locks;
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gsteinconst dav_hooks_propdb *dav_get_propdb_hooks(request_rec *r)
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gstein{
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gstein return dav_get_provider(r)->propdb;
709df1e1c2e1710570f8cb4209497e88662829c3gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
709df1e1c2e1710570f8cb4209497e88662829c3gsteinconst dav_hooks_vsn *dav_get_vsn_hooks(request_rec *r)
709df1e1c2e1710570f8cb4209497e88662829c3gstein{
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gstein return dav_get_provider(r)->vsn;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
7281ea331999debdc337b02ce37a3169e0e033a2gsteinconst dav_hooks_binding *dav_get_binding_hooks(request_rec *r)
7281ea331999debdc337b02ce37a3169e0e033a2gstein{
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_get_provider(r)->binding;
7281ea331999debdc337b02ce37a3169e0e033a2gstein}
7281ea331999debdc337b02ce37a3169e0e033a2gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
000397350b42c6266351bd618fa07df929fa7c79gstein * Command handler for the DAV directive, which is TAKE1.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
000397350b42c6266351bd618fa07df929fa7c79gsteinstatic const char *dav_cmd_dav(cmd_parms *cmd, void *config, const char *arg1)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_dir_conf *conf = (dav_dir_conf *) config;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
000397350b42c6266351bd618fa07df929fa7c79gstein if (strcasecmp(arg1, "on") == 0) {
9f18c80269be35c0b5653e84b0db0a24044722c4gstein conf->provider_name = DAV_DEFAULT_PROVIDER;
000397350b42c6266351bd618fa07df929fa7c79gstein }
000397350b42c6266351bd618fa07df929fa7c79gstein else if (strcasecmp(arg1, "off") == 0) {
9f18c80269be35c0b5653e84b0db0a24044722c4gstein conf->provider_name = NULL;
9f18c80269be35c0b5653e84b0db0a24044722c4gstein conf->provider = NULL;
000397350b42c6266351bd618fa07df929fa7c79gstein }
000397350b42c6266351bd618fa07df929fa7c79gstein else {
9f18c80269be35c0b5653e84b0db0a24044722c4gstein conf->provider_name = apr_pstrdup(cmd->pool, arg1);
000397350b42c6266351bd618fa07df929fa7c79gstein }
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gstein
9f18c80269be35c0b5653e84b0db0a24044722c4gstein if (conf->provider_name != NULL) {
9f18c80269be35c0b5653e84b0db0a24044722c4gstein /* lookup and cache the actual provider now */
9f18c80269be35c0b5653e84b0db0a24044722c4gstein conf->provider = dav_lookup_provider(conf->provider_name);
9f18c80269be35c0b5653e84b0db0a24044722c4gstein
9f18c80269be35c0b5653e84b0db0a24044722c4gstein if (conf->provider == NULL) {
9f18c80269be35c0b5653e84b0db0a24044722c4gstein /* by the time they use it, the provider should be loaded and
9f18c80269be35c0b5653e84b0db0a24044722c4gstein registered with us. */
9f18c80269be35c0b5653e84b0db0a24044722c4gstein return apr_psprintf(cmd->pool,
9f18c80269be35c0b5653e84b0db0a24044722c4gstein "Unknown DAV provider: %s",
9f18c80269be35c0b5653e84b0db0a24044722c4gstein conf->provider_name);
9f18c80269be35c0b5653e84b0db0a24044722c4gstein }
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gstein }
000397350b42c6266351bd618fa07df929fa7c79gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Command handler for the DAVDepthInfinity directive, which is FLAG.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *dav_cmd_davdepthinfinity(cmd_parms *cmd, void *config,
f4c310fd2555c6faca1f980f00b161eadb089023gstein int arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_dir_conf *conf = (dav_dir_conf *) config;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (arg)
f4c310fd2555c6faca1f980f00b161eadb089023gstein conf->allow_depthinfinity = DAV_ENABLED_ON;
f4c310fd2555c6faca1f980f00b161eadb089023gstein else
f4c310fd2555c6faca1f980f00b161eadb089023gstein conf->allow_depthinfinity = DAV_ENABLED_OFF;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Command handler for DAVMinTimeout directive, which is TAKE1
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *dav_cmd_davmintimeout(cmd_parms *cmd, void *config,
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein const char *arg1)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_dir_conf *conf = (dav_dir_conf *) config;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein conf->locktimeout = atoi(arg1);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (conf->locktimeout < 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return "DAVMinTimeout requires a non-negative integer.";
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Command handler for DAVParam directive, which is TAKE2
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const char *dav_cmd_davparam(cmd_parms *cmd, void *config,
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein const char *arg1, const char *arg2)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_dir_conf *conf = (dav_dir_conf *) config;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_table_set(conf->d_params, arg1, arg2);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
f4c310fd2555c6faca1f980f00b161eadb089023gstein** dav_error_response()
f4c310fd2555c6faca1f980f00b161eadb089023gstein**
f4c310fd2555c6faca1f980f00b161eadb089023gstein** Send a nice response back to the user. In most cases, Apache doesn't
f4c310fd2555c6faca1f980f00b161eadb089023gstein** allow us to provide details in the body about what happened. This
f4c310fd2555c6faca1f980f00b161eadb089023gstein** function allows us to completely specify the response body.
f4c310fd2555c6faca1f980f00b161eadb089023gstein*/
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_error_response(request_rec *r, int status, const char *body)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein r->status = status;
f4c310fd2555c6faca1f980f00b161eadb089023gstein r->content_type = "text/html";
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* since we're returning DONE, ensure the request body is consumed. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein (void) ap_discard_request_body(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* begin the response now... */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_send_http_header(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rvputs(r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein DAV_RESPONSE_BODY_1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein r->status_line,
f4c310fd2555c6faca1f980f00b161eadb089023gstein DAV_RESPONSE_BODY_2,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &r->status_line[4],
f4c310fd2555c6faca1f980f00b161eadb089023gstein DAV_RESPONSE_BODY_3,
f4c310fd2555c6faca1f980f00b161eadb089023gstein NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rputs(body, r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rputs(ap_psignature("\n<P><HR>\n", r), r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rputs(DAV_RESPONSE_BODY_4, r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* the response has been sent. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein * ### Use of DONE obviates logging..!
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DONE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
f4c310fd2555c6faca1f980f00b161eadb089023gstein** Apache's URI escaping does not replace '&' since that is a valid character
f4c310fd2555c6faca1f980f00b161eadb089023gstein** in a URI (to form a query section). We must explicitly handle it so that
f4c310fd2555c6faca1f980f00b161eadb089023gstein** we can embed the URI into an XML document.
f4c310fd2555c6faca1f980f00b161eadb089023gstein*/
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic const char *dav_xml_escape_uri(apr_pool_t *p, const char *uri)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *e_uri = ap_escape_uri(p, uri);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* check the easy case... */
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein if (ap_strchr_c(e_uri, '&') == NULL)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return e_uri;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* more work needed... sigh. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Note: this is a teeny bit of overkill since we know there are no
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** '<' or '>' characters, but who cares.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein return ap_xml_quote_string(p, e_uri, 0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void dav_send_multistatus(request_rec *r, int status,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_response *first,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_array_header_t *namespaces)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Set the correct status and Content-Type */
f4c310fd2555c6faca1f980f00b161eadb089023gstein r->status = status;
f4c310fd2555c6faca1f980f00b161eadb089023gstein r->content_type = DAV_XML_CONTENT_TYPE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Send all of the headers now */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_send_http_header(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Send the actual multistatus response now... */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rputs(DAV_XML_HEADER DEBUG_CR
f4c310fd2555c6faca1f980f00b161eadb089023gstein "<D:multistatus xmlns:D=\"DAV:\"", r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (namespaces != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein int i;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (i = namespaces->nelts; i--; ) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rprintf(r, " xmlns:ns%d=\"%s\"", i,
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein AP_XML_GET_URI_ITEM(namespaces, i));
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ap_rputc('>', r); */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rputs(">" DEBUG_CR, r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (; first != NULL; first = first->next) {
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_text *t;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (first->propresult.xmlns == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rputs("<D:response>", r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rputs("<D:response", r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (t = first->propresult.xmlns; t; t = t->next) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rputs(t->text, r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rputc('>', r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rputs(DEBUG_CR "<D:href>", r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rputs(dav_xml_escape_uri(r->pool, first->href), r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rputs("</D:href>" DEBUG_CR, r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (first->propresult.propstats == NULL) {
d839a9822ee53ce00da24c15f2d9fe054233d342gstein /* use the Status-Line text from Apache. Note, this will
d839a9822ee53ce00da24c15f2d9fe054233d342gstein * default to 500 Internal Server Error if first->status
d839a9822ee53ce00da24c15f2d9fe054233d342gstein * is not a known (or valid) status code. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rprintf(r,
d839a9822ee53ce00da24c15f2d9fe054233d342gstein "<D:status>HTTP/1.1 %s</D:status>" DEBUG_CR,
d839a9822ee53ce00da24c15f2d9fe054233d342gstein ap_get_status_line(first->status));
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* assume this includes <propstat> and is quoted properly */
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (t = first->propresult.propstats; t; t = t->next) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rputs(t->text, r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (first->desc != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** We supply the description, so we know it doesn't have to
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** have any escaping/encoding applied to it.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rputs("<D:responsedescription>", r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rputs(first->desc, r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rputs("</D:responsedescription>" DEBUG_CR, r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rputs("</D:response>" DEBUG_CR, r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rputs("</D:multistatus>" DEBUG_CR, r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
f4c310fd2555c6faca1f980f00b161eadb089023gstein** dav_log_err()
f4c310fd2555c6faca1f980f00b161eadb089023gstein**
f4c310fd2555c6faca1f980f00b161eadb089023gstein** Write error information to the log.
f4c310fd2555c6faca1f980f00b161eadb089023gstein*/
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void dav_log_err(request_rec *r, dav_error *err, int level)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *errscan;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Log the errors */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### should have a directive to log the first or all */
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (errscan = err; errscan != NULL; errscan = errscan->prev) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (errscan->desc == NULL)
f4c310fd2555c6faca1f980f00b161eadb089023gstein continue;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (errscan->save_errno != 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein errno = errscan->save_errno;
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein ap_log_rerror(APLOG_MARK, level, errno, r, "%s [%d, #%d]",
f4c310fd2555c6faca1f980f00b161eadb089023gstein errscan->desc, errscan->status, errscan->error_id);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein ap_log_rerror(APLOG_MARK, level | APLOG_NOERRNO, 0, r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "%s [%d, #%d]",
f4c310fd2555c6faca1f980f00b161eadb089023gstein errscan->desc, errscan->status, errscan->error_id);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
f4c310fd2555c6faca1f980f00b161eadb089023gstein** dav_handle_err()
f4c310fd2555c6faca1f980f00b161eadb089023gstein**
f4c310fd2555c6faca1f980f00b161eadb089023gstein** Handle the standard error processing. <err> must be non-NULL.
f4c310fd2555c6faca1f980f00b161eadb089023gstein**
f4c310fd2555c6faca1f980f00b161eadb089023gstein** <response> is set by the following:
f4c310fd2555c6faca1f980f00b161eadb089023gstein** - dav_validate_request()
f4c310fd2555c6faca1f980f00b161eadb089023gstein** - dav_add_lock()
f4c310fd2555c6faca1f980f00b161eadb089023gstein** - repos_hooks->remove_resource
f4c310fd2555c6faca1f980f00b161eadb089023gstein** - repos_hooks->move_resource
f4c310fd2555c6faca1f980f00b161eadb089023gstein** - repos_hooks->copy_resource
f4c310fd2555c6faca1f980f00b161eadb089023gstein*/
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_handle_err(request_rec *r, dav_error *err,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_response *response)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* log the errors */
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_log_err(r, err, APLOG_ERR);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (response == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* our error messages are safe; tell Apache this */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_table_setn(r->notes, "verbose-error-to", "*");
f4c310fd2555c6faca1f980f00b161eadb089023gstein return err->status;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* since we're returning DONE, ensure the request body is consumed. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein (void) ap_discard_request_body(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* send the multistatus and tell Apache the request/response is DONE. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_send_multistatus(r, err->status, response, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DONE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* handy function for return values of methods that (may) create things */
50bd75672ef114fb839dd9643c192b432fdf344cgsteinstatic int dav_created(request_rec *r, const char *locn, const char *what,
50bd75672ef114fb839dd9643c192b432fdf344cgstein int replaced)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *body;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
50bd75672ef114fb839dd9643c192b432fdf344cgstein if (locn == NULL) {
50bd75672ef114fb839dd9643c192b432fdf344cgstein locn = r->uri;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* did the target resource already exist? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (replaced) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Apache will supply a default message */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_NO_CONTENT;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Per HTTP/1.1, S10.2.2: add a Location header to contain the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * URI that was created. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein /* Convert locn to an absolute URI, and return in Location header */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein apr_table_setn(r->headers_out, "Location", ap_construct_url(r->pool, locn, r));
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### insert an ETag header? see HTTP/1.1 S10.2.2 */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Apache doesn't allow us to set a variable body for HTTP_CREATED, so
f4c310fd2555c6faca1f980f00b161eadb089023gstein * we must manufacture the entire response. */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm body = apr_psprintf(r->pool, "%s %s has been created.",
50bd75672ef114fb839dd9643c192b432fdf344cgstein what, ap_escape_html(r->pool, locn));
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, HTTP_CREATED, body);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* ### move to dav_util? */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinint dav_get_depth(request_rec *r, int def_depth)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm const char *depth = apr_table_get(r->headers_in, "Depth");
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (depth == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return def_depth;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (strcasecmp(depth, "infinity") == 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DAV_INFINITY;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (strcmp(depth, "0") == 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (strcmp(depth, "1") == 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* The caller will return an HTTP_BAD_REQUEST. This will augment the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * default message that Apache provides. */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "An invalid Depth header was specified.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein return -1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_get_overwrite(request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm const char *overwrite = apr_table_get(r->headers_in, "Overwrite");
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (overwrite == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 1; /* default is "T" */
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((*overwrite == 'F' || *overwrite == 'f') && overwrite[1] == '\0') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((*overwrite == 'T' || *overwrite == 't') && overwrite[1] == '\0') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* The caller will return an HTTP_BAD_REQUEST. This will augment the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * default message that Apache provides. */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "An invalid Overwrite header was specified.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein return -1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein/* resolve a request URI to a resource descriptor.
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein * If target_allowed != 0, then allow the request target to be overridden
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein * by either a DAV:version or DAV:label-name element (passed as
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein * the target argument), or any Target-Selector header in the request.
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gsteinstatic int dav_get_resource(request_rec *r, int target_allowed,
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein ap_xml_elem *target, dav_resource **res_p)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein void *data;
5a47cad1aef57039cd47eb34ebbc2959c610f326gstein dav_dir_conf *conf;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein const char *target_selector = NULL;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein int is_label = 0;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein int result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein /* go look for the resource if it isn't already present */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm (void) apr_get_userdata(&data, DAV_KEY_RESOURCE, r->pool);
5a47cad1aef57039cd47eb34ebbc2959c610f326gstein if (data != NULL) {
5a47cad1aef57039cd47eb34ebbc2959c610f326gstein *res_p = data;
5a47cad1aef57039cd47eb34ebbc2959c610f326gstein return OK;
5a47cad1aef57039cd47eb34ebbc2959c610f326gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein /* if the request target can be overridden, get any target selector */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein if (target_allowed) {
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein if ((result = dav_get_target_selector(r, target,
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein &target_selector,
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein &is_label)) != OK)
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein return result;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein }
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein
9f18c80269be35c0b5653e84b0db0a24044722c4gstein conf = ap_get_module_config(r->per_dir_config, &dav_module);
9f18c80269be35c0b5653e84b0db0a24044722c4gstein /* assert: conf->provider != NULL */
9f18c80269be35c0b5653e84b0db0a24044722c4gstein
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein /* resolve the resource */
7281ea331999debdc337b02ce37a3169e0e033a2gstein *res_p = (*conf->provider->repos->get_resource)(r, conf->dir,
9f18c80269be35c0b5653e84b0db0a24044722c4gstein target_selector, is_label);
5a47cad1aef57039cd47eb34ebbc2959c610f326gstein if (*res_p == NULL) {
5a47cad1aef57039cd47eb34ebbc2959c610f326gstein /* Apache will supply a default error for this. */
5a47cad1aef57039cd47eb34ebbc2959c610f326gstein return HTTP_NOT_FOUND;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
5a47cad1aef57039cd47eb34ebbc2959c610f326gstein (void) apr_set_userdata(*res_p, DAV_KEY_RESOURCE, apr_null_cleanup,
5a47cad1aef57039cd47eb34ebbc2959c610f326gstein r->pool);
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein /* ### hmm. this doesn't feel like the right place or thing to do */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein /* if there were any input headers requiring a Vary header in the response,
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein * add it now */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein dav_add_vary_header(r, r, *res_p);
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return OK;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic dav_error * dav_open_lockdb(request_rec *r, int ro, dav_lockdb **lockdb)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein const dav_hooks_locks *hooks = DAV_GET_HOOKS_LOCKS(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (hooks == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein *lockdb = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* open the thing lazily */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return (*hooks->open_lockdb)(r, ro, 0, lockdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_parse_range(request_rec *r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein off_t *range_start, off_t *range_end)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein const char *range_c;
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein char *range;
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *dash;
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *slash;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm range_c = apr_table_get(r->headers_in, "content-range");
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein if (range_c == NULL)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm range = apr_pstrdup(r->pool, range_c);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (strncasecmp(range, "bytes ", 6) != 0
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein || (dash = ap_strchr(range, '-')) == NULL
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein || (slash = ap_strchr(range, '/')) == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* malformed header. ignore it (per S14.16 of RFC2616) */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein *dash = *slash = '\0';
f4c310fd2555c6faca1f980f00b161eadb089023gstein *range_start = atol(range + 6);
f4c310fd2555c6faca1f980f00b161eadb089023gstein *range_end = atol(dash + 1);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (*range_end < *range_start
f4c310fd2555c6faca1f980f00b161eadb089023gstein || (slash[1] != '*' && atol(slash + 1) <= *range_end)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* invalid range. ignore it (per S14.16 of RFC2616) */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* we now have a valid range */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* handle the GET method */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_method_get(request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *resource;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* This method should only be called when the resource is not
f4c310fd2555c6faca1f980f00b161eadb089023gstein * visible to Apache. We will fetch the resource from the repository,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * then create a subrequest for Apache to handle.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein result = dav_get_resource(r, 1 /*target_allowed*/, NULL, &resource);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (result != OK)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->exists) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Apache will supply a default error for this. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_NOT_FOUND;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Check resource type */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resource->type != DAV_RESOURCE_TYPE_REGULAR &&
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein resource->type != DAV_RESOURCE_TYPE_VERSION &&
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein resource->type != DAV_RESOURCE_TYPE_WORKING)
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, HTTP_CONFLICT,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Cannot GET this type of resource.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Cannot handle GET of a collection from a repository */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resource->collection) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, HTTP_CONFLICT,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "No default response to GET for a "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "collection.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** We can use two different approaches for a GET.
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** 1) get_pathname will return a pathname to a file which should be
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** sent to the client. If the repository provides this, then we
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** use it.
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** This is the best alternative since it allows us to do a sub-
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** request on the file, which gives the Apache framework a chance
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** to deal with negotiation, MIME types, or whatever.
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** 2) open_stream and read_stream.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resource->hooks->get_pathname != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *pathname;
f4c310fd2555c6faca1f980f00b161eadb089023gstein void *fhandle;
f4c310fd2555c6faca1f980f00b161eadb089023gstein request_rec *new_req;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Ask repository for copy of file */
f4c310fd2555c6faca1f980f00b161eadb089023gstein pathname = (*resource->hooks->get_pathname)(resource, &fhandle);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (pathname == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_NOT_FOUND;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Convert to canonical filename, so Apache detects component
f4c310fd2555c6faca1f980f00b161eadb089023gstein * separators (on Windows, it only looks for '/', not '\')
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein pathname = ap_os_case_canonical_filename(r->pool, pathname);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Create a sub-request with the new filename */
f958dac1550254a59b45f4655138bb34dad5e76egstein new_req = ap_sub_req_lookup_file(pathname, r, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (new_req == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein (*resource->hooks->free_file)(fhandle);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_INTERNAL_SERVER_ERROR;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* This may be a HEAD request */
f4c310fd2555c6faca1f980f00b161eadb089023gstein new_req->header_only = r->header_only;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### this enables header generation */
f4c310fd2555c6faca1f980f00b161eadb089023gstein new_req->assbackwards = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Run the sub-request */
f4c310fd2555c6faca1f980f00b161eadb089023gstein result = ap_run_sub_req(new_req);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_destroy_sub_req(new_req);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Free resources */
f4c310fd2555c6faca1f980f00b161eadb089023gstein (*resource->hooks->free_file)(fhandle);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_stream_mode mode;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_stream *stream;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein void *buffer;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int has_range;
f4c310fd2555c6faca1f980f00b161eadb089023gstein off_t range_start;
f4c310fd2555c6faca1f980f00b161eadb089023gstein off_t range_end;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* set up the HTTP headers for the response */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = (*resource->hooks->set_headers)(r, resource)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, err->status, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Unable to set up HTTP headers.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* use plain READ mode unless we see a Content-Range */
f4c310fd2555c6faca1f980f00b161eadb089023gstein mode = DAV_MODE_READ;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* process the Content-Range header (if present) */
f4c310fd2555c6faca1f980f00b161eadb089023gstein has_range = dav_parse_range(r, &range_start, &range_end);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (has_range) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* use a read mode which is seekable */
f4c310fd2555c6faca1f980f00b161eadb089023gstein mode = DAV_MODE_READ_SEEKABLE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* prep the output */
f4c310fd2555c6faca1f980f00b161eadb089023gstein r->status = HTTP_PARTIAL_CONTENT;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_table_setn(r->headers_out,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Content-Range",
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_psprintf(r->pool, "bytes %ld-%ld/*",
f4c310fd2555c6faca1f980f00b161eadb089023gstein range_start, range_end));
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_set_content_length(r, range_end - range_start + 1);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->header_only) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_send_http_header(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DONE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = (*resource->hooks->open_stream)(resource, mode,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &stream)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### assuming FORBIDDEN is probably not quite right... */
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, HTTP_FORBIDDEN, 0,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_psprintf(r->pool,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Unable to GET contents for %s.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_escape_html(r->pool, r->uri)),
f4c310fd2555c6faca1f980f00b161eadb089023gstein err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (has_range
f4c310fd2555c6faca1f980f00b161eadb089023gstein && (err = (*resource->hooks->seek_stream)(stream,
f4c310fd2555c6faca1f980f00b161eadb089023gstein range_start)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, err->status, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Could not seek to beginning of the "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "specified Content-Range.", err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* all set. send the headers now. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_send_http_header(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm buffer = apr_palloc(r->pool, DAV_READ_BLOCKSIZE);
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein size_t amt;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!has_range)
f4c310fd2555c6faca1f980f00b161eadb089023gstein amt = DAV_READ_BLOCKSIZE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if ((range_end - range_start + 1) > DAV_READ_BLOCKSIZE)
f4c310fd2555c6faca1f980f00b161eadb089023gstein amt = DAV_READ_BLOCKSIZE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* note: range_end - range_start is an ssize_t */
f4c310fd2555c6faca1f980f00b161eadb089023gstein amt = (size_t)(range_end - range_start + 1);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = (*resource->hooks->read_stream)(stream, buffer,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &amt)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (amt == 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* no more content */
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ap_rwrite(buffer, amt, r) < 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### what to do with this error? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (has_range) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein range_start += amt;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (range_start > range_end)
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### range_start should equal range_end+1. if it doesn't, then
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### we did not send enough data to the client. the client will
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### hang (and timeout) waiting for the data.
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### what to do? abort the connection?
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DONE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* NOTREACHED */
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* validate resource on POST, then pass it off to the default handler */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_method_post(request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *resource;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Ask repository module to resolve the resource */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein result = dav_get_resource(r, 0 /*target_allowed*/, NULL, &resource);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (result != OK) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Note: depth == 0. Implies no need for a multistatus response. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_validate_request(r, resource, 0, NULL, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein DAV_VALIDATE_RESOURCE, NULL)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### add a higher-level description? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DECLINED;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* handle the PUT method */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_method_put(request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *resource;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int resource_state;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein dav_auto_version_info av_info;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const dav_hooks_locks *locks_hooks = DAV_GET_HOOKS_LOCKS(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *body;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err2;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_stream_mode mode;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_stream *stream;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_response *multi_response;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int has_range;
f4c310fd2555c6faca1f980f00b161eadb089023gstein off_t range_start;
f4c310fd2555c6faca1f980f00b161eadb089023gstein off_t range_end;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((result = ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK)) != OK) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Ask repository module to resolve the resource */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein result = dav_get_resource(r, 0 /*target_allowed*/, NULL, &resource);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (result != OK) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* If not a file or collection resource, PUT not allowed */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resource->type != DAV_RESOURCE_TYPE_REGULAR) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm body = apr_psprintf(r->pool,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Cannot create resource %s with PUT.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_escape_html(r->pool, r->uri));
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, HTTP_CONFLICT, body);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Cannot PUT a collection */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resource->collection) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, HTTP_CONFLICT,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Cannot PUT to a collection.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein resource_state = dav_get_resource_state(r, resource);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Note: depth == 0 normally requires no multistatus response. However,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** if we pass DAV_VALIDATE_PARENT, then we could get an error on a URI
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** other than the Request-URI, thereby requiring a multistatus.
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** If the resource does not exist (DAV_RESOURCE_NULL), then we must
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** check the resource *and* its parent. If the resource exists or is
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** a locknull resource, then we check only the resource.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_validate_request(r, resource, 0, NULL, &multi_response,
f4c310fd2555c6faca1f980f00b161eadb089023gstein resource_state == DAV_RESOURCE_NULL ?
f4c310fd2555c6faca1f980f00b161eadb089023gstein DAV_VALIDATE_PARENT :
f4c310fd2555c6faca1f980f00b161eadb089023gstein DAV_VALIDATE_RESOURCE, NULL)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### add a higher-level description? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, multi_response);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* make sure the resource can be modified (if versioning repository) */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_ensure_resource_writable(r, resource,
f4c310fd2555c6faca1f980f00b161eadb089023gstein 0 /* not parent_only */,
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein &av_info)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### add a higher-level description? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* truncate and rewrite the file unless we see a Content-Range */
f4c310fd2555c6faca1f980f00b161eadb089023gstein mode = DAV_MODE_WRITE_TRUNC;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein has_range = dav_parse_range(r, &range_start, &range_end);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (has_range) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein mode = DAV_MODE_WRITE_SEEKABLE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Create the new file in the repository */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = (*resource->hooks->open_stream)(resource, mode,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &stream)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### assuming FORBIDDEN is probably not quite right... */
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, HTTP_FORBIDDEN, 0,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_psprintf(r->pool,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Unable to PUT new contents for %s.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_escape_html(r->pool, r->uri)),
f4c310fd2555c6faca1f980f00b161eadb089023gstein err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err == NULL && has_range) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* a range was provided. seek to the start */
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = (*resource->hooks->seek_stream)(stream, range_start);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ap_should_client_block(r)) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm char *buffer = apr_palloc(r->pool, DAV_READ_BLOCKSIZE);
f4c310fd2555c6faca1f980f00b161eadb089023gstein long len;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Once we start reading the request, then we must read the
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** whole darn thing. ap_discard_request_body() won't do anything
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** for a partially-read request.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein while ((len = ap_get_client_block(r, buffer,
f4c310fd2555c6faca1f980f00b161eadb089023gstein DAV_READ_BLOCKSIZE)) > 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* write whatever we read, until we see an error */
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = (*resource->hooks->write_stream)(stream,
f4c310fd2555c6faca1f980f00b161eadb089023gstein buffer, len);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### what happens if we read more/less than the amount
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### specified in the Content-Range? eek...
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (len == -1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Error reading request body. This has precedence over
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** prior errors.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_new_error(r->pool, HTTP_BAD_REQUEST, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "An error occurred while reading the "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "request body.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein err2 = (*resource->hooks->close_stream)(stream,
f4c310fd2555c6faca1f980f00b161eadb089023gstein err == NULL /* commit */);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err2 != NULL && err == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* no error during the write, but we hit one at close. use it. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = err2;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Ensure that we think the resource exists now.
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### eek. if an error occurred during the write and we did not commit,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### then the resource might NOT exist (e.g. dav_fs_repos.c)
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein resource->exists = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* restore modifiability of resources back to what they were */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein err2 = dav_revert_resource_writability(r, resource, err != NULL /* undo if error */,
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein &av_info);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* check for errors now */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err2 != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* just log a warning */
f4c310fd2555c6faca1f980f00b161eadb089023gstein err2 = dav_push_error(r->pool, err->status, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The PUT was successful, but there "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "was a problem reverting the writability of "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "the resource or its parent collection.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein err2);
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_log_err(r, err2, APLOG_WARNING);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### place the Content-Type and Content-Language into the propdb */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (locks_hooks != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_lockdb *lockdb;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = (*locks_hooks->open_lockdb)(r, 0, 0, &lockdb)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* The file creation was successful, but the locking failed. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, err->status, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The file was PUT successfully, but there "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "was a problem opening the lock database "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "which prevents inheriting locks from the "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "parent resources.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* notify lock system that we have created/replaced a resource */
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_notify_created(r, lockdb, resource, resource_state, 0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein (*locks_hooks->close_lockdb)(lockdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* The file creation was successful, but the locking failed. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, err->status, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The file was PUT successfully, but there "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "was a problem updating its lock "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "information.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* NOTE: WebDAV spec, S8.7.1 states properties should be unaffected */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* return an appropriate response (HTTP_CREATED or HTTP_NO_CONTENT) */
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_created(r, NULL, "Resource", resource_state == DAV_RESOURCE_EXISTS);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* ### move this to dav_util? */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gsteinDAV_DECLARE(void) dav_add_response(dav_walk_resource *wres,
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe int status, dav_get_props_result *propstats)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein dav_walker_ctx *ctx = wres->walk_ctx;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_response *resp;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* just drop some data into an dav_response */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein resp = apr_pcalloc(ctx->w.pool, sizeof(*resp));
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein resp->href = apr_pstrdup(ctx->w.pool, wres->resource->uri);
f4c310fd2555c6faca1f980f00b161eadb089023gstein resp->status = status;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (propstats) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein resp->propresult = *propstats;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein resp->next = wres->response;
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein wres->response = resp;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* handle the DELETE method */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_method_delete(request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *resource;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein dav_auto_version_info av_info;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err2;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_response *multi_response;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int depth;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* We don't use the request body right now, so torch it. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((result = ap_discard_request_body(r)) != OK) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Ask repository module to resolve the resource */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein result = dav_get_resource(r, 0 /*target_allowed*/, NULL, &resource);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (result != OK)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->exists) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Apache will supply a default error for this. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_NOT_FOUND;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* 2518 says that depth must be infinity only for collections.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * For non-collections, depth is ignored, unless it is an illegal value (1).
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein depth = dav_get_depth(r, DAV_INFINITY);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resource->collection && depth != DAV_INFINITY) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* This supplies additional information for the default message. */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Depth must be \"infinity\" for DELETE of a collection.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->collection && depth == 1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* This supplies additional information for the default message. */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Depth of \"1\" is not allowed for DELETE.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** If any resources fail the lock/If: conditions, then we must fail
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** the delete. Each of the failing resources will be listed within
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** a DAV:multistatus body, wrapped into a 424 response.
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Note that a failure on the resource itself does not generate a
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** multistatus response -- only internal members/collections.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_validate_request(r, resource, depth, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &multi_response,
f4c310fd2555c6faca1f980f00b161eadb089023gstein DAV_VALIDATE_PARENT
f4c310fd2555c6faca1f980f00b161eadb089023gstein | DAV_VALIDATE_USE_424, NULL)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, err->status, 0,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_psprintf(r->pool,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Could not DELETE %s due to a failed "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "precondition (e.g. locks).",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_escape_html(r->pool, r->uri)),
f4c310fd2555c6faca1f980f00b161eadb089023gstein err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, multi_response);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### RFC 2518 s. 8.10.5 says to remove _all_ locks, not just those
f4c310fd2555c6faca1f980f00b161eadb089023gstein * locked by the token(s) in the if_header.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((result = dav_unlock(r, resource, NULL)) != OK) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* if versioned resource, make sure parent is checked out */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_ensure_resource_writable(r, resource, 1 /* parent_only */,
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein &av_info)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### add a higher-level description? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* try to remove the resource */
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = (*resource->hooks->remove_resource)(resource, &multi_response);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* restore writability of parent back to what it was */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein err2 = dav_revert_resource_writability(r, NULL, err != NULL /* undo if error */,
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein &av_info);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* check for errors now */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, err->status, 0,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_psprintf(r->pool,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Could not DELETE %s.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_escape_html(r->pool, r->uri)),
f4c310fd2555c6faca1f980f00b161eadb089023gstein err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, multi_response);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err2 != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* just log a warning */
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, err2->status, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The DELETE was successful, but there "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "was a problem reverting the writability of "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "its parent collection.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein err2);
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_log_err(r, err, APLOG_WARNING);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### HTTP_NO_CONTENT if no body, HTTP_OK if there is a body (some day) */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Apache will supply a default error for this. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_NO_CONTENT;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* handle the OPTIONS method */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_method_options(request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein const dav_hooks_locks *locks_hooks = DAV_GET_HOOKS_LOCKS(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
7281ea331999debdc337b02ce37a3169e0e033a2gstein const dav_hooks_binding *binding_hooks = DAV_GET_HOOKS_BINDING(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *resource;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *options;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *dav_level;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *vsn_level;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int result;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_array_header_t *uri_ary;
6b745319b1099edacf401e8911efa480440f999agstein const char *uris;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* per HTTP/1.1 S9.2, we can discard this body */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((result = ap_discard_request_body(r)) != OK) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* no body */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_set_content_length(r, 0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* resolve the resource */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein result = dav_get_resource(r, 0 /*target_allowed*/, NULL, &resource);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (result != OK)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* determine which providers are available */
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_level = "1";
f4c310fd2555c6faca1f980f00b161eadb089023gstein vsn_level = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (locks_hooks != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_level = "1,2";
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (vsn_hooks != NULL
7281ea331999debdc337b02ce37a3169e0e033a2gstein && (vsn_level = (*vsn_hooks->get_vsn_header)()) != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_level = apr_pstrcat(r->pool, dav_level, ",", vsn_level, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
6b745319b1099edacf401e8911efa480440f999agstein /* gather property set URIs from all the liveprop providers */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm uri_ary = apr_make_array(r->pool, 5, sizeof(const char *));
6b745319b1099edacf401e8911efa480440f999agstein ap_run_gather_propsets(uri_ary);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm uris = apr_array_pstrcat(r->pool, uri_ary, ',');
6b745319b1099edacf401e8911efa480440f999agstein if (*uris) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm dav_level = apr_pstrcat(r->pool, dav_level, ",", uris, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* this tells MSFT products to skip looking for FrontPage extensions */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_table_setn(r->headers_out, "MS-Author-Via", "DAV");
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Three cases: resource is null (3), is lock-null (7.4), or exists.
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** All cases support OPTIONS and LOCK.
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** (Lock-) null resources also support MKCOL and PUT.
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Lock-null support PROPFIND and UNLOCK.
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Existing resources support lots of stuff.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### take into account resource type */
f4c310fd2555c6faca1f980f00b161eadb089023gstein switch (dav_get_resource_state(r, resource))
f4c310fd2555c6faca1f980f00b161eadb089023gstein {
f4c310fd2555c6faca1f980f00b161eadb089023gstein case DAV_RESOURCE_EXISTS:
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* resource exists */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resource->collection) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm options = apr_pstrcat(r->pool,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "OPTIONS, "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "GET, HEAD, POST, DELETE, TRACE, "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "PROPFIND, PROPPATCH, COPY, MOVE",
f4c310fd2555c6faca1f980f00b161eadb089023gstein locks_hooks != NULL ? ", LOCK, UNLOCK" : "",
f4c310fd2555c6faca1f980f00b161eadb089023gstein NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* files also support PUT */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm options = apr_pstrcat(r->pool,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "OPTIONS, "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "GET, HEAD, POST, DELETE, TRACE, "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "PROPFIND, PROPPATCH, COPY, MOVE, PUT",
f4c310fd2555c6faca1f980f00b161eadb089023gstein locks_hooks != NULL ? ", LOCK, UNLOCK" : "",
f4c310fd2555c6faca1f980f00b161eadb089023gstein NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein case DAV_RESOURCE_LOCK_NULL:
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* resource is lock-null. */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm options = apr_pstrcat(r->pool, "OPTIONS, MKCOL, PUT, PROPFIND",
f4c310fd2555c6faca1f980f00b161eadb089023gstein locks_hooks != NULL ? ", LOCK, UNLOCK" : "",
f4c310fd2555c6faca1f980f00b161eadb089023gstein NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein case DAV_RESOURCE_NULL:
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* resource is null. */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm options = apr_pstrcat(r->pool, "OPTIONS, MKCOL, PUT",
f4c310fd2555c6faca1f980f00b161eadb089023gstein locks_hooks != NULL ? ", LOCK" : "",
f4c310fd2555c6faca1f980f00b161eadb089023gstein NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein default:
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### internal error! */
f4c310fd2555c6faca1f980f00b161eadb089023gstein options = "OPTIONS";
f4c310fd2555c6faca1f980f00b161eadb089023gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* If there is a versioning provider, add versioning options */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (vsn_hooks != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *vsn_options = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->exists) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein int vsn_control = (*vsn_hooks->versionable)(resource);
7281ea331999debdc337b02ce37a3169e0e033a2gstein int mkworkspace = vsn_hooks->can_be_workspace != NULL
7281ea331999debdc337b02ce37a3169e0e033a2gstein && (*vsn_hooks->can_be_workspace)(resource);
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (vsn_control && mkworkspace) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein vsn_options = ", VERSION-CONTROL, MKWORKSPACE";
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein else if (vsn_control)
7281ea331999debdc337b02ce37a3169e0e033a2gstein vsn_options = ", VERSION-CONTROL";
7281ea331999debdc337b02ce37a3169e0e033a2gstein else if (mkworkspace) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein vsn_options = ", MKWORKSPACE";
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (!resource->versioned) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((*vsn_hooks->versionable)(resource)) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein vsn_options = ", VERSION-CONTROL";
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (resource->working)
f4c310fd2555c6faca1f980f00b161eadb089023gstein vsn_options = ", CHECKIN, UNCHECKOUT";
7281ea331999debdc337b02ce37a3169e0e033a2gstein else if (vsn_hooks->add_label != NULL)
7281ea331999debdc337b02ce37a3169e0e033a2gstein vsn_options = ", CHECKOUT, LABEL";
f4c310fd2555c6faca1f980f00b161eadb089023gstein else
f4c310fd2555c6faca1f980f00b161eadb089023gstein vsn_options = ", CHECKOUT";
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (vsn_options != NULL)
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm options = apr_pstrcat(r->pool, options, vsn_options, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* If there is a bindings provider, see if resource is bindable */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (binding_hooks != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_level = apr_pstrcat(r->pool, dav_level, ",bindings", NULL);
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((*binding_hooks->is_bindable)(resource))
7281ea331999debdc337b02ce37a3169e0e033a2gstein options = apr_pstrcat(r->pool, options, ", BIND", NULL);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_table_setn(r->headers_out, "Allow", options);
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_table_setn(r->headers_out, "DAV", dav_level);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### this will send a Content-Type. the default OPTIONS does not. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_send_http_header(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### the default (ap_send_http_options) returns OK, but I believe
f4c310fd2555c6faca1f980f00b161eadb089023gstein * ### that is because it is the default handler and nothing else
f4c310fd2555c6faca1f980f00b161eadb089023gstein * ### will run after the thing. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* we've sent everything necessary to the client. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DONE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void dav_cache_badprops(dav_walker_ctx *ctx)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein const ap_xml_elem *elem;
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_text_header hdr = { 0 };
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* just return if we built the thing already */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ctx->propstat_404 != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein ap_text_append(ctx->w.pool, &hdr,
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein "<D:propstat>" DEBUG_CR
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein "<D:prop>" DEBUG_CR);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein elem = dav_find_child(ctx->doc->root, "prop");
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (elem = elem->first_child; elem; elem = elem->next) {
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein ap_text_append(ctx->w.pool, &hdr,
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein ap_xml_empty_elem(ctx->w.pool, elem));
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein ap_text_append(ctx->w.pool, &hdr,
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein "</D:prop>" DEBUG_CR
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein "<D:status>HTTP/1.1 404 Not Found</D:status>" DEBUG_CR
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein "</D:propstat>" DEBUG_CR);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ctx->propstat_404 = hdr.first;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gsteinstatic dav_error * dav_propfind_walker(dav_walk_resource *wres, int calltype)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein dav_walker_ctx *ctx = wres->walk_ctx;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_propdb *propdb;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_get_props_result propstats = { 0 };
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Note: ctx->doc can only be NULL for DAV_PROPFIND_IS_ALLPROP. Since
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** dav_get_allprops() does not need to do namespace translation,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** we're okay.
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Note: we cast to lose the "const". The propdb won't try to change
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** the resource, however, since we are opening readonly.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein err = dav_open_propdb(ctx->r, ctx->w.lockdb,
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein (dav_resource *)wres->resource, 1,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ctx->doc ? ctx->doc->namespaces : NULL, &propdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### do something with err! */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ctx->propfind_type == DAV_PROPFIND_IS_PROP) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_get_props_result badprops = { 0 };
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* some props were expected on this collection/resource */
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_cache_badprops(ctx);
f4c310fd2555c6faca1f980f00b161eadb089023gstein badprops.propstats = ctx->propstat_404;
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein dav_add_response(wres, 0, &badprops);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* no props on this collection/resource */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein dav_add_response(wres, HTTP_OK, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### what to do about closing the propdb on server failure? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ctx->propfind_type == DAV_PROPFIND_IS_PROP) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein propstats = dav_get_props(propdb, ctx->doc);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein propstats = dav_get_allprops(propdb,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ctx->propfind_type == DAV_PROPFIND_IS_ALLPROP);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_close_propdb(propdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein dav_add_response(wres, 0, &propstats);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* handle the PROPFIND method */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_method_propfind(request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *resource;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int depth;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int result;
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_xml_doc *doc;
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein const ap_xml_elem *child;
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein dav_walker_ctx ctx = { { 0 } };
f94aab38f6ee899f463f0118ea395291f7c5b4cegstein dav_response *multi_status;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Ask repository module to resolve the resource */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein result = dav_get_resource(r, 1 /*target_allowed*/, NULL, &resource);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (result != OK)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (dav_get_resource_state(r, resource) == DAV_RESOURCE_NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Apache will supply a default error for this. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_NOT_FOUND;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((depth = dav_get_depth(r, DAV_INFINITY)) < 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* dav_get_depth() supplies additional information for the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * default message. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (depth == DAV_INFINITY) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_dir_conf *conf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein conf = (dav_dir_conf *) ap_get_module_config(r->per_dir_config,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &dav_module);
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* default is to DISALLOW these requests */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (conf->allow_depthinfinity != DAV_ENABLED_ON) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, HTTP_FORBIDDEN,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_psprintf(r->pool,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "PROPFIND requests with a "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Depth of \"infinity\" are "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "not allowed for %s.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_escape_html(r->pool,
f4c310fd2555c6faca1f980f00b161eadb089023gstein r->uri)));
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein if ((result = ap_xml_parse_input(r, &doc)) != OK) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* note: doc == NULL if no request body */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (doc && !dav_validate_root(doc, "propfind")) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* This supplies additional information for the default message. */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The \"propfind\" element was not found.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### validate that only one of these three elements is present */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (doc == NULL
f4c310fd2555c6faca1f980f00b161eadb089023gstein || (child = dav_find_child(doc->root, "allprop")) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* note: no request body implies allprop */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ctx.propfind_type = DAV_PROPFIND_IS_ALLPROP;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if ((child = dav_find_child(doc->root, "propname")) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ctx.propfind_type = DAV_PROPFIND_IS_PROPNAME;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if ((child = dav_find_child(doc->root, "prop")) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ctx.propfind_type = DAV_PROPFIND_IS_PROP;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* "propfind" element must have one of the above three children */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* This supplies additional information for the default message. */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The \"propfind\" element does not contain one of "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "the required child elements (the specific command).");
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein ctx.w.walk_type = DAV_WALKTYPE_NORMAL | DAV_WALKTYPE_AUTH;
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein ctx.w.func = dav_propfind_walker;
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein ctx.w.walk_ctx = &ctx;
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein ctx.w.pool = r->pool;
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein ctx.w.root = resource;
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ctx.doc = doc;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ctx.r = r;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### should open read-only */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein if ((err = dav_open_lockdb(r, 0, &ctx.w.lockdb)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, err->status, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The lock database could not be opened, "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "preventing access to the various lock "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "properties for the PROPFIND.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein if (ctx.w.lockdb != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* if we have a lock database, then we can walk locknull resources */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein ctx.w.walk_type |= DAV_WALKTYPE_LOCKNULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f94aab38f6ee899f463f0118ea395291f7c5b4cegstein err = (*resource->hooks->walk)(&ctx.w, depth, &multi_status);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein if (ctx.w.lockdb != NULL) {
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein (*ctx.w.lockdb->hooks->close_lockdb)(ctx.w.lockdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### add a higher-level description? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* return a 207 (Multi-Status) response now. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* if a 404 was generated for an HREF, then we need to spit out the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * doc's namespaces for use by the 404. Note that <response> elements
f4c310fd2555c6faca1f980f00b161eadb089023gstein * will override these ns0, ns1, etc, but NOT within the <response>
f4c310fd2555c6faca1f980f00b161eadb089023gstein * scope for the badprops. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* NOTE: propstat_404 != NULL implies doc != NULL */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ctx.propstat_404 != NULL) {
f94aab38f6ee899f463f0118ea395291f7c5b4cegstein dav_send_multistatus(r, HTTP_MULTI_STATUS, multi_status,
f4c310fd2555c6faca1f980f00b161eadb089023gstein doc->namespaces);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f94aab38f6ee899f463f0118ea395291f7c5b4cegstein dav_send_multistatus(r, HTTP_MULTI_STATUS, multi_status, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* the response has been sent. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DONE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic ap_text * dav_failed_proppatch(apr_pool_t *p,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_array_header_t *prop_ctx)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_text_header hdr = { 0 };
f4c310fd2555c6faca1f980f00b161eadb089023gstein int i = prop_ctx->nelts;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_prop_ctx *ctx = (dav_prop_ctx *)prop_ctx->elts;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err424_set = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err424_delete = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *s;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### might be nice to sort by status code and description */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein for ( ; i-- > 0; ++ctx ) {
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_text_append(p, &hdr,
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein "<D:propstat>" DEBUG_CR
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein "<D:prop>");
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_text_append(p, &hdr, ap_xml_empty_elem(p, ctx->prop));
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_text_append(p, &hdr, "</D:prop>" DEBUG_CR);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ctx->err == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* nothing was assigned here yet, so make it a 424 */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ctx->operation == DAV_PROP_OP_SET) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err424_set == NULL)
f4c310fd2555c6faca1f980f00b161eadb089023gstein err424_set = dav_new_error(p, HTTP_FAILED_DEPENDENCY, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Attempted DAV:set operation "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "could not be completed due "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "to other errors.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein ctx->err = err424_set;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (ctx->operation == DAV_PROP_OP_DELETE) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err424_delete == NULL)
f4c310fd2555c6faca1f980f00b161eadb089023gstein err424_delete = dav_new_error(p, HTTP_FAILED_DEPENDENCY, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Attempted DAV:remove "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "operation could not be "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "completed due to other "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "errors.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein ctx->err = err424_delete;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm s = apr_psprintf(p,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "<D:status>"
f4c310fd2555c6faca1f980f00b161eadb089023gstein "HTTP/1.1 %d (status)"
f4c310fd2555c6faca1f980f00b161eadb089023gstein "</D:status>" DEBUG_CR,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ctx->err->status);
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_text_append(p, &hdr, s);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### we should use compute_desc if necessary... */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ctx->err->desc != NULL) {
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_text_append(p, &hdr, "<D:responsedescription>" DEBUG_CR);
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_text_append(p, &hdr, ctx->err->desc);
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_text_append(p, &hdr, "</D:responsedescription>" DEBUG_CR);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_text_append(p, &hdr, "</D:propstat>" DEBUG_CR);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return hdr.first;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic ap_text * dav_success_proppatch(apr_pool_t *p, apr_array_header_t *prop_ctx)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_text_header hdr = { 0 };
f4c310fd2555c6faca1f980f00b161eadb089023gstein int i = prop_ctx->nelts;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_prop_ctx *ctx = (dav_prop_ctx *)prop_ctx->elts;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### we probably need to revise the way we assemble the response...
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### this code assumes everything will return status==200.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_text_append(p, &hdr,
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein "<D:propstat>" DEBUG_CR
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein "<D:prop>" DEBUG_CR);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein for ( ; i-- > 0; ++ctx ) {
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_text_append(p, &hdr, ap_xml_empty_elem(p, ctx->prop));
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_text_append(p, &hdr,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "</D:prop>" DEBUG_CR
f4c310fd2555c6faca1f980f00b161eadb089023gstein "<D:status>HTTP/1.1 200 OK</D:status>" DEBUG_CR
f4c310fd2555c6faca1f980f00b161eadb089023gstein "</D:propstat>" DEBUG_CR);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return hdr.first;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic void dav_prop_log_errors(dav_prop_ctx *ctx)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_log_err(ctx->r, ctx->err, APLOG_ERR);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
f4c310fd2555c6faca1f980f00b161eadb089023gstein** Call <func> for each context. This can stop when an error occurs, or
f4c310fd2555c6faca1f980f00b161eadb089023gstein** simply iterate through the whole list.
f4c310fd2555c6faca1f980f00b161eadb089023gstein**
f4c310fd2555c6faca1f980f00b161eadb089023gstein** Returns 1 if an error occurs (and the iteration is aborted). Returns 0
f4c310fd2555c6faca1f980f00b161eadb089023gstein** if all elements are processed.
f4c310fd2555c6faca1f980f00b161eadb089023gstein**
f4c310fd2555c6faca1f980f00b161eadb089023gstein** If <reverse> is true (non-zero), then the list is traversed in
f4c310fd2555c6faca1f980f00b161eadb089023gstein** reverse order.
f4c310fd2555c6faca1f980f00b161eadb089023gstein*/
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_process_ctx_list(void (*func)(dav_prop_ctx *ctx),
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_array_header_t *ctx_list, int stop_on_error,
f4c310fd2555c6faca1f980f00b161eadb089023gstein int reverse)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein int i = ctx_list->nelts;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_prop_ctx *ctx = (dav_prop_ctx *)ctx_list->elts;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (reverse)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ctx += i;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (i--) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (reverse)
f4c310fd2555c6faca1f980f00b161eadb089023gstein --ctx;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein (*func)(ctx);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (stop_on_error && DAV_PROP_CTX_HAS_ERR(*ctx)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!reverse)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ++ctx;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* handle the PROPPATCH method */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_method_proppatch(request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *resource;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int result;
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_xml_doc *doc;
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_xml_elem *child;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_propdb *propdb;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int failure = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_response resp = { 0 };
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_text *propstat_text;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_array_header_t *ctx_list;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_prop_ctx *ctx;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Ask repository module to resolve the resource */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein result = dav_get_resource(r, 0 /*target_allowed*/, NULL, &resource);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (result != OK)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->exists) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Apache will supply a default error for this. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_NOT_FOUND;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein if ((result = ap_xml_parse_input(r, &doc)) != OK) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* note: doc == NULL if no request body */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (doc == NULL || !dav_validate_root(doc, "propertyupdate")) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* This supplies additional information for the default message. */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The request body does not contain "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "a \"propertyupdate\" element.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Check If-Headers and existing locks */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Note: depth == 0. Implies no need for a multistatus response. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_validate_request(r, resource, 0, NULL, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein DAV_VALIDATE_RESOURCE, NULL)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### add a higher-level description? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_open_propdb(r, NULL, resource, 0, doc->namespaces,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &propdb)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_psprintf(r->pool,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Could not open the property "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "database for %s.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_escape_html(r->pool, r->uri)),
f4c310fd2555c6faca1f980f00b161eadb089023gstein err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### what to do about closing the propdb on server failure? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### validate "live" properties */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* set up an array to hold property operation contexts */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm ctx_list = apr_make_array(r->pool, 10, sizeof(dav_prop_ctx));
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* do a first pass to ensure that all "remove" properties exist */
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (child = doc->root->first_child; child; child = child->next) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein int is_remove;
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_xml_elem *prop_group;
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein ap_xml_elem *one_prop;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Ignore children that are not set/remove */
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein if (child->ns != AP_XML_NS_DAV_ID
f4c310fd2555c6faca1f980f00b161eadb089023gstein || (!(is_remove = strcmp(child->name, "remove") == 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein && strcmp(child->name, "set") != 0)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein continue;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* make sure that a "prop" child exists for set/remove */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((prop_group = dav_find_child(child, "prop")) == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_close_propdb(propdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* This supplies additional information for the default message. */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "A \"prop\" element is missing inside "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "the propertyupdate command.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (one_prop = prop_group->first_child; one_prop;
f4c310fd2555c6faca1f980f00b161eadb089023gstein one_prop = one_prop->next) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm ctx = (dav_prop_ctx *)apr_push_array(ctx_list);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ctx->propdb = propdb;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ctx->operation = is_remove ? DAV_PROP_OP_DELETE : DAV_PROP_OP_SET;
f4c310fd2555c6faca1f980f00b161eadb089023gstein ctx->prop = one_prop;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ctx->r = r; /* for later use by dav_prop_log_errors() */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_prop_validate(ctx);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ( DAV_PROP_CTX_HAS_ERR(*ctx) ) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein failure = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### should test that we found at least one set/remove */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* execute all of the operations */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!failure && dav_process_ctx_list(dav_prop_exec, ctx_list, 1, 0)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein failure = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* generate a failure/success response */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (failure) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein (void)dav_process_ctx_list(dav_prop_rollback, ctx_list, 0, 1);
f4c310fd2555c6faca1f980f00b161eadb089023gstein propstat_text = dav_failed_proppatch(r->pool, ctx_list);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein (void)dav_process_ctx_list(dav_prop_commit, ctx_list, 0, 0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein propstat_text = dav_success_proppatch(r->pool, ctx_list);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* make sure this gets closed! */
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_close_propdb(propdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* log any errors that occurred */
f4c310fd2555c6faca1f980f00b161eadb089023gstein (void)dav_process_ctx_list(dav_prop_log_errors, ctx_list, 0, 0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein resp.href = resource->uri;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### should probably use something new to pass along this text... */
f4c310fd2555c6faca1f980f00b161eadb089023gstein resp.propresult.propstats = propstat_text;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_send_multistatus(r, HTTP_MULTI_STATUS, &resp, doc->namespaces);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* the response has been sent. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DONE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int process_mkcol_body(request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* This is snarfed from ap_setup_client_block(). We could get pretty
f4c310fd2555c6faca1f980f00b161eadb089023gstein * close to this behavior by passing REQUEST_NO_BODY, but we need to
f4c310fd2555c6faca1f980f00b161eadb089023gstein * return HTTP_UNSUPPORTED_MEDIA_TYPE (while ap_setup_client_block
f4c310fd2555c6faca1f980f00b161eadb089023gstein * returns HTTP_REQUEST_ENTITY_TOO_LARGE). */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm const char *tenc = apr_table_get(r->headers_in, "Transfer-Encoding");
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm const char *lenp = apr_table_get(r->headers_in, "Content-Length");
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* make sure to set the Apache request fields properly. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein r->read_body = REQUEST_NO_BODY;
f4c310fd2555c6faca1f980f00b161eadb089023gstein r->read_chunked = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein r->remaining = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (tenc) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (strcasecmp(tenc, "chunked")) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Use this instead of Apache's default error string */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Unknown Transfer-Encoding %s", tenc);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_NOT_IMPLEMENTED;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein r->read_chunked = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (lenp) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *pos = lenp;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
10a4cdd68ef1ca0e54af296fe1d08ac00150c90bwrowe while (apr_isdigit(*pos) || apr_isspace(*pos)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ++pos;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (*pos != '\0') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* This supplies additional information for the default message. */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Invalid Content-Length %s", lenp);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein r->remaining = atol(lenp);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->read_chunked || r->remaining > 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### log something? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Apache will supply a default error for this. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_UNSUPPORTED_MEDIA_TYPE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Get rid of the body. this will call ap_setup_client_block(), but
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** our copy above has already verified its work.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return ap_discard_request_body(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* handle the MKCOL method */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_method_mkcol(request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *resource;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int resource_state;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein dav_auto_version_info av_info;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const dav_hooks_locks *locks_hooks = DAV_GET_HOOKS_LOCKS(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err2;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_dir_conf *conf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_response *multi_status;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* handle the request body */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### this may move lower once we start processing bodies */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((result = process_mkcol_body(r)) != OK) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein conf = (dav_dir_conf *) ap_get_module_config(r->per_dir_config,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &dav_module);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Ask repository module to resolve the resource */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein result = dav_get_resource(r, 0 /*target_allowed*/, NULL, &resource);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (result != OK)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resource->exists) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* oops. something was already there! */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Apache will supply a default error for this. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### we should provide a specific error message! */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_METHOD_NOT_ALLOWED;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein resource_state = dav_get_resource_state(r, resource);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Check If-Headers and existing locks.
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Note: depth == 0 normally requires no multistatus response. However,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** if we pass DAV_VALIDATE_PARENT, then we could get an error on a URI
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** other than the Request-URI, thereby requiring a multistatus.
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** If the resource does not exist (DAV_RESOURCE_NULL), then we must
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** check the resource *and* its parent. If the resource exists or is
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** a locknull resource, then we check only the resource.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_validate_request(r, resource, 0, NULL, &multi_status,
f4c310fd2555c6faca1f980f00b161eadb089023gstein resource_state == DAV_RESOURCE_NULL ?
f4c310fd2555c6faca1f980f00b161eadb089023gstein DAV_VALIDATE_PARENT :
f4c310fd2555c6faca1f980f00b161eadb089023gstein DAV_VALIDATE_RESOURCE, NULL)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### add a higher-level description? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, multi_status);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* if versioned resource, make sure parent is checked out */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_ensure_resource_writable(r, resource, 1 /* parent_only */,
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein &av_info)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### add a higher-level description? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* try to create the collection */
f4c310fd2555c6faca1f980f00b161eadb089023gstein resource->collection = 1;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein err = (*resource->hooks->create_collection)(resource);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* restore modifiability of parent back to what it was */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein err2 = dav_revert_resource_writability(r, NULL, err != NULL /* undo if error */,
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein &av_info);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* check for errors now */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err2 != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* just log a warning */
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, err->status, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The MKCOL was successful, but there "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "was a problem reverting the writability of "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "its parent collection.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein err2);
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_log_err(r, err, APLOG_WARNING);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (locks_hooks != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_lockdb *lockdb;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = (*locks_hooks->open_lockdb)(r, 0, 0, &lockdb)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* The directory creation was successful, but the locking failed. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, err->status, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The MKCOL was successful, but there "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "was a problem opening the lock database "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "which prevents inheriting locks from the "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "parent resources.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* notify lock system that we have created/replaced a resource */
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_notify_created(r, lockdb, resource, resource_state, 0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein (*locks_hooks->close_lockdb)(lockdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* The dir creation was successful, but the locking failed. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, err->status, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The MKCOL was successful, but there "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "was a problem updating its lock "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "information.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* return an appropriate response (HTTP_CREATED) */
50bd75672ef114fb839dd9643c192b432fdf344cgstein return dav_created(r, NULL, "Collection", 0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* handle the COPY and MOVE methods */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_method_copymove(request_rec *r, int is_move)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *resource;
f958dac1550254a59b45f4655138bb34dad5e76egstein dav_auto_version_info src_av_info = { 0 };
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *resnew;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein dav_auto_version_info dst_av_info;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *body;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *dest;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err2;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err3;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_response *multi_response;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_lookup_result lookup;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int is_dir;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int overwrite;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int depth;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_lockdb *lockdb;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int replaced;
4b28d4385b48010bc271cba9b40b56e458cbd5d8keith int resource_state;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Ask repository module to resolve the resource */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein result = dav_get_resource(r, !is_move /*target_allowed*/, NULL, &resource);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (result != OK)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->exists) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Apache will supply a default error for this. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_NOT_FOUND;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* If not a file or collection resource, COPY/MOVE not allowed */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resource->type != DAV_RESOURCE_TYPE_REGULAR) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm body = apr_psprintf(r->pool,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Cannot COPY/MOVE resource %s.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_escape_html(r->pool, r->uri));
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, HTTP_METHOD_NOT_ALLOWED, body);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* get the destination URI */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm dest = apr_table_get(r->headers_in, "Destination");
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (dest == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Look in headers provided by Netscape's Roaming Profiles */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm const char *nscp_host = apr_table_get(r->headers_in, "Host");
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm const char *nscp_path = apr_table_get(r->headers_in, "New-uri");
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (nscp_host != NULL && nscp_path != NULL)
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm dest = apr_psprintf(r->pool, "http://%s%s", nscp_host, nscp_path);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (dest == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* This supplies additional information for the default message. */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The request is missing a Destination header.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein lookup = dav_lookup_uri(dest, r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (lookup.rnew == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (lookup.err.status == HTTP_BAD_REQUEST) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* This supplies additional information for the default message. */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein lookup.err.desc);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### this assumes that dav_lookup_uri() only generates a status
f4c310fd2555c6faca1f980f00b161eadb089023gstein * ### that Apache can provide a status line for!! */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, lookup.err.status, lookup.err.desc);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (lookup.rnew->status != HTTP_OK) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### how best to report this... */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, lookup.rnew->status,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Destination URI had an error.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Resolve destination resource */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein result = dav_get_resource(lookup.rnew, 0 /*target_allowed*/, NULL, &resnew);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (result != OK)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* are the two resources handled by the same repository? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resource->hooks != resnew->hooks) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### this message exposes some backend config, but screw it... */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, HTTP_BAD_GATEWAY,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Destination URI is handled by a "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "different repository than the source URI. "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "MOVE or COPY between repositories is "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "not possible.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* get and parse the overwrite header value */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((overwrite = dav_get_overwrite(r)) < 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* dav_get_overwrite() supplies additional information for the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * default message. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* quick failure test: if dest exists and overwrite is false. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resnew->exists && !overwrite) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Supply some text for the error response body. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, HTTP_PRECONDITION_FAILED,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Destination is not empty and "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Overwrite is not \"T\"");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* are the source and destination the same? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((*resource->hooks->is_same_resource)(resource, resnew)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Supply some text for the error response body. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, HTTP_FORBIDDEN,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Source and Destination URIs are the same.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein is_dir = resource->collection;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* get and parse the Depth header value. "0" and "infinity" are legal. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((depth = dav_get_depth(r, DAV_INFINITY)) < 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* dav_get_depth() supplies additional information for the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * default message. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (depth == 1) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* This supplies additional information for the default message. */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Depth must be \"0\" or \"infinity\" for COPY or MOVE.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (is_move && is_dir && depth != DAV_INFINITY) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* This supplies additional information for the default message. */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Depth must be \"infinity\" when moving a collection.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Check If-Headers and existing locks for each resource in the source
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** if we are performing a MOVE. We will return a 424 response with a
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** DAV:multistatus body. The multistatus responses will contain the
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** information about any resource that fails the validation.
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** We check the parent resource, too, since this is a MOVE. Moving the
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** resource effectively removes it from the parent collection, so we
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** must ensure that we have met the appropriate conditions.
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** If a problem occurs with the Request-URI itself, then a plain error
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** (rather than a multistatus) will be returned.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (is_move
f4c310fd2555c6faca1f980f00b161eadb089023gstein && (err = dav_validate_request(r, resource, depth, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &multi_response,
f4c310fd2555c6faca1f980f00b161eadb089023gstein DAV_VALIDATE_PARENT
f4c310fd2555c6faca1f980f00b161eadb089023gstein | DAV_VALIDATE_USE_424,
f4c310fd2555c6faca1f980f00b161eadb089023gstein NULL)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, err->status, 0,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_psprintf(r->pool,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Could not MOVE %s due to a failed "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "precondition on the source "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "(e.g. locks).",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_escape_html(r->pool, r->uri)),
f4c310fd2555c6faca1f980f00b161eadb089023gstein err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, multi_response);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Check If-Headers and existing locks for destination. Note that we
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** use depth==infinity since the target (hierarchy) will be deleted
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** before the move/copy is completed.
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Note that we are overwriting the target, which implies a DELETE, so
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** we are subject to the error/response rules as a DELETE. Namely, we
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** will return a 424 error if any of the validations fail.
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** (see dav_method_delete() for more information)
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_validate_request(lookup.rnew, resnew, DAV_INFINITY, NULL,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &multi_response,
f4c310fd2555c6faca1f980f00b161eadb089023gstein DAV_VALIDATE_PARENT
f4c310fd2555c6faca1f980f00b161eadb089023gstein | DAV_VALIDATE_USE_424, NULL)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, err->status, 0,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_psprintf(r->pool,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Could not MOVE/COPY %s due to a "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "failed precondition on the "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "destination (e.g. locks).",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_escape_html(r->pool, r->uri)),
f4c310fd2555c6faca1f980f00b161eadb089023gstein err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, multi_response);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (is_dir
f4c310fd2555c6faca1f980f00b161eadb089023gstein && depth == DAV_INFINITY
f4c310fd2555c6faca1f980f00b161eadb089023gstein && (*resource->hooks->is_parent_resource)(resource, resnew)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Supply some text for the error response body. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, HTTP_FORBIDDEN,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Source collection contains the "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Destination.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (is_dir
f4c310fd2555c6faca1f980f00b161eadb089023gstein && (*resnew->hooks->is_parent_resource)(resnew, resource)) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* The destination must exist (since it contains the source), and
f4c310fd2555c6faca1f980f00b161eadb089023gstein * a condition above implies Overwrite==T. Obviously, we cannot
f4c310fd2555c6faca1f980f00b161eadb089023gstein * delete the Destination before the MOVE/COPY, as that would
f4c310fd2555c6faca1f980f00b161eadb089023gstein * delete the Source.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Supply some text for the error response body. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, HTTP_FORBIDDEN,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Destination collection contains the Source "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "and Overwrite has been specified.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### for now, we don't need anything in the body */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((result = ap_discard_request_body(r)) != OK) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_open_lockdb(r, 0, &lockdb)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### add a higher-level description? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* remove any locks from the old resources */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### this is Yet Another Traversal. if we do a rename(), then we
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### really don't have to do this in some cases since the inode
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### values will remain constant across the move. but we can't
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### know that fact from outside the provider :-(
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### note that we now have a problem atomicity in the move/copy
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### since a failure after this would have removed locks (technically,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### this is okay to do, but really...)
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (is_move && lockdb != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### this is wrong! it blasts direct locks on parent resources */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### pass lockdb! */
f4c310fd2555c6faca1f980f00b161eadb089023gstein (void)dav_unlock(r, resource, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* remember whether target resource existed */
f4c310fd2555c6faca1f980f00b161eadb089023gstein replaced = resnew->exists;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* if this is a move, then the source parent collection will be modified */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (is_move) {
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein if ((err = dav_ensure_resource_writable(r, resource, 1 /* parent_only */,
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein &src_av_info)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (lockdb != NULL)
f4c310fd2555c6faca1f980f00b161eadb089023gstein (*lockdb->hooks->close_lockdb)(lockdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### add a higher-level description? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* prepare the destination collection for modification */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_ensure_resource_writable(r, resnew, 1 /* parent_only */,
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein &dst_av_info)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* could not make destination writable:
f4c310fd2555c6faca1f980f00b161eadb089023gstein * if move, restore state of source parent
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (is_move) {
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein (void) dav_revert_resource_writability(r, NULL, 1 /* undo */,
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein &src_av_info);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (lockdb != NULL)
f4c310fd2555c6faca1f980f00b161eadb089023gstein (*lockdb->hooks->close_lockdb)(lockdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### add a higher-level description? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* If source and destination parents are the same, then
f4c310fd2555c6faca1f980f00b161eadb089023gstein * use the same object, so status updates to one are reflected
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein * in the other, when reverting their writable states.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein if (src_av_info.parent_resource != NULL
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein && (*src_av_info.parent_resource->hooks->is_same_resource)
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein (src_av_info.parent_resource, dst_av_info.parent_resource)) {
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein dst_av_info.parent_resource = src_av_info.parent_resource;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* New resource will be same kind as source */
f4c310fd2555c6faca1f980f00b161eadb089023gstein resnew->collection = resource->collection;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
4b28d4385b48010bc271cba9b40b56e458cbd5d8keith resource_state = dav_get_resource_state(lookup.rnew, resnew);
4b28d4385b48010bc271cba9b40b56e458cbd5d8keith
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* If target exists, remove it first (we know Ovewrite must be TRUE).
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Then try to copy/move the resource.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resnew->exists)
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = (*resnew->hooks->remove_resource)(resnew, &multi_response);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (is_move)
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = (*resource->hooks->move_resource)(resource, resnew,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &multi_response);
f4c310fd2555c6faca1f980f00b161eadb089023gstein else
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = (*resource->hooks->copy_resource)(resource, resnew, depth,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &multi_response);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* restore parent collection states */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein err2 = dav_revert_resource_writability(r, NULL, err != NULL /* undo if error */,
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein &dst_av_info);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (is_move) {
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein err3 = dav_revert_resource_writability(r, NULL, err != NULL /* undo if error */,
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein &src_av_info);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else
f4c310fd2555c6faca1f980f00b161eadb089023gstein err3 = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* check for error from remove/copy/move operations */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (lockdb != NULL)
f4c310fd2555c6faca1f980f00b161eadb089023gstein (*lockdb->hooks->close_lockdb)(lockdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, err->status, 0,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_psprintf(r->pool,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Could not MOVE/COPY %s.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_escape_html(r->pool, r->uri)),
f4c310fd2555c6faca1f980f00b161eadb089023gstein err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, multi_response);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* check for errors from reverting writability */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err2 != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* just log a warning */
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, err2->status, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The MOVE/COPY was successful, but there was a "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "problem reverting the writability of the "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "source parent collection.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein err2);
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_log_err(r, err, APLOG_WARNING);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err3 != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* just log a warning */
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, err3->status, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The MOVE/COPY was successful, but there was a "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "problem reverting the writability of the "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "destination parent collection.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein err3);
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_log_err(r, err, APLOG_WARNING);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* propagate any indirect locks at the target */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (lockdb != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* notify lock system that we have created/replaced a resource */
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_notify_created(r, lockdb, resnew, resource_state, depth);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein (*lockdb->hooks->close_lockdb)(lockdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* The move/copy was successful, but the locking failed. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, err->status, 0,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The MOVE/COPY was successful, but there "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "was a problem updating the lock "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "information.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* return an appropriate response (HTTP_CREATED or HTTP_NO_CONTENT) */
50bd75672ef114fb839dd9643c192b432fdf344cgstein return dav_created(r, lookup.rnew->uri, "Destination", replaced);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* dav_method_lock: Handler to implement the DAV LOCK method
f4c310fd2555c6faca1f980f00b161eadb089023gstein** Returns appropriate HTTP_* response.
f4c310fd2555c6faca1f980f00b161eadb089023gstein*/
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_method_lock(request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *resource;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const dav_hooks_locks *locks_hooks;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int depth;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int new_lock_request = 0;
50bd75672ef114fb839dd9643c192b432fdf344cgstein ap_xml_doc *doc;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_lock *lock;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_response *multi_response = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_lockdb *lockdb;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int resource_state;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* If no locks provider, decline the request */
f4c310fd2555c6faca1f980f00b161eadb089023gstein locks_hooks = DAV_GET_HOOKS_LOCKS(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (locks_hooks == NULL)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DECLINED;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein if ((result = ap_xml_parse_input(r, &doc)) != OK)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein depth = dav_get_depth(r, DAV_INFINITY);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (depth != 0 && depth != DAV_INFINITY) {
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Depth must be 0 or \"infinity\" for LOCK.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein /* Ask repository module to resolve the resource.
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein * DeltaV says result of target selector is undefined,
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein * so allow it, and let provider reject the lock attempt
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein * on a version if it wants to.
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein result = dav_get_resource(r, 1 /*target_allowed*/, NULL, &resource);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (result != OK)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Open writable. Unless an error occurs, we'll be
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** writing into the database.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = (*locks_hooks->open_lockdb)(r, 0, 0, &lockdb)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### add a higher-level description? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (doc != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_lock_parse_lockinfo(r, resource, lockdb, doc,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &lock)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### add a higher-level description to err? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein goto error;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein new_lock_request = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm lock->auth_user = apr_pstrdup(r->pool, r->user);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein resource_state = dav_get_resource_state(r, resource);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Check If-Headers and existing locks.
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** If this will create a locknull resource, then the LOCK will affect
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** the parent collection (much like a PUT/MKCOL). For that case, we must
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** validate the parent resource's conditions.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_validate_request(r, resource, depth, NULL, &multi_response,
f4c310fd2555c6faca1f980f00b161eadb089023gstein (resource_state == DAV_RESOURCE_NULL
f4c310fd2555c6faca1f980f00b161eadb089023gstein ? DAV_VALIDATE_PARENT
f4c310fd2555c6faca1f980f00b161eadb089023gstein : DAV_VALIDATE_RESOURCE)
f4c310fd2555c6faca1f980f00b161eadb089023gstein | (new_lock_request ? lock->scope : 0)
f4c310fd2555c6faca1f980f00b161eadb089023gstein | DAV_VALIDATE_ADD_LD,
f4c310fd2555c6faca1f980f00b161eadb089023gstein lockdb)) != OK) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, err->status, 0,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_psprintf(r->pool,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Could not LOCK %s due to a failed "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "precondition (e.g. other locks).",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_escape_html(r->pool, r->uri)),
f4c310fd2555c6faca1f980f00b161eadb089023gstein err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein goto error;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (new_lock_request == 0) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_locktoken_list *ltl;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Refresh request
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### Assumption: We can renew multiple locks on the same resource
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### at once. First harvest all the positive lock-tokens given in
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### the If header. Then modify the lock entries for this resource
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### with the new Timeout val.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_get_locktoken_list(r, &ltl)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, err->status, 0,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_psprintf(r->pool,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The lock refresh for %s failed "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "because no lock tokens were "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "specified in an \"If:\" "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "header.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_escape_html(r->pool, r->uri)),
f4c310fd2555c6faca1f980f00b161eadb089023gstein err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein goto error;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = (*locks_hooks->refresh_locks)(lockdb, resource, ltl,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_get_timeout(r),
f4c310fd2555c6faca1f980f00b161eadb089023gstein &lock)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### add a higher-level description to err? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein goto error;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein } else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* New lock request */
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *locktoken_txt;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_dir_conf *conf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein conf = (dav_dir_conf *) ap_get_module_config(r->per_dir_config,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &dav_module);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* apply lower bound (if any) from DAVMinTimeout directive */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (lock->timeout != DAV_TIMEOUT_INFINITE
f4c310fd2555c6faca1f980f00b161eadb089023gstein && lock->timeout < time(NULL) + conf->locktimeout)
f4c310fd2555c6faca1f980f00b161eadb089023gstein lock->timeout = time(NULL) + conf->locktimeout;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_add_lock(r, resource, lockdb, lock, &multi_response);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### add a higher-level description to err? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein goto error;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm locktoken_txt = apr_pstrcat(r->pool, "<",
f4c310fd2555c6faca1f980f00b161eadb089023gstein (*locks_hooks->format_locktoken)(r->pool, lock->locktoken),
f4c310fd2555c6faca1f980f00b161eadb089023gstein ">", NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_table_set(r->headers_out, "Lock-Token", locktoken_txt);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein (*locks_hooks->close_lockdb)(lockdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein r->status = HTTP_OK;
f4c310fd2555c6faca1f980f00b161eadb089023gstein r->content_type = DAV_XML_CONTENT_TYPE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_send_http_header(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rputs(DAV_XML_HEADER DEBUG_CR "<D:prop xmlns:D=\"DAV:\">" DEBUG_CR, r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (lock == NULL)
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rputs("<D:lockdiscovery/>" DEBUG_CR, r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rprintf(r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "<D:lockdiscovery>" DEBUG_CR
f4c310fd2555c6faca1f980f00b161eadb089023gstein "%s" DEBUG_CR
f4c310fd2555c6faca1f980f00b161eadb089023gstein "</D:lockdiscovery>" DEBUG_CR,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_lock_get_activelock(r, lock, NULL));
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rputs("</D:prop>", r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* the response has been sent. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DONE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein error:
f4c310fd2555c6faca1f980f00b161eadb089023gstein (*locks_hooks->close_lockdb)(lockdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, multi_response);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* dav_method_unlock: Handler to implement the DAV UNLOCK method
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Returns appropriate HTTP_* response.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_method_unlock(request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *resource;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const dav_hooks_locks *locks_hooks;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *const_locktoken_txt;
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *locktoken_txt;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_locktoken *locktoken = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int resource_state;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_response *multi_response;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* If no locks provider, decline the request */
f4c310fd2555c6faca1f980f00b161eadb089023gstein locks_hooks = DAV_GET_HOOKS_LOCKS(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (locks_hooks == NULL)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DECLINED;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm if ((const_locktoken_txt = apr_table_get(r->headers_in, "Lock-Token")) == NULL) {
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Unlock failed (%s): No Lock-Token specified in header", r->filename);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm locktoken_txt = apr_pstrdup(r->pool, const_locktoken_txt);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (locktoken_txt[0] != '<') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### should provide more specifics... */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein locktoken_txt++;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (locktoken_txt[strlen(locktoken_txt) - 1] != '>') {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### should provide more specifics... */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein locktoken_txt[strlen(locktoken_txt) - 1] = '\0';
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = (*locks_hooks->parse_locktoken)(r->pool, locktoken_txt,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &locktoken)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, HTTP_BAD_REQUEST, 0,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_psprintf(r->pool,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The UNLOCK on %s failed -- an "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "invalid lock token was specified "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "in the \"If:\" header.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_escape_html(r->pool, r->uri)),
f4c310fd2555c6faca1f980f00b161eadb089023gstein err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein /* Ask repository module to resolve the resource.
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein * DeltaV says result of target selector is undefined,
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein * so allow it, and let provider reject the unlock attempt
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein * on a version if it wants to.
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein result = dav_get_resource(r, 1 /*target_allowed*/, NULL, &resource);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (result != OK)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein resource_state = dav_get_resource_state(r, resource);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Check If-Headers and existing locks.
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** Note: depth == 0 normally requires no multistatus response. However,
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** if we pass DAV_VALIDATE_PARENT, then we could get an error on a URI
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** other than the Request-URI, thereby requiring a multistatus.
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** If the resource is a locknull resource, then the UNLOCK will affect
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** the parent collection (much like a delete). For that case, we must
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** validate the parent resource's conditions.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_validate_request(r, resource, 0, locktoken,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &multi_response,
f4c310fd2555c6faca1f980f00b161eadb089023gstein resource_state == DAV_RESOURCE_LOCK_NULL
f4c310fd2555c6faca1f980f00b161eadb089023gstein ? DAV_VALIDATE_PARENT
f4c310fd2555c6faca1f980f00b161eadb089023gstein : DAV_VALIDATE_RESOURCE, NULL)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### add a higher-level description? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, multi_response);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### RFC 2518 s. 8.11: If this resource is locked by locktoken,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * _all_ resources locked by locktoken are released. It does not say
f4c310fd2555c6faca1f980f00b161eadb089023gstein * resource has to be the root of an infinte lock. Thus, an UNLOCK
f4c310fd2555c6faca1f980f00b161eadb089023gstein * on any part of an infinte lock will remove the lock on all resources.
f4c310fd2555c6faca1f980f00b161eadb089023gstein *
f4c310fd2555c6faca1f980f00b161eadb089023gstein * For us, if r->filename represents an indirect lock (part of an infinity lock),
f4c310fd2555c6faca1f980f00b161eadb089023gstein * we must actually perform an UNLOCK on the direct lock for this resource.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((result = dav_unlock(r, resource, locktoken)) != OK) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_NO_CONTENT;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
50bd75672ef114fb839dd9643c192b432fdf344cgsteinstatic int dav_method_vsn_control(request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_resource *resource;
7281ea331999debdc337b02ce37a3169e0e033a2gstein int resource_state;
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_auto_version_info av_info;
7281ea331999debdc337b02ce37a3169e0e033a2gstein const dav_hooks_locks *locks_hooks = DAV_GET_HOOKS_LOCKS(r);
7281ea331999debdc337b02ce37a3169e0e033a2gstein const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_error *err;
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_xml_doc *doc;
7281ea331999debdc337b02ce37a3169e0e033a2gstein const char *target = NULL;
7281ea331999debdc337b02ce37a3169e0e033a2gstein int result;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* if no versioning provider, decline the request */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (vsn_hooks == NULL)
7281ea331999debdc337b02ce37a3169e0e033a2gstein return DECLINED;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* ask repository module to resolve the resource */
7281ea331999debdc337b02ce37a3169e0e033a2gstein result = dav_get_resource(r, 0 /*target_allowed*/, NULL, &resource);
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (result != OK)
7281ea331999debdc337b02ce37a3169e0e033a2gstein return result;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* remember the pre-creation resource state */
7281ea331999debdc337b02ce37a3169e0e033a2gstein resource_state = dav_get_resource_state(r, resource);
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* parse the request body (may be a version-control element) */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((result = ap_xml_parse_input(r, &doc)) != OK) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein return result;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* note: doc == NULL if no request body */
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (doc != NULL) {
1d69b25dcd7ca16cd3ee662bf768ffb1d36c46b6gstein const ap_xml_elem *child;
1d69b25dcd7ca16cd3ee662bf768ffb1d36c46b6gstein apr_size_t tsize;
1d69b25dcd7ca16cd3ee662bf768ffb1d36c46b6gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (!dav_validate_root(doc, "version-control")) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "The request body does not contain "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "a \"version-control\" element.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* get the version URI */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((child = dav_find_child(doc->root, "version")) == NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "The \"version-control\" element does not contain "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "a \"version\" element.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((child = dav_find_child(child, "href")) == NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "The \"version\" element does not contain "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "an \"href\" element.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* get version URI */
1d69b25dcd7ca16cd3ee662bf768ffb1d36c46b6gstein ap_xml_to_text(r->pool, child, AP_XML_X2T_INNER, NULL, NULL,
1d69b25dcd7ca16cd3ee662bf768ffb1d36c46b6gstein &target, &tsize);
1d69b25dcd7ca16cd3ee662bf768ffb1d36c46b6gstein if (tsize == 0) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "An \"href\" element does not contain a URI.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* Check request preconditions */
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* ### need a general mechanism for reporting precondition violations
7281ea331999debdc337b02ce37a3169e0e033a2gstein * ### (should be returning XML document for 403/409 responses)
7281ea331999debdc337b02ce37a3169e0e033a2gstein */
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* if not versioning existing resource, must specify version to select */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (!resource->exists && target == NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_new_error(r->pool, HTTP_CONFLICT, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "<DAV:initial-version-required/>");
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_handle_err(r, err, NULL);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein else if (resource->exists) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* cannot add resource to existing version history */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (target != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_new_error(r->pool, HTTP_CONFLICT, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "<DAV:cannot-add-to-existing-history/>");
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_handle_err(r, err, NULL);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* resource must be unversioned and versionable, or version selector */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (resource->type != DAV_RESOURCE_TYPE_REGULAR
7281ea331999debdc337b02ce37a3169e0e033a2gstein || (!resource->versioned && !(vsn_hooks->versionable)(resource))) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_new_error(r->pool, HTTP_CONFLICT, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "<DAV:must-be-versionable/>");
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_handle_err(r, err, NULL);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* the DeltaV spec says if resource is a version selector,
7281ea331999debdc337b02ce37a3169e0e033a2gstein * then VERSION-CONTROL is a no-op
7281ea331999debdc337b02ce37a3169e0e033a2gstein */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (resource->versioned) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* set the Cache-Control header, per the spec */
7281ea331999debdc337b02ce37a3169e0e033a2gstein apr_table_setn(r->headers_out, "Cache-Control", "no-cache");
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* no body */
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_set_content_length(r, 0);
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_send_http_header(r);
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein return DONE;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* Check If-Headers and existing locks */
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* Note: depth == 0. Implies no need for a multistatus response. */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((err = dav_validate_request(r, resource, 0, NULL, NULL,
7281ea331999debdc337b02ce37a3169e0e033a2gstein resource_state == DAV_RESOURCE_NULL ?
7281ea331999debdc337b02ce37a3169e0e033a2gstein DAV_VALIDATE_PARENT :
7281ea331999debdc337b02ce37a3169e0e033a2gstein DAV_VALIDATE_RESOURCE, NULL)) != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_handle_err(r, err, NULL);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* if in versioned collection, make sure parent is checked out */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((err = dav_ensure_resource_writable(r, resource, 1 /* parent_only */,
7281ea331999debdc337b02ce37a3169e0e033a2gstein &av_info)) != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_handle_err(r, err, NULL);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* attempt to version-control the resource */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((err = (*vsn_hooks->vsn_control)(resource, target)) != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_revert_resource_writability(r, resource, 1 /*undo*/, &av_info);
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_push_error(r->pool, HTTP_CONFLICT, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein apr_psprintf(r->pool,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "Could not VERSION-CONTROL resource %s.",
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_escape_html(r->pool, r->uri)),
7281ea331999debdc337b02ce37a3169e0e033a2gstein err);
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_handle_err(r, err, NULL);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* revert writability of parent directory */
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_revert_resource_writability(r, resource, 0 /*undo*/, &av_info);
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (err != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* just log a warning */
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_push_error(r->pool, err->status, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "The VERSION-CONTROL was successful, but there "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "was a problem reverting the writability of "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "the parent collection.",
7281ea331999debdc337b02ce37a3169e0e033a2gstein err);
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_log_err(r, err, APLOG_WARNING);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* if the resource is lockable, let lock system know of new resource */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (locks_hooks != NULL
7281ea331999debdc337b02ce37a3169e0e033a2gstein && (*locks_hooks->get_supportedlock)(resource) != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_lockdb *lockdb;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((err = (*locks_hooks->open_lockdb)(r, 0, 0, &lockdb)) != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* The resource creation was successful, but the locking failed. */
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_push_error(r->pool, err->status, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "The VERSION-CONTROL was successful, but there "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "was a problem opening the lock database "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "which prevents inheriting locks from the "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "parent resources.",
7281ea331999debdc337b02ce37a3169e0e033a2gstein err);
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_handle_err(r, err, NULL);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* notify lock system that we have created/replaced a resource */
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_notify_created(r, lockdb, resource, resource_state, 0);
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein (*locks_hooks->close_lockdb)(lockdb);
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (err != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* The dir creation was successful, but the locking failed. */
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_push_error(r->pool, err->status, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "The VERSION-CONTROL was successful, but there "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "was a problem updating its lock "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "information.",
7281ea331999debdc337b02ce37a3169e0e033a2gstein err);
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_handle_err(r, err, NULL);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* set the Cache-Control header, per the spec */
7281ea331999debdc337b02ce37a3169e0e033a2gstein apr_table_setn(r->headers_out, "Cache-Control", "no-cache");
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* return an appropriate response (HTTP_CREATED) */
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_created(r, resource->uri, "Version selector", 0 /*replaced*/);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* handle the CHECKOUT method */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_method_checkout(request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *resource;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein dav_resource *working_resource;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int result;
50bd75672ef114fb839dd9643c192b432fdf344cgstein ap_xml_doc *doc;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein ap_xml_elem *target = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* If no versioning provider, decline the request */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (vsn_hooks == NULL)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DECLINED;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
50bd75672ef114fb839dd9643c192b432fdf344cgstein if ((result = ap_xml_parse_input(r, &doc)) != OK)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
50bd75672ef114fb839dd9643c192b432fdf344cgstein
50bd75672ef114fb839dd9643c192b432fdf344cgstein if (doc != NULL) {
50bd75672ef114fb839dd9643c192b432fdf344cgstein if (!dav_validate_root(doc, "checkout")) {
50bd75672ef114fb839dd9643c192b432fdf344cgstein /* This supplies additional information for the default msg. */
50bd75672ef114fb839dd9643c192b432fdf344cgstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
50bd75672ef114fb839dd9643c192b432fdf344cgstein "The request body, if present, must be a "
50bd75672ef114fb839dd9643c192b432fdf344cgstein "DAV:checkout element.");
50bd75672ef114fb839dd9643c192b432fdf344cgstein return HTTP_BAD_REQUEST;
50bd75672ef114fb839dd9643c192b432fdf344cgstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein if ((target = dav_find_child(doc->root, "version")) == NULL)
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein target = dav_find_child(doc->root, "label-name");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Ask repository module to resolve the resource */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein result = dav_get_resource(r, 1 /*target_allowed*/, target, &resource);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (result != OK)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->exists) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Apache will supply a default error for this. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_NOT_FOUND;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Check the state of the resource: must be a file or collection,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * must be versioned, and must not already be checked out.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resource->type != DAV_RESOURCE_TYPE_REGULAR) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, HTTP_CONFLICT,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Cannot checkout this type of resource.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->versioned) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, HTTP_CONFLICT,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Cannot checkout unversioned resource.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resource->working) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, HTTP_CONFLICT,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The resource is already checked out to the workspace.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### do lock checks, once behavior is defined */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Do the checkout */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein if ((err = (*vsn_hooks->checkout)(resource, &working_resource)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, HTTP_CONFLICT, 0,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_psprintf(r->pool,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Could not CHECKOUT resource %s.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_escape_html(r->pool, r->uri)),
f4c310fd2555c6faca1f980f00b161eadb089023gstein err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
de18a9e85398b9c79c422f578633ed56c2747bbbgstein /* set the Cache-Control header, per the spec */
50bd75672ef114fb839dd9643c192b432fdf344cgstein apr_table_setn(r->headers_out, "Cache-Control", "no-cache");
de18a9e85398b9c79c422f578633ed56c2747bbbgstein
de18a9e85398b9c79c422f578633ed56c2747bbbgstein /* use appropriate URI for Location header */
de18a9e85398b9c79c422f578633ed56c2747bbbgstein if (working_resource == NULL)
de18a9e85398b9c79c422f578633ed56c2747bbbgstein working_resource = resource;
de18a9e85398b9c79c422f578633ed56c2747bbbgstein
de18a9e85398b9c79c422f578633ed56c2747bbbgstein return dav_created(r, working_resource->uri, "Checked-out resource", 0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* handle the UNCHECKOUT method */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_method_uncheckout(request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *resource;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* If no versioning provider, decline the request */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (vsn_hooks == NULL)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DECLINED;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((result = ap_discard_request_body(r)) != OK) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Ask repository module to resolve the resource */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein result = dav_get_resource(r, 0 /*target_allowed*/, NULL, &resource);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (result != OK)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->exists) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Apache will supply a default error for this. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_NOT_FOUND;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Check the state of the resource: must be a file or collection,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * must be versioned, and must be checked out.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resource->type != DAV_RESOURCE_TYPE_REGULAR) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, HTTP_CONFLICT,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Cannot uncheckout this type of resource.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->versioned) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, HTTP_CONFLICT,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Cannot uncheckout unversioned resource.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->working) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, HTTP_CONFLICT,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The resource is not checked out to the workspace.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### do lock checks, once behavior is defined */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Do the uncheckout */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = (*vsn_hooks->uncheckout)(resource)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, HTTP_CONFLICT, 0,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_psprintf(r->pool,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Could not UNCHECKOUT resource %s.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_escape_html(r->pool, r->uri)),
f4c310fd2555c6faca1f980f00b161eadb089023gstein err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* no body */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_set_content_length(r, 0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_send_http_header(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DONE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* handle the CHECKIN method */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_method_checkin(request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *resource;
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein dav_resource *new_version;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* If no versioning provider, decline the request */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (vsn_hooks == NULL)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DECLINED;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((result = ap_discard_request_body(r)) != OK) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Ask repository module to resolve the resource */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein result = dav_get_resource(r, 0 /* target_allowed */, NULL, &resource);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (result != OK)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->exists) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Apache will supply a default error for this. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_NOT_FOUND;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Check the state of the resource: must be a file or collection,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * must be versioned, and must be checked out.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resource->type != DAV_RESOURCE_TYPE_REGULAR) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, HTTP_CONFLICT,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Cannot checkin this type of resource.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->versioned) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, HTTP_CONFLICT,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Cannot checkin unversioned resource.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->working) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, HTTP_CONFLICT,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "The resource is not checked out to the workspace.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### do lock checks, once behavior is defined */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Do the checkin */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein if ((err = (*vsn_hooks->checkin)(resource, &new_version)) != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_push_error(r->pool, HTTP_CONFLICT, 0,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_psprintf(r->pool,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Could not CHECKIN resource %s.",
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_escape_html(r->pool, r->uri)),
f4c310fd2555c6faca1f980f00b161eadb089023gstein err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein return dav_created(r, new_version->uri, "Version", 0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein/* context maintained during SET-TARGET treewalk */
7281ea331999debdc337b02ce37a3169e0e033a2gsteintypedef struct dav_set_target_walker_ctx
50bd75672ef114fb839dd9643c192b432fdf344cgstein{
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* input: */
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_walk_params w;
50bd75672ef114fb839dd9643c192b432fdf344cgstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* target specifier */
7281ea331999debdc337b02ce37a3169e0e033a2gstein const char *target;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* flag for whether target is version URI or label */
7281ea331999debdc337b02ce37a3169e0e033a2gstein int is_label;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* version provider hooks */
7281ea331999debdc337b02ce37a3169e0e033a2gstein const dav_hooks_vsn *vsn_hooks;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein} dav_set_target_walker_ctx;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gsteinstatic dav_error * dav_set_target_walker(dav_walk_resource *wres, int calltype)
50bd75672ef114fb839dd9643c192b432fdf344cgstein{
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_set_target_walker_ctx *ctx = wres->walk_ctx;
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_error *err = NULL;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* Check the state of the resource: must be a checked-in version
7281ea331999debdc337b02ce37a3169e0e033a2gstein * or baseline selector
7281ea331999debdc337b02ce37a3169e0e033a2gstein */
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* ### need a general mechanism for reporting precondition violations
7281ea331999debdc337b02ce37a3169e0e033a2gstein * ### (should be returning XML document for 403/409 responses)
7281ea331999debdc337b02ce37a3169e0e033a2gstein */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (wres->resource->type != DAV_RESOURCE_TYPE_REGULAR
7281ea331999debdc337b02ce37a3169e0e033a2gstein || !wres->resource->versioned || wres->resource->working) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_new_error(ctx->w.pool, HTTP_CONFLICT, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "<DAV:must-be-checked-in-version-selector/>");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein else {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* do the set-target operation */
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = (*ctx->vsn_hooks->set_target)(wres->resource, ctx->target, ctx->is_label);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (err != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* ### need utility routine to add response with description? */
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_add_response(wres, err->status, NULL);
7281ea331999debdc337b02ce37a3169e0e033a2gstein wres->response->desc = err->desc;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein return NULL;
50bd75672ef114fb839dd9643c192b432fdf344cgstein}
50bd75672ef114fb839dd9643c192b432fdf344cgstein
7281ea331999debdc337b02ce37a3169e0e033a2gsteinstatic int dav_method_set_target(request_rec *r)
50bd75672ef114fb839dd9643c192b432fdf344cgstein{
50bd75672ef114fb839dd9643c192b432fdf344cgstein dav_resource *resource;
50bd75672ef114fb839dd9643c192b432fdf344cgstein const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
50bd75672ef114fb839dd9643c192b432fdf344cgstein ap_xml_doc *doc;
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_xml_elem *child;
7281ea331999debdc337b02ce37a3169e0e033a2gstein int depth;
7281ea331999debdc337b02ce37a3169e0e033a2gstein int result;
1d69b25dcd7ca16cd3ee662bf768ffb1d36c46b6gstein apr_size_t tsize;
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_error *err;
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_set_target_walker_ctx ctx = { { 0 } };
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_response *multi_status;
50bd75672ef114fb839dd9643c192b432fdf344cgstein
50bd75672ef114fb839dd9643c192b432fdf344cgstein /* If no versioning provider, decline the request */
50bd75672ef114fb839dd9643c192b432fdf344cgstein if (vsn_hooks == NULL)
50bd75672ef114fb839dd9643c192b432fdf344cgstein return DECLINED;
50bd75672ef114fb839dd9643c192b432fdf344cgstein
50bd75672ef114fb839dd9643c192b432fdf344cgstein /* Ask repository module to resolve the resource */
7281ea331999debdc337b02ce37a3169e0e033a2gstein result = dav_get_resource(r, 0 /*target_allowed*/, NULL, &resource);
50bd75672ef114fb839dd9643c192b432fdf344cgstein if (result != OK)
50bd75672ef114fb839dd9643c192b432fdf344cgstein return result;
50bd75672ef114fb839dd9643c192b432fdf344cgstein if (!resource->exists) {
50bd75672ef114fb839dd9643c192b432fdf344cgstein /* Apache will supply a default error for this. */
50bd75672ef114fb839dd9643c192b432fdf344cgstein return HTTP_NOT_FOUND;
50bd75672ef114fb839dd9643c192b432fdf344cgstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((depth = dav_get_depth(r, 0)) < 0) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* dav_get_depth() supplies additional information for the
7281ea331999debdc337b02ce37a3169e0e033a2gstein * default message. */
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_BAD_REQUEST;
50bd75672ef114fb839dd9643c192b432fdf344cgstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* parse the request body */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((result = ap_xml_parse_input(r, &doc)) != OK) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein return result;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (doc == NULL || !dav_validate_root(doc, "set-target")) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* This supplies additional information for the default message. */
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "The request body does not contain "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "a \"set-target\" element.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* check for label-name or version element */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((child = dav_find_child(doc->root, "label-name")) != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein ctx.is_label = 1;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein else if ((child = dav_find_child(doc->root, "version")) != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein ctx.is_label = 0;
50bd75672ef114fb839dd9643c192b432fdf344cgstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* get the href element */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((child = dav_find_child(child, "href")) == NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "The version element does not contain "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "an \"href\" element.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein else {
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "The \"set-target\" element does not contain "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "a \"label-name\" or \"version\" element.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* get the target value (a label or a version URI */
1d69b25dcd7ca16cd3ee662bf768ffb1d36c46b6gstein ap_xml_to_text(r->pool, child, AP_XML_X2T_INNER, NULL, NULL,
1d69b25dcd7ca16cd3ee662bf768ffb1d36c46b6gstein &ctx.target, &tsize);
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (tsize == 0) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "A \"label-name\" or \"href\" element does not contain "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "any content.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* do the set-target operation walk */
7281ea331999debdc337b02ce37a3169e0e033a2gstein ctx.w.walk_type = DAV_WALKTYPE_NORMAL;
7281ea331999debdc337b02ce37a3169e0e033a2gstein ctx.w.func = dav_set_target_walker;
7281ea331999debdc337b02ce37a3169e0e033a2gstein ctx.w.walk_ctx = &ctx;
7281ea331999debdc337b02ce37a3169e0e033a2gstein ctx.w.pool = r->pool;
7281ea331999debdc337b02ce37a3169e0e033a2gstein ctx.w.root = resource;
7281ea331999debdc337b02ce37a3169e0e033a2gstein ctx.vsn_hooks = vsn_hooks;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = (*resource->hooks->walk)(&ctx.w, depth, &multi_status);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (err != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* some sort of error occurred which terminated the walk */
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_push_error(r->pool, err->status, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "The SET-TARGET operation was terminated prematurely.",
7281ea331999debdc337b02ce37a3169e0e033a2gstein err);
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_handle_err(r, err, multi_status);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (multi_status != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* One or more resources had errors. If depth was zero, convert
7281ea331999debdc337b02ce37a3169e0e033a2gstein * response to simple error, else make sure there is an
7281ea331999debdc337b02ce37a3169e0e033a2gstein * overall error to pass to dav_handle_err()
7281ea331999debdc337b02ce37a3169e0e033a2gstein */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (depth == 0) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_new_error(r->pool, multi_status->status, 0, multi_status->desc);
7281ea331999debdc337b02ce37a3169e0e033a2gstein multi_status = NULL;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein else {
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_new_error(r->pool, HTTP_MULTI_STATUS, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "Errors occurred during the SET-TARGET operation.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_handle_err(r, err, multi_status);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* set the Cache-Control header, per the spec */
7281ea331999debdc337b02ce37a3169e0e033a2gstein apr_table_setn(r->headers_out, "Cache-Control", "no-cache");
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* no body */
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_set_content_length(r, 0);
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_send_http_header(r);
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein return DONE;
7281ea331999debdc337b02ce37a3169e0e033a2gstein}
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein/* context maintained during LABEL treewalk */
7281ea331999debdc337b02ce37a3169e0e033a2gsteintypedef struct dav_label_walker_ctx
7281ea331999debdc337b02ce37a3169e0e033a2gstein{
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* input: */
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_walk_params w;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* label being manipulated */
7281ea331999debdc337b02ce37a3169e0e033a2gstein const char *label;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* label operation */
7281ea331999debdc337b02ce37a3169e0e033a2gstein int label_op;
7281ea331999debdc337b02ce37a3169e0e033a2gstein#define DAV_LABEL_ADD 1
7281ea331999debdc337b02ce37a3169e0e033a2gstein#define DAV_LABEL_SET 2
7281ea331999debdc337b02ce37a3169e0e033a2gstein#define DAV_LABEL_REMOVE 3
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* version provider hooks */
7281ea331999debdc337b02ce37a3169e0e033a2gstein const dav_hooks_vsn *vsn_hooks;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein} dav_label_walker_ctx;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gsteinstatic dav_error * dav_label_walker(dav_walk_resource *wres, int calltype)
7281ea331999debdc337b02ce37a3169e0e033a2gstein{
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_label_walker_ctx *ctx = wres->walk_ctx;
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_error *err = NULL;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* Check the state of the resource: must be a version or
7281ea331999debdc337b02ce37a3169e0e033a2gstein * non-checkedout version selector
7281ea331999debdc337b02ce37a3169e0e033a2gstein */
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* ### need a general mechanism for reporting precondition violations
7281ea331999debdc337b02ce37a3169e0e033a2gstein * ### (should be returning XML document for 403/409 responses)
7281ea331999debdc337b02ce37a3169e0e033a2gstein */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (wres->resource->type != DAV_RESOURCE_TYPE_VERSION &&
7281ea331999debdc337b02ce37a3169e0e033a2gstein (wres->resource->type != DAV_RESOURCE_TYPE_REGULAR
7281ea331999debdc337b02ce37a3169e0e033a2gstein || !wres->resource->versioned)) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_new_error(ctx->w.pool, HTTP_CONFLICT, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "<DAV:must-be-version-or-version-selector/>");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein else if (wres->resource->working) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_new_error(ctx->w.pool, HTTP_CONFLICT, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "<DAV:must-not-be-checked-out/>");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein else {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* do the label operation */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (ctx->label_op == DAV_LABEL_REMOVE)
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = (*ctx->vsn_hooks->remove_label)(wres->resource, ctx->label);
7281ea331999debdc337b02ce37a3169e0e033a2gstein else
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = (*ctx->vsn_hooks->add_label)(wres->resource, ctx->label,
7281ea331999debdc337b02ce37a3169e0e033a2gstein ctx->label_op == DAV_LABEL_SET);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (err != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* ### need utility routine to add response with description? */
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_add_response(wres, err->status, NULL);
7281ea331999debdc337b02ce37a3169e0e033a2gstein wres->response->desc = err->desc;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein return NULL;
7281ea331999debdc337b02ce37a3169e0e033a2gstein}
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gsteinstatic int dav_method_label(request_rec *r)
7281ea331999debdc337b02ce37a3169e0e033a2gstein{
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_resource *resource;
7281ea331999debdc337b02ce37a3169e0e033a2gstein const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_xml_doc *doc;
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_xml_elem *child;
7281ea331999debdc337b02ce37a3169e0e033a2gstein int depth;
7281ea331999debdc337b02ce37a3169e0e033a2gstein int result;
1d69b25dcd7ca16cd3ee662bf768ffb1d36c46b6gstein apr_size_t tsize;
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_error *err;
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_label_walker_ctx ctx = { { 0 } };
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_response *multi_status;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* If no versioning provider, or the provider doesn't support
7281ea331999debdc337b02ce37a3169e0e033a2gstein * labels, decline the request */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (vsn_hooks == NULL || vsn_hooks->add_label == NULL)
7281ea331999debdc337b02ce37a3169e0e033a2gstein return DECLINED;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* Ask repository module to resolve the resource */
7281ea331999debdc337b02ce37a3169e0e033a2gstein result = dav_get_resource(r, 1 /*target_allowed*/, NULL, &resource);
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (result != OK)
7281ea331999debdc337b02ce37a3169e0e033a2gstein return result;
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (!resource->exists) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* Apache will supply a default error for this. */
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_NOT_FOUND;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((depth = dav_get_depth(r, 0)) < 0) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* dav_get_depth() supplies additional information for the
7281ea331999debdc337b02ce37a3169e0e033a2gstein * default message. */
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* parse the request body */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((result = ap_xml_parse_input(r, &doc)) != OK) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein return result;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (doc == NULL || !dav_validate_root(doc, "label")) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* This supplies additional information for the default message. */
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "The request body does not contain "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "a \"label\" element.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* check for add, set, or remove element */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((child = dav_find_child(doc->root, "add")) != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein ctx.label_op = DAV_LABEL_ADD;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein else if ((child = dav_find_child(doc->root, "set")) != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein ctx.label_op = DAV_LABEL_SET;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein else if ((child = dav_find_child(doc->root, "remove")) != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein ctx.label_op = DAV_LABEL_REMOVE;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein else {
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "The \"label\" element does not contain "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "an \"add\", \"set\", or \"remove\" element.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* get the label string */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((child = dav_find_child(child, "label-name")) == NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "The label command element does not contain "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "a \"label-name\" element.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
1d69b25dcd7ca16cd3ee662bf768ffb1d36c46b6gstein ap_xml_to_text(r->pool, child, AP_XML_X2T_INNER, NULL, NULL,
1d69b25dcd7ca16cd3ee662bf768ffb1d36c46b6gstein &ctx.label, &tsize);
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (tsize == 0) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "A \"label-name\" element does not contain "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "a label name.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* do the label operation walk */
7281ea331999debdc337b02ce37a3169e0e033a2gstein ctx.w.walk_type = DAV_WALKTYPE_NORMAL;
7281ea331999debdc337b02ce37a3169e0e033a2gstein ctx.w.func = dav_label_walker;
7281ea331999debdc337b02ce37a3169e0e033a2gstein ctx.w.walk_ctx = &ctx;
7281ea331999debdc337b02ce37a3169e0e033a2gstein ctx.w.pool = r->pool;
7281ea331999debdc337b02ce37a3169e0e033a2gstein ctx.w.root = resource;
7281ea331999debdc337b02ce37a3169e0e033a2gstein ctx.vsn_hooks = vsn_hooks;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = (*resource->hooks->walk)(&ctx.w, depth, &multi_status);
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (err != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* some sort of error occurred which terminated the walk */
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_push_error(r->pool, err->status, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "The LABEL operation was terminated prematurely.",
7281ea331999debdc337b02ce37a3169e0e033a2gstein err);
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_handle_err(r, err, multi_status);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (multi_status != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* One or more resources had errors. If depth was zero, convert
7281ea331999debdc337b02ce37a3169e0e033a2gstein * response to simple error, else make sure there is an
7281ea331999debdc337b02ce37a3169e0e033a2gstein * overall error to pass to dav_handle_err()
7281ea331999debdc337b02ce37a3169e0e033a2gstein */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (depth == 0) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_new_error(r->pool, multi_status->status, 0, multi_status->desc);
7281ea331999debdc337b02ce37a3169e0e033a2gstein multi_status = NULL;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein else {
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_new_error(r->pool, HTTP_MULTI_STATUS, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "Errors occurred during the LABEL operation.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_handle_err(r, err, multi_status);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* set the Cache-Control header, per the spec */
7281ea331999debdc337b02ce37a3169e0e033a2gstein apr_table_setn(r->headers_out, "Cache-Control", "no-cache");
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* no body */
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_set_content_length(r, 0);
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_send_http_header(r);
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein return DONE;
7281ea331999debdc337b02ce37a3169e0e033a2gstein}
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gsteinstatic int dav_method_report(request_rec *r)
7281ea331999debdc337b02ce37a3169e0e033a2gstein{
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_resource *resource;
7281ea331999debdc337b02ce37a3169e0e033a2gstein const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
7281ea331999debdc337b02ce37a3169e0e033a2gstein int result;
7281ea331999debdc337b02ce37a3169e0e033a2gstein int target_allowed;
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_xml_doc *doc;
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_text_header hdr = { 0 };
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_text *t;
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_error *err;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* If no versioning provider, decline the request */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (vsn_hooks == NULL)
7281ea331999debdc337b02ce37a3169e0e033a2gstein return DECLINED;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((result = ap_xml_parse_input(r, &doc)) != OK)
7281ea331999debdc337b02ce37a3169e0e033a2gstein return result;
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (doc == NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* This supplies additional information for the default msg. */
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "The request body must specify a report.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* Ask repository module to resolve the resource.
7281ea331999debdc337b02ce37a3169e0e033a2gstein * First determine whether a Target-Selector header is allowed
7281ea331999debdc337b02ce37a3169e0e033a2gstein * for this report.
7281ea331999debdc337b02ce37a3169e0e033a2gstein */
7281ea331999debdc337b02ce37a3169e0e033a2gstein target_allowed = (*vsn_hooks->report_target_selector_allowed)(doc);
7281ea331999debdc337b02ce37a3169e0e033a2gstein result = dav_get_resource(r, target_allowed, NULL, &resource);
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (result != OK)
7281ea331999debdc337b02ce37a3169e0e033a2gstein return result;
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (!resource->exists) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* Apache will supply a default error for this. */
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_NOT_FOUND;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* run report hook */
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* ### writing large reports to memory could be bad...
7281ea331999debdc337b02ce37a3169e0e033a2gstein * ### but if provider generated output directly, it would
7281ea331999debdc337b02ce37a3169e0e033a2gstein * ### have to handle error responses as well.
7281ea331999debdc337b02ce37a3169e0e033a2gstein */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((err = (*vsn_hooks->get_report)(r, resource, doc, &hdr)) != NULL)
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_handle_err(r, err, NULL);
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* send the report response */
7281ea331999debdc337b02ce37a3169e0e033a2gstein r->status = HTTP_OK;
7281ea331999debdc337b02ce37a3169e0e033a2gstein r->content_type = DAV_XML_CONTENT_TYPE;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* send the headers and start a timeout */
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_send_http_header(r);
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* send the response body */
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_rputs(DAV_XML_HEADER DEBUG_CR, r);
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein for (t = hdr.first; t != NULL; t = t->next)
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_rputs(t->text, r);
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein return DONE;
7281ea331999debdc337b02ce37a3169e0e033a2gstein}
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gsteinstatic int dav_method_make_workspace(request_rec *r)
7281ea331999debdc337b02ce37a3169e0e033a2gstein{
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_resource *resource;
7281ea331999debdc337b02ce37a3169e0e033a2gstein const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_error *err;
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_xml_doc *doc;
7281ea331999debdc337b02ce37a3169e0e033a2gstein int result;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* if no versioning provider, or the provider does not support workspaces,
7281ea331999debdc337b02ce37a3169e0e033a2gstein * decline the request
7281ea331999debdc337b02ce37a3169e0e033a2gstein */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (vsn_hooks == NULL || vsn_hooks->make_workspace == NULL)
7281ea331999debdc337b02ce37a3169e0e033a2gstein return DECLINED;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* ask repository module to resolve the resource */
7281ea331999debdc337b02ce37a3169e0e033a2gstein result = dav_get_resource(r, 0 /*target_allowed*/, NULL, &resource);
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (result != OK)
7281ea331999debdc337b02ce37a3169e0e033a2gstein return result;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* parse the request body (must be a mkworkspace element) */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((result = ap_xml_parse_input(r, &doc)) != OK) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein return result;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (doc == NULL
7281ea331999debdc337b02ce37a3169e0e033a2gstein || !dav_validate_root(doc, "mkworkspace")) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "The request body does not contain "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "a \"mkworkspace\" element.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* Check request preconditions */
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* ### need a general mechanism for reporting precondition violations
7281ea331999debdc337b02ce37a3169e0e033a2gstein * ### (should be returning XML document for 403/409 responses)
7281ea331999debdc337b02ce37a3169e0e033a2gstein */
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* resource must not already exist */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (resource->exists) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_new_error(r->pool, HTTP_CONFLICT, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "<DAV:resource-must-be-null/>");
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_handle_err(r, err, NULL);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* ### what about locking? */
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* attempt to create the workspace */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((err = (*vsn_hooks->make_workspace)(resource, doc)) != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_push_error(r->pool, HTTP_CONFLICT, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein apr_psprintf(r->pool,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "Could not create workspace %s.",
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_escape_html(r->pool, r->uri)),
7281ea331999debdc337b02ce37a3169e0e033a2gstein err);
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_handle_err(r, err, NULL);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* set the Cache-Control header, per the spec */
7281ea331999debdc337b02ce37a3169e0e033a2gstein apr_table_setn(r->headers_out, "Cache-Control", "no-cache");
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* return an appropriate response (HTTP_CREATED) */
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_created(r, resource->uri, "Workspace", 0 /*replaced*/);
7281ea331999debdc337b02ce37a3169e0e033a2gstein}
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gsteinstatic int dav_method_make_activity(request_rec *r)
7281ea331999debdc337b02ce37a3169e0e033a2gstein{
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* ### */
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_METHOD_NOT_ALLOWED;
7281ea331999debdc337b02ce37a3169e0e033a2gstein}
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gsteinstatic int dav_method_baseline_control(request_rec *r)
7281ea331999debdc337b02ce37a3169e0e033a2gstein{
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* ### */
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_METHOD_NOT_ALLOWED;
7281ea331999debdc337b02ce37a3169e0e033a2gstein}
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gsteinstatic int dav_method_merge(request_rec *r)
7281ea331999debdc337b02ce37a3169e0e033a2gstein{
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* ### */
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_METHOD_NOT_ALLOWED;
7281ea331999debdc337b02ce37a3169e0e033a2gstein}
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gsteinstatic int dav_method_bind(request_rec *r)
7281ea331999debdc337b02ce37a3169e0e033a2gstein{
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_resource *resource;
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_resource *binding;
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_auto_version_info av_info;
7281ea331999debdc337b02ce37a3169e0e033a2gstein const dav_hooks_binding *binding_hooks = DAV_GET_HOOKS_BINDING(r);
7281ea331999debdc337b02ce37a3169e0e033a2gstein const char *dest;
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_error *err;
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_error *err2;
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_response *multi_response = NULL;
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_lookup_result lookup;
7281ea331999debdc337b02ce37a3169e0e033a2gstein int overwrite;
7281ea331999debdc337b02ce37a3169e0e033a2gstein int result;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* If no bindings provider, decline the request */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (binding_hooks == NULL)
7281ea331999debdc337b02ce37a3169e0e033a2gstein return DECLINED;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* Ask repository module to resolve the resource */
7281ea331999debdc337b02ce37a3169e0e033a2gstein result = dav_get_resource(r, 0 /*!target_allowed*/, NULL, &resource);
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (result != OK)
7281ea331999debdc337b02ce37a3169e0e033a2gstein return result;
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (!resource->exists) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* Apache will supply a default error for this. */
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_NOT_FOUND;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* get the destination URI */
7281ea331999debdc337b02ce37a3169e0e033a2gstein dest = apr_table_get(r->headers_in, "Destination");
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (dest == NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* This supplies additional information for the default message. */
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "The request is missing a Destination header.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein lookup = dav_lookup_uri(dest, r);
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (lookup.rnew == NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (lookup.err.status == HTTP_BAD_REQUEST) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* This supplies additional information for the default message. */
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, 0, r,
7281ea331999debdc337b02ce37a3169e0e033a2gstein lookup.err.desc);
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein else if (lookup.err.status == HTTP_BAD_GATEWAY) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* ### Bindings protocol draft 02 says to return 507
7281ea331999debdc337b02ce37a3169e0e033a2gstein * ### (Cross Server Binding Forbidden); Apache already defines 507
7281ea331999debdc337b02ce37a3169e0e033a2gstein * ### as HTTP_INSUFFICIENT_STORAGE. So, for now, we'll return
7281ea331999debdc337b02ce37a3169e0e033a2gstein * ### HTTP_FORBIDDEN
7281ea331999debdc337b02ce37a3169e0e033a2gstein */
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_error_response(r, HTTP_FORBIDDEN,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "Cross server bindings are not allowed by this server.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* ### this assumes that dav_lookup_uri() only generates a status
7281ea331999debdc337b02ce37a3169e0e033a2gstein * ### that Apache can provide a status line for!! */
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_error_response(r, lookup.err.status, lookup.err.desc);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (lookup.rnew->status != HTTP_OK) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* ### how best to report this... */
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_error_response(r, lookup.rnew->status,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "Destination URI had an error.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* resolve binding resource */
7281ea331999debdc337b02ce37a3169e0e033a2gstein result = dav_get_resource(lookup.rnew, 0 /*!target_allowed*/, NULL, &binding);
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (result != OK)
7281ea331999debdc337b02ce37a3169e0e033a2gstein return result;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* are the two resources handled by the same repository? */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (resource->hooks != binding->hooks) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* ### this message exposes some backend config, but screw it... */
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_error_response(r, HTTP_BAD_GATEWAY,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "Destination URI is handled by a "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "different repository than the source URI. "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "BIND between repositories is not possible.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* get and parse the overwrite header value */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((overwrite = dav_get_overwrite(r)) < 0) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* dav_get_overwrite() supplies additional information for the
7281ea331999debdc337b02ce37a3169e0e033a2gstein * default message. */
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* quick failure test: if dest exists and overwrite is false. */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (binding->exists && !overwrite) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_error_response(r, HTTP_PRECONDITION_FAILED,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "Destination is not empty and "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "Overwrite is not \"T\"");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* are the source and destination the same? */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((*resource->hooks->is_same_resource)(resource, binding)) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_error_response(r, HTTP_FORBIDDEN,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "Source and Destination URIs are the same.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /*
7281ea331999debdc337b02ce37a3169e0e033a2gstein ** Check If-Headers and existing locks for destination. Note that we
7281ea331999debdc337b02ce37a3169e0e033a2gstein ** use depth==infinity since the target (hierarchy) will be deleted
7281ea331999debdc337b02ce37a3169e0e033a2gstein ** before the move/copy is completed.
7281ea331999debdc337b02ce37a3169e0e033a2gstein **
7281ea331999debdc337b02ce37a3169e0e033a2gstein ** Note that we are overwriting the target, which implies a DELETE, so
7281ea331999debdc337b02ce37a3169e0e033a2gstein ** we are subject to the error/response rules as a DELETE. Namely, we
7281ea331999debdc337b02ce37a3169e0e033a2gstein ** will return a 424 error if any of the validations fail.
7281ea331999debdc337b02ce37a3169e0e033a2gstein ** (see dav_method_delete() for more information)
7281ea331999debdc337b02ce37a3169e0e033a2gstein */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((err = dav_validate_request(lookup.rnew, binding, DAV_INFINITY, NULL,
7281ea331999debdc337b02ce37a3169e0e033a2gstein &multi_response,
7281ea331999debdc337b02ce37a3169e0e033a2gstein DAV_VALIDATE_PARENT
7281ea331999debdc337b02ce37a3169e0e033a2gstein | DAV_VALIDATE_USE_424, NULL)) != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_push_error(r->pool, err->status, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein apr_psprintf(r->pool,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "Could not BIND %s due to a "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "failed precondition on the "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "destination (e.g. locks).",
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_escape_html(r->pool, r->uri)),
7281ea331999debdc337b02ce37a3169e0e033a2gstein err);
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_handle_err(r, err, multi_response);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* guard against creating circular bindings */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (resource->collection
7281ea331999debdc337b02ce37a3169e0e033a2gstein && (*resource->hooks->is_parent_resource)(resource, binding)) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_error_response(r, HTTP_FORBIDDEN,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "Source collection contains the Destination.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (resource->collection
7281ea331999debdc337b02ce37a3169e0e033a2gstein && (*resource->hooks->is_parent_resource)(binding, resource)) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* The destination must exist (since it contains the source), and
7281ea331999debdc337b02ce37a3169e0e033a2gstein * a condition above implies Overwrite==T. Obviously, we cannot
7281ea331999debdc337b02ce37a3169e0e033a2gstein * delete the Destination before the BIND, as that would
7281ea331999debdc337b02ce37a3169e0e033a2gstein * delete the Source.
7281ea331999debdc337b02ce37a3169e0e033a2gstein */
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_error_response(r, HTTP_FORBIDDEN,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "Destination collection contains the Source and "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "Overwrite has been specified.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* prepare the destination collection for modification */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((err = dav_ensure_resource_writable(r, binding, 1 /* parent_only */,
7281ea331999debdc337b02ce37a3169e0e033a2gstein &av_info)) != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* could not make destination writable */
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_handle_err(r, err, NULL);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* If target exists, remove it first (we know Ovewrite must be TRUE).
7281ea331999debdc337b02ce37a3169e0e033a2gstein * Then try to bind to the resource.
7281ea331999debdc337b02ce37a3169e0e033a2gstein */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (binding->exists)
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = (*resource->hooks->remove_resource)(binding, &multi_response);
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (err == NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = (*binding_hooks->bind_resource)(resource, binding);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* restore parent collection states */
7281ea331999debdc337b02ce37a3169e0e033a2gstein err2 = dav_revert_resource_writability(r, NULL,
7281ea331999debdc337b02ce37a3169e0e033a2gstein err != NULL /* undo if error */,
7281ea331999debdc337b02ce37a3169e0e033a2gstein &av_info);
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* check for error from remove/bind operations */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (err != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_push_error(r->pool, err->status, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein apr_psprintf(r->pool,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "Could not BIND %s.",
7281ea331999debdc337b02ce37a3169e0e033a2gstein ap_escape_html(r->pool, r->uri)),
7281ea331999debdc337b02ce37a3169e0e033a2gstein err);
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_handle_err(r, err, multi_response);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* check for errors from reverting writability */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (err2 != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* just log a warning */
7281ea331999debdc337b02ce37a3169e0e033a2gstein err = dav_push_error(r->pool, err2->status, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "The BIND was successful, but there was a "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "problem reverting the writability of the "
7281ea331999debdc337b02ce37a3169e0e033a2gstein "source parent collection.",
7281ea331999debdc337b02ce37a3169e0e033a2gstein err2);
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_log_err(r, err, APLOG_WARNING);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* return an appropriate response (HTTP_CREATED) */
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* ### spec doesn't say what happens when destination was replaced */
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_created(r, lookup.rnew->uri, "Binding", 0);
7281ea331999debdc337b02ce37a3169e0e033a2gstein}
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein/*
7281ea331999debdc337b02ce37a3169e0e033a2gstein * Response handler for DAV resources
7281ea331999debdc337b02ce37a3169e0e033a2gstein */
7281ea331999debdc337b02ce37a3169e0e033a2gsteinstatic int dav_handler(request_rec *r)
7281ea331999debdc337b02ce37a3169e0e033a2gstein{
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_dir_conf *conf;
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* quickly ignore any HTTP/0.9 requests */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (r->assbackwards) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein return DECLINED;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### do we need to do anything with r->proxyreq ?? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein conf = (dav_dir_conf *) ap_get_module_config(r->per_dir_config,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &dav_module);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein * Set up the methods mask, since that's one of the reasons this handler
f4c310fd2555c6faca1f980f00b161eadb089023gstein * gets called, and lower-level things may need the info.
f4c310fd2555c6faca1f980f00b161eadb089023gstein *
f4c310fd2555c6faca1f980f00b161eadb089023gstein * First, set the mask to the methods we handle directly. Since by
f4c310fd2555c6faca1f980f00b161eadb089023gstein * definition we own our managed space, we unconditionally set
f4c310fd2555c6faca1f980f00b161eadb089023gstein * the r->allowed field rather than ORing our values with anything
f4c310fd2555c6faca1f980f00b161eadb089023gstein * any other module may have put in there.
f4c310fd2555c6faca1f980f00b161eadb089023gstein *
f4c310fd2555c6faca1f980f00b161eadb089023gstein * These are the HTTP-defined methods that we handle directly.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein r->allowed = 0
f4c310fd2555c6faca1f980f00b161eadb089023gstein | (1 << M_GET)
f4c310fd2555c6faca1f980f00b161eadb089023gstein | (1 << M_PUT)
f4c310fd2555c6faca1f980f00b161eadb089023gstein | (1 << M_DELETE)
f4c310fd2555c6faca1f980f00b161eadb089023gstein | (1 << M_OPTIONS)
f4c310fd2555c6faca1f980f00b161eadb089023gstein | (1 << M_INVALID);
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein * These are the DAV methods we handle.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein r->allowed |= 0
f4c310fd2555c6faca1f980f00b161eadb089023gstein | (1 << M_COPY)
f4c310fd2555c6faca1f980f00b161eadb089023gstein | (1 << M_LOCK)
f4c310fd2555c6faca1f980f00b161eadb089023gstein | (1 << M_UNLOCK)
f4c310fd2555c6faca1f980f00b161eadb089023gstein | (1 << M_MKCOL)
f4c310fd2555c6faca1f980f00b161eadb089023gstein | (1 << M_MOVE)
f4c310fd2555c6faca1f980f00b161eadb089023gstein | (1 << M_PROPFIND)
f4c310fd2555c6faca1f980f00b161eadb089023gstein | (1 << M_PROPPATCH);
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein * These are methods that we don't handle directly, but let the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * server's default handler do for us as our agent.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein r->allowed |= 0
f4c310fd2555c6faca1f980f00b161eadb089023gstein | (1 << M_POST);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### hrm. if we return HTTP_METHOD_NOT_ALLOWED, then an Allow header
f4c310fd2555c6faca1f980f00b161eadb089023gstein * ### is sent; it will need the other allowed states; since the default
f4c310fd2555c6faca1f980f00b161eadb089023gstein * ### handler is not called on error, then it doesn't add the other
f4c310fd2555c6faca1f980f00b161eadb089023gstein * ### allowed states, so we must */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### we might need to refine this for just where we return the error.
f4c310fd2555c6faca1f980f00b161eadb089023gstein * ### also, there is the issue with other methods (see ISSUES) */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### more work necessary, now that we have M_foo for DAV methods */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* dispatch the appropriate method handler */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_GET) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_method_get(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_PUT) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_method_put(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_POST) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_method_post(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_DELETE) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_method_delete(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_OPTIONS) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_method_options(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_PROPFIND) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_method_propfind(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_PROPPATCH) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_method_proppatch(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_MKCOL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_method_mkcol(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_COPY) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_method_copymove(r, DAV_DO_COPY);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_MOVE) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_method_copymove(r, DAV_DO_MOVE);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_LOCK) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_method_lock(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_UNLOCK) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_method_unlock(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein * NOTE: When Apache moves creates defines for the add'l DAV methods,
f4c310fd2555c6faca1f980f00b161eadb089023gstein * then it will no longer use M_INVALID. This code must be
f4c310fd2555c6faca1f980f00b161eadb089023gstein * updated each time Apache adds method defines.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number != M_INVALID) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DECLINED;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
50bd75672ef114fb839dd9643c192b432fdf344cgstein if (!strcmp(r->method, "VERSION-CONTROL")) {
50bd75672ef114fb839dd9643c192b432fdf344cgstein return dav_method_vsn_control(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!strcmp(r->method, "CHECKOUT")) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_method_checkout(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!strcmp(r->method, "UNCHECKOUT")) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_method_uncheckout(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!strcmp(r->method, "CHECKIN")) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_method_checkin(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
50bd75672ef114fb839dd9643c192b432fdf344cgstein if (!strcmp(r->method, "SET-TARGET")) {
50bd75672ef114fb839dd9643c192b432fdf344cgstein return dav_method_set_target(r);
50bd75672ef114fb839dd9643c192b432fdf344cgstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
50bd75672ef114fb839dd9643c192b432fdf344cgstein if (!strcmp(r->method, "LABEL")) {
50bd75672ef114fb839dd9643c192b432fdf344cgstein return dav_method_label(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!strcmp(r->method, "REPORT")) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_method_report(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
50bd75672ef114fb839dd9643c192b432fdf344cgstein if (!strcmp(r->method, "MKWORKSPACE")) {
50bd75672ef114fb839dd9643c192b432fdf344cgstein return dav_method_make_workspace(r);
50bd75672ef114fb839dd9643c192b432fdf344cgstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
50bd75672ef114fb839dd9643c192b432fdf344cgstein if (!strcmp(r->method, "MKACTIVITY")) {
50bd75672ef114fb839dd9643c192b432fdf344cgstein return dav_method_make_activity(r);
50bd75672ef114fb839dd9643c192b432fdf344cgstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
50bd75672ef114fb839dd9643c192b432fdf344cgstein if (!strcmp(r->method, "BASELINE-CONTROL")) {
50bd75672ef114fb839dd9643c192b432fdf344cgstein return dav_method_baseline_control(r);
50bd75672ef114fb839dd9643c192b432fdf344cgstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
50bd75672ef114fb839dd9643c192b432fdf344cgstein if (!strcmp(r->method, "MERGE")) {
50bd75672ef114fb839dd9643c192b432fdf344cgstein return dav_method_merge(r);
50bd75672ef114fb839dd9643c192b432fdf344cgstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (!strcmp(r->method, "BIND")) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_method_bind(r);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### add'l methods for Advanced Collections, ACLs, DASL */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DECLINED;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_type_checker(request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_dir_conf *conf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein conf = (dav_dir_conf *) ap_get_module_config(r->per_dir_config,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &dav_module);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* if DAV is not enabled, then we've got nothing to do */
000397350b42c6266351bd618fa07df929fa7c79gstein if (conf->provider == NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DECLINED;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_GET) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### need some work to pull Content-Type and Content-Language
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### from the property database.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** If the repository hasn't indicated that it will handle the
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** GET method, then just punt.
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### this isn't quite right... taking over the response can break
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### things like mod_negotiation. need to look into this some more.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
9f18c80269be35c0b5653e84b0db0a24044722c4gstein if (!conf->provider->repos->handle_get) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DECLINED;
06cb1a83b6a1cfbe9c7815569e6c1d1408966ff7gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### we should (instead) trap the ones that we DO understand */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### the handler DOES handle POST, so we need to fix one of these */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number != M_POST) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### anything else to do here? could another module and/or
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### config option "take over" the handler here? i.e. how do
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### we lock down this hierarchy so that we are the ultimate
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### arbiter? (or do we simply depend on the administrator
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### to avoid conflicting configurations?)
f4c310fd2555c6faca1f980f00b161eadb089023gstein **
f4c310fd2555c6faca1f980f00b161eadb089023gstein ** ### I think the OK stops running type-checkers. need to look.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein r->handler = "dav-handler";
f4c310fd2555c6faca1f980f00b161eadb089023gstein return OK;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DECLINED;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagsteinstatic void register_hooks(void)
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein{
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein ap_hook_post_config(dav_init_handler, NULL, NULL, AP_HOOK_MIDDLE);
06cb1a83b6a1cfbe9c7815569e6c1d1408966ff7gstein ap_hook_type_checker(dav_type_checker, NULL, NULL, AP_HOOK_FIRST);
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*---------------------------------------------------------------------------
f4c310fd2555c6faca1f980f00b161eadb089023gstein**
f4c310fd2555c6faca1f980f00b161eadb089023gstein** Configuration info for the module
f4c310fd2555c6faca1f980f00b161eadb089023gstein*/
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const command_rec dav_cmds[] =
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein /* per directory/location */
000397350b42c6266351bd618fa07df929fa7c79gstein AP_INIT_TAKE1("DAV", dav_cmd_dav, NULL, ACCESS_CONF,
000397350b42c6266351bd618fa07df929fa7c79gstein "specify the DAV provider for a directory or location"),
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein /* per directory/location, or per server */
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein AP_INIT_TAKE1("DAVMinTimeout", dav_cmd_davmintimeout, NULL,
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein ACCESS_CONF|RSRC_CONF,
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein "specify minimum allowed timeout"),
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein /* per directory/location, or per server */
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein AP_INIT_FLAG("DAVDepthInfinity", dav_cmd_davdepthinfinity, NULL,
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein ACCESS_CONF|RSRC_CONF,
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein "allow Depth infinity PROPFIND requests"),
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein /* per directory/location, or per server */
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein AP_INIT_TAKE2("DAVParam", dav_cmd_davparam, NULL,
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein ACCESS_CONF|RSRC_CONF,
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein "DAVParam <parameter name> <parameter value>"),
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein { NULL }
f4c310fd2555c6faca1f980f00b161eadb089023gstein};
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic const handler_rec dav_handlers[] =
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein {"dav-handler", dav_handler},
f4c310fd2555c6faca1f980f00b161eadb089023gstein { NULL }
f4c310fd2555c6faca1f980f00b161eadb089023gstein};
f4c310fd2555c6faca1f980f00b161eadb089023gstein
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowemodule DAV_DECLARE_DATA dav_module =
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein STANDARD20_MODULE_STUFF,
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_create_dir_config, /* dir config creater */
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_merge_dir_config, /* dir merger --- default is to override */
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_create_server_config, /* server config */
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_merge_server_config, /* merge server config */
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_cmds, /* command table */
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_handlers, /* handlers */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein register_hooks, /* register hooks */
f4c310fd2555c6faca1f980f00b161eadb089023gstein};
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein
ba8574a7fe6f1c3405982bb856591b5f13fe205agsteinAP_HOOK_STRUCT(
6b745319b1099edacf401e8911efa480440f999agstein AP_HOOK_LINK(gather_propsets)
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein AP_HOOK_LINK(find_liveprop)
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein AP_HOOK_LINK(insert_all_liveprops)
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein )
98e9c4a310bb623ff788680f88b6bd200ff36a24wroweAP_IMPLEMENT_EXTERNAL_HOOK_VOID(DAV, gather_propsets,
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe (apr_array_header_t *uris),
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe (uris))
98e9c4a310bb623ff788680f88b6bd200ff36a24wroweAP_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(DAV, int, find_liveprop,
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe (request_rec *r, const char *ns_uri,
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe const char *name,
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe const dav_hooks_liveprop **hooks),
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe (r, ns_uri, name, hooks), 0);
98e9c4a310bb623ff788680f88b6bd200ff36a24wroweAP_IMPLEMENT_EXTERNAL_HOOK_VOID(DAV, insert_all_liveprops,
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe (request_rec *r, const dav_resource *resource,
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe int insvalue, ap_text_header *phdr),
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowe (r, resource, insvalue, phdr));