/* ====================================================================
* 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"
#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 ""
#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
/* --------------------------------------------------------------------
**
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;
** 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.
** <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... */
/* 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 */
*/
/* 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;
/* --------------------------------------------------------------------
** 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;
/*
*/
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;
/*
/* 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);
/* --------------------------------------------------------------------
** 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 */
} 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
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)
/* --------------------------------------------------------------------
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;
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
** 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
**
*/
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);
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;
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);
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,
*/
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
);
* Always returns non-NULL.
*/
const char * (*format_locktoken)(
- ap_pool_t *p,
+ apr_pool_t *p,
const dav_locktoken *locktoken
);
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.
#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) */
** 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 */
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);
/* --------------------------------------------------------------------
DAV_MODE_WRITE_SEEKABLE /* open for writing; random access */
} dav_stream_mode;
+
/* --------------------------------------------------------------------
**
** REPOSITORY FUNCTIONS
*/
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.
** 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.
** 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
** 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)
* 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.
/* 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);
** 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
* 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
* 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.
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.
* 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);
+
};
*/
/* 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
}