842ae4bd224140319ae7feec1872b93dfd491143fielding/* Licensed to the Apache Software Foundation (ASF) under one or more
842ae4bd224140319ae7feec1872b93dfd491143fielding * contributor license agreements. See the NOTICE file distributed with
842ae4bd224140319ae7feec1872b93dfd491143fielding * this work for additional information regarding copyright ownership.
842ae4bd224140319ae7feec1872b93dfd491143fielding * The ASF licenses this file to You under the Apache License, Version 2.0
842ae4bd224140319ae7feec1872b93dfd491143fielding * (the "License"); you may not use this file except in compliance with
842ae4bd224140319ae7feec1872b93dfd491143fielding * the License. You may obtain a copy of the License at
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
71da3cca78eea6010f89b139ecadb79e6d213c4fnd * http://www.apache.org/licenses/LICENSE-2.0
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein *
71da3cca78eea6010f89b139ecadb79e6d213c4fnd * Unless required by applicable law or agreed to in writing, software
71da3cca78eea6010f89b139ecadb79e6d213c4fnd * distributed under the License is distributed on an "AS IS" BASIS,
71da3cca78eea6010f89b139ecadb79e6d213c4fnd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
71da3cca78eea6010f89b139ecadb79e6d213c4fnd * See the License for the specific language governing permissions and
71da3cca78eea6010f89b139ecadb79e6d213c4fnd * limitations under the License.
b0fb330a8581c8bfab5e523084f9f39264a52b12gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * DAV extension module for Apache 2.0.*
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * This module is repository-independent. It depends on hooks provided by a
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * repository implementation.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * APACHE ISSUES:
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * - within a DAV hierarchy, if an unknown method is used and we default
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * to Apache's implementation, it sends back an OPTIONS with the wrong
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * set of methods -- there is NO HOOK for us.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * therefore: we need to manually handle the HTTP_METHOD_NOT_ALLOWED
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * and HTTP_NOT_IMPLEMENTED responses (not ap_send_error_response).
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * - process_mkcol_body() had to dup code from ap_setup_client_block().
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * - it would be nice to get status lines from Apache for arbitrary
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * status codes
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * - it would be nice to be able to extend Apache's set of response
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * codes so that it doesn't return 500 when an unknown code is placed
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * into r->status.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * - http_vhost functions should apply "const" to their params
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * DESIGN NOTES:
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * - For PROPFIND, we batch up the entire response in memory before
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * sending it. We may want to reorganize around sending the information
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * as we suck it in from the propdb. Alternatively, we should at least
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * generate a total Content-Length if we're going to buffer in memory
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * so that we can keep the connection open.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1b21d7b3d97def358b2e923655edeb16613a1c31gstein#include "apr_strings.h"
1327b173ab33ae5bec795b798d5c54c16a7b5c05gstein#include "apr_lib.h" /* for apr_is* */
1b21d7b3d97def358b2e923655edeb16613a1c31gstein
1b21d7b3d97def358b2e923655edeb16613a1c31gstein#define APR_WANT_STRFUNC
1b21d7b3d97def358b2e923655edeb16613a1c31gstein#include "apr_want.h"
1b21d7b3d97def358b2e923655edeb16613a1c31gstein
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"
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein#include "mod_dav.h"
f4c310fd2555c6faca1f980f00b161eadb089023gstein
847b3922f7dcde6830f4aad49d29c84b4569c260minfrin#include "ap_provider.h"
847b3922f7dcde6830f4aad49d29c84b4569c260minfrin
f4c310fd2555c6faca1f980f00b161eadb089023gstein
000397350b42c6266351bd618fa07df929fa7c79gstein/* ### what is the best way to set this? */
000397350b42c6266351bd618fa07df929fa7c79gstein#define DAV_DEFAULT_PROVIDER "filesystem"
000397350b42c6266351bd618fa07df929fa7c79gstein
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein/* used to denote that mod_dav will be handling this request */
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein#define DAV_HANDLER_NAME "dav-handler"
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein
36ef8f77bffe75d1aa327882be1b5bdbe2ff567asfAPLOG_USE_MODULE(dav);
36ef8f77bffe75d1aa327882be1b5bdbe2ff567asf
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
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) \
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ((child)->field ? (child)->field : (parent)->field)
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* forward-declare for use in configuration lookup */
98e9c4a310bb623ff788680f88b6bd200ff36a24wroweextern module DAV_DECLARE_DATA dav_module;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
ef3c32d4a7accb38368c7b9face2ade88d987a8bgstein/* DAV methods */
ef3c32d4a7accb38368c7b9face2ade88d987a8bgsteinenum {
5a9667916c79d8c699b069068e5570aa1c331c80gstein DAV_M_BIND = 0,
67ec15681c83d4f5e119f0742618569017beb3fbstriker DAV_M_SEARCH,
ef3c32d4a7accb38368c7b9face2ade88d987a8bgstein DAV_M_LAST
ef3c32d4a7accb38368c7b9face2ade88d987a8bgstein};
ef3c32d4a7accb38368c7b9face2ade88d987a8bgsteinstatic int dav_methods[DAV_M_LAST];
ef3c32d4a7accb38368c7b9face2ade88d987a8bgstein
5a9667916c79d8c699b069068e5570aa1c331c80gstein
9d0665da83d1e22c0ea0e5f6f940f70f75bf5237ianhstatic int 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
ef3c32d4a7accb38368c7b9face2ade88d987a8bgstein /* Register DAV methods */
ef3c32d4a7accb38368c7b9face2ade88d987a8bgstein dav_methods[DAV_M_BIND] = ap_method_register(p, "BIND");
67ec15681c83d4f5e119f0742618569017beb3fbstriker dav_methods[DAV_M_SEARCH] = ap_method_register(p, "SEARCH");
ef3c32d4a7accb38368c7b9face2ade88d987a8bgstein
9d0665da83d1e22c0ea0e5f6f940f70f75bf5237ianh return OK;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic void *dav_create_server_config(apr_pool_t *p, server_rec *s)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_server_conf *newconf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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
3c290fd0361d6d9d84d97725eaf299456bddd6cfsf l = strlen(dir);
3c290fd0361d6d9d84d97725eaf299456bddd6cfsf d = apr_pstrmemdup(p, dir, l);
de18a9e85398b9c79c422f578633ed56c2747bbbgstein if (l > 1 && d[l - 1] == '/')
de18a9e85398b9c79c422f578633ed56c2747bbbgstein d[l - 1] = '\0';
de18a9e85398b9c79c422f578633ed56c2747bbbgstein conf->dir = d;
de18a9e85398b9c79c422f578633ed56c2747bbbgstein }
de18a9e85398b9c79c422f578633ed56c2747bbbgstein
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;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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) {
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, APLOGNO(00578)
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) {
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_error(APLOG_MARK, APLOG_ERR, 0, NULL, APLOGNO(00579)
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
f4c310fd2555c6faca1f980f00b161eadb089023gstein return newconf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3strikerstatic 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
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantzDAV_DECLARE(const dav_hooks_locks *) dav_get_lock_hooks(request_rec *r)
709df1e1c2e1710570f8cb4209497e88662829c3gstein{
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gstein return dav_get_provider(r)->locks;
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantzDAV_DECLARE(const dav_hooks_propdb *) dav_get_propdb_hooks(request_rec *r)
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gstein{
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gstein return dav_get_provider(r)->propdb;
709df1e1c2e1710570f8cb4209497e88662829c3gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantzDAV_DECLARE(const dav_hooks_vsn *) dav_get_vsn_hooks(request_rec *r)
709df1e1c2e1710570f8cb4209497e88662829c3gstein{
eb2abb2d3f87f28e99bcb282b91e432822b4d9b4gstein return dav_get_provider(r)->vsn;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantzDAV_DECLARE(const dav_hooks_binding *) dav_get_binding_hooks(request_rec *r)
7281ea331999debdc337b02ce37a3169e0e033a2gstein{
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_get_provider(r)->binding;
7281ea331999debdc337b02ce37a3169e0e033a2gstein}
7281ea331999debdc337b02ce37a3169e0e033a2gstein
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantzDAV_DECLARE(const dav_hooks_search *) dav_get_search_hooks(request_rec *r)
67ec15681c83d4f5e119f0742618569017beb3fbstriker{
67ec15681c83d4f5e119f0742618569017beb3fbstriker return dav_get_provider(r)->search;
67ec15681c83d4f5e119f0742618569017beb3fbstriker}
67ec15681c83d4f5e119f0742618569017beb3fbstriker
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{
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dav_dir_conf *conf = (dav_dir_conf *)config;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
000397350b42c6266351bd618fa07df929fa7c79gstein if (strcasecmp(arg1, "on") == 0) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker conf->provider_name = DAV_DEFAULT_PROVIDER;
000397350b42c6266351bd618fa07df929fa7c79gstein }
000397350b42c6266351bd618fa07df929fa7c79gstein else if (strcasecmp(arg1, "off") == 0) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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{
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dav_dir_conf *conf = (dav_dir_conf *)config;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (arg)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker conf->allow_depthinfinity = DAV_ENABLED_ON;
f4c310fd2555c6faca1f980f00b161eadb089023gstein else
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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{
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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** 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.
f39230a531b23d94f86a087963299bbe2e431a4agstein**
f39230a531b23d94f86a087963299bbe2e431a4agstein** ### this function is not logging any errors! (e.g. the body)
f4c310fd2555c6faca1f980f00b161eadb089023gstein*/
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_error_response(request_rec *r, int status, const char *body)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein r->status = status;
6ae44edfc69d005a18e000b9826ff5718abb7b11jkaluza r->status_line = ap_get_status_line(status);
5b03ba47ff7225cacb131f14b019332af27da960gstein
a1790fb35c4b352dab721370985c623a9f8f5062rpluem ap_set_content_type(r, "text/html; charset=ISO-8859-1");
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* begin the response now... */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rvputs(r,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker DAV_RESPONSE_BODY_1,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker r->status_line,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker DAV_RESPONSE_BODY_2,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker &r->status_line[4],
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker DAV_RESPONSE_BODY_3,
f5d88bab65052e00ba37a1af17e5e67a437628b5wrowe body,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker DAV_RESPONSE_BODY_4,
f5d88bab65052e00ba37a1af17e5e67a437628b5wrowe ap_psignature("<hr />\n", r),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker DAV_RESPONSE_BODY_5,
f5d88bab65052e00ba37a1af17e5e67a437628b5wrowe NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* the response has been sent. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein * ### Use of DONE obviates logging..!
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DONE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
5b03ba47ff7225cacb131f14b019332af27da960gstein
5b03ba47ff7225cacb131f14b019332af27da960gstein/*
5b03ba47ff7225cacb131f14b019332af27da960gstein * Send a "standardized" error response based on the error's namespace & tag
5b03ba47ff7225cacb131f14b019332af27da960gstein */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3strikerstatic int dav_error_response_tag(request_rec *r,
5b03ba47ff7225cacb131f14b019332af27da960gstein dav_error *err)
5b03ba47ff7225cacb131f14b019332af27da960gstein{
5b03ba47ff7225cacb131f14b019332af27da960gstein r->status = err->status;
5b03ba47ff7225cacb131f14b019332af27da960gstein
e0d102c882a7ed34d3eec24b36da49f097066a36stoddard ap_set_content_type(r, DAV_XML_CONTENT_TYPE);
5b03ba47ff7225cacb131f14b019332af27da960gstein
5b03ba47ff7225cacb131f14b019332af27da960gstein ap_rputs(DAV_XML_HEADER DEBUG_CR
5b03ba47ff7225cacb131f14b019332af27da960gstein "<D:error xmlns:D=\"DAV:\"", r);
5b03ba47ff7225cacb131f14b019332af27da960gstein
5b03ba47ff7225cacb131f14b019332af27da960gstein if (err->desc != NULL) {
5b03ba47ff7225cacb131f14b019332af27da960gstein /* ### should move this namespace somewhere (with the others!) */
5b03ba47ff7225cacb131f14b019332af27da960gstein ap_rputs(" xmlns:m=\"http://apache.org/dav/xmlns\"", r);
5b03ba47ff7225cacb131f14b019332af27da960gstein }
5b03ba47ff7225cacb131f14b019332af27da960gstein
5b03ba47ff7225cacb131f14b019332af27da960gstein if (err->namespace != NULL) {
5b03ba47ff7225cacb131f14b019332af27da960gstein ap_rprintf(r,
5b03ba47ff7225cacb131f14b019332af27da960gstein " xmlns:C=\"%s\">" DEBUG_CR
5b03ba47ff7225cacb131f14b019332af27da960gstein "<C:%s/>" DEBUG_CR,
5b03ba47ff7225cacb131f14b019332af27da960gstein err->namespace, err->tagname);
5b03ba47ff7225cacb131f14b019332af27da960gstein }
5b03ba47ff7225cacb131f14b019332af27da960gstein else {
5b03ba47ff7225cacb131f14b019332af27da960gstein ap_rprintf(r,
5b03ba47ff7225cacb131f14b019332af27da960gstein ">" DEBUG_CR
5b03ba47ff7225cacb131f14b019332af27da960gstein "<D:%s/>" DEBUG_CR, err->tagname);
5b03ba47ff7225cacb131f14b019332af27da960gstein }
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
5b03ba47ff7225cacb131f14b019332af27da960gstein /* here's our mod_dav specific tag: */
5b03ba47ff7225cacb131f14b019332af27da960gstein if (err->desc != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_rprintf(r,
5b03ba47ff7225cacb131f14b019332af27da960gstein "<m:human-readable errcode=\"%d\">" DEBUG_CR
5b03ba47ff7225cacb131f14b019332af27da960gstein "%s" DEBUG_CR
5b03ba47ff7225cacb131f14b019332af27da960gstein "</m:human-readable>" DEBUG_CR,
5b03ba47ff7225cacb131f14b019332af27da960gstein err->error_id,
5b03ba47ff7225cacb131f14b019332af27da960gstein apr_xml_quote_string(r->pool, err->desc, 0));
5b03ba47ff7225cacb131f14b019332af27da960gstein }
5b03ba47ff7225cacb131f14b019332af27da960gstein
5b03ba47ff7225cacb131f14b019332af27da960gstein ap_rputs("</D:error>" DEBUG_CR, r);
5b03ba47ff7225cacb131f14b019332af27da960gstein
5b03ba47ff7225cacb131f14b019332af27da960gstein /* the response has been sent. */
5b03ba47ff7225cacb131f14b019332af27da960gstein /*
5b03ba47ff7225cacb131f14b019332af27da960gstein * ### Use of DONE obviates logging..!
5b03ba47ff7225cacb131f14b019332af27da960gstein */
5b03ba47ff7225cacb131f14b019332af27da960gstein return DONE;
5b03ba47ff7225cacb131f14b019332af27da960gstein}
5b03ba47ff7225cacb131f14b019332af27da960gstein
5b03ba47ff7225cacb131f14b019332af27da960gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Apache's URI escaping does not replace '&' since that is a valid character
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * in a URI (to form a query section). We must explicitly handle it so that
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * we can embed the URI into an XML document.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
1ccd992d37d62c8cb2056126f2234f64ec189bfddougmstatic const char *dav_xml_escape_uri(apr_pool_t *p, const char *uri)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
4f01ee597f569d80e2e81f912e425a572002328cbreser const char *e_uri = ap_escape_uri(p, uri);
4f01ee597f569d80e2e81f912e425a572002328cbreser
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* check the easy case... */
4f01ee597f569d80e2e81f912e425a572002328cbreser if (ap_strchr_c(e_uri, '&') == NULL)
4f01ee597f569d80e2e81f912e425a572002328cbreser return e_uri;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein /* there was a '&', so more work is needed... sigh. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Note: this is a teeny bit of overkill since we know there are no
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * '<' or '>' characters, but who cares.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
4f01ee597f569d80e2e81f912e425a572002328cbreser return apr_xml_quote_string(p, e_uri, 0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein/* Write a complete RESPONSE object out as a <DAV:repsonse> xml
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein element. Data is sent into brigade BB, which is auto-flushed into
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein OUTPUT filter stack. Use POOL for any temporary allocations.
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein [Presumably the <multistatus> tag has already been written; this
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein routine is shared by dav_send_multistatus and dav_stream_response.]
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein*/
87e4c2191581abcfaba8133868a1e9c96d9643a5gsteinstatic void dav_send_one_response(dav_response *response,
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein apr_bucket_brigade *bb,
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein ap_filter_t *output,
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein apr_pool_t *pool)
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein{
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein apr_text *t = NULL;
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein if (response->propresult.xmlns == NULL) {
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein ap_fputs(output, bb, "<D:response>");
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein }
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein else {
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein ap_fputs(output, bb, "<D:response");
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein for (t = response->propresult.xmlns; t; t = t->next) {
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein ap_fputs(output, bb, t->text);
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein }
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein ap_fputc(output, bb, '>');
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein }
e8f95a682820a599fe41b22977010636be5c2717jim
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein ap_fputstrs(output, bb,
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein DEBUG_CR "<D:href>",
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein dav_xml_escape_uri(pool, response->href),
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein "</D:href>" DEBUG_CR,
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein NULL);
e8f95a682820a599fe41b22977010636be5c2717jim
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein if (response->propresult.propstats == NULL) {
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein /* use the Status-Line text from Apache. Note, this will
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein * default to 500 Internal Server Error if first->status
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein * is not a known (or valid) status code.
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein */
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein ap_fputstrs(output, bb,
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein "<D:status>HTTP/1.1 ",
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein ap_get_status_line(response->status),
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein "</D:status>" DEBUG_CR,
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein NULL);
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein }
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein else {
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein /* assume this includes <propstat> and is quoted properly */
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein for (t = response->propresult.propstats; t; t = t->next) {
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein ap_fputs(output, bb, t->text);
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein }
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein }
e8f95a682820a599fe41b22977010636be5c2717jim
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein if (response->desc != NULL) {
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein /*
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein * We supply the description, so we know it doesn't have to
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein * have any escaping/encoding applied to it.
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein */
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein ap_fputstrs(output, bb,
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein "<D:responsedescription>",
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein response->desc,
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein "</D:responsedescription>" DEBUG_CR,
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein NULL);
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein }
e8f95a682820a599fe41b22977010636be5c2717jim
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein ap_fputs(output, bb, "</D:response>" DEBUG_CR);
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein}
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein/* Factorized helper function: prep request_rec R for a multistatus
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein response and write <multistatus> tag into BB, destined for
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein R->output_filters. Use xml NAMESPACES in initial tag, if
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein non-NULL. */
87e4c2191581abcfaba8133868a1e9c96d9643a5gsteinstatic void dav_begin_multistatus(apr_bucket_brigade *bb,
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein request_rec *r, int status,
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein apr_array_header_t *namespaces)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Set the correct status and Content-Type */
f4c310fd2555c6faca1f980f00b161eadb089023gstein r->status = status;
e0d102c882a7ed34d3eec24b36da49f097066a36stoddard ap_set_content_type(r, DAV_XML_CONTENT_TYPE);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
72360798a27566f28e2cbee0e39a0a6e3c3bd729wrowe /* Send the headers and actual multistatus response now... */
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein ap_fputs(r->output_filters, bb, DAV_XML_HEADER DEBUG_CR
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein "<D:multistatus xmlns:D=\"DAV:\"");
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (namespaces != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker int i;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker for (i = namespaces->nelts; i--; ) {
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein ap_fprintf(r->output_filters, bb, " xmlns:ns%d=\"%s\"", i,
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe APR_XML_GET_URI_ITEM(namespaces, i));
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein ap_fputs(r->output_filters, bb, ">" DEBUG_CR);
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
21aaa180f4f49d57612dcd5634e7a8eb0503edc6jorton/* Finish a multistatus response started by dav_begin_multistatus: */
21aaa180f4f49d57612dcd5634e7a8eb0503edc6jortonstatic apr_status_t dav_finish_multistatus(request_rec *r,
21aaa180f4f49d57612dcd5634e7a8eb0503edc6jorton apr_bucket_brigade *bb)
21aaa180f4f49d57612dcd5634e7a8eb0503edc6jorton{
21aaa180f4f49d57612dcd5634e7a8eb0503edc6jorton apr_bucket *b;
e8f95a682820a599fe41b22977010636be5c2717jim
21aaa180f4f49d57612dcd5634e7a8eb0503edc6jorton ap_fputs(r->output_filters, bb, "</D:multistatus>" DEBUG_CR);
e8f95a682820a599fe41b22977010636be5c2717jim
21aaa180f4f49d57612dcd5634e7a8eb0503edc6jorton /* indicate the end of the response body */
21aaa180f4f49d57612dcd5634e7a8eb0503edc6jorton b = apr_bucket_eos_create(r->connection->bucket_alloc);
21aaa180f4f49d57612dcd5634e7a8eb0503edc6jorton APR_BRIGADE_INSERT_TAIL(bb, b);
21aaa180f4f49d57612dcd5634e7a8eb0503edc6jorton
21aaa180f4f49d57612dcd5634e7a8eb0503edc6jorton /* deliver whatever might be remaining in the brigade */
21aaa180f4f49d57612dcd5634e7a8eb0503edc6jorton return ap_pass_brigade(r->output_filters, bb);
21aaa180f4f49d57612dcd5634e7a8eb0503edc6jorton}
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
87e4c2191581abcfaba8133868a1e9c96d9643a5gsteinstatic void dav_send_multistatus(request_rec *r, int status,
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein dav_response *first,
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein apr_array_header_t *namespaces)
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein{
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein apr_pool_t *subpool;
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein apr_bucket_brigade *bb = apr_brigade_create(r->pool,
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein r->connection->bucket_alloc);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein dav_begin_multistatus(bb, r, status, namespaces);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein apr_pool_create(&subpool, r->pool);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein for (; first != NULL; first = first->next) {
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein apr_pool_clear(subpool);
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein dav_send_one_response(first, bb, r->output_filters, subpool);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein apr_pool_destroy(subpool);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
21aaa180f4f49d57612dcd5634e7a8eb0503edc6jorton dav_finish_multistatus(r, bb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * dav_log_err()
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Write error information to the log.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (errscan->desc == NULL)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker continue;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
99d46a23c6eac800f327b29f8009f7d7da986230trawick ap_log_rerror(APLOG_MARK, level, errscan->aprerr, r, "%s [%d, #%d]",
99d46a23c6eac800f327b29f8009f7d7da986230trawick errscan->desc, errscan->status, errscan->error_id);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * dav_handle_err()
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Handle the standard error processing. <err> must be non-NULL.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * <response> is set by the following:
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * - dav_validate_request()
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * - dav_add_lock()
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * - repos_hooks->remove_resource
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * - repos_hooks->move_resource
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * - repos_hooks->copy_resource
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * - vsn_hooks->update
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_handle_err(request_rec *r, dav_error *err,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dav_response *response)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* log the errors */
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_log_err(r, err, APLOG_ERR);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1715880355ef7f574cae2e8f973411b51acededeylavic if (!ap_is_HTTP_VALID_RESPONSE(err->status)) {
1715880355ef7f574cae2e8f973411b51acededeylavic /* we have responded already */
1715880355ef7f574cae2e8f973411b51acededeylavic return AP_FILTER_ERROR;
1715880355ef7f574cae2e8f973411b51acededeylavic }
1715880355ef7f574cae2e8f973411b51acededeylavic
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (response == NULL) {
0dc04ceaaa28e4c949d82c7b066880eeb32a55f0gstein dav_error *stackerr = err;
0dc04ceaaa28e4c949d82c7b066880eeb32a55f0gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* our error messages are safe; tell Apache this */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker apr_table_setn(r->notes, "verbose-error-to", "*");
5b03ba47ff7225cacb131f14b019332af27da960gstein
0dc04ceaaa28e4c949d82c7b066880eeb32a55f0gstein /* Didn't get a multistatus response passed in, but we still
0dc04ceaaa28e4c949d82c7b066880eeb32a55f0gstein might be able to generate a standard <D:error> response.
0dc04ceaaa28e4c949d82c7b066880eeb32a55f0gstein Search the error stack for an errortag. */
0dc04ceaaa28e4c949d82c7b066880eeb32a55f0gstein while (stackerr != NULL && stackerr->tagname == NULL)
0dc04ceaaa28e4c949d82c7b066880eeb32a55f0gstein stackerr = stackerr->prev;
0dc04ceaaa28e4c949d82c7b066880eeb32a55f0gstein
0dc04ceaaa28e4c949d82c7b066880eeb32a55f0gstein if (stackerr != NULL && stackerr->tagname != NULL)
0dc04ceaaa28e4c949d82c7b066880eeb32a55f0gstein return dav_error_response_tag(r, stackerr);
5b03ba47ff7225cacb131f14b019332af27da960gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return err->status;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
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
22e9a19da7fd79a2801d99e6501b8f8470abdf6ebreser/* handy function for return values of methods that (may) create things.
22e9a19da7fd79a2801d99e6501b8f8470abdf6ebreser * locn if provided is assumed to be escaped. */
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) {
84cc33a59da2554b173504952e8ff72a1fc050a3breser locn = ap_escape_uri(r->pool, r->uri);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* did the target resource already exist? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (replaced) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* Apache will supply a default message */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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? */
0206c121a68a63559b2e843288e81bcf16093e46jerenkrantzDAV_DECLARE(int) 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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return def_depth;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (strcasecmp(depth, "infinity") == 0) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return DAV_INFINITY;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (strcmp(depth, "0") == 0) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (strcmp(depth, "1") == 0) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* The caller will return an HTTP_BAD_REQUEST. This will augment the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * default message that Apache provides. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00580)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return 1; /* default is "T" */
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((*overwrite == 'F' || *overwrite == 'f') && overwrite[1] == '\0') {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((*overwrite == 'T' || *overwrite == 't') && overwrite[1] == '\0') {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* The caller will return an HTTP_BAD_REQUEST. This will augment the
f4c310fd2555c6faca1f980f00b161eadb089023gstein * default message that Apache provides. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00581)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "An invalid Overwrite header was specified.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein return -1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein/* resolve a request URI to a resource descriptor.
f39230a531b23d94f86a087963299bbe2e431a4agstein *
f39230a531b23d94f86a087963299bbe2e431a4agstein * If label_allowed != 0, then allow the request target to be altered by
f39230a531b23d94f86a087963299bbe2e431a4agstein * a Label: header.
f39230a531b23d94f86a087963299bbe2e431a4agstein *
f39230a531b23d94f86a087963299bbe2e431a4agstein * If use_checked_in is true, then the repository provider should return
f39230a531b23d94f86a087963299bbe2e431a4agstein * the resource identified by the DAV:checked-in property of the resource
f39230a531b23d94f86a087963299bbe2e431a4agstein * identified by the Request-URI.
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3strikerstatic dav_error *dav_get_resource(request_rec *r, int label_allowed,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker int use_checked_in, dav_resource **res_p)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
5a47cad1aef57039cd47eb34ebbc2959c610f326gstein dav_dir_conf *conf;
f39230a531b23d94f86a087963299bbe2e431a4agstein const char *label = NULL;
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein dav_error *err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein /* if the request target can be overridden, get any target selector */
f39230a531b23d94f86a087963299bbe2e431a4agstein if (label_allowed) {
f39230a531b23d94f86a087963299bbe2e431a4agstein label = apr_table_get(r->headers_in, "label");
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein }
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein
9f18c80269be35c0b5653e84b0db0a24044722c4gstein conf = ap_get_module_config(r->per_dir_config, &dav_module);
9f18c80269be35c0b5653e84b0db0a24044722c4gstein /* assert: conf->provider != NULL */
441d366a564bc6faa7c1eaffbacf8c4f37862199minfrin if (conf->provider == NULL) {
441d366a564bc6faa7c1eaffbacf8c4f37862199minfrin return dav_new_error(r->pool, HTTP_METHOD_NOT_ALLOWED, 0, 0,
441d366a564bc6faa7c1eaffbacf8c4f37862199minfrin apr_psprintf(r->pool,
2f849349a8b1dd9c1f8523abffe99c96e995ddb2jailletc "DAV not enabled for %s",
2f849349a8b1dd9c1f8523abffe99c96e995ddb2jailletc ap_escape_html(r->pool, r->uri)));
441d366a564bc6faa7c1eaffbacf8c4f37862199minfrin }
9f18c80269be35c0b5653e84b0db0a24044722c4gstein
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein /* resolve the resource */
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein err = (*conf->provider->repos->get_resource)(r, conf->dir,
f39230a531b23d94f86a087963299bbe2e431a4agstein label, use_checked_in,
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein res_p);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (err != NULL) {
2c1c23b040db2a79518fb327b51471b42accb1a6gstein err = dav_push_error(r->pool, err->status, 0,
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein "Could not fetch resource information.", err);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return err;
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein }
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein /* Note: this shouldn't happen, but just be sure... */
5a47cad1aef57039cd47eb34ebbc2959c610f326gstein if (*res_p == NULL) {
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein /* ### maybe use HTTP_INTERNAL_SERVER_ERROR */
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(r->pool, HTTP_NOT_FOUND, 0, 0,
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein apr_psprintf(r->pool,
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein "The provider did not define a "
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein "resource for %s.",
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein ap_escape_html(r->pool, r->uri)));
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
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
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return NULL;
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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *lockdb = NULL;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* open the thing lazily */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return (*hooks->open_lockdb)(r, ro, 0, lockdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
97b692bfc8673c8858f03498f81a993ac0c04c01sf/**
97b692bfc8673c8858f03498f81a993ac0c04c01sf * @return 1 if valid content-range,
97b692bfc8673c8858f03498f81a993ac0c04c01sf * 0 if no content-range,
97b692bfc8673c8858f03498f81a993ac0c04c01sf * -1 if malformed content-range
97b692bfc8673c8858f03498f81a993ac0c04c01sf */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_parse_range(request_rec *r,
1327b173ab33ae5bec795b798d5c54c16a7b5c05gstein apr_off_t *range_start, apr_off_t *range_end)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein const char *range_c;
26250b0077972bf21b6d8a8d23772a4cf53f9477gstein char *range;
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *dash;
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *slash;
7fa1283f349463f76adf38290d02211ad15f5894nd char *errp;
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) {
97b692bfc8673c8858f03498f81a993ac0c04c01sf /* malformed header */
97b692bfc8673c8858f03498f81a993ac0c04c01sf return -1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
7fa1283f349463f76adf38290d02211ad15f5894nd *dash++ = *slash++ = '\0';
1327b173ab33ae5bec795b798d5c54c16a7b5c05gstein
97b692bfc8673c8858f03498f81a993ac0c04c01sf /* detect invalid ranges */
7fa1283f349463f76adf38290d02211ad15f5894nd if (apr_strtoff(range_start, range + 6, &errp, 10)
7fa1283f349463f76adf38290d02211ad15f5894nd || *errp || *range_start < 0) {
97b692bfc8673c8858f03498f81a993ac0c04c01sf return -1;
7fa1283f349463f76adf38290d02211ad15f5894nd }
7fa1283f349463f76adf38290d02211ad15f5894nd if (apr_strtoff(range_end, dash, &errp, 10)
7fa1283f349463f76adf38290d02211ad15f5894nd || *errp || *range_end < 0 || *range_end < *range_start) {
97b692bfc8673c8858f03498f81a993ac0c04c01sf return -1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
7fa1283f349463f76adf38290d02211ad15f5894nd if (*slash != '*') {
7fa1283f349463f76adf38290d02211ad15f5894nd apr_off_t dummy;
7fa1283f349463f76adf38290d02211ad15f5894nd
7fa1283f349463f76adf38290d02211ad15f5894nd if (apr_strtoff(&dummy, slash, &errp, 10)
7fa1283f349463f76adf38290d02211ad15f5894nd || *errp || dummy <= *range_end) {
97b692bfc8673c8858f03498f81a993ac0c04c01sf return -1;
7fa1283f349463f76adf38290d02211ad15f5894nd }
7fa1283f349463f76adf38290d02211ad15f5894nd }
7fa1283f349463f76adf38290d02211ad15f5894nd
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;
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein dav_error *err;
5bfc8a13ddae3da9bc10b3a23ebcbef19d874addstriker int status;
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 */
f39230a531b23d94f86a087963299bbe2e431a4agstein err = dav_get_resource(r, 1 /* label_allowed */, 0 /* use_checked_in */,
f39230a531b23d94f86a087963299bbe2e431a4agstein &resource);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (err != NULL)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return dav_handle_err(r, err, NULL);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->exists) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Apache will supply a default error for this. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return HTTP_NOT_FOUND;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein /* set up the HTTP headers for the response */
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein if ((err = (*resource->hooks->set_headers)(r, resource)) != NULL) {
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein err = dav_push_error(r->pool, err->status, 0,
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein "Unable to set up HTTP headers.",
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein err);
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
5bfc8a13ddae3da9bc10b3a23ebcbef19d874addstriker /* Handle conditional requests */
5bfc8a13ddae3da9bc10b3a23ebcbef19d874addstriker status = ap_meets_conditions(r);
5bfc8a13ddae3da9bc10b3a23ebcbef19d874addstriker if (status) {
5bfc8a13ddae3da9bc10b3a23ebcbef19d874addstriker return status;
5bfc8a13ddae3da9bc10b3a23ebcbef19d874addstriker }
5bfc8a13ddae3da9bc10b3a23ebcbef19d874addstriker
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein if (r->header_only) {
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein return DONE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein /* okay... time to deliver the content */
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein if ((err = (*resource->hooks->deliver)(resource,
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein r->output_filters)) != NULL) {
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein err = dav_push_error(r->pool, err->status, 0,
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein "Unable to deliver content.",
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein err);
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
b6c56e35c5ebdbe1da09806714fb579f3b8c648egstein return DONE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
4aca53840942c24d6cab01c91137dcf6bbfee31agstein/* validate resource/locks on POST, then pass to the default handler */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_method_post(request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *resource;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Ask repository module to resolve the resource */
f39230a531b23d94f86a087963299bbe2e431a4agstein err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
f39230a531b23d94f86a087963299bbe2e431a4agstein &resource);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (err != NULL)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Note: depth == 0. Implies no need for a multistatus response. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_validate_request(r, resource, 0, NULL, NULL,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker DAV_VALIDATE_RESOURCE, NULL)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### add a higher-level description? */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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 dav_stream_mode mode;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_stream *stream;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_response *multi_response;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int has_range;
1327b173ab33ae5bec795b798d5c54c16a7b5c05gstein apr_off_t range_start;
1327b173ab33ae5bec795b798d5c54c16a7b5c05gstein apr_off_t range_end;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Ask repository module to resolve the resource */
f39230a531b23d94f86a087963299bbe2e431a4agstein err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
f39230a531b23d94f86a087963299bbe2e431a4agstein &resource);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (err != NULL)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* If not a file or collection resource, PUT not allowed */
f80b9e9d38dff8bc3f51406475adb99d7fe888cegstein if (resource->type != DAV_RESOURCE_TYPE_REGULAR
f80b9e9d38dff8bc3f51406475adb99d7fe888cegstein && resource->type != DAV_RESOURCE_TYPE_WORKING) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm body = apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Cannot create resource %s with PUT.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_escape_html(r->pool, r->uri));
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, HTTP_CONFLICT, body);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Cannot PUT a collection */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resource->collection) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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 /*
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Note: depth == 0 normally requires no multistatus response. However,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * if we pass DAV_VALIDATE_PARENT, then we could get an error on a URI
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * other than the Request-URI, thereby requiring a multistatus.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * If the resource does not exist (DAV_RESOURCE_NULL), then we must
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * check the resource *and* its parent. If the resource exists or is
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * a locknull resource, then we check only the resource.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_validate_request(r, resource, 0, NULL, &multi_response,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker resource_state == DAV_RESOURCE_NULL ?
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker DAV_VALIDATE_PARENT :
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker DAV_VALIDATE_RESOURCE, NULL)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### add a higher-level description? */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, multi_response);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
97b692bfc8673c8858f03498f81a993ac0c04c01sf has_range = dav_parse_range(r, &range_start, &range_end);
97b692bfc8673c8858f03498f81a993ac0c04c01sf if (has_range < 0) {
97b692bfc8673c8858f03498f81a993ac0c04c01sf /* RFC 2616 14.16: If we receive an invalid Content-Range we must
97b692bfc8673c8858f03498f81a993ac0c04c01sf * not use the content.
97b692bfc8673c8858f03498f81a993ac0c04c01sf */
97b692bfc8673c8858f03498f81a993ac0c04c01sf body = apr_psprintf(r->pool,
97b692bfc8673c8858f03498f81a993ac0c04c01sf "Malformed Content-Range header for PUT %s.",
97b692bfc8673c8858f03498f81a993ac0c04c01sf ap_escape_html(r->pool, r->uri));
97b692bfc8673c8858f03498f81a993ac0c04c01sf return dav_error_response(r, HTTP_BAD_REQUEST, body);
97b692bfc8673c8858f03498f81a993ac0c04c01sf } else if (has_range) {
97b692bfc8673c8858f03498f81a993ac0c04c01sf mode = DAV_MODE_WRITE_SEEKABLE;
97b692bfc8673c8858f03498f81a993ac0c04c01sf }
97b692bfc8673c8858f03498f81a993ac0c04c01sf else {
97b692bfc8673c8858f03498f81a993ac0c04c01sf mode = DAV_MODE_WRITE_TRUNC;
97b692bfc8673c8858f03498f81a993ac0c04c01sf }
97b692bfc8673c8858f03498f81a993ac0c04c01sf
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* make sure the resource can be modified (if versioning repository) */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if ((err = dav_auto_checkout(r, resource,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 0 /* not parent_only */,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker &av_info)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### add a higher-level description? */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Create the new file in the repository */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = (*resource->hooks->open_stream)(resource, mode,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &stream)) != NULL) {
6d601599d3d65df0410eae6e573e75b2dbfb1fb4minfrin int status = err->status ? err->status : HTTP_FORBIDDEN;
6d601599d3d65df0410eae6e573e75b2dbfb1fb4minfrin if (status > 299) {
6d601599d3d65df0410eae6e573e75b2dbfb1fb4minfrin err = dav_push_error(r->pool, status, 0,
6d601599d3d65df0410eae6e573e75b2dbfb1fb4minfrin apr_psprintf(r->pool,
6d601599d3d65df0410eae6e573e75b2dbfb1fb4minfrin "Unable to PUT new contents for %s.",
6d601599d3d65df0410eae6e573e75b2dbfb1fb4minfrin ap_escape_html(r->pool, r->uri)),
6d601599d3d65df0410eae6e573e75b2dbfb1fb4minfrin err);
6d601599d3d65df0410eae6e573e75b2dbfb1fb4minfrin }
6d601599d3d65df0410eae6e573e75b2dbfb1fb4minfrin else {
6d601599d3d65df0410eae6e573e75b2dbfb1fb4minfrin err = NULL;
6d601599d3d65df0410eae6e573e75b2dbfb1fb4minfrin }
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) {
5b953b9aeef5b38cae481e062a7b5ac209a6170end apr_bucket_brigade *bb;
5b953b9aeef5b38cae481e062a7b5ac209a6170end apr_bucket *b;
5b953b9aeef5b38cae481e062a7b5ac209a6170end int seen_eos = 0;
5b953b9aeef5b38cae481e062a7b5ac209a6170end
5b953b9aeef5b38cae481e062a7b5ac209a6170end bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
5b953b9aeef5b38cae481e062a7b5ac209a6170end
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd do {
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd apr_status_t rc;
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd rc = ap_get_brigade(r->input_filters, bb, AP_MODE_READBYTES,
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd APR_BLOCK_READ, DAV_READ_BLOCKSIZE);
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd if (rc != APR_SUCCESS) {
d8cff78abd95dd96d47e54e2d979b25b5f1dab4asf int http_err;
d8cff78abd95dd96d47e54e2d979b25b5f1dab4asf char *msg = ap_escape_html(r->pool, r->uri);
d8cff78abd95dd96d47e54e2d979b25b5f1dab4asf if (APR_STATUS_IS_TIMEUP(rc)) {
d8cff78abd95dd96d47e54e2d979b25b5f1dab4asf http_err = HTTP_REQUEST_TIME_OUT;
d8cff78abd95dd96d47e54e2d979b25b5f1dab4asf msg = apr_psprintf(r->pool, "Timeout reading the body "
d8cff78abd95dd96d47e54e2d979b25b5f1dab4asf "(URI: %s)", msg);
d8cff78abd95dd96d47e54e2d979b25b5f1dab4asf }
d8cff78abd95dd96d47e54e2d979b25b5f1dab4asf else {
1715880355ef7f574cae2e8f973411b51acededeylavic http_err = ap_map_http_request_error(rc, HTTP_BAD_REQUEST);
a511a29faf2ff7ead3b67680154a624effb31aafminfrin msg = apr_psprintf(r->pool,
a511a29faf2ff7ead3b67680154a624effb31aafminfrin "An error occurred while reading"
a511a29faf2ff7ead3b67680154a624effb31aafminfrin " the request body (URI: %s)", msg);
d8cff78abd95dd96d47e54e2d979b25b5f1dab4asf }
d8cff78abd95dd96d47e54e2d979b25b5f1dab4asf err = dav_new_error(r->pool, http_err, 0, rc, msg);
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd break;
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd }
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd
2e7ef6efb7164346000607d5b5c2d2d392d1a5eajwoolley for (b = APR_BRIGADE_FIRST(bb);
2e7ef6efb7164346000607d5b5c2d2d392d1a5eajwoolley b != APR_BRIGADE_SENTINEL(bb);
2e7ef6efb7164346000607d5b5c2d2d392d1a5eajwoolley b = APR_BUCKET_NEXT(b))
2e7ef6efb7164346000607d5b5c2d2d392d1a5eajwoolley {
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd const char *data;
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd apr_size_t len;
5b953b9aeef5b38cae481e062a7b5ac209a6170end
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd if (APR_BUCKET_IS_EOS(b)) {
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd seen_eos = 1;
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd break;
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd }
5b953b9aeef5b38cae481e062a7b5ac209a6170end
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd if (APR_BUCKET_IS_METADATA(b)) {
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd continue;
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd }
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd if (err == NULL) {
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd /* write whatever we read, until we see an error */
691db92094897494d6c31326108da20088bc175etrawick rc = apr_bucket_read(b, &data, &len, APR_BLOCK_READ);
691db92094897494d6c31326108da20088bc175etrawick if (rc != APR_SUCCESS) {
691db92094897494d6c31326108da20088bc175etrawick err = dav_new_error(r->pool, HTTP_BAD_REQUEST, 0, rc,
691db92094897494d6c31326108da20088bc175etrawick apr_psprintf(r->pool,
691db92094897494d6c31326108da20088bc175etrawick "An error occurred while"
691db92094897494d6c31326108da20088bc175etrawick " reading the request body"
691db92094897494d6c31326108da20088bc175etrawick " from the bucket (URI: %s)",
691db92094897494d6c31326108da20088bc175etrawick ap_escape_html(r->pool, r->uri)));
691db92094897494d6c31326108da20088bc175etrawick break;
691db92094897494d6c31326108da20088bc175etrawick }
691db92094897494d6c31326108da20088bc175etrawick
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd err = (*resource->hooks->write_stream)(stream, data, len);
5b953b9aeef5b38cae481e062a7b5ac209a6170end }
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd }
5b953b9aeef5b38cae481e062a7b5ac209a6170end
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd apr_brigade_cleanup(bb);
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd } while (!seen_eos);
5b953b9aeef5b38cae481e062a7b5ac209a6170end
3a9fa07c2bcf1a6a3054cc8a8bed89a49947305dnd apr_brigade_destroy(bb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein err2 = (*resource->hooks->close_stream)(stream,
f4c310fd2555c6faca1f980f00b161eadb089023gstein err == NULL /* commit */);
691db92094897494d6c31326108da20088bc175etrawick err = dav_join_error(err, err2);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Ensure that we think the resource exists now.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * ### eek. if an error occurred during the write and we did not commit,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * ### then the resource might NOT exist (e.g. dav_fs_repos.c)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err == NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker resource->exists = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* restore modifiability of resources back to what they were */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein err2 = dav_auto_checkin(r, resource, err != NULL /* undo if error */,
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein 0 /*unlock*/, &av_info);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* check for errors now */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
691db92094897494d6c31326108da20088bc175etrawick err = dav_join_error(err, err2); /* don't forget err2 */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err2 != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* just log a warning */
423b7570b0e70f8f411f1c5da912377e3436ac20jorton err2 = dav_push_error(r->pool, err2->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The PUT was successful, but there "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "was a problem automatically checking in "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "the resource or its parent collection.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err2);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* The file creation was successful, but the locking failed. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The file was PUT successfully, but there "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "was a problem opening the lock database "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "which prevents inheriting locks from the "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "parent resources.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* notify lock system that we have created/replaced a resource */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_notify_created(r, lockdb, resource, resource_state, 0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker (*locks_hooks->close_lockdb)(lockdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (err != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* The file creation was successful, but the locking failed. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The file was PUT successfully, but there "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "was a problem updating its lock "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "information.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, NULL);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
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
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein/* Use POOL to temporarily construct a dav_response object (from WRES
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein STATUS, and PROPSTATS) and stream it via WRES's ctx->brigade. */
87e4c2191581abcfaba8133868a1e9c96d9643a5gsteinstatic void dav_stream_response(dav_walk_resource *wres,
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein int status,
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein dav_get_props_result *propstats,
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein apr_pool_t *pool)
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein{
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein dav_response resp = { 0 };
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein dav_walker_ctx *ctx = wres->walk_ctx;
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein resp.href = wres->resource->uri;
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein resp.status = status;
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein if (propstats) {
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein resp.propresult = *propstats;
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein }
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein dav_send_one_response(&resp, ctx->bb, ctx->r->output_filters, pool);
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein}
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein
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{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_response *resp;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* just drop some data into an dav_response */
00f73f5096966f34c7db15562e5d2e1233eb4571gstein resp = apr_pcalloc(wres->pool, sizeof(*resp));
00f73f5096966f34c7db15562e5d2e1233eb4571gstein resp->href = apr_pstrdup(wres->pool, wres->resource->uri);
f4c310fd2555c6faca1f980f00b161eadb089023gstein resp->status = status;
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (propstats) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker resp->propresult = *propstats;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein resp->next = wres->response;
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein wres->response = resp;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein
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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Ask repository module to resolve the resource */
f39230a531b23d94f86a087963299bbe2e431a4agstein err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
f39230a531b23d94f86a087963299bbe2e431a4agstein &resource);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (err != NULL)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->exists) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Apache will supply a default error for this. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* This supplies additional information for the default message. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00582)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Depth must be \"infinity\" for DELETE of a collection.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->collection && depth == 1) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* This supplies additional information for the default message. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00583)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Depth of \"1\" is not allowed for DELETE.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker &multi_response,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker DAV_VALIDATE_PARENT
f4c310fd2555c6faca1f980f00b161eadb089023gstein | DAV_VALIDATE_USE_424, NULL)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Could not DELETE %s due to a failed "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "precondition (e.g. locks).",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_escape_html(r->pool, r->uri)),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* if versioned resource, make sure parent is checked out */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if ((err = dav_auto_checkout(r, resource, 1 /* parent_only */,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker &av_info)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### add a higher-level description? */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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 */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein err2 = dav_auto_checkin(r, NULL, err != NULL /* undo if error */,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 0 /*unlock*/, &av_info);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* check for errors now */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Could not DELETE %s.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_escape_html(r->pool, r->uri)),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, multi_response);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err2 != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* just log a warning */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err2->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The DELETE was successful, but there "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "was a problem automatically checking in "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "the parent collection.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err2);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein/* generate DAV:supported-method-set OPTIONS response */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gsteinstatic dav_error *dav_gen_supported_methods(request_rec *r,
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe const apr_xml_elem *elem,
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein const apr_table_t *methods,
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_header *body)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein{
d4f351074a8f7af5e41aa0a70410816436608e3dianh const apr_array_header_t *arr;
d4f351074a8f7af5e41aa0a70410816436608e3dianh const apr_table_entry_t *elts;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_elem *child;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_attr *attr;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein char *s;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein int i;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(r->pool, body, "<D:supported-method-set>" DEBUG_CR);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (elem->first_child == NULL) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* show all supported methods */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein arr = apr_table_elts(methods);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker elts = (const apr_table_entry_t *)arr->elts;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein for (i = 0; i < arr->nelts; ++i) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (elts[i].key == NULL)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein continue;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein s = apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "<D:supported-method D:name=\"%s\"/>"
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker DEBUG_CR,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker elts[i].key);
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(r->pool, body, s);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein else {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* check for support of specific methods */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein for (child = elem->first_child; child != NULL; child = child->next) {
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe if (child->ns == APR_XML_NS_DAV_ID
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein && strcmp(child->name, "supported-method") == 0) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein const char *name = NULL;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* go through attributes to find method name */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein for (attr = child->attr; attr != NULL; attr = attr->next) {
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe if (attr->ns == APR_XML_NS_DAV_ID
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein && strcmp(attr->name, "name") == 0)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein name = attr->value;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (name == NULL) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(r->pool, HTTP_BAD_REQUEST, 0, 0,
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein "A DAV:supported-method element "
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein "does not have a \"name\" attribute");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* see if method is supported */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (apr_table_get(methods, name) != NULL) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein s = apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "<D:supported-method D:name=\"%s\"/>"
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker DEBUG_CR,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker name);
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(r->pool, body, s);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(r->pool, body, "</D:supported-method-set>" DEBUG_CR);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein return NULL;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein}
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein/* generate DAV:supported-live-property-set OPTIONS response */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gsteinstatic dav_error *dav_gen_supported_live_props(request_rec *r,
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein const dav_resource *resource,
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe const apr_xml_elem *elem,
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_header *body)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein{
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein dav_lockdb *lockdb;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein dav_propdb *propdb;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_elem *child;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_attr *attr;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein dav_error *err;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* open lock database, to report on supported lock properties */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* ### should open read-only */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if ((err = dav_open_lockdb(r, 0, &lockdb)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The lock database could not be opened, "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "preventing the reporting of supported lock "
bbba27074551817d7c6a606c4362965c26a0777egstein "properties.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* open the property database (readonly) for the resource */
bbba27074551817d7c6a606c4362965c26a0777egstein if ((err = dav_open_propdb(r, lockdb, resource, 1, NULL,
bbba27074551817d7c6a606c4362965c26a0777egstein &propdb)) != NULL) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (lockdb != NULL)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein (*lockdb->hooks->close_lockdb)(lockdb);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The property database could not be opened, "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "preventing report of supported properties.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(r->pool, body, "<D:supported-live-property-set>" DEBUG_CR);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (elem->first_child == NULL) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* show all supported live properties */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein dav_get_props_result props = dav_get_allprops(propdb, DAV_PROP_INSERT_SUPPORTED);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein body->last->next = props.propstats;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein while (body->last->next != NULL)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein body->last = body->last->next;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein else {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* check for support of specific live property */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein for (child = elem->first_child; child != NULL; child = child->next) {
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe if (child->ns == APR_XML_NS_DAV_ID
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein && strcmp(child->name, "supported-live-property") == 0) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein const char *name = NULL;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein const char *nmspace = NULL;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* go through attributes to find name and namespace */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein for (attr = child->attr; attr != NULL; attr = attr->next) {
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe if (attr->ns == APR_XML_NS_DAV_ID) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (strcmp(attr->name, "name") == 0)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein name = attr->value;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein else if (strcmp(attr->name, "namespace") == 0)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein nmspace = attr->value;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (name == NULL) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick err = dav_new_error(r->pool, HTTP_BAD_REQUEST, 0, 0,
bbba27074551817d7c6a606c4362965c26a0777egstein "A DAV:supported-live-property "
bbba27074551817d7c6a606c4362965c26a0777egstein "element does not have a \"name\" "
bbba27074551817d7c6a606c4362965c26a0777egstein "attribute");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein break;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* default namespace to DAV: */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (nmspace == NULL)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein nmspace = "DAV:";
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* check for support of property */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein dav_get_liveprop_supported(propdb, nmspace, name, body);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(r->pool, body, "</D:supported-live-property-set>" DEBUG_CR);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein dav_close_propdb(propdb);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (lockdb != NULL)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein (*lockdb->hooks->close_lockdb)(lockdb);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein return err;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein}
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein/* generate DAV:supported-report-set OPTIONS response */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gsteinstatic dav_error *dav_gen_supported_reports(request_rec *r,
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein const dav_resource *resource,
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe const apr_xml_elem *elem,
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein const dav_hooks_vsn *vsn_hooks,
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_header *body)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein{
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_elem *child;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_attr *attr;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein dav_error *err;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein char *s;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(r->pool, body, "<D:supported-report-set>" DEBUG_CR);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (vsn_hooks != NULL) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein const dav_report_elem *reports;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein const dav_report_elem *rp;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if ((err = (*vsn_hooks->avail_reports)(resource, &reports)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_push_error(r->pool, err->status, 0,
bbba27074551817d7c6a606c4362965c26a0777egstein "DAV:supported-report-set could not be "
bbba27074551817d7c6a606c4362965c26a0777egstein "determined due to a problem fetching the "
bbba27074551817d7c6a606c4362965c26a0777egstein "available reports for this resource.",
bbba27074551817d7c6a606c4362965c26a0777egstein err);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (reports != NULL) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (elem->first_child == NULL) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* show all supported reports */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein for (rp = reports; rp->nmspace != NULL; ++rp) {
e8f95a682820a599fe41b22977010636be5c2717jim /* Note: we presume reports->namespace is
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * properly XML/URL quoted */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein s = apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "<D:supported-report D:name=\"%s\" "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "D:namespace=\"%s\"/>" DEBUG_CR,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker rp->name, rp->nmspace);
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(r->pool, body, s);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein else {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* check for support of specific report */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein for (child = elem->first_child; child != NULL; child = child->next) {
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe if (child->ns == APR_XML_NS_DAV_ID
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein && strcmp(child->name, "supported-report") == 0) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein const char *name = NULL;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein const char *nmspace = NULL;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* go through attributes to find name and namespace */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein for (attr = child->attr; attr != NULL; attr = attr->next) {
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe if (attr->ns == APR_XML_NS_DAV_ID) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (strcmp(attr->name, "name") == 0)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein name = attr->value;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein else if (strcmp(attr->name, "namespace") == 0)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein nmspace = attr->value;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (name == NULL) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick return dav_new_error(r->pool, HTTP_BAD_REQUEST, 0, 0,
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein "A DAV:supported-report element "
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein "does not have a \"name\" attribute");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* default namespace to DAV: */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (nmspace == NULL)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein nmspace = "DAV:";
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein for (rp = reports; rp->nmspace != NULL; ++rp) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (strcmp(name, rp->name) == 0
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein && strcmp(nmspace, rp->nmspace) == 0) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* Note: we presume reports->nmspace is
e8f95a682820a599fe41b22977010636be5c2717jim * properly XML/URL quoted
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein s = apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "<D:supported-report "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "D:name=\"%s\" "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "D:namespace=\"%s\"/>"
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker DEBUG_CR,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker rp->name, rp->nmspace);
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(r->pool, body, s);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein break;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(r->pool, body, "</D:supported-report-set>" DEBUG_CR);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein return NULL;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein}
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
67ec15681c83d4f5e119f0742618569017beb3fbstriker
67ec15681c83d4f5e119f0742618569017beb3fbstriker/* handle the SEARCH method */
67ec15681c83d4f5e119f0742618569017beb3fbstrikerstatic int dav_method_search(request_rec *r)
67ec15681c83d4f5e119f0742618569017beb3fbstriker{
67ec15681c83d4f5e119f0742618569017beb3fbstriker const dav_hooks_search *search_hooks = DAV_GET_HOOKS_SEARCH(r);
67ec15681c83d4f5e119f0742618569017beb3fbstriker dav_resource *resource;
67ec15681c83d4f5e119f0742618569017beb3fbstriker dav_error *err;
67ec15681c83d4f5e119f0742618569017beb3fbstriker dav_response *multi_status;
67ec15681c83d4f5e119f0742618569017beb3fbstriker
67ec15681c83d4f5e119f0742618569017beb3fbstriker /* If no search provider, decline the request */
67ec15681c83d4f5e119f0742618569017beb3fbstriker if (search_hooks == NULL)
67ec15681c83d4f5e119f0742618569017beb3fbstriker return DECLINED;
67ec15681c83d4f5e119f0742618569017beb3fbstriker
67ec15681c83d4f5e119f0742618569017beb3fbstriker /* This method should only be called when the resource is not
67ec15681c83d4f5e119f0742618569017beb3fbstriker * visible to Apache. We will fetch the resource from the repository,
67ec15681c83d4f5e119f0742618569017beb3fbstriker * then create a subrequest for Apache to handle.
67ec15681c83d4f5e119f0742618569017beb3fbstriker */
67ec15681c83d4f5e119f0742618569017beb3fbstriker err = dav_get_resource(r, 1 /* label_allowed */, 0 /* use_checked_in */,
67ec15681c83d4f5e119f0742618569017beb3fbstriker &resource);
67ec15681c83d4f5e119f0742618569017beb3fbstriker if (err != NULL)
67ec15681c83d4f5e119f0742618569017beb3fbstriker return dav_handle_err(r, err, NULL);
67ec15681c83d4f5e119f0742618569017beb3fbstriker
67ec15681c83d4f5e119f0742618569017beb3fbstriker if (!resource->exists) {
67ec15681c83d4f5e119f0742618569017beb3fbstriker /* Apache will supply a default error for this. */
67ec15681c83d4f5e119f0742618569017beb3fbstriker return HTTP_NOT_FOUND;
67ec15681c83d4f5e119f0742618569017beb3fbstriker }
67ec15681c83d4f5e119f0742618569017beb3fbstriker
67ec15681c83d4f5e119f0742618569017beb3fbstriker /* set up the HTTP headers for the response */
67ec15681c83d4f5e119f0742618569017beb3fbstriker if ((err = (*resource->hooks->set_headers)(r, resource)) != NULL) {
67ec15681c83d4f5e119f0742618569017beb3fbstriker err = dav_push_error(r->pool, err->status, 0,
67ec15681c83d4f5e119f0742618569017beb3fbstriker "Unable to set up HTTP headers.",
67ec15681c83d4f5e119f0742618569017beb3fbstriker err);
67ec15681c83d4f5e119f0742618569017beb3fbstriker return dav_handle_err(r, err, NULL);
67ec15681c83d4f5e119f0742618569017beb3fbstriker }
67ec15681c83d4f5e119f0742618569017beb3fbstriker
67ec15681c83d4f5e119f0742618569017beb3fbstriker if (r->header_only) {
67ec15681c83d4f5e119f0742618569017beb3fbstriker return DONE;
67ec15681c83d4f5e119f0742618569017beb3fbstriker }
67ec15681c83d4f5e119f0742618569017beb3fbstriker
67ec15681c83d4f5e119f0742618569017beb3fbstriker /* okay... time to search the content */
67ec15681c83d4f5e119f0742618569017beb3fbstriker /* Let's validate XML and process walk function
67ec15681c83d4f5e119f0742618569017beb3fbstriker * in the hook function
67ec15681c83d4f5e119f0742618569017beb3fbstriker */
67ec15681c83d4f5e119f0742618569017beb3fbstriker if ((err = (*search_hooks->search_resource)(r, &multi_status)) != NULL) {
67ec15681c83d4f5e119f0742618569017beb3fbstriker /* ### add a higher-level description? */
67ec15681c83d4f5e119f0742618569017beb3fbstriker return dav_handle_err(r, err, NULL);
67ec15681c83d4f5e119f0742618569017beb3fbstriker }
67ec15681c83d4f5e119f0742618569017beb3fbstriker
67ec15681c83d4f5e119f0742618569017beb3fbstriker /* We have results in multi_status */
67ec15681c83d4f5e119f0742618569017beb3fbstriker /* Should I pass namespace?? */
67ec15681c83d4f5e119f0742618569017beb3fbstriker dav_send_multistatus(r, HTTP_MULTI_STATUS, multi_status, NULL);
67ec15681c83d4f5e119f0742618569017beb3fbstriker
67ec15681c83d4f5e119f0742618569017beb3fbstriker return DONE;
67ec15681c83d4f5e119f0742618569017beb3fbstriker}
67ec15681c83d4f5e119f0742618569017beb3fbstriker
67ec15681c83d4f5e119f0742618569017beb3fbstriker
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);
67ec15681c83d4f5e119f0742618569017beb3fbstriker const dav_hooks_search *search_hooks = DAV_GET_HOOKS_SEARCH(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *resource;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const char *dav_level;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein char *allow;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein char *s;
d4f351074a8f7af5e41aa0a70410816436608e3dianh const apr_array_header_t *arr;
d4f351074a8f7af5e41aa0a70410816436608e3dianh const apr_table_entry_t *elts;
066877f1a045103acfdd376d48cdd473c33f409bdougm apr_table_t *methods = apr_table_make(r->pool, 12);
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_header vsn_options = { 0 };
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_header body = { 0 };
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text *t;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein int text_size;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int result;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein int i;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_array_header_t *uri_ary;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_doc *doc;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe const apr_xml_elem *elem;
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein dav_error *err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
847b3922f7dcde6830f4aad49d29c84b4569c260minfrin apr_array_header_t *extensions;
847b3922f7dcde6830f4aad49d29c84b4569c260minfrin ap_list_provider_names_t *entry;
847b3922f7dcde6830f4aad49d29c84b4569c260minfrin
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* resolve the resource */
f39230a531b23d94f86a087963299bbe2e431a4agstein err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
f39230a531b23d94f86a087963299bbe2e431a4agstein &resource);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (err != NULL)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* parse any request body */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if ((result = ap_xml_parse_input(r, &doc)) != OK) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return result;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* note: doc == NULL if no request body */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (doc && !dav_validate_root(doc, "options")) {
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00584)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The \"options\" element was not found.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* determine which providers are available */
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_level = "1";
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (locks_hooks != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_level = "1,2";
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (binding_hooks != NULL)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dav_level = apr_pstrcat(r->pool, dav_level, ",bindings", NULL);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
847b3922f7dcde6830f4aad49d29c84b4569c260minfrin /* DAV header additions registered by external modules */
847b3922f7dcde6830f4aad49d29c84b4569c260minfrin extensions = ap_list_provider_names(r->pool, DAV_OPTIONS_EXTENSION_GROUP, "0");
847b3922f7dcde6830f4aad49d29c84b4569c260minfrin entry = (ap_list_provider_names_t *)extensions->elts;
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim
847b3922f7dcde6830f4aad49d29c84b4569c260minfrin for (i = 0; i < extensions->nelts; i++, entry++) {
11e076839c8d5a82d55e710194d0daac51390dbdsf const dav_options_provider *options =
11e076839c8d5a82d55e710194d0daac51390dbdsf dav_get_options_providers(entry->provider_name);
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim
11e076839c8d5a82d55e710194d0daac51390dbdsf if (options && options->dav_header) {
11e076839c8d5a82d55e710194d0daac51390dbdsf apr_text_header hoptions = { 0 };
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim
11e076839c8d5a82d55e710194d0daac51390dbdsf options->dav_header(r, resource, &hoptions);
11e076839c8d5a82d55e710194d0daac51390dbdsf for (t = hoptions.first; t && t->text; t = t->next)
11e076839c8d5a82d55e710194d0daac51390dbdsf dav_level = apr_pstrcat(r->pool, dav_level, ",", t->text, NULL);
11e076839c8d5a82d55e710194d0daac51390dbdsf }
847b3922f7dcde6830f4aad49d29c84b4569c260minfrin }
847b3922f7dcde6830f4aad49d29c84b4569c260minfrin
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* ###
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * MSFT Web Folders chokes if length of DAV header value > 63 characters!
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * To workaround that, we use separate DAV headers for versioning and
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * live prop provider namespace URIs.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * ###
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_setn(r->headers_out, "DAV", dav_level);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /*
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * If there is a versioning provider, generate DAV headers
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * for versioning options.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (vsn_hooks != NULL) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein (*vsn_hooks->get_vsn_options)(r->pool, &vsn_options);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein for (t = vsn_options.first; t != NULL; t = t->next)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(r->headers_out, "DAV", t->text);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /*
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Gather property set URIs from all the liveprop providers,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * and generate a separate DAV header for each URI, to avoid
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * problems with long header lengths.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
066877f1a045103acfdd376d48cdd473c33f409bdougm uri_ary = apr_array_make(r->pool, 5, sizeof(const char *));
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe dav_run_gather_propsets(uri_ary);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein for (i = 0; i < uri_ary->nelts; ++i) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (((char **)uri_ary->elts)[i] != NULL)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(r->headers_out, "DAV", ((char **)uri_ary->elts)[i]);
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 /*
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Determine which methods are allowed on the resource.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Three cases: resource is null (3), is lock-null (7.4), or exists.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * All cases support OPTIONS, and if there is a lock provider, LOCK.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * (Lock-) null resources also support MKCOL and PUT.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Lock-null supports PROPFIND and UNLOCK.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Existing resources support lots of stuff.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "OPTIONS", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### take into account resource type */
f4c310fd2555c6faca1f980f00b161eadb089023gstein switch (dav_get_resource_state(r, resource))
f4c310fd2555c6faca1f980f00b161eadb089023gstein {
f4c310fd2555c6faca1f980f00b161eadb089023gstein case DAV_RESOURCE_EXISTS:
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* resource exists */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "GET", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "HEAD", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "POST", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "DELETE", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "TRACE", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "PROPFIND", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "PROPPATCH", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "COPY", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "MOVE", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (!resource->collection)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "PUT", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (locks_hooks != NULL) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "LOCK", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "UNLOCK", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein case DAV_RESOURCE_LOCK_NULL:
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* resource is lock-null. */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "MKCOL", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "PROPFIND", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "PUT", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (locks_hooks != NULL) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "LOCK", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "UNLOCK", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein case DAV_RESOURCE_NULL:
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* resource is null. */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "MKCOL", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "PUT", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (locks_hooks != NULL)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "LOCK", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein default:
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### internal error! */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker break;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* If there is a versioning provider, add versioning methods */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (vsn_hooks != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->exists) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if ((*vsn_hooks->versionable)(resource))
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "VERSION-CONTROL", "");
7281ea331999debdc337b02ce37a3169e0e033a2gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (vsn_hooks->can_be_workspace != NULL
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein && (*vsn_hooks->can_be_workspace)(resource))
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "MKWORKSPACE", "");
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein if (vsn_hooks->can_be_activity != NULL
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein && (*vsn_hooks->can_be_activity)(resource))
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein apr_table_addn(methods, "MKACTIVITY", "");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (!resource->versioned) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if ((*vsn_hooks->versionable)(resource))
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "VERSION-CONTROL", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein else if (resource->working) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "CHECKIN", "");
bbba27074551817d7c6a606c4362965c26a0777egstein
bbba27074551817d7c6a606c4362965c26a0777egstein /* ### we might not support this DeltaV option */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "UNCHECKOUT", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein else if (vsn_hooks->add_label != NULL) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "CHECKOUT", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "LABEL", "");
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein else {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "CHECKOUT", "");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* If there is a bindings provider, see if resource is bindable */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (binding_hooks != NULL
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein && (*binding_hooks->is_bindable)(resource)) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_addn(methods, "BIND", "");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
67ec15681c83d4f5e119f0742618569017beb3fbstriker /* If there is a search provider, set SEARCH in option */
67ec15681c83d4f5e119f0742618569017beb3fbstriker if (search_hooks != NULL) {
67ec15681c83d4f5e119f0742618569017beb3fbstriker apr_table_addn(methods, "SEARCH", "");
67ec15681c83d4f5e119f0742618569017beb3fbstriker }
67ec15681c83d4f5e119f0742618569017beb3fbstriker
847b3922f7dcde6830f4aad49d29c84b4569c260minfrin /* additional methods registered by external modules */
847b3922f7dcde6830f4aad49d29c84b4569c260minfrin extensions = ap_list_provider_names(r->pool, DAV_OPTIONS_EXTENSION_GROUP, "0");
847b3922f7dcde6830f4aad49d29c84b4569c260minfrin entry = (ap_list_provider_names_t *)extensions->elts;
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim
847b3922f7dcde6830f4aad49d29c84b4569c260minfrin for (i = 0; i < extensions->nelts; i++, entry++) {
11e076839c8d5a82d55e710194d0daac51390dbdsf const dav_options_provider *options =
11e076839c8d5a82d55e710194d0daac51390dbdsf dav_get_options_providers(entry->provider_name);
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim
11e076839c8d5a82d55e710194d0daac51390dbdsf if (options && options->dav_method) {
11e076839c8d5a82d55e710194d0daac51390dbdsf apr_text_header hoptions = { 0 };
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim
11e076839c8d5a82d55e710194d0daac51390dbdsf options->dav_method(r, resource, &hoptions);
11e076839c8d5a82d55e710194d0daac51390dbdsf for (t = hoptions.first; t && t->text; t = t->next)
11e076839c8d5a82d55e710194d0daac51390dbdsf apr_table_addn(methods, t->text, "");
11e076839c8d5a82d55e710194d0daac51390dbdsf }
847b3922f7dcde6830f4aad49d29c84b4569c260minfrin }
847b3922f7dcde6830f4aad49d29c84b4569c260minfrin
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* Generate the Allow header */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein arr = apr_table_elts(methods);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker elts = (const apr_table_entry_t *)arr->elts;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein text_size = 0;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* first, compute total length */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein for (i = 0; i < arr->nelts; ++i) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (elts[i].key == NULL)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein continue;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* add 1 for comma or null */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein text_size += strlen(elts[i].key) + 1;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein s = allow = apr_palloc(r->pool, text_size);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein for (i = 0; i < arr->nelts; ++i) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (elts[i].key == NULL)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein continue;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (s != allow)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein *s++ = ',';
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein strcpy(s, elts[i].key);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein s += strlen(s);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein apr_table_setn(r->headers_out, "Allow", allow);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
67ec15681c83d4f5e119f0742618569017beb3fbstriker
67ec15681c83d4f5e119f0742618569017beb3fbstriker /* If there is search set_option_head function, set head */
67ec15681c83d4f5e119f0742618569017beb3fbstriker /* DASL: <DAV:basicsearch>
67ec15681c83d4f5e119f0742618569017beb3fbstriker * DASL: <http://foo.bar.com/syntax1>
67ec15681c83d4f5e119f0742618569017beb3fbstriker * DASL: <http://akuma.com/syntax2>
67ec15681c83d4f5e119f0742618569017beb3fbstriker */
67ec15681c83d4f5e119f0742618569017beb3fbstriker if (search_hooks != NULL
67ec15681c83d4f5e119f0742618569017beb3fbstriker && *search_hooks->set_option_head != NULL) {
67ec15681c83d4f5e119f0742618569017beb3fbstriker if ((err = (*search_hooks->set_option_head)(r)) != NULL) {
67ec15681c83d4f5e119f0742618569017beb3fbstriker return dav_handle_err(r, err, NULL);
67ec15681c83d4f5e119f0742618569017beb3fbstriker }
67ec15681c83d4f5e119f0742618569017beb3fbstriker }
67ec15681c83d4f5e119f0742618569017beb3fbstriker
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* if there was no request body, then there is no response body */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (doc == NULL) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein ap_set_content_length(r, 0);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
72360798a27566f28e2cbee0e39a0a6e3c3bd729wrowe /* ### this sends a Content-Type. the default OPTIONS does not. */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* ### the default (ap_send_http_options) returns OK, but I believe
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein * ### that is because it is the default handler and nothing else
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein * ### will run after the thing. */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein return DONE;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* handle each options request */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein for (elem = doc->root->first_child; elem != NULL; elem = elem->next) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* check for something we recognize first */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein int core_option = 0;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein dav_error *err = NULL;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe if (elem->ns == APR_XML_NS_DAV_ID) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (strcmp(elem->name, "supported-method-set") == 0) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein err = dav_gen_supported_methods(r, elem, methods, &body);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein core_option = 1;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein else if (strcmp(elem->name, "supported-live-property-set") == 0) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein err = dav_gen_supported_live_props(r, resource, elem, &body);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein core_option = 1;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein else if (strcmp(elem->name, "supported-report-set") == 0) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein err = dav_gen_supported_reports(r, resource, elem, vsn_hooks, &body);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein core_option = 1;
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if (err != NULL)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein return dav_handle_err(r, err, NULL);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* if unrecognized option, pass to versioning provider */
25bc56d39c9ca09a5b91da3c199d062fdc94ba0fgstein if (!core_option && vsn_hooks != NULL) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein if ((err = (*vsn_hooks->get_option)(resource, elem, &body))
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein != NULL) {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein return dav_handle_err(r, err, NULL);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein }
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein /* send the options response */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein r->status = HTTP_OK;
e0d102c882a7ed34d3eec24b36da49f097066a36stoddard ap_set_content_type(r, DAV_XML_CONTENT_TYPE);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
72360798a27566f28e2cbee0e39a0a6e3c3bd729wrowe /* send the headers and response body */
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein ap_rputs(DAV_XML_HEADER DEBUG_CR
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein "<D:options-response xmlns:D=\"DAV:\">" DEBUG_CR, r);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein for (t = body.first; t != NULL; t = t->next)
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein ap_rputs(t->text, r);
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein ap_rputs("</D:options-response>" DEBUG_CR, r);
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{
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe const apr_xml_elem *elem;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_header hdr = { 0 };
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* just return if we built the thing already */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ctx->propstat_404 != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(ctx->w.pool, &hdr,
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe "<D:propstat>" DEBUG_CR
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe "<D:prop>" DEBUG_CR);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein elem = dav_find_child(ctx->doc->root, "prop");
f4c310fd2555c6faca1f980f00b161eadb089023gstein for (elem = elem->first_child; elem; elem = elem->next) {
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(ctx->w.pool, &hdr,
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_empty_elem(ctx->w.pool, elem));
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(ctx->w.pool, &hdr,
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe "</D:prop>" DEBUG_CR
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe "<D:status>HTTP/1.1 404 Not Found</D:status>" DEBUG_CR
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe "</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 */
bbba27074551817d7c6a606c4362965c26a0777egstein err = dav_open_propdb(ctx->r, ctx->w.lockdb, wres->resource, 1,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ctx->doc ? ctx->doc->namespaces : NULL, &propdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### do something with err! */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (ctx->propfind_type == DAV_PROPFIND_IS_PROP) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dav_get_props_result badprops = { 0 };
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* some props were expected on this collection/resource */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dav_cache_badprops(ctx);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker badprops.propstats = ctx->propstat_404;
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein dav_stream_response(wres, 0, &badprops, ctx->scratchpool);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker else {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* no props on this collection/resource */
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein dav_stream_response(wres, HTTP_OK, NULL, ctx->scratchpool);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein apr_pool_clear(ctx->scratchpool);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### what to do about closing the propdb on server failure? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (ctx->propfind_type == DAV_PROPFIND_IS_PROP) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker propstats = dav_get_props(propdb, ctx->doc);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein dav_prop_insert what = ctx->propfind_type == DAV_PROPFIND_IS_ALLPROP
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein ? DAV_PROP_INSERT_VALUE
c7548bcd69fbe1338ad855ba44f0b2b774e57bd8gstein : DAV_PROP_INSERT_NAME;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker propstats = dav_get_allprops(propdb, what);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_close_propdb(propdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein dav_stream_response(wres, 0, &propstats, ctx->scratchpool);
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein /* at this point, ctx->scratchpool has been used to stream a
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein single response. this function fully controls the pool, and
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein thus has the right to clear it for the next iteration of this
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein callback. */
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein apr_pool_clear(ctx->scratchpool);
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;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_doc *doc;
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein dav_walker_ctx ctx = { { 0 } };
f94aab38f6ee899f463f0118ea395291f7c5b4cegstein dav_response *multi_status;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Ask repository module to resolve the resource */
f39230a531b23d94f86a087963299bbe2e431a4agstein err = dav_get_resource(r, 1 /* label_allowed */, 0 /* use_checked_in */,
f39230a531b23d94f86a087963299bbe2e431a4agstein &resource);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (err != NULL)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (dav_get_resource_state(r, resource) == DAV_RESOURCE_NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* Apache will supply a default error for this. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_NOT_FOUND;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((depth = dav_get_depth(r, DAV_INFINITY)) < 0) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* dav_get_depth() supplies additional information for the
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * default message. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1cf62e9550d43af51e35c453ff2517dd5b0f98bfgstein if (depth == DAV_INFINITY && resource->collection) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dav_dir_conf *conf;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker conf = (dav_dir_conf *)ap_get_module_config(r->per_dir_config,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker &dav_module);
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* default is to DISALLOW these requests */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (conf->allow_depthinfinity != DAV_ENABLED_ON) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_error_response(r, HTTP_FORBIDDEN,
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "PROPFIND requests with a "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Depth of \"infinity\" are "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "not allowed for %s.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_escape_html(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker r->uri)));
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein if ((result = ap_xml_parse_input(r, &doc)) != OK) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* note: doc == NULL if no request body */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (doc && !dav_validate_root(doc, "propfind")) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* This supplies additional information for the default message. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00585)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The \"propfind\" element was not found.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### validate that only one of these three elements is present */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
89c7a19f9c47b03f00f622a979490c9bccb2ff03sf if (doc == NULL || dav_find_child(doc->root, "allprop") != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* note: no request body implies allprop */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ctx.propfind_type = DAV_PROPFIND_IS_ALLPROP;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
89c7a19f9c47b03f00f622a979490c9bccb2ff03sf else if (dav_find_child(doc->root, "propname") != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ctx.propfind_type = DAV_PROPFIND_IS_PROPNAME;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
89c7a19f9c47b03f00f622a979490c9bccb2ff03sf else if (dav_find_child(doc->root, "prop") != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ctx.propfind_type = DAV_PROPFIND_IS_PROP;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* "propfind" element must have one of the above three children */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* This supplies additional information for the default message. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00586)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The \"propfind\" element does not contain one of "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "the required child elements (the specific command).");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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;
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein ctx.bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein apr_pool_create(&ctx.scratchpool, r->pool);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### should open read-only */
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein if ((err = dav_open_lockdb(r, 0, &ctx.w.lockdb)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The lock database could not be opened, "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "preventing access to the various lock "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "properties for the PROPFIND.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein if (ctx.w.lockdb != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* if we have a lock database, then we can walk locknull resources */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ctx.w.walk_type |= DAV_WALKTYPE_LOCKNULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein /* send <multistatus> tag, with all doc->namespaces attached. */
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein /* NOTE: we *cannot* leave out the doc's namespaces from the
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein initial <multistatus> tag. if a 404 was generated for an HREF,
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein then we need to spit out the doc's namespaces for use by the
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein 404. Note that <response> elements will override these ns0,
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein ns1, etc, but NOT within the <response> scope for the
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein badprops. */
1c21b8086c5a1425f5816c69e2da727a7df7d085gstein dav_begin_multistatus(ctx.bb, r, HTTP_MULTI_STATUS,
1c21b8086c5a1425f5816c69e2da727a7df7d085gstein doc ? doc->namespaces : NULL);
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein
87e4c2191581abcfaba8133868a1e9c96d9643a5gstein /* Have the provider walk the resource. */
f94aab38f6ee899f463f0118ea395291f7c5b4cegstein err = (*resource->hooks->walk)(&ctx.w, depth, &multi_status);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
52c1d304b1bd8e05da40a7cded2ecb9f0ba614c5gstein if (ctx.w.lockdb != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker (*ctx.w.lockdb->hooks->close_lockdb)(ctx.w.lockdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein /* If an error occurred during the resource walk, there's
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein basically nothing we can do but abort the connection and
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein log an error. This is one of the limitations of HTTP; it
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein needs to "know" the entire status of the response before
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein generating it, which is just impossible in these streamy
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein response situations. */
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein err = dav_push_error(r->pool, err->status, 0,
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein "Provider encountered an error while streaming"
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein " a multistatus PROPFIND response.", err);
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein dav_log_err(r, err, APLOG_ERR);
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein r->connection->aborted = 1;
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein return DONE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
21aaa180f4f49d57612dcd5634e7a8eb0503edc6jorton dav_finish_multistatus(r, ctx.bb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* the response has been sent. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DONE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowestatic apr_text * dav_failed_proppatch(apr_pool_t *p,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker apr_array_header_t *prop_ctx)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_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 ) {
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(p, &hdr,
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe "<D:propstat>" DEBUG_CR
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe "<D:prop>");
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(p, &hdr, apr_xml_empty_elem(p, ctx->prop));
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(p, &hdr, "</D:prop>" DEBUG_CR);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (ctx->err == NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* nothing was assigned here yet, so make it a 424 */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (ctx->operation == DAV_PROP_OP_SET) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (err424_set == NULL)
99d46a23c6eac800f327b29f8009f7d7da986230trawick err424_set = dav_new_error(p, HTTP_FAILED_DEPENDENCY, 0, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Attempted DAV:set operation "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "could not be completed due "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "to other errors.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ctx->err = err424_set;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker else if (ctx->operation == DAV_PROP_OP_DELETE) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (err424_delete == NULL)
99d46a23c6eac800f327b29f8009f7d7da986230trawick err424_delete = dav_new_error(p, HTTP_FAILED_DEPENDENCY, 0, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Attempted DAV:remove "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "operation could not be "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "completed due to other "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "errors.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ctx->err = err424_delete;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker s = apr_psprintf(p,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "<D:status>"
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "HTTP/1.1 %d (status)"
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "</D:status>" DEBUG_CR,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ctx->err->status);
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(p, &hdr, s);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### we should use compute_desc if necessary... */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (ctx->err->desc != NULL) {
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(p, &hdr, "<D:responsedescription>" DEBUG_CR);
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(p, &hdr, ctx->err->desc);
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(p, &hdr, "</D:responsedescription>" DEBUG_CR);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(p, &hdr, "</D:propstat>" DEBUG_CR);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return hdr.first;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowestatic apr_text * dav_success_proppatch(apr_pool_t *p, apr_array_header_t *prop_ctx)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_header hdr = { 0 };
f4c310fd2555c6faca1f980f00b161eadb089023gstein int i = prop_ctx->nelts;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_prop_ctx *ctx = (dav_prop_ctx *)prop_ctx->elts;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * ### we probably need to revise the way we assemble the response...
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * ### this code assumes everything will return status==200.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(p, &hdr,
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe "<D:propstat>" DEBUG_CR
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe "<D:prop>" DEBUG_CR);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein for ( ; i-- > 0; ++ctx ) {
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(p, &hdr, apr_xml_empty_elem(p, ctx->prop));
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text_append(p, &hdr,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "</D:prop>" DEBUG_CR
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "<D:status>HTTP/1.1 200 OK</D:status>" DEBUG_CR
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "</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/*
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Call <func> for each context. This can stop when an error occurs, or
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * simply iterate through the whole list.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Returns 1 if an error occurs (and the iteration is aborted). Returns 0
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * if all elements are processed.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * If <reverse> is true (non-zero), then the list is traversed in
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * reverse order.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_process_ctx_list(void (*func)(dav_prop_ctx *ctx),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker apr_array_header_t *ctx_list, int stop_on_error,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker int reverse)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein int i = ctx_list->nelts;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_prop_ctx *ctx = (dav_prop_ctx *)ctx_list->elts;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (reverse)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ctx += i;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein while (i--) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (reverse)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker --ctx;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker (*func)(ctx);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (stop_on_error && DAV_PROP_CTX_HAS_ERR(*ctx)) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return 1;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (!reverse)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ++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;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_doc *doc;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_elem *child;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_propdb *propdb;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int failure = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_response resp = { 0 };
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_text *propstat_text;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm apr_array_header_t *ctx_list;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_prop_ctx *ctx;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein dav_auto_version_info av_info;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Ask repository module to resolve the resource */
f39230a531b23d94f86a087963299bbe2e431a4agstein err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
f39230a531b23d94f86a087963299bbe2e431a4agstein &resource);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (err != NULL)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->exists) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* Apache will supply a default error for this. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_NOT_FOUND;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
252e2478cb56afb5ca8585b50bc2ffb780d2efb6gstein if ((result = ap_xml_parse_input(r, &doc)) != OK) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* note: doc == NULL if no request body */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (doc == NULL || !dav_validate_root(doc, "propertyupdate")) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* This supplies additional information for the default message. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00587)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The request body does not contain "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "a \"propertyupdate\" element.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker DAV_VALIDATE_RESOURCE, NULL)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### add a higher-level description? */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein /* make sure the resource can be modified (if versioning repository) */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if ((err = dav_auto_checkout(r, resource,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 0 /* not parent_only */,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker &av_info)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### add a higher-level description? */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, NULL);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_open_propdb(r, NULL, resource, 0, doc->namespaces,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker &propdb)) != NULL) {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein /* undo any auto-checkout */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein dav_auto_checkin(r, resource, 1 /*undo*/, 0 /*unlock*/, &av_info);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Could not open the property "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "database for %s.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_escape_html(r->pool, r->uri)),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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 */
066877f1a045103acfdd376d48cdd473c33f409bdougm ctx_list = apr_array_make(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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker int is_remove;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_elem *prop_group;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_elem *one_prop;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* Ignore children that are not set/remove */
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe if (child->ns != APR_XML_NS_DAV_ID
51384f4dc9cd87f8670177563beea1e635eac46dsf || (!(is_remove = (strcmp(child->name, "remove") == 0))
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker && strcmp(child->name, "set") != 0)) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker continue;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* make sure that a "prop" child exists for set/remove */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if ((prop_group = dav_find_child(child, "prop")) == NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dav_close_propdb(propdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein /* undo any auto-checkout */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein dav_auto_checkin(r, resource, 1 /*undo*/, 0 /*unlock*/, &av_info);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* This supplies additional information for the default message. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00588)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "A \"prop\" element is missing inside "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "the propertyupdate command.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker for (one_prop = prop_group->first_child; one_prop;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker one_prop = one_prop->next) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ctx = (dav_prop_ctx *)apr_array_push(ctx_list);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ctx->propdb = propdb;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ctx->operation = is_remove ? DAV_PROP_OP_DELETE : DAV_PROP_OP_SET;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ctx->prop = one_prop;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ctx->r = r; /* for later use by dav_prop_log_errors() */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dav_prop_validate(ctx);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if ( DAV_PROP_CTX_HAS_ERR(*ctx) ) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker failure = 1;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
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)) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker failure = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* generate a failure/success response */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (failure) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker (void)dav_process_ctx_list(dav_prop_rollback, ctx_list, 0, 1);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker propstat_text = dav_failed_proppatch(r->pool, ctx_list);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker (void)dav_process_ctx_list(dav_prop_commit, ctx_list, 0, 0);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker propstat_text = dav_success_proppatch(r->pool, ctx_list);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* make sure this gets closed! */
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_close_propdb(propdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein /* complete any auto-versioning */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein dav_auto_checkin(r, resource, failure, 0 /*unlock*/, &av_info);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (strcasecmp(tenc, "chunked")) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* Use this instead of Apache's default error string */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00589)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Unknown Transfer-Encoding %s", tenc);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_NOT_IMPLEMENTED;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker r->read_chunked = 1;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else if (lenp) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker const char *pos = lenp;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker while (apr_isdigit(*pos) || apr_isspace(*pos)) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ++pos;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (*pos != '\0') {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* This supplies additional information for the default message. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00590)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Invalid Content-Length %s", lenp);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
cba1beeab00aa7d89ccd51fa18bb2b0f5d3a07d0wrowe r->remaining = apr_atoi64(lenp);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->read_chunked || r->remaining > 0) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### log something? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* Apache will supply a default error for this. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_UNSUPPORTED_MEDIA_TYPE;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Get rid of the body. this will call ap_setup_client_block(), but
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * our copy above has already verified its work.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
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_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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Ask repository module to resolve the resource */
f39230a531b23d94f86a087963299bbe2e431a4agstein err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
f39230a531b23d94f86a087963299bbe2e431a4agstein &resource);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (err != NULL)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resource->exists) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* oops. something was already there! */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* Apache will supply a default error for this. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### we should provide a specific error message! */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_METHOD_NOT_ALLOWED;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein resource_state = dav_get_resource_state(r, resource);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Check If-Headers and existing locks.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Note: depth == 0 normally requires no multistatus response. However,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * if we pass DAV_VALIDATE_PARENT, then we could get an error on a URI
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * other than the Request-URI, thereby requiring a multistatus.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * If the resource does not exist (DAV_RESOURCE_NULL), then we must
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * check the resource *and* its parent. If the resource exists or is
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * a locknull resource, then we check only the resource.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_validate_request(r, resource, 0, NULL, &multi_status,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker resource_state == DAV_RESOURCE_NULL ?
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker DAV_VALIDATE_PARENT :
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker DAV_VALIDATE_RESOURCE, NULL)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### add a higher-level description? */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, multi_status);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* if versioned resource, make sure parent is checked out */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if ((err = dav_auto_checkout(r, resource, 1 /* parent_only */,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker &av_info)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### add a higher-level description? */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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 */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein err2 = dav_auto_checkin(r, NULL, err != NULL /* undo if error */,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 0 /*unlock*/, &av_info);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* check for errors now */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err2 != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* just log a warning */
7fab402fa233a9cb3214042cb8d1de7497dbafa0rpluem err = dav_push_error(r->pool, err2->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The MKCOL was successful, but there "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "was a problem automatically checking in "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "the parent collection.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err2);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dav_log_err(r, err, APLOG_WARNING);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (locks_hooks != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dav_lockdb *lockdb;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if ((err = (*locks_hooks->open_lockdb)(r, 0, 0, &lockdb)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* The directory creation was successful, but the locking failed. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The MKCOL was successful, but there "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "was a problem opening the lock database "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "which prevents inheriting locks from the "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "parent resources.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, NULL);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* notify lock system that we have created/replaced a resource */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_notify_created(r, lockdb, resource, resource_state, 0);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker (*locks_hooks->close_lockdb)(lockdb);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (err != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* The dir creation was successful, but the locking failed. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The MKCOL was successful, but there "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "was a problem updating its lock "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "information.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, NULL);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
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;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *resnew;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein dav_auto_version_info src_av_info = { 0 };
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein dav_auto_version_info dst_av_info = { 0 };
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;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein int replace_dest;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein int resnew_state;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Ask repository module to resolve the resource */
f39230a531b23d94f86a087963299bbe2e431a4agstein err = dav_get_resource(r, !is_move /* label_allowed */,
f39230a531b23d94f86a087963299bbe2e431a4agstein 0 /* use_checked_in */, &resource);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (err != NULL)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return dav_handle_err(r, err, NULL);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->exists) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* Apache will supply a default error for this. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_NOT_FOUND;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* If not a file or collection resource, COPY/MOVE not allowed */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein /* ### allow COPY/MOVE of DeltaV resource types */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resource->type != DAV_RESOURCE_TYPE_REGULAR) {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm body = apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Cannot COPY/MOVE resource %s.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_escape_html(r->pool, r->uri));
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* Look in headers provided by Netscape's Roaming Profiles */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker const char *nscp_host = apr_table_get(r->headers_in, "Host");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker const char *nscp_path = apr_table_get(r->headers_in, "New-uri");
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (nscp_host != NULL && nscp_path != NULL)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dest = apr_psprintf(r->pool, "http://%s%s", nscp_host, nscp_path);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (dest == NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* This supplies additional information for the default message. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00591)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The request is missing a Destination header.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
48f35e10f195dd594d75738fc536bb885eda537cgstein lookup = dav_lookup_uri(dest, r, 1 /* must_be_absolute */);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (lookup.rnew == NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (lookup.err.status == HTTP_BAD_REQUEST) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* This supplies additional information for the default message. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00592)
8eed3bcafe1c99a43296009f5d2a862b984e3d46gstein "%s", lookup.err.desc);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### this assumes that dav_lookup_uri() only generates a status
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * ### that Apache can provide a status line for!! */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, lookup.err.status, lookup.err.desc);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (lookup.rnew->status != HTTP_OK) {
058d5e61ccdd2310f16664d4fc62a6a35331eeb4jorton const char *auth = apr_table_get(lookup.rnew->err_headers_out,
058d5e61ccdd2310f16664d4fc62a6a35331eeb4jorton "WWW-Authenticate");
058d5e61ccdd2310f16664d4fc62a6a35331eeb4jorton if (lookup.rnew->status == HTTP_UNAUTHORIZED && auth != NULL) {
058d5e61ccdd2310f16664d4fc62a6a35331eeb4jorton /* propagate the WWW-Authorization header up from the
058d5e61ccdd2310f16664d4fc62a6a35331eeb4jorton * subreq so the client sees it. */
04d6458a2cd3b44376f00a56804bb6bf6bc46865sf apr_table_setn(r->err_headers_out, "WWW-Authenticate",
04d6458a2cd3b44376f00a56804bb6bf6bc46865sf apr_pstrdup(r->pool, auth));
058d5e61ccdd2310f16664d4fc62a6a35331eeb4jorton }
058d5e61ccdd2310f16664d4fc62a6a35331eeb4jorton
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### how best to report this... */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, lookup.rnew->status,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Destination URI had an error.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Resolve destination resource */
f39230a531b23d94f86a087963299bbe2e431a4agstein err = dav_get_resource(lookup.rnew, 0 /* label_allowed */,
f39230a531b23d94f86a087963299bbe2e431a4agstein 0 /* use_checked_in */, &resnew);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (err != NULL)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* are the two resources handled by the same repository? */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resource->hooks != resnew->hooks) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### this message exposes some backend config, but screw it... */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, HTTP_BAD_GATEWAY,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Destination URI is handled by a "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "different repository than the source URI. "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "MOVE or COPY between repositories is "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "not possible.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* get and parse the overwrite header value */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((overwrite = dav_get_overwrite(r)) < 0) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* dav_get_overwrite() supplies additional information for the
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * default message. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* quick failure test: if dest exists and overwrite is false. */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resnew->exists && !overwrite) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* Supply some text for the error response body. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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)) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* Supply some text for the error response body. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* dav_get_depth() supplies additional information for the
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * default message. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (depth == 1) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* This supplies additional information for the default message. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00593)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Depth must be \"0\" or \"infinity\" for COPY or MOVE.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (is_move && is_dir && depth != DAV_INFINITY) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* This supplies additional information for the default message. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00594)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Depth must be \"infinity\" when moving a collection.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
d3e0a61e1bcc497f2efd7af41a5a9d77090ecc1cminfrin * Check If-Headers and existing locks for each resource in the source.
d3e0a61e1bcc497f2efd7af41a5a9d77090ecc1cminfrin * We will return a 424 response with a DAV:multistatus body.
d3e0a61e1bcc497f2efd7af41a5a9d77090ecc1cminfrin * The multistatus responses will contain the information about any
d3e0a61e1bcc497f2efd7af41a5a9d77090ecc1cminfrin * resource that fails the validation.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *
c8e0bfe1e601a9d27c13a13e24dbf8416ee83684gstein * We check the parent resource, too, if this is a MOVE. Moving the
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * resource effectively removes it from the parent collection, so we
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * must ensure that we have met the appropriate conditions.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * If a problem occurs with the Request-URI itself, then a plain error
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * (rather than a multistatus) will be returned.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
d3e0a61e1bcc497f2efd7af41a5a9d77090ecc1cminfrin if ((err = dav_validate_request(r, resource, depth, NULL,
d3e0a61e1bcc497f2efd7af41a5a9d77090ecc1cminfrin &multi_response,
c8e0bfe1e601a9d27c13a13e24dbf8416ee83684gstein (is_move ? DAV_VALIDATE_PARENT
89fc13eb43e6c78d3377e9ef0d79d343a138041bbreser : DAV_VALIDATE_RESOURCE
89fc13eb43e6c78d3377e9ef0d79d343a138041bbreser | DAV_VALIDATE_NO_MODIFY)
d3e0a61e1bcc497f2efd7af41a5a9d77090ecc1cminfrin | DAV_VALIDATE_USE_424,
d3e0a61e1bcc497f2efd7af41a5a9d77090ecc1cminfrin NULL)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker apr_psprintf(r->pool,
d3e0a61e1bcc497f2efd7af41a5a9d77090ecc1cminfrin "Could not %s %s due to a failed "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "precondition on the source "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "(e.g. locks).",
d3e0a61e1bcc497f2efd7af41a5a9d77090ecc1cminfrin is_move ? "MOVE" : "COPY",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_escape_html(r->pool, r->uri)),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, multi_response);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Check If-Headers and existing locks for destination. Note that we
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * use depth==infinity since the target (hierarchy) will be deleted
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * before the move/copy is completed.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Note that we are overwriting the target, which implies a DELETE, so
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * we are subject to the error/response rules as a DELETE. Namely, we
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * will return a 424 error if any of the validations fail.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * (see dav_method_delete() for more information)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_validate_request(lookup.rnew, resnew, DAV_INFINITY, NULL,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker &multi_response,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker DAV_VALIDATE_PARENT
f4c310fd2555c6faca1f980f00b161eadb089023gstein | DAV_VALIDATE_USE_424, NULL)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Could not MOVE/COPY %s due to a "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "failed precondition on the "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "destination (e.g. locks).",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_escape_html(r->pool, r->uri)),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, multi_response);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (is_dir
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker && depth == DAV_INFINITY
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker && (*resource->hooks->is_parent_resource)(resource, resnew)) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* Supply some text for the error response body. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, HTTP_FORBIDDEN,
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Source collection contains the "
f4c310fd2555c6faca1f980f00b161eadb089023gstein "Destination.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (is_dir
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker && (*resnew->hooks->is_parent_resource)(resnew, resource)) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* The destination must exist (since it contains the source), and
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * a condition above implies Overwrite==T. Obviously, we cannot
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * delete the Destination before the MOVE/COPY, as that would
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * delete the Source.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* Supply some text for the error response body. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_open_lockdb(r, 0, &lockdb)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### add a higher-level description? */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* remove any locks from the old resources */
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * ### this is Yet Another Traversal. if we do a rename(), then we
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * ### really don't have to do this in some cases since the inode
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * ### values will remain constant across the move. but we can't
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * ### know that fact from outside the provider :-(
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * ### note that we now have a problem atomicity in the move/copy
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * ### since a failure after this would have removed locks (technically,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * ### this is okay to do, but really...)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (is_move && lockdb != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### this is wrong! it blasts direct locks on parent resources */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### pass lockdb! */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker (void)dav_unlock(r, resource, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* if this is a move, then the source parent collection will be modified */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (is_move) {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if ((err = dav_auto_checkout(r, resource, 1 /* parent_only */,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker &src_av_info)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (lockdb != NULL)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker (*lockdb->hooks->close_lockdb)(lockdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### add a higher-level description? */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein /*
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein * Remember the initial state of the destination, so the lock system
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein * can be notified as to how it changed.
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein resnew_state = dav_get_resource_state(lookup.rnew, resnew);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein /* In a MOVE operation, the destination is replaced by the source.
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein * In a COPY operation, if the destination exists, is under version
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein * control, and is the same resource type as the source,
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein * then it should not be replaced, but modified to be a copy of
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein * the source.
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if (!resnew->exists)
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein replace_dest = 0;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein else if (is_move || !resource->versioned)
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein replace_dest = 1;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein else if (resource->type != resnew->type)
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein replace_dest = 1;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein else if ((resource->collection == 0) != (resnew->collection == 0))
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein replace_dest = 1;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein else
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein replace_dest = 0;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein /* If the destination must be created or replaced,
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein * make sure the parent collection is writable
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if (!resnew->exists || replace_dest) {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if ((err = dav_auto_checkout(r, resnew, 1 /*parent_only*/,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker &dst_av_info)) != NULL) {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein /* could not make destination writable:
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * if move, restore state of source parent
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if (is_move) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker (void)dav_auto_checkin(r, NULL, 1 /* undo */,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 0 /*unlock*/, &src_av_info);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (lockdb != NULL)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker (*lockdb->hooks->close_lockdb)(lockdb);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### add a higher-level description? */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, NULL);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* If source and destination parents are the same, then
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein * use the same resource object, so status updates to one are reflected
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein * in the other, when doing auto-versioning. Otherwise,
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein * we may try to checkin the parent twice.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein if (src_av_info.parent_resource != NULL
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein && dst_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
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein /* If destination is being replaced, remove it first
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein * (we know Ovewrite must be TRUE). Then try to copy/move the resource.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if (replace_dest)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = (*resnew->hooks->remove_resource)(resnew, &multi_response);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err == NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (is_move)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = (*resource->hooks->move_resource)(resource, resnew,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &multi_response);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker else
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = (*resource->hooks->copy_resource)(resource, resnew, depth,
f4c310fd2555c6faca1f980f00b161eadb089023gstein &multi_response);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein /* perform any auto-versioning cleanup */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein err2 = dav_auto_checkin(r, NULL, err != NULL /* undo if error */,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 0 /*unlock*/, &dst_av_info);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (is_move) {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein err3 = dav_auto_checkin(r, NULL, err != NULL /* undo if error */,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 0 /*unlock*/, &src_av_info);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein else
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err3 = NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* check for error from remove/copy/move operations */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (lockdb != NULL)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker (*lockdb->hooks->close_lockdb)(lockdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Could not MOVE/COPY %s.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_escape_html(r->pool, r->uri)),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, multi_response);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein /* check for errors from auto-versioning */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err2 != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* just log a warning */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err2->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The MOVE/COPY was successful, but there was a "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "problem automatically checking in the "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "source parent collection.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err2);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dav_log_err(r, err, APLOG_WARNING);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (err3 != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* just log a warning */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err3->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The MOVE/COPY was successful, but there was a "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "problem automatically checking in the "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "destination or its parent collection.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err3);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dav_log_err(r, err, APLOG_WARNING);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* propagate any indirect locks at the target */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (lockdb != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* notify lock system that we have created/replaced a resource */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_notify_created(r, lockdb, resnew, resnew_state, depth);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker (*lockdb->hooks->close_lockdb)(lockdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (err != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* The move/copy was successful, but the locking failed. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The MOVE/COPY was successful, but there "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "was a problem updating the lock "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "information.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, NULL);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* return an appropriate response (HTTP_CREATED or HTTP_NO_CONTENT) */
22e9a19da7fd79a2801d99e6501b8f8470abdf6ebreser return dav_created(r, lookup.rnew->unparsed_uri, "Destination",
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein resnew_state == DAV_RESOURCE_EXISTS);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/* dav_method_lock: Handler to implement the DAV LOCK method
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Returns appropriate HTTP_* response.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
f4c310fd2555c6faca1f980f00b161eadb089023gsteinstatic int dav_method_lock(request_rec *r)
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_error *err;
f4c310fd2555c6faca1f980f00b161eadb089023gstein dav_resource *resource;
3f985866b9b5b49fb57735b5eb135591163f30dfsf dav_resource *parent;
f4c310fd2555c6faca1f980f00b161eadb089023gstein const dav_hooks_locks *locks_hooks;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int depth;
f4c310fd2555c6faca1f980f00b161eadb089023gstein int new_lock_request = 0;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_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)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein depth = dav_get_depth(r, DAV_INFINITY);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (depth != 0 && depth != DAV_INFINITY) {
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00595)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Depth must be 0 or \"infinity\" for LOCK.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein /* Ask repository module to resolve the resource */
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
f39230a531b23d94f86a087963299bbe2e431a4agstein &resource);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (err != NULL)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
3f985866b9b5b49fb57735b5eb135591163f30dfsf /* Check if parent collection exists */
3f985866b9b5b49fb57735b5eb135591163f30dfsf if ((err = resource->hooks->get_parent_resource(resource, &parent)) != NULL) {
3f985866b9b5b49fb57735b5eb135591163f30dfsf /* ### add a higher-level description? */
3f985866b9b5b49fb57735b5eb135591163f30dfsf return dav_handle_err(r, err, NULL);
3f985866b9b5b49fb57735b5eb135591163f30dfsf }
3f985866b9b5b49fb57735b5eb135591163f30dfsf if (parent && (!parent->exists || parent->collection != 1)) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick err = dav_new_error(r->pool, HTTP_CONFLICT, 0, 0,
3f985866b9b5b49fb57735b5eb135591163f30dfsf apr_psprintf(r->pool,
3f985866b9b5b49fb57735b5eb135591163f30dfsf "The parent resource of %s does not "
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim "exist or is not a collection.",
3f985866b9b5b49fb57735b5eb135591163f30dfsf ap_escape_html(r->pool, r->uri)));
3f985866b9b5b49fb57735b5eb135591163f30dfsf return dav_handle_err(r, err, NULL);
3f985866b9b5b49fb57735b5eb135591163f30dfsf }
3f985866b9b5b49fb57735b5eb135591163f30dfsf
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Open writable. Unless an error occurs, we'll be
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * writing into the database.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = (*locks_hooks->open_lockdb)(r, 0, 0, &lockdb)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### add a higher-level description? */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (doc != NULL) {
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = dav_lock_parse_lockinfo(r, resource, lockdb, doc,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker &lock)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### 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 /*
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Check If-Headers and existing locks.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * If this will create a locknull resource, then the LOCK will affect
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * the parent collection (much like a PUT/MKCOL). For that case, we must
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * validate the parent resource's conditions.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Could not LOCK %s due to a failed "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "precondition (e.g. other locks).",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_escape_html(r->pool, r->uri)),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker goto error;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (new_lock_request == 0) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dav_locktoken_list *ltl;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /*
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Refresh request
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * ### Assumption: We can renew multiple locks on the same resource
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * ### at once. First harvest all the positive lock-tokens given in
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * ### the If header. Then modify the lock entries for this resource
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * ### with the new Timeout val.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if ((err = dav_get_locktoken_list(r, &ltl)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The lock refresh for %s failed "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "because no lock tokens were "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "specified in an \"If:\" "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "header.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_escape_html(r->pool, r->uri)),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker goto error;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if ((err = (*locks_hooks->refresh_locks)(lockdb, resource, ltl,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dav_get_timeout(r),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker &lock)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### add a higher-level description to err? */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker goto error;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
f4c310fd2555c6faca1f980f00b161eadb089023gstein } else {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* New lock request */
f4c310fd2555c6faca1f980f00b161eadb089023gstein char *locktoken_txt;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dav_dir_conf *conf;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker conf = (dav_dir_conf *)ap_get_module_config(r->per_dir_config,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker &dav_module);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* apply lower bound (if any) from DAVMinTimeout directive */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (lock->timeout != DAV_TIMEOUT_INFINITE
f4c310fd2555c6faca1f980f00b161eadb089023gstein && lock->timeout < time(NULL) + conf->locktimeout)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker lock->timeout = time(NULL) + conf->locktimeout;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein err = dav_add_lock(r, resource, lockdb, lock, &multi_response);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (err != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### add a higher-level description to err? */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker goto error;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm locktoken_txt = apr_pstrcat(r->pool, "<",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker (*locks_hooks->format_locktoken)(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker lock->locktoken),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ">", NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
04d6458a2cd3b44376f00a56804bb6bf6bc46865sf apr_table_setn(r->headers_out, "Lock-Token", locktoken_txt);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein (*locks_hooks->close_lockdb)(lockdb);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein r->status = HTTP_OK;
e0d102c882a7ed34d3eec24b36da49f097066a36stoddard ap_set_content_type(r, DAV_XML_CONTENT_TYPE);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_rputs(DAV_XML_HEADER DEBUG_CR "<D:prop xmlns:D=\"DAV:\">" DEBUG_CR, r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (lock == NULL)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_rputs("<D:lockdiscovery/>" DEBUG_CR, r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein else {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_rprintf(r,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "<D:lockdiscovery>" DEBUG_CR
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "%s" DEBUG_CR
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "</D:lockdiscovery>" DEBUG_CR,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if ((const_locktoken_txt = apr_table_get(r->headers_in,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Lock-Token")) == NULL) {
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00596)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Unlock failed (%s): "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "No Lock-Token specified in header", r->filename);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm locktoken_txt = apr_pstrdup(r->pool, const_locktoken_txt);
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (locktoken_txt[0] != '<') {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### should provide more specifics... */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein locktoken_txt++;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (locktoken_txt[strlen(locktoken_txt) - 1] != '>') {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### should provide more specifics... */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein locktoken_txt[strlen(locktoken_txt) - 1] = '\0';
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((err = (*locks_hooks->parse_locktoken)(r->pool, locktoken_txt,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker &locktoken)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, HTTP_BAD_REQUEST, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The UNLOCK on %s failed -- an "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "invalid lock token was specified "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "in the \"If:\" header.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_escape_html(r->pool, r->uri)),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein /* Ask repository module to resolve the resource */
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
f39230a531b23d94f86a087963299bbe2e431a4agstein &resource);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (err != NULL)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein resource_state = dav_get_resource_state(r, resource);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Check If-Headers and existing locks.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Note: depth == 0 normally requires no multistatus response. However,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * if we pass DAV_VALIDATE_PARENT, then we could get an error on a URI
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * other than the Request-URI, thereby requiring a multistatus.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * If the resource is a locknull resource, then the UNLOCK will affect
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * the parent collection (much like a delete). For that case, we must
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * validate the parent resource's conditions.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### add a higher-level description? */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *
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.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if ((result = dav_unlock(r, resource, locktoken)) != OK) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_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 */
f39230a531b23d94f86a087963299bbe2e431a4agstein err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
f39230a531b23d94f86a087963299bbe2e431a4agstein &resource);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (err != NULL)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return dav_handle_err(r, err, NULL);
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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return result;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* note: doc == NULL if no request body */
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (doc != NULL) {
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe const apr_xml_elem *child;
1d69b25dcd7ca16cd3ee662bf768ffb1d36c46b6gstein apr_size_t tsize;
1d69b25dcd7ca16cd3ee662bf768ffb1d36c46b6gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (!dav_validate_root(doc, "version-control")) {
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00597)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The request body does not contain "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "a \"version-control\" element.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* get the version URI */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((child = dav_find_child(doc->root, "version")) == NULL) {
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00598)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The \"version-control\" element does not contain "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "a \"version\" element.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((child = dav_find_child(child, "href")) == NULL) {
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00599)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The \"version\" element does not contain "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "an \"href\" element.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* get version URI */
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_to_text(r->pool, child, APR_XML_X2T_INNER, NULL, NULL,
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe &target, &tsize);
1d69b25dcd7ca16cd3ee662bf768ffb1d36c46b6gstein if (tsize == 0) {
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00600)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "An \"href\" element does not contain a URI.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick err = dav_new_error(r->pool, HTTP_CONFLICT, 0, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "<DAV:initial-version-required/>");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick err = dav_new_error(r->pool, HTTP_CONFLICT, 0, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "<DAV:cannot-add-to-existing-history/>");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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))) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick err = dav_new_error(r->pool, HTTP_CONFLICT, 0, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "<DAV:must-be-versionable/>");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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
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,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker resource_state == DAV_RESOURCE_NULL ?
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker DAV_VALIDATE_PARENT :
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker DAV_VALIDATE_RESOURCE, NULL)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, NULL);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* if in versioned collection, make sure parent is checked out */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if ((err = dav_auto_checkout(r, resource, 1 /* parent_only */,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker &av_info)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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) {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein dav_auto_checkin(r, resource, 1 /*undo*/, 0 /*unlock*/, &av_info);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, HTTP_CONFLICT, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Could not VERSION-CONTROL resource %s.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_escape_html(r->pool, r->uri)),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
7281ea331999debdc337b02ce37a3169e0e033a2gstein return dav_handle_err(r, err, NULL);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* revert writability of parent directory */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein err = dav_auto_checkin(r, resource, 0 /*undo*/, 0 /*unlock*/, &av_info);
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (err != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* just log a warning */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The VERSION-CONTROL was successful, but there "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "was a problem automatically checking in "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "the parent collection.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker && (*locks_hooks->get_supportedlock)(resource) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dav_lockdb *lockdb;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if ((err = (*locks_hooks->open_lockdb)(r, 0, 0, &lockdb)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* The resource creation was successful, but the locking failed. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The VERSION-CONTROL was successful, but there "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "was a problem opening the lock database "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "which prevents inheriting locks from the "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "parent resources.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, NULL);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* notify lock system that we have created/replaced a resource */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_notify_created(r, lockdb, resource, resource_state, 0);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker (*locks_hooks->close_lockdb)(lockdb);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (err != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* The dir creation was successful, but the locking failed. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The VERSION-CONTROL was successful, but there "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "was a problem updating its lock "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "information.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, NULL);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
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;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_doc *doc;
f39230a531b23d94f86a087963299bbe2e431a4agstein int apply_to_vsn = 0;
f39230a531b23d94f86a087963299bbe2e431a4agstein int is_unreserved = 0;
f39230a531b23d94f86a087963299bbe2e431a4agstein int is_fork_ok = 0;
f39230a531b23d94f86a087963299bbe2e431a4agstein int create_activity = 0;
f39230a531b23d94f86a087963299bbe2e431a4agstein apr_array_header_t *activities = 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)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return result;
50bd75672ef114fb839dd9643c192b432fdf344cgstein
50bd75672ef114fb839dd9643c192b432fdf344cgstein if (doc != NULL) {
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe const apr_xml_elem *aset;
f39230a531b23d94f86a087963299bbe2e431a4agstein
50bd75672ef114fb839dd9643c192b432fdf344cgstein if (!dav_validate_root(doc, "checkout")) {
50bd75672ef114fb839dd9643c192b432fdf344cgstein /* This supplies additional information for the default msg. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00601)
50bd75672ef114fb839dd9643c192b432fdf344cgstein "The request body, if present, must be a "
50bd75672ef114fb839dd9643c192b432fdf344cgstein "DAV:checkout element.");
50bd75672ef114fb839dd9643c192b432fdf344cgstein return HTTP_BAD_REQUEST;
50bd75672ef114fb839dd9643c192b432fdf344cgstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
f39230a531b23d94f86a087963299bbe2e431a4agstein if (dav_find_child(doc->root, "apply-to-version") != NULL) {
f39230a531b23d94f86a087963299bbe2e431a4agstein if (apr_table_get(r->headers_in, "label") != NULL) {
f39230a531b23d94f86a087963299bbe2e431a4agstein /* ### we want generic 403/409 XML reporting here */
f39230a531b23d94f86a087963299bbe2e431a4agstein /* ### DAV:must-not-have-label-and-apply-to-version */
f39230a531b23d94f86a087963299bbe2e431a4agstein return dav_error_response(r, HTTP_CONFLICT,
f39230a531b23d94f86a087963299bbe2e431a4agstein "DAV:apply-to-version cannot be "
f39230a531b23d94f86a087963299bbe2e431a4agstein "used in conjunction with a "
f39230a531b23d94f86a087963299bbe2e431a4agstein "Label header.");
f39230a531b23d94f86a087963299bbe2e431a4agstein }
f39230a531b23d94f86a087963299bbe2e431a4agstein apply_to_vsn = 1;
f39230a531b23d94f86a087963299bbe2e431a4agstein }
f39230a531b23d94f86a087963299bbe2e431a4agstein
f39230a531b23d94f86a087963299bbe2e431a4agstein is_unreserved = dav_find_child(doc->root, "unreserved") != NULL;
f39230a531b23d94f86a087963299bbe2e431a4agstein is_fork_ok = dav_find_child(doc->root, "fork-ok") != NULL;
f39230a531b23d94f86a087963299bbe2e431a4agstein
f39230a531b23d94f86a087963299bbe2e431a4agstein if ((aset = dav_find_child(doc->root, "activity-set")) != NULL) {
f39230a531b23d94f86a087963299bbe2e431a4agstein if (dav_find_child(aset, "new") != NULL) {
f39230a531b23d94f86a087963299bbe2e431a4agstein create_activity = 1;
f39230a531b23d94f86a087963299bbe2e431a4agstein }
f39230a531b23d94f86a087963299bbe2e431a4agstein else {
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe const apr_xml_elem *child = aset->first_child;
f39230a531b23d94f86a087963299bbe2e431a4agstein
38bae21017e2bd57de2902a19b912a1e3e368026trawick activities = apr_array_make(r->pool, 1, sizeof(const char *));
2086145076ca0269617987150ec518e91f789175gstein
f39230a531b23d94f86a087963299bbe2e431a4agstein for (; child != NULL; child = child->next) {
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe if (child->ns == APR_XML_NS_DAV_ID
f39230a531b23d94f86a087963299bbe2e431a4agstein && strcmp(child->name, "href") == 0) {
f39230a531b23d94f86a087963299bbe2e431a4agstein const char *href;
f39230a531b23d94f86a087963299bbe2e431a4agstein
f39230a531b23d94f86a087963299bbe2e431a4agstein href = dav_xml_get_cdata(child, r->pool,
f39230a531b23d94f86a087963299bbe2e431a4agstein 1 /* strip_white */);
066877f1a045103acfdd376d48cdd473c33f409bdougm *(const char **)apr_array_push(activities) = href;
f39230a531b23d94f86a087963299bbe2e431a4agstein }
f39230a531b23d94f86a087963299bbe2e431a4agstein }
f39230a531b23d94f86a087963299bbe2e431a4agstein
f39230a531b23d94f86a087963299bbe2e431a4agstein if (activities->nelts == 0) {
f39230a531b23d94f86a087963299bbe2e431a4agstein /* no href's is a DTD violation:
f39230a531b23d94f86a087963299bbe2e431a4agstein <!ELEMENT activity-set (href+ | new)>
f39230a531b23d94f86a087963299bbe2e431a4agstein */
f39230a531b23d94f86a087963299bbe2e431a4agstein
f39230a531b23d94f86a087963299bbe2e431a4agstein /* This supplies additional info for the default msg. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00602)
f39230a531b23d94f86a087963299bbe2e431a4agstein "Within the DAV:activity-set element, the "
f39230a531b23d94f86a087963299bbe2e431a4agstein "DAV:new element must be used, or at least "
f39230a531b23d94f86a087963299bbe2e431a4agstein "one DAV:href must be specified.");
f39230a531b23d94f86a087963299bbe2e431a4agstein return HTTP_BAD_REQUEST;
f39230a531b23d94f86a087963299bbe2e431a4agstein }
f39230a531b23d94f86a087963299bbe2e431a4agstein }
f39230a531b23d94f86a087963299bbe2e431a4agstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Ask repository module to resolve the resource */
f39230a531b23d94f86a087963299bbe2e431a4agstein err = dav_get_resource(r, 1 /*label_allowed*/, apply_to_vsn, &resource);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (err != NULL)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return dav_handle_err(r, err, NULL);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
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 */
2086145076ca0269617987150ec518e91f789175gstein if (resource->type != DAV_RESOURCE_TYPE_REGULAR
2086145076ca0269617987150ec518e91f789175gstein && resource->type != DAV_RESOURCE_TYPE_VERSION) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, HTTP_CONFLICT,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Cannot checkout this type of resource.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->versioned) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, HTTP_CONFLICT,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Cannot checkout unversioned resource.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (resource->working) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, HTTP_CONFLICT,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The resource is already checked out to the workspace.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### do lock checks, once behavior is defined */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Do the checkout */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if ((err = (*vsn_hooks->checkout)(resource, 0 /*auto_checkout*/,
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein is_unreserved, is_fork_ok,
f39230a531b23d94f86a087963299bbe2e431a4agstein create_activity, activities,
f39230a531b23d94f86a087963299bbe2e431a4agstein &working_resource)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, HTTP_CONFLICT, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Could not CHECKOUT resource %s.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_escape_html(r->pool, r->uri)),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein /* if no working resource created, return OK,
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein * else return CREATED with working resource URL in Location header
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if (working_resource == NULL) {
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein /* no body */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein ap_set_content_length(r, 0);
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein return DONE;
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein }
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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return result;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Ask repository module to resolve the resource */
f39230a531b23d94f86a087963299bbe2e431a4agstein err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
f39230a531b23d94f86a087963299bbe2e431a4agstein &resource);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (err != NULL)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return dav_handle_err(r, err, NULL);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, HTTP_CONFLICT,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Cannot uncheckout this type of resource.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->versioned) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, HTTP_CONFLICT,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Cannot uncheckout unversioned resource.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->working) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, HTTP_CONFLICT,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, HTTP_CONFLICT, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Could not UNCHECKOUT resource %s.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_escape_html(r->pool, r->uri)),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* no body */
f4c310fd2555c6faca1f980f00b161eadb089023gstein ap_set_content_length(r, 0);
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;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_doc *doc;
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein int keep_checked_out = 0;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* If no versioning provider, decline the request */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (vsn_hooks == NULL)
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DECLINED;
f4c310fd2555c6faca1f980f00b161eadb089023gstein
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein if ((result = ap_xml_parse_input(r, &doc)) != OK)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return result;
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein if (doc != NULL) {
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein if (!dav_validate_root(doc, "checkin")) {
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein /* This supplies additional information for the default msg. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00603)
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein "The request body, if present, must be a "
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein "DAV:checkin element.");
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein return HTTP_BAD_REQUEST;
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein }
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein keep_checked_out = dav_find_child(doc->root, "keep-checked-out") != NULL;
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Ask repository module to resolve the resource */
f39230a531b23d94f86a087963299bbe2e431a4agstein err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
f39230a531b23d94f86a087963299bbe2e431a4agstein &resource);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (err != NULL)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return dav_handle_err(r, err, NULL);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, HTTP_CONFLICT,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Cannot checkin this type of resource.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->versioned) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, HTTP_CONFLICT,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Cannot checkin unversioned resource.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (!resource->working) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, HTTP_CONFLICT,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The resource is not checked out.");
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### do lock checks, once behavior is defined */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* Do the checkin */
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein if ((err = (*vsn_hooks->checkin)(resource, keep_checked_out, &new_version))
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, HTTP_CONFLICT, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Could not CHECKIN resource %s.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_escape_html(r->pool, r->uri)),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
f4c310fd2555c6faca1f980f00b161eadb089023gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
83719c22db4a6d0575bb4f7f34382d7b185a6f74gstein return dav_created(r, new_version->uri, "Version", 0);
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gsteinstatic int dav_method_update(request_rec *r)
50bd75672ef114fb839dd9643c192b432fdf344cgstein{
50bd75672ef114fb839dd9643c192b432fdf344cgstein dav_resource *resource;
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein dav_resource *version = NULL;
50bd75672ef114fb839dd9643c192b432fdf344cgstein const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_doc *doc;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_elem *child;
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein int is_label = 0;
7281ea331999debdc337b02ce37a3169e0e033a2gstein int depth;
7281ea331999debdc337b02ce37a3169e0e033a2gstein int result;
6582c8e9b0d0d65427b0c55cb48eaac7950dcb8ftrawick apr_size_t tsize;
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein const char *target;
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein dav_response *multi_response;
7281ea331999debdc337b02ce37a3169e0e033a2gstein dav_error *err;
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein dav_lookup_result lookup;
50bd75672ef114fb839dd9643c192b432fdf344cgstein
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein /* If no versioning provider, or UPDATE not supported,
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein * decline the request */
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein if (vsn_hooks == NULL || vsn_hooks->update == NULL)
50bd75672ef114fb839dd9643c192b432fdf344cgstein return DECLINED;
50bd75672ef114fb839dd9643c192b432fdf344cgstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((depth = dav_get_depth(r, 0)) < 0) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* dav_get_depth() supplies additional information for the
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * default message. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
50bd75672ef114fb839dd9643c192b432fdf344cgstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* parse the request body */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((result = ap_xml_parse_input(r, &doc)) != OK) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return result;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein if (doc == NULL || !dav_validate_root(doc, "update")) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* This supplies additional information for the default message. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00604)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The request body does not contain "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "an \"update\" element.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein /* check for label-name or version element, but not both */
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein if ((child = dav_find_child(doc->root, "label-name")) != NULL)
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein is_label = 1;
7281ea331999debdc337b02ce37a3169e0e033a2gstein else if ((child = dav_find_child(doc->root, "version")) != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* get the href element */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((child = dav_find_child(child, "href")) == NULL) {
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00605)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The version element does not contain "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "an \"href\" element.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein else {
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00606)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The \"update\" element does not contain "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "a \"label-name\" or \"version\" element.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein /* a depth greater than zero is only allowed for a label */
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein if (!is_label && depth != 0) {
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00607)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Depth must be zero for UPDATE with a version");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein }
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein /* get the target value (a label or a version URI) */
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_to_text(r->pool, child, APR_XML_X2T_INNER, NULL, NULL,
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe &target, &tsize);
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (tsize == 0) {
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00608)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "A \"label-name\" or \"href\" element does not contain "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "any content.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein /* Ask repository module to resolve the resource */
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein &resource);
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein if (err != NULL)
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein return dav_handle_err(r, err, NULL);
f4c310fd2555c6faca1f980f00b161eadb089023gstein
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein if (!resource->exists) {
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein /* Apache will supply a default error for this. */
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein return HTTP_NOT_FOUND;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein /* ### need a general mechanism for reporting precondition violations
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein * ### (should be returning XML document for 403/409 responses)
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein */
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein if (resource->type != DAV_RESOURCE_TYPE_REGULAR
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein || !resource->versioned || resource->working) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, HTTP_CONFLICT,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "<DAV:must-be-checked-in-version-controlled-resource>");
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein }
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein /* if target is a version, resolve the version resource */
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein /* ### dav_lookup_uri only allows absolute URIs; is that OK? */
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein if (!is_label) {
48f35e10f195dd594d75738fc536bb885eda537cgstein lookup = dav_lookup_uri(target, r, 0 /* must_be_absolute */);
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein if (lookup.rnew == NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (lookup.err.status == HTTP_BAD_REQUEST) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* This supplies additional information for the default message. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00609)
8eed3bcafe1c99a43296009f5d2a862b984e3d46gstein "%s", lookup.err.desc);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### this assumes that dav_lookup_uri() only generates a status
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * ### that Apache can provide a status line for!! */
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, lookup.err.status, lookup.err.desc);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein if (lookup.rnew->status != HTTP_OK) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### how best to report this... */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, lookup.rnew->status,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Version URI had an error.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein /* resolve version resource */
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein err = dav_get_resource(lookup.rnew, 0 /* label_allowed */,
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein 0 /* use_checked_in */, &version);
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein if (err != NULL)
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein return dav_handle_err(r, err, NULL);
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein /* NULL out target, since we're using a version resource */
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein target = NULL;
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein }
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein /* do the UPDATE operation */
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein err = (*vsn_hooks->update)(resource, version, target, depth, &multi_response);
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein if (err != NULL) {
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein err = dav_push_error(r->pool, err->status, 0,
9c305658eb1006c78f760061b8840c1b4fc28038wrowe apr_psprintf(r->pool,
9c305658eb1006c78f760061b8840c1b4fc28038wrowe "Could not UPDATE %s.",
9c305658eb1006c78f760061b8840c1b4fc28038wrowe ap_escape_html(r->pool, r->uri)),
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein err);
d0b8a620f3625f57ff85d9b94fa549c8cfdc5934gstein return dav_handle_err(r, err, multi_response);
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
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)) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick err = dav_new_error(ctx->w.pool, HTTP_CONFLICT, 0, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "<DAV:must-be-version-or-version-selector/>");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein else if (wres->resource->working) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick err = dav_new_error(ctx->w.pool, HTTP_CONFLICT, 0, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "<DAV:must-not-be-checked-out/>");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein else {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* do the label operation */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (ctx->label_op == DAV_LABEL_REMOVE)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = (*ctx->vsn_hooks->remove_label)(wres->resource, ctx->label);
7281ea331999debdc337b02ce37a3169e0e033a2gstein else
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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);
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_doc *doc;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_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 */
f39230a531b23d94f86a087963299bbe2e431a4agstein err = dav_get_resource(r, 1 /* label_allowed */, 0 /* use_checked_in */,
f39230a531b23d94f86a087963299bbe2e431a4agstein &resource);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (err != NULL)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return dav_handle_err(r, err, NULL);
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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* dav_get_depth() supplies additional information for the
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * default message. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* parse the request body */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((result = ap_xml_parse_input(r, &doc)) != OK) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return result;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (doc == NULL || !dav_validate_root(doc, "label")) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* This supplies additional information for the default message. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00610)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The request body does not contain "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "a \"label\" element.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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 {
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00611)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The \"label\" element does not contain "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "an \"add\", \"set\", or \"remove\" element.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* get the label string */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((child = dav_find_child(child, "label-name")) == NULL) {
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00612)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The label command element does not contain "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "a \"label-name\" element.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_to_text(r->pool, child, APR_XML_X2T_INNER, NULL, NULL,
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe &ctx.label, &tsize);
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (tsize == 0) {
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00613)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "A \"label-name\" element does not contain "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "a label name.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick err = dav_new_error(r->pool, multi_status->status, 0, 0,
99d46a23c6eac800f327b29f8009f7d7da986230trawick multi_status->desc);
7281ea331999debdc337b02ce37a3169e0e033a2gstein multi_status = NULL;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein else {
99d46a23c6eac800f327b29f8009f7d7da986230trawick err = dav_new_error(r->pool, HTTP_MULTI_STATUS, 0, 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
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;
f39230a531b23d94f86a087963299bbe2e431a4agstein int label_allowed;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_doc *doc;
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)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return result;
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (doc == NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* This supplies additional information for the default msg. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00614)
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 */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein label_allowed = (*vsn_hooks->report_label_header_allowed)(doc);
f39230a531b23d94f86a087963299bbe2e431a4agstein err = dav_get_resource(r, label_allowed, 0 /* use_checked_in */,
f39230a531b23d94f86a087963299bbe2e431a4agstein &resource);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (err != NULL)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return dav_handle_err(r, err, NULL);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (!resource->exists) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* Apache will supply a default error for this. */
7281ea331999debdc337b02ce37a3169e0e033a2gstein return HTTP_NOT_FOUND;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
d0e1056198453d25bccaed50556118dd31caf58bgstein /* set up defaults for the report response */
7281ea331999debdc337b02ce37a3169e0e033a2gstein r->status = HTTP_OK;
e0d102c882a7ed34d3eec24b36da49f097066a36stoddard ap_set_content_type(r, DAV_XML_CONTENT_TYPE);
7281ea331999debdc337b02ce37a3169e0e033a2gstein
d0e1056198453d25bccaed50556118dd31caf58bgstein /* run report hook */
d0e1056198453d25bccaed50556118dd31caf58bgstein if ((err = (*vsn_hooks->deliver_report)(r, resource, doc,
d0e1056198453d25bccaed50556118dd31caf58bgstein r->output_filters)) != NULL) {
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein if (! r->sent_bodyct)
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein /* No data has been sent to client yet; throw normal error. */
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein return dav_handle_err(r, err, NULL);
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein /* If an error occurred during the report delivery, there's
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein basically nothing we can do but abort the connection and
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein log an error. This is one of the limitations of HTTP; it
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein needs to "know" the entire status of the response before
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein generating it, which is just impossible in these streamy
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein response situations. */
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein err = dav_push_error(r->pool, err->status, 0,
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein "Provider encountered an error while streaming"
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein " a REPORT response.", err);
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein dav_log_err(r, err, APLOG_ERR);
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein r->connection->aborted = 1;
dbff5589d5aec3f9621422b6343dd7e41fa2fab7gstein return DONE;
d0e1056198453d25bccaed50556118dd31caf58bgstein }
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;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_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 */
f39230a531b23d94f86a087963299bbe2e431a4agstein err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
f39230a531b23d94f86a087963299bbe2e431a4agstein &resource);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (err != NULL)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return dav_handle_err(r, err, NULL);
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* parse the request body (must be a mkworkspace element) */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((result = ap_xml_parse_input(r, &doc)) != OK) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return result;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (doc == NULL
7281ea331999debdc337b02ce37a3169e0e033a2gstein || !dav_validate_root(doc, "mkworkspace")) {
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00615)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The request body does not contain "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "a \"mkworkspace\" element.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick err = dav_new_error(r->pool, HTTP_CONFLICT, 0, 0,
7281ea331999debdc337b02ce37a3169e0e033a2gstein "<DAV:resource-must-be-null/>");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Could not create workspace %s.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_escape_html(r->pool, r->uri)),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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{
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein dav_resource *resource;
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein dav_error *err;
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein int result;
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein /* if no versioning provider, or the provider does not support activities,
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein * decline the request
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein */
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein if (vsn_hooks == NULL || vsn_hooks->make_activity == NULL)
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein return DECLINED;
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein /* ask repository module to resolve the resource */
f39230a531b23d94f86a087963299bbe2e431a4agstein err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
f39230a531b23d94f86a087963299bbe2e431a4agstein &resource);
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein if (err != NULL)
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein return dav_handle_err(r, err, NULL);
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein /* MKACTIVITY does not have a defined request body. */
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein if ((result = ap_discard_request_body(r)) != OK) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return result;
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein }
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein /* Check request preconditions */
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein /* ### need a general mechanism for reporting precondition violations
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein * ### (should be returning XML document for 403/409 responses)
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein */
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein /* resource must not already exist */
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein if (resource->exists) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick err = dav_new_error(r->pool, HTTP_CONFLICT, 0, 0,
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein "<DAV:resource-must-be-null/>");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, NULL);
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein }
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein
85a563d6914b7071bee294aa38bfe649c86abb63striker /* the provider must say whether the resource can be created as
85a563d6914b7071bee294aa38bfe649c86abb63striker an activity, i.e. whether the location is ok. */
85a563d6914b7071bee294aa38bfe649c86abb63striker if (vsn_hooks->can_be_activity != NULL
85a563d6914b7071bee294aa38bfe649c86abb63striker && !(*vsn_hooks->can_be_activity)(resource)) {
99d46a23c6eac800f327b29f8009f7d7da986230trawick err = dav_new_error(r->pool, HTTP_FORBIDDEN, 0, 0,
85a563d6914b7071bee294aa38bfe649c86abb63striker "<DAV:activity-location-ok/>");
85a563d6914b7071bee294aa38bfe649c86abb63striker return dav_handle_err(r, err, NULL);
85a563d6914b7071bee294aa38bfe649c86abb63striker }
85a563d6914b7071bee294aa38bfe649c86abb63striker
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein /* ### what about locking? */
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein /* attempt to create the activity */
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein if ((err = (*vsn_hooks->make_activity)(resource)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Could not create activity %s.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_escape_html(r->pool, r->uri)),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein return dav_handle_err(r, err, NULL);
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein }
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein /* set the Cache-Control header, per the spec */
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein apr_table_setn(r->headers_out, "Cache-Control", "no-cache");
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein /* return an appropriate response (HTTP_CREATED) */
f554635ae7f32620fefcd575dcbea37b1cc11b6egstein return dav_created(r, resource->uri, "Activity", 0 /*replaced*/);
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{
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein dav_resource *resource;
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein dav_resource *source_resource;
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein const dav_hooks_vsn *vsn_hooks = DAV_GET_HOOKS_VSN(r);
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein dav_error *err;
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein int result;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_doc *doc;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_elem *source_elem;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_elem *href_elem;
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe apr_xml_elem *prop_elem;
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein const char *source;
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein int no_auto_merge;
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein int no_checkout;
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein dav_lookup_result lookup;
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein /* If no versioning provider, decline the request */
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein if (vsn_hooks == NULL)
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein return DECLINED;
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein if ((result = ap_xml_parse_input(r, &doc)) != OK)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return result;
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein if (doc == NULL || !dav_validate_root(doc, "merge")) {
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein /* This supplies additional information for the default msg. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00616)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The request body must be present and must be a "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "DAV:merge element.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein }
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein if ((source_elem = dav_find_child(doc->root, "source")) == NULL) {
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein /* This supplies additional information for the default msg. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00617)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The DAV:merge element must contain a DAV:source "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "element.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein }
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein if ((href_elem = dav_find_child(source_elem, "href")) == NULL) {
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein /* This supplies additional information for the default msg. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00618)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The DAV:source element must contain a DAV:href "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "element.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein }
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein source = dav_xml_get_cdata(href_elem, r->pool, 1 /* strip_white */);
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein /* get a subrequest for the source, so that we can get a dav_resource
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein for that source. */
48f35e10f195dd594d75738fc536bb885eda537cgstein lookup = dav_lookup_uri(source, r, 0 /* must_be_absolute */);
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein if (lookup.rnew == NULL) {
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein if (lookup.err.status == HTTP_BAD_REQUEST) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* This supplies additional information for the default message. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00619)
8eed3bcafe1c99a43296009f5d2a862b984e3d46gstein "%s", lookup.err.desc);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### this assumes that dav_lookup_uri() only generates a status
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * ### that Apache can provide a status line for!! */
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, lookup.err.status, lookup.err.desc);
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein }
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein if (lookup.rnew->status != HTTP_OK) {
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein /* ### how best to report this... */
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein return dav_error_response(r, lookup.rnew->status,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Merge source URI had an error.");
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein }
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein err = dav_get_resource(lookup.rnew, 0 /* label_allowed */,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 0 /* use_checked_in */, &source_resource);
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein if (err != NULL)
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein return dav_handle_err(r, err, NULL);
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein no_auto_merge = dav_find_child(doc->root, "no-auto-merge") != NULL;
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein no_checkout = dav_find_child(doc->root, "no-checkout") != NULL;
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein prop_elem = dav_find_child(doc->root, "prop");
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein /* ### check RFC. I believe the DAV:merge element may contain any
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein ### element also allowed within DAV:checkout. need to extract them
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein ### here, and pass them along.
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein ### if so, then refactor the CHECKOUT method handling so we can reuse
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein ### the code. maybe create a structure to hold CHECKOUT parameters
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein ### which can be passed to the checkout() and merge() hooks. */
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein /* Ask repository module to resolve the resource */
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker &resource);
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein if (err != NULL)
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein return dav_handle_err(r, err, NULL);
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein if (!resource->exists) {
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein /* Apache will supply a default error for this. */
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein return HTTP_NOT_FOUND;
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein }
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein /* ### check the source and target resources flags/types */
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein /* ### do lock checks, once behavior is defined */
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein /* set the Cache-Control header, per the spec */
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein /* ### correct? */
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein apr_table_setn(r->headers_out, "Cache-Control", "no-cache");
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein /* Initialize these values for a standard MERGE response. If the MERGE
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein is going to do something different (i.e. an error), then it must
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein return a dav_error, and we'll reset these values properly. */
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein r->status = HTTP_OK;
e0d102c882a7ed34d3eec24b36da49f097066a36stoddard ap_set_content_type(r, "text/xml");
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein /* ### should we do any preliminary response generation? probably not,
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein ### because we may have an error, thus demanding something else in
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein ### the response body. */
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein /* Do the merge, including any response generation. */
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein if ((err = (*vsn_hooks->merge)(resource, source_resource,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker no_auto_merge, no_checkout,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker prop_elem,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker r->output_filters)) != NULL) {
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein /* ### is err->status the right error here? */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Could not MERGE resource \"%s\" "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "into \"%s\".",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_escape_html(r->pool, source),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_escape_html(r->pool, r->uri)),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein return dav_handle_err(r, err, NULL);
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein }
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein /* the response was fully generated by the merge() hook. */
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein /* ### urk. does this prevent logging? need to check... */
9a1d0e3184c65f510dbef5e83ba5b9f27f961b44gstein return DONE;
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
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 */
f39230a531b23d94f86a087963299bbe2e431a4agstein err = dav_get_resource(r, 0 /* label_allowed */, 0 /* use_checked_in */,
f39230a531b23d94f86a087963299bbe2e431a4agstein &resource);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (err != NULL)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return dav_handle_err(r, err, NULL);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (!resource->exists) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* Apache will supply a default error for this. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_NOT_FOUND;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* get the destination URI */
7281ea331999debdc337b02ce37a3169e0e033a2gstein dest = apr_table_get(r->headers_in, "Destination");
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (dest == NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* This supplies additional information for the default message. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00620)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The request is missing a Destination header.");
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
48f35e10f195dd594d75738fc536bb885eda537cgstein lookup = dav_lookup_uri(dest, r, 0 /* must_be_absolute */);
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (lookup.rnew == NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker if (lookup.err.status == HTTP_BAD_REQUEST) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* This supplies additional information for the default message. */
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00621)
8eed3bcafe1c99a43296009f5d2a862b984e3d46gstein "%s", lookup.err.desc);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker }
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,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Cross server bindings are not "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "allowed by this server.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### this assumes that dav_lookup_uri() only generates a status
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * ### that Apache can provide a status line for!! */
7281ea331999debdc337b02ce37a3169e0e033a2gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, lookup.err.status, lookup.err.desc);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (lookup.rnew->status != HTTP_OK) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### how best to report this... */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, lookup.rnew->status,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Destination URI had an error.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* resolve binding resource */
f39230a531b23d94f86a087963299bbe2e431a4agstein err = dav_get_resource(lookup.rnew, 0 /* label_allowed */,
f39230a531b23d94f86a087963299bbe2e431a4agstein 0 /* use_checked_in */, &binding);
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein if (err != NULL)
866b521be8a30b2798ad3c3b73de5e965edd7c2fgstein return dav_handle_err(r, err, NULL);
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* are the two resources handled by the same repository? */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (resource->hooks != binding->hooks) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* ### this message exposes some backend config, but screw it... */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, HTTP_BAD_GATEWAY,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Destination URI is handled by a "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "different repository than the source URI. "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "BIND between repositories is not possible.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* get and parse the overwrite header value */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((overwrite = dav_get_overwrite(r)) < 0) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* dav_get_overwrite() supplies additional information for the
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * default message. */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return HTTP_BAD_REQUEST;
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* quick failure test: if dest exists and overwrite is false. */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (binding->exists && !overwrite) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, HTTP_PRECONDITION_FAILED,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Destination is not empty and "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Overwrite is not \"T\"");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* are the source and destination the same? */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((*resource->hooks->is_same_resource)(resource, binding)) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, HTTP_FORBIDDEN,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Source and Destination URIs are the same.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /*
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Check If-Headers and existing locks for destination. Note that we
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * use depth==infinity since the target (hierarchy) will be deleted
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * before the move/copy is completed.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Note that we are overwriting the target, which implies a DELETE, so
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * we are subject to the error/response rules as a DELETE. Namely, we
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * will return a 424 error if any of the validations fail.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * (see dav_method_delete() for more information)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if ((err = dav_validate_request(lookup.rnew, binding, DAV_INFINITY, NULL,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker &multi_response,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker DAV_VALIDATE_PARENT
7281ea331999debdc337b02ce37a3169e0e033a2gstein | DAV_VALIDATE_USE_424, NULL)) != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Could not BIND %s due to a "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "failed precondition on the "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "destination (e.g. locks).",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_escape_html(r->pool, r->uri)),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, multi_response);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* guard against creating circular bindings */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (resource->collection
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker && (*resource->hooks->is_parent_resource)(resource, binding)) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, HTTP_FORBIDDEN,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Source collection contains the Destination.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (resource->collection
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker && (*resource->hooks->is_parent_resource)(binding, resource)) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* The destination must exist (since it contains the source), and
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * a condition above implies Overwrite==T. Obviously, we cannot
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * delete the Destination before the BIND, as that would
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * delete the Source.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
7281ea331999debdc337b02ce37a3169e0e033a2gstein
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_error_response(r, HTTP_FORBIDDEN,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Destination collection contains the Source and "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Overwrite has been specified.");
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* prepare the destination collection for modification */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein if ((err = dav_auto_checkout(r, binding, 1 /* parent_only */,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker &av_info)) != NULL) {
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* could not make destination writable */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = (*resource->hooks->remove_resource)(binding, &multi_response);
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (err == NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = (*binding_hooks->bind_resource)(resource, binding);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* restore parent collection states */
4d0b0b6d8341c5e54b2081665fc91b4e4f781753gstein err2 = dav_auto_checkin(r, NULL,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err != NULL /* undo if error */,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 0 /* unlock */, &av_info);
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* check for error from remove/bind operations */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (err != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker apr_psprintf(r->pool,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "Could not BIND %s.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker ap_escape_html(r->pool, r->uri)),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_handle_err(r, err, multi_response);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein /* check for errors from reverting writability */
7281ea331999debdc337b02ce37a3169e0e033a2gstein if (err2 != NULL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker /* just log a warning */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err = dav_push_error(r->pool, err2->status, 0,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "The BIND was successful, but there was a "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "problem automatically checking in the "
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker "source parent collection.",
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker err2);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker 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 */
22e9a19da7fd79a2801d99e6501b8f8470abdf6ebreser return dav_created(r, lookup.rnew->unparsed_uri, "Binding", 0);
7281ea331999debdc337b02ce37a3169e0e033a2gstein}
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein
7281ea331999debdc337b02ce37a3169e0e033a2gstein/*
7281ea331999debdc337b02ce37a3169e0e033a2gstein * Response handler for DAV resources
7281ea331999debdc337b02ce37a3169e0e033a2gstein */
7281ea331999debdc337b02ce37a3169e0e033a2gsteinstatic int dav_handler(request_rec *r)
7281ea331999debdc337b02ce37a3169e0e033a2gstein{
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein if (strcmp(r->handler, DAV_HANDLER_NAME) != 0)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return DECLINED;
4aca53840942c24d6cab01c91137dcf6bbfee31agstein
3b86be5b30d5cbacc1f942b05dff8a9365449d30jorton /* Reject requests with an unescaped hash character, as these may
3b86be5b30d5cbacc1f942b05dff8a9365449d30jorton * be more destructive than the user intended. */
3b86be5b30d5cbacc1f942b05dff8a9365449d30jorton if (r->parsed_uri.fragment != NULL) {
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00622)
3b86be5b30d5cbacc1f942b05dff8a9365449d30jorton "buggy client used un-escaped hash in Request-URI");
e8f95a682820a599fe41b22977010636be5c2717jim return dav_error_response(r, HTTP_BAD_REQUEST,
3b86be5b30d5cbacc1f942b05dff8a9365449d30jorton "The request was invalid: the URI included "
3b86be5b30d5cbacc1f942b05dff8a9365449d30jorton "an un-escaped hash character");
3b86be5b30d5cbacc1f942b05dff8a9365449d30jorton }
3b86be5b30d5cbacc1f942b05dff8a9365449d30jorton
4aca53840942c24d6cab01c91137dcf6bbfee31agstein /* ### do we need to do anything with r->proxyreq ?? */
4aca53840942c24d6cab01c91137dcf6bbfee31agstein
4aca53840942c24d6cab01c91137dcf6bbfee31agstein /*
4aca53840942c24d6cab01c91137dcf6bbfee31agstein * ### anything else to do here? could another module and/or
4aca53840942c24d6cab01c91137dcf6bbfee31agstein * ### config option "take over" the handler here? i.e. how do
4aca53840942c24d6cab01c91137dcf6bbfee31agstein * ### we lock down this hierarchy so that we are the ultimate
4aca53840942c24d6cab01c91137dcf6bbfee31agstein * ### arbiter? (or do we simply depend on the administrator
4aca53840942c24d6cab01c91137dcf6bbfee31agstein * ### to avoid conflicting configurations?)
4aca53840942c24d6cab01c91137dcf6bbfee31agstein */
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
48d2edbfb84e5559b5da0f8d614ccab805cc67a8rbb | (AP_METHOD_BIT << M_GET)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker | (AP_METHOD_BIT << M_PUT)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker | (AP_METHOD_BIT << M_DELETE)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker | (AP_METHOD_BIT << M_OPTIONS)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker | (AP_METHOD_BIT << M_INVALID);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
f4c310fd2555c6faca1f980f00b161eadb089023gstein /*
f4c310fd2555c6faca1f980f00b161eadb089023gstein * These are the DAV methods we handle.
f4c310fd2555c6faca1f980f00b161eadb089023gstein */
f4c310fd2555c6faca1f980f00b161eadb089023gstein r->allowed |= 0
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker | (AP_METHOD_BIT << M_COPY)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker | (AP_METHOD_BIT << M_LOCK)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker | (AP_METHOD_BIT << M_UNLOCK)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker | (AP_METHOD_BIT << M_MKCOL)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker | (AP_METHOD_BIT << M_MOVE)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker | (AP_METHOD_BIT << M_PROPFIND)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker | (AP_METHOD_BIT << M_PROPPATCH);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
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
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker | (AP_METHOD_BIT << M_POST);
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
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
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * ### allowed states, so we must
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* ### we might need to refine this for just where we return the error.
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * ### also, there is the issue with other methods (see ISSUES)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
f4c310fd2555c6faca1f980f00b161eadb089023gstein /* dispatch the appropriate method handler */
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_GET) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_get(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_PUT) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_put(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_POST) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_post(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_DELETE) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_delete(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_OPTIONS) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_options(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_PROPFIND) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_propfind(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_PROPPATCH) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_proppatch(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_MKCOL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_mkcol(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_COPY) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_copymove(r, DAV_DO_COPY);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_MOVE) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_copymove(r, DAV_DO_MOVE);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_LOCK) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_lock(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein if (r->method_number == M_UNLOCK) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_unlock(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
5a9667916c79d8c699b069068e5570aa1c331c80gstein if (r->method_number == M_VERSION_CONTROL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_vsn_control(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
5a9667916c79d8c699b069068e5570aa1c331c80gstein if (r->method_number == M_CHECKOUT) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_checkout(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
5a9667916c79d8c699b069068e5570aa1c331c80gstein if (r->method_number == M_UNCHECKOUT) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_uncheckout(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
5a9667916c79d8c699b069068e5570aa1c331c80gstein if (r->method_number == M_CHECKIN) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_checkin(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
5a9667916c79d8c699b069068e5570aa1c331c80gstein if (r->method_number == M_UPDATE) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_update(r);
50bd75672ef114fb839dd9643c192b432fdf344cgstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
5a9667916c79d8c699b069068e5570aa1c331c80gstein if (r->method_number == M_LABEL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_label(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
5a9667916c79d8c699b069068e5570aa1c331c80gstein if (r->method_number == M_REPORT) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_report(r);
f4c310fd2555c6faca1f980f00b161eadb089023gstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
5a9667916c79d8c699b069068e5570aa1c331c80gstein if (r->method_number == M_MKWORKSPACE) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_make_workspace(r);
50bd75672ef114fb839dd9643c192b432fdf344cgstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
5a9667916c79d8c699b069068e5570aa1c331c80gstein if (r->method_number == M_MKACTIVITY) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_make_activity(r);
50bd75672ef114fb839dd9643c192b432fdf344cgstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
5a9667916c79d8c699b069068e5570aa1c331c80gstein if (r->method_number == M_BASELINE_CONTROL) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_baseline_control(r);
50bd75672ef114fb839dd9643c192b432fdf344cgstein }
50bd75672ef114fb839dd9643c192b432fdf344cgstein
5a9667916c79d8c699b069068e5570aa1c331c80gstein if (r->method_number == M_MERGE) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_merge(r);
50bd75672ef114fb839dd9643c192b432fdf344cgstein }
f4c310fd2555c6faca1f980f00b161eadb089023gstein
4aca53840942c24d6cab01c91137dcf6bbfee31agstein /* BIND method */
ef3c32d4a7accb38368c7b9face2ade88d987a8bgstein if (r->method_number == dav_methods[DAV_M_BIND]) {
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker return dav_method_bind(r);
7281ea331999debdc337b02ce37a3169e0e033a2gstein }
7281ea331999debdc337b02ce37a3169e0e033a2gstein
67ec15681c83d4f5e119f0742618569017beb3fbstriker /* DASL method */
67ec15681c83d4f5e119f0742618569017beb3fbstriker if (r->method_number == dav_methods[DAV_M_SEARCH]) {
67ec15681c83d4f5e119f0742618569017beb3fbstriker return dav_method_search(r);
67ec15681c83d4f5e119f0742618569017beb3fbstriker }
67ec15681c83d4f5e119f0742618569017beb3fbstriker
67ec15681c83d4f5e119f0742618569017beb3fbstriker /* ### add'l methods for Advanced Collections, ACLs */
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein return DECLINED;
f4c310fd2555c6faca1f980f00b161eadb089023gstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gsteinstatic int dav_fixups(request_rec *r)
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein{
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein dav_dir_conf *conf;
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein /* quickly ignore any HTTP/0.9 requests which aren't subreqs. */
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein if (r->assbackwards && !r->main) {
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein return DECLINED;
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein }
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein conf = (dav_dir_conf *)ap_get_module_config(r->per_dir_config,
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein &dav_module);
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein /* if DAV is not enabled, then we've got nothing to do */
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein if (conf->provider == NULL) {
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein return DECLINED;
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein }
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein /* We are going to handle almost every request. In certain cases,
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein the provider maps to the filesystem (thus, handle_get is
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein FALSE), and core Apache will handle it. a For that case, we
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein just return right away. */
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein if (r->method_number == M_GET) {
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein /*
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein * ### need some work to pull Content-Type and Content-Language
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein * ### from the property database.
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein */
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein /*
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein * If the repository hasn't indicated that it will handle the
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein * GET method, then just punt.
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein *
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein * ### this isn't quite right... taking over the response can break
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein * ### things like mod_negotiation. need to look into this some more.
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein */
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein if (!conf->provider->repos->handle_get) {
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein return DECLINED;
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein }
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein }
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein
a5ca705e053a6c754c5958aafcd6f0aa60a2e67frbb /* ### this is wrong. We should only be setting the r->handler for the
a5ca705e053a6c754c5958aafcd6f0aa60a2e67frbb * requests that mod_dav knows about. If we set the handler for M_POST
a5ca705e053a6c754c5958aafcd6f0aa60a2e67frbb * requests, then CGI scripts that use POST will return the source for the
e8f95a682820a599fe41b22977010636be5c2717jim * script. However, mod_dav DOES handle POST, so something else needs
a5ca705e053a6c754c5958aafcd6f0aa60a2e67frbb * to be fixed.
a5ca705e053a6c754c5958aafcd6f0aa60a2e67frbb */
a5ca705e053a6c754c5958aafcd6f0aa60a2e67frbb if (r->method_number != M_POST) {
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein
a5ca705e053a6c754c5958aafcd6f0aa60a2e67frbb /* We are going to be handling the response for this resource. */
a5ca705e053a6c754c5958aafcd6f0aa60a2e67frbb r->handler = DAV_HANDLER_NAME;
a5ca705e053a6c754c5958aafcd6f0aa60a2e67frbb return OK;
a5ca705e053a6c754c5958aafcd6f0aa60a2e67frbb }
a5ca705e053a6c754c5958aafcd6f0aa60a2e67frbb
a5ca705e053a6c754c5958aafcd6f0aa60a2e67frbb return DECLINED;
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein}
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein
73e8b26287de5c06fa470d36162e103dbac9c7e5wrowestatic void register_hooks(apr_pool_t *p)
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein{
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe ap_hook_handler(dav_handler, NULL, NULL, APR_HOOK_MIDDLE);
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe ap_hook_post_config(dav_init_handler, NULL, NULL, APR_HOOK_MIDDLE);
5ca401d5a2dd63d75464895dc2a6ea292b62fd99gstein ap_hook_fixups(dav_fixups, NULL, NULL, APR_HOOK_MIDDLE);
5fbee309625f7a631a42d7dc05bbfa0d45a926ccgstein
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe dav_hook_find_liveprop(dav_core_find_liveprop, NULL, NULL, APR_HOOK_LAST);
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe dav_hook_insert_all_liveprops(dav_core_insert_all_liveprops,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker NULL, NULL, APR_HOOK_MIDDLE);
5fbee309625f7a631a42d7dc05bbfa0d45a926ccgstein
73e8b26287de5c06fa470d36162e103dbac9c7e5wrowe dav_core_register_uris(p);
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein}
f4c310fd2555c6faca1f980f00b161eadb089023gstein
f4c310fd2555c6faca1f980f00b161eadb089023gstein/*---------------------------------------------------------------------------
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker *
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker * Configuration info for the module
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker */
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
f4c310fd2555c6faca1f980f00b161eadb089023gstein { NULL }
f4c310fd2555c6faca1f980f00b161eadb089023gstein};
f4c310fd2555c6faca1f980f00b161eadb089023gstein
98e9c4a310bb623ff788680f88b6bd200ff36a24wrowemodule DAV_DECLARE_DATA dav_module =
f4c310fd2555c6faca1f980f00b161eadb089023gstein{
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein STANDARD20_MODULE_STUFF,
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dav_create_dir_config, /* dir config creater */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dav_merge_dir_config, /* dir merger --- default is to override */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dav_create_server_config, /* server config */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dav_merge_server_config, /* merge server config */
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker dav_cmds, /* command table */
f5ec9b038bb9db933072ba2c0a8e7bb2a3cedbdagstein register_hooks, /* register hooks */
f4c310fd2555c6faca1f980f00b161eadb089023gstein};
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein
b980ad7fdc218b4855cde9f75a747527f50c554dwroweAPR_HOOK_STRUCT(
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe APR_HOOK_LINK(gather_propsets)
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe APR_HOOK_LINK(find_liveprop)
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe APR_HOOK_LINK(insert_all_liveprops)
ba8574a7fe6f1c3405982bb856591b5f13fe205agstein )
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
b980ad7fdc218b4855cde9f75a747527f50c554dwroweAPR_IMPLEMENT_EXTERNAL_HOOK_VOID(dav, DAV, gather_propsets,
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe (apr_array_header_t *uris),
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe (uris))
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
b980ad7fdc218b4855cde9f75a747527f50c554dwroweAPR_IMPLEMENT_EXTERNAL_HOOK_RUN_FIRST(dav, DAV, int, find_liveprop,
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe (const dav_resource *resource,
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe const char *ns_uri, const char *name,
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe const dav_hooks_liveprop **hooks),
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker (resource, ns_uri, name, hooks), 0)
49f1aab8b6762ee5b4afdb3a9cc48e7c00435dd3striker
b980ad7fdc218b4855cde9f75a747527f50c554dwroweAPR_IMPLEMENT_EXTERNAL_HOOK_VOID(dav, DAV, insert_all_liveprops,
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe (request_rec *r, const dav_resource *resource,
0946f90438dcf29a5fe5d9e21559b3b9d640bc12wrowe dav_prop_insert what, apr_text_header *phdr),
c4c825811ec30fc8639c4eac95ba6e947d886227orlikowski (r, resource, what, phdr))