props.c revision 252e2478cb56afb5ca8585b50bc2ffb780d2efb6
842ae4bd224140319ae7feec1872b93dfd491143fielding/* ====================================================================
842ae4bd224140319ae7feec1872b93dfd491143fielding * The Apache Software License, Version 1.1
842ae4bd224140319ae7feec1872b93dfd491143fielding *
842ae4bd224140319ae7feec1872b93dfd491143fielding * Copyright (c) 2000 The Apache Software Foundation. All rights
842ae4bd224140319ae7feec1872b93dfd491143fielding * reserved.
842ae4bd224140319ae7feec1872b93dfd491143fielding *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Redistribution and use in source and binary forms, with or without
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * modification, are permitted provided that the following conditions
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * are met:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * 1. Redistributions of source code must retain the above copyright
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * notice, this list of conditions and the following disclaimer.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * 2. Redistributions in binary form must reproduce the above copyright
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * notice, this list of conditions and the following disclaimer in
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * the documentation and/or other materials provided with the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * distribution.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
e8f95a682820a599fe41b22977010636be5c2717jim * 3. The end-user documentation included with the redistribution,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * if any, must include the following acknowledgment:
e8f95a682820a599fe41b22977010636be5c2717jim * "This product includes software developed by the
1747d30b98aa1bdbc43994c02cd46ab4cb9319e4fielding * Apache Software Foundation (http://www.apache.org/)."
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Alternately, this acknowledgment may appear in the software itself,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * if and wherever such third-party acknowledgments normally appear.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * 4. The names "Apache" and "Apache Software Foundation" must
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * not be used to endorse or promote products derived from this
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * software without prior written permission. For written
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * permission, please contact apache@apache.org.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
11f2c481e1d57bedb3f758565307501e9a2730ddtrawick * 5. Products derived from this software may not be called "Apache",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * nor may "Apache" appear in their name, without prior written
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * permission of the Apache Software Foundation.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *
5c0419d51818eb02045cf923a9fe456127a44c60wrowe * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
5c0419d51818eb02045cf923a9fe456127a44c60wrowe * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
d266c3777146d36a4c23c17aad6f153aebea1bf4jorton * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
d266c3777146d36a4c23c17aad6f153aebea1bf4jorton * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes * SUCH DAMAGE.
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes * ====================================================================
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes *
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes * This software consists of voluntary contributions made by many
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes * individuals on behalf of the Apache Software Foundation. For more
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes * information on the Apache Software Foundation, please see
cd3bbd6d2df78d6c75e5d159a81ef8bdd5f70df9trawick * <http://www.apache.org/>.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
0f60998368b493f90120180a93fc2e1e74490872covener
0f60998368b493f90120180a93fc2e1e74490872covener/*
0f60998368b493f90120180a93fc2e1e74490872covener** DAV extension module for Apache 2.0.*
0f60998368b493f90120180a93fc2e1e74490872covener** - Property database handling (repository-independent)
0f60998368b493f90120180a93fc2e1e74490872covener**
0f60998368b493f90120180a93fc2e1e74490872covener** NOTES:
0f60998368b493f90120180a93fc2e1e74490872covener**
0f60998368b493f90120180a93fc2e1e74490872covener** PROPERTY DATABASE
87587593f1a53030e840acc0dec6cc881022ea40covener**
87587593f1a53030e840acc0dec6cc881022ea40covener** This version assumes that there is a per-resource database provider
87587593f1a53030e840acc0dec6cc881022ea40covener** to record properties. The database provider decides how and where to
87587593f1a53030e840acc0dec6cc881022ea40covener** store these databases.
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener**
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener** The DBM keys for the properties have the following form:
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** namespace ":" propname
43997561b2302d13dee973998e77743a3ddd2374trawick**
fa123db15501821e36e513afa78e839775ad2800covener** For example: 5:author
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes**
0568280364eb026393be492ebc732795c4934643jorton** The namespace provides an integer index into the namespace table
0568280364eb026393be492ebc732795c4934643jorton** (see below). propname is simply the property name, without a namespace
0568280364eb026393be492ebc732795c4934643jorton** prefix.
0568280364eb026393be492ebc732795c4934643jorton**
0568280364eb026393be492ebc732795c4934643jorton** A special case exists for properties that had a prefix starting with
0568280364eb026393be492ebc732795c4934643jorton** "xml". The XML Specification reserves these for future use. mod_dav
0568280364eb026393be492ebc732795c4934643jorton** stores and retrieves them unchanged. The keys for these properties
0568280364eb026393be492ebc732795c4934643jorton** have the form:
0568280364eb026393be492ebc732795c4934643jorton**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** ":" propname
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** The propname will contain the prefix and the property name. For
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** example, a key might be ":xmlfoo:name"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** The ":name" style will also be used for properties that do not
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** exist within a namespace.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** The DBM values consist of two null-terminated strings, appended
796e4a7141265d8ed7036e4628161c6eafb2a789jorton** together (the null-terms are retained and stored in the database).
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** The first string is the xml:lang value for the property. An empty
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** string signifies that a lang value was not in context for the value.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** The second string is the property value itself.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** NAMESPACE TABLE
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** The namespace table is an array that lists each of the namespaces
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** that are in use by the properties in the given propdb. Each entry
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** in the array is a simple URI.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** For example: http://www.foo.bar/standards/props/
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** The prefix used for the property is stripped and the URI for it
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** is entered into the namespace table. Also, any namespaces used
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe** within the property value will be entered into the table (and
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** stripped from the child elements).
95b6fe1346805e1731e6e97c15d569c73be22cf7minfrin**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** The namespaces are stored in the DBM database under the "METADATA" key.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes**
95b6fe1346805e1731e6e97c15d569c73be22cf7minfrin**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** STRIPPING NAMESPACES
95b6fe1346805e1731e6e97c15d569c73be22cf7minfrin**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** Within the property values, the namespace declarations (xmlns...)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** are stripped. Each element and attribute will have its prefix removed
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** and a new prefix inserted.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** This must be done so that we can return multiple properties in a
95b6fe1346805e1731e6e97c15d569c73be22cf7minfrin** PROPFIND which may have (originally) used conflicting prefixes. For
95b6fe1346805e1731e6e97c15d569c73be22cf7minfrin** that case, we must bind all property value elements to new namespace
95b6fe1346805e1731e6e97c15d569c73be22cf7minfrin** values.
a1790fb35c4b352dab721370985c623a9f8f5062rpluem**
713a2b68bac4aeb1e9c48785006c0732451039depquerna** This implies that clients must NOT be sensitive to the namespace
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** prefix used for their properties. It WILL change when the properties
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** are returned (we return them as "ns<index>", e.g. "ns5"). Also, the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** property value can contain ONLY XML elements and CDATA. PI and comment
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** elements will be stripped. CDATA whitespace will be preserved, but
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** whitespace within element tags will be altered. Attribute ordering
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe** may be altered. Element and CDATA ordering will be preserved.
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** ATTRIBUTES ON PROPERTY NAME ELEMENTS
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** When getting/setting properties, the XML used looks like:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** <prop>
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** <propname1>value</propname1>
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** <propname2>value</propname1>
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener** </prop>
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** This implementation (mod_dav) DOES NOT save any attributes that are
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes** associated with the <propname1> element. The property value is deemed
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** to be only the contents ("value" in the above example).
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes**
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe** We do store the xml:lang value (if any) that applies to the context
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** of the <propname1> element. Whether the xml:lang attribute is on
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** <propname1> itself, or from a higher level element, we will store it
fa123db15501821e36e513afa78e839775ad2800covener** with the property value.
fa123db15501821e36e513afa78e839775ad2800covener**
fa123db15501821e36e513afa78e839775ad2800covener**
fa123db15501821e36e513afa78e839775ad2800covener** VERSIONING
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener**
fa123db15501821e36e513afa78e839775ad2800covener** The DBM db contains a key named "METADATA" that holds database-level
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener** information, such as the namespace table. The record also contains the
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener** db's version number as the very first 16-bit value. This first number
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener** is actually stored as two single bytes: the first byte is a "major"
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener** version number. The second byte is a "minor" number.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes**
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener** If the major number is not what mod_dav expects, then the db is closed
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** immediately and an error is returned. A minor number change is
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener** acceptable -- it is presumed that old/new dav_props.c can deal with
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** the database format. For example, a newer dav_props might update the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** minor value and append information to the end of the metadata record
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** (which would be ignored by previous versions).
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** ISSUES:
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** At the moment, for the dav_get_allprops() and dav_get_props() functions,
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe** we must return a set of xmlns: declarations for ALL known namespaces
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** in the file. There isn't a way to filter this because we don't know
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** which are going to be used or not. Examining property names is not
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** sufficient because the property values could use entirely different
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** namespaces.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** ==> we must devise a scheme where we can "garbage collect" the namespace
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** entries from the property database.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes*/
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#include "mod_dav.h"
fa123db15501821e36e513afa78e839775ad2800covener
cceddc0b6c0fdaed0c73abda39975bb1d388243acovener#include "http_log.h"
cceddc0b6c0fdaed0c73abda39975bb1d388243acovener#include "http_request.h"
fa123db15501821e36e513afa78e839775ad2800covener
cceddc0b6c0fdaed0c73abda39975bb1d388243acovener/*
f2be127030aa4190033084f0a6add531c9bc41desf** There is some rough support for writeable DAV:getcontenttype and
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener** DAV:getcontentlanguage properties. If this #define is (1), then
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener** this support is disabled.
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener**
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener** We are disabling it because of a lack of support in GET and PUT
60215f303c7e1ce8b6d272acb5bfa5b3d99dfd34covener** operations. For GET, it would be "expensive" to look for a propdb,
60215f303c7e1ce8b6d272acb5bfa5b3d99dfd34covener** open it, and attempt to extract the Content-Type and Content-Language
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener** values for the response.
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener** (Handling the PUT would not be difficult, though)
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener*/
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener#define DAV_DISABLE_WRITEABLE_PROPS 1
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener#define DAV_GDBM_NS_KEY "METADATA"
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener#define DAV_GDBM_NS_KEY_LEN 8
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener#define DAV_EMPTY_VALUE "\0" /* TWO null terms */
6683642c1e0032eeeed5f99e8c14880692ef84c5sf
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener/* the namespace URI was not found; no ID is available */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener#define AP_XML_NS_ERROR_NOT_FOUND (AP_XML_NS_ERROR_BASE)
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
6683642c1e0032eeeed5f99e8c14880692ef84c5sftypedef struct {
6683642c1e0032eeeed5f99e8c14880692ef84c5sf unsigned char major;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener#define DAV_DBVSN_MAJOR 4
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener /*
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener ** V4 -- 0.9.9 ..
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener ** Prior versions could have keys or values with invalid
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener ** namespace prefixes as a result of the xmlns="" form not
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener ** resetting the default namespace to be "no namespace". The
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener ** namespace would be set to "" which is invalid; it should
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener ** be set to "no namespace".
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener **
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener ** V3 -- 0.9.8
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener ** Prior versions could have values with invalid namespace
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener ** prefixes due to an incorrect mapping of input to propdb
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener ** namespace indices. Version bumped to obsolete the old
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener ** values.
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener **
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener ** V2 -- 0.9.7
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener ** This introduced the xml:lang value into the property value's
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener ** record in the propdb.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes **
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** V1 -- .. 0.9.6
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener ** Initial version.
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener unsigned char minor;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener#define DAV_DBVSN_MINOR 0
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener short ns_count;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener} dav_propdb_metadata;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovenerstruct dav_propdb {
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener int version; /* *minor* version of this db */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener ap_pool_t *p; /* the pool we should use */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener request_rec *r; /* the request record */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_resource *resource; /* the target resource */
60215f303c7e1ce8b6d272acb5bfa5b3d99dfd34covener
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int deferred; /* open of db has been deferred */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes dav_db *db; /* underlying database containing props */
0e05808dc59a321566303084c84b9826a4353cefrederpj
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_buffer ns_table; /* table of namespace URIs */
b08925593f214f621161742925dcf074a8047e0acovener short ns_count; /* number of entries in table */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int ns_table_dirty; /* ns_table was modified */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
465bb68501690d7a47bfd2a6129580047d76d8f1rederpj ap_array_header_t *ns_xlate; /* translation of an elem->ns to URI */
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf int *ns_map; /* map elem->ns to propdb ns values */
465bb68501690d7a47bfd2a6129580047d76d8f1rederpj int incomplete_map; /* some mappings do not exist */
e8f95a682820a599fe41b22977010636be5c2717jim
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes dav_lockdb *lockdb; /* the lock database */
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes
54d22ed1c429b903b029bbd62621f11a9e286137minfrin dav_buffer wb_key; /* work buffer for dav_gdbm_key */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes dav_buffer wb_lock; /* work buffer for lockdiscovery property */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* if we ever run a GET subreq, it will be stored here */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes request_rec *subreq;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* hooks we should use for processing (based on the target resource) */
ebe5305f8b22507374358f32b74d12fb50c05a25covener const dav_hooks_db *db_hooks;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes const dav_hooks_vsn *vsn_hooks;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes const dav_dyn_hooks *liveprop; /* head of list */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes};
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
513b324e774c559b579896df131fd7c8471ed529rederpj/* ### move these into a "core" liveprop provider? */
513b324e774c559b579896df131fd7c8471ed529rederpjstatic const char * const dav_core_props[] =
513b324e774c559b579896df131fd7c8471ed529rederpj{
513b324e774c559b579896df131fd7c8471ed529rederpj "getcontenttype",
513b324e774c559b579896df131fd7c8471ed529rederpj "getcontentlanguage",
513b324e774c559b579896df131fd7c8471ed529rederpj "lockdiscovery",
513b324e774c559b579896df131fd7c8471ed529rederpj "resourcetype",
513b324e774c559b579896df131fd7c8471ed529rederpj "supportedlock",
513b324e774c559b579896df131fd7c8471ed529rederpj
513b324e774c559b579896df131fd7c8471ed529rederpj NULL /* sentinel */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes};
02fd88c85a9850109753b87612955ad372de1575sfenum {
02fd88c85a9850109753b87612955ad372de1575sf DAV_PROPID_CORE_getcontenttype = DAV_PROPID_CORE,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes DAV_PROPID_CORE_getcontentlanguage,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes DAV_PROPID_CORE_lockdiscovery,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes DAV_PROPID_CORE_resourcetype,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes DAV_PROPID_CORE_supportedlock,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes DAV_PROPID_CORE_UNKNOWN
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes};
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes#define DAV_IS_CORE_PROP(propid) ((propid) >= DAV_PROPID_CORE && \
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes (propid) <= DAV_PROPID_CORE_UNKNOWN)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/*
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes** This structure is used to track information needed for a rollback.
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes** If a SET was performed and no prior value existed, then value.dptr
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** will be NULL.
707f6d077f73cc948deead8df5b40ea42c1eaa78covener*/
707f6d077f73cc948deead8df5b40ea42c1eaa78covenertypedef struct dav_rollback_item {
fa123db15501821e36e513afa78e839775ad2800covener dav_datum key; /* key for the item being saved */
707f6d077f73cc948deead8df5b40ea42c1eaa78covener dav_datum value; /* value before set/replace/delete */
707f6d077f73cc948deead8df5b40ea42c1eaa78covener
707f6d077f73cc948deead8df5b40ea42c1eaa78covener /* or use the following (choice selected by dav_prop_ctx.is_liveprop) */
707f6d077f73cc948deead8df5b40ea42c1eaa78covener struct dav_liveprop_rollback *liveprop; /* liveprop rollback ctx */
707f6d077f73cc948deead8df5b40ea42c1eaa78covener
707f6d077f73cc948deead8df5b40ea42c1eaa78covener} dav_rollback_item;
707f6d077f73cc948deead8df5b40ea42c1eaa78covener
9ad7b260be233be7d7b5576979825cac72e15498rederpj
9ad7b260be233be7d7b5576979825cac72e15498rederpj#if 0
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes/* ### unused */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesstatic const char *dav_get_ns_table_uri(dav_propdb *propdb, int ns)
54d22ed1c429b903b029bbd62621f11a9e286137minfrin{
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes const char *p = propdb->ns_table.buf + sizeof(dav_propdb_metadata);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
ebe5305f8b22507374358f32b74d12fb50c05a25covener while (ns--)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes p += strlen(p) + 1;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return p;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes}
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes#endif
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesstatic void dav_find_liveprop(dav_propdb *propdb, ap_xml_elem *elem)
54d22ed1c429b903b029bbd62621f11a9e286137minfrin{
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes int propid;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes const char *ns_uri;
ebe5305f8b22507374358f32b74d12fb50c05a25covener const dav_dyn_hooks *ddh;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes dav_elem_private *priv = elem->private;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (elem->ns == AP_XML_NS_DAV_ID) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes const char * const *p = dav_core_props;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes for (propid = DAV_PROPID_CORE; *p != NULL; ++p, ++propid)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (strcmp(elem->name, *p) == 0) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes priv->propid = propid;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return;
b08925593f214f621161742925dcf074a8047e0acovener }
b08925593f214f621161742925dcf074a8047e0acovener
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* didn't find it. fall thru. a provider can define DAV: props */
707f6d077f73cc948deead8df5b40ea42c1eaa78covener }
707f6d077f73cc948deead8df5b40ea42c1eaa78covener else if (elem->ns == AP_XML_NS_NONE) {
9ad7b260be233be7d7b5576979825cac72e15498rederpj /* policy: liveprop providers cannot define no-namespace properties */
707f6d077f73cc948deead8df5b40ea42c1eaa78covener priv->propid = DAV_PROPID_CORE_UNKNOWN;
707f6d077f73cc948deead8df5b40ea42c1eaa78covener return;
9ad7b260be233be7d7b5576979825cac72e15498rederpj }
707f6d077f73cc948deead8df5b40ea42c1eaa78covener
707f6d077f73cc948deead8df5b40ea42c1eaa78covener ns_uri = AP_XML_GET_URI_ITEM(propdb->ns_xlate, elem->ns);
707f6d077f73cc948deead8df5b40ea42c1eaa78covener
707f6d077f73cc948deead8df5b40ea42c1eaa78covener for (ddh = propdb->liveprop; ddh != NULL; ddh = ddh->next) {
9ad7b260be233be7d7b5576979825cac72e15498rederpj propid = (*DAV_AS_HOOKS_LIVEPROP(ddh)->find_prop)(ns_uri, elem->name);
707f6d077f73cc948deead8df5b40ea42c1eaa78covener if (propid != 0) {
707f6d077f73cc948deead8df5b40ea42c1eaa78covener priv->propid = propid;
707f6d077f73cc948deead8df5b40ea42c1eaa78covener priv->provider = DAV_AS_HOOKS_LIVEPROP(ddh);
707f6d077f73cc948deead8df5b40ea42c1eaa78covener priv->ns_map = ddh->ctx.ns_map;
707f6d077f73cc948deead8df5b40ea42c1eaa78covener return;
707f6d077f73cc948deead8df5b40ea42c1eaa78covener }
707f6d077f73cc948deead8df5b40ea42c1eaa78covener }
707f6d077f73cc948deead8df5b40ea42c1eaa78covener
707f6d077f73cc948deead8df5b40ea42c1eaa78covener priv->propid = DAV_PROPID_CORE_UNKNOWN;
707f6d077f73cc948deead8df5b40ea42c1eaa78covener}
707f6d077f73cc948deead8df5b40ea42c1eaa78covener
707f6d077f73cc948deead8df5b40ea42c1eaa78covener/* is the live property read/write? */
707f6d077f73cc948deead8df5b40ea42c1eaa78covenerstatic int dav_rw_liveprop(dav_propdb *propdb, int propid)
707f6d077f73cc948deead8df5b40ea42c1eaa78covener{
707f6d077f73cc948deead8df5b40ea42c1eaa78covener dav_prop_rw rw;
707f6d077f73cc948deead8df5b40ea42c1eaa78covener const dav_dyn_hooks *ddh;
707f6d077f73cc948deead8df5b40ea42c1eaa78covener
707f6d077f73cc948deead8df5b40ea42c1eaa78covener /* these are defined as read-only */
707f6d077f73cc948deead8df5b40ea42c1eaa78covener if (propid == DAV_PROPID_CORE_lockdiscovery
707f6d077f73cc948deead8df5b40ea42c1eaa78covener || propid == DAV_PROPID_CORE_resourcetype
707f6d077f73cc948deead8df5b40ea42c1eaa78covener#if DAV_DISABLE_WRITEABLE_PROPS
707f6d077f73cc948deead8df5b40ea42c1eaa78covener || propid == DAV_PROPID_CORE_getcontenttype
707f6d077f73cc948deead8df5b40ea42c1eaa78covener || propid == DAV_PROPID_CORE_getcontentlanguage
707f6d077f73cc948deead8df5b40ea42c1eaa78covener#endif
707f6d077f73cc948deead8df5b40ea42c1eaa78covener || propid == DAV_PROPID_CORE_supportedlock) {
707f6d077f73cc948deead8df5b40ea42c1eaa78covener
707f6d077f73cc948deead8df5b40ea42c1eaa78covener return 0;
707f6d077f73cc948deead8df5b40ea42c1eaa78covener }
707f6d077f73cc948deead8df5b40ea42c1eaa78covener
9ad7b260be233be7d7b5576979825cac72e15498rederpj /* these are defined as read/write */
9ad7b260be233be7d7b5576979825cac72e15498rederpj if (propid == DAV_PROPID_CORE_getcontenttype
9ad7b260be233be7d7b5576979825cac72e15498rederpj || propid == DAV_PROPID_CORE_getcontentlanguage
7add8f7fb048534390571801b7794f71cd9e127abnicholes || propid == DAV_PROPID_CORE_UNKNOWN) {
7add8f7fb048534390571801b7794f71cd9e127abnicholes
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem return 1;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
7add8f7fb048534390571801b7794f71cd9e127abnicholes
7add8f7fb048534390571801b7794f71cd9e127abnicholes /*
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes ** Check the liveprop providers
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes for (ddh = propdb->liveprop; ddh != NULL; ddh = ddh->next) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes rw = (*DAV_AS_HOOKS_LIVEPROP(ddh)->is_writeable)(propdb->resource,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes propid);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (rw == DAV_PROP_RW_YES)
7add8f7fb048534390571801b7794f71cd9e127abnicholes return 1;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (rw == DAV_PROP_RW_NO)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return 0;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /*
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes ** No provider recognized the property, so it must be dead (and writable)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return 1;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes}
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
7add8f7fb048534390571801b7794f71cd9e127abnicholes/* do a sub-request to fetch properties for the target resource's URI. */
7add8f7fb048534390571801b7794f71cd9e127abnicholesstatic void dav_do_prop_subreq(dav_propdb *propdb)
141e1368614dc7564e1627671361b01b4869b491bnicholes{
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes /* perform a "GET" on the resource's URI (note that the resource
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes may not correspond to the current request!). */
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf propdb->subreq = ap_sub_req_lookup_uri(propdb->resource->uri, propdb->r);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes}
e8f95a682820a599fe41b22977010636be5c2717jim
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholesstatic dav_error * dav_insert_coreprop(dav_propdb *propdb,
ebe5305f8b22507374358f32b74d12fb50c05a25covener int propid, const char *name,
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf int getvals,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes ap_text_header *phdr,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes int *inserted)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes{
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes const char *value = NULL;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes *inserted = 0;
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf /* fast-path the common case */
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf if (propid == DAV_PROPID_CORE_UNKNOWN)
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf return NULL;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf switch (propid) {
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf case DAV_PROPID_CORE_resourcetype:
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf switch (propdb->resource->type) {
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf case DAV_RESOURCE_TYPE_REGULAR:
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf if (propdb->resource->collection) {
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf value = "<D:collection/>";
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf }
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf else {
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf /* ### should we denote lock-null resources? */
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf value = ""; /* becomes: <D:resourcetype/> */
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf }
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf break;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf case DAV_RESOURCE_TYPE_HISTORY:
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes value = "<D:history/>";
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes break;
e8f95a682820a599fe41b22977010636be5c2717jim case DAV_RESOURCE_TYPE_WORKSPACE:
7dbf29be626018bc389ef94c1846aeac4b72633bsf value = "<D:workspace/>";
7dbf29be626018bc389ef94c1846aeac4b72633bsf break;
7dbf29be626018bc389ef94c1846aeac4b72633bsf case DAV_RESOURCE_TYPE_ACTIVITY:
7dbf29be626018bc389ef94c1846aeac4b72633bsf value = "<D:activity/>";
7dbf29be626018bc389ef94c1846aeac4b72633bsf break;
7dbf29be626018bc389ef94c1846aeac4b72633bsf case DAV_RESOURCE_TYPE_CONFIGURATION:
7dbf29be626018bc389ef94c1846aeac4b72633bsf value = "<D:configuration/>";
7dbf29be626018bc389ef94c1846aeac4b72633bsf break;
7dbf29be626018bc389ef94c1846aeac4b72633bsf case DAV_RESOURCE_TYPE_REVISION:
7dbf29be626018bc389ef94c1846aeac4b72633bsf value = "<D:revision/>";
7dbf29be626018bc389ef94c1846aeac4b72633bsf break;
7dbf29be626018bc389ef94c1846aeac4b72633bsf
7dbf29be626018bc389ef94c1846aeac4b72633bsf default:
7dbf29be626018bc389ef94c1846aeac4b72633bsf /* ### bad juju */
7dbf29be626018bc389ef94c1846aeac4b72633bsf break;
7dbf29be626018bc389ef94c1846aeac4b72633bsf }
7dbf29be626018bc389ef94c1846aeac4b72633bsf break;
7dbf29be626018bc389ef94c1846aeac4b72633bsf
7dbf29be626018bc389ef94c1846aeac4b72633bsf case DAV_PROPID_CORE_lockdiscovery:
7dbf29be626018bc389ef94c1846aeac4b72633bsf if (propdb->lockdb != NULL) {
7dbf29be626018bc389ef94c1846aeac4b72633bsf dav_error *err;
7dbf29be626018bc389ef94c1846aeac4b72633bsf dav_lock *locks;
7dbf29be626018bc389ef94c1846aeac4b72633bsf
7dbf29be626018bc389ef94c1846aeac4b72633bsf if ((err = dav_lock_query(propdb->lockdb, propdb->resource,
7dbf29be626018bc389ef94c1846aeac4b72633bsf &locks)) != NULL) {
7dbf29be626018bc389ef94c1846aeac4b72633bsf return dav_push_error(propdb->p, err->status, 0,
7dbf29be626018bc389ef94c1846aeac4b72633bsf "DAV:lockdiscovery could not be "
7dbf29be626018bc389ef94c1846aeac4b72633bsf "determined due to a problem fetching "
7dbf29be626018bc389ef94c1846aeac4b72633bsf "the locks for this resource.",
7dbf29be626018bc389ef94c1846aeac4b72633bsf err);
7dbf29be626018bc389ef94c1846aeac4b72633bsf }
7dbf29be626018bc389ef94c1846aeac4b72633bsf
7dbf29be626018bc389ef94c1846aeac4b72633bsf /* fast-path the no-locks case */
7dbf29be626018bc389ef94c1846aeac4b72633bsf if (locks == NULL) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes value = "";
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes else {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /*
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes ** This may modify the buffer. value may point to
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes ** wb_lock.pbuf or a string constant.
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes value = dav_lock_get_activelock(propdb->r, locks,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes &propdb->wb_lock);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* make a copy to isolate it from changes to wb_lock */
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf value = ap_pstrdup(propdb->p, propdb->wb_lock.buf);
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes break;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes case DAV_PROPID_CORE_supportedlock:
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (propdb->lockdb != NULL) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes value = (*propdb->lockdb->hooks->get_supportedlock)();
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes break;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes case DAV_PROPID_CORE_getcontenttype:
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (propdb->subreq == NULL) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes dav_do_prop_subreq(propdb);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (propdb->subreq->content_type != NULL) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes value = propdb->subreq->content_type;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes }
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes break;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf case DAV_PROPID_CORE_getcontentlanguage:
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes const char *lang;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (propdb->subreq == NULL) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes dav_do_prop_subreq(propdb);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if ((lang = ap_table_get(propdb->subreq->headers_out,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "Content-Language")) != NULL) {
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf value = lang;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf }
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf break;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf case DAV_PROPID_CORE_UNKNOWN:
7dbf29be626018bc389ef94c1846aeac4b72633bsf default:
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf /* fall through to interpret as a dead property */
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf break;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
e8f95a682820a599fe41b22977010636be5c2717jim
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* if something was supplied, then insert it */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (value != NULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *s;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (getvals && *value != '\0') {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* use D: prefix to refer to the DAV: namespace URI */
7dbf29be626018bc389ef94c1846aeac4b72633bsf s = ap_psprintf(propdb->p, "<D:%s>%s</D:%s>" DEBUG_CR,
7dbf29be626018bc389ef94c1846aeac4b72633bsf name, value, name);
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf }
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf else {
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf /* use D: prefix to refer to the DAV: namespace URI */
9c63a05713cb83a44a1590b4af33edeebf39f118sf s = ap_psprintf(propdb->p, "<D:%s/>" DEBUG_CR, name);
9c63a05713cb83a44a1590b4af33edeebf39f118sf }
9c63a05713cb83a44a1590b4af33edeebf39f118sf ap_text_append(propdb->p, phdr, s);
9c63a05713cb83a44a1590b4af33edeebf39f118sf
9c63a05713cb83a44a1590b4af33edeebf39f118sf *inserted = 1;
9c63a05713cb83a44a1590b4af33edeebf39f118sf }
9c63a05713cb83a44a1590b4af33edeebf39f118sf
9c63a05713cb83a44a1590b4af33edeebf39f118sf return NULL;
9c63a05713cb83a44a1590b4af33edeebf39f118sf}
9c63a05713cb83a44a1590b4af33edeebf39f118sf
9c63a05713cb83a44a1590b4af33edeebf39f118sfstatic dav_error * dav_insert_liveprop(dav_propdb *propdb,
9c63a05713cb83a44a1590b4af33edeebf39f118sf const ap_xml_elem *elem,
9c63a05713cb83a44a1590b4af33edeebf39f118sf int getvals,
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf ap_text_header *phdr,
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf int *inserted)
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf{
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf dav_prop_insert pi;
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf dav_elem_private *priv = elem->private;
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf *inserted = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (DAV_IS_CORE_PROP(priv->propid))
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return dav_insert_coreprop(propdb, priv->propid, elem->name,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes getvals, phdr, inserted);
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ask the provider (that defined this prop) to insert the prop */
9c63a05713cb83a44a1590b4af33edeebf39f118sf pi = (*priv->provider->insert_prop)(propdb->resource, priv->propid,
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf getvals, priv->ns_map, phdr);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#if DAV_DEBUG
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (pi == DAV_PROP_INSERT_NOTME) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### the provider should have returned NOTDEF, at least */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return dav_new_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR, 0,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "DESIGN ERROR: a liveprop provider defined "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "a property, but did not respond to the "
54d22ed1c429b903b029bbd62621f11a9e286137minfrin "insert_prop hook for it.");
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
54d22ed1c429b903b029bbd62621f11a9e286137minfrin#endif
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin if (pi != DAV_PROP_INSERT_NOTDEF)
54d22ed1c429b903b029bbd62621f11a9e286137minfrin *inserted = 1;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin return NULL;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin}
e8f95a682820a599fe41b22977010636be5c2717jim
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowestatic void dav_append_prop(dav_propdb *propdb,
8a03cd420b800a2428f49f4617293de9b2387b20jorton const char *name, const char *value,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin ap_text_header *phdr)
54d22ed1c429b903b029bbd62621f11a9e286137minfrin{
54d22ed1c429b903b029bbd62621f11a9e286137minfrin const char *s;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin const char *lang = value;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* skip past the xml:lang value */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin value += strlen(lang) + 1;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin if (*value == '\0') {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* the property is an empty value */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin if (*name == ':') {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* "no namespace" case */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin s = ap_psprintf(propdb->p, "<%s/>" DEBUG_CR, name+1);
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
54d22ed1c429b903b029bbd62621f11a9e286137minfrin else {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin s = ap_psprintf(propdb->p, "<ns%s/>" DEBUG_CR, name);
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
6999a76d8eb5ef6b4b295e51df0b2fb6064bd373covener }
6999a76d8eb5ef6b4b295e51df0b2fb6064bd373covener else if (*lang != '\0') {
6999a76d8eb5ef6b4b295e51df0b2fb6064bd373covener if (*name == ':') {
6999a76d8eb5ef6b4b295e51df0b2fb6064bd373covener /* "no namespace" case */
6999a76d8eb5ef6b4b295e51df0b2fb6064bd373covener s = ap_psprintf(propdb->p, "<%s xml:lang=\"%s\">%s</%s>" DEBUG_CR,
6999a76d8eb5ef6b4b295e51df0b2fb6064bd373covener name+1, lang, value, name+1);
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
54d22ed1c429b903b029bbd62621f11a9e286137minfrin else {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin s = ap_psprintf(propdb->p, "<ns%s xml:lang=\"%s\">%s</ns%s>" DEBUG_CR,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin name, lang, value, name);
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
54d22ed1c429b903b029bbd62621f11a9e286137minfrin }
54d22ed1c429b903b029bbd62621f11a9e286137minfrin else if (*name == ':') {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* "no namespace" case */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes s = ap_psprintf(propdb->p, "<%s>%s</%s>" DEBUG_CR, name+1, value, name+1);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes s = ap_psprintf(propdb->p, "<ns%s>%s</ns%s>" DEBUG_CR, name, value, name);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_text_append(propdb->p, phdr, s);
e8f95a682820a599fe41b22977010636be5c2717jim}
e8f95a682820a599fe41b22977010636be5c2717jim
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe/*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** Prepare the ns_map variable in the propdb structure. This entails copying
e8f95a682820a599fe41b22977010636be5c2717jim** all URIs from the "input" namespace list (in propdb->ns_xlate) into the
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe** propdb's list of namespaces. As each URI is copied (or pre-existing
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe** URI looked up), the index mapping is stored into the ns_map variable.
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe**
f0f6f1b90ab582896f8a7d56d85bd62a55e57d90covener** Note: we must copy all declared namespaces because we cannot easily
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe** determine which input namespaces were actually used within the property
54d22ed1c429b903b029bbd62621f11a9e286137minfrin** values that are being stored within the propdb. Theoretically, we can
560fd0658902ab57754616c172d8953e69fc4722bnicholes** determine this at the point where we serialize the property values
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener** back into strings. This would require a bit more work, and will be
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** left to future optimizations.
e8f95a682820a599fe41b22977010636be5c2717jim**
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** ### we should always initialize the propdb namespace array with "DAV:"
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** ### since we know it will be entered anyhow (by virtue of it always
9ad7b260be233be7d7b5576979825cac72e15498rederpj** ### occurring in the ns_xlate array). That will allow us to use
9ad7b260be233be7d7b5576979825cac72e15498rederpj** ### AP_XML_NS_DAV_ID for propdb ns values, too.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes*/
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void dav_prep_ns_map(dav_propdb *propdb, int add_ns)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int i;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char **puri;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const int orig_count = propdb->ns_count;
560fd0658902ab57754616c172d8953e69fc4722bnicholes int *pmap;
560fd0658902ab57754616c172d8953e69fc4722bnicholes int updating = 0; /* are we updating an existing ns_map? */
560fd0658902ab57754616c172d8953e69fc4722bnicholes
560fd0658902ab57754616c172d8953e69fc4722bnicholes if (propdb->ns_map) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (add_ns && propdb->incomplete_map) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* we must revisit the map and insert new entries */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes updating = 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes propdb->incomplete_map = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* nothing to do: we have a proper ns_map */
e8f95a682820a599fe41b22977010636be5c2717jim return;
e8f95a682820a599fe41b22977010636be5c2717jim }
e8f95a682820a599fe41b22977010636be5c2717jim }
e8f95a682820a599fe41b22977010636be5c2717jim else {
e8f95a682820a599fe41b22977010636be5c2717jim propdb->ns_map = ap_palloc(propdb->p, propdb->ns_xlate->nelts * sizeof(*propdb->ns_map));
e8f95a682820a599fe41b22977010636be5c2717jim }
ae1981fc94adf2b231e2d0e15d2f895b2138c969covener
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe pmap = propdb->ns_map;
7a55c294da84865fe13262ed66ffd0c5841a9da5covener
7a55c294da84865fe13262ed66ffd0c5841a9da5covener /* ### stupid O(n * orig_count) algorithm */
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener for (i = propdb->ns_xlate->nelts, puri = (const char **)propdb->ns_xlate->elts;
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener i-- > 0;
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener ++puri, ++pmap) {
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener
54091ac5c596337658fc568231ca1a900abdc5fecovener const char *uri = *puri;
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener const size_t uri_len = strlen(uri);
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener
54091ac5c596337658fc568231ca1a900abdc5fecovener if (updating) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* updating an existing mapping... we can skip a lot of stuff */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (*pmap != AP_XML_NS_ERROR_NOT_FOUND) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* This entry has been filled in, so we can skip it */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes continue;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int j;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes size_t len;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *p;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** GIVEN: uri (a namespace URI from the request input)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes **
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** FIND: an equivalent URI in the propdb namespace table
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* only scan original entries (we may have added some in here) */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes for (p = propdb->ns_table.buf + sizeof(dav_propdb_metadata),
e8f95a682820a599fe41b22977010636be5c2717jim j = 0;
560fd0658902ab57754616c172d8953e69fc4722bnicholes j < orig_count;
ae1981fc94adf2b231e2d0e15d2f895b2138c969covener ++j, p += len + 1) {
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes len = strlen(p);
7a55c294da84865fe13262ed66ffd0c5841a9da5covener
fa123db15501821e36e513afa78e839775ad2800covener if (uri_len != len)
fa123db15501821e36e513afa78e839775ad2800covener continue;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (memcmp(uri, p, len) == 0) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *pmap = j;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes goto next_input_uri;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (!add_ns) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *pmap = AP_XML_NS_ERROR_NOT_FOUND;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** This flag indicates that we have an ns_map with missing
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** entries. If dav_prep_ns_map() is called with add_ns==1 AND
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** this flag is set, then we zip thru the array and add those
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** URIs (effectively updating the ns_map as if add_ns=1 was
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** passed when the initial prep was called).
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes propdb->incomplete_map = 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
0e05808dc59a321566303084c84b9826a4353cefrederpj continue;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener /*
0e05808dc59a321566303084c84b9826a4353cefrederpj ** The input URI was not found in the propdb namespace table, and
ebe5305f8b22507374358f32b74d12fb50c05a25covener ** we are supposed to add it. Append it to the table and store
ebe5305f8b22507374358f32b74d12fb50c05a25covener ** the index into the ns_map.
ebe5305f8b22507374358f32b74d12fb50c05a25covener */
ebe5305f8b22507374358f32b74d12fb50c05a25covener dav_check_bufsize(propdb->p, &propdb->ns_table, uri_len + 1);
ebe5305f8b22507374358f32b74d12fb50c05a25covener memcpy(propdb->ns_table.buf + propdb->ns_table.cur_len, uri, uri_len + 1);
ebe5305f8b22507374358f32b74d12fb50c05a25covener propdb->ns_table.cur_len += uri_len + 1;
ebe5305f8b22507374358f32b74d12fb50c05a25covener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener propdb->ns_table_dirty = 1;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener *pmap = propdb->ns_count++;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener next_input_uri:
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener ;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener }
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener}
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener/* find the "DAV:" namespace in our table and return its ID. */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovenerstatic int dav_find_dav_id(dav_propdb *propdb)
0e05808dc59a321566303084c84b9826a4353cefrederpj{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *p = propdb->ns_table.buf + sizeof(dav_propdb_metadata);
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener int ns;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes for (ns = 0; ns < propdb->ns_count; ++ns) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes size_t len = strlen(p);
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (len == 4 && memcmp(p, "DAV:", 5) == 0)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return ns;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes p += len + 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
9ad7b260be233be7d7b5576979825cac72e15498rederpj
9ad7b260be233be7d7b5576979825cac72e15498rederpj /* the "DAV:" namespace is not present */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin return -1;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin}
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrinstatic void dav_insert_xmlns(ap_pool_t *p, const char *pre_prefix, int ns,
54d22ed1c429b903b029bbd62621f11a9e286137minfrin const char *ns_uri, ap_text_header *phdr)
54d22ed1c429b903b029bbd62621f11a9e286137minfrin{
560fd0658902ab57754616c172d8953e69fc4722bnicholes const char *s;
54d22ed1c429b903b029bbd62621f11a9e286137minfrin
54d22ed1c429b903b029bbd62621f11a9e286137minfrin s = ap_psprintf(p, " xmlns:%s%d=\"%s\"", pre_prefix, ns, ns_uri);
ae1981fc94adf2b231e2d0e15d2f895b2138c969covener ap_text_append(p, phdr, s);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
a81c0c1ae464b2063a21b45f80c9da8d89bb840ecovener
7a55c294da84865fe13262ed66ffd0c5841a9da5covener/* return all known namespaces (in this propdb) */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovenerstatic void dav_get_propdb_xmlns(dav_propdb *propdb, ap_text_header *phdr)
fa123db15501821e36e513afa78e839775ad2800covener{
fa123db15501821e36e513afa78e839775ad2800covener int i;
fa123db15501821e36e513afa78e839775ad2800covener const char *p = propdb->ns_table.buf + sizeof(dav_propdb_metadata);
fa123db15501821e36e513afa78e839775ad2800covener size_t len;
fa123db15501821e36e513afa78e839775ad2800covener
fa123db15501821e36e513afa78e839775ad2800covener /* note: ns_count == 0 when we have no propdb file */
fa123db15501821e36e513afa78e839775ad2800covener for (i = 0; i < propdb->ns_count; ++i, p += len + 1) {
fa123db15501821e36e513afa78e839775ad2800covener
fa123db15501821e36e513afa78e839775ad2800covener len = strlen(p);
fa123db15501821e36e513afa78e839775ad2800covener
fa123db15501821e36e513afa78e839775ad2800covener dav_insert_xmlns(propdb->p, "ns", i, p, phdr);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* add a namespace decl from one of the namespace tables */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void dav_add_marked_xmlns(dav_propdb *propdb, char *marks, int ns,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_array_header_t *ns_table,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *pre_prefix,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_text_header *phdr)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (marks[ns])
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes marks[ns] = 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_insert_xmlns(propdb->p,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes pre_prefix, ns, AP_XML_GET_URI_ITEM(ns_table, ns),
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes phdr);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe/*
e8f95a682820a599fe41b22977010636be5c2717jim** Internal function to build a key
e8f95a682820a599fe41b22977010636be5c2717jim**
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe** WARNING: returns a pointer to a "static" buffer holding the key. The
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** value must be copied or no longer used if this function is
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes** called again.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes*/
e8f95a682820a599fe41b22977010636be5c2717jimstatic dav_datum dav_gdbm_key(dav_propdb *propdb, const ap_xml_elem *elem)
e8f95a682820a599fe41b22977010636be5c2717jim{
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe int ns;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char nsbuf[20];
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes size_t l_ns;
e8f95a682820a599fe41b22977010636be5c2717jim size_t l_name = strlen(elem->name);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_datum key = { 0 };
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Convert namespace ID to a string. "no namespace" is an empty string,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * so the keys will have the form ":name". Otherwise, the keys will
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * have the form "#:name".
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe if (elem->ns == AP_XML_NS_NONE) {
e8f95a682820a599fe41b22977010636be5c2717jim nsbuf[0] = '\0';
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe l_ns = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (propdb->ns_map == NULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Note that we prep the map and do NOT add namespaces. If that
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * is required, then the caller should have called prep
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * beforehand, passing the correct values.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_prep_ns_map(propdb, 0);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ns = propdb->ns_map[elem->ns];
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (AP_XML_NS_IS_ERROR(ns))
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return key; /* zeroed */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes l_ns = sprintf(nsbuf, "%d", ns);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* assemble: #:name */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_set_bufsize(propdb->p, &propdb->wb_key, l_ns + 1 + l_name + 1);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes memcpy(propdb->wb_key.buf, nsbuf, l_ns);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes propdb->wb_key.buf[l_ns] = ':';
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes memcpy(&propdb->wb_key.buf[l_ns + 1], elem->name, l_name + 1);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* build the database key */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes key.dsize = l_ns + 1 + l_name + 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes key.dptr = propdb->wb_key.buf;
e8f95a682820a599fe41b22977010636be5c2717jim
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return key;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic dav_error *dav_really_open_db(dav_propdb *propdb, int ro)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_error *err;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_datum key;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_datum value = { 0 };
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* we're trying to open the db; turn off the 'deferred' flag */
e8f95a682820a599fe41b22977010636be5c2717jim propdb->deferred = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ask the DB provider to open the thing */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes err = (*propdb->db_hooks->open)(propdb->p, propdb->resource, ro,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes &propdb->db);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (err != NULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return dav_push_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR,
43c3e6a4b559b76b750c245ee95e2782c15b4296jim DAV_ERR_PROP_OPENING,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "Could not open the property database.",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes err);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes /*
43c3e6a4b559b76b750c245ee95e2782c15b4296jim ** NOTE: propdb->db could be NULL if we attempted to open a readonly
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** database that doesn't exist. If we require read/write
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** access, then a database was created and opened.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener if (propdb->db != NULL) {
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener key.dptr = DAV_GDBM_NS_KEY;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf key.dsize = DAV_GDBM_NS_KEY_LEN;
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener if ((err = (*propdb->db_hooks->fetch)(propdb->db, key,
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe &value)) != NULL) {
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe /* ### push a higher-level description? */
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe return err;
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (value.dptr == NULL) {
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf dav_propdb_metadata m = {
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf DAV_DBVSN_MAJOR, DAV_DBVSN_MINOR, 0
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf };
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf if (propdb->db != NULL) {
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf /*
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf * If there is no METADATA key, then the database may be
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf * from versions 0.9.0 .. 0.9.4 (which would be incompatible).
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf * These can be identified by the presence of an NS_TABLE entry.
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes key.dptr = "NS_TABLE";
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes key.dsize = 8;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if ((*propdb->db_hooks->exists)(propdb->db, key)) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes (*propdb->db_hooks->close)(propdb->db);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* call it a major version error */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return dav_new_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes DAV_ERR_PROP_BAD_MAJOR,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "Prop database has the wrong major "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "version number and cannot be used.");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* initialize a new metadata structure */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_set_bufsize(propdb->p, &propdb->ns_table, sizeof(m));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes memcpy(propdb->ns_table.buf, &m, sizeof(m));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_propdb_metadata m;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_set_bufsize(propdb->p, &propdb->ns_table, value.dsize);
e8f95a682820a599fe41b22977010636be5c2717jim memcpy(propdb->ns_table.buf, value.dptr, value.dsize);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe memcpy(&m, value.dptr, sizeof(m));
e8f95a682820a599fe41b22977010636be5c2717jim if (m.major != DAV_DBVSN_MAJOR) {
e8f95a682820a599fe41b22977010636be5c2717jim (*propdb->db_hooks->close)(propdb->db);
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return dav_new_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes DAV_ERR_PROP_BAD_MAJOR,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "Prop database has the wrong major "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "version number and cannot be used.");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes propdb->version = m.minor;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes propdb->ns_count = ntohs(m.ns_count);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes (*propdb->db_hooks->freedatum)(propdb->db, value);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
e8f95a682820a599fe41b22977010636be5c2717jimdav_error *dav_open_propdb(request_rec *r, dav_lockdb *lockdb,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dav_resource *resource,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem int ro,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ap_array_header_t * ns_xlate,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_propdb **p_propdb)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe dav_propdb *propdb = ap_pcalloc(r->pool, sizeof(*propdb));
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe dav_error *err;
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes *p_propdb = NULL;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
e8f95a682820a599fe41b22977010636be5c2717jim#if DAV_DEBUG
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (resource->uri == NULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "INTERNAL DESIGN ERROR: resource must define "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "its URI.");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#endif
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe propdb->version = DAV_DBVSN_MINOR;
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe propdb->r = r;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes propdb->p = r->pool; /* ### get rid of this */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes propdb->resource = resource;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes propdb->ns_xlate = ns_xlate;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes propdb->db_hooks = DAV_GET_HOOKS_PROPDB(r);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes propdb->vsn_hooks = DAV_GET_HOOKS_VSN(r);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes propdb->liveprop = dav_get_provider_hooks(r, DAV_DYN_TYPE_LIVEPROP);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes propdb->lockdb = lockdb;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (!ro) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes propdb->deferred = 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
e8f95a682820a599fe41b22977010636be5c2717jim else if ((err = dav_really_open_db(propdb, 1 /* ro */)) != NULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return err;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### what to do about closing the propdb on server failure? */
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj *p_propdb = propdb;
e8f95a682820a599fe41b22977010636be5c2717jim return NULL;
e8f95a682820a599fe41b22977010636be5c2717jim}
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe
e8f95a682820a599fe41b22977010636be5c2717jimvoid dav_close_propdb(dav_propdb *propdb)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (propdb->db == NULL)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (propdb->ns_table_dirty) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_propdb_metadata m;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_datum key;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_datum value;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_error *err;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes key.dptr = DAV_GDBM_NS_KEY;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes key.dsize = DAV_GDBM_NS_KEY_LEN;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes value.dptr = propdb->ns_table.buf;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes value.dsize = propdb->ns_table.cur_len;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* fill in the metadata that we store into the prop db. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes m.major = DAV_DBVSN_MAJOR;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes m.minor = propdb->version; /* ### keep current minor version? */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes m.ns_count = htons(propdb->ns_count);
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj memcpy(propdb->ns_table.buf, &m, sizeof(m));
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj err = (*propdb->db_hooks->store)(propdb->db, key, value);
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj /* ### what to do with the error? */
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes (*propdb->db_hooks->close)(propdb->db);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesdav_get_props_result dav_get_allprops(dav_propdb *propdb, int getvals)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const dav_hooks_db *db_hooks = propdb->db_hooks;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_text_header hdr = { 0 };
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_text_header hdr_ns = { 0 };
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_get_props_result result = { 0 };
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int found_resourcetype = 0;
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj int found_contenttype = 0;
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes int found_contentlang = 0;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int unused_inserted;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes int i;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char * const * scan_uri;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const dav_dyn_hooks *ddh;
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener /* generate all the namespaces that are in the propdb */
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener dav_get_propdb_xmlns(propdb, &hdr_ns);
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener /* initialize the result with some start tags... */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_text_append(propdb->p, &hdr,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "<D:propstat>" DEBUG_CR
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes "<D:prop>" DEBUG_CR);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* if there ARE properties, then scan them */
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf if (propdb->db != NULL) {
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf dav_datum key;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf int dav_id = dav_find_dav_id(propdb);
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf (void) (*db_hooks->firstkey)(propdb->db, &key);
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf while (key.dptr) {
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf dav_datum prevkey;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf /* any keys with leading capital letters should be skipped
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes (real keys start with a number or a colon) */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (*key.dptr >= 'A' && *key.dptr <= 'Z')
e8f95a682820a599fe41b22977010636be5c2717jim goto next_key;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** See if this is the <DAV:resourcetype> property. We need to
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** know whether it was found (and therefore, whether to supply
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** a default later).
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes **
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** We also look for <DAV:getcontenttype> and
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj ** <DAV:getcontentlanguage>. If they are not stored as dead
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj ** properties, then we need to perform a subrequest to get
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** their values (if any).
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe */
e8f95a682820a599fe41b22977010636be5c2717jim if (dav_id != -1
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe && *key.dptr != ':'
e8f95a682820a599fe41b22977010636be5c2717jim && dav_id == atoi(key.dptr)) {
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe
e8f95a682820a599fe41b22977010636be5c2717jim const char *colon;
e8f95a682820a599fe41b22977010636be5c2717jim
e8f95a682820a599fe41b22977010636be5c2717jim /* find the colon */
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe if ( key.dptr[1] == ':' ) {
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe colon = key.dptr + 1;
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj }
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj else {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem colon = strchr(key.dptr + 2, ':');
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
9c63a05713cb83a44a1590b4af33edeebf39f118sf
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (colon[1] == 'r'
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf && strcmp(colon + 1, "resourcetype") == 0) {
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes found_resourcetype = 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else if (colon[1] == 'g') {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (strcmp(colon + 1, "getcontenttype") == 0) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes found_contenttype = 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else if (strcmp(colon + 1, "getcontentlanguage") == 0) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes found_contentlang = 1;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (getvals) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_datum value;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes (void) (*db_hooks->fetch)(propdb->db, key, &value);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (value.dptr == NULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### anything better to do? */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### probably should enter a 500 error */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes goto next_key;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* put the prop name and value into the result */
8869662bb1a4078297020e94ae5e928626d877c6rederpj dav_append_prop(propdb, key.dptr, value.dptr, &hdr);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem (*db_hooks->freedatum)(propdb->db, value);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem else {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* simple, empty element if a value isn't needed */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dav_append_prop(propdb, key.dptr, DAV_EMPTY_VALUE, &hdr);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj next_key:
8869662bb1a4078297020e94ae5e928626d877c6rederpj prevkey = key;
8869662bb1a4078297020e94ae5e928626d877c6rederpj (void) (*db_hooks->nextkey)(propdb->db, &key);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem (*db_hooks->freedatum)(propdb->db, prevkey);
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* add namespaces for all the liveprop providers */
8869662bb1a4078297020e94ae5e928626d877c6rederpj for (i = 0, scan_uri = (const char * const *)dav_liveprop_uris->elts;
8869662bb1a4078297020e94ae5e928626d877c6rederpj i < dav_liveprop_uris->nelts;
8869662bb1a4078297020e94ae5e928626d877c6rederpj ++i, ++scan_uri)
8869662bb1a4078297020e94ae5e928626d877c6rederpj dav_insert_xmlns(propdb->p, "lp", i, *scan_uri, &hdr_ns);
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* ask the liveprop providers to insert their properties */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem for (ddh = propdb->liveprop; ddh != NULL; ddh = ddh->next) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem (*DAV_AS_HOOKS_LIVEPROP(ddh)->insert_all)(propdb->resource, getvals,
8869662bb1a4078297020e94ae5e928626d877c6rederpj ddh->ctx.ns_map,
8869662bb1a4078297020e94ae5e928626d877c6rederpj &hdr);
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* insert the standard properties */
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* ### should be handling the return errors here */
8869662bb1a4078297020e94ae5e928626d877c6rederpj (void)dav_insert_coreprop(propdb,
8869662bb1a4078297020e94ae5e928626d877c6rederpj DAV_PROPID_CORE_supportedlock, "supportedlock",
8869662bb1a4078297020e94ae5e928626d877c6rederpj getvals, &hdr, &unused_inserted);
8869662bb1a4078297020e94ae5e928626d877c6rederpj (void)dav_insert_coreprop(propdb,
8869662bb1a4078297020e94ae5e928626d877c6rederpj DAV_PROPID_CORE_lockdiscovery, "lockdiscovery",
8869662bb1a4078297020e94ae5e928626d877c6rederpj getvals, &hdr, &unused_inserted);
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* if the resourcetype wasn't stored, then prepare one */
6733d943c9e8d0f27dd077a04037e8c49eb090ffcovener if (!found_resourcetype) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* ### should be handling the return error here */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem (void)dav_insert_coreprop(propdb,
8869662bb1a4078297020e94ae5e928626d877c6rederpj DAV_PROPID_CORE_resourcetype, "resourcetype",
8869662bb1a4078297020e94ae5e928626d877c6rederpj getvals, &hdr, &unused_inserted);
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf /* if we didn't find these, then do the whole subreq thing. */
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf if (!found_contenttype) {
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf /* ### should be handling the return error here */
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf (void)dav_insert_coreprop(propdb,
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf DAV_PROPID_CORE_getcontenttype,
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf "getcontenttype",
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf getvals, &hdr, &unused_inserted);
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf }
8869662bb1a4078297020e94ae5e928626d877c6rederpj if (!found_contentlang) {
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* ### should be handling the return error here */
8869662bb1a4078297020e94ae5e928626d877c6rederpj (void)dav_insert_coreprop(propdb,
8869662bb1a4078297020e94ae5e928626d877c6rederpj DAV_PROPID_CORE_getcontentlanguage,
8869662bb1a4078297020e94ae5e928626d877c6rederpj "getcontentlanguage",
8869662bb1a4078297020e94ae5e928626d877c6rederpj getvals, &hdr, &unused_inserted);
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* terminate the result */
8869662bb1a4078297020e94ae5e928626d877c6rederpj ap_text_append(propdb->p, &hdr,
8869662bb1a4078297020e94ae5e928626d877c6rederpj "</D:prop>" DEBUG_CR
8869662bb1a4078297020e94ae5e928626d877c6rederpj "<D:status>HTTP/1.1 200 OK</D:status>" DEBUG_CR
8869662bb1a4078297020e94ae5e928626d877c6rederpj "</D:propstat>" DEBUG_CR);
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj result.propstats = hdr.first;
8869662bb1a4078297020e94ae5e928626d877c6rederpj result.xmlns = hdr_ns.first;
8869662bb1a4078297020e94ae5e928626d877c6rederpj return result;
8869662bb1a4078297020e94ae5e928626d877c6rederpj}
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpjdav_get_props_result dav_get_props(dav_propdb *propdb, ap_xml_doc *doc)
8869662bb1a4078297020e94ae5e928626d877c6rederpj{
8869662bb1a4078297020e94ae5e928626d877c6rederpj const dav_hooks_db *db_hooks = propdb->db_hooks;
8869662bb1a4078297020e94ae5e928626d877c6rederpj ap_xml_elem *elem = dav_find_child(doc->root, "prop");
8869662bb1a4078297020e94ae5e928626d877c6rederpj ap_text_header hdr_good = { 0 };
8869662bb1a4078297020e94ae5e928626d877c6rederpj ap_text_header hdr_bad = { 0 };
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ap_text_header hdr_ns = { 0 };
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem int have_good = 0;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dav_get_props_result result = { 0 };
8869662bb1a4078297020e94ae5e928626d877c6rederpj char *marks_input;
8869662bb1a4078297020e94ae5e928626d877c6rederpj char *marks_liveprop;
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* ### NOTE: we should pass in TWO buffers -- one for keys, one for
8869662bb1a4078297020e94ae5e928626d877c6rederpj the marks */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* we will ALWAYS provide a "good" result, even if it is EMPTY */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ap_text_append(propdb->p, &hdr_good,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "<D:propstat>" DEBUG_CR
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "<D:prop>" DEBUG_CR);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* generate all the namespaces that are in the propdb */
8869662bb1a4078297020e94ae5e928626d877c6rederpj dav_get_propdb_xmlns(propdb, &hdr_ns);
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* ### the marks should be in a buffer! */
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* allocate zeroed-memory for the marks. These marks indicate which
8869662bb1a4078297020e94ae5e928626d877c6rederpj input namespaces we've generated into the output xmlns buffer */
8869662bb1a4078297020e94ae5e928626d877c6rederpj marks_input = ap_pcalloc(propdb->p, propdb->ns_xlate->nelts);
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* same for the liveprops */
8869662bb1a4078297020e94ae5e928626d877c6rederpj marks_liveprop = ap_pcalloc(propdb->p, dav_liveprop_uris->nelts);
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj for (elem = elem->first_child; elem; elem = elem->next) {
8869662bb1a4078297020e94ae5e928626d877c6rederpj dav_datum key;
8869662bb1a4078297020e94ae5e928626d877c6rederpj dav_datum value = { 0 };
8869662bb1a4078297020e94ae5e928626d877c6rederpj dav_elem_private *priv;
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj /*
8869662bb1a4078297020e94ae5e928626d877c6rederpj ** Note: the key may be NULL if we have no properties that are in
8869662bb1a4078297020e94ae5e928626d877c6rederpj ** a namespace that matches the requested prop's namespace.
8869662bb1a4078297020e94ae5e928626d877c6rederpj */
8869662bb1a4078297020e94ae5e928626d877c6rederpj key = dav_gdbm_key(propdb, elem);
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* fetch IF we have a db and a key. otherwise, value is NULL */
8869662bb1a4078297020e94ae5e928626d877c6rederpj if (propdb->db != NULL && key.dptr != NULL) {
8869662bb1a4078297020e94ae5e928626d877c6rederpj (void) (*db_hooks->fetch)(propdb->db, key, &value);
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (elem->private == NULL) {
8869662bb1a4078297020e94ae5e928626d877c6rederpj elem->private = ap_pcalloc(propdb->p, sizeof(*elem->private));
8869662bb1a4078297020e94ae5e928626d877c6rederpj }
8869662bb1a4078297020e94ae5e928626d877c6rederpj priv = elem->private;
8869662bb1a4078297020e94ae5e928626d877c6rederpj
8869662bb1a4078297020e94ae5e928626d877c6rederpj /*
8869662bb1a4078297020e94ae5e928626d877c6rederpj ** If we did not find the property in the database, then it may
8869662bb1a4078297020e94ae5e928626d877c6rederpj ** be a liveprop that we can handle specially.
8869662bb1a4078297020e94ae5e928626d877c6rederpj */
8869662bb1a4078297020e94ae5e928626d877c6rederpj if (value.dptr == NULL) {
8869662bb1a4078297020e94ae5e928626d877c6rederpj dav_error *err;
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj int inserted;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* cache the propid; dav_get_props() could be called many times */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (priv->propid == 0)
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dav_find_liveprop(propdb, elem);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* insert the property. returns 1 if an insertion was done. */
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj if ((err = dav_insert_liveprop(propdb, elem, 1, &hdr_good,
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj &inserted)) != NULL) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* ### need to propagate the error to the caller... */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* ### skip it for now, as if nothing was inserted */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (inserted) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem have_good = 1;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /*
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ** Add the liveprop's namespace URIs. Note that provider==NULL
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ** for core properties.
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (priv->provider != NULL) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem const char * const * scan_ns_uri;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem const int * scan_ns;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem for (scan_ns_uri = priv->provider->namespace_uris,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem scan_ns = priv->ns_map;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem *scan_ns_uri != NULL;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ++scan_ns_uri, ++scan_ns) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dav_add_marked_xmlns(propdb, marks_liveprop, *scan_ns,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dav_liveprop_uris, "lp", &hdr_ns);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem continue;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (value.dptr == NULL) {
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj /* not found. add a record to the "bad" propstats */
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* make sure we've started our "bad" propstat */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (hdr_bad.first == NULL) {
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj ap_text_append(propdb->p, &hdr_bad,
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj "<D:propstat>" DEBUG_CR
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "<D:prop>" DEBUG_CR);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* note: key.dptr may be NULL if the propdb doesn't have an
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj equivalent namespace stored */
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj if (key.dptr == NULL) {
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj const char *s;
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj if (elem->ns == AP_XML_NS_NONE) {
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj /*
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj * elem has a prefix already (xml...:name) or the elem
0e05808dc59a321566303084c84b9826a4353cefrederpj * simply has no namespace.
a9c4332dc6241dc11dd104826bd179d42ccc0f12fuankg */
a9c4332dc6241dc11dd104826bd179d42ccc0f12fuankg s = ap_psprintf(propdb->p, "<%s/>" DEBUG_CR, elem->name);
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj }
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj else {
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj /* ensure that an xmlns is generated for the
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj input namespace */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dav_add_marked_xmlns(propdb, marks_input, elem->ns,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem propdb->ns_xlate, "i", &hdr_ns);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem s = ap_psprintf(propdb->p, "<i%d:%s/>" DEBUG_CR,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem elem->ns, elem->name);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ap_text_append(propdb->p, &hdr_bad, s);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem else {
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj /* add in the bad prop using our namespace decl */
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj dav_append_prop(propdb, key.dptr, DAV_EMPTY_VALUE, &hdr_bad);
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj }
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj }
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj else {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* found it. put the value into the "good" propstats */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem have_good = 1;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dav_append_prop(propdb, key.dptr, value.dptr, &hdr_good);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem (*db_hooks->freedatum)(propdb->db, value);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj }
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj ap_text_append(propdb->p, &hdr_good,
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj "</D:prop>" DEBUG_CR
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj "<D:status>HTTP/1.1 200 OK</D:status>" DEBUG_CR
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj "</D:propstat>" DEBUG_CR);
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /* default to start with the good */
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj result.propstats = hdr_good.first;
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* we may not have any "bad" results */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (hdr_bad.first != NULL) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ap_text_append(propdb->p, &hdr_bad,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "</D:prop>" DEBUG_CR
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj "<D:status>HTTP/1.1 404 Not Found</D:status>" DEBUG_CR
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj "</D:propstat>" DEBUG_CR);
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /* if there are no good props, then just return the bad */
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj if (!have_good) {
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj result.propstats = hdr_bad.first;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj }
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj else {
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj /* hook the bad propstat to the end of the good one */
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj hdr_good.last->next = hdr_bad.first;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj }
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj }
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj result.xmlns = hdr_ns.first;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj return result;
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj}
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluemvoid dav_prop_validate(dav_prop_ctx *ctx)
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj{
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj dav_propdb *propdb = ctx->propdb;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ap_xml_elem *prop = ctx->prop;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem dav_elem_private *priv;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem priv = ctx->prop->private = ap_pcalloc(propdb->p, sizeof(*priv));
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj /*
0e05808dc59a321566303084c84b9826a4353cefrederpj ** Check to see if this is a live property, and fill the fields
0e05808dc59a321566303084c84b9826a4353cefrederpj ** in the XML elem, as appropriate.
0e05808dc59a321566303084c84b9826a4353cefrederpj **
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf ** Verify that the property is read/write. If not, then it cannot
0e05808dc59a321566303084c84b9826a4353cefrederpj ** be SET or DELETEd.
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf */
0e05808dc59a321566303084c84b9826a4353cefrederpj if (priv->propid == 0) {
0e05808dc59a321566303084c84b9826a4353cefrederpj dav_find_liveprop(propdb, prop);
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj /* it's a liveprop if a provider was found */
0e05808dc59a321566303084c84b9826a4353cefrederpj /* ### actually the "core" props should really be liveprops, but
0e05808dc59a321566303084c84b9826a4353cefrederpj ### there is no "provider" for those and the r/w props are
0e05808dc59a321566303084c84b9826a4353cefrederpj ### treated as dead props anyhow */
0e05808dc59a321566303084c84b9826a4353cefrederpj ctx->is_liveprop = priv->provider != NULL;
0e05808dc59a321566303084c84b9826a4353cefrederpj }
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj if (!dav_rw_liveprop(propdb, priv->propid)) {
0e05808dc59a321566303084c84b9826a4353cefrederpj ctx->err = dav_new_error(propdb->p, HTTP_CONFLICT,
0e05808dc59a321566303084c84b9826a4353cefrederpj DAV_ERR_PROP_READONLY,
0e05808dc59a321566303084c84b9826a4353cefrederpj "Property is read-only.");
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj return;
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj }
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj if (ctx->is_liveprop) {
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj int defer_to_dead = 0;
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj ctx->err = (*priv->provider->patch_validate)(propdb->resource,
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj prop, ctx->operation,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem &ctx->liveprop_ctx,
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf &defer_to_dead);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (ctx->err != NULL || !defer_to_dead)
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem return;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /* clear is_liveprop -- act as a dead prop now */
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf ctx->is_liveprop = 0;
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf }
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj /*
0e05808dc59a321566303084c84b9826a4353cefrederpj ** The property is supposed to be stored into the dead-property
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ** database. Make sure the thing is truly open (and writeable).
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (propdb->deferred
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj && (ctx->err = dav_really_open_db(propdb, 0 /* ro */)) != NULL) {
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj return;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj }
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /*
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj ** There should be an open, writable database in here!
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj **
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj ** Note: the database would be NULL if it was opened readonly and it
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj ** did not exist.
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (propdb->db == NULL) {
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj ctx->err = dav_new_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR,
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj DAV_ERR_PROP_NO_DATABASE,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "Attempted to set/remove a property "
0e05808dc59a321566303084c84b9826a4353cefrederpj "without a valid, open, read/write "
0e05808dc59a321566303084c84b9826a4353cefrederpj "property database.");
0e05808dc59a321566303084c84b9826a4353cefrederpj return;
0e05808dc59a321566303084c84b9826a4353cefrederpj }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
0e05808dc59a321566303084c84b9826a4353cefrederpj if (ctx->operation == DAV_PROP_OP_SET) {
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf /*
0e05808dc59a321566303084c84b9826a4353cefrederpj ** Prep the element => propdb namespace index mapping, inserting
0e05808dc59a321566303084c84b9826a4353cefrederpj ** namespace URIs into the propdb that don't exist.
0e05808dc59a321566303084c84b9826a4353cefrederpj */
0e05808dc59a321566303084c84b9826a4353cefrederpj dav_prep_ns_map(propdb, 1);
0e05808dc59a321566303084c84b9826a4353cefrederpj }
0e05808dc59a321566303084c84b9826a4353cefrederpj else if (ctx->operation == DAV_PROP_OP_DELETE) {
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf /*
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf ** There are no checks to perform here. If a property exists, then
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf ** we will delete it. If it does not exist, then it does not matter
0e05808dc59a321566303084c84b9826a4353cefrederpj ** (see S12.13.1).
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj **
0e05808dc59a321566303084c84b9826a4353cefrederpj ** Note that if a property does not exist, that does not rule out
40a1aee60a66f7c8dbd0835fdd4f09334e12fc15rpluem ** that a SET will occur during this PROPPATCH (thusly creating it).
0e05808dc59a321566303084c84b9826a4353cefrederpj */
0e05808dc59a321566303084c84b9826a4353cefrederpj }
40a1aee60a66f7c8dbd0835fdd4f09334e12fc15rpluem}
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpjvoid dav_prop_exec(dav_prop_ctx *ctx)
0e05808dc59a321566303084c84b9826a4353cefrederpj{
0e05808dc59a321566303084c84b9826a4353cefrederpj dav_propdb *propdb = ctx->propdb;
0e05808dc59a321566303084c84b9826a4353cefrederpj dav_error *err = NULL;
0e05808dc59a321566303084c84b9826a4353cefrederpj dav_rollback_item *rollback;
0e05808dc59a321566303084c84b9826a4353cefrederpj dav_elem_private *priv = ctx->prop->private;
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj rollback = ap_pcalloc(propdb->p, sizeof(*rollback));
0e05808dc59a321566303084c84b9826a4353cefrederpj ctx->rollback = rollback;
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj if (ctx->is_liveprop) {
0e05808dc59a321566303084c84b9826a4353cefrederpj err = (*priv->provider->patch_exec)(propdb->resource,
0e05808dc59a321566303084c84b9826a4353cefrederpj ctx->prop, ctx->operation,
0e05808dc59a321566303084c84b9826a4353cefrederpj ctx->liveprop_ctx,
0e05808dc59a321566303084c84b9826a4353cefrederpj &ctx->rollback->liveprop);
0e05808dc59a321566303084c84b9826a4353cefrederpj }
0e05808dc59a321566303084c84b9826a4353cefrederpj else {
0e05808dc59a321566303084c84b9826a4353cefrederpj dav_datum key;
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj /* we're going to need the key for all operations */
0e05808dc59a321566303084c84b9826a4353cefrederpj key = dav_gdbm_key(propdb, ctx->prop);
0e05808dc59a321566303084c84b9826a4353cefrederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj /* save the old value so that we can do a rollback. */
0e05808dc59a321566303084c84b9826a4353cefrederpj rollback->key = key;
0e05808dc59a321566303084c84b9826a4353cefrederpj if ((err = (*propdb->db_hooks->fetch)(propdb->db, key,
0e05808dc59a321566303084c84b9826a4353cefrederpj &rollback->value)) != NULL)
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj goto error;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
0e05808dc59a321566303084c84b9826a4353cefrederpj if (ctx->operation == DAV_PROP_OP_SET) {
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj dav_datum value;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* Note: propdb->ns_map was set in dav_prop_validate() */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* quote all the values in the element */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ap_xml_quote_elem(propdb->p, ctx->prop);
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /* generate a text blob for the xml:lang plus the contents */
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj ap_xml_to_text(propdb->p, ctx->prop, AP_XML_X2T_LANG_INNER, NULL,
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj propdb->ns_map,
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj (const char **)&value.dptr, &value.dsize);
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj err = (*propdb->db_hooks->store)(propdb->db, key, value);
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /*
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ** If an error occurred, then assume that we didn't change the
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ** value. Remove the rollback item so that we don't try to set
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ** its value during the rollback.
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj */
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem else if (ctx->operation == DAV_PROP_OP_DELETE) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /*
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ** Delete the property. Ignore errors -- the property is there, or
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf ** we are deleting it for a second time.
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf */
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf /* ### but what about other errors? */
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf (void) (*propdb->db_hooks->remove)(propdb->db, key);
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj }
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem error:
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* push a more specific error here */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if (err != NULL) {
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf /*
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf ** Use HTTP_INTERNAL_SERVER_ERROR because we shouldn't have seen
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf ** any errors at this point.
9efd5708f6f0ab1992f6a5233eb622ad5e4eae18sf */
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj ctx->err = dav_push_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem DAV_ERR_PROP_EXEC,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "Could not execute PROPPATCH.", err);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem }
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem}
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpjvoid dav_prop_commit(dav_prop_ctx *ctx)
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj{
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj dav_elem_private *priv = ctx->prop->private;
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj /*
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj ** Note that a commit implies ctx->err is NULL. The caller should assume
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj ** a status of HTTP_OK for this case.
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe */
e8f95a682820a599fe41b22977010636be5c2717jim
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe if (ctx->is_liveprop) {
e8f95a682820a599fe41b22977010636be5c2717jim (*priv->provider->patch_commit)(ctx->propdb->resource,
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe ctx->operation,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ctx->liveprop_ctx,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ctx->rollback->liveprop);
8bdea88407c848c1c2693655e2f8b23abde12307bnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesvoid dav_prop_rollback(dav_prop_ctx *ctx)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes{
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes dav_error *err = NULL;
f05787953018140838ad51456c86c965d6a86267jim dav_elem_private *priv = ctx->prop->private;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
f05787953018140838ad51456c86c965d6a86267jim /* do nothing if there is no rollback information. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (ctx->rollback == NULL)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
e8f95a682820a599fe41b22977010636be5c2717jim /*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** ### if we have an error, and a rollback occurs, then the namespace
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** ### mods should not happen at all. Basically, the namespace management
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ** ### is simply a bitch.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (ctx->is_liveprop) {
e8f95a682820a599fe41b22977010636be5c2717jim err = (*priv->provider->patch_rollback)(ctx->propdb->resource,
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe ctx->operation,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ctx->liveprop_ctx,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ctx->rollback->liveprop);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else if (ctx->rollback->value.dptr == NULL) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* don't fail if the thing isn't really there */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ### but what about other errors? */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes (void) (*ctx->propdb->db_hooks->remove)(ctx->propdb->db,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ctx->rollback->key);
e8f95a682820a599fe41b22977010636be5c2717jim }
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe else {
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes err = (*ctx->propdb->db_hooks->store)(ctx->propdb->db,
e8f95a682820a599fe41b22977010636be5c2717jim ctx->rollback->key,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ctx->rollback->value);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes }
e8f95a682820a599fe41b22977010636be5c2717jim
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (err != NULL) {
e8f95a682820a599fe41b22977010636be5c2717jim if (ctx->err == NULL)
e8f95a682820a599fe41b22977010636be5c2717jim ctx->err = err;
e8f95a682820a599fe41b22977010636be5c2717jim else {
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe dav_error *scan = err;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* hook previous errors at the end of the rollback error */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes while (scan->prev != NULL)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes scan = scan->prev;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes scan->prev = ctx->err;
e8f95a682820a599fe41b22977010636be5c2717jim ctx->err = err;
e8f95a682820a599fe41b22977010636be5c2717jim }
e8f95a682820a599fe41b22977010636be5c2717jim }
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe}
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes