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