github.com/krum110487/go-htaccess@v0.0.0-20240316004156-60641c8e7598/tests/data/apache_2_4_58/include/mod_dav.h (about)

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