util_lock.c revision 6f15570e3adc0faf87bf55f70857028276fc9e32
6de8046f8f7e07cd83895a528df25d977e502c76nd/* ====================================================================
f062ed7bd262a37a909dd77ce5fc23b446818823fielding * The Apache Software License, Version 1.1
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * Copyright (c) 2000-2002 The Apache Software Foundation. All rights
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * reserved.
2d2eda71267231c2526be701fe655db125852c1ffielding *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * Redistribution and use in source and binary forms, with or without
2d2eda71267231c2526be701fe655db125852c1ffielding * modification, are permitted provided that the following conditions
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * are met:
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * 1. Redistributions of source code must retain the above copyright
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * notice, this list of conditions and the following disclaimer.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd *
2d2eda71267231c2526be701fe655db125852c1ffielding * 2. Redistributions in binary form must reproduce the above copyright
2d2eda71267231c2526be701fe655db125852c1ffielding * notice, this list of conditions and the following disclaimer in
2d2eda71267231c2526be701fe655db125852c1ffielding * the documentation and/or other materials provided with the
2d2eda71267231c2526be701fe655db125852c1ffielding * distribution.
2d2eda71267231c2526be701fe655db125852c1ffielding *
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb * 3. The end-user documentation included with the redistribution,
b980ad7fdc218b4855cde9f75a747527f50c554dwrowe * if any, must include the following acknowledgment:
ab5581cc78e9d865b0a6ab1404c53347b3276968rbb * "This product includes software developed by the
92f3af936ce61f25358a3ee4f28df2f6d62040dfdreid * Apache Software Foundation (http://www.apache.org/)."
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb * Alternately, this acknowledgment may appear in the software itself,
c9a95767fbf0f5fb0976a06b97a256033925e433rbb * if and wherever such third-party acknowledgments normally appear.
fd0edaa8e3d4dd67d0604ccef2e96b071db96643fielding *
2d2eda71267231c2526be701fe655db125852c1ffielding * 4. The names "Apache" and "Apache Software Foundation" must
2d2eda71267231c2526be701fe655db125852c1ffielding * not be used to endorse or promote products derived from this
2d2eda71267231c2526be701fe655db125852c1ffielding * software without prior written permission. For written
2d2eda71267231c2526be701fe655db125852c1ffielding * permission, please contact apache@apache.org.
61fd0cab072a05b855cbef9c585702401ac5ae29rbb *
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * 5. Products derived from this software may not be called "Apache",
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * nor may "Apache" appear in their name, without prior written
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * permission of the Apache Software Foundation.
52de7a47876ce1748910cf3a0ee97f78842fab54rederpj *
52de7a47876ce1748910cf3a0ee97f78842fab54rederpj * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
52de7a47876ce1748910cf3a0ee97f78842fab54rederpj * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
52de7a47876ce1748910cf3a0ee97f78842fab54rederpj * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
52de7a47876ce1748910cf3a0ee97f78842fab54rederpj * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
52de7a47876ce1748910cf3a0ee97f78842fab54rederpj * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
52de7a47876ce1748910cf3a0ee97f78842fab54rederpj * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
fd492f9543f14fb5bae78e04b135c3448eb9cc56rbb * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
fd492f9543f14fb5bae78e04b135c3448eb9cc56rbb * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
fd492f9543f14fb5bae78e04b135c3448eb9cc56rbb * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
fd492f9543f14fb5bae78e04b135c3448eb9cc56rbb * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
fd492f9543f14fb5bae78e04b135c3448eb9cc56rbb * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2d2eda71267231c2526be701fe655db125852c1ffielding * SUCH DAMAGE.
2d2eda71267231c2526be701fe655db125852c1ffielding * ====================================================================
2d2eda71267231c2526be701fe655db125852c1ffielding *
2d2eda71267231c2526be701fe655db125852c1ffielding * This software consists of voluntary contributions made by many
2d2eda71267231c2526be701fe655db125852c1ffielding * individuals on behalf of the Apache Software Foundation. For more
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * information on the Apache Software Foundation, please see
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * <http://www.apache.org/>.
61fd0cab072a05b855cbef9c585702401ac5ae29rbb */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/*
2d2eda71267231c2526be701fe655db125852c1ffielding** DAV repository-independent lock functions
2d2eda71267231c2526be701fe655db125852c1ffielding*/
8af88bd6958b80c224e964892b8237720b13ab1ajerenkrantz
8af88bd6958b80c224e964892b8237720b13ab1ajerenkrantz#include "apr.h"
8af88bd6958b80c224e964892b8237720b13ab1ajerenkrantz#include "apr_strings.h"
8af88bd6958b80c224e964892b8237720b13ab1ajerenkrantz
50e60f30bdc074fbc887f0b98f4d570457ac97c9brianp#if APR_HAVE_STDIO_H
50e60f30bdc074fbc887f0b98f4d570457ac97c9brianp#include <stdio.h> /* for sprintf() */
50e60f30bdc074fbc887f0b98f4d570457ac97c9brianp#endif
50e60f30bdc074fbc887f0b98f4d570457ac97c9brianp
50e60f30bdc074fbc887f0b98f4d570457ac97c9brianp#include "mod_dav.h"
50e60f30bdc074fbc887f0b98f4d570457ac97c9brianp#include "http_log.h"
50e60f30bdc074fbc887f0b98f4d570457ac97c9brianp#include "http_config.h"
50e60f30bdc074fbc887f0b98f4d570457ac97c9brianp#include "http_protocol.h"
50e60f30bdc074fbc887f0b98f4d570457ac97c9brianp#include "http_core.h"
50e60f30bdc074fbc887f0b98f4d570457ac97c9brianp
8af88bd6958b80c224e964892b8237720b13ab1ajerenkrantz
bfb62a96023822c56c9120e4ee627d4091cc59c2rbb/* ---------------------------------------------------------------
bfb62a96023822c56c9120e4ee627d4091cc59c2rbb**
61fd0cab072a05b855cbef9c585702401ac5ae29rbb** Property-related lock functions
61fd0cab072a05b855cbef9c585702401ac5ae29rbb**
61fd0cab072a05b855cbef9c585702401ac5ae29rbb*/
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/*
61fd0cab072a05b855cbef9c585702401ac5ae29rbb** dav_lock_get_activelock: Returns a <lockdiscovery> containing
3d96ee83babeec32482c9082c9426340cee8c44dwrowe** an activelock element for every item in the lock_discovery tree
2d2eda71267231c2526be701fe655db125852c1ffielding*/
61fd0cab072a05b855cbef9c585702401ac5ae29rbbconst char *dav_lock_get_activelock(request_rec *r, dav_lock *lock,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_buffer *pbuf)
61fd0cab072a05b855cbef9c585702401ac5ae29rbb{
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_lock *lock_scan;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb const dav_hooks_locks *hooks = DAV_GET_HOOKS_LOCKS(r);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb int count = 0;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_buffer work_buf = { 0 };
61fd0cab072a05b855cbef9c585702401ac5ae29rbb apr_pool_t *p = r->pool;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
2d2eda71267231c2526be701fe655db125852c1ffielding /* If no locks or no lock provider, there are no locks */
3d96ee83babeec32482c9082c9426340cee8c44dwrowe if (lock == NULL || hooks == NULL) {
2d2eda71267231c2526be701fe655db125852c1ffielding /*
2d2eda71267231c2526be701fe655db125852c1ffielding ** Since resourcediscovery is defined with (activelock)*,
2d2eda71267231c2526be701fe655db125852c1ffielding ** <D:activelock/> shouldn't be necessary for an empty lock.
2d2eda71267231c2526be701fe655db125852c1ffielding */
000b67449410515eac43e76ef6667915bfd4d2abgstein return "";
2d2eda71267231c2526be701fe655db125852c1ffielding }
2d2eda71267231c2526be701fe655db125852c1ffielding
2d2eda71267231c2526be701fe655db125852c1ffielding /*
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ** Note: it could be interesting to sum the lengths of the owners
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ** and locktokens during this loop. However, the buffer
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ** mechanism provides some rough padding so that we don't
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ** really need to have an exact size. Further, constructing
7bdef86e15d47d16dcbe7a5611683191774bd5fbgstein ** locktoken strings could be relatively expensive.
61fd0cab072a05b855cbef9c585702401ac5ae29rbb */
7bdef86e15d47d16dcbe7a5611683191774bd5fbgstein for (lock_scan = lock; lock_scan != NULL; lock_scan = lock_scan->next)
7bdef86e15d47d16dcbe7a5611683191774bd5fbgstein count++;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* if a buffer was not provided, then use an internal buffer */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (pbuf == NULL)
61fd0cab072a05b855cbef9c585702401ac5ae29rbb pbuf = &work_buf;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* reset the length before we start appending stuff */
3d96ee83babeec32482c9082c9426340cee8c44dwrowe pbuf->cur_len = 0;
7bdef86e15d47d16dcbe7a5611683191774bd5fbgstein
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* prep the buffer with a "good" size */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_check_bufsize(p, pbuf, count * 300);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb for (; lock != NULL; lock = lock->next) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb char tmp[100];
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb#if DAV_DEBUG
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (lock->rectype == DAV_LOCKREC_INDIRECT_PARTIAL) {
3d96ee83babeec32482c9082c9426340cee8c44dwrowe /* ### crap. design error */
7bdef86e15d47d16dcbe7a5611683191774bd5fbgstein dav_buffer_append(p, pbuf,
c9a95767fbf0f5fb0976a06b97a256033925e433rbb "DESIGN ERROR: attempted to product an "
c9a95767fbf0f5fb0976a06b97a256033925e433rbb "activelock element from a partial, indirect "
c9a95767fbf0f5fb0976a06b97a256033925e433rbb "lock record. Creating an XML parsing error "
c9a95767fbf0f5fb0976a06b97a256033925e433rbb "to ease detection of this situation: <");
c9a95767fbf0f5fb0976a06b97a256033925e433rbb }
c9a95767fbf0f5fb0976a06b97a256033925e433rbb#endif
c9a95767fbf0f5fb0976a06b97a256033925e433rbb
c9a95767fbf0f5fb0976a06b97a256033925e433rbb dav_buffer_append(p, pbuf, "<D:activelock>" DEBUG_CR "<D:locktype>");
c9a95767fbf0f5fb0976a06b97a256033925e433rbb switch (lock->type) {
c9a95767fbf0f5fb0976a06b97a256033925e433rbb case DAV_LOCKTYPE_WRITE:
c9a95767fbf0f5fb0976a06b97a256033925e433rbb dav_buffer_append(p, pbuf, "<D:write/>");
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp break;
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp default:
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp /* ### internal error. log something? */
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp break;
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp }
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp dav_buffer_append(p, pbuf, "</D:locktype>" DEBUG_CR "<D:lockscope>");
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp switch (lock->scope) {
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp case DAV_LOCKSCOPE_EXCLUSIVE:
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp dav_buffer_append(p, pbuf, "<D:exclusive/>");
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp break;
d82d78a97558238d16c52ec5278fe921bb7d7ec3brianp case DAV_LOCKSCOPE_SHARED:
c9a95767fbf0f5fb0976a06b97a256033925e433rbb dav_buffer_append(p, pbuf, "<D:shared/>");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb break;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb default:
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* ### internal error. log something? */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb break;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_buffer_append(p, pbuf, "</D:lockscope>" DEBUG_CR);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb sprintf(tmp, "<D:depth>%s</D:depth>" DEBUG_CR,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb lock->depth == DAV_INFINITY ? "infinity" : "0");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_buffer_append(p, pbuf, tmp);
3d96ee83babeec32482c9082c9426340cee8c44dwrowe
7bdef86e15d47d16dcbe7a5611683191774bd5fbgstein if (lock->owner) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /*
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ** This contains a complete, self-contained <DAV:owner> element,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ** with namespace declarations and xml:lang handling. Just drop
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ** it in.
61fd0cab072a05b855cbef9c585702401ac5ae29rbb */
3d96ee83babeec32482c9082c9426340cee8c44dwrowe dav_buffer_append(p, pbuf, lock->owner);
7bdef86e15d47d16dcbe7a5611683191774bd5fbgstein }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_buffer_append(p, pbuf, "<D:timeout>");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (lock->timeout == DAV_TIMEOUT_INFINITE) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_buffer_append(p, pbuf, "Infinite");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
3d96ee83babeec32482c9082c9426340cee8c44dwrowe else {
7bdef86e15d47d16dcbe7a5611683191774bd5fbgstein time_t now = time(NULL);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb sprintf(tmp, "Second-%lu", (long unsigned int)(lock->timeout - now));
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_buffer_append(p, pbuf, tmp);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_buffer_append(p, pbuf,
78ae1cbba5a848a24ca551629bbf0a90d2b931f0stas "</D:timeout>" DEBUG_CR
78ae1cbba5a848a24ca551629bbf0a90d2b931f0stas "<D:locktoken>" DEBUG_CR
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "<D:href>");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_buffer_append(p, pbuf,
3d96ee83babeec32482c9082c9426340cee8c44dwrowe (*hooks->format_locktoken)(p, lock->locktoken));
2d2eda71267231c2526be701fe655db125852c1ffielding dav_buffer_append(p, pbuf,
2d2eda71267231c2526be701fe655db125852c1ffielding "</D:href>" DEBUG_CR
2d2eda71267231c2526be701fe655db125852c1ffielding "</D:locktoken>" DEBUG_CR
2d2eda71267231c2526be701fe655db125852c1ffielding "</D:activelock>" DEBUG_CR);
2d2eda71267231c2526be701fe655db125852c1ffielding }
2d2eda71267231c2526be701fe655db125852c1ffielding
2d2eda71267231c2526be701fe655db125852c1ffielding return pbuf->buf;
2d2eda71267231c2526be701fe655db125852c1ffielding}
2d2eda71267231c2526be701fe655db125852c1ffielding
2d2eda71267231c2526be701fe655db125852c1ffielding/*
2d2eda71267231c2526be701fe655db125852c1ffielding** dav_lock_parse_lockinfo: Validates the given xml_doc to contain a
2d2eda71267231c2526be701fe655db125852c1ffielding** lockinfo XML element, then populates a dav_lock structure
61fd0cab072a05b855cbef9c585702401ac5ae29rbb** with its contents.
61fd0cab072a05b855cbef9c585702401ac5ae29rbb*/
61fd0cab072a05b855cbef9c585702401ac5ae29rbbdav_error * dav_lock_parse_lockinfo(request_rec *r,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb const dav_resource *resource,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_lockdb *lockdb,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb const apr_xml_doc *doc,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_lock **lock_request)
61fd0cab072a05b855cbef9c585702401ac5ae29rbb{
61fd0cab072a05b855cbef9c585702401ac5ae29rbb apr_pool_t *p = r->pool;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_error *err;
3d96ee83babeec32482c9082c9426340cee8c44dwrowe apr_xml_elem *child;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm dav_lock *lock;
7bdef86e15d47d16dcbe7a5611683191774bd5fbgstein
23ff73a56371e21f16744cb94d06399b877829f1rbb if (!dav_validate_root(doc, "lockinfo")) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return dav_new_error(p, HTTP_BAD_REQUEST, 0,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "The request body contains an unexpected "
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "XML root element.");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if ((err = (*lockdb->hooks->create_lock)(lockdb, resource,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb &lock)) != NULL) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return dav_push_error(p, err->status, 0,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "Could not parse the lockinfo due to an "
3d96ee83babeec32482c9082c9426340cee8c44dwrowe "internal problem creating a lock structure.",
2d2eda71267231c2526be701fe655db125852c1ffielding err);
23ff73a56371e21f16744cb94d06399b877829f1rbb }
2d2eda71267231c2526be701fe655db125852c1ffielding
62db15de4c1f335a64d45821796ae197cff94ef8rbb lock->depth = dav_get_depth(r, DAV_INFINITY);
62db15de4c1f335a64d45821796ae197cff94ef8rbb if (lock->depth == -1) {
62db15de4c1f335a64d45821796ae197cff94ef8rbb return dav_new_error(p, HTTP_BAD_REQUEST, 0,
62db15de4c1f335a64d45821796ae197cff94ef8rbb "An invalid Depth header was specified.");
62db15de4c1f335a64d45821796ae197cff94ef8rbb }
62db15de4c1f335a64d45821796ae197cff94ef8rbb lock->timeout = dav_get_timeout(r);
62db15de4c1f335a64d45821796ae197cff94ef8rbb
62db15de4c1f335a64d45821796ae197cff94ef8rbb /* Parse elements in the XML body */
62db15de4c1f335a64d45821796ae197cff94ef8rbb for (child = doc->root->first_child; child; child = child->next) {
48d2edbfb84e5559b5da0f8d614ccab805cc67a8rbb if (strcmp(child->name, "locktype") == 0
62db15de4c1f335a64d45821796ae197cff94ef8rbb && child->first_child
62db15de4c1f335a64d45821796ae197cff94ef8rbb && lock->type == DAV_LOCKTYPE_UNKNOWN) {
62db15de4c1f335a64d45821796ae197cff94ef8rbb if (strcmp(child->first_child->name, "write") == 0) {
62db15de4c1f335a64d45821796ae197cff94ef8rbb lock->type = DAV_LOCKTYPE_WRITE;
62db15de4c1f335a64d45821796ae197cff94ef8rbb continue;
62db15de4c1f335a64d45821796ae197cff94ef8rbb }
62db15de4c1f335a64d45821796ae197cff94ef8rbb }
62db15de4c1f335a64d45821796ae197cff94ef8rbb if (strcmp(child->name, "lockscope") == 0
62db15de4c1f335a64d45821796ae197cff94ef8rbb && child->first_child
62db15de4c1f335a64d45821796ae197cff94ef8rbb && lock->scope == DAV_LOCKSCOPE_UNKNOWN) {
62db15de4c1f335a64d45821796ae197cff94ef8rbb if (strcmp(child->first_child->name, "exclusive") == 0)
62db15de4c1f335a64d45821796ae197cff94ef8rbb lock->scope = DAV_LOCKSCOPE_EXCLUSIVE;
48d2edbfb84e5559b5da0f8d614ccab805cc67a8rbb else if (strcmp(child->first_child->name, "shared") == 0)
48d2edbfb84e5559b5da0f8d614ccab805cc67a8rbb lock->scope = DAV_LOCKSCOPE_SHARED;
62db15de4c1f335a64d45821796ae197cff94ef8rbb if (lock->scope != DAV_LOCKSCOPE_UNKNOWN)
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar continue;
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar }
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar if (strcmp(child->name, "owner") == 0 && lock->owner == NULL) {
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar const char *text;
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar /* quote all the values in the <DAV:owner> element */
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar apr_xml_quote_elem(p, child);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar /*
3d96ee83babeec32482c9082c9426340cee8c44dwrowe ** Store a full <DAV:owner> element with namespace definitions
3d96ee83babeec32482c9082c9426340cee8c44dwrowe ** and an xml:lang definition, if applicable.
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar */
3d96ee83babeec32482c9082c9426340cee8c44dwrowe apr_xml_to_text(p, child, APR_XML_X2T_FULL_NS_LANG, doc->namespaces,
a19698aebe10b9d41574e4a73794ba7d4cecd78btrawick NULL, &text, NULL);
a19698aebe10b9d41574e4a73794ba7d4cecd78btrawick lock->owner = text;
a19698aebe10b9d41574e4a73794ba7d4cecd78btrawick
3d96ee83babeec32482c9082c9426340cee8c44dwrowe continue;
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar }
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar return dav_new_error(p, HTTP_PRECONDITION_FAILED, 0,
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar apr_psprintf(p,
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar "The server cannot satisfy the "
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar "LOCK request due to an unknown XML "
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar "element (\"%s\") within the "
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar "DAV:lockinfo element.",
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar child->name));
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar }
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar *lock_request = lock;
3d96ee83babeec32482c9082c9426340cee8c44dwrowe return NULL;
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar}
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar/* ---------------------------------------------------------------
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar**
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar** General lock functions
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar**
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar*/
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar/* dav_lock_walker: Walker callback function to record indirect locks */
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coarstatic dav_error * dav_lock_walker(dav_walk_resource *wres, int calltype)
3d96ee83babeec32482c9082c9426340cee8c44dwrowe{
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar dav_walker_ctx *ctx = wres->walk_ctx;
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar dav_error *err;
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar /* We don't want to set indirects on the target */
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar if ((*wres->resource->hooks->is_same_resource)(wres->resource,
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar ctx->w.root))
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar return NULL;
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar if ((err = (*ctx->w.lockdb->hooks->append_locks)(ctx->w.lockdb,
3d96ee83babeec32482c9082c9426340cee8c44dwrowe wres->resource, 1,
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar ctx->lock)) != NULL) {
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar if (ap_is_HTTP_SERVER_ERROR(err->status)) {
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar /* ### add a higher-level description? */
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar return err;
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar }
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar /* add to the multistatus response */
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar dav_add_response(wres, err->status, NULL);
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar
3d96ee83babeec32482c9082c9426340cee8c44dwrowe /*
91f0d8da77152d24e4bbb31ce199282b3fd6e3b2coar ** ### actually, this is probably wrong: we want to fail the whole
2864362ca8266097928e84f101010bdf814ffa08stoddard ** ### LOCK process if something goes bad. maybe the caller should
db08da9ddcd65c31f9ea44b823898b72a1b24fbestoddard ** ### do a dav_unlock() (e.g. a rollback) if any errors occurred.
db08da9ddcd65c31f9ea44b823898b72a1b24fbestoddard */
bf648cbfa4a723c9c02fe8444103cd41ed8642d0wrowe }
db08da9ddcd65c31f9ea44b823898b72a1b24fbestoddard
bf648cbfa4a723c9c02fe8444103cd41ed8642d0wrowe return NULL;
bf648cbfa4a723c9c02fe8444103cd41ed8642d0wrowe}
2864362ca8266097928e84f101010bdf814ffa08stoddard
db08da9ddcd65c31f9ea44b823898b72a1b24fbestoddard/*
2864362ca8266097928e84f101010bdf814ffa08stoddard** dav_add_lock: Add a direct lock for resource, and indirect locks for
2d2eda71267231c2526be701fe655db125852c1ffielding** all children, bounded by depth.
2d2eda71267231c2526be701fe655db125852c1ffielding** ### assume request only contains one lock
2d2eda71267231c2526be701fe655db125852c1ffielding*/
2d2eda71267231c2526be701fe655db125852c1ffieldingdav_error * dav_add_lock(request_rec *r, const dav_resource *resource,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_lockdb *lockdb, dav_lock *lock,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_response **response)
61fd0cab072a05b855cbef9c585702401ac5ae29rbb{
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_error *err;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb int depth = lock->depth;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb *response = NULL;
3d96ee83babeec32482c9082c9426340cee8c44dwrowe
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein /* Requested lock can be:
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * Depth: 0 for null resource, existing resource, or existing collection
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * Depth: Inf for existing collection
61fd0cab072a05b855cbef9c585702401ac5ae29rbb */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /*
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ** 2518 9.2 says to ignore depth if target is not a collection (it has
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ** no internal children); pretend the client gave the correct depth.
3d96ee83babeec32482c9082c9426340cee8c44dwrowe */
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein if (!resource->collection) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb depth = 0;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* In all cases, first add direct entry in lockdb */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /*
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ** Append the new (direct) lock to the resource's existing locks.
61fd0cab072a05b855cbef9c585702401ac5ae29rbb **
3d96ee83babeec32482c9082c9426340cee8c44dwrowe ** Note: this also handles locknull resources
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if ((err = (*lockdb->hooks->append_locks)(lockdb, resource, 0,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb lock)) != NULL) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* ### maybe add a higher-level description */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return err;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (depth > 0) {
3d96ee83babeec32482c9082c9426340cee8c44dwrowe /* Walk existing collection and set indirect locks */
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein dav_walker_ctx ctx = { { 0 } };
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_response *multi_status;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ctx.w.walk_type = DAV_WALKTYPE_NORMAL | DAV_WALKTYPE_AUTH;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ctx.w.func = dav_lock_walker;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ctx.w.walk_ctx = &ctx;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ctx.w.pool = r->pool;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ctx.w.root = resource;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ctx.w.lockdb = lockdb;
3d96ee83babeec32482c9082c9426340cee8c44dwrowe
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein ctx.r = r;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ctx.lock = lock;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb err = (*resource->hooks->walk)(&ctx.w, DAV_INFINITY, &multi_status);
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (err != NULL) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* implies a 5xx status code occurred. screw the multistatus */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return err;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
3d96ee83babeec32482c9082c9426340cee8c44dwrowe if (multi_status != NULL) {
2d2eda71267231c2526be701fe655db125852c1ffielding /* manufacture a 207 error for the multistatus response */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb *response = multi_status;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return dav_new_error(r->pool, HTTP_MULTI_STATUS, 0,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "Error(s) occurred on resources during the "
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "addition of a depth lock.");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
3d96ee83babeec32482c9082c9426340cee8c44dwrowe
2d2eda71267231c2526be701fe655db125852c1ffielding return NULL;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb}
2d2eda71267231c2526be701fe655db125852c1ffielding
2d2eda71267231c2526be701fe655db125852c1ffielding/*
61fd0cab072a05b855cbef9c585702401ac5ae29rbb** dav_lock_query: Opens the lock database. Returns a linked list of
61fd0cab072a05b855cbef9c585702401ac5ae29rbb** dav_lock structures for all direct locks on path.
61fd0cab072a05b855cbef9c585702401ac5ae29rbb*/
2d2eda71267231c2526be701fe655db125852c1ffieldingDAV_DECLARE(dav_error*) dav_lock_query(dav_lockdb *lockdb,
3d96ee83babeec32482c9082c9426340cee8c44dwrowe const dav_resource *resource,
2d2eda71267231c2526be701fe655db125852c1ffielding dav_lock **locks)
61fd0cab072a05b855cbef9c585702401ac5ae29rbb{
d839a9822ee53ce00da24c15f2d9fe054233d342gstein /* If no lock database, return empty result */
d839a9822ee53ce00da24c15f2d9fe054233d342gstein if (lockdb == NULL) {
d839a9822ee53ce00da24c15f2d9fe054233d342gstein *locks = NULL;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return NULL;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
d839a9822ee53ce00da24c15f2d9fe054233d342gstein /* ### insert a higher-level description? */
3d96ee83babeec32482c9082c9426340cee8c44dwrowe return (*lockdb->hooks->get_locks)(lockdb, resource,
d839a9822ee53ce00da24c15f2d9fe054233d342gstein DAV_GETLOCKS_RESOLVED,
2d2eda71267231c2526be701fe655db125852c1ffielding locks);
2d2eda71267231c2526be701fe655db125852c1ffielding}
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/* dav_unlock_walker: Walker callback function to remove indirect locks */
61fd0cab072a05b855cbef9c585702401ac5ae29rbbstatic dav_error * dav_unlock_walker(dav_walk_resource *wres, int calltype)
61fd0cab072a05b855cbef9c585702401ac5ae29rbb{
346029f34d03eb20d84fc35664426d3874b00f9ewrowe dav_walker_ctx *ctx = wres->walk_ctx;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_error *err;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* Before removing the lock, do any auto-checkin required */
346029f34d03eb20d84fc35664426d3874b00f9ewrowe if (wres->resource->working) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* ### get rid of this typecast */
eda25307d712abd132e100e2b40ae1de5497d3e2trawick if ((err = dav_auto_checkin(ctx->r, (dav_resource *) wres->resource,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb 0 /*undo*/, 1 /*unlock*/, NULL))
3d96ee83babeec32482c9082c9426340cee8c44dwrowe != NULL) {
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein return err;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
face099b681c052cb1f52176a5499661c44b2982trawick
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if ((err = (*ctx->w.lockdb->hooks->remove_lock)(ctx->w.lockdb,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb wres->resource,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ctx->locktoken)) != NULL) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* ### should we stop or return a multistatus? looks like STOP */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* ### add a higher-level description? */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return err;
3d96ee83babeec32482c9082c9426340cee8c44dwrowe }
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return NULL;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb}
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/*
61fd0cab072a05b855cbef9c585702401ac5ae29rbb** dav_get_direct_resource:
61fd0cab072a05b855cbef9c585702401ac5ae29rbb**
61fd0cab072a05b855cbef9c585702401ac5ae29rbb** Find a lock on the specified resource, then return the resource the
61fd0cab072a05b855cbef9c585702401ac5ae29rbb** lock was applied to (in other words, given a (possibly) indirect lock,
11a7b0dff22d26770b532c174d1cf2e7b56ec244wrowe** return the direct lock's corresponding resource).
61fd0cab072a05b855cbef9c585702401ac5ae29rbb**
11a7b0dff22d26770b532c174d1cf2e7b56ec244wrowe** If the lock is an indirect lock, this usually means traversing up the
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein** namespace [repository] hierarchy. Note that some lock providers may be
61fd0cab072a05b855cbef9c585702401ac5ae29rbb** able to return this information with a traversal.
61fd0cab072a05b855cbef9c585702401ac5ae29rbb*/
61fd0cab072a05b855cbef9c585702401ac5ae29rbbstatic dav_error * dav_get_direct_resource(apr_pool_t *p,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_lockdb *lockdb,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb const dav_locktoken *locktoken,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb const dav_resource *resource,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb const dav_resource **direct_resource)
61fd0cab072a05b855cbef9c585702401ac5ae29rbb{
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (lockdb->hooks->lookup_resource != NULL) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return (*lockdb->hooks->lookup_resource)(lockdb, locktoken,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb resource, direct_resource);
3d96ee83babeec32482c9082c9426340cee8c44dwrowe }
2d2eda71267231c2526be701fe655db125852c1ffielding
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein *direct_resource = NULL;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* Find the top of this lock-
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * If r->filename's direct locks include locktoken, use r->filename.
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * If r->filename's indirect locks include locktoken, retry r->filename/..
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * Else fail.
61fd0cab072a05b855cbef9c585702401ac5ae29rbb */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb while (resource != NULL) {
3d96ee83babeec32482c9082c9426340cee8c44dwrowe dav_error *err;
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein dav_lock *lock;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_resource *parent;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /*
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ** Find the lock specified by <locktoken> on <resource>. If it is
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ** an indirect lock, then partial results are okay. We're just
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ** trying to find the thing and know whether it is a direct or
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ** an indirect lock.
3d96ee83babeec32482c9082c9426340cee8c44dwrowe */
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein if ((err = (*lockdb->hooks->find_lock)(lockdb, resource, locktoken,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb 1, &lock)) != NULL) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* ### add a higher-level desc? */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return err;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* not found! that's an error. */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (lock == NULL) {
3d96ee83babeec32482c9082c9426340cee8c44dwrowe return dav_new_error(p, HTTP_BAD_REQUEST, 0,
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein "The specified locktoken does not correspond "
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "to an existing lock on this resource.");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if (lock->rectype == DAV_LOCKREC_DIRECT) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* we found the direct lock. return this resource. */
94d240fc213d4a96160d7014633374cc22a204d8trawick
61fd0cab072a05b855cbef9c585702401ac5ae29rbb *direct_resource = resource;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return NULL;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* the lock was indirect. move up a level in the URL namespace */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb if ((err = (*resource->hooks->get_parent_resource)(resource,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb &parent)) != NULL) {
3d96ee83babeec32482c9082c9426340cee8c44dwrowe /* ### add a higher-level desc? */
2d2eda71267231c2526be701fe655db125852c1ffielding return err;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb resource = parent;
346029f34d03eb20d84fc35664426d3874b00f9ewrowe }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return dav_new_error(p, HTTP_INTERNAL_SERVER_ERROR, 0,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "The lock database is corrupt. A direct lock could "
346029f34d03eb20d84fc35664426d3874b00f9ewrowe "not be found for the corresponding indirect lock "
61fd0cab072a05b855cbef9c585702401ac5ae29rbb "on this resource.");
61fd0cab072a05b855cbef9c585702401ac5ae29rbb}
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/*
3d96ee83babeec32482c9082c9426340cee8c44dwrowe** dav_unlock: Removes all direct and indirect locks for r->filename,
2d2eda71267231c2526be701fe655db125852c1ffielding** with given locktoken. If locktoken == null_locktoken, all locks
fd8b91502bc200ed4cca3810560a2a570522b3debrianp** are removed. If r->filename represents an indirect lock,
fd8b91502bc200ed4cca3810560a2a570522b3debrianp** we must unlock the appropriate direct lock.
fd8b91502bc200ed4cca3810560a2a570522b3debrianp** Returns OK or appropriate HTTP_* response and logs any errors.
fd8b91502bc200ed4cca3810560a2a570522b3debrianp**
fd8b91502bc200ed4cca3810560a2a570522b3debrianp** ### We've already crawled the tree to ensure everything was locked
fd8b91502bc200ed4cca3810560a2a570522b3debrianp** by us; there should be no need to incorporate a rollback.
fd8b91502bc200ed4cca3810560a2a570522b3debrianp*/
fd8b91502bc200ed4cca3810560a2a570522b3debrianpint dav_unlock(request_rec *r, const dav_resource *resource,
fd8b91502bc200ed4cca3810560a2a570522b3debrianp const dav_locktoken *locktoken)
fd8b91502bc200ed4cca3810560a2a570522b3debrianp{
fd8b91502bc200ed4cca3810560a2a570522b3debrianp int result;
aa4af3da5c68fe5dbd9d2c3fd7b2fe7103daa2b7dougm dav_lockdb *lockdb;
e351a4349a3dcc2e8d9c27bcdf72414bdde0942frbb const dav_resource *lock_resource = resource;
fd8b91502bc200ed4cca3810560a2a570522b3debrianp const dav_hooks_locks *hooks = DAV_GET_HOOKS_LOCKS(r);
fd8b91502bc200ed4cca3810560a2a570522b3debrianp const dav_hooks_repository *repos_hooks = resource->hooks;
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames dav_walker_ctx ctx = { { 0 } };
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames dav_response *multi_status;
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames dav_error *err;
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames /* If no locks provider, then there is nothing to unlock. */
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames if (hooks == NULL) {
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames return OK;
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames }
fd8b91502bc200ed4cca3810560a2a570522b3debrianp
fd8b91502bc200ed4cca3810560a2a570522b3debrianp /* 2518 requires the entire lock to be removed if resource/locktoken
fd8b91502bc200ed4cca3810560a2a570522b3debrianp * point to an indirect lock. We need resource of the _direct_
fd8b91502bc200ed4cca3810560a2a570522b3debrianp * lock in order to walk down the tree and remove the locks. So,
45613d36b9466a48def0498cffa07f48980720f8jerenkrantz * If locktoken != null_locktoken,
fd8b91502bc200ed4cca3810560a2a570522b3debrianp * Walk up the resource hierarchy until we see a direct lock.
fd8b91502bc200ed4cca3810560a2a570522b3debrianp * Or, we could get the direct lock's db/key, pick out the URL
50e60f30bdc074fbc887f0b98f4d570457ac97c9brianp * and do a subrequest. I think walking up is faster and will work
45613d36b9466a48def0498cffa07f48980720f8jerenkrantz * all the time.
45613d36b9466a48def0498cffa07f48980720f8jerenkrantz * Else
45613d36b9466a48def0498cffa07f48980720f8jerenkrantz * Just start removing all locks at and below resource.
fd8b91502bc200ed4cca3810560a2a570522b3debrianp */
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames if ((err = (*hooks->open_lockdb)(r, 0, 1, &lockdb)) != NULL) {
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames /* ### return err! maybe add a higher-level desc */
50e60f30bdc074fbc887f0b98f4d570457ac97c9brianp /* ### map result to something nice; log an error */
50e60f30bdc074fbc887f0b98f4d570457ac97c9brianp return HTTP_INTERNAL_SERVER_ERROR;
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames }
50e60f30bdc074fbc887f0b98f4d570457ac97c9brianp
50e60f30bdc074fbc887f0b98f4d570457ac97c9brianp if (locktoken != NULL
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames && (err = dav_get_direct_resource(r->pool, lockdb,
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames locktoken, resource,
4111de96e9f75c58e77c2bdda23be83b8ebf81ccgregames &lock_resource)) != NULL) {
50e60f30bdc074fbc887f0b98f4d570457ac97c9brianp /* ### add a higher-level desc? */
50e60f30bdc074fbc887f0b98f4d570457ac97c9brianp /* ### should return err! */
5a9667916c79d8c699b069068e5570aa1c331c80gstein return err->status;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
2d2eda71267231c2526be701fe655db125852c1ffielding /* At this point, lock_resource/locktoken refers to a direct lock (key), ie
61fd0cab072a05b855cbef9c585702401ac5ae29rbb * the root of a depth > 0 lock, or locktoken is null.
61fd0cab072a05b855cbef9c585702401ac5ae29rbb */
2d2eda71267231c2526be701fe655db125852c1ffielding ctx.w.walk_type = DAV_WALKTYPE_NORMAL | DAV_WALKTYPE_LOCKNULL;
3d96ee83babeec32482c9082c9426340cee8c44dwrowe ctx.w.func = dav_unlock_walker;
2d2eda71267231c2526be701fe655db125852c1ffielding ctx.w.walk_ctx = &ctx;
344f3bc38dfccf6261d5bb8d689794cde113b3d6coar ctx.w.pool = r->pool;
344f3bc38dfccf6261d5bb8d689794cde113b3d6coar ctx.w.root = lock_resource;
344f3bc38dfccf6261d5bb8d689794cde113b3d6coar ctx.w.lockdb = lockdb;
5a9667916c79d8c699b069068e5570aa1c331c80gstein
344f3bc38dfccf6261d5bb8d689794cde113b3d6coar ctx.r = r;
344f3bc38dfccf6261d5bb8d689794cde113b3d6coar ctx.locktoken = locktoken;
344f3bc38dfccf6261d5bb8d689794cde113b3d6coar
5a9667916c79d8c699b069068e5570aa1c331c80gstein err = (*repos_hooks->walk)(&ctx.w, DAV_INFINITY, &multi_status);
344f3bc38dfccf6261d5bb8d689794cde113b3d6coar
d5df46b7972c0c4a5ca0ba5068e238f6053c2e6ftrawick /* ### fix this! */
fd0edaa8e3d4dd67d0604ccef2e96b071db96643fielding /* ### do something with multi_status */
fd0edaa8e3d4dd67d0604ccef2e96b071db96643fielding result = err == NULL ? OK : err->status;
fd0edaa8e3d4dd67d0604ccef2e96b071db96643fielding
fd0edaa8e3d4dd67d0604ccef2e96b071db96643fielding (*hooks->close_lockdb)(lockdb);
fd0edaa8e3d4dd67d0604ccef2e96b071db96643fielding
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return result;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb}
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/* dav_inherit_walker: Walker callback function to inherit locks */
61fd0cab072a05b855cbef9c585702401ac5ae29rbbstatic dav_error * dav_inherit_walker(dav_walk_resource *wres, int calltype)
61fd0cab072a05b855cbef9c585702401ac5ae29rbb{
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_walker_ctx *ctx = wres->walk_ctx;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
42ce672c516baf6e4eaed18ccc1647de2d456d8edougm if (ctx->skip_root
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein && (*wres->resource->hooks->is_same_resource)(wres->resource,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb ctx->w.root)) {
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return NULL;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb }
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb /* ### maybe add a higher-level desc */
61fd0cab072a05b855cbef9c585702401ac5ae29rbb return (*ctx->w.lockdb->hooks->append_locks)(ctx->w.lockdb,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb wres->resource, 1,
42ce672c516baf6e4eaed18ccc1647de2d456d8edougm ctx->lock);
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein}
61fd0cab072a05b855cbef9c585702401ac5ae29rbb
61fd0cab072a05b855cbef9c585702401ac5ae29rbb/*
61fd0cab072a05b855cbef9c585702401ac5ae29rbb** dav_inherit_locks: When a resource or collection is added to a collection,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb** locks on the collection should be inherited to the resource/collection.
61fd0cab072a05b855cbef9c585702401ac5ae29rbb** (MOVE, MKCOL, etc) Here we propagate any direct or indirect locks from
61fd0cab072a05b855cbef9c585702401ac5ae29rbb** parent of resource to resource and below.
61fd0cab072a05b855cbef9c585702401ac5ae29rbb*/
42ce672c516baf6e4eaed18ccc1647de2d456d8edougmstatic dav_error * dav_inherit_locks(request_rec *r, dav_lockdb *lockdb,
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein const dav_resource *resource,
61fd0cab072a05b855cbef9c585702401ac5ae29rbb int use_parent)
61fd0cab072a05b855cbef9c585702401ac5ae29rbb{
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_error *err;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb const dav_resource *which_resource;
dad234382d8424e1c5a30af2838e172aec9d6d1bdreid dav_lock *locks;
61fd0cab072a05b855cbef9c585702401ac5ae29rbb dav_lock *scan;
42ce672c516baf6e4eaed18ccc1647de2d456d8edougm dav_lock *prev;
fd0edaa8e3d4dd67d0604ccef2e96b071db96643fielding dav_walker_ctx ctx = { { 0 } };
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb const dav_hooks_repository *repos_hooks = resource->hooks;
a6b9ed64fdf548c61de9714e2cfb999ec59d149cgstein dav_response *multi_status;
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb if (use_parent) {
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb dav_resource *parent;
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb if ((err = (*repos_hooks->get_parent_resource)(resource,
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb &parent)) != NULL) {
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb /* ### add a higher-level desc? */
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb return err;
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb }
0de8f88b22d24dd57ed10b96fb594e69b6aa0072jwoolley if (parent == NULL) {
0de8f88b22d24dd57ed10b96fb594e69b6aa0072jwoolley /* ### map result to something nice; log an error */
8b7047e519340545e6807c9749576a40a76b6d3frbb return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
8b7047e519340545e6807c9749576a40a76b6d3frbb "Could not fetch parent resource. Unable to "
8b7047e519340545e6807c9749576a40a76b6d3frbb "inherit locks from the parent and apply "
6d00a43be9ab145c89e8cc22bad59e3aa746f761jwoolley "them to this resource.");
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb }
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb which_resource = parent;
9484ae61c7cc5fa8d8d9a836efdbdb1e88d3036dwrowe }
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb else {
2e75499d05677dd589f7ce6b5139ae15ba049419jerenkrantz which_resource = resource;
2e75499d05677dd589f7ce6b5139ae15ba049419jerenkrantz }
2e75499d05677dd589f7ce6b5139ae15ba049419jerenkrantz
2e75499d05677dd589f7ce6b5139ae15ba049419jerenkrantz if ((err = (*lockdb->hooks->get_locks)(lockdb, which_resource,
2e75499d05677dd589f7ce6b5139ae15ba049419jerenkrantz DAV_GETLOCKS_PARTIAL,
2e75499d05677dd589f7ce6b5139ae15ba049419jerenkrantz &locks)) != NULL) {
2e75499d05677dd589f7ce6b5139ae15ba049419jerenkrantz /* ### maybe add a higher-level desc */
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb return err;
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb }
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb if (locks == NULL) {
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb /* No locks to propagate, just return */
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb return NULL;
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb }
561e5f16a2f9fb397aac4c283aaa87a752520a4ddougm
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb /*
561e5f16a2f9fb397aac4c283aaa87a752520a4ddougm ** (1) Copy all indirect locks from our parent;
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb ** (2) Create indirect locks for the depth infinity, direct locks
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb ** in our parent.
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb **
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb ** The append_locks call in the walker callback will do the indirect
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb ** conversion, but we need to remove any direct locks that are NOT
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb ** depth "infinity".
2fc50921b88defeb7127985dfe4b4130175e069ejwoolley */
2fc50921b88defeb7127985dfe4b4130175e069ejwoolley for (scan = locks, prev = NULL;
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb scan != NULL;
2fc50921b88defeb7127985dfe4b4130175e069ejwoolley prev = scan, scan = scan->next) {
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb
2fc50921b88defeb7127985dfe4b4130175e069ejwoolley if (scan->rectype == DAV_LOCKREC_DIRECT
2fc50921b88defeb7127985dfe4b4130175e069ejwoolley && scan->depth != DAV_INFINITY) {
2fc50921b88defeb7127985dfe4b4130175e069ejwoolley
fcc25eda7b150e226d3c1cdaea66a943d3fdee4erbb if (prev == NULL)
c9a95767fbf0f5fb0976a06b97a256033925e433rbb locks = scan->next;
c9a95767fbf0f5fb0976a06b97a256033925e433rbb else
c9a95767fbf0f5fb0976a06b97a256033925e433rbb prev->next = scan->next;
c9a95767fbf0f5fb0976a06b97a256033925e433rbb }
c9a95767fbf0f5fb0976a06b97a256033925e433rbb }
c9a95767fbf0f5fb0976a06b97a256033925e433rbb
c9a95767fbf0f5fb0976a06b97a256033925e433rbb /* <locks> has all our new locks. Walk down and propagate them. */
c9a95767fbf0f5fb0976a06b97a256033925e433rbb
c9a95767fbf0f5fb0976a06b97a256033925e433rbb ctx.w.walk_type = DAV_WALKTYPE_NORMAL | DAV_WALKTYPE_LOCKNULL;
c9a95767fbf0f5fb0976a06b97a256033925e433rbb ctx.w.func = dav_inherit_walker;
3311183b8638d2ba2ff8496cad5e01c27d329a05nd ctx.w.walk_ctx = &ctx;
3311183b8638d2ba2ff8496cad5e01c27d329a05nd ctx.w.pool = r->pool;
c9a95767fbf0f5fb0976a06b97a256033925e433rbb ctx.w.root = resource;
2d2eda71267231c2526be701fe655db125852c1ffielding ctx.w.lockdb = lockdb;
2d2eda71267231c2526be701fe655db125852c1ffielding
2d2eda71267231c2526be701fe655db125852c1ffielding ctx.r = r;
2d2eda71267231c2526be701fe655db125852c1ffielding ctx.lock = locks;
2d2eda71267231c2526be701fe655db125852c1ffielding ctx.skip_root = !use_parent;
/* ### do something with multi_status */
return (*repos_hooks->walk)(&ctx.w, DAV_INFINITY, &multi_status);
}
/* ---------------------------------------------------------------
**
** Functions dealing with lock-null resources
**
*/
/*
** dav_get_resource_state: Returns the state of the resource
** r->filename: DAV_RESOURCE_NULL, DAV_RESOURCE_LOCK_NULL,
** or DAV_RESOURCE_EXIST.
**
** Returns DAV_RESOURCE_ERROR if an error occurs.
*/
int dav_get_resource_state(request_rec *r, const dav_resource *resource)
{
const dav_hooks_locks *hooks = DAV_GET_HOOKS_LOCKS(r);
if (resource->exists)
return DAV_RESOURCE_EXISTS;
if (hooks != NULL) {
dav_error *err;
dav_lockdb *lockdb;
int locks_present;
/*
** A locknull resource has the form:
**
** known-dir "/" locknull-file
**
** It would be nice to look into <resource> to verify this form,
** but it does not have enough information for us. Instead, we
** can look at the path_info. If the form does not match, then
** there is no way we could have a locknull resource -- it must
** be a plain, null resource.
**
** Apache sets r->filename to known-dir/unknown-file and r->path_info
** to "" for the "proper" case. If anything is in path_info, then
** it can't be a locknull resource.
**
** ### I bet this path_info hack doesn't work for repositories.
** ### Need input from repository implementors! What kind of
** ### restructure do we need? New provider APIs?
*/
if (r->path_info != NULL && *r->path_info != '\0') {
return DAV_RESOURCE_NULL;
}
if ((err = (*hooks->open_lockdb)(r, 1, 1, &lockdb)) == NULL) {
/* note that we might see some expired locks... *shrug* */
err = (*hooks->has_locks)(lockdb, resource, &locks_present);
(*hooks->close_lockdb)(lockdb);
}
if (err != NULL) {
/* ### don't log an error. return err. add higher-level desc. */
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"Failed to query lock-null status for %s",
r->filename);
return DAV_RESOURCE_ERROR;
}
if (locks_present)
return DAV_RESOURCE_LOCK_NULL;
}
return DAV_RESOURCE_NULL;
}
dav_error * dav_notify_created(request_rec *r,
dav_lockdb *lockdb,
const dav_resource *resource,
int resource_state,
int depth)
{
dav_error *err;
if (resource_state == DAV_RESOURCE_LOCK_NULL) {
/*
** The resource is no longer a locknull resource. This will remove
** the special marker.
**
** Note that a locknull resource has already inherited all of the
** locks from the parent. We do not need to call dav_inherit_locks.
**
** NOTE: some lock providers record locks for locknull resources using
** a different key than for regular resources. this will shift
** the lock information between the two key types.
*/
(void)(*lockdb->hooks->remove_locknull_state)(lockdb, resource);
/*
** There are resources under this one, which are new. We must
** propagate the locks down to the new resources.
*/
if (depth > 0 &&
(err = dav_inherit_locks(r, lockdb, resource, 0)) != NULL) {
/* ### add a higher level desc? */
return err;
}
}
else if (resource_state == DAV_RESOURCE_NULL) {
/* ### should pass depth to dav_inherit_locks so that it can
** ### optimize for the depth==0 case.
*/
/* this resource should inherit locks from its parent */
if ((err = dav_inherit_locks(r, lockdb, resource, 1)) != NULL) {
err = dav_push_error(r->pool, err->status, 0,
"The resource was created successfully, but "
"there was a problem inheriting locks from "
"the parent resource.",
err);
return err;
}
}
/* else the resource already exists and its locks are correct. */
return NULL;
}