📄 props.c
字号:
/* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2000-2001 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. *//*** 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_GDBM_NS_KEY "METADATA"#define DAV_GDBM_NS_KEY_LEN 8#define DAV_EMPTY_VALUE "\0" /* TWO null terms *//* the namespace URI was not found; no ID is available */#define AP_XML_NS_ERROR_NOT_FOUND (AP_XML_NS_ERROR_BASE)typedef struct { unsigned char major;#define DAV_DBVSN_MAJOR 4 /* ** V4 -- 0.9.9 .. ** Prior versions could have keys or values with invalid ** namespace prefixes as a result of the xmlns="" form not ** resetting the default namespace to be "no namespace". The ** namespace would be set to "" which is invalid; it should ** be set to "no namespace". ** ** V3 -- 0.9.8 ** Prior versions could have values with invalid namespace ** prefixes due to an incorrect mapping of input to propdb ** namespace indices. Version bumped to obsolete the old ** values. ** ** V2 -- 0.9.7 ** This introduced the xml:lang value into the property value's ** record in the propdb. ** ** V1 -- .. 0.9.6 ** Initial version. */ unsigned char minor;#define DAV_DBVSN_MINOR 0 short ns_count;} dav_propdb_metadata;struct dav_propdb { int version; /* *minor* version of this db */ 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 */ dav_buffer ns_table; /* table of namespace URIs */ short ns_count; /* number of entries in table */ int ns_table_dirty; /* ns_table was modified */ apr_array_header_t *ns_xlate; /* translation of an elem->ns to URI */ int *ns_map; /* map elem->ns to propdb ns values */ int incomplete_map; /* some mappings do not exist */ dav_lockdb *lockdb; /* the lock database */ dav_buffer wb_key; /* work buffer for dav_gdbm_key */ 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.** If a SET was performed and no prior value existed, then value.dptr** will be NULL.*/typedef struct dav_rollback_item { dav_datum key; /* key for the item being saved */ dav_datum value; /* value before set/replace/delete */ /* or use the following (choice selected by dav_prop_ctx.is_liveprop) */ struct dav_liveprop_rollback *liveprop; /* liveprop rollback ctx */} dav_rollback_item;#if 0/* ### unused */static const char *dav_get_ns_table_uri(dav_propdb *propdb, int ns){ const char *p = propdb->ns_table.buf + sizeof(dav_propdb_metadata); while (ns--) p += strlen(p) + 1; return p;}#endifstatic 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; } else 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; } /* didn't find it. fall thru. a provider can define DAV: props */ } /* is there a liveprop provider for this property? */ propid = dav_run_find_liveprop(propdb->resource, ns_uri, propname, provider); if (propid != 0) { return propid; } /* no provider for this property */ return DAV_PROPID_CORE_UNKNOWN;}static void dav_find_liveprop(dav_propdb *propdb, ap_xml_elem *elem){ const char *ns_uri; dav_elem_private *priv = elem->private; const dav_hooks_liveprop *hooks; if (elem->ns == AP_XML_NS_NONE) ns_uri = NULL; else if (elem->ns == AP_XML_NS_DAV_ID) ns_uri = "DAV:"; else ns_uri = AP_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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -