]> granicus.if.org Git - apache/blobdiff - modules/dav/main/mod_dav.h
Update copyright to 2001
[apache] / modules / dav / main / mod_dav.h
index d4dab1ca3a840c6522c81dc2f9629b4936b00108..097663b3e26f87fff1c47c1386c2f5aad2c6edcb 100644 (file)
@@ -1,7 +1,7 @@
 /* ====================================================================
  * The Apache Software License, Version 1.1
  *
- * Copyright (c) 2000 The Apache Software Foundation.  All rights
+ * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
  * reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #ifndef _MOD_DAV_H_
 #define _MOD_DAV_H_
 
+#include "apr_hooks.h"
+#include "apr_hash.h"
+#include "apr_dbm.h"
+#include "apr_tables.h"
+
+#include "httpd.h"
+#include "util_xml.h"
+
+#include <limits.h>     /* for INT_MAX */
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-#include "httpd.h"
-
 
-#define DAV_VERSION            "1.0.1"
+#define DAV_VERSION            AP_SERVER_BASEREVISION
 
 #define DAV_XML_HEADER         "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
 #define DAV_XML_CONTENT_TYPE   "text/xml; charset=\"utf-8\""
 
 #define DAV_READ_BLOCKSIZE     2048    /* used for reading input blocks */
 
-#ifdef WIN32
-#include <limits.h>
-typedef int ssize_t;
-#endif /* WIN32 */
-
 #define DAV_RESPONSE_BODY_1    "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<HTML><HEAD>\n<TITLE>"
 #define DAV_RESPONSE_BODY_2    "</TITLE>\n</HEAD><BODY>\n<H1>"
 #define DAV_RESPONSE_BODY_3    "</H1>\n"
@@ -91,13 +94,13 @@ typedef int ssize_t;
 #define DAV_DEBUG 1
 #define DEBUG_CR       "\n"
 #define DBG0(f)                ap_log_error(APLOG_MARK, \
-                               APLOG_ERR|APLOG_NOERRNO, NULL, (f))
+                               APLOG_ERR|APLOG_NOERRNO, 0, NULL, (f))
 #define DBG1(f,a1)     ap_log_error(APLOG_MARK, \
-                               APLOG_ERR|APLOG_NOERRNO, NULL, f, a1)
+                               APLOG_ERR|APLOG_NOERRNO, 0, NULL, f, a1)
 #define DBG2(f,a1,a2)  ap_log_error(APLOG_MARK, \
-                               APLOG_ERR|APLOG_NOERRNO, NULL, f, a1, a2)
+                               APLOG_ERR|APLOG_NOERRNO, 0, NULL, f, a1, a2)
 #define DBG3(f,a1,a2,a3) ap_log_error(APLOG_MARK, \
-                               APLOG_ERR|APLOG_NOERRNO, NULL, f, a1, a2, a3)
+                              APLOG_ERR|APLOG_NOERRNO, 0, NULL, f, a1, a2, a3)
 #else
 #undef DAV_DEBUG
 #define DEBUG_CR       ""
@@ -105,6 +108,26 @@ typedef int ssize_t;
 
 #define DAV_INFINITY   INT_MAX /* for the Depth: header */
 
+/* Create a set of DAV_DECLARE(type), DAV_DECLARE_NONSTD(type) and 
+ * DAV_DECLARE_DATA with appropriate export and import tags for the platform
+ */
+#if !defined(WIN32)
+#define DAV_DECLARE(type)            type
+#define DAV_DECLARE_NONSTD(type)     type
+#define DAV_DECLARE_DATA
+#elif defined(DAV_DECLARE_STATIC)
+#define DAV_DECLARE(type)            type __stdcall
+#define DAV_DECLARE_NONSTD(type)     type
+#define DAV_DECLARE_DATA
+#elif defined(DAV_DECLARE_EXPORT)
+#define DAV_DECLARE(type)            __declspec(dllexport) type __stdcall
+#define DAV_DECLARE_NONSTD(type)     __declspec(dllexport) type
+#define DAV_DECLARE_DATA             __declspec(dllexport)
+#else
+#define DAV_DECLARE(type)            __declspec(dllimport) type __stdcall
+#define DAV_DECLARE_NONSTD(type)     __declspec(dllimport) type
+#define DAV_DECLARE_DATA             __declspec(dllimport)
+#endif
 
 /* --------------------------------------------------------------------
 **
@@ -135,7 +158,7 @@ typedef struct dav_error {
     struct dav_error *prev;    /* previous error (in stack) */
 
     /* deferred computation of the description */
-    void (*compute_desc)(struct dav_error *err, ap_pool_t *p);
+    void (*compute_desc)(struct dav_error *err, apr_pool_t *p);
     int ctx_i;
     const char *ctx_s;
     void *ctx_p;
@@ -146,7 +169,8 @@ typedef struct dav_error {
 ** Create a new error structure. save_errno will be filled with the current
 ** errno value.
 */
-dav_error *dav_new_error(ap_pool_t *p, int status, int error_id, const char *desc);
+DAV_DECLARE(dav_error*) dav_new_error(apr_pool_t *p, int status, 
+                                      int error_id, const char *desc);
 
 /*
 ** Push a new error description onto the stack of errors.
@@ -161,8 +185,8 @@ dav_error *dav_new_error(ap_pool_t *p, int status, int error_id, const char *des
 ** <error_id> can specify a new error_id since the topmost description has
 ** changed.
 */
-dav_error *dav_push_error(ap_pool_t *p, int status, int error_id, const char *desc,
-                         dav_error *prev);
+DAV_DECLARE(dav_error*) dav_push_error(apr_pool_t *p, int status, int error_id,
+                                       const char *desc, dav_error *prev);
 
 
 /* error ID values... */
@@ -178,7 +202,7 @@ dav_error *dav_push_error(ap_pool_t *p, int status, int error_id, const char *de
 /* Prop DB errors */
 #define DAV_ERR_PROP_BAD_MAJOR         200     /* major version was wrong */
 #define DAV_ERR_PROP_READONLY          201     /* prop is read-only */
-#define DAV_ERR_PROP_NO_DATABASE       202     /* writeable db not avail */
+#define DAV_ERR_PROP_NO_DATABASE       202     /* writable db not avail */
 #define DAV_ERR_PROP_NOT_FOUND         203     /* prop not found */
 #define DAV_ERR_PROP_BAD_LOCKDB                204     /* could not open lockdb */
 #define DAV_ERR_PROP_OPENING           205     /* problem opening propdb */
@@ -226,11 +250,15 @@ dav_error *dav_push_error(ap_pool_t *p, int status, int error_id, const char *de
 */
 
 /* forward-declare this structure */
-typedef struct dav_hooks_db dav_hooks_db;
+typedef struct dav_hooks_propdb dav_hooks_propdb;
 typedef struct dav_hooks_locks dav_hooks_locks;
 typedef struct dav_hooks_vsn dav_hooks_vsn;
 typedef struct dav_hooks_repository dav_hooks_repository;
 typedef struct dav_hooks_liveprop dav_hooks_liveprop;
+typedef struct dav_hooks_binding dav_hooks_binding;
+
+/* ### deprecated name */
+typedef dav_hooks_propdb dav_hooks_db;
 
 
 /* --------------------------------------------------------------------
@@ -243,15 +271,32 @@ typedef struct dav_hooks_liveprop dav_hooks_liveprop;
 ** The base protocol defines only file and collection resources.
 ** The versioning protocol defines several additional resource types
 ** to represent artifacts of a version control system.
+**
+** This enumeration identifies the type of URL used to identify the
+** resource. Since the same resource may have more than one type of
+** URL which can identify it, dav_resource_type cannot be used
+** alone to determine the type of the resource; attributes of the
+** dav_resource object must also be consulted.
 */
 typedef enum {
-    DAV_RESOURCE_TYPE_REGULAR,      /* file or collection, working resource
-                                      or revision */
-    DAV_RESOURCE_TYPE_REVISION,     /* explicit revision-id */
-    DAV_RESOURCE_TYPE_HISTORY,      /* explicit history-id */
-    DAV_RESOURCE_TYPE_WORKSPACE,    /* workspace */
-    DAV_RESOURCE_TYPE_ACTIVITY,     /* activity */
-    DAV_RESOURCE_TYPE_CONFIGURATION /* configuration */
+    DAV_RESOURCE_TYPE_UNKNOWN,
+
+    DAV_RESOURCE_TYPE_REGULAR,          /* file or collection; could be
+                                         * unversioned, or version selector,
+                                         * or baseline selector */
+
+    DAV_RESOURCE_TYPE_VERSION,          /* version or baseline URL */
+
+    DAV_RESOURCE_TYPE_HISTORY,          /* version or baseline history URL */
+
+    DAV_RESOURCE_TYPE_WORKING,          /* working resource URL */
+
+    DAV_RESOURCE_TYPE_WORKSPACE,        /* workspace URL */
+
+    DAV_RESOURCE_TYPE_ACTIVITY,         /* activity URL */
+
+    DAV_RESOURCE_TYPE_PRIVATE           /* repository-private type */
+
 } dav_resource_type;
 
 /*
@@ -259,26 +304,103 @@ typedef enum {
 */
 typedef struct dav_resource_private dav_resource_private;
 
-/* Resource descriptor, generated by a repository provider.
- * Note: the lock-null state is not explicitly represented here,
- * since it may be expensive to compute. Use dav_get_resource_state()
- * to determine whether a non-existent resource is a lock-null resource.
- */
+/*
+** Resource descriptor, generated by a repository provider.
+**
+** Note: the lock-null state is not explicitly represented here,
+** since it may be expensive to compute. Use dav_get_resource_state()
+** to determine whether a non-existent resource is a lock-null resource.
+**
+** A quick explanation of how the flags can apply to different resources:
+**
+** unversioned file or collection:
+**     type       = DAV_RESOURCE_TYPE_REGULAR
+**     exists     = ? (1 if exists)
+**     collection = ? (1 if collection)
+**     versioned  = 0
+**     baselined  = 0
+**     working    = 0
+**
+** version/baseline selector:
+**     type       = DAV_RESOURCE_TYPE_REGULAR
+**     exists     = 1
+**     collection = ? (1 if collection)
+**     versioned  = 1
+**     baselined  = ? (1 if baseline selector)
+**     working    = ? (1 if checked out)
+**
+** version/baseline history:
+**     type       = DAV_RESOURCE_TYPE_HISTORY
+**     exists     = 1
+**     collection = 0
+**     versioned  = 0
+**     baselined  = 0
+**     working    = 0
+**
+** version/baseline:
+**     type       = DAV_RESOURCE_TYPE_VERSION
+**     exists     = 1
+**     collection = ? (1 if collection)
+**     versioned  = 1
+**     baselined  = ? (1 if baseline)
+**     working    = 0
+**
+** working resource:
+**     type       = DAV_RESOURCE_TYPE_WORKING
+**     exists     = 1
+**     collection = ? (1 if collection)
+**     versioned  = 1
+**     baselined  = 0
+**     working    = 1
+**
+** workspace:
+**     type       = DAV_RESOURCE_TYPE_WORKSPACE
+**     exists     = ? (1 if exists)
+**     collection = 1
+**     versioned  = * (jvasta: I'm seeking clarification on whether a
+**     baselined  = *  workspace can be versioned or baselined)
+**     working    = *
+**
+** activity:
+**     type       = DAV_RESOURCE_TYPE_ACTIVITY
+**     exists     = ? (1 if exists)
+**     collection = 0
+**     versioned  = 0
+**     baselined  = 0
+**     working    = 0
+*/
 typedef struct dav_resource {
     dav_resource_type type;
 
     int exists;                /* 0 => null resource */
-    int collection;    /* 0 => file (if type == DAV_RESOURCE_TYPE_REGULAR) */
-    int versioned;     /* 0 => unversioned */
-    int working;       /* 0 => revision (if versioned) */
-    int baselined;     /* 0 => not baselined */
+
+    int collection;    /* 0 => file; can be 1 for
+                         * REGULAR, VERSION, and WORKING resources,
+                         * and is always 1 for WORKSPACE */
+
+    int versioned;     /* 0 => unversioned; can be 1 for
+                         * REGULAR and WORKSPACE resources,
+                         * and is always 1 for VERSION and WORKING */
+
+    int baselined;      /* 0 => not baselined; can be 1 for
+                         * REGULAR and VERSION resources;
+                         * versioned == 1 when baselined == 1 */
+
+    int working;       /* 0 => not checked out; can be 1 for
+                         * REGULAR and WORKSPACE resources,
+                         * and is always 1 for WORKING */
 
     const char *uri;   /* the URI for this resource */
 
-    dav_resource_private *info;
+    dav_resource_private *info;         /* the provider's private info */
 
     const dav_hooks_repository *hooks; /* hooks used for this resource */
 
+    /* When allocating items related specifically to this resource, the
+       following pool should be used. Its lifetime will be at least as
+       long as the dav_resource structure. */
+    apr_pool_t *pool;
+
 } dav_resource;
 
 /*
@@ -301,31 +423,37 @@ typedef struct dav_locktoken dav_locktoken;
 /* buffer for reuse; can grow to accomodate needed size */
 typedef struct
 {
-    size_t alloc_len;  /* how much has been allocated */
-    size_t cur_len;    /* how much is currently being used */
-    char *buf;         /* buffer contents */
+    apr_size_t alloc_len;      /* how much has been allocated */
+    apr_size_t cur_len;                /* how much is currently being used */
+    char *buf;                 /* buffer contents */
 } dav_buffer;
 #define DAV_BUFFER_MINSIZE     256     /* minimum size for buffer */
 #define DAV_BUFFER_PAD         64      /* amount of pad when growing */
 
 /* set the cur_len to the given size and ensure space is available */
-void dav_set_bufsize(ap_pool_t *p, dav_buffer *pbuf, size_t size);
+DAV_DECLARE(void) dav_set_bufsize(apr_pool_t *p, dav_buffer *pbuf, 
+                                  apr_size_t size);
 
 /* initialize a buffer and copy the specified (null-term'd) string into it */
-void dav_buffer_init(ap_pool_t *p, dav_buffer *pbuf, const char *str);
+DAV_DECLARE(void) dav_buffer_init(apr_pool_t *p, dav_buffer *pbuf, 
+                                  const char *str);
 
 /* check that the buffer can accomodate <extra_needed> more bytes */
-void dav_check_bufsize(ap_pool_t *p, dav_buffer *pbuf, size_t extra_needed);
+DAV_DECLARE(void) dav_check_bufsize(apr_pool_t *p, dav_buffer *pbuf, 
+                                    apr_size_t extra_needed);
 
 /* append a string to the end of the buffer, adjust length */
-void dav_buffer_append(ap_pool_t *p, dav_buffer *pbuf, const char *str);
+DAV_DECLARE(void) dav_buffer_append(apr_pool_t *p, dav_buffer *pbuf, 
+                                    const char *str);
 
 /* place a string on the end of the buffer, do NOT adjust length */
-void dav_buffer_place(ap_pool_t *p, dav_buffer *pbuf, const char *str);
+DAV_DECLARE(void) dav_buffer_place(apr_pool_t *p, dav_buffer *pbuf, 
+                                   const char *str);
 
 /* place some memory on the end of a buffer; do NOT adjust length */
-void dav_buffer_place_mem(ap_pool_t *p, dav_buffer *pbuf, const void *mem,
-                          size_t amt, size_t pad);
+DAV_DECLARE(void) dav_buffer_place_mem(apr_pool_t *p, dav_buffer *pbuf, 
+                                       const void *mem, apr_size_t amt, 
+                                       apr_size_t pad);
 
 
 /* --------------------------------------------------------------------
@@ -333,24 +461,11 @@ void dav_buffer_place_mem(ap_pool_t *p, dav_buffer *pbuf, const void *mem,
 ** HANDY UTILITIES
 */
 
-/* simple strutures to keep a linked list of pieces of text */
-typedef struct dav_text
-{
-    const char *text;
-    struct dav_text *next;
-} dav_text;
-
-typedef struct
-{
-    dav_text *first;
-    dav_text *last;
-} dav_text_header;
-
 /* contains results from one of the getprop functions */
 typedef struct
 {
-    dav_text * propstats;      /* <propstat> element text */
-    dav_text * xmlns;          /* namespace decls for <response> elem */
+    ap_text * propstats;       /* <propstat> element text */
+    ap_text * xmlns;           /* namespace decls for <response> elem */
 } dav_get_props_result;
 
 /* holds the contents of a <response> element */
@@ -374,10 +489,28 @@ typedef struct
 } dav_lookup_result;
 
 
-void dav_text_append(ap_pool_t *p, dav_text_header *hdr, const char *text);
-
 dav_lookup_result dav_lookup_uri(const char *uri, request_rec *r);
 
+/* defines type of property info a provider is to return */
+typedef enum {
+    DAV_PROP_INSERT_NOTDEF,    /* property is defined by this provider,
+                                  but nothing was inserted because the
+                                  (live) property is not defined for this
+                                  resource (it may be present as a dead
+                                  property). */
+    DAV_PROP_INSERT_NOTSUPP,    /* property is recognized by this provider,
+                                   but it is not supported, and cannot be
+                                   treated as a dead property */
+    DAV_PROP_INSERT_NAME,      /* a property name (empty elem) was
+                                  inserted into the text block */
+    DAV_PROP_INSERT_VALUE,     /* a property name/value pair was inserted
+                                  into the text block */
+    DAV_PROP_INSERT_SUPPORTED   /* a supported live property was added to
+                                   the text block as a
+                                   <DAV:supported-live-property> element */
+} dav_prop_insert;
+
+/* ### this stuff is private to dav/fs/repos.c; move it... */
 /* format a time string (buf must be at least DAV_TIMEBUF_SIZE chars) */
 #define DAV_STYLE_ISO8601      1
 #define DAV_STYLE_RFC822       2
@@ -385,180 +518,108 @@ dav_lookup_result dav_lookup_uri(const char *uri, request_rec *r);
 
 int dav_get_depth(request_rec *r, int def_depth);
 
+int dav_validate_root(const ap_xml_doc *doc, const char *tagname);
+ap_xml_elem *dav_find_child(const ap_xml_elem *elem, const char *tagname);
 
-/* --------------------------------------------------------------------
-**
-** DYNAMIC EXTENSIONS
-*/
-
-/* ### docco goes here... */
-
-
-/*
-** This structure is used to define the runtime, per-directory/location
-** operating context for a single provider.
-*/
-typedef struct
-{
-    int id;            /* provider ID */
-
-    void *m_context;   /* module-level context (i.e. managed globals) */
-
-    void *d_context;   /* per-directory context */
-    ap_table_t *d_params;      /* per-directory DAV config parameters */
+/* gather up all the CDATA into a single string */
+const char *dav_xml_get_cdata(const ap_xml_elem *elem, apr_pool_t *pool,
+                              int strip_white);
 
-    int *ns_map;       /* for LIVEPROP, map provider URI to global URI */
 
-} dav_dyn_context;
-
-/*
-** This structure is used to specify a set of hooks and its associated
-** context, on a per-directory/location basis.
+/* --------------------------------------------------------------------
 **
-** Note: the context is assembled from various sources. dav_dyn_hooks
-** structures will typically have the same pointer values within the
-** context (e.g. ctx.m_context is shared across all providers in a module).
+** DAV PLUGINS
 */
-typedef struct dav_dyn_hooks
-{
-    dav_dyn_context ctx;       /* context for this set of hooks */
-    const void *hooks;         /* the type-specific hooks */
-
-    struct dav_dyn_hooks *next;        /* next set of hooks, if applicable */
 
-} dav_dyn_hooks;
+/* ### docco ... */
 
 /*
-** These enumerated values define the different types of functionality that
-** a provider can implement.
+** dav_provider
+**
+** This structure wraps up all of the hooks that a mod_dav provider can
+** supply. The provider MUST supply <repos> and <propdb>. The rest are
+** optional and should contain NULL if that feature is not supplied.
+**
+** Note that a provider cannot pick and choose portions. There are too many
+** dependencies between a dav_resource (defined by <repos>) and the other
+** functionality.
+**
+** Live properties are not part of the dav_provider structure because they
+** are handled through the APR_HOOK interface (to allow for multiple liveprop
+** providers). The core always provides some properties, and then a given
+** provider will add more properties.
 */
-enum
-{
-    DAV_DYN_TYPE_SENTINEL,
+typedef struct {
+    const dav_hooks_repository *repos;
+    const dav_hooks_propdb *propdb;
+    const dav_hooks_locks *locks;
+    const dav_hooks_vsn *vsn;
+    const dav_hooks_binding *binding;
 
-    DAV_DYN_TYPE_PROPDB,       /* property database (1 per dir) */
-    DAV_DYN_TYPE_LOCKS,                /* lock handling (1 per dir) */
-    DAV_DYN_TYPE_QUERY_GRAMMAR,        /* DASL search grammar (N per dir) */
-    DAV_DYN_TYPE_ACL,          /* ACL handling (1 per dir) */
-    DAV_DYN_TYPE_VSN,          /* versioning (1 per dir) */
-    DAV_DYN_TYPE_REPOSITORY,   /* resource repository (1 per dir) */
-    DAV_DYN_TYPE_LIVEPROP,     /* live property handler (N per dir) */
-
-    DAV_DYN_TYPE_MAX
-};
+} dav_provider;
 
 /*
-** This structure defines a provider for a particular type of functionality.
-**
-** The ID is private to a provider and can be used to differentiate between
-** different subclasses of functionality which are implemented using the
-** same set of hooks. For example, a hook function could perform two entirely
-** different operations based on the ID which is passed.
+** gather_propsets: gather all live property propset-URIs
 **
-** is_active() is used by the system to determine whether a particular
-** provider is "active" for the given context. It is possible that a provider
-** is configured for a directory, but has not been enabled -- the is_active()
-** function is used to determine that information.
+** The hook implementor should push one or more URIs into the specified
+** array. These URIs are returned in the DAV: header to let clients know
+** what sets of live properties are supported by the installation. mod_dav
+** will place open/close angle brackets around each value (much like
+** a Coded-URL); quotes and brackets should not be in the value.
 **
-** ### is_active is not used right now
+** Example:    http://apache.org/dav/props/
 **
-** Note: dav_dyn_provider structures are always treated as "const" by mod_dav.
+** (of course, use your own domain to ensure a unique value)
 */
-typedef struct dav_dyn_provider
-{
-    int id;                    /* provider ID */
-
-    int type;                  /* provider's functionality type */
-    const void *hooks;         /* pointer to type-specific hooks */
-
-    int (*is_active)(dav_dyn_context *ctx, int id);
-
-} dav_dyn_provider;
-
-#define DAV_DYN_END_MARKER     { 0, DAV_DYN_TYPE_SENTINEL, NULL, NULL }
+APR_DECLARE_EXTERNAL_HOOK(dav, DAV, void, gather_propsets, 
+                         (apr_array_header_t *uris))
 
 /*
-** This structure defines a module (a set of providers).
-**
-** The friendly name should be a single word. It is used with the "DAV"
-** directive to specify the module to use for a particular directory/location.
+** find_liveprop: find a live property, returning a non-zero, unique,
+**                opaque identifier.
 **
-** The module_open/close functions are used to initialize per-module "global"
-** data. The functions are expected to update ctx->m_context.
+** If the hook implementor determines the specified URI/name refers to
+** one of its properties, then it should fill in HOOKS and return a
+** non-zero value. The returned value is the "property ID" and will
+** be passed to the various liveprop hook functions.
 **
-** ### module_open/close are not used at the moment
-** ### dir_* are not well-defined, nor are they used
+** Return 0 if the property is not defined by the hook implementor.
+*/
+APR_DECLARE_EXTERNAL_HOOK(dav, DAV, int, find_liveprop,
+                         (const dav_resource *resource,
+                          const char *ns_uri, const char *name,
+                          const dav_hooks_liveprop **hooks))
+
+/*
+** insert_all_liveprops: insert all (known) live property names/values.
 **
-** Note: The DAV_DYN_VERSION specifies the version of the dav_dyn_module
-**       structure itself. It will be updated if changes in the structure
-**       are made. There are no provisions for forward or backward
-**       compatible changes.
+** The hook implementor should append XML text to PHDR, containing liveprop
+** names. If INSVALUE is true, then the property values should also be
+** inserted into the output XML stream.
 **
-** Note: dav_dyn_module structures are always treated as "const" by mod_dav.
+** The liveprop provider should insert *all* known and *defined* live
+** properties on the specified resource. If a particular liveprop is
+** not defined for this resource, then it should not be inserted.
 */
-typedef struct
-{
-    int magic;
-#define DAV_DYN_MAGIC          0x44415621      /* "DAV!" */
+APR_DECLARE_EXTERNAL_HOOK(dav, DAV, void, insert_all_liveprops, 
+                         (request_rec *r, const dav_resource *resource,
+                          dav_prop_insert what, ap_text_header *phdr))
 
-    int version;
-#define DAV_DYN_VERSION                1               /* must match exactly */
+const dav_hooks_locks *dav_get_lock_hooks(request_rec *r);
+const dav_hooks_propdb *dav_get_propdb_hooks(request_rec *r);
+const dav_hooks_vsn *dav_get_vsn_hooks(request_rec *r);
+const dav_hooks_binding *dav_get_binding_hooks(request_rec *r);
 
-    const char *name;                          /* friendly name */
+DAV_DECLARE(void) dav_register_provider(apr_pool_t *p, const char *name,
+                                        const dav_provider *hooks);
+const dav_provider * dav_lookup_provider(const char *name);
 
-    int (*module_open)(dav_dyn_context *ctx);
-    int (*module_close)(dav_dyn_context *ctx);
 
-    int (*dir_open)(dav_dyn_context *ctx);
-    int (*dir_param)(dav_dyn_context *ctx, const char *param_name,
-                    const char *param_value);
-    int (*dir_merge)(dav_dyn_context *base, dav_dyn_context *overrides,
-                    dav_dyn_context *result);
-    int (*dir_close)(dav_dyn_context *ctx);
-
-    const dav_dyn_provider *providers;         /* providers in this module */
-
-} dav_dyn_module;
-
-int dav_load_module(const char *name, const char *module_sym,
-                   const char *filename);
-const dav_dyn_module *dav_find_module(const char *name);
-
-/*
-** Various management functions.
-**
-** NOTE: the pool should be the "configuration pool"
-*/
-void dav_process_builtin_modules(ap_pool_t *p);
-void dav_process_module(ap_pool_t *p, const dav_dyn_module *mod);
-
-int * dav_collect_liveprop_uris(ap_pool_t *p, const dav_hooks_liveprop *hooks);
-extern ap_array_header_t *dav_liveprop_uris;
-
-void *dav_prepare_scan(ap_pool_t *p, const dav_dyn_module *mod);
-int dav_scan_providers(void *ctx,
-                      const dav_dyn_provider **provider,
-                      dav_dyn_hooks *output);
-
-/* handy macros to assist with dav_dyn_hooks.hooks usage */
-#define DAV_AS_HOOKS_PROPDB(ph)                ((const dav_hooks_db *)((ph)->hooks))
-#define DAV_AS_HOOKS_LOCKS(ph)         ((const dav_hooks_locks *)((ph)->hooks))
-#define DAV_AS_HOOKS_QUERY_GRAMMAR(ph) ((void *)((ph)->hooks))
-#define DAV_AS_HOOKS_ACL(ph)           ((void *)((ph)->hooks))
-#define DAV_AS_HOOKS_VSN(ph)           ((const dav_hooks_vsn *)((ph)->hooks))
-#define DAV_AS_HOOKS_REPOSITORY(ph)    ((const dav_hooks_repository *)((ph)->hooks))
-#define DAV_AS_HOOKS_LIVEPROP(ph)      ((const dav_hooks_liveprop *)((ph)->hooks))
-
-/* get provider hooks, given a request record */
-const dav_dyn_hooks *dav_get_provider_hooks(request_rec *r, int provider_type);
-
-#define DAV_GET_HOOKS_PROPDB(r)         DAV_AS_HOOKS_PROPDB(dav_get_provider_hooks(r, DAV_DYN_TYPE_PROPDB))
-#define DAV_GET_HOOKS_LOCKS(r)          DAV_AS_HOOKS_LOCKS(dav_get_provider_hooks(r, DAV_DYN_TYPE_LOCKS))
-#define DAV_GET_HOOKS_QUERY_GRAMMAR(r)  DAV_AS_HOOKS_QUERY_GRAMMAR(dav_get_provider_hooks(r, DAV_DYN_TYPE_QUERY_GRAMMAR))
-#define DAV_GET_HOOKS_ACL(r)            DAV_AS_HOOKS_ACL(dav_get_provider_hooks(r, DAV_DYN_TYPE_ACL))
-#define DAV_GET_HOOKS_VSN(r)            DAV_AS_HOOKS_VSN(dav_get_provider_hooks(r, DAV_DYN_TYPE_VSN))
-#define DAV_GET_HOOKS_REPOSITORY(r)     DAV_AS_HOOKS_REPOSITORY(dav_get_provider_hooks(r, DAV_DYN_TYPE_REPOSITORY))
-#define DAV_GET_HOOKS_LIVEPROP(r)       DAV_AS_HOOKS_LIVEPROP(dav_get_provider_hooks(r, DAV_DYN_TYPE_LIVEPROP))
+/* ### deprecated */
+#define DAV_GET_HOOKS_PROPDB(r)         dav_get_propdb_hooks(r)
+#define DAV_GET_HOOKS_LOCKS(r)          dav_get_lock_hooks(r)
+#define DAV_GET_HOOKS_VSN(r)            dav_get_vsn_hooks(r)
+#define DAV_GET_HOOKS_BINDING(r)        dav_get_binding_hooks(r)
 
 
 /* --------------------------------------------------------------------
@@ -610,7 +671,7 @@ typedef struct dav_if_state_list
 typedef struct dav_if_header
 {
     const char *uri;
-    size_t uri_len;
+    apr_size_t uri_len;
     struct dav_if_state_list *state;
     struct dav_if_header *next;
 
@@ -626,234 +687,52 @@ typedef struct dav_locktoken_list
 dav_error * dav_get_locktoken_list(request_rec *r, dav_locktoken_list **ltl);
 
 
-/* --------------------------------------------------------------------
-**
-** XML PARSING
-*/
-
-/*
-** Qualified namespace values
-**
-** DAV_NS_DAV_ID
-**    We always insert the "DAV:" namespace URI at the head of the
-**    namespace array. This means that it will always be at ID==0,
-**    making it much easier to test for.
-**
-** DAV_NS_NONE
-**    This special ID is used for two situations:
-**
-**    1) The namespace prefix begins with "xml" (and we do not know
-**       what it means). Namespace prefixes with "xml" (any case) as
-**       their first three characters are reserved by the XML Namespaces
-**       specification for future use. mod_dav will pass these through
-**       unchanged. When this identifier is used, the prefix is LEFT in
-**       the element/attribute name. Downstream processing should not
-**       prepend another prefix.
-**
-**    2) The element/attribute does not have a namespace.
-**
-**       a) No prefix was used, and a default namespace has not been
-**          defined.
-**       b) No prefix was used, and the default namespace was specified
-**          to mean "no namespace". This is done with a namespace
-**          declaration of:  xmlns=""
-**          (this declaration is typically used to override a previous
-**          specification for the default namespace)
-**
-**       In these cases, we need to record that the elem/attr has no
-**       namespace so that we will not attempt to prepend a prefix.
-**       All namespaces that are used will have a prefix assigned to
-**       them -- mod_dav will never set or use the default namespace
-**       when generating XML. This means that "no prefix" will always
-**       mean "no namespace".
-**
-**    In both cases, the XML generation will avoid prepending a prefix.
-**    For the first case, this means the original prefix/name will be
-**    inserted into the output stream. For the latter case, it means
-**    the name will have no prefix, and since we never define a default
-**    namespace, this means it will have no namespace.
-**
-** Note: currently, mod_dav understands the "xmlns" prefix and the
-**     "xml:lang" attribute. These are handled specially (they aren't
-**     left within the XML tree), so the DAV_NS_NONE value won't ever
-**     really apply to these values.
-*/
-#define DAV_NS_DAV_ID          0       /* namespace ID for "DAV:" */
-#define DAV_NS_NONE            -10     /* no namespace for this elem/attr */
-
-#define DAV_NS_ERROR_BASE      -100    /* used only during processing */
-#define DAV_NS_IS_ERROR(e)     ((e) <= DAV_NS_ERROR_BASE)
-
-
-/*
-** dav_xml_doc: holds a parsed XML document
-** dav_xml_elem: holds a parsed XML element
-** dav_xml_attr: holds a parsed XML attribute
-**
-** dav_xml_ns_scope: internal struct used during processing to scope
-**                   namespace declarations
-*/
-
-typedef struct dav_xml_attr
-{
-    const char *name;                  /* attribute name */
-    int ns;                            /* index into namespace array */
-
-    const char *value;                 /* attribute value */
-
-    struct dav_xml_attr *next;         /* next attribute */
-} dav_xml_attr;
-
-typedef struct dav_xml_elem
-{
-    const char *name;                  /* element name */
-    int ns;                            /* index into namespace array */
-    const char *lang;                  /* xml:lang for attrs/contents */
-
-    dav_text_header first_cdata;       /* cdata right after start tag */
-    dav_text_header following_cdata;   /* cdata after MY end tag */
-
-    struct dav_xml_elem *parent;       /* parent element */
-    struct dav_xml_elem *next;         /* next (sibling) element */
-    struct dav_xml_elem *first_child;  /* first child element */
-    struct dav_xml_attr *attr;         /* first attribute */
-
-    /* used only during parsing */
-    struct dav_xml_elem *last_child;   /* last child element */
-    struct dav_xml_ns_scope *ns_scope; /* namespaces scoped by this elem */
-
-    /* used during request processing */
-    int propid;                                /* live property ID */
-    const dav_hooks_liveprop *provider;        /* the provider defining this prop */
-    const int *ns_map;                 /* ns map for this provider */
-
-} dav_xml_elem;
-
-#define DAV_ELEM_IS_EMPTY(e)   ((e)->first_child == NULL && \
-                                (e)->first_cdata.first == NULL)
-
-typedef struct dav_xml_doc
-{
-    dav_xml_elem *root;                 /* root element */
-    ap_array_header_t *namespaces;      /* array of namespaces used */
-
-} dav_xml_doc;
-
-
-int dav_parse_input(request_rec *r, dav_xml_doc **pdoc);
-
-int dav_validate_root(const dav_xml_doc *doc, const char *tagname);
-
-dav_xml_elem *dav_find_child(
-    const dav_xml_elem *elem,
-    const char *tagname);
-
-void dav_xml2text(
-    ap_pool_t *p,
-    const dav_xml_elem *elem,
-    int style,
-    ap_array_header_t *namespaces,
-    int *ns_map,
-    const char **pbuf,
-    size_t *psize
-    );
-#define DAV_X2T_FULL           0       /* start tag, contents, end tag */
-#define DAV_X2T_INNER          1       /* contents only */
-#define DAV_X2T_LANG_INNER     2       /* xml:lang + inner contents */
-#define DAV_X2T_FULL_NS_LANG   3       /* FULL + ns defns + xml:lang */
-
-const char *dav_empty_elem(ap_pool_t *p, const dav_xml_elem *elem);
-void dav_quote_xml_elem(ap_pool_t *p, dav_xml_elem *elem);
-const char * dav_quote_string(ap_pool_t *p, const char *s, int quotes);
-
-
 /* --------------------------------------------------------------------
 **
 ** LIVE PROPERTY HANDLING
 */
 
-typedef enum {
-    DAV_PROP_INSERT_NOTME,     /* prop not defined by this provider */
-    DAV_PROP_INSERT_NOTDEF,    /* property is defined by this provider,
-                                  but nothing was inserted because the
-                                  (live) property is not defined for this
-                                  resource (it may be present as a dead
-                                  property). */
-    DAV_PROP_INSERT_NAME,      /* a property name (empty elem) was
-                                  inserted into the text block */
-    DAV_PROP_INSERT_VALUE      /* a property name/value pair was inserted
-                                  into the text block */
-} dav_prop_insert;
-
-typedef enum {
-    DAV_PROP_RW_NOTME,         /* not my property */
-    DAV_PROP_RW_NO,            /* property is NOT writeable */
-    DAV_PROP_RW_YES            /* property IS writeable */
-} dav_prop_rw;
-
 /* opaque type for PROPPATCH rollback information */
 typedef struct dav_liveprop_rollback dav_liveprop_rollback;
 
 struct dav_hooks_liveprop
 {
     /*
-    ** This URI is returned in the DAV: header to let clients know what
-    ** sets of live properties are supported by the installation. mod_dav
-    ** will place open/close angle brackets around this value (much like
-    ** a Coded-URL); quotes and brackets should not be in the value.
-    **
-    ** Example:    http://apache.org/dav/props/
-    **
-    ** (of course, use your own domain to ensure a unique value)
-    */
-    const char * propset_uri;
-
-    /*
-    ** Find a property, returning a non-zero, unique, opaque identifier.
-    **
-    ** NOTE: Providers must ensure this identifier is universally unique.
-    **       See the registration table below.
-    ** ### it would be nice to avoid this uniqueness constraint. however,
-    ** ### that would mean our xml_elem annotation concept would need to
-    ** ### change (w.r.t. the fact that it acts as a cache for find_prop).
-    **
-    ** Returns 0 if the property is not defined by this provider.
-    */
-    int (*find_prop)(const char *ns_uri, const char *name);
-
-    /*
-    ** Insert a property name/value into a text block. The property to
-    ** insert is identified by the propid value. Providers should return
-    ** DAV_PROP_INSERT_NOTME if they do not define the specified propid.
-    ** If insvalue is true, then the property's value should be inserted;
-    ** otherwise, an empty element (ie. just the prop's name) should be
-    ** inserted.
+    ** Insert property information into a text block. The property to
+    ** insert is identified by the propid value. The information to insert
+    ** is identified by the "what" argument, as follows:
+    **   DAV_PROP_INSERT_NAME
+    **      property name, as an empty XML element
+    **   DAV_PROP_INSERT_VALUE
+    **      property name/value, as an XML element
+    **   DAV_PROP_INSERT_SUPPORTED
+    **      if the property is defined on the resource, then
+    **      a DAV:supported-live-property element, as defined
+    **      by the DeltaV extensions to RFC2518.
+    **                      
+    ** Providers should return DAV_PROP_INSERT_NOTDEF if the property is
+    ** known and not defined for this resource, so should be handled as a
+    ** dead property. If a provider recognizes, but does not support, a
+    ** property, and does not want it handled as a dead property, it should
+    ** return DAV_PROP_INSERT_NOTSUPP.
     **
     ** Returns one of DAV_PROP_INSERT_* based on what happened.
     **
     ** ### we may need more context... ie. the lock database
     */
     dav_prop_insert (*insert_prop)(const dav_resource *resource,
-                                  int propid, int insvalue,
-                                  const int *ns_map, dav_text_header *phdr);
+                                  int propid, dav_prop_insert what,
+                                  ap_text_header *phdr);
 
     /*
-    ** Insert all known/defined property names (and values). This is
-    ** similar to insert_prop, but *all* properties will be inserted
-    ** rather than specific, individual properties.
-    */
-    void (*insert_all)(const dav_resource *resource, int insvalue,
-                      const int *ns_map, dav_text_header *phdr);
-
-    /*
-    ** Determine whether a given property is writeable.
+    ** Determine whether a given property is writable.
     **
     ** ### we may want a different semantic. i.e. maybe it should be
     ** ### "can we write <value> into this property?"
     **
-    ** Returns appropriate read/write status.
+    ** Returns 1 if the live property can be written, 0 if read-only.
     */
-    dav_prop_rw (*is_writeable)(const dav_resource *resource, int propid);
+    int (*is_writable)(const dav_resource *resource, int propid);
 
     /*
     ** This member defines the set of namespace URIs that the provider
@@ -896,31 +775,171 @@ struct dav_hooks_liveprop
     ** database. Note: it will be set to zero on entry.
     */
     dav_error * (*patch_validate)(const dav_resource *resource,
-                                 const dav_xml_elem *elem,
+                                 const ap_xml_elem *elem,
                                  int operation,
                                  void **context,
                                  int *defer_to_dead);
 
     /* ### doc... */
-    dav_error * (*patch_exec)(dav_resource *resource,
-                             const dav_xml_elem *elem,
+    dav_error * (*patch_exec)(const dav_resource *resource,
+                             const ap_xml_elem *elem,
                              int operation,
                              void *context,
                              dav_liveprop_rollback **rollback_ctx);
 
     /* ### doc... */
-    void (*patch_commit)(dav_resource *resource,
+    void (*patch_commit)(const dav_resource *resource,
                         int operation,
                         void *context,
                         dav_liveprop_rollback *rollback_ctx);
 
     /* ### doc... */
-    dav_error * (*patch_rollback)(dav_resource *resource,
+    dav_error * (*patch_rollback)(const dav_resource *resource,
                                  int operation,
                                  void *context,
                                  dav_liveprop_rollback *rollback_ctx);
 };
 
+/*
+** dav_liveprop_spec: specify a live property
+**
+** This structure is used as a standard way to determine if a particular
+** property is a live property. Its use is not part of the mandated liveprop
+** interface, but can be used by liveprop providers in conjuction with the
+** utility routines below.
+*/
+typedef struct {
+    int ns;             /* provider-local namespace index */
+    const char *name;   /* name of the property */
+
+    int propid;         /* provider-local property ID */
+
+    int is_writable;    /* is the property writable? */
+
+} dav_liveprop_spec;
+
+/*
+** dav_liveprop_group: specify a group of liveprops
+**
+** This structure specifies a group of live properties, their namespaces,
+** and how to handle them.
+*/
+typedef struct {
+    const dav_liveprop_spec *specs;
+    const char * const *namespace_uris;
+    const dav_hooks_liveprop *hooks;
+
+} dav_liveprop_group;
+
+/* ### docco */
+DAV_DECLARE(int) dav_do_find_liveprop(const char *ns_uri, const char *name,
+                                      const dav_liveprop_group *group,
+                                      const dav_hooks_liveprop **hooks);
+
+/* ### docco */
+DAV_DECLARE(int) dav_get_liveprop_info(int propid,
+                                       const dav_liveprop_group *group,
+                                       const dav_liveprop_spec **info);
+
+/* ### docco */
+DAV_DECLARE(void) dav_register_liveprop_group(apr_pool_t *pool, 
+                                              const dav_liveprop_group *group);
+
+/* ### docco */
+DAV_DECLARE(int) dav_get_liveprop_ns_index(const char *uri);
+
+/* ### docco */
+int dav_get_liveprop_ns_count(void);
+
+/* ### docco */
+void dav_add_all_liveprop_xmlns(apr_pool_t *p, ap_text_header *phdr);
+
+/*
+** The following three functions are part of mod_dav's internal handling
+** for the core WebDAV properties. They are not part of mod_dav's API.
+*/
+int dav_core_find_liveprop(const dav_resource *resource,
+                           const char *ns_uri, const char *name,
+                           const dav_hooks_liveprop **hooks);
+void dav_core_insert_all_liveprops(request_rec *r,
+                                   const dav_resource *resource,
+                                   dav_prop_insert what, ap_text_header *phdr);
+void dav_core_register_uris(apr_pool_t *p);
+
+
+/*
+** Standard WebDAV Property Identifiers
+**
+** A live property provider does not need to use these; they are simply
+** provided for convenience.
+**
+** Property identifiers need to be unique within a given provider, but not
+** *across* providers (note: this uniqueness constraint was different in
+** older versions of mod_dav).
+**
+** The identifiers start at 20000 to make it easier for providers to avoid
+** conflicts with the standard properties. The properties are arranged
+** alphabetically, and may be reordered from time to time (as properties
+** are introduced).
+**
+** NOTE: there is no problem with reordering (e.g. binary compat) since the
+** identifiers are only used within a given provider, which would pick up
+** the entire set of changes upon a recompile.
+*/
+enum {
+    DAV_PROPID_BEGIN = 20000,
+
+    /* Standard WebDAV properties (RFC 2518 and DeltaV I-D) */
+    DAV_PROPID_comment,                         /* from DeltaV I-D */
+    DAV_PROPID_creationdate,
+    DAV_PROPID_creator_displayname,             /* from DeltaV I-D */
+    DAV_PROPID_displayname,
+    DAV_PROPID_getcontentlanguage,
+    DAV_PROPID_getcontentlength,
+    DAV_PROPID_getcontenttype,
+    DAV_PROPID_getetag,
+    DAV_PROPID_getlastmodified,
+    DAV_PROPID_lockdiscovery,
+    DAV_PROPID_resourcetype,
+    DAV_PROPID_source,
+    DAV_PROPID_supportedlock,
+
+    /* DeltaV properties (from the I-D) */
+    DAV_PROPID_activity_collection_set,
+    DAV_PROPID_activity_set,
+    DAV_PROPID_auto_merge_set,
+    DAV_PROPID_auto_version,
+    DAV_PROPID_baseline_selector,
+    DAV_PROPID_baselined_collection,
+    DAV_PROPID_baselined_collection_set,
+    DAV_PROPID_checked_out,
+    DAV_PROPID_checkin_date,
+    DAV_PROPID_checkin_fork,
+    DAV_PROPID_checkout_fork,
+    DAV_PROPID_checkout_set,
+    DAV_PROPID_current_activity_set,
+    DAV_PROPID_current_workspace_set,
+    DAV_PROPID_initial_version,
+    DAV_PROPID_label_name_set,
+    DAV_PROPID_latest_version,
+    DAV_PROPID_merge_set,
+    DAV_PROPID_mutable,
+    DAV_PROPID_predecessor_set,
+    DAV_PROPID_subactivity_set,
+    DAV_PROPID_successor_set,
+    DAV_PROPID_target,
+    DAV_PROPID_unreserved,
+    DAV_PROPID_version,
+    DAV_PROPID_version_history,
+    DAV_PROPID_version_name,
+    DAV_PROPID_version_set,
+    DAV_PROPID_workspace,
+    DAV_PROPID_workspace_checkout_set,
+    DAV_PROPID_workspace_collection_set,
+
+    DAV_PROPID_END
+};
+
 /*
 ** Property Identifier Registration
 **
@@ -946,16 +965,12 @@ struct dav_hooks_liveprop
 */
 
 typedef struct dav_db dav_db;
-typedef struct
-{
-    char *dptr;
-    size_t dsize;
-} dav_datum;
+typedef apr_datum_t dav_datum;
 
 /* hook functions to enable pluggable databases */
-struct dav_hooks_db
+struct dav_hooks_propdb
 {
-    dav_error * (*open)(ap_pool_t *p, const dav_resource *resource, int ro,
+    dav_error * (*open)(apr_pool_t *p, const dav_resource *resource, int ro,
                        dav_db **pdb);
     void (*close)(dav_db *db);
 
@@ -991,12 +1006,12 @@ struct dav_hooks_db
 time_t dav_get_timeout(request_rec *r);
 
 /*
-** Opaque, repository-specific information for a lock database.
+** Opaque, provider-specific information for a lock database.
 */
 typedef struct dav_lockdb_private dav_lockdb_private;
 
 /*
-** Opaque, repository-specific information for a lock record.
+** Opaque, provider-specific information for a lock record.
 */
 typedef struct dav_lock_private dav_lock_private;
 
@@ -1087,11 +1102,10 @@ const char *dav_lock_get_activelock(request_rec *r, dav_lock *locks,
                                    dav_buffer *pbuf);
 
 /* LockDB-related public lock functions */
-const char *dav_get_lockdb_path(const request_rec *r);
 dav_error * dav_lock_parse_lockinfo(request_rec *r,
                                    const dav_resource *resrouce,
                                    dav_lockdb *lockdb,
-                                   const dav_xml_doc *doc,
+                                   const ap_xml_doc *doc,
                                    dav_lock **lock_request);
 int dav_unlock(request_rec *r, const dav_resource *resource,
               const dav_locktoken *locktoken);
@@ -1104,8 +1118,9 @@ dav_error * dav_notify_created(request_rec *r,
                               int resource_state,
                               int depth);
 
-dav_error * dav_lock_query(dav_lockdb *lockdb, const dav_resource *resource,
-                          dav_lock **locks);
+DAV_DECLARE(dav_error*) dav_lock_query(dav_lockdb *lockdb, 
+                                       const dav_resource *resource,
+                                       dav_lock **locks);
 
 dav_error * dav_validate_request(request_rec *r, dav_resource *resource,
                                 int depth, dav_locktoken *locktoken,
@@ -1132,15 +1147,16 @@ int dav_get_resource_state(request_rec *r, const dav_resource *resource);
  */
 struct dav_hooks_locks
 {
-    /* Return the supportedlock property for this provider */
-    /* ### maybe this should take a resource argument? */
-    const char * (*get_supportedlock)(void);
+    /* Return the supportedlock property for a resource */
+    const char * (*get_supportedlock)(
+        const dav_resource *resource
+    );
 
     /* Parse a lock token URI, returning a lock token object allocated
      * in the given pool.
      */
     dav_error * (*parse_locktoken)(
-        ap_pool_t *p,
+        apr_pool_t *p,
         const char *char_token,
         dav_locktoken **locktoken_p
     );
@@ -1151,7 +1167,7 @@ struct dav_hooks_locks
      * Always returns non-NULL.
      */
     const char * (*format_locktoken)(
-        ap_pool_t *p,
+        apr_pool_t *p,
         const dav_locktoken *locktoken
     );
 
@@ -1342,20 +1358,26 @@ typedef struct dav_propdb dav_propdb;
 dav_error *dav_open_propdb(
     request_rec *r,
     dav_lockdb *lockdb,
-    dav_resource *resource,
+    const dav_resource *resource,
     int ro,
-    ap_array_header_t *ns_xlate,
+    apr_array_header_t *ns_xlate,
     dav_propdb **propdb);
 
 void dav_close_propdb(dav_propdb *db);
 
 dav_get_props_result dav_get_props(
     dav_propdb *db,
-    dav_xml_doc *doc);
+    ap_xml_doc *doc);
 
 dav_get_props_result dav_get_allprops(
     dav_propdb *db,
-    int getvals);
+    dav_prop_insert what);
+
+void dav_get_liveprop_supported(
+    dav_propdb *propdb,
+    const char *ns_uri,
+    const char *propname,
+    ap_text_header *body);
 
 /*
 ** 3-phase property modification.
@@ -1402,7 +1424,7 @@ typedef struct dav_prop_ctx
 #define DAV_PROP_OP_DELETE     2       /* delete a prop value */
 /* ### add a GET? */
 
-    dav_xml_elem *prop;                        /* property to affect */
+    ap_xml_elem *prop;                 /* property to affect */
 
     dav_error *err;                    /* error (if any) */
 
@@ -1429,51 +1451,69 @@ void dav_prop_rollback(dav_prop_ctx *ctx);
 ** WALKER STRUCTURE
 */
 
-/* private, opaque info structure for repository walking context */
-typedef struct dav_walker_private dav_walker_private;
+enum {
+    DAV_CALLTYPE_MEMBER = 1,   /* called for a member resource */
+    DAV_CALLTYPE_COLLECTION,   /* called for a collection */
+    DAV_CALLTYPE_LOCKNULL      /* called for a locknull resource */
+};
 
-/* directory tree walking context */
-typedef struct dav_walker_ctx
+typedef struct
 {
-    int walk_type;
-#define DAV_WALKTYPE_AUTH      1       /* limit to authorized files */
-#define DAV_WALKTYPE_ALL       2       /* walk normal files */
-#define DAV_WALKTYPE_HIDDEN    4       /* walk hidden files */
-#define DAV_WALKTYPE_LOCKNULL  8       /* walk locknull resources */
+    /* the client-provided context */
+    void *walk_ctx;
 
-    int postfix;               /* call func for dirs after files */
+    /* pool to use for allocations in the callback */
+    apr_pool_t *pool;
 
-    dav_error * (*func)(struct dav_walker_ctx *ctx, int calltype);
-#define DAV_CALLTYPE_MEMBER    1       /* called for a member resource */
-#define DAV_CALLTYPE_COLLECTION        2       /* called for a collection */
-#define DAV_CALLTYPE_LOCKNULL  3       /* called for a locknull resource */
-#define DAV_CALLTYPE_POSTFIX   4       /* postfix call for a collection */
+    /* the current resource */
+    const dav_resource *resource;
 
-    ap_pool_t *pool;
+    /* OUTPUT: add responses to this */
+    dav_response *response;
 
-    request_rec *r;                    /* original request */
-    dav_buffer uri;                    /* current URI */
-    const dav_resource *resource;      /* current resource */
-    const dav_resource *res2;          /* optional secondary resource */
+} dav_walk_resource;
 
-    const dav_resource *root;          /* RO: root resource of the walk */
+typedef struct
+{
+    int walk_type;
+#define DAV_WALKTYPE_AUTH      0x0001  /* limit to authorized files */
+#define DAV_WALKTYPE_NORMAL    0x0002  /* walk normal files */
+#define DAV_WALKTYPE_LOCKNULL  0x0004  /* walk locknull resources */
 
+    /* callback function and a client context for the walk */
+    dav_error * (*func)(dav_walk_resource *wres, int calltype);
+    void *walk_ctx;
+
+    /* what pool to use for allocations needed by walk logic */
+    apr_pool_t *pool;
+
+    /* beginning root of the walk */
+    const dav_resource *root;
+
+    /* lock database to enable walking LOCKNULL resources */
     dav_lockdb *lockdb;
 
-    dav_response *response;            /* OUT: multistatus responses */
+} dav_walk_params;
+
+/* directory tree walking context */
+typedef struct dav_walker_ctx
+{
+    /* input: */
+    dav_walk_params w;
+
+
+    /* ### client data... phasing out this big glom */
+
+    request_rec *r;                    /* original request */
 
     /* for PROPFIND operations */
-    dav_xml_doc *doc;
+    ap_xml_doc *doc;
     int propfind_type;
 #define DAV_PROPFIND_IS_ALLPROP                1
 #define DAV_PROPFIND_IS_PROPNAME       2
 #define DAV_PROPFIND_IS_PROP           3
 
-    dav_text *propstat_404;    /* (cached) propstat giving a 404 error */
-
-    /* for COPY and MOVE operations */
-    int is_move;
-    dav_buffer work_buf;
+    ap_text *propstat_404;     /* (cached) propstat giving a 404 error */
 
     const dav_if_header *if_header;    /* for validation */
     const dav_locktoken *locktoken;    /* for UNLOCK */
@@ -1482,12 +1522,13 @@ typedef struct dav_walker_ctx
 
     int flags;
 
-    dav_walker_private *info;           /* for use by repository manager */
+    dav_buffer work_buf;                /* for dav_validate_request() */
 
 } dav_walker_ctx;
 
-void dav_add_response(dav_walker_ctx *ctx, const char *href, int status,
-                     dav_get_props_result *propstats);
+DAV_DECLARE(void) dav_add_response(dav_walk_resource *wres,
+                                   int status,
+                                   dav_get_props_result *propstats);
 
 
 /* --------------------------------------------------------------------
@@ -1511,6 +1552,7 @@ typedef enum {
     DAV_MODE_WRITE_SEEKABLE    /* open for writing; random access */
 } dav_stream_mode;
 
+
 /* --------------------------------------------------------------------
 **
 ** REPOSITORY FUNCTIONS
@@ -1527,30 +1569,47 @@ struct dav_hooks_repository
      */
     int handle_get;
 
-    /* Get a resource descriptor for the URI in a request.
-     * A descriptor is returned even if the resource does not exist.
-     * The return value should only be NULL for some kind of fatal error.
+    /* Get a resource descriptor for the URI in a request. A descriptor
+     * should always be returned even if the resource does not exist. This
+     * repository has been identified as handling the resource given by
+     * the URI, so an answer must be given. If there is a problem with the
+     * URI or accessing the resource or whatever, then an error should be
+     * returned.
+     *
+     * root_dir:
+     *   the root of the directory for which this repository is configured.
      *
-     * The root_dir is the root of the directory for which this repository
-     * is configured.
-     * The workspace is the value of any Target-Selector header, or NULL
-     * if there is none.
+     * label:
+     *   if a Label: header is present (and allowed), this is the label
+     *   to use to identify a version resource from the resource's
+     *   corresponding version history. Otherwise, it will be NULL.
      *
-     * The provider may associate the request storage pool with the resource,
-     * to use in other operations on that resource.
+     * use_checked_in:
+     *   use the DAV:checked-in property of the resource identified by the
+     *   Request-URI to identify and return a version resource
+     *
+     * The provider may associate the request storage pool with the resource
+     * (in the resource->pool field), to use in other operations on that
+     * resource. 
      */
-    dav_resource * (*get_resource)(
+    dav_error * (*get_resource)(
         request_rec *r,
         const char *root_dir,
-        const char *workspace
+       const char *label,
+        int use_checked_in,
+        dav_resource **resource
     );
 
     /* Get a resource descriptor for the parent of the given resource.
      * The resources need not exist.  NULL is returned if the resource 
      * is the root collection.
+     *
+     * An error should be returned only if there is a fatal error in
+     * fetching information about the parent resource.
      */
-    dav_resource * (*get_parent_resource)(
-        const dav_resource *resource
+    dav_error * (*get_parent_resource)(
+        const dav_resource *resource,
+        dav_resource **parent_resource
     );
 
     /* Determine whether two resource descriptors refer to the same resource.
@@ -1609,7 +1668,7 @@ struct dav_hooks_repository
     ** on each call, until the EOF condition is met.
     */
     dav_error * (*read_stream)(dav_stream *stream,
-                              void *buf, size_t *bufsize);
+                              void *buf, apr_size_t *bufsize);
 
     /*
     ** Write data to the stream.
@@ -1617,7 +1676,7 @@ struct dav_hooks_repository
     ** All of the bytes must be written, or an error should be returned.
     */
     dav_error * (*write_stream)(dav_stream *stream,
-                               const void *buf, size_t bufsize);
+                               const void *buf, apr_size_t bufsize);
 
     /*
     ** Seek to an absolute position in the stream. This is used to support
@@ -1626,7 +1685,7 @@ struct dav_hooks_repository
     ** NOTE: if this function is NULL (which is allowed), then any
     **       operations using Content-Range will be refused.
     */
-    dav_error * (*seek_stream)(dav_stream *stream, off_t abs_position);
+    dav_error * (*seek_stream)(dav_stream *stream, apr_off_t abs_position);
 
     /*
     ** If a GET is processed using a stream (open_stream, read_stream)
@@ -1666,7 +1725,7 @@ struct dav_hooks_repository
      * is a collection.
      */
     dav_error * (*create_collection)(
-        ap_pool_t *p, dav_resource *resource
+        dav_resource *resource
     );
 
     /* Copy one resource to another. The destination must not exist.
@@ -1713,14 +1772,17 @@ struct dav_hooks_repository
 
     /* Walk a resource hierarchy.
      *
-     * Iterates over the resource hierarchy specified by wctx->resource.
-     * Parameter for control of the walk and the callback are specified
-     * by wctx.
+     * Iterates over the resource hierarchy specified by params->root.
+     * Control of the walk and the callback are specified by 'params'.
      *
-     * An HTTP_* status code is returned if an error occurs during the
-     * walk or the callback indicates an error. OK is returned on success.
+     * An error may be returned. *response will contain multistatus
+     * responses (if any) suitable for the body of the error. It is also
+     * possible to return NULL, yet still have multistatus responses.
+     * In this case, typically the caller should return a 207 (Multistatus)
+     * and the responses (in the body) as the HTTP response.
      */
-    dav_error * (*walk)(dav_walker_ctx *wctx, int depth);
+    dav_error * (*walk)(const dav_walk_params *params, int depth,
+                        dav_response **response);
 
     /* Get the entity tag for a resource */
     const char * (*getetag)(const dav_resource *resource);
@@ -1732,12 +1794,27 @@ struct dav_hooks_repository
 ** VERSIONING FUNCTIONS
 */
 
-/* dav_get_target_selector:
+
+/* dav_add_vary_header
  *
- * Returns any Target-Selector header in a request
- * (used by versioning clients)
+ * If there were any headers in the request which require a Vary header
+ * in the response, add it.
  */
-const char *dav_get_target_selector(request_rec *r);
+void dav_add_vary_header(request_rec *in_req,
+                        request_rec *out_req,
+                        const dav_resource *resource);
+
+/*
+** This structure is used to record what auto-versioning operations
+** were done to make a resource writable, so that they can be undone
+** at the end of a request.
+*/
+typedef struct {
+    int resource_created;               /* 0 => resource existed previously */
+    int resource_checkedout;            /* 0 => resource was checked out */
+    int parent_checkedout;              /* 0 => parent was checked out */
+    dav_resource *parent_resource;      /* parent resource, if it was needed */
+} dav_auto_version_info;
 
 /* Ensure that a resource is writable. If there is no versioning
  * provider, then this is essentially a no-op. Versioning repositories
@@ -1750,21 +1827,14 @@ const char *dav_get_target_selector(request_rec *r);
  * child does not exist, then a new versioned resource is created and
  * checked out.
  *
- * The parent_resource and parent_was_writable arguments are optional
- * (i.e. they may be NULL). If parent_only is set, then the
- * resource_existed and resource_was_writable arguments are ignored.
- *
- * The previous states of the resources are returned, so they can be
- * restored after the operation completes (see
- * dav_revert_resource_writability())
+ * The dav_auto_version_info structure is filled in with enough information
+ * to restore both parent and child resources to the state they were in
+ * before the auto-versioning operations occurred.
  */
 dav_error *dav_ensure_resource_writable(request_rec *r,
                                        dav_resource *resource,
                                         int parent_only,
-                                       dav_resource **parent_resource,
-                                       int *resource_existed,
-                                       int *resource_was_writable,
-                                       int *parent_was_writable);
+                                        dav_auto_version_info *av_info);
 
 /* Revert the writability of resources back to what they were
  * before they were modified. If undo == 0, then the resource
@@ -1772,34 +1842,93 @@ dav_error *dav_ensure_resource_writable(request_rec *r,
  * If undo != 0, then resource modifications are discarded
  * (i.e. they are unchecked out).
  *
- * The resource and parent_resource arguments are optional
- * (i.e. they may be NULL).
+ * The resource argument may be NULL if only the parent resource
+ * was made writable (i.e. the parent_only was != 0 in the
+ * dav_ensure_resource_writable call).
  */
-dav_error *dav_revert_resource_writability(request_rec *r,
-                                          dav_resource *resource,
-                                          dav_resource *parent_resource,
-                                          int undo,
-                                          int resource_existed,
-                                          int resource_was_writable,
-                                          int parent_was_writable);
+dav_error *dav_revert_resource_writability(
+    request_rec *r,
+    dav_resource *resource,
+    int undo,
+    const dav_auto_version_info *av_info);
+
+/*
+** This structure is used to describe available reports
+**
+** "nmspace" should be valid XML and URL-quoted. mod_dav will place
+** double-quotes around it and use it in an xmlns declaration.
+*/
+typedef struct {
+    const char *nmspace;        /* namespace of the XML report element */
+    const char *name;           /* element name for the XML report */
+} dav_report_elem;
+
 
 /* Versioning provider hooks */
 struct dav_hooks_vsn
 {
-    /* Return supported versioning level
-     * for the Versioning header
+    /*
+    ** MANDATORY HOOKS
+    ** The following hooks are mandatory for all versioning providers;
+    ** they define the functionality needed to implement "core" versioning.
+    */
+
+    /* Return supported versioning options.
+     * Each dav_text item in the list will be returned as a separate
+     * DAV header. Providers are advised to limit the length of an
+     * individual text item to 63 characters, to conform to the limit
+     * used by MS Web Folders.
      */
-    const char * (*get_vsn_header)(void);
+    void (*get_vsn_options)(apr_pool_t *p, ap_text_header *phdr);
 
-    /* Create a new (empty) resource. If successful,
-     * the resource object state is updated appropriately.
+    /* Get the value of a specific option for an OPTIONS request.
+     * The option being requested is given by the parsed XML
+     * element object "elem". The value of the option should be
+     * appended to the "option" text object.
      */
-    dav_error * (*mkresource)(dav_resource *resource);
+    dav_error * (*get_option)(const dav_resource *resource,
+                              const ap_xml_elem *elem,
+                              ap_text_header *option);
+
+    /* Put a resource under version control. If the resource already
+     * exists unversioned, then it becomes the initial version of the
+     * new version history, and it is replaced by a version selector
+     * which targets the new version.
+     *
+     * If the resource does not exist, then a new version selector
+     * is created which either targets an existing version (if the
+     * "target" argument is not NULL), or the initial, empty version
+     * in a new history resource (if the "target" argument is NULL).
+     *
+     * If successful, the resource object state is updated appropriately
+     * (that is, changed to refer to the new version selector resource).
+     */
+    dav_error * (*vsn_control)(dav_resource *resource,
+                               const char *target);
 
     /* Checkout a resource. If successful, the resource
      * object state is updated appropriately.
+     *
+     * If the working resource has a different URL from the
+     * target resource, a dav_resource descriptor is returned
+     * for the new working resource. Otherwise, the original
+     * resource descriptor will refer to the working resource.
+     * The working_resource argument can be NULL if the caller
+     * is not interested in the working resource.
+     *
+     * If the client has specified DAV:unreserved or DAV:fork-ok in the
+     * checkout request, then the corresponding flags are set. If
+     * DAV:activity-set has been specified, then create_activity is set
+     * if DAV:new was specified; otherwise, the DAV:href elements' CDATA
+     * (the actual href text) is passed in the "activities" array (each
+     * element of the array is a const char *). activities will be NULL
+     * no DAV:activity-set was provided or when create_activity is set.
      */
-    dav_error * (*checkout)(dav_resource *resource);
+    dav_error * (*checkout)(dav_resource *resource,
+                            int is_unreserved, int is_fork_ok,
+                            int create_activity,
+                            apr_array_header_t *activities,
+                            dav_resource **working_resource);
 
     /* Uncheckout a resource. If successful, the resource
      * object state is updated appropriately.
@@ -1807,9 +1936,24 @@ struct dav_hooks_vsn
     dav_error * (*uncheckout)(dav_resource *resource);
 
     /* Checkin a working resource. If successful, the resource
-     * object state is updated appropriately.
+     * object state is updated appropriately, and the
+     * version_resource descriptor will refer to the new version.
+     * The version_resource argument can be NULL if the caller
+     * is not interested in the new version resource.
      */
-    dav_error * (*checkin)(dav_resource *resource);
+    dav_error * (*checkin)(dav_resource *resource,
+                           dav_resource **version_resource);
+
+    /*
+    ** Set the default target of a version selector or
+    ** baseline selector resource.
+    ** The target argument specifies the new target, which
+    ** can be a label, if is_label != 0, or a version URI,
+    ** if is_label == 0.
+    */
+    dav_error * (*set_target)(const dav_resource *resource,
+                             const char *target,
+                              int is_label);
 
     /* Determine whether a non-versioned (or non-existent) resource
      * is versionable. Returns != 0 if resource can be versioned.
@@ -1821,6 +1965,151 @@ struct dav_hooks_vsn
      * Returns != 0 if auto-versioning is enabled.
      */
     int (*auto_version_enabled)(const dav_resource *resource);
+
+    /*
+    ** Return the set of reports available at this resource.
+    **
+    ** An array of report elements should be returned, with an end-marker
+    ** element containing namespace==NULL. The value of the
+    ** DAV:supported-report-set property will be constructed and
+    ** returned.
+    */
+    dav_error * (*avail_reports)(const dav_resource *resource,
+                                 const dav_report_elem **reports);
+
+    /*
+    ** Determine whether a Target-Selector header can be used
+    ** with a particular report. The dav_xml_doc structure
+    ** contains the parsed report request body.
+    ** Returns 0 if Target-Selector is not allowed.
+    */
+    int (*report_target_selector_allowed)(const ap_xml_doc *doc);
+
+    /*
+    ** Generate a report on a resource. Since a provider is free
+    ** to define its own reports, and the value of request headers
+    ** may affect the interpretation of a report, the request record
+    ** must be passed to this routine.
+    **
+    ** The dav_xml_doc structure contains the parsed report request
+    ** body. The report response is generated into the ap_text_header
+    ** structure.
+    **
+    ** ### shouldn't generate large responses to memory ###
+    */
+    dav_error * (*get_report)(request_rec *r,
+                              const dav_resource *resource,
+                              const ap_xml_doc *doc,
+                              ap_text_header *report);
+
+    /*
+    ** OPTIONAL HOOKS
+    ** The following hooks are optional; if not defined, then the
+    ** corresponding protocol methods will be unsupported.
+    */
+
+    /*
+    ** Add a label to a version. The resource is either a specific
+    ** version, or a version selector, in which case the label should
+    ** be added to the current target of the version selector. The
+    ** version selector cannot be checked out.
+    **
+    ** If replace != 0, any existing label by the same name is
+    ** effectively deleted first. Otherwise, it is an error to
+    ** attempt to add a label which already exists on some version
+    ** of the same history resource.
+    **
+    ** This hook is optional; if not defined, then the LABEL method
+    ** will not be supported. If it is defined, then the remove_label
+    ** hook must be defined also.
+    */
+    dav_error * (*add_label)(const dav_resource *resource,
+                             const char *label,
+                             int replace);
+
+    /*
+    ** Remove a label from a version. The resource is either a specific
+    ** version, or a version selector, in which case the label should
+    ** be added to the current target of the version selector. The
+    ** version selector cannot be checked out.
+    **
+    ** It is an error if no such label exists on the specified version.
+    **
+    ** This hook is optional, but if defined, the add_label hook
+    ** must be defined also.
+    */
+    dav_error * (*remove_label)(const dav_resource *resource,
+                                const char *label);
+
+    /*
+    ** Determine whether a null resource can be created as a workspace.
+    ** The provider may restrict workspaces to certain locations.
+    ** Returns 0 if the resource cannot be a workspace.
+    **
+    ** This hook is optional; if the provider does not support workspaces,
+    ** it should be set to NULL.
+    */
+    int (*can_be_workspace)(const dav_resource *resource);
+
+    /*
+    ** Create a workspace resource. The resource must not already
+    ** exist. Any <DAV:mkworkspace> element is passed to the provider
+    ** in the "doc" structure; it may be empty.
+    **
+    ** If workspace creation is succesful, the state of the resource
+    ** object is updated appropriately.
+    **
+    ** This hook is optional; if the provider does not support workspaces,
+    ** it should be set to NULL.
+    */
+    dav_error * (*make_workspace)(dav_resource *resource,
+                                  ap_xml_doc *doc);
+
+    /*
+    ** Determine whether a null resource can be created as an activity.
+    ** The provider may restrict activities to certain locations.
+    ** Returns 0 if the resource cannot be an activity.
+    **
+    ** This hook is optional; if the provider does not support activities,
+    ** it should be set to NULL.
+    */
+    int (*can_be_activity)(const dav_resource *resource);
+
+    /*
+    ** Create an activity resource. The resource must not already
+    ** exist.
+    **
+    ** If activity creation is succesful, the state of the resource
+    ** object is updated appropriately.
+    **
+    ** This hook is optional; if the provider does not support activities,
+    ** it should be set to NULL.
+    */
+    dav_error * (*make_activity)(dav_resource *resource);
+};
+
+
+/* --------------------------------------------------------------------
+**
+** BINDING FUNCTIONS
+*/
+
+/* binding provider hooks */
+struct dav_hooks_binding {
+
+    /* Determine whether a resource can be the target of a binding.
+     * Returns 0 if the resource cannot be a binding target.
+     */
+    int (*is_bindable)(const dav_resource *resource);
+
+    /* Create a binding to a resource.
+     * The resource argument is the target of the binding;
+     * the binding argument must be a resource which does not already
+     * exist.
+     */
+    dav_error * (*bind_resource)(const dav_resource *resource,
+                                dav_resource *binding);
+
 };
 
 
@@ -1830,17 +2119,15 @@ struct dav_hooks_vsn
 */
 
 /* allow providers access to the per-directory parameters */
-ap_table_t *dav_get_dir_params(const request_rec *r);
+apr_table_t *dav_get_dir_params(const request_rec *r);
 
 /* fetch the "LimitXMLRequestBody" in force for this resource */
-size_t dav_get_limit_xml_body(const request_rec *r);
-
-/* manage an array of unique URIs: dav_insert_uri() and DAV_GET_URI_ITEM() */
-
-/* return the URI's (existing) index, or insert it and return a new index */
-int dav_insert_uri(ap_array_header_t *uri_array, const char *uri);
-#define DAV_GET_URI_ITEM(ary, i)    (((const char * const *)(ary)->elts)[i])
+apr_size_t dav_get_limit_xml_body(const request_rec *r);
 
+typedef struct {
+    int propid;                                /* live property ID */
+    const dav_hooks_liveprop *provider;        /* the provider defining this prop */
+} dav_elem_private;    
 
 #ifdef __cplusplus
 }