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