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