1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements.  See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License.  You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/**
18 * @file  mod_dav.h
19 * @brief DAV extension module for Apache 2.0.*
20 *
21 * @defgroup MOD_DAV mod_dav
22 * @ingroup APACHE_MODS
23 * @{
24 */
25
26#ifndef _MOD_DAV_H_
27#define _MOD_DAV_H_
28
29#include "apr_hooks.h"
30#include "apr_hash.h"
31#include "apr_dbm.h"
32#include "apr_tables.h"
33
34#include "httpd.h"
35#include "util_filter.h"
36#include "util_xml.h"
37
38#include <limits.h>     /* for INT_MAX */
39#include <time.h>       /* for time_t */
40
41#ifdef __cplusplus
42extern "C" {
43#endif
44
45
46#define DAV_VERSION             AP_SERVER_BASEREVISION
47
48#define DAV_XML_HEADER          "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
49#define DAV_XML_CONTENT_TYPE    "text/xml; charset=\"utf-8\""
50
51#define DAV_READ_BLOCKSIZE      2048    /* used for reading input blocks */
52
53#define DAV_RESPONSE_BODY_1     "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n<html><head>\n<title>"
54#define DAV_RESPONSE_BODY_2     "</title>\n</head><body>\n<h1>"
55#define DAV_RESPONSE_BODY_3     "</h1>\n<p>"
56#define DAV_RESPONSE_BODY_4     "</p>\n"
57#define DAV_RESPONSE_BODY_5     "</body></html>\n"
58
59#define DAV_DO_COPY             0
60#define DAV_DO_MOVE             1
61
62
63#if 1
64#define DAV_DEBUG        1
65#define DEBUG_CR         "\n"
66#define DBG0(f)          ap_log_error(APLOG_MARK, \
67                                APLOG_ERR, 0, NULL, (f))
68#define DBG1(f,a1)       ap_log_error(APLOG_MARK, \
69                                APLOG_ERR, 0, NULL, f, a1)
70#define DBG2(f,a1,a2)    ap_log_error(APLOG_MARK, \
71                                APLOG_ERR, 0, NULL, f, a1, a2)
72#define DBG3(f,a1,a2,a3) ap_log_error(APLOG_MARK, \
73                                APLOG_ERR, 0, NULL, f, a1, a2, a3)
74#else
75#undef DAV_DEBUG
76#define DEBUG_CR        ""
77#endif
78
79#define DAV_INFINITY    INT_MAX    /* for the Depth: header */
80
81/* Create a set of DAV_DECLARE(type), DAV_DECLARE_NONSTD(type) and
82 * DAV_DECLARE_DATA with appropriate export and import tags for the platform
83 */
84#if !defined(WIN32)
85#define DAV_DECLARE(type)            type
86#define DAV_DECLARE_NONSTD(type)     type
87#define DAV_DECLARE_DATA
88#elif defined(DAV_DECLARE_STATIC)
89#define DAV_DECLARE(type)            type __stdcall
90#define DAV_DECLARE_NONSTD(type)     type
91#define DAV_DECLARE_DATA
92#elif defined(DAV_DECLARE_EXPORT)
93#define DAV_DECLARE(type)            __declspec(dllexport) type __stdcall
94#define DAV_DECLARE_NONSTD(type)     __declspec(dllexport) type
95#define DAV_DECLARE_DATA             __declspec(dllexport)
96#else
97#define DAV_DECLARE(type)            __declspec(dllimport) type __stdcall
98#define DAV_DECLARE_NONSTD(type)     __declspec(dllimport) type
99#define DAV_DECLARE_DATA             __declspec(dllimport)
100#endif
101
102/* --------------------------------------------------------------------
103**
104** ERROR MANAGEMENT
105*/
106
107/*
108** dav_error structure.
109**
110** In most cases, mod_dav uses a pointer to a dav_error structure. If the
111** pointer is NULL, then no error has occurred.
112**
113** In certain cases, a dav_error structure is directly used. In these cases,
114** a status value of 0 means that an error has not occurred.
115**
116** Note: this implies that status != 0 whenever an error occurs.
117**
118** The desc field is optional (it may be NULL). When NULL, it typically
119** implies that Apache has a proper description for the specified status.
120*/
121typedef struct dav_error {
122    int status;                 /* suggested HTTP status (0 for no error) */
123    int error_id;               /* DAV-specific error ID */
124    const char *desc;           /* DAV:responsedescription and error log */
125
126    apr_status_t aprerr;        /* APR error if any, or 0/APR_SUCCESS */
127
128    const char *namespace;      /* [optional] namespace of error */
129    const char *tagname;        /* name of error-tag */
130
131    struct dav_error *prev;     /* previous error (in stack) */
132
133} dav_error;
134
135/*
136** Create a new error structure. save_errno will be filled with the current
137** errno value.
138*/
139DAV_DECLARE(dav_error*) dav_new_error(apr_pool_t *p, int status,
140                                      int error_id, apr_status_t aprerr,
141                                      const char *desc);
142
143
144/*
145** Create a new error structure with tagname and (optional) namespace;
146** namespace may be NULL, which means "DAV:".
147*/
148DAV_DECLARE(dav_error*) dav_new_error_tag(apr_pool_t *p, int status,
149                                          int error_id, apr_status_t aprerr,
150                                          const char *desc,
151                                          const char *namespace,
152                                          const char *tagname);
153
154
155/*
156** Push a new error description onto the stack of errors.
157**
158** This function is used to provide an additional description to an existing
159** error.
160**
161** <status> should contain the caller's view of what the current status is,
162** given the underlying error. If it doesn't have a better idea, then the
163** caller should pass prev->status.
164**
165** <error_id> can specify a new error_id since the topmost description has
166** changed.
167*/
168DAV_DECLARE(dav_error*) dav_push_error(apr_pool_t *p, int status, int error_id,
169                                       const char *desc, dav_error *prev);
170
171
172/*
173** Join two errors together.
174**
175** This function is used to add a new error stack onto an existing error so
176** that subsequent errors can be reported after the first error.  It returns
177** the correct error stack to use so that the caller can blindly call it
178** without checking that both dest and src are not NULL.
179**
180** <dest> is the error stack that the error will be added to.
181**
182** <src> is the error stack that will be appended.
183*/
184DAV_DECLARE(dav_error*) dav_join_error(dav_error* dest, dav_error* src);
185
186
187/* error ID values... */
188
189/* IF: header errors */
190#define DAV_ERR_IF_PARSE                100    /* general parsing error */
191#define DAV_ERR_IF_MULTIPLE_NOT         101    /* multiple "Not" found */
192#define DAV_ERR_IF_UNK_CHAR             102    /* unknown char in header */
193#define DAV_ERR_IF_ABSENT               103    /* no locktokens given */
194#define DAV_ERR_IF_TAGGED               104    /* in parsing tagged-list */
195#define DAV_ERR_IF_UNCLOSED_PAREN       105    /* in no-tagged-list */
196
197/* Prop DB errors */
198#define DAV_ERR_PROP_BAD_MAJOR          200    /* major version was wrong */
199#define DAV_ERR_PROP_READONLY           201    /* prop is read-only */
200#define DAV_ERR_PROP_NO_DATABASE        202    /* writable db not avail */
201#define DAV_ERR_PROP_NOT_FOUND          203    /* prop not found */
202#define DAV_ERR_PROP_BAD_LOCKDB         204    /* could not open lockdb */
203#define DAV_ERR_PROP_OPENING            205    /* problem opening propdb */
204#define DAV_ERR_PROP_EXEC               206    /* problem exec'ing patch */
205
206/* Predefined DB errors */
207/* ### any to define?? */
208
209/* Predefined locking system errors */
210#define DAV_ERR_LOCK_OPENDB             400    /* could not open lockdb */
211#define DAV_ERR_LOCK_NO_DB              401    /* no database defined */
212#define DAV_ERR_LOCK_CORRUPT_DB         402    /* DB is corrupt */
213#define DAV_ERR_LOCK_UNK_STATE_TOKEN    403    /* unknown State-token */
214#define DAV_ERR_LOCK_PARSE_TOKEN        404    /* bad opaquelocktoken */
215#define DAV_ERR_LOCK_SAVE_LOCK          405    /* err saving locks */
216
217/*
218** Some comments on Error ID values:
219**
220** The numbers do not necessarily need to be unique. Uniqueness simply means
221** that two errors that have not been predefined above can be distinguished
222** from each other. At the moment, mod_dav does not use this distinguishing
223** feature, but it could be used in the future to collapse <response> elements
224** into groups based on the error ID (and associated responsedescription).
225**
226** If a compute_desc is provided, then the error ID should be unique within
227** the context of the compute_desc function (so the function can figure out
228** what to filled into the desc).
229**
230** Basically, subsystems can ignore defining new error ID values if they want
231** to. The subsystems *do* need to return the predefined errors when
232** appropriate, so that mod_dav can figure out what to do. Subsystems can
233** simply leave the error ID field unfilled (zero) if there isn't an error
234** that must be placed there.
235*/
236
237
238/* --------------------------------------------------------------------
239**
240** HOOK STRUCTURES
241**
242** These are here for forward-declaration purposes. For more info, see
243** the section title "HOOK HANDLING" for more information, plus each
244** structure definition.
245*/
246
247/* forward-declare this structure */
248typedef struct dav_hooks_propdb dav_hooks_propdb;
249typedef struct dav_hooks_locks dav_hooks_locks;
250typedef struct dav_hooks_vsn dav_hooks_vsn;
251typedef struct dav_hooks_repository dav_hooks_repository;
252typedef struct dav_hooks_liveprop dav_hooks_liveprop;
253typedef struct dav_hooks_binding dav_hooks_binding;
254typedef struct dav_hooks_search dav_hooks_search;
255
256/* ### deprecated name */
257typedef dav_hooks_propdb dav_hooks_db;
258
259
260/* --------------------------------------------------------------------
261**
262** RESOURCE HANDLING
263*/
264
265/*
266** Resource Types:
267** The base protocol defines only file and collection resources.
268** The versioning protocol defines several additional resource types
269** to represent artifacts of a version control system.
270**
271** This enumeration identifies the type of URL used to identify the
272** resource. Since the same resource may have more than one type of
273** URL which can identify it, dav_resource_type cannot be used
274** alone to determine the type of the resource; attributes of the
275** dav_resource object must also be consulted.
276*/
277typedef enum {
278    DAV_RESOURCE_TYPE_UNKNOWN,
279
280    DAV_RESOURCE_TYPE_REGULAR,          /* file or collection; could be
281                                         * unversioned, or version selector,
282                                         * or baseline selector */
283
284    DAV_RESOURCE_TYPE_VERSION,          /* version or baseline URL */
285
286    DAV_RESOURCE_TYPE_HISTORY,          /* version or baseline history URL */
287
288    DAV_RESOURCE_TYPE_WORKING,          /* working resource URL */
289
290    DAV_RESOURCE_TYPE_WORKSPACE,        /* workspace URL */
291
292    DAV_RESOURCE_TYPE_ACTIVITY,         /* activity URL */
293
294    DAV_RESOURCE_TYPE_PRIVATE           /* repository-private type */
295
296} dav_resource_type;
297
298/*
299** Opaque, repository-specific information for a resource.
300*/
301typedef struct dav_resource_private dav_resource_private;
302
303/*
304** Resource descriptor, generated by a repository provider.
305**
306** Note: the lock-null state is not explicitly represented here,
307** since it may be expensive to compute. Use dav_get_resource_state()
308** to determine whether a non-existent resource is a lock-null resource.
309**
310** A quick explanation of how the flags can apply to different resources:
311**
312** unversioned file or collection:
313**     type       = DAV_RESOURCE_TYPE_REGULAR
314**     exists     = ? (1 if exists)
315**     collection = ? (1 if collection)
316**     versioned  = 0
317**     baselined  = 0
318**     working    = 0
319**
320** version-controlled resource or configuration:
321**     type       = DAV_RESOURCE_TYPE_REGULAR
322**     exists     = 1
323**     collection = ? (1 if collection)
324**     versioned  = 1
325**     baselined  = ? (1 if configuration)
326**     working    = ? (1 if checked out)
327**
328** version/baseline history:
329**     type       = DAV_RESOURCE_TYPE_HISTORY
330**     exists     = 1
331**     collection = 0
332**     versioned  = 0
333**     baselined  = 0
334**     working    = 0
335**
336** version/baseline:
337**     type       = DAV_RESOURCE_TYPE_VERSION
338**     exists     = 1
339**     collection = ? (1 if collection)
340**     versioned  = 1
341**     baselined  = ? (1 if baseline)
342**     working    = 0
343**
344** working resource:
345**     type       = DAV_RESOURCE_TYPE_WORKING
346**     exists     = 1
347**     collection = ? (1 if collection)
348**     versioned  = 1
349**     baselined  = 0
350**     working    = 1
351**
352** workspace:
353**     type       = DAV_RESOURCE_TYPE_WORKSPACE
354**     exists     = ? (1 if exists)
355**     collection = 1
356**     versioned  = ? (1 if version-controlled)
357**     baselined  = ? (1 if baseline-controlled)
358**     working    = ? (1 if checked out)
359**
360** activity:
361**     type       = DAV_RESOURCE_TYPE_ACTIVITY
362**     exists     = ? (1 if exists)
363**     collection = 0
364**     versioned  = 0
365**     baselined  = 0
366**     working    = 0
367*/
368typedef struct dav_resource {
369    dav_resource_type type;
370
371    int exists;         /* 0 => null resource */
372
373    int collection;     /* 0 => file; can be 1 for
374                         * REGULAR, VERSION, and WORKING resources,
375                         * and is always 1 for WORKSPACE */
376
377    int versioned;      /* 0 => unversioned; can be 1 for
378                         * REGULAR and WORKSPACE resources,
379                         * and is always 1 for VERSION and WORKING */
380
381    int baselined;      /* 0 => not baselined; can be 1 for
382                         * REGULAR, VERSION, and WORKSPACE resources;
383                         * versioned == 1 when baselined == 1 */
384
385    int working;        /* 0 => not checked out; can be 1 for
386                         * REGULAR and WORKSPACE resources,
387                         * and is always 1 for WORKING */
388
389    const char *uri;    /* the escaped URI for this resource */
390
391    dav_resource_private *info;         /* the provider's private info */
392
393    const dav_hooks_repository *hooks;  /* hooks used for this resource */
394
395    /* When allocating items related specifically to this resource, the
396       following pool should be used. Its lifetime will be at least as
397       long as the dav_resource structure. */
398    apr_pool_t *pool;
399
400} dav_resource;
401
402/*
403** Lock token type. Lock providers define the details of a lock token.
404** However, all providers are expected to at least be able to parse
405** the "opaquelocktoken" scheme, which is represented by a uuid_t.
406*/
407typedef struct dav_locktoken dav_locktoken;
408
409
410/* --------------------------------------------------------------------
411**
412** BUFFER HANDLING
413**
414** These buffers are used as a lightweight buffer reuse mechanism. Apache
415** provides sub-pool creation and destruction to much the same effect, but
416** the sub-pools are a bit more general and heavyweight than these buffers.
417*/
418
419/* buffer for reuse; can grow to accomodate needed size */
420typedef struct
421{
422    apr_size_t alloc_len;       /* how much has been allocated */
423    apr_size_t cur_len;         /* how much is currently being used */
424    char *buf;                  /* buffer contents */
425} dav_buffer;
426#define DAV_BUFFER_MINSIZE      256    /* minimum size for buffer */
427#define DAV_BUFFER_PAD          64     /* amount of pad when growing */
428
429/* set the cur_len to the given size and ensure space is available */
430DAV_DECLARE(void) dav_set_bufsize(apr_pool_t *p, dav_buffer *pbuf,
431                                  apr_size_t size);
432
433/* initialize a buffer and copy the specified (null-term'd) string into it */
434DAV_DECLARE(void) dav_buffer_init(apr_pool_t *p, dav_buffer *pbuf,
435                                  const char *str);
436
437/* check that the buffer can accomodate <extra_needed> more bytes */
438DAV_DECLARE(void) dav_check_bufsize(apr_pool_t *p, dav_buffer *pbuf,
439                                    apr_size_t extra_needed);
440
441/* append a string to the end of the buffer, adjust length */
442DAV_DECLARE(void) dav_buffer_append(apr_pool_t *p, dav_buffer *pbuf,
443                                    const char *str);
444
445/* place a string on the end of the buffer, do NOT adjust length */
446DAV_DECLARE(void) dav_buffer_place(apr_pool_t *p, dav_buffer *pbuf,
447                                   const char *str);
448
449/* place some memory on the end of a buffer; do NOT adjust length */
450DAV_DECLARE(void) dav_buffer_place_mem(apr_pool_t *p, dav_buffer *pbuf,
451                                       const void *mem, apr_size_t amt,
452                                       apr_size_t pad);
453
454
455/* --------------------------------------------------------------------
456**
457** HANDY UTILITIES
458*/
459
460/* contains results from one of the getprop functions */
461typedef struct
462{
463    apr_text * propstats;       /* <propstat> element text */
464    apr_text * xmlns;           /* namespace decls for <response> elem */
465} dav_get_props_result;
466
467/* holds the contents of a <response> element */
468typedef struct dav_response
469{
470    const char *href;           /* always */
471    const char *desc;           /* optional description at <response> level */
472
473    /* use status if propresult.propstats is NULL. */
474    dav_get_props_result propresult;
475
476    int status;
477
478    struct dav_response *next;
479} dav_response;
480
481typedef struct
482{
483    request_rec *rnew;          /* new subrequest */
484    dav_error err;              /* potential error response */
485} dav_lookup_result;
486
487
488DAV_DECLARE(dav_lookup_result) dav_lookup_uri(const char *uri, request_rec *r,
489                                              int must_be_absolute);
490
491/* defines type of property info a provider is to return */
492typedef enum {
493    DAV_PROP_INSERT_NOTDEF,     /* property is defined by this provider,
494                                   but nothing was inserted because the
495                                   (live) property is not defined for this
496                                   resource (it may be present as a dead
497                                   property). */
498    DAV_PROP_INSERT_NOTSUPP,    /* property is recognized by this provider,
499                                   but it is not supported, and cannot be
500                                   treated as a dead property */
501    DAV_PROP_INSERT_NAME,       /* a property name (empty elem) was
502                                   inserted into the text block */
503    DAV_PROP_INSERT_VALUE,      /* a property name/value pair was inserted
504                                   into the text block */
505    DAV_PROP_INSERT_SUPPORTED   /* a supported live property was added to
506                                   the text block as a
507                                   <DAV:supported-live-property> element */
508} dav_prop_insert;
509
510/* ### this stuff is private to dav/fs/repos.c; move it... */
511/* format a time string (buf must be at least DAV_TIMEBUF_SIZE chars) */
512#define DAV_STYLE_ISO8601       1
513#define DAV_STYLE_RFC822        2
514#define DAV_TIMEBUF_SIZE        30
515
516DAV_DECLARE(int) dav_get_depth(request_rec *r, int def_depth);
517
518DAV_DECLARE(int) dav_validate_root(const apr_xml_doc *doc,
519                                   const char *tagname);
520DAV_DECLARE(apr_xml_elem *) dav_find_child(const apr_xml_elem *elem,
521                                           const char *tagname);
522
523/* gather up all the CDATA into a single string */
524DAV_DECLARE(const char *) dav_xml_get_cdata(const apr_xml_elem *elem, apr_pool_t *pool,
525                              int strip_white);
526
527/*
528** XML namespace handling
529**
530** This structure tracks namespace declarations (xmlns:prefix="URI").
531** It maintains a one-to-many relationship of URIs-to-prefixes. In other
532** words, one URI may be defined by many prefixes, but any specific
533** prefix will specify only one URI.
534**
535** Prefixes using the "g###" pattern can be generated automatically if
536** the caller does not have specific prefix requirements.
537*/
538typedef struct {
539    apr_pool_t *pool;
540    apr_hash_t *uri_prefix;     /* map URIs to an available prefix */
541    apr_hash_t *prefix_uri;     /* map all prefixes to their URIs */
542    int count;                  /* counter for "g###" prefixes */
543} dav_xmlns_info;
544
545/* create an empty dav_xmlns_info structure */
546DAV_DECLARE(dav_xmlns_info *) dav_xmlns_create(apr_pool_t *pool);
547
548/* add a specific prefix/URI pair. the prefix/uri should have a lifetime
549   at least that of xmlns->pool */
550DAV_DECLARE(void) dav_xmlns_add(dav_xmlns_info *xi,
551                                const char *prefix, const char *uri);
552
553/* add a URI (if not present); any prefix is acceptable and is returned.
554   the uri should have a lifetime at least that xmlns->pool */
555DAV_DECLARE(const char *) dav_xmlns_add_uri(dav_xmlns_info *xi,
556                                            const char *uri);
557
558/* return the URI for a specified prefix (or NULL if the prefix is unknown) */
559DAV_DECLARE(const char *) dav_xmlns_get_uri(dav_xmlns_info *xi,
560                                            const char *prefix);
561
562/* return an available prefix for a specified URI (or NULL if the URI
563   is unknown) */
564DAV_DECLARE(const char *) dav_xmlns_get_prefix(dav_xmlns_info *xi,
565                                               const char *uri);
566
567/* generate xmlns declarations (appending into the given text) */
568DAV_DECLARE(void) dav_xmlns_generate(dav_xmlns_info *xi,
569                                     apr_text_header *phdr);
570
571/* --------------------------------------------------------------------
572**
573** DAV PLUGINS
574*/
575
576/* ### docco ... */
577
578/*
579** dav_provider
580**
581** This structure wraps up all of the hooks that a mod_dav provider can
582** supply. The provider MUST supply <repos> and <propdb>. The rest are
583** optional and should contain NULL if that feature is not supplied.
584**
585** Note that a provider cannot pick and choose portions from various
586** underlying implementations (which was theoretically possible in
587** mod_dav 1.0). There are too many dependencies between a dav_resource
588** (defined by <repos>) and the other functionality.
589**
590** Live properties are not part of the dav_provider structure because they
591** are handled through the APR_HOOK interface (to allow for multiple liveprop
592** providers). The core always provides some properties, and then a given
593** provider will add more properties.
594**
595** Some providers may need to associate a context with the dav_provider
596** structure -- the ctx field is available for storing this context. Just
597** leave it NULL if it isn't required.
598*/
599typedef struct {
600    const dav_hooks_repository *repos;
601    const dav_hooks_propdb *propdb;
602    const dav_hooks_locks *locks;
603    const dav_hooks_vsn *vsn;
604    const dav_hooks_binding *binding;
605    const dav_hooks_search *search;
606
607    void *ctx;
608} dav_provider;
609
610/*
611** gather_propsets: gather all live property propset-URIs
612**
613** The hook implementor should push one or more URIs into the specified
614** array. These URIs are returned in the DAV: header to let clients know
615** what sets of live properties are supported by the installation. mod_dav
616** will place open/close angle brackets around each value (much like
617** a Coded-URL); quotes and brackets should not be in the value.
618**
619** Example:    http://apache.org/dav/props/
620**
621** (of course, use your own domain to ensure a unique value)
622*/
623APR_DECLARE_EXTERNAL_HOOK(dav, DAV, void, gather_propsets,
624                         (apr_array_header_t *uris))
625
626/*
627** find_liveprop: find a live property, returning a non-zero, unique,
628**                opaque identifier.
629**
630** If the hook implementor determines the specified URI/name refers to
631** one of its properties, then it should fill in HOOKS and return a
632** non-zero value. The returned value is the "property ID" and will
633** be passed to the various liveprop hook functions.
634**
635** Return 0 if the property is not defined by the hook implementor.
636*/
637APR_DECLARE_EXTERNAL_HOOK(dav, DAV, int, find_liveprop,
638                         (const dav_resource *resource,
639                          const char *ns_uri, const char *name,
640                          const dav_hooks_liveprop **hooks))
641
642/*
643** insert_all_liveprops: insert all (known) live property names/values.
644**
645** The hook implementor should append XML text to PHDR, containing liveprop
646** names. If INSVALUE is true, then the property values should also be
647** inserted into the output XML stream.
648**
649** The liveprop provider should insert *all* known and *defined* live
650** properties on the specified resource. If a particular liveprop is
651** not defined for this resource, then it should not be inserted.
652*/
653APR_DECLARE_EXTERNAL_HOOK(dav, DAV, void, insert_all_liveprops,
654                         (request_rec *r, const dav_resource *resource,
655                          dav_prop_insert what, apr_text_header *phdr))
656
657DAV_DECLARE(const dav_hooks_locks *) dav_get_lock_hooks(request_rec *r);
658DAV_DECLARE(const dav_hooks_propdb *) dav_get_propdb_hooks(request_rec *r);
659DAV_DECLARE(const dav_hooks_vsn *) dav_get_vsn_hooks(request_rec *r);
660DAV_DECLARE(const dav_hooks_binding *) dav_get_binding_hooks(request_rec *r);
661DAV_DECLARE(const dav_hooks_search *) dav_get_search_hooks(request_rec *r);
662
663DAV_DECLARE(void) dav_register_provider(apr_pool_t *p, const char *name,
664                                        const dav_provider *hooks);
665DAV_DECLARE(const dav_provider *) dav_lookup_provider(const char *name);
666
667
668/* ### deprecated */
669#define DAV_GET_HOOKS_PROPDB(r)         dav_get_propdb_hooks(r)
670#define DAV_GET_HOOKS_LOCKS(r)          dav_get_lock_hooks(r)
671#define DAV_GET_HOOKS_VSN(r)            dav_get_vsn_hooks(r)
672#define DAV_GET_HOOKS_BINDING(r)        dav_get_binding_hooks(r)
673#define DAV_GET_HOOKS_SEARCH(r)         dav_get_search_hooks(r)
674
675
676/* --------------------------------------------------------------------
677**
678** IF HEADER PROCESSING
679**
680** Here is the definition of the If: header from RFC 2518, S9.4:
681**
682**    If = "If" ":" (1*No-tag-list | 1*Tagged-list)
683**    No-tag-list = List
684**    Tagged-list = Resource 1*List
685**    Resource = Coded-URL
686**    List = "(" 1*(["Not"](State-token | "[" entity-tag "]")) ")"
687**    State-token = Coded-URL
688**    Coded-URL = "<" absoluteURI ">"        ; absoluteURI from RFC 2616
689**
690** List corresponds to dav_if_state_list. No-tag-list corresponds to
691** dav_if_header with uri==NULL. Tagged-list corresponds to a sequence of
692** dav_if_header structures with (duplicate) uri==Resource -- one
693** dav_if_header per state_list. A second Tagged-list will start a new
694** sequence of dav_if_header structures with the new URI.
695**
696** A summary of the semantics, mapped into our structures:
697**    - Chained dav_if_headers: OR
698**    - Chained dav_if_state_lists: AND
699**    - NULL uri matches all resources
700*/
701
702typedef enum
703{
704    dav_if_etag,
705    dav_if_opaquelock,
706    dav_if_unknown /* the "unknown" state type; always matches false. */
707} dav_if_state_type;
708
709typedef struct dav_if_state_list
710{
711    dav_if_state_type type;
712
713    int condition;
714#define DAV_IF_COND_NORMAL      0
715#define DAV_IF_COND_NOT         1    /* "Not" was applied */
716
717    const char *etag;
718    dav_locktoken *locktoken;
719
720    struct dav_if_state_list *next;
721} dav_if_state_list;
722
723typedef struct dav_if_header
724{
725    const char *uri;
726    apr_size_t uri_len;
727    struct dav_if_state_list *state;
728    struct dav_if_header *next;
729
730    int dummy_header;   /* used internally by the lock/etag validation */
731} dav_if_header;
732
733typedef struct dav_locktoken_list
734{
735    dav_locktoken *locktoken;
736    struct dav_locktoken_list *next;
737} dav_locktoken_list;
738
739DAV_DECLARE(dav_error *) dav_get_locktoken_list(request_rec *r,
740                                                dav_locktoken_list **ltl);
741
742
743/* --------------------------------------------------------------------
744**
745** LIVE PROPERTY HANDLING
746*/
747
748/* opaque type for PROPPATCH rollback information */
749typedef struct dav_liveprop_rollback dav_liveprop_rollback;
750
751struct dav_hooks_liveprop
752{
753    /*
754    ** Insert property information into a text block. The property to
755    ** insert is identified by the propid value. The information to insert
756    ** is identified by the "what" argument, as follows:
757    **   DAV_PROP_INSERT_NAME
758    **      property name, as an empty XML element
759    **   DAV_PROP_INSERT_VALUE
760    **      property name/value, as an XML element
761    **   DAV_PROP_INSERT_SUPPORTED
762    **      if the property is defined on the resource, then
763    **      a DAV:supported-live-property element, as defined
764    **      by the DeltaV extensions to RFC2518.
765    **
766    ** Providers should return DAV_PROP_INSERT_NOTDEF if the property is
767    ** known and not defined for this resource, so should be handled as a
768    ** dead property. If a provider recognizes, but does not support, a
769    ** property, and does not want it handled as a dead property, it should
770    ** return DAV_PROP_INSERT_NOTSUPP.
771    **
772    ** Returns one of DAV_PROP_INSERT_* based on what happened.
773    **
774    ** ### we may need more context... ie. the lock database
775    */
776    dav_prop_insert (*insert_prop)(const dav_resource *resource,
777                                   int propid, dav_prop_insert what,
778                                   apr_text_header *phdr);
779
780    /*
781    ** Determine whether a given property is writable.
782    **
783    ** ### we may want a different semantic. i.e. maybe it should be
784    ** ### "can we write <value> into this property?"
785    **
786    ** Returns 1 if the live property can be written, 0 if read-only.
787    */
788    int (*is_writable)(const dav_resource *resource, int propid);
789
790    /*
791    ** This member defines the set of namespace URIs that the provider
792    ** uses for its properties. When insert_all is called, it will be
793    ** passed a list of integers that map from indices into this list
794    ** to namespace IDs for output generation.
795    **
796    ** The last entry in this list should be a NULL value (sentinel).
797    */
798    const char * const * namespace_uris;
799
800    /*
801    ** ### this is not the final design. we want an open-ended way for
802    ** ### liveprop providers to attach *new* properties. To this end,
803    ** ### we'll have a "give me a list of the props you define", a way
804    ** ### to check for a prop's existence, a way to validate a set/remove
805    ** ### of a prop, and a way to execute/commit/rollback that change.
806    */
807
808    /*
809    ** Validate that the live property can be assigned a value, and that
810    ** the provided value is valid.
811    **
812    ** elem will point to the XML element that names the property. For
813    ** example:
814    **     <lp1:executable>T</lp1:executable>
815    **
816    ** The provider can access the cdata fields and the child elements
817    ** to extract the relevant pieces.
818    **
819    ** operation is one of DAV_PROP_OP_SET or _DELETE.
820    **
821    ** The provider may return a value in *context which will be passed
822    ** to each of the exec/commit/rollback functions. For example, this
823    ** may contain an internal value which has been processed from the
824    ** input element.
825    **
826    ** The provider must set defer_to_dead to true (non-zero) or false.
827    ** If true, then the set/remove is deferred to the dead property
828    ** database. Note: it will be set to zero on entry.
829    */
830    dav_error * (*patch_validate)(const dav_resource *resource,
831                                  const apr_xml_elem *elem,
832                                  int operation,
833                                  void **context,
834                                  int *defer_to_dead);
835
836    /* ### doc... */
837    dav_error * (*patch_exec)(const dav_resource *resource,
838                              const apr_xml_elem *elem,
839                              int operation,
840                              void *context,
841                              dav_liveprop_rollback **rollback_ctx);
842
843    /* ### doc... */
844    void (*patch_commit)(const dav_resource *resource,
845                         int operation,
846                         void *context,
847                         dav_liveprop_rollback *rollback_ctx);
848
849    /* ### doc... */
850    dav_error * (*patch_rollback)(const dav_resource *resource,
851                                  int operation,
852                                  void *context,
853                                  dav_liveprop_rollback *rollback_ctx);
854
855    /*
856    ** If a provider needs a context to associate with this hooks structure,
857    ** then this field may be used. In most cases, it will just be NULL.
858    */
859    void *ctx;
860};
861
862/*
863** dav_liveprop_spec: specify a live property
864**
865** This structure is used as a standard way to determine if a particular
866** property is a live property. Its use is not part of the mandated liveprop
867** interface, but can be used by liveprop providers in conjuction with the
868** utility routines below.
869**
870** spec->name == NULL is the defined end-sentinel for a list of specs.
871*/
872typedef struct {
873    int ns;             /* provider-local namespace index */
874    const char *name;   /* name of the property */
875
876    int propid;         /* provider-local property ID */
877
878    int is_writable;    /* is the property writable? */
879
880} dav_liveprop_spec;
881
882/*
883** dav_liveprop_group: specify a group of liveprops
884**
885** This structure specifies a group of live properties, their namespaces,
886** and how to handle them.
887*/
888typedef struct {
889    const dav_liveprop_spec *specs;
890    const char * const *namespace_uris;
891    const dav_hooks_liveprop *hooks;
892
893} dav_liveprop_group;
894
895/* ### docco */
896DAV_DECLARE(int) dav_do_find_liveprop(const char *ns_uri, const char *name,
897                                      const dav_liveprop_group *group,
898                                      const dav_hooks_liveprop **hooks);
899
900/* ### docco */
901DAV_DECLARE(long) dav_get_liveprop_info(int propid,
902                                        const dav_liveprop_group *group,
903                                        const dav_liveprop_spec **info);
904
905/* ### docco */
906DAV_DECLARE(void) dav_register_liveprop_group(apr_pool_t *pool,
907                                              const dav_liveprop_group *group);
908
909/* ### docco */
910DAV_DECLARE(long) dav_get_liveprop_ns_index(const char *uri);
911
912/* ### docco */
913DAV_DECLARE(long) dav_get_liveprop_ns_count(void);
914
915/* ### docco */
916DAV_DECLARE(void) dav_add_all_liveprop_xmlns(apr_pool_t *p,
917                                             apr_text_header *phdr);
918
919/*
920** The following three functions are part of mod_dav's internal handling
921** for the core WebDAV properties. They are not part of mod_dav's API.
922*/
923DAV_DECLARE_NONSTD(int) dav_core_find_liveprop(
924    const dav_resource *resource,
925    const char *ns_uri,
926    const char *name,
927    const dav_hooks_liveprop **hooks);
928DAV_DECLARE_NONSTD(void) dav_core_insert_all_liveprops(
929    request_rec *r,
930    const dav_resource *resource,
931    dav_prop_insert what,
932    apr_text_header *phdr);
933DAV_DECLARE_NONSTD(void) dav_core_register_uris(apr_pool_t *p);
934
935
936/*
937** Standard WebDAV Property Identifiers
938**
939** A live property provider does not need to use these; they are simply
940** provided for convenience.
941**
942** Property identifiers need to be unique within a given provider, but not
943** *across* providers (note: this uniqueness constraint was different in
944** older versions of mod_dav).
945**
946** The identifiers start at 20000 to make it easier for providers to avoid
947** conflicts with the standard properties. The properties are arranged
948** alphabetically, and may be reordered from time to time (as properties
949** are introduced).
950**
951** NOTE: there is no problem with reordering (e.g. binary compat) since the
952** identifiers are only used within a given provider, which would pick up
953** the entire set of changes upon a recompile.
954*/
955enum {
956    DAV_PROPID_BEGIN = 20000,
957
958    /* Standard WebDAV properties (RFC 2518) */
959    DAV_PROPID_creationdate,
960    DAV_PROPID_displayname,
961    DAV_PROPID_getcontentlanguage,
962    DAV_PROPID_getcontentlength,
963    DAV_PROPID_getcontenttype,
964    DAV_PROPID_getetag,
965    DAV_PROPID_getlastmodified,
966    DAV_PROPID_lockdiscovery,
967    DAV_PROPID_resourcetype,
968    DAV_PROPID_source,
969    DAV_PROPID_supportedlock,
970
971    /* DeltaV properties (from the I-D (#14)) */
972    DAV_PROPID_activity_checkout_set,
973    DAV_PROPID_activity_set,
974    DAV_PROPID_activity_version_set,
975    DAV_PROPID_auto_merge_set,
976    DAV_PROPID_auto_version,
977    DAV_PROPID_baseline_collection,
978    DAV_PROPID_baseline_controlled_collection,
979    DAV_PROPID_baseline_controlled_collection_set,
980    DAV_PROPID_checked_in,
981    DAV_PROPID_checked_out,
982    DAV_PROPID_checkin_fork,
983    DAV_PROPID_checkout_fork,
984    DAV_PROPID_checkout_set,
985    DAV_PROPID_comment,
986    DAV_PROPID_creator_displayname,
987    DAV_PROPID_current_activity_set,
988    DAV_PROPID_current_workspace_set,
989    DAV_PROPID_default_variant,
990    DAV_PROPID_eclipsed_set,
991    DAV_PROPID_label_name_set,
992    DAV_PROPID_merge_set,
993    DAV_PROPID_precursor_set,
994    DAV_PROPID_predecessor_set,
995    DAV_PROPID_root_version,
996    DAV_PROPID_subactivity_set,
997    DAV_PROPID_subbaseline_set,
998    DAV_PROPID_successor_set,
999    DAV_PROPID_supported_method_set,
1000    DAV_PROPID_supported_live_property_set,
1001    DAV_PROPID_supported_report_set,
1002    DAV_PROPID_unreserved,
1003    DAV_PROPID_variant_set,
1004    DAV_PROPID_version_controlled_binding_set,
1005    DAV_PROPID_version_controlled_configuration,
1006    DAV_PROPID_version_history,
1007    DAV_PROPID_version_name,
1008    DAV_PROPID_workspace,
1009    DAV_PROPID_workspace_checkout_set,
1010
1011    DAV_PROPID_END
1012};
1013
1014/*
1015** Property Identifier Registration
1016**
1017** At the moment, mod_dav requires live property providers to ensure that
1018** each property returned has a unique value. For now, this is done through
1019** central registration (there are no known providers other than the default,
1020** so this remains manageable).
1021**
1022** WARNING: the TEST ranges should never be "shipped".
1023*/
1024#define DAV_PROPID_CORE         10000   /* ..10099. defined by mod_dav */
1025#define DAV_PROPID_FS           10100   /* ..10299.
1026                                           mod_dav filesystem provider. */
1027#define DAV_PROPID_TEST1        10300   /* ..10399 */
1028#define DAV_PROPID_TEST2        10400   /* ..10499 */
1029#define DAV_PROPID_TEST3        10500   /* ..10599 */
1030/* Next: 10600 */
1031
1032
1033/* --------------------------------------------------------------------
1034**
1035** DATABASE FUNCTIONS
1036*/
1037
1038typedef struct dav_db dav_db;
1039typedef struct dav_namespace_map dav_namespace_map;
1040typedef struct dav_deadprop_rollback dav_deadprop_rollback;
1041
1042typedef struct {
1043    const char *ns;     /* "" signals "no namespace" */
1044    const char *name;
1045} dav_prop_name;
1046
1047/* hook functions to enable pluggable databases */
1048struct dav_hooks_propdb
1049{
1050    dav_error * (*open)(apr_pool_t *p, const dav_resource *resource, int ro,
1051                        dav_db **pdb);
1052    void (*close)(dav_db *db);
1053
1054    /*
1055    ** In bulk, define any namespaces that the values and their name
1056    ** elements may need.
1057    **
1058    ** Note: sometimes mod_dav will defer calling this until output_value
1059    ** returns found==1. If the output process needs the dav_xmlns_info
1060    ** filled for its work, then it will need to fill it on demand rather
1061    ** than depending upon this hook to fill in the structure.
1062    **
1063    ** Note: this will *always* be called during an output sequence. Thus,
1064    ** the provider may rely solely on using this to fill the xmlns info.
1065    */
1066    dav_error * (*define_namespaces)(dav_db *db, dav_xmlns_info *xi);
1067
1068    /*
1069    ** Output the value from the database (i.e. add an element name and
1070    ** the value into *phdr). Set *found based on whether the name/value
1071    ** was found in the propdb.
1072    **
1073    ** Note: it is NOT an error for the key/value pair to not exist.
1074    **
1075    ** The dav_xmlns_info passed to define_namespaces() is also passed to
1076    ** each output_value() call so that namespaces can be added on-demand.
1077    ** It can also be used to look up prefixes or URIs during the output
1078    ** process.
1079    */
1080    dav_error * (*output_value)(dav_db *db, const dav_prop_name *name,
1081                                dav_xmlns_info *xi,
1082                                apr_text_header *phdr, int *found);
1083
1084    /*
1085    ** Build a mapping from "global" namespaces (stored in apr_xml_*)
1086    ** into provider-local namespace identifiers.
1087    **
1088    ** This mapping should be done once per set of namespaces, and the
1089    ** resulting mapping should be passed into the store() hook function.
1090    **
1091    ** Note: usually, there is just a single document/namespaces for all
1092    ** elements passed. However, the generality of creating multiple
1093    ** mappings and passing them to store() is provided here.
1094    **
1095    ** Note: this is only in preparation for a series of store() calls.
1096    ** As a result, the propdb must be open for read/write access when
1097    ** this function is called.
1098    */
1099    dav_error * (*map_namespaces)(dav_db *db,
1100                                  const apr_array_header_t *namespaces,
1101                                  dav_namespace_map **mapping);
1102
1103    /*
1104    ** Store a property value for a given name. The value->combined field
1105    ** MUST be set for this call.
1106    **
1107    ** ### WARNING: current providers will quote the text within ELEM.
1108    ** ### this implies you can call this function only once with a given
1109    ** ### element structure (a second time will quote it again).
1110    */
1111    dav_error * (*store)(dav_db *db, const dav_prop_name *name,
1112                         const apr_xml_elem *elem,
1113                         dav_namespace_map *mapping);
1114
1115    /* remove a given property */
1116    dav_error * (*remove)(dav_db *db, const dav_prop_name *name);
1117
1118    /* returns 1 if the record specified by "key" exists; 0 otherwise */
1119    int (*exists)(dav_db *db, const dav_prop_name *name);
1120
1121    /*
1122    ** Iterate over the property names in the database.
1123    **
1124    ** iter->name.ns == iter->name.name == NULL when there are no more names.
1125    **
1126    ** Note: only one iteration may occur over the propdb at a time.
1127    */
1128    dav_error * (*first_name)(dav_db *db, dav_prop_name *pname);
1129    dav_error * (*next_name)(dav_db *db, dav_prop_name *pname);
1130
1131    /*
1132    ** Rollback support: get rollback context, and apply it.
1133    **
1134    ** struct dav_deadprop_rollback is a provider-private structure; it
1135    ** should remember the name, and the name's old value (or the fact that
1136    ** the value was not present, and should be deleted if a rollback occurs).
1137    */
1138    dav_error * (*get_rollback)(dav_db *db, const dav_prop_name *name,
1139                                dav_deadprop_rollback **prollback);
1140    dav_error * (*apply_rollback)(dav_db *db,
1141                                  dav_deadprop_rollback *rollback);
1142
1143    /*
1144    ** If a provider needs a context to associate with this hooks structure,
1145    ** then this field may be used. In most cases, it will just be NULL.
1146    */
1147    void *ctx;
1148};
1149
1150
1151/* --------------------------------------------------------------------
1152**
1153** LOCK FUNCTIONS
1154*/
1155
1156/* Used to represent a Timeout header of "Infinity" */
1157#define DAV_TIMEOUT_INFINITE 0
1158
1159DAV_DECLARE(time_t) dav_get_timeout(request_rec *r);
1160
1161/*
1162** Opaque, provider-specific information for a lock database.
1163*/
1164typedef struct dav_lockdb_private dav_lockdb_private;
1165
1166/*
1167** Opaque, provider-specific information for a lock record.
1168*/
1169typedef struct dav_lock_private dav_lock_private;
1170
1171/*
1172** Lock database type. Lock providers are urged to implement a "lazy" open, so
1173** doing an "open" is cheap until something is actually needed from the DB.
1174*/
1175typedef struct
1176{
1177    const dav_hooks_locks *hooks;   /* the hooks used for this lockdb */
1178    int ro;                         /* was it opened readonly? */
1179
1180    dav_lockdb_private *info;
1181
1182} dav_lockdb;
1183
1184typedef enum {
1185    DAV_LOCKSCOPE_UNKNOWN,
1186    DAV_LOCKSCOPE_EXCLUSIVE,
1187    DAV_LOCKSCOPE_SHARED
1188} dav_lock_scope;
1189
1190typedef enum {
1191    DAV_LOCKTYPE_UNKNOWN,
1192    DAV_LOCKTYPE_WRITE
1193} dav_lock_type;
1194
1195typedef enum {
1196    DAV_LOCKREC_DIRECT,             /* lock asserted on this resource */
1197    DAV_LOCKREC_INDIRECT,           /* lock inherited from a parent */
1198    DAV_LOCKREC_INDIRECT_PARTIAL    /* most info is not filled in */
1199} dav_lock_rectype;
1200
1201/*
1202** dav_lock: hold information about a lock on a resource.
1203**
1204** This structure is used for both direct and indirect locks. A direct lock
1205** is a lock applied to a specific resource by the client. An indirect lock
1206** is one that is inherited from a parent resource by virtue of a non-zero
1207** Depth: header when the lock was applied.
1208**
1209** mod_dav records both types of locks in the lock database, managing their
1210** addition/removal as resources are moved about the namespace.
1211**
1212** Note that the lockdb is free to marshal this structure in any form that
1213** it likes.
1214**
1215** For a "partial" lock, the <rectype> and <locktoken> fields must be filled
1216** in. All other (user) fields should be zeroed. The lock provider will
1217** usually fill in the <info> field, and the <next> field may be used to
1218** construct a list of partial locks.
1219**
1220** The lock provider MUST use the info field to store a value such that a
1221** dav_lock structure can locate itself in the underlying lock database.
1222** This requirement is needed for refreshing: when an indirect dav_lock is
1223** refreshed, its reference to the direct lock does not specify the direct's
1224** resource, so the only way to locate the (refreshed, direct) lock in the
1225** database is to use the info field.
1226**
1227** Note that <is_locknull> only refers to the resource where this lock was
1228** found.
1229** ### hrm. that says the abstraction is wrong. is_locknull may disappear.
1230*/
1231typedef struct dav_lock
1232{
1233    dav_lock_rectype rectype;   /* type of lock record */
1234    int is_locknull;            /* lock establishes a locknull resource */
1235
1236    /* ### put the resource in here? */
1237
1238    dav_lock_scope scope;       /* scope of the lock */
1239    dav_lock_type type;         /* type of lock */
1240    int depth;                  /* depth of the lock */
1241    time_t timeout;             /* when the lock will timeout */
1242
1243    const dav_locktoken *locktoken;  /* the token that was issued */
1244
1245    const char *owner;          /* (XML) owner of the lock */
1246    const char *auth_user;      /* auth'd username owning lock */
1247
1248    dav_lock_private *info;     /* private to the lockdb */
1249
1250    struct dav_lock *next;      /* for managing a list of locks */
1251} dav_lock;
1252
1253/* Property-related public lock functions */
1254DAV_DECLARE(const char *)dav_lock_get_activelock(request_rec *r,
1255                                                 dav_lock *locks,
1256                                                 dav_buffer *pbuf);
1257
1258/* LockDB-related public lock functions */
1259DAV_DECLARE(dav_error *) dav_lock_parse_lockinfo(request_rec *r,
1260                                                 const dav_resource *resrouce,
1261                                                 dav_lockdb *lockdb,
1262                                                 const apr_xml_doc *doc,
1263                                                 dav_lock **lock_request);
1264DAV_DECLARE(int) dav_unlock(request_rec *r,
1265                            const dav_resource *resource,
1266                            const dav_locktoken *locktoken);
1267DAV_DECLARE(dav_error *) dav_add_lock(request_rec *r,
1268                                      const dav_resource *resource,
1269                                      dav_lockdb *lockdb, dav_lock *request,
1270                                      dav_response **response);
1271DAV_DECLARE(dav_error *) dav_notify_created(request_rec *r,
1272                                            dav_lockdb *lockdb,
1273                                            const dav_resource *resource,
1274                                            int resource_state,
1275                                            int depth);
1276
1277DAV_DECLARE(dav_error*) dav_lock_query(dav_lockdb *lockdb,
1278                                       const dav_resource *resource,
1279                                       dav_lock **locks);
1280
1281DAV_DECLARE(dav_error *) dav_validate_request(request_rec *r,
1282                                              dav_resource *resource,
1283                                              int depth,
1284                                              dav_locktoken *locktoken,
1285                                              dav_response **response,
1286                                              int flags,
1287                                              dav_lockdb *lockdb);
1288/*
1289** flags:
1290**    0x0F -- reserved for <dav_lock_scope> values
1291**
1292**    other flags, detailed below
1293*/
1294#define DAV_VALIDATE_RESOURCE   0x0010  /* validate just the resource */
1295#define DAV_VALIDATE_PARENT     0x0020  /* validate resource AND its parent */
1296#define DAV_VALIDATE_ADD_LD     0x0040  /* add DAV:lockdiscovery into
1297                                           the 424 DAV:response */
1298#define DAV_VALIDATE_USE_424    0x0080  /* return 424 status, not 207 */
1299#define DAV_VALIDATE_IS_PARENT  0x0100  /* for internal use */
1300#define DAV_VALIDATE_NO_MODIFY  0x0200  /* resource is not being modified
1301                                           so allow even if lock token
1302                                           is not provided */
1303
1304/* Lock-null related public lock functions */
1305DAV_DECLARE(int) dav_get_resource_state(request_rec *r,
1306                                        const dav_resource *resource);
1307
1308/* Lock provider hooks. Locking is optional, so there may be no
1309 * lock provider for a given repository.
1310 */
1311struct dav_hooks_locks
1312{
1313    /* Return the supportedlock property for a resource */
1314    const char * (*get_supportedlock)(
1315        const dav_resource *resource
1316    );
1317
1318    /* Parse a lock token URI, returning a lock token object allocated
1319     * in the given pool.
1320     */
1321    dav_error * (*parse_locktoken)(
1322        apr_pool_t *p,
1323        const char *char_token,
1324        dav_locktoken **locktoken_p
1325    );
1326
1327    /* Format a lock token object into a URI string, allocated in
1328     * the given pool.
1329     *
1330     * Always returns non-NULL.
1331     */
1332    const char * (*format_locktoken)(
1333        apr_pool_t *p,
1334        const dav_locktoken *locktoken
1335    );
1336
1337    /* Compare two lock tokens.
1338     *
1339     * Result < 0  => lt1 < lt2
1340     * Result == 0 => lt1 == lt2
1341     * Result > 0  => lt1 > lt2
1342     */
1343    int (*compare_locktoken)(
1344        const dav_locktoken *lt1,
1345        const dav_locktoken *lt2
1346    );
1347
1348    /* Open the provider's lock database.
1349     *
1350     * The provider may or may not use a "real" database for locks
1351     * (a lock could be an attribute on a resource, for example).
1352     *
1353     * The provider may choose to use the value of the DAVLockDB directive
1354     * (as returned by dav_get_lockdb_path()) to decide where to place
1355     * any storage it may need.
1356     *
1357     * The request storage pool should be associated with the lockdb,
1358     * so it can be used in subsequent operations.
1359     *
1360     * If ro != 0, only readonly operations will be performed.
1361     * If force == 0, the open can be "lazy"; no subsequent locking operations
1362     * may occur.
1363     * If force != 0, locking operations will definitely occur.
1364     */
1365    dav_error * (*open_lockdb)(
1366        request_rec *r,
1367        int ro,
1368        int force,
1369        dav_lockdb **lockdb
1370    );
1371
1372    /* Indicates completion of locking operations */
1373    void (*close_lockdb)(
1374        dav_lockdb *lockdb
1375    );
1376
1377    /* Take a resource out of the lock-null state. */
1378    dav_error * (*remove_locknull_state)(
1379        dav_lockdb *lockdb,
1380        const dav_resource *resource
1381    );
1382
1383    /*
1384    ** Create a (direct) lock structure for the given resource. A locktoken
1385    ** will be created.
1386    **
1387    ** The lock provider may store private information into lock->info.
1388    */
1389    dav_error * (*create_lock)(dav_lockdb *lockdb,
1390                               const dav_resource *resource,
1391                               dav_lock **lock);
1392
1393    /*
1394    ** Get the locks associated with the specified resource.
1395    **
1396    ** If resolve_locks is true (non-zero), then any indirect locks are
1397    ** resolved to their actual, direct lock (i.e. the reference to followed
1398    ** to the original lock).
1399    **
1400    ** The locks, if any, are returned as a linked list in no particular
1401    ** order. If no locks are present, then *locks will be NULL.
1402    */
1403    dav_error * (*get_locks)(dav_lockdb *lockdb,
1404                             const dav_resource *resource,
1405                             int calltype,
1406                             dav_lock **locks);
1407
1408#define DAV_GETLOCKS_RESOLVED   0    /* resolve indirects to directs */
1409#define DAV_GETLOCKS_PARTIAL    1    /* leave indirects partially filled */
1410#define DAV_GETLOCKS_COMPLETE   2    /* fill out indirect locks */
1411
1412    /*
1413    ** Find a particular lock on a resource (specified by its locktoken).
1414    **
1415    ** *lock will be set to NULL if the lock is not found.
1416    **
1417    ** Note that the provider can optimize the unmarshalling -- only one
1418    ** lock (or none) must be constructed and returned.
1419    **
1420    ** If partial_ok is true (non-zero), then an indirect lock can be
1421    ** partially filled in. Otherwise, another lookup is done and the
1422    ** lock structure will be filled out as a DAV_LOCKREC_INDIRECT.
1423    */
1424    dav_error * (*find_lock)(dav_lockdb *lockdb,
1425                             const dav_resource *resource,
1426                             const dav_locktoken *locktoken,
1427                             int partial_ok,
1428                             dav_lock **lock);
1429
1430    /*
1431    ** Quick test to see if the resource has *any* locks on it.
1432    **
1433    ** This is typically used to determine if a non-existent resource
1434    ** has a lock and is (therefore) a locknull resource.
1435    **
1436    ** WARNING: this function may return TRUE even when timed-out locks
1437    **          exist (i.e. it may not perform timeout checks).
1438    */
1439    dav_error * (*has_locks)(dav_lockdb *lockdb,
1440                             const dav_resource *resource,
1441                             int *locks_present);
1442
1443    /*
1444    ** Append the specified lock(s) to the set of locks on this resource.
1445    **
1446    ** If "make_indirect" is true (non-zero), then the specified lock(s)
1447    ** should be converted to an indirect lock (if it is a direct lock)
1448    ** before appending. Note that the conversion to an indirect lock does
1449    ** not alter the passed-in lock -- the change is internal the
1450    ** append_locks function.
1451    **
1452    ** Multiple locks are specified using the lock->next links.
1453    */
1454    dav_error * (*append_locks)(dav_lockdb *lockdb,
1455                                const dav_resource *resource,
1456                                int make_indirect,
1457                                const dav_lock *lock);
1458
1459    /*
1460    ** Remove any lock that has the specified locktoken.
1461    **
1462    ** If locktoken == NULL, then ALL locks are removed.
1463    */
1464    dav_error * (*remove_lock)(dav_lockdb *lockdb,
1465                               const dav_resource *resource,
1466                               const dav_locktoken *locktoken);
1467
1468    /*
1469    ** Refresh all locks, found on the specified resource, which has a
1470    ** locktoken in the provided list.
1471    **
1472    ** If the lock is indirect, then the direct lock is referenced and
1473    ** refreshed.
1474    **
1475    ** Each lock that is updated is returned in the <locks> argument.
1476    ** Note that the locks will be fully resolved.
1477    */
1478    dav_error * (*refresh_locks)(dav_lockdb *lockdb,
1479                                 const dav_resource *resource,
1480                                 const dav_locktoken_list *ltl,
1481                                 time_t new_time,
1482                                 dav_lock **locks);
1483
1484    /*
1485    ** Look up the resource associated with a particular locktoken.
1486    **
1487    ** The search begins at the specified <start_resource> and the lock
1488    ** specified by <locktoken>.
1489    **
1490    ** If the resource/token specifies an indirect lock, then the direct
1491    ** lock will be looked up, and THAT resource will be returned. In other
1492    ** words, this function always returns the resource where a particular
1493    ** lock (token) was asserted.
1494    **
1495    ** NOTE: this function pointer is allowed to be NULL, indicating that
1496    **       the provider does not support this type of functionality. The
1497    **       caller should then traverse up the repository hierarchy looking
1498    **       for the resource defining a lock with this locktoken.
1499    */
1500    dav_error * (*lookup_resource)(dav_lockdb *lockdb,
1501                                   const dav_locktoken *locktoken,
1502                                   const dav_resource *start_resource,
1503                                   const dav_resource **resource);
1504
1505    /*
1506    ** If a provider needs a context to associate with this hooks structure,
1507    ** then this field may be used. In most cases, it will just be NULL.
1508    */
1509    void *ctx;
1510};
1511
1512/* what types of resources can be discovered by dav_get_resource_state() */
1513#define DAV_RESOURCE_LOCK_NULL  10    /* resource lock-null */
1514#define DAV_RESOURCE_NULL       11    /* resource null */
1515#define DAV_RESOURCE_EXISTS     12    /* resource exists */
1516#define DAV_RESOURCE_ERROR      13    /* an error occurred */
1517
1518
1519/* --------------------------------------------------------------------
1520**
1521** PROPERTY HANDLING
1522*/
1523
1524typedef struct dav_propdb dav_propdb;
1525
1526
1527DAV_DECLARE(dav_error *) dav_open_propdb(
1528    request_rec *r,
1529    dav_lockdb *lockdb,
1530    const dav_resource *resource,
1531    int ro,
1532    apr_array_header_t *ns_xlate,
1533    dav_propdb **propdb);
1534
1535DAV_DECLARE(void) dav_close_propdb(dav_propdb *db);
1536
1537DAV_DECLARE(dav_get_props_result) dav_get_props(
1538    dav_propdb *db,
1539    apr_xml_doc *doc);
1540
1541DAV_DECLARE(dav_get_props_result) dav_get_allprops(
1542    dav_propdb *db,
1543    dav_prop_insert what);
1544
1545DAV_DECLARE(void) dav_get_liveprop_supported(
1546    dav_propdb *propdb,
1547    const char *ns_uri,
1548    const char *propname,
1549    apr_text_header *body);
1550
1551/*
1552** 3-phase property modification.
1553**
1554**   1) validate props. readable? unlocked? ACLs allow access?
1555**   2) execute operation (set/delete)
1556**   3) commit or rollback
1557**
1558** ### eventually, auth must be available. a ref to the request_rec (which
1559** ### contains the auth info) should be in the shared context struct.
1560**
1561** Each function may alter the error values and information contained within
1562** the context record. This should be done as an "increasing" level of
1563** error, rather than overwriting any previous error.
1564**
1565** Note that commit() cannot generate errors. It should simply free the
1566** rollback information.
1567**
1568** rollback() may generate additional errors because the rollback operation
1569** can sometimes fail(!).
1570**
1571** The caller should allocate an array of these, one per operation. It should
1572** be zero-initialized, then the db, operation, and prop fields should be
1573** filled in before calling dav_prop_validate. Note that the set/delete
1574** operations are order-dependent. For a given (logical) context, the same
1575** pointer must be passed to each phase.
1576**
1577** error_type is an internal value, but will have the same numeric value
1578** for each possible "desc" value. This allows the caller to group the
1579** descriptions via the error_type variable, rather than through string
1580** comparisons. Note that "status" does not provide enough granularity to
1581** differentiate/group the "desc" values.
1582**
1583** Note that the propdb will maintain some (global) context across all
1584** of the property change contexts. This implies that you can have only
1585** one open transaction per propdb.
1586*/
1587typedef struct dav_prop_ctx
1588{
1589    dav_propdb *propdb;
1590
1591    apr_xml_elem *prop;             /* property to affect */
1592
1593    int operation;
1594#define DAV_PROP_OP_SET        1    /* set a property value */
1595#define DAV_PROP_OP_DELETE     2    /* delete a prop value */
1596/* ### add a GET? */
1597
1598    /* private items to the propdb */
1599    int is_liveprop;
1600    void *liveprop_ctx;
1601    struct dav_rollback_item *rollback;  /* optional rollback info */
1602
1603    dav_error *err;                 /* error (if any) */
1604
1605    /* private to mod_dav.c */
1606    request_rec *r;
1607
1608} dav_prop_ctx;
1609
1610DAV_DECLARE_NONSTD(void) dav_prop_validate(dav_prop_ctx *ctx);
1611DAV_DECLARE_NONSTD(void) dav_prop_exec(dav_prop_ctx *ctx);
1612DAV_DECLARE_NONSTD(void) dav_prop_commit(dav_prop_ctx *ctx);
1613DAV_DECLARE_NONSTD(void) dav_prop_rollback(dav_prop_ctx *ctx);
1614
1615#define DAV_PROP_CTX_HAS_ERR(dpc)  ((dpc).err && (dpc).err->status >= 300)
1616
1617
1618/* --------------------------------------------------------------------
1619**
1620** WALKER STRUCTURE
1621*/
1622
1623enum {
1624    DAV_CALLTYPE_MEMBER = 1,    /* called for a member resource */
1625    DAV_CALLTYPE_COLLECTION,    /* called for a collection */
1626    DAV_CALLTYPE_LOCKNULL       /* called for a locknull resource */
1627};
1628
1629typedef struct
1630{
1631    /* the client-provided context */
1632    void *walk_ctx;
1633
1634    /* pool to use for allocations in the callback */
1635    apr_pool_t *pool;
1636
1637    /* the current resource */
1638    const dav_resource *resource;
1639
1640    /* OUTPUT: add responses to this */
1641    dav_response *response;
1642
1643} dav_walk_resource;
1644
1645typedef struct
1646{
1647    int walk_type;
1648#define DAV_WALKTYPE_AUTH       0x0001  /* limit to authorized files */
1649#define DAV_WALKTYPE_NORMAL     0x0002  /* walk normal files */
1650#define DAV_WALKTYPE_LOCKNULL   0x0004  /* walk locknull resources */
1651
1652    /* callback function and a client context for the walk */
1653    dav_error * (*func)(dav_walk_resource *wres, int calltype);
1654    void *walk_ctx;
1655
1656    /* what pool to use for allocations needed by walk logic */
1657    apr_pool_t *pool;
1658
1659    /* beginning root of the walk */
1660    const dav_resource *root;
1661
1662    /* lock database to enable walking LOCKNULL resources */
1663    dav_lockdb *lockdb;
1664
1665} dav_walk_params;
1666
1667/* directory tree walking context */
1668typedef struct dav_walker_ctx
1669{
1670    /* input: */
1671    dav_walk_params w;
1672
1673
1674    /* ### client data... phasing out this big glom */
1675
1676    /* this brigade buffers data being sent to r->output_filters */
1677    apr_bucket_brigade *bb;
1678
1679    /* a scratch pool, used to stream responses and iteratively cleared. */
1680    apr_pool_t *scratchpool;
1681
1682    request_rec *r;                 /* original request */
1683
1684    /* for PROPFIND operations */
1685    apr_xml_doc *doc;
1686    int propfind_type;
1687#define DAV_PROPFIND_IS_ALLPROP     1
1688#define DAV_PROPFIND_IS_PROPNAME    2
1689#define DAV_PROPFIND_IS_PROP        3
1690
1691    apr_text *propstat_404;         /* (cached) propstat giving a 404 error */
1692
1693    const dav_if_header *if_header; /* for validation */
1694    const dav_locktoken *locktoken; /* for UNLOCK */
1695    const dav_lock *lock;           /* for LOCK */
1696    int skip_root;                  /* for dav_inherit_locks() */
1697
1698    int flags;
1699
1700    dav_buffer work_buf;            /* for dav_validate_request() */
1701
1702} dav_walker_ctx;
1703
1704DAV_DECLARE(void) dav_add_response(dav_walk_resource *wres,
1705                                   int status,
1706                                   dav_get_props_result *propstats);
1707
1708
1709/* --------------------------------------------------------------------
1710**
1711** "STREAM" STRUCTURE
1712**
1713** mod_dav uses this abstraction for interacting with the repository
1714** while fetching/storing resources. mod_dav views resources as a stream
1715** of bytes.
1716**
1717** Note that the structure is opaque -- it is private to the repository
1718** that created the stream in the repository's "open" function.
1719**
1720** ### THIS STUFF IS GOING AWAY ... GET/read requests are handled by
1721** ### having the provider jam stuff straight into the filter stack.
1722** ### this is only left for handling PUT/write requests.
1723*/
1724
1725typedef struct dav_stream dav_stream;
1726
1727typedef enum {
1728    DAV_MODE_WRITE_TRUNC,      /* truncate and open for writing */
1729    DAV_MODE_WRITE_SEEKABLE    /* open for writing; random access */
1730} dav_stream_mode;
1731
1732
1733/* --------------------------------------------------------------------
1734**
1735** REPOSITORY FUNCTIONS
1736*/
1737
1738/* Repository provider hooks */
1739struct dav_hooks_repository
1740{
1741    /* Flag for whether repository requires special GET handling.
1742     * If resources in the repository are not visible in the
1743     * filesystem location which URLs map to, then special handling
1744     * is required to first fetch a resource from the repository,
1745     * respond to the GET request, then free the resource copy.
1746     */
1747    int handle_get;
1748
1749    /* Get a resource descriptor for the URI in a request. A descriptor
1750     * should always be returned even if the resource does not exist. This
1751     * repository has been identified as handling the resource given by
1752     * the URI, so an answer must be given. If there is a problem with the
1753     * URI or accessing the resource or whatever, then an error should be
1754     * returned.
1755     *
1756     * root_dir:
1757     *   the root of the directory for which this repository is configured.
1758     *
1759     * label:
1760     *   if a Label: header is present (and allowed), this is the label
1761     *   to use to identify a version resource from the resource's
1762     *   corresponding version history. Otherwise, it will be NULL.
1763     *
1764     * use_checked_in:
1765     *   use the DAV:checked-in property of the resource identified by the
1766     *   Request-URI to identify and return a version resource
1767     *
1768     * The provider may associate the request storage pool with the resource
1769     * (in the resource->pool field), to use in other operations on that
1770     * resource.
1771     */
1772    dav_error * (*get_resource)(
1773        request_rec *r,
1774        const char *root_dir,
1775        const char *label,
1776        int use_checked_in,
1777        dav_resource **resource
1778    );
1779
1780    /* Get a resource descriptor for the parent of the given resource.
1781     * The resources need not exist.  NULL is returned if the resource
1782     * is the root collection.
1783     *
1784     * An error should be returned only if there is a fatal error in
1785     * fetching information about the parent resource.
1786     */
1787    dav_error * (*get_parent_resource)(
1788        const dav_resource *resource,
1789        dav_resource **parent_resource
1790    );
1791
1792    /* Determine whether two resource descriptors refer to the same resource.
1793    *
1794     * Result != 0 => the resources are the same.
1795     */
1796    int (*is_same_resource)(
1797        const dav_resource *res1,
1798        const dav_resource *res2
1799    );
1800
1801    /* Determine whether one resource is a parent (immediate or otherwise)
1802     * of another.
1803     *
1804     * Result != 0 => res1 is a parent of res2.
1805     */
1806    int (*is_parent_resource)(
1807        const dav_resource *res1,
1808        const dav_resource *res2
1809    );
1810
1811    /*
1812    ** Open a stream for this resource, using the specified mode. The
1813    ** stream will be returned in *stream.
1814    */
1815    dav_error * (*open_stream)(const dav_resource *resource,
1816                               dav_stream_mode mode,
1817                               dav_stream **stream);
1818
1819    /*
1820    ** Close the specified stream.
1821    **
1822    ** mod_dav will (ideally) make sure to call this. For safety purposes,
1823    ** a provider should (ideally) register a cleanup function with the
1824    ** request pool to get this closed and cleaned up.
1825    **
1826    ** Note the possibility of an error from the close -- it is entirely
1827    ** feasible that the close does a "commit" of some kind, which can
1828    ** produce an error.
1829    **
1830    ** commit should be TRUE (non-zero) or FALSE (0) if the stream was
1831    ** opened for writing. This flag states whether to retain the file
1832    ** or not.
1833    ** Note: the commit flag is ignored for streams opened for reading.
1834    */
1835    dav_error * (*close_stream)(dav_stream *stream, int commit);
1836
1837    /*
1838    ** Write data to the stream.
1839    **
1840    ** All of the bytes must be written, or an error should be returned.
1841    */
1842    dav_error * (*write_stream)(dav_stream *stream,
1843                                const void *buf, apr_size_t bufsize);
1844
1845    /*
1846    ** Seek to an absolute position in the stream. This is used to support
1847    ** Content-Range in a GET/PUT.
1848    **
1849    ** NOTE: if this function is NULL (which is allowed), then any
1850    **       operations using Content-Range will be refused.
1851    */
1852    dav_error * (*seek_stream)(dav_stream *stream, apr_off_t abs_position);
1853
1854    /*
1855    ** If a GET is processed using a stream (open_stream, read_stream)
1856    ** rather than via a sub-request (on get_pathname), then this function
1857    ** is used to provide the repository with a way to set the headers
1858    ** in the response.
1859    **
1860    ** This function may be called without a following deliver(), to
1861    ** handle a HEAD request.
1862    **
1863    ** This may be NULL if handle_get is FALSE.
1864    */
1865    dav_error * (*set_headers)(request_rec *r,
1866                               const dav_resource *resource);
1867
1868    /*
1869    ** The provider should deliver the resource into the specified filter.
1870    ** Basically, this is the response to the GET method.
1871    **
1872    ** Note that this is called for all resources, including collections.
1873    ** The provider should determine what has content to deliver or not.
1874    **
1875    ** set_headers will be called prior to this function, allowing the
1876    ** provider to set the appropriate response headers.
1877    **
1878    ** This may be NULL if handle_get is FALSE.
1879    ** ### maybe toss handle_get and just use this function as the marker
1880    */
1881    dav_error * (*deliver)(const dav_resource *resource,
1882                           ap_filter_t *output);
1883
1884    /* Create a collection resource. The resource must not already exist.
1885     *
1886     * Result == NULL if the collection was created successfully. Also, the
1887     * resource object is updated to reflect that the resource exists, and
1888     * is a collection.
1889     */
1890    dav_error * (*create_collection)(
1891        dav_resource *resource
1892    );
1893
1894    /* Copy one resource to another. The destination may exist, if it is
1895     * versioned.
1896     * Handles both files and collections. Properties are copied as well.
1897     * If the destination exists and is versioned, the provider must update
1898     * the destination to have identical content to the source,
1899     * recursively for collections.
1900     * The depth argument is ignored for a file, and can be either 0 or
1901     * DAV_INFINITY for a collection.
1902     * If an error occurs in a child resource, then the return value is
1903     * non-NULL, and *response is set to a multistatus response.
1904     * If the copy is successful, the dst resource object is
1905     * updated to reflect that the resource exists.
1906     */
1907    dav_error * (*copy_resource)(
1908        const dav_resource *src,
1909        dav_resource *dst,
1910        int depth,
1911        dav_response **response
1912    );
1913
1914    /* Move one resource to another. The destination must not exist.
1915     * Handles both files and collections. Properties are moved as well.
1916     * If an error occurs in a child resource, then the return value is
1917     * non-NULL, and *response is set to a multistatus response.
1918     * If the move is successful, the src and dst resource objects are
1919     * updated to reflect that the source no longer exists, and the
1920     * destination does.
1921     */
1922    dav_error * (*move_resource)(
1923        dav_resource *src,
1924        dav_resource *dst,
1925        dav_response **response
1926    );
1927
1928    /* Remove a resource. Handles both files and collections.
1929     * Removes any associated properties as well.
1930     * If an error occurs in a child resource, then the return value is
1931     * non-NULL, and *response is set to a multistatus response.
1932     * If the delete is successful, the resource object is updated to
1933     * reflect that the resource no longer exists.
1934     */
1935    dav_error * (*remove_resource)(
1936        dav_resource *resource,
1937        dav_response **response
1938    );
1939
1940    /* Walk a resource hierarchy.
1941     *
1942     * Iterates over the resource hierarchy specified by params->root.
1943     * Control of the walk and the callback are specified by 'params'.
1944     *
1945     * An error may be returned. *response will contain multistatus
1946     * responses (if any) suitable for the body of the error. It is also
1947     * possible to return NULL, yet still have multistatus responses.
1948     * In this case, typically the caller should return a 207 (Multistatus)
1949     * and the responses (in the body) as the HTTP response.
1950     */
1951    dav_error * (*walk)(const dav_walk_params *params, int depth,
1952                        dav_response **response);
1953
1954    /* Get the entity tag for a resource */
1955    const char * (*getetag)(const dav_resource *resource);
1956
1957    /*
1958    ** If a provider needs a context to associate with this hooks structure,
1959    ** then this field may be used. In most cases, it will just be NULL.
1960    */
1961    void *ctx;
1962
1963    /* Get the request rec for a resource */
1964    request_rec * (*get_request_rec)(const dav_resource *resource);
1965
1966    /* Get the pathname for a resource */
1967    const char * (*get_pathname)(const dav_resource *resource);
1968};
1969
1970
1971/* --------------------------------------------------------------------
1972**
1973** VERSIONING FUNCTIONS
1974*/
1975
1976
1977/* dav_add_vary_header
1978 *
1979 * If there were any headers in the request which require a Vary header
1980 * in the response, add it.
1981 */
1982DAV_DECLARE(void) dav_add_vary_header(request_rec *in_req,
1983                                      request_rec *out_req,
1984                                      const dav_resource *resource);
1985
1986/*
1987** Flags specifying auto-versioning behavior, returned by
1988** the auto_versionable hook. The value returned depends
1989** on both the state of the resource and the value of the
1990** DAV:auto-versioning property for the resource.
1991**
1992** If the resource does not exist (null or lock-null),
1993** DAV_AUTO_VERSION_ALWAYS causes creation of a new version-controlled resource
1994**
1995** If the resource is checked in,
1996** DAV_AUTO_VERSION_ALWAYS causes it to be checked out always,
1997** DAV_AUTO_VERSION_LOCKED causes it to be checked out only when locked
1998**
1999** If the resource is checked out,
2000** DAV_AUTO_VERSION_ALWAYS causes it to be checked in always,
2001** DAV_AUTO_VERSION_LOCKED causes it to be checked in when unlocked
2002** (note: a provider should allow auto-checkin only for resources which
2003** were automatically checked out)
2004**
2005** In all cases, DAV_AUTO_VERSION_NEVER results in no auto-versioning behavior.
2006*/
2007typedef enum {
2008    DAV_AUTO_VERSION_NEVER,
2009    DAV_AUTO_VERSION_ALWAYS,
2010    DAV_AUTO_VERSION_LOCKED
2011} dav_auto_version;
2012
2013/*
2014** This structure is used to record what auto-versioning operations
2015** were done to make a resource writable, so that they can be undone
2016** at the end of a request.
2017*/
2018typedef struct {
2019    int resource_versioned;             /* 1 => resource was auto-version-controlled */
2020    int resource_checkedout;            /* 1 => resource was auto-checked-out */
2021    int parent_checkedout;              /* 1 => parent was auto-checked-out */
2022    dav_resource *parent_resource;      /* parent resource, if it was needed */
2023} dav_auto_version_info;
2024
2025/* Ensure that a resource is writable. If there is no versioning
2026 * provider, then this is essentially a no-op. Versioning repositories
2027 * require explicit resource creation and checkout before they can
2028 * be written to. If a new resource is to be created, or an existing
2029 * resource deleted, the parent collection must be checked out as well.
2030 *
2031 * Set the parent_only flag to only make the parent collection writable.
2032 * Otherwise, both parent and child are made writable as needed. If the
2033 * child does not exist, then a new versioned resource is created and
2034 * checked out.
2035 *
2036 * If auto-versioning is not enabled for a versioned resource, then an error is
2037 * returned, since the resource cannot be modified.
2038 *
2039 * The dav_auto_version_info structure is filled in with enough information
2040 * to restore both parent and child resources to the state they were in
2041 * before the auto-versioning operations occurred.
2042 */
2043DAV_DECLARE(dav_error *) dav_auto_checkout(
2044    request_rec *r,
2045    dav_resource *resource,
2046    int parent_only,
2047    dav_auto_version_info *av_info);
2048
2049/* Revert the writability of resources back to what they were
2050 * before they were modified. If undo == 0, then the resource
2051 * modifications are maintained (i.e. they are checked in).
2052 * If undo != 0, then resource modifications are discarded
2053 * (i.e. they are unchecked out).
2054 *
2055 * Set the unlock flag to indicate that the resource is about
2056 * to be unlocked; it will be checked in if the resource
2057 * auto-versioning property indicates it should be. In this case,
2058 * av_info is ignored, so it can be NULL.
2059 *
2060 * The resource argument may be NULL if only the parent resource
2061 * was checked out (i.e. the parent_only was != 0 in the
2062 * dav_auto_checkout call).
2063 */
2064DAV_DECLARE(dav_error *) dav_auto_checkin(
2065    request_rec *r,
2066    dav_resource *resource,
2067    int undo,
2068    int unlock,
2069    dav_auto_version_info *av_info);
2070
2071/*
2072** This structure is used to describe available reports
2073**
2074** "nmspace" should be valid XML and URL-quoted. mod_dav will place
2075** double-quotes around it and use it in an xmlns declaration.
2076*/
2077typedef struct {
2078    const char *nmspace;        /* namespace of the XML report element */
2079    const char *name;           /* element name for the XML report */
2080} dav_report_elem;
2081
2082
2083/* Versioning provider hooks */
2084struct dav_hooks_vsn
2085{
2086    /*
2087    ** MANDATORY HOOKS
2088    ** The following hooks are mandatory for all versioning providers;
2089    ** they define the functionality needed to implement "core" versioning.
2090    */
2091
2092    /* Return supported versioning options.
2093     * Each dav_text item in the list will be returned as a separate
2094     * DAV header. Providers are advised to limit the length of an
2095     * individual text item to 63 characters, to conform to the limit
2096     * used by MS Web Folders.
2097     */
2098    void (*get_vsn_options)(apr_pool_t *p, apr_text_header *phdr);
2099
2100    /* Get the value of a specific option for an OPTIONS request.
2101     * The option being requested is given by the parsed XML
2102     * element object "elem". The value of the option should be
2103     * appended to the "option" text object.
2104     */
2105    dav_error * (*get_option)(const dav_resource *resource,
2106                              const apr_xml_elem *elem,
2107                              apr_text_header *option);
2108
2109    /* Determine whether a non-versioned (or non-existent) resource
2110     * is versionable. Returns != 0 if resource can be versioned.
2111     */
2112    int (*versionable)(const dav_resource *resource);
2113
2114    /* Determine whether auto-versioning is enabled for a resource
2115     * (which may not exist, or may not be versioned). If the resource
2116     * is a checked-out resource, the provider must only enable
2117     * auto-checkin if the resource was automatically checked out.
2118     *
2119     * The value returned depends on both the state of the resource
2120     * and the value of its DAV:auto-version property. See the description
2121     * of the dav_auto_version enumeration above for the details.
2122     */
2123    dav_auto_version (*auto_versionable)(const dav_resource *resource);
2124
2125    /* Put a resource under version control. If the resource already
2126     * exists unversioned, then it becomes the initial version of the
2127     * new version history, and it is replaced by a version selector
2128     * which targets the new version.
2129     *
2130     * If the resource does not exist, then a new version-controlled
2131     * resource is created which either targets an existing version (if the
2132     * "target" argument is not NULL), or the initial, empty version
2133     * in a new history resource (if the "target" argument is NULL).
2134     *
2135     * If successful, the resource object state is updated appropriately
2136     * (that is, changed to refer to the new version-controlled resource).
2137     */
2138    dav_error * (*vsn_control)(dav_resource *resource,
2139                               const char *target);
2140
2141    /* Checkout a resource. If successful, the resource
2142     * object state is updated appropriately.
2143     *
2144     * The auto_checkout flag will be set if this checkout is being
2145     * done automatically, as part of some method which modifies
2146     * the resource. The provider must remember that the resource
2147     * was automatically checked out, so it can determine whether it
2148     * can be automatically checked in. (Auto-checkin should only be
2149     * enabled for resources which were automatically checked out.)
2150     *
2151     * If the working resource has a different URL from the
2152     * target resource, a dav_resource descriptor is returned
2153     * for the new working resource. Otherwise, the original
2154     * resource descriptor will refer to the working resource.
2155     * The working_resource argument can be NULL if the caller
2156     * is not interested in the working resource.
2157     *
2158     * If the client has specified DAV:unreserved or DAV:fork-ok in the
2159     * checkout request, then the corresponding flags are set. If
2160     * DAV:activity-set has been specified, then create_activity is set
2161     * if DAV:new was specified; otherwise, the DAV:href elements' CDATA
2162     * (the actual href text) is passed in the "activities" array (each
2163     * element of the array is a const char *). activities will be NULL
2164     * no DAV:activity-set was provided or when create_activity is set.
2165     */
2166    dav_error * (*checkout)(dav_resource *resource,
2167                            int auto_checkout,
2168                            int is_unreserved, int is_fork_ok,
2169                            int create_activity,
2170                            apr_array_header_t *activities,
2171                            dav_resource **working_resource);
2172
2173    /* Uncheckout a checked-out resource. If successful, the resource
2174     * object state is updated appropriately.
2175     */
2176    dav_error * (*uncheckout)(dav_resource *resource);
2177
2178    /* Checkin a checked-out resource. If successful, the resource
2179     * object state is updated appropriately, and the
2180     * version_resource descriptor will refer to the new version.
2181     * The version_resource argument can be NULL if the caller
2182     * is not interested in the new version resource.
2183     *
2184     * If the client has specified DAV:keep-checked-out in the checkin
2185     * request, then the keep_checked_out flag is set. The provider
2186     * should create a new version, but keep the resource in the
2187     * checked-out state.
2188     */
2189    dav_error * (*checkin)(dav_resource *resource,
2190                           int keep_checked_out,
2191                           dav_resource **version_resource);
2192
2193    /*
2194    ** Return the set of reports available at this resource.
2195    **
2196    ** An array of report elements should be returned, with an end-marker
2197    ** element containing namespace==NULL. The value of the
2198    ** DAV:supported-report-set property will be constructed and
2199    ** returned.
2200    */
2201    dav_error * (*avail_reports)(const dav_resource *resource,
2202                                 const dav_report_elem **reports);
2203
2204    /*
2205    ** Determine whether a Label header can be used
2206    ** with a particular report. The dav_xml_doc structure
2207    ** contains the parsed report request body.
2208    ** Returns 0 if the Label header is not allowed.
2209    */
2210    int (*report_label_header_allowed)(const apr_xml_doc *doc);
2211
2212    /*
2213    ** Generate a report on a resource. Since a provider is free
2214    ** to define its own reports, and the value of request headers
2215    ** may affect the interpretation of a report, the request record
2216    ** must be passed to this routine.
2217    **
2218    ** The dav_xml_doc structure contains the parsed report request
2219    ** body. The report response should be generated into the specified
2220    ** output filter.
2221    **
2222    ** If an error occurs, and a response has not yet been generated,
2223    ** then an error can be returned from this function. mod_dav will
2224    ** construct an appropriate error response. Once some output has
2225    ** been placed into the filter, however, the provider should not
2226    ** return an error -- there is no way that mod_dav can deliver it
2227    ** properly.
2228    **
2229    ** ### maybe we need a way to signal an error anyways, and then
2230    ** ### apache can abort the connection?
2231    */
2232    dav_error * (*deliver_report)(request_rec *r,
2233                                  const dav_resource *resource,
2234                                  const apr_xml_doc *doc,
2235                                  ap_filter_t *output);
2236
2237    /*
2238    ** OPTIONAL HOOKS
2239    ** The following hooks are optional; if not defined, then the
2240    ** corresponding protocol methods will be unsupported.
2241    */
2242
2243    /*
2244    ** Set the state of a checked-in version-controlled resource.
2245    **
2246    ** If the request specified a version, the version resource
2247    ** represents that version. If the request specified a label,
2248    ** then "version" is NULL, and "label" is the label.
2249    **
2250    ** The depth argument is ignored for a file, and can be 0, 1, or
2251    ** DAV_INFINITY for a collection. The depth argument only applies
2252    ** with a label, not a version.
2253    **
2254    ** If an error occurs in a child resource, then the return value is
2255    ** non-NULL, and *response is set to a multistatus response.
2256    **
2257    ** This hook is optional; if not defined, then the UPDATE method
2258    ** will not be supported.
2259    */
2260    dav_error * (*update)(const dav_resource *resource,
2261                          const dav_resource *version,
2262                          const char *label,
2263                          int depth,
2264                          dav_response **response);
2265
2266    /*
2267    ** Add a label to a version. The resource is either a specific
2268    ** version, or a version selector, in which case the label should
2269    ** be added to the current target of the version selector. The
2270    ** version selector cannot be checked out.
2271    **
2272    ** If replace != 0, any existing label by the same name is
2273    ** effectively deleted first. Otherwise, it is an error to
2274    ** attempt to add a label which already exists on some version
2275    ** of the same history resource.
2276    **
2277    ** This hook is optional; if not defined, then the LABEL method
2278    ** will not be supported. If it is defined, then the remove_label
2279    ** hook must be defined also.
2280    */
2281    dav_error * (*add_label)(const dav_resource *resource,
2282                             const char *label,
2283                             int replace);
2284
2285    /*
2286    ** Remove a label from a version. The resource is either a specific
2287    ** version, or a version selector, in which case the label should
2288    ** be added to the current target of the version selector. The
2289    ** version selector cannot be checked out.
2290    **
2291    ** It is an error if no such label exists on the specified version.
2292    **
2293    ** This hook is optional, but if defined, the add_label hook
2294    ** must be defined also.
2295    */
2296    dav_error * (*remove_label)(const dav_resource *resource,
2297                                const char *label);
2298
2299    /*
2300    ** Determine whether a null resource can be created as a workspace.
2301    ** The provider may restrict workspaces to certain locations.
2302    ** Returns 0 if the resource cannot be a workspace.
2303    **
2304    ** This hook is optional; if the provider does not support workspaces,
2305    ** it should be set to NULL.
2306    */
2307    int (*can_be_workspace)(const dav_resource *resource);
2308
2309    /*
2310    ** Create a workspace resource. The resource must not already
2311    ** exist. Any <DAV:mkworkspace> element is passed to the provider
2312    ** in the "doc" structure; it may be empty.
2313    **
2314    ** If workspace creation is succesful, the state of the resource
2315    ** object is updated appropriately.
2316    **
2317    ** This hook is optional; if the provider does not support workspaces,
2318    ** it should be set to NULL.
2319    */
2320    dav_error * (*make_workspace)(dav_resource *resource,
2321                                  apr_xml_doc *doc);
2322
2323    /*
2324    ** Determine whether a null resource can be created as an activity.
2325    ** The provider may restrict activities to certain locations.
2326    ** Returns 0 if the resource cannot be an activity.
2327    **
2328    ** This hook is optional; if the provider does not support activities,
2329    ** it should be set to NULL.
2330    */
2331    int (*can_be_activity)(const dav_resource *resource);
2332
2333    /*
2334    ** Create an activity resource. The resource must not already
2335    ** exist.
2336    **
2337    ** If activity creation is succesful, the state of the resource
2338    ** object is updated appropriately.
2339    **
2340    ** This hook is optional; if the provider does not support activities,
2341    ** it should be set to NULL.
2342    */
2343    dav_error * (*make_activity)(dav_resource *resource);
2344
2345    /*
2346    ** Merge a resource (tree) into target resource (tree).
2347    **
2348    ** ### more doc...
2349    **
2350    ** This hook is optional; if the provider does not support merging,
2351    ** then this should be set to NULL.
2352    */
2353    dav_error * (*merge)(dav_resource *target, dav_resource *source,
2354                         int no_auto_merge, int no_checkout,
2355                         apr_xml_elem *prop_elem,
2356                         ap_filter_t *output);
2357
2358    /*
2359    ** If a provider needs a context to associate with this hooks structure,
2360    ** then this field may be used. In most cases, it will just be NULL.
2361    */
2362    void *ctx;
2363};
2364
2365
2366/* --------------------------------------------------------------------
2367**
2368** BINDING FUNCTIONS
2369*/
2370
2371/* binding provider hooks */
2372struct dav_hooks_binding {
2373
2374    /* Determine whether a resource can be the target of a binding.
2375     * Returns 0 if the resource cannot be a binding target.
2376     */
2377    int (*is_bindable)(const dav_resource *resource);
2378
2379    /* Create a binding to a resource.
2380     * The resource argument is the target of the binding;
2381     * the binding argument must be a resource which does not already
2382     * exist.
2383     */
2384    dav_error * (*bind_resource)(const dav_resource *resource,
2385                                 dav_resource *binding);
2386
2387    /*
2388    ** If a provider needs a context to associate with this hooks structure,
2389    ** then this field may be used. In most cases, it will just be NULL.
2390    */
2391    void *ctx;
2392
2393};
2394
2395
2396/* --------------------------------------------------------------------
2397**
2398** SEARCH(DASL) FUNCTIONS
2399*/
2400
2401/* search provider hooks */
2402struct dav_hooks_search {
2403    /* Set header for a OPTION method
2404     * An error may be returned.
2405     * To set a hadder, this function might call
2406     * apr_table_setn(r->headers_out, "DASL", dasl_optin1);
2407     *
2408     * Examples:
2409     * DASL: <DAV:basicsearch>
2410     * DASL: <http://foo.bar.com/syntax1>
2411     * DASL: <http://akuma.com/syntax2>
2412     */
2413    dav_error * (*set_option_head)(request_rec *r);
2414
2415    /* Search resources
2416     * An error may be returned. *response will contain multistatus
2417     * responses (if any) suitable for the body of the error. It is also
2418     * possible to return NULL, yet still have multistatus responses.
2419     * In this case, typically the caller should return a 207 (Multistatus)
2420     * and the responses (in the body) as the HTTP response.
2421     */
2422    dav_error * (*search_resource)(request_rec *r,
2423                                   dav_response **response);
2424
2425    /*
2426    ** If a provider needs a context to associate with this hooks structure,
2427    ** then this field may be used. In most cases, it will just be NULL.
2428    */
2429    void *ctx;
2430
2431};
2432
2433
2434/* --------------------------------------------------------------------
2435**
2436** MISCELLANEOUS STUFF
2437*/
2438
2439typedef struct {
2440    int propid;                          /* live property ID */
2441    const dav_hooks_liveprop *provider;  /* the provider defining this prop */
2442} dav_elem_private;
2443
2444/* --------------------------------------------------------------------
2445**
2446** DAV OPTIONS
2447*/
2448#define DAV_OPTIONS_EXTENSION_GROUP "dav_options"
2449
2450typedef struct dav_options_provider
2451{
2452    dav_error* (*dav_header)(request_rec *r,
2453                             const dav_resource *resource,
2454                             apr_text_header *phdr);
2455
2456    dav_error* (*dav_method)(request_rec *r,
2457                             const dav_resource *resource,
2458                             apr_text_header *phdr);
2459
2460    void *ctx;
2461} dav_options_provider;
2462
2463extern DAV_DECLARE(const dav_options_provider *) dav_get_options_providers(const char *name);
2464
2465extern DAV_DECLARE(void) dav_options_provider_register(apr_pool_t *p,
2466                               const char *name,
2467                               const dav_options_provider *provider);
2468
2469/* --------------------------------------------------------------------
2470**
2471** DAV RESOURCE TYPE HOOKS
2472*/
2473
2474typedef struct dav_resource_type_provider
2475{
2476    int (*get_resource_type)(const dav_resource *resource,
2477                  const char **name,
2478                  const char **uri);
2479} dav_resource_type_provider;
2480
2481#define DAV_RESOURCE_TYPE_GROUP "dav_resource_type"
2482
2483DAV_DECLARE(void) dav_resource_type_provider_register(apr_pool_t *p,
2484                                        const char *name,
2485                                    const dav_resource_type_provider *provider);
2486
2487DAV_DECLARE(const dav_resource_type_provider *) dav_get_resource_type_providers(const char *name);
2488
2489#ifdef __cplusplus
2490}
2491#endif
2492
2493#endif /* _MOD_DAV_H_ */
2494/** @} */
2495
2496