summaryrefslogtreecommitdiffstats
path: root/rubbos/app/httpd-2.0.64/modules/dav/main/props.c
diff options
context:
space:
mode:
Diffstat (limited to 'rubbos/app/httpd-2.0.64/modules/dav/main/props.c')
-rw-r--r--rubbos/app/httpd-2.0.64/modules/dav/main/props.c1116
1 files changed, 0 insertions, 1116 deletions
diff --git a/rubbos/app/httpd-2.0.64/modules/dav/main/props.c b/rubbos/app/httpd-2.0.64/modules/dav/main/props.c
deleted file mode 100644
index fc28532d..00000000
--- a/rubbos/app/httpd-2.0.64/modules/dav/main/props.c
+++ /dev/null
@@ -1,1116 +0,0 @@
-/* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
-** DAV extension module for Apache 2.0.*
-** - Property database handling (repository-independent)
-**
-** NOTES:
-**
-** PROPERTY DATABASE
-**
-** This version assumes that there is a per-resource database provider
-** to record properties. The database provider decides how and where to
-** store these databases.
-**
-** The DBM keys for the properties have the following form:
-**
-** namespace ":" propname
-**
-** For example: 5:author
-**
-** The namespace provides an integer index into the namespace table
-** (see below). propname is simply the property name, without a namespace
-** prefix.
-**
-** A special case exists for properties that had a prefix starting with
-** "xml". The XML Specification reserves these for future use. mod_dav
-** stores and retrieves them unchanged. The keys for these properties
-** have the form:
-**
-** ":" propname
-**
-** The propname will contain the prefix and the property name. For
-** example, a key might be ":xmlfoo:name"
-**
-** The ":name" style will also be used for properties that do not
-** exist within a namespace.
-**
-** The DBM values consist of two null-terminated strings, appended
-** together (the null-terms are retained and stored in the database).
-** The first string is the xml:lang value for the property. An empty
-** string signifies that a lang value was not in context for the value.
-** The second string is the property value itself.
-**
-**
-** NAMESPACE TABLE
-**
-** The namespace table is an array that lists each of the namespaces
-** that are in use by the properties in the given propdb. Each entry
-** in the array is a simple URI.
-**
-** For example: http://www.foo.bar/standards/props/
-**
-** The prefix used for the property is stripped and the URI for it
-** is entered into the namespace table. Also, any namespaces used
-** within the property value will be entered into the table (and
-** stripped from the child elements).
-**
-** The namespaces are stored in the DBM database under the "METADATA" key.
-**
-**
-** STRIPPING NAMESPACES
-**
-** Within the property values, the namespace declarations (xmlns...)
-** are stripped. Each element and attribute will have its prefix removed
-** and a new prefix inserted.
-**
-** This must be done so that we can return multiple properties in a
-** PROPFIND which may have (originally) used conflicting prefixes. For
-** that case, we must bind all property value elements to new namespace
-** values.
-**
-** This implies that clients must NOT be sensitive to the namespace
-** prefix used for their properties. It WILL change when the properties
-** are returned (we return them as "ns<index>", e.g. "ns5"). Also, the
-** property value can contain ONLY XML elements and CDATA. PI and comment
-** elements will be stripped. CDATA whitespace will be preserved, but
-** whitespace within element tags will be altered. Attribute ordering
-** may be altered. Element and CDATA ordering will be preserved.
-**
-**
-** ATTRIBUTES ON PROPERTY NAME ELEMENTS
-**
-** When getting/setting properties, the XML used looks like:
-**
-** <prop>
-** <propname1>value</propname1>
-** <propname2>value</propname1>
-** </prop>
-**
-** This implementation (mod_dav) DOES NOT save any attributes that are
-** associated with the <propname1> element. The property value is deemed
-** to be only the contents ("value" in the above example).
-**
-** We do store the xml:lang value (if any) that applies to the context
-** of the <propname1> element. Whether the xml:lang attribute is on
-** <propname1> itself, or from a higher level element, we will store it
-** with the property value.
-**
-**
-** VERSIONING
-**
-** The DBM db contains a key named "METADATA" that holds database-level
-** information, such as the namespace table. The record also contains the
-** db's version number as the very first 16-bit value. This first number
-** is actually stored as two single bytes: the first byte is a "major"
-** version number. The second byte is a "minor" number.
-**
-** If the major number is not what mod_dav expects, then the db is closed
-** immediately and an error is returned. A minor number change is
-** acceptable -- it is presumed that old/new dav_props.c can deal with
-** the database format. For example, a newer dav_props might update the
-** minor value and append information to the end of the metadata record
-** (which would be ignored by previous versions).
-**
-**
-** ISSUES:
-**
-** At the moment, for the dav_get_allprops() and dav_get_props() functions,
-** we must return a set of xmlns: declarations for ALL known namespaces
-** in the file. There isn't a way to filter this because we don't know
-** which are going to be used or not. Examining property names is not
-** sufficient because the property values could use entirely different
-** namespaces.
-**
-** ==> we must devise a scheme where we can "garbage collect" the namespace
-** entries from the property database.
-*/
-
-#include "apr.h"
-#include "apr_strings.h"
-
-#define APR_WANT_STDIO
-#define APR_WANT_BYTEFUNC
-#include "apr_want.h"
-
-#include "mod_dav.h"
-
-#include "http_log.h"
-#include "http_request.h"
-
-/*
-** There is some rough support for writable DAV:getcontenttype and
-** DAV:getcontentlanguage properties. If this #define is (1), then
-** this support is disabled.
-**
-** We are disabling it because of a lack of support in GET and PUT
-** operations. For GET, it would be "expensive" to look for a propdb,
-** open it, and attempt to extract the Content-Type and Content-Language
-** values for the response.
-** (Handling the PUT would not be difficult, though)
-*/
-#define DAV_DISABLE_WRITABLE_PROPS 1
-
-#define DAV_EMPTY_VALUE "\0" /* TWO null terms */
-
-struct dav_propdb {
- apr_pool_t *p; /* the pool we should use */
- request_rec *r; /* the request record */
-
- const dav_resource *resource; /* the target resource */
-
- int deferred; /* open of db has been deferred */
- dav_db *db; /* underlying database containing props */
-
- apr_array_header_t *ns_xlate; /* translation of an elem->ns to URI */
- dav_namespace_map *mapping; /* namespace mapping */
-
- dav_lockdb *lockdb; /* the lock database */
-
- dav_buffer wb_lock; /* work buffer for lockdiscovery property */
-
- /* if we ever run a GET subreq, it will be stored here */
- request_rec *subreq;
-
- /* hooks we should use for processing (based on the target resource) */
- const dav_hooks_db *db_hooks;
-};
-
-/* NOTE: dav_core_props[] and the following enum must stay in sync. */
-/* ### move these into a "core" liveprop provider? */
-static const char * const dav_core_props[] =
-{
- "getcontenttype",
- "getcontentlanguage",
- "lockdiscovery",
- "supportedlock",
-
- NULL /* sentinel */
-};
-enum {
- DAV_PROPID_CORE_getcontenttype = DAV_PROPID_CORE,
- DAV_PROPID_CORE_getcontentlanguage,
- DAV_PROPID_CORE_lockdiscovery,
- DAV_PROPID_CORE_supportedlock,
-
- DAV_PROPID_CORE_UNKNOWN
-};
-
-/*
-** This structure is used to track information needed for a rollback.
-*/
-typedef struct dav_rollback_item {
- /* select one of the two rollback context structures based on the
- value of dav_prop_ctx.is_liveprop */
- dav_deadprop_rollback *deadprop;
- dav_liveprop_rollback *liveprop;
-
-} dav_rollback_item;
-
-
-static int dav_find_liveprop_provider(dav_propdb *propdb,
- const char *ns_uri,
- const char *propname,
- const dav_hooks_liveprop **provider)
-{
- int propid;
-
- *provider = NULL;
-
- if (ns_uri == NULL) {
- /* policy: liveprop providers cannot define no-namespace properties */
- return DAV_PROPID_CORE_UNKNOWN;
- }
-
- /* check liveprop providers first, so they can define core properties */
- propid = dav_run_find_liveprop(propdb->resource, ns_uri, propname,
- provider);
- if (propid != 0) {
- return propid;
- }
-
- /* check for core property */
- if (strcmp(ns_uri, "DAV:") == 0) {
- const char * const *p = dav_core_props;
-
- for (propid = DAV_PROPID_CORE; *p != NULL; ++p, ++propid)
- if (strcmp(propname, *p) == 0) {
- return propid;
- }
- }
-
- /* no provider for this property */
- return DAV_PROPID_CORE_UNKNOWN;
-}
-
-static void dav_find_liveprop(dav_propdb *propdb, apr_xml_elem *elem)
-{
- const char *ns_uri;
- dav_elem_private *priv = elem->priv;
- const dav_hooks_liveprop *hooks;
-
-
- if (elem->ns == APR_XML_NS_NONE)
- ns_uri = NULL;
- else if (elem->ns == APR_XML_NS_DAV_ID)
- ns_uri = "DAV:";
- else
- ns_uri = APR_XML_GET_URI_ITEM(propdb->ns_xlate, elem->ns);
-
- priv->propid = dav_find_liveprop_provider(propdb, ns_uri, elem->name,
- &hooks);
-
- /* ### this test seems redundant... */
- if (priv->propid != DAV_PROPID_CORE_UNKNOWN) {
- priv->provider = hooks;
- }
-}
-
-/* is the live property read/write? */
-static int dav_rw_liveprop(dav_propdb *propdb, dav_elem_private *priv)
-{
- int propid = priv->propid;
-
- /*
- ** Check the liveprop provider (if this is a provider-defined prop)
- */
- if (priv->provider != NULL) {
- return (*priv->provider->is_writable)(propdb->resource, propid);
- }
-
- /* these are defined as read-only */
- if (propid == DAV_PROPID_CORE_lockdiscovery
-#if DAV_DISABLE_WRITABLE_PROPS
- || propid == DAV_PROPID_CORE_getcontenttype
- || propid == DAV_PROPID_CORE_getcontentlanguage
-#endif
- || propid == DAV_PROPID_CORE_supportedlock
- ) {
-
- return 0;
- }
-
- /* these are defined as read/write */
- if (propid == DAV_PROPID_CORE_getcontenttype
- || propid == DAV_PROPID_CORE_getcontentlanguage
- || propid == DAV_PROPID_CORE_UNKNOWN) {
-
- return 1;
- }
-
- /*
- ** We don't recognize the property, so it must be dead (and writable)
- */
- return 1;
-}
-
-/* do a sub-request to fetch properties for the target resource's URI. */
-static void dav_do_prop_subreq(dav_propdb *propdb)
-{
- /* perform a "GET" on the resource's URI (note that the resource
- may not correspond to the current request!). */
- propdb->subreq = ap_sub_req_lookup_uri(propdb->resource->uri, propdb->r,
- NULL);
-}
-
-static dav_error * dav_insert_coreprop(dav_propdb *propdb,
- int propid, const char *name,
- dav_prop_insert what,
- apr_text_header *phdr,
- dav_prop_insert *inserted)
-{
- const char *value = NULL;
- dav_error *err;
-
- *inserted = DAV_PROP_INSERT_NOTDEF;
-
- /* fast-path the common case */
- if (propid == DAV_PROPID_CORE_UNKNOWN)
- return NULL;
-
- switch (propid) {
-
- case DAV_PROPID_CORE_lockdiscovery:
- if (propdb->lockdb != NULL) {
- dav_lock *locks;
-
- if ((err = dav_lock_query(propdb->lockdb, propdb->resource,
- &locks)) != NULL) {
- return dav_push_error(propdb->p, err->status, 0,
- "DAV:lockdiscovery could not be "
- "determined due to a problem fetching "
- "the locks for this resource.",
- err);
- }
-
- /* fast-path the no-locks case */
- if (locks == NULL) {
- value = "";
- }
- else {
- /*
- ** This may modify the buffer. value may point to
- ** wb_lock.pbuf or a string constant.
- */
- value = dav_lock_get_activelock(propdb->r, locks,
- &propdb->wb_lock);
-
- /* make a copy to isolate it from changes to wb_lock */
- value = apr_pstrdup(propdb->p, propdb->wb_lock.buf);
- }
- }
- break;
-
- case DAV_PROPID_CORE_supportedlock:
- if (propdb->lockdb != NULL) {
- value = (*propdb->lockdb->hooks->get_supportedlock)(propdb->resource);
- }
- break;
-
- case DAV_PROPID_CORE_getcontenttype:
- if (propdb->subreq == NULL) {
- dav_do_prop_subreq(propdb);
- }
- if (propdb->subreq->content_type != NULL) {
- value = propdb->subreq->content_type;
- }
- break;
-
- case DAV_PROPID_CORE_getcontentlanguage:
- {
- const char *lang;
-
- if (propdb->subreq == NULL) {
- dav_do_prop_subreq(propdb);
- }
- if ((lang = apr_table_get(propdb->subreq->headers_out,
- "Content-Language")) != NULL) {
- value = lang;
- }
- break;
- }
-
- default:
- /* fall through to interpret as a dead property */
- break;
- }
-
- /* if something was supplied, then insert it */
- if (value != NULL) {
- const char *s;
-
- if (what == DAV_PROP_INSERT_SUPPORTED) {
- /* use D: prefix to refer to the DAV: namespace URI,
- * and let the namespace attribute default to "DAV:"
- */
- s = apr_psprintf(propdb->p,
- "<D:supported-live-property D:name=\"%s\"/>" DEBUG_CR,
- name);
- }
- else if (what == DAV_PROP_INSERT_VALUE && *value != '\0') {
- /* use D: prefix to refer to the DAV: namespace URI */
- s = apr_psprintf(propdb->p, "<D:%s>%s</D:%s>" DEBUG_CR,
- name, value, name);
- }
- else {
- /* use D: prefix to refer to the DAV: namespace URI */
- s = apr_psprintf(propdb->p, "<D:%s/>" DEBUG_CR, name);
- }
- apr_text_append(propdb->p, phdr, s);
-
- *inserted = what;
- }
-
- return NULL;
-}
-
-static dav_error * dav_insert_liveprop(dav_propdb *propdb,
- const apr_xml_elem *elem,
- dav_prop_insert what,
- apr_text_header *phdr,
- dav_prop_insert *inserted)
-{
- dav_elem_private *priv = elem->priv;
-
- *inserted = DAV_PROP_INSERT_NOTDEF;
-
- if (priv->provider == NULL) {
- /* this is a "core" property that we define */
- return dav_insert_coreprop(propdb, priv->propid, elem->name,
- what, phdr, inserted);
- }
-
- /* ask the provider (that defined this prop) to insert the prop */
- *inserted = (*priv->provider->insert_prop)(propdb->resource, priv->propid,
- what, phdr);
-
- return NULL;
-}
-
-static void dav_output_prop_name(apr_pool_t *pool,
- const dav_prop_name *name,
- dav_xmlns_info *xi,
- apr_text_header *phdr)
-{
- const char *s;
-
- if (*name->ns == '\0')
- s = apr_psprintf(pool, "<%s/>" DEBUG_CR, name->name);
- else {
- const char *prefix = dav_xmlns_add_uri(xi, name->ns);
-
- s = apr_psprintf(pool, "<%s:%s/>" DEBUG_CR, prefix, name->name);
- }
-
- apr_text_append(pool, phdr, s);
-}
-
-static void dav_insert_xmlns(apr_pool_t *p, const char *pre_prefix, int ns,
- const char *ns_uri, apr_text_header *phdr)
-{
- const char *s;
-
- s = apr_psprintf(p, " xmlns:%s%d=\"%s\"", pre_prefix, ns, ns_uri);
- apr_text_append(p, phdr, s);
-}
-
-static dav_error *dav_really_open_db(dav_propdb *propdb, int ro)
-{
- dav_error *err;
-
- /* we're trying to open the db; turn off the 'deferred' flag */
- propdb->deferred = 0;
-
- /* ask the DB provider to open the thing */
- err = (*propdb->db_hooks->open)(propdb->p, propdb->resource, ro,
- &propdb->db);
- if (err != NULL) {
- return dav_push_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR,
- DAV_ERR_PROP_OPENING,
- "Could not open the property database.",
- err);
- }
-
- /*
- ** NOTE: propdb->db could be NULL if we attempted to open a readonly
- ** database that doesn't exist. If we require read/write
- ** access, then a database was created and opened.
- */
-
- return NULL;
-}
-
-DAV_DECLARE(dav_error *)dav_open_propdb(request_rec *r, dav_lockdb *lockdb,
- const dav_resource *resource,
- int ro,
- apr_array_header_t * ns_xlate,
- dav_propdb **p_propdb)
-{
- dav_propdb *propdb = apr_pcalloc(r->pool, sizeof(*propdb));
-
- *p_propdb = NULL;
-
-#if DAV_DEBUG
- if (resource->uri == NULL) {
- return dav_new_error(r->pool, HTTP_INTERNAL_SERVER_ERROR, 0,
- "INTERNAL DESIGN ERROR: resource must define "
- "its URI.");
- }
-#endif
-
- propdb->r = r;
- propdb->p = r->pool; /* ### get rid of this */
- propdb->resource = resource;
- propdb->ns_xlate = ns_xlate;
-
- propdb->db_hooks = DAV_GET_HOOKS_PROPDB(r);
-
- propdb->lockdb = lockdb;
-
- /* always defer actual open, to avoid expense of accessing db
- * when only live properties are involved
- */
- propdb->deferred = 1;
-
- /* ### what to do about closing the propdb on server failure? */
-
- *p_propdb = propdb;
- return NULL;
-}
-
-DAV_DECLARE(void) dav_close_propdb(dav_propdb *propdb)
-{
- if (propdb->db == NULL)
- return;
-
- (*propdb->db_hooks->close)(propdb->db);
-}
-
-DAV_DECLARE(dav_get_props_result) dav_get_allprops(dav_propdb *propdb,
- dav_prop_insert what)
-{
- const dav_hooks_db *db_hooks = propdb->db_hooks;
- apr_text_header hdr = { 0 };
- apr_text_header hdr_ns = { 0 };
- dav_get_props_result result = { 0 };
- int found_contenttype = 0;
- int found_contentlang = 0;
- dav_prop_insert unused_inserted;
-
- /* if not just getting supported live properties,
- * scan all properties in the dead prop database
- */
- if (what != DAV_PROP_INSERT_SUPPORTED) {
- if (propdb->deferred) {
- /* ### what to do with db open error? */
- (void) dav_really_open_db(propdb, 1 /*ro*/);
- }
-
- /* initialize the result with some start tags... */
- apr_text_append(propdb->p, &hdr,
- "<D:propstat>" DEBUG_CR
- "<D:prop>" DEBUG_CR);
-
- /* if there ARE properties, then scan them */
- if (propdb->db != NULL) {
- dav_xmlns_info *xi = dav_xmlns_create(propdb->p);
- dav_prop_name name;
-
- /* define (up front) any namespaces the db might need */
- (void) (*db_hooks->define_namespaces)(propdb->db, xi);
-
- /* get the first property name, beginning the scan */
- (void) (*db_hooks->first_name)(propdb->db, &name);
- while (name.ns != NULL) {
-
- /*
- ** We also look for <DAV:getcontenttype> and
- ** <DAV:getcontentlanguage>. If they are not stored as dead
- ** properties, then we need to perform a subrequest to get
- ** their values (if any).
- */
- if (*name.ns == 'D' && strcmp(name.ns, "DAV:") == 0
- && *name.name == 'g') {
- if (strcmp(name.name, "getcontenttype") == 0) {
- found_contenttype = 1;
- }
- else if (strcmp(name.name, "getcontentlanguage") == 0) {
- found_contentlang = 1;
- }
- }
-
- if (what == DAV_PROP_INSERT_VALUE) {
- dav_error *err;
- int found;
-
- if ((err = (*db_hooks->output_value)(propdb->db, &name,
- xi, &hdr,
- &found)) != NULL) {
- /* ### anything better to do? */
- /* ### probably should enter a 500 error */
- goto next_key;
- }
- /* assert: found == 1 */
- }
- else {
- /* the value was not requested, so just add an empty
- tag specifying the property name. */
- dav_output_prop_name(propdb->p, &name, xi, &hdr);
- }
-
- next_key:
- (void) (*db_hooks->next_name)(propdb->db, &name);
- }
-
- /* all namespaces have been entered into xi. generate them into
- the output now. */
- dav_xmlns_generate(xi, &hdr_ns);
-
- } /* propdb->db != NULL */
-
- /* add namespaces for all the liveprop providers */
- dav_add_all_liveprop_xmlns(propdb->p, &hdr_ns);
- }
-
- /* ask the liveprop providers to insert their properties */
- dav_run_insert_all_liveprops(propdb->r, propdb->resource, what, &hdr);
-
- /* insert the standard properties */
- /* ### should be handling the return errors here */
- (void)dav_insert_coreprop(propdb,
- DAV_PROPID_CORE_supportedlock, "supportedlock",
- what, &hdr, &unused_inserted);
- (void)dav_insert_coreprop(propdb,
- DAV_PROPID_CORE_lockdiscovery, "lockdiscovery",
- what, &hdr, &unused_inserted);
-
- /* if we didn't find these, then do the whole subreq thing. */
- if (!found_contenttype) {
- /* ### should be handling the return error here */
- (void)dav_insert_coreprop(propdb,
- DAV_PROPID_CORE_getcontenttype,
- "getcontenttype",
- what, &hdr, &unused_inserted);
- }
- if (!found_contentlang) {
- /* ### should be handling the return error here */
- (void)dav_insert_coreprop(propdb,
- DAV_PROPID_CORE_getcontentlanguage,
- "getcontentlanguage",
- what, &hdr, &unused_inserted);
- }
-
- /* if not just reporting on supported live props,
- * terminate the result */
- if (what != DAV_PROP_INSERT_SUPPORTED) {
- apr_text_append(propdb->p, &hdr,
- "</D:prop>" DEBUG_CR
- "<D:status>HTTP/1.1 200 OK</D:status>" DEBUG_CR
- "</D:propstat>" DEBUG_CR);
- }
-
- result.propstats = hdr.first;
- result.xmlns = hdr_ns.first;
- return result;
-}
-
-DAV_DECLARE(dav_get_props_result) dav_get_props(dav_propdb *propdb,
- apr_xml_doc *doc)
-{
- const dav_hooks_db *db_hooks = propdb->db_hooks;
- apr_xml_elem *elem = dav_find_child(doc->root, "prop");
- apr_text_header hdr_good = { 0 };
- apr_text_header hdr_bad = { 0 };
- apr_text_header hdr_ns = { 0 };
- int have_good = 0;
- dav_get_props_result result = { 0 };
- char *marks_liveprop;
- dav_xmlns_info *xi;
- int xi_filled = 0;
-
- /* ### NOTE: we should pass in TWO buffers -- one for keys, one for
- the marks */
-
- /* we will ALWAYS provide a "good" result, even if it is EMPTY */
- apr_text_append(propdb->p, &hdr_good,
- "<D:propstat>" DEBUG_CR
- "<D:prop>" DEBUG_CR);
-
- /* ### the marks should be in a buffer! */
- /* allocate zeroed-memory for the marks. These marks indicate which
- liveprop namespaces we've generated into the output xmlns buffer */
-
- /* same for the liveprops */
- marks_liveprop = apr_pcalloc(propdb->p, dav_get_liveprop_ns_count() + 1);
-
- xi = dav_xmlns_create(propdb->p);
-
- for (elem = elem->first_child; elem; elem = elem->next) {
- dav_elem_private *priv;
- dav_error *err;
- dav_prop_insert inserted;
- dav_prop_name name;
-
- /*
- ** First try live property providers; if they don't handle
- ** the property, then try looking it up in the propdb.
- */
-
- if (elem->priv == NULL) {
- elem->priv = apr_pcalloc(propdb->p, sizeof(*priv));
- }
- priv = elem->priv;
-
- /* cache the propid; dav_get_props() could be called many times */
- if (priv->propid == 0)
- dav_find_liveprop(propdb, elem);
-
- if (priv->propid != DAV_PROPID_CORE_UNKNOWN) {
-
- /* insert the property. returns 1 if an insertion was done. */
- if ((err = dav_insert_liveprop(propdb, elem, DAV_PROP_INSERT_VALUE,
- &hdr_good, &inserted)) != NULL) {
- /* ### need to propagate the error to the caller... */
- /* ### skip it for now, as if nothing was inserted */
- }
- if (inserted == DAV_PROP_INSERT_VALUE) {
- have_good = 1;
-
- /*
- ** Add the liveprop's namespace URIs. Note that provider==NULL
- ** for core properties.
- */
- if (priv->provider != NULL) {
- const char * const * scan_ns_uri;
-
- for (scan_ns_uri = priv->provider->namespace_uris;
- *scan_ns_uri != NULL;
- ++scan_ns_uri) {
- int ns;
-
- ns = dav_get_liveprop_ns_index(*scan_ns_uri);
- if (marks_liveprop[ns])
- continue;
- marks_liveprop[ns] = 1;
-
- dav_insert_xmlns(propdb->p, "lp", ns, *scan_ns_uri,
- &hdr_ns);
- }
- }
-
- /* property added. move on to the next property. */
- continue;
- }
- else if (inserted == DAV_PROP_INSERT_NOTDEF) {
- /* nothing to do. fall thru to allow property to be handled
- as a dead property */
- }
-#if DAV_DEBUG
- else {
-#if 0
- /* ### need to change signature to return an error */
- return dav_new_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR, 0,
- "INTERNAL DESIGN ERROR: insert_liveprop "
- "did not insert what was asked for.");
-#endif
- }
-#endif
- }
-
- /* The property wasn't a live property, so look in the dead property
- database. */
-
- /* make sure propdb is really open */
- if (propdb->deferred) {
- /* ### what to do with db open error? */
- (void) dav_really_open_db(propdb, 1 /*ro*/);
- }
-
- if (elem->ns == APR_XML_NS_NONE)
- name.ns = "";
- else
- name.ns = APR_XML_GET_URI_ITEM(propdb->ns_xlate, elem->ns);
- name.name = elem->name;
-
- /* only bother to look if a database exists */
- if (propdb->db != NULL) {
- int found;
-
- if ((err = (*db_hooks->output_value)(propdb->db, &name,
- xi, &hdr_good,
- &found)) != NULL) {
- /* ### what to do? continue doesn't seem right... */
- continue;
- }
-
- if (found) {
- have_good = 1;
-
- /* if we haven't added the db's namespaces, then do so... */
- if (!xi_filled) {
- (void) (*db_hooks->define_namespaces)(propdb->db, xi);
- xi_filled = 1;
- }
- continue;
- }
- }
-
- /* not found as a live OR dead property. add a record to the "bad"
- propstats */
-
- /* make sure we've started our "bad" propstat */
- if (hdr_bad.first == NULL) {
- apr_text_append(propdb->p, &hdr_bad,
- "<D:propstat>" DEBUG_CR
- "<D:prop>" DEBUG_CR);
- }
-
- /* output this property's name (into the bad propstats) */
- dav_output_prop_name(propdb->p, &name, xi, &hdr_bad);
- }
-
- apr_text_append(propdb->p, &hdr_good,
- "</D:prop>" DEBUG_CR
- "<D:status>HTTP/1.1 200 OK</D:status>" DEBUG_CR
- "</D:propstat>" DEBUG_CR);
-
- /* default to start with the good */
- result.propstats = hdr_good.first;
-
- /* we may not have any "bad" results */
- if (hdr_bad.first != NULL) {
- /* "close" the bad propstat */
- apr_text_append(propdb->p, &hdr_bad,
- "</D:prop>" DEBUG_CR
- "<D:status>HTTP/1.1 404 Not Found</D:status>" DEBUG_CR
- "</D:propstat>" DEBUG_CR);
-
- /* if there are no good props, then just return the bad */
- if (!have_good) {
- result.propstats = hdr_bad.first;
- }
- else {
- /* hook the bad propstat to the end of the good one */
- hdr_good.last->next = hdr_bad.first;
- }
- }
-
- /* add in all the various namespaces, and return them */
- dav_xmlns_generate(xi, &hdr_ns);
- result.xmlns = hdr_ns.first;
-
- return result;
-}
-
-DAV_DECLARE(void) dav_get_liveprop_supported(dav_propdb *propdb,
- const char *ns_uri,
- const char *propname,
- apr_text_header *body)
-{
- int propid;
- const dav_hooks_liveprop *hooks;
-
- propid = dav_find_liveprop_provider(propdb, ns_uri, propname, &hooks);
-
- if (propid != DAV_PROPID_CORE_UNKNOWN) {
- if (hooks == NULL) {
- /* this is a "core" property that we define */
- dav_prop_insert unused_inserted;
- dav_insert_coreprop(propdb, propid, propname,
- DAV_PROP_INSERT_SUPPORTED, body, &unused_inserted);
- }
- else {
- (*hooks->insert_prop)(propdb->resource, propid,
- DAV_PROP_INSERT_SUPPORTED, body);
- }
- }
-}
-
-DAV_DECLARE_NONSTD(void) dav_prop_validate(dav_prop_ctx *ctx)
-{
- dav_propdb *propdb = ctx->propdb;
- apr_xml_elem *prop = ctx->prop;
- dav_elem_private *priv;
-
- priv = ctx->prop->priv = apr_pcalloc(propdb->p, sizeof(*priv));
-
- /*
- ** Check to see if this is a live property, and fill the fields
- ** in the XML elem, as appropriate.
- **
- ** Verify that the property is read/write. If not, then it cannot
- ** be SET or DELETEd.
- */
- if (priv->propid == 0) {
- dav_find_liveprop(propdb, prop);
-
- /* it's a liveprop if a provider was found */
- /* ### actually the "core" props should really be liveprops, but
- ### there is no "provider" for those and the r/w props are
- ### treated as dead props anyhow */
- ctx->is_liveprop = priv->provider != NULL;
- }
-
- if (!dav_rw_liveprop(propdb, priv)) {
- ctx->err = dav_new_error(propdb->p, HTTP_CONFLICT,
- DAV_ERR_PROP_READONLY,
- "Property is read-only.");
- return;
- }
-
- if (ctx->is_liveprop) {
- int defer_to_dead = 0;
-
- ctx->err = (*priv->provider->patch_validate)(propdb->resource,
- prop, ctx->operation,
- &ctx->liveprop_ctx,
- &defer_to_dead);
- if (ctx->err != NULL || !defer_to_dead)
- return;
-
- /* clear is_liveprop -- act as a dead prop now */
- ctx->is_liveprop = 0;
- }
-
- /*
- ** The property is supposed to be stored into the dead-property
- ** database. Make sure the thing is truly open (and writable).
- */
- if (propdb->deferred
- && (ctx->err = dav_really_open_db(propdb, 0 /* ro */)) != NULL) {
- return;
- }
-
- /*
- ** There should be an open, writable database in here!
- **
- ** Note: the database would be NULL if it was opened readonly and it
- ** did not exist.
- */
- if (propdb->db == NULL) {
- ctx->err = dav_new_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR,
- DAV_ERR_PROP_NO_DATABASE,
- "Attempted to set/remove a property "
- "without a valid, open, read/write "
- "property database.");
- return;
- }
-
- if (ctx->operation == DAV_PROP_OP_SET) {
- /*
- ** Prep the element => propdb namespace index mapping, inserting
- ** namespace URIs into the propdb that don't exist.
- */
- (void) (*propdb->db_hooks->map_namespaces)(propdb->db,
- propdb->ns_xlate,
- &propdb->mapping);
- }
- else if (ctx->operation == DAV_PROP_OP_DELETE) {
- /*
- ** There are no checks to perform here. If a property exists, then
- ** we will delete it. If it does not exist, then it does not matter
- ** (see S12.13.1).
- **
- ** Note that if a property does not exist, that does not rule out
- ** that a SET will occur during this PROPPATCH (thusly creating it).
- */
- }
-}
-
-DAV_DECLARE_NONSTD(void) dav_prop_exec(dav_prop_ctx *ctx)
-{
- dav_propdb *propdb = ctx->propdb;
- dav_error *err = NULL;
- dav_elem_private *priv = ctx->prop->priv;
-
- ctx->rollback = apr_pcalloc(propdb->p, sizeof(*ctx->rollback));
-
- if (ctx->is_liveprop) {
- err = (*priv->provider->patch_exec)(propdb->resource,
- ctx->prop, ctx->operation,
- ctx->liveprop_ctx,
- &ctx->rollback->liveprop);
- }
- else {
- dav_prop_name name;
-
- if (ctx->prop->ns == APR_XML_NS_NONE)
- name.ns = "";
- else
- name.ns = APR_XML_GET_URI_ITEM(propdb->ns_xlate, ctx->prop->ns);
- name.name = ctx->prop->name;
-
- /* save the old value so that we can do a rollback. */
- if ((err = (*propdb->db_hooks
- ->get_rollback)(propdb->db, &name,
- &ctx->rollback->deadprop)) != NULL)
- goto error;
-
- if (ctx->operation == DAV_PROP_OP_SET) {
-
- /* Note: propdb->mapping was set in dav_prop_validate() */
- err = (*propdb->db_hooks->store)(propdb->db, &name, ctx->prop,
- propdb->mapping);
-
- /*
- ** If an error occurred, then assume that we didn't change the
- ** value. Remove the rollback item so that we don't try to set
- ** its value during the rollback.
- */
- /* ### euh... where is the removal? */
- }
- else if (ctx->operation == DAV_PROP_OP_DELETE) {
-
- /*
- ** Delete the property. Ignore errors -- the property is there, or
- ** we are deleting it for a second time.
- */
- /* ### but what about other errors? */
- (void) (*propdb->db_hooks->remove)(propdb->db, &name);
- }
- }
-
- error:
- /* push a more specific error here */
- if (err != NULL) {
- /*
- ** Use HTTP_INTERNAL_SERVER_ERROR because we shouldn't have seen
- ** any errors at this point.
- */
- ctx->err = dav_push_error(propdb->p, HTTP_INTERNAL_SERVER_ERROR,
- DAV_ERR_PROP_EXEC,
- "Could not execute PROPPATCH.", err);
- }
-}
-
-DAV_DECLARE_NONSTD(void) dav_prop_commit(dav_prop_ctx *ctx)
-{
- dav_elem_private *priv = ctx->prop->priv;
-
- /*
- ** Note that a commit implies ctx->err is NULL. The caller should assume
- ** a status of HTTP_OK for this case.
- */
-
- if (ctx->is_liveprop) {
- (*priv->provider->patch_commit)(ctx->propdb->resource,
- ctx->operation,
- ctx->liveprop_ctx,
- ctx->rollback->liveprop);
- }
-}
-
-DAV_DECLARE_NONSTD(void) dav_prop_rollback(dav_prop_ctx *ctx)
-{
- dav_error *err = NULL;
- dav_elem_private *priv = ctx->prop->priv;
-
- /* do nothing if there is no rollback information. */
- if (ctx->rollback == NULL)
- return;
-
- /*
- ** ### if we have an error, and a rollback occurs, then the namespace
- ** ### mods should not happen at all. Basically, the namespace management
- ** ### is simply a bitch.
- */
-
- if (ctx->is_liveprop) {
- err = (*priv->provider->patch_rollback)(ctx->propdb->resource,
- ctx->operation,
- ctx->liveprop_ctx,
- ctx->rollback->liveprop);
- }
- else {
- err = (*ctx->propdb->db_hooks
- ->apply_rollback)(ctx->propdb->db, ctx->rollback->deadprop);
- }
-
- if (err != NULL) {
- if (ctx->err == NULL)
- ctx->err = err;
- else {
- dav_error *scan = err;
-
- /* hook previous errors at the end of the rollback error */
- while (scan->prev != NULL)
- scan = scan->prev;
- scan->prev = ctx->err;
- ctx->err = err;
- }
- }
-}