Blame modules/dav/main/mod_dav.h

Packit 90a5c9
/* Licensed to the Apache Software Foundation (ASF) under one or more
Packit 90a5c9
 * contributor license agreements.  See the NOTICE file distributed with
Packit 90a5c9
 * this work for additional information regarding copyright ownership.
Packit 90a5c9
 * The ASF licenses this file to You under the Apache License, Version 2.0
Packit 90a5c9
 * (the "License"); you may not use this file except in compliance with
Packit 90a5c9
 * the License.  You may obtain a copy of the License at
Packit 90a5c9
 *
Packit 90a5c9
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 90a5c9
 *
Packit 90a5c9
 * Unless required by applicable law or agreed to in writing, software
Packit 90a5c9
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 90a5c9
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 90a5c9
 * See the License for the specific language governing permissions and
Packit 90a5c9
 * limitations under the License.
Packit 90a5c9
 */
Packit 90a5c9
Packit 90a5c9
/**
Packit 90a5c9
 * @file  mod_dav.h
Packit 90a5c9
 * @brief DAV extension module for Apache 2.0.*
Packit 90a5c9
 *
Packit 90a5c9
 * @defgroup MOD_DAV mod_dav
Packit 90a5c9
 * @ingroup APACHE_MODS
Packit 90a5c9
 * @{
Packit 90a5c9
 */
Packit 90a5c9
Packit 90a5c9
#ifndef _MOD_DAV_H_
Packit 90a5c9
#define _MOD_DAV_H_
Packit 90a5c9
Packit 90a5c9
#include "apr_hooks.h"
Packit 90a5c9
#include "apr_hash.h"
Packit 90a5c9
#include "apr_dbm.h"
Packit 90a5c9
#include "apr_tables.h"
Packit 90a5c9
Packit 90a5c9
#include "httpd.h"
Packit 90a5c9
#include "util_filter.h"
Packit 90a5c9
#include "util_xml.h"
Packit 90a5c9
Packit 90a5c9
#include <limits.h>     /* for INT_MAX */
Packit 90a5c9
#include <time.h>       /* for time_t */
Packit 90a5c9
Packit 90a5c9
#ifdef __cplusplus
Packit 90a5c9
extern "C" {
Packit 90a5c9
#endif
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
#define DAV_VERSION             AP_SERVER_BASEREVISION
Packit 90a5c9
Packit 90a5c9
#define DAV_XML_HEADER          ""
Packit 90a5c9
#define DAV_XML_CONTENT_TYPE    "text/xml; charset=\"utf-8\""
Packit 90a5c9
Packit 90a5c9
#define DAV_READ_BLOCKSIZE      2048    /* used for reading input blocks */
Packit 90a5c9
Packit 90a5c9
#define DAV_RESPONSE_BODY_1     "\n<html><head>\n<title>"
Packit 90a5c9
#define DAV_RESPONSE_BODY_2     "</title>\n</head><body>\n

"

Packit 90a5c9
#define DAV_RESPONSE_BODY_3     "\n

"

Packit 90a5c9
#define DAV_RESPONSE_BODY_4     "

\n"
Packit 90a5c9
#define DAV_RESPONSE_BODY_5     "</body></html>\n"
Packit 90a5c9
Packit 90a5c9
#define DAV_DO_COPY             0
Packit 90a5c9
#define DAV_DO_MOVE             1
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
#if 1
Packit 90a5c9
#define DAV_DEBUG        1
Packit 90a5c9
#define DEBUG_CR         "\n"
Packit 90a5c9
#define DBG0(f)          ap_log_error(APLOG_MARK, \
Packit 90a5c9
                                APLOG_ERR, 0, NULL, (f))
Packit 90a5c9
#define DBG1(f,a1)       ap_log_error(APLOG_MARK, \
Packit 90a5c9
                                APLOG_ERR, 0, NULL, f, a1)
Packit 90a5c9
#define DBG2(f,a1,a2)    ap_log_error(APLOG_MARK, \
Packit 90a5c9
                                APLOG_ERR, 0, NULL, f, a1, a2)
Packit 90a5c9
#define DBG3(f,a1,a2,a3) ap_log_error(APLOG_MARK, \
Packit 90a5c9
                                APLOG_ERR, 0, NULL, f, a1, a2, a3)
Packit 90a5c9
#else
Packit 90a5c9
#undef DAV_DEBUG
Packit 90a5c9
#define DEBUG_CR        ""
Packit 90a5c9
#endif
Packit 90a5c9
Packit 90a5c9
#define DAV_INFINITY    INT_MAX    /* for the Depth: header */
Packit 90a5c9
Packit 90a5c9
/* Create a set of DAV_DECLARE(type), DAV_DECLARE_NONSTD(type) and
Packit 90a5c9
 * DAV_DECLARE_DATA with appropriate export and import tags for the platform
Packit 90a5c9
 */
Packit 90a5c9
#if !defined(WIN32)
Packit 90a5c9
#define DAV_DECLARE(type)            type
Packit 90a5c9
#define DAV_DECLARE_NONSTD(type)     type
Packit 90a5c9
#define DAV_DECLARE_DATA
Packit 90a5c9
#elif defined(DAV_DECLARE_STATIC)
Packit 90a5c9
#define DAV_DECLARE(type)            type __stdcall
Packit 90a5c9
#define DAV_DECLARE_NONSTD(type)     type
Packit 90a5c9
#define DAV_DECLARE_DATA
Packit 90a5c9
#elif defined(DAV_DECLARE_EXPORT)
Packit 90a5c9
#define DAV_DECLARE(type)            __declspec(dllexport) type __stdcall
Packit 90a5c9
#define DAV_DECLARE_NONSTD(type)     __declspec(dllexport) type
Packit 90a5c9
#define DAV_DECLARE_DATA             __declspec(dllexport)
Packit 90a5c9
#else
Packit 90a5c9
#define DAV_DECLARE(type)            __declspec(dllimport) type __stdcall
Packit 90a5c9
#define DAV_DECLARE_NONSTD(type)     __declspec(dllimport) type
Packit 90a5c9
#define DAV_DECLARE_DATA             __declspec(dllimport)
Packit 90a5c9
#endif
Packit 90a5c9
Packit 90a5c9
/* --------------------------------------------------------------------
Packit 90a5c9
**
Packit 90a5c9
** ERROR MANAGEMENT
Packit 90a5c9
*/
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** dav_error structure.
Packit 90a5c9
**
Packit 90a5c9
** In most cases, mod_dav uses a pointer to a dav_error structure. If the
Packit 90a5c9
** pointer is NULL, then no error has occurred.
Packit 90a5c9
**
Packit 90a5c9
** In certain cases, a dav_error structure is directly used. In these cases,
Packit 90a5c9
** a status value of 0 means that an error has not occurred.
Packit 90a5c9
**
Packit 90a5c9
** Note: this implies that status != 0 whenever an error occurs.
Packit 90a5c9
**
Packit 90a5c9
** The desc field is optional (it may be NULL). When NULL, it typically
Packit 90a5c9
** implies that Apache has a proper description for the specified status.
Packit 90a5c9
*/
Packit 90a5c9
typedef struct dav_error {
Packit 90a5c9
    int status;                 /* suggested HTTP status (0 for no error) */
Packit 90a5c9
    int error_id;               /* DAV-specific error ID */
Packit 90a5c9
    const char *desc;           /* DAV:responsedescription and error log */
Packit 90a5c9
Packit 90a5c9
    apr_status_t aprerr;        /* APR error if any, or 0/APR_SUCCESS */
Packit 90a5c9
Packit 90a5c9
    const char *namespace;      /* [optional] namespace of error */
Packit 90a5c9
    const char *tagname;        /* name of error-tag */
Packit 90a5c9
Packit 90a5c9
    struct dav_error *prev;     /* previous error (in stack) */
Packit 90a5c9
Packit 90a5c9
    const char *childtags;      /* error-tag may have children */
Packit 90a5c9
Packit 90a5c9
} dav_error;
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** Create a new error structure. save_errno will be filled with the current
Packit 90a5c9
** errno value.
Packit 90a5c9
*/
Packit 90a5c9
DAV_DECLARE(dav_error*) dav_new_error(apr_pool_t *p, int status,
Packit 90a5c9
                                      int error_id, apr_status_t aprerr,
Packit 90a5c9
                                      const char *desc);
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** Create a new error structure with tagname and (optional) namespace;
Packit 90a5c9
** namespace may be NULL, which means "DAV:".
Packit 90a5c9
*/
Packit 90a5c9
DAV_DECLARE(dav_error*) dav_new_error_tag(apr_pool_t *p, int status,
Packit 90a5c9
                                          int error_id, apr_status_t aprerr,
Packit 90a5c9
                                          const char *desc,
Packit 90a5c9
                                          const char *namespace,
Packit 90a5c9
                                          const char *tagname);
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** Push a new error description onto the stack of errors.
Packit 90a5c9
**
Packit 90a5c9
** This function is used to provide an additional description to an existing
Packit 90a5c9
** error.
Packit 90a5c9
**
Packit 90a5c9
** <status> should contain the caller's view of what the current status is,
Packit 90a5c9
** given the underlying error. If it doesn't have a better idea, then the
Packit 90a5c9
** caller should pass prev->status.
Packit 90a5c9
**
Packit 90a5c9
** <error_id> can specify a new error_id since the topmost description has
Packit 90a5c9
** changed.
Packit 90a5c9
*/
Packit 90a5c9
DAV_DECLARE(dav_error*) dav_push_error(apr_pool_t *p, int status, int error_id,
Packit 90a5c9
                                       const char *desc, dav_error *prev);
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** Join two errors together.
Packit 90a5c9
**
Packit 90a5c9
** This function is used to add a new error stack onto an existing error so
Packit 90a5c9
** that subsequent errors can be reported after the first error.  It returns
Packit 90a5c9
** the correct error stack to use so that the caller can blindly call it
Packit 90a5c9
** without checking that both dest and src are not NULL.
Packit 90a5c9
** 
Packit 90a5c9
** <dest> is the error stack that the error will be added to.
Packit 90a5c9
**
Packit 90a5c9
** <src> is the error stack that will be appended.
Packit 90a5c9
*/
Packit 90a5c9
DAV_DECLARE(dav_error*) dav_join_error(dav_error* dest, dav_error* src);
Packit 90a5c9
Packit 90a5c9
typedef struct dav_response dav_response;
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** dav_handle_err()
Packit 90a5c9
**
Packit 90a5c9
** Handle the standard error processing. <err> must be non-NULL.
Packit 90a5c9
**
Packit 90a5c9
** <response> is set by the following:
Packit 90a5c9
**   - dav_validate_request()
Packit 90a5c9
**   - dav_add_lock()
Packit 90a5c9
**   - repos_hooks->remove_resource
Packit 90a5c9
**   - repos_hooks->move_resource
Packit 90a5c9
**   - repos_hooks->copy_resource
Packit 90a5c9
**   - vsn_hooks->update
Packit 90a5c9
*/
Packit 90a5c9
DAV_DECLARE(int) dav_handle_err(request_rec *r, dav_error *err,
Packit 90a5c9
                                dav_response *response);
Packit 90a5c9
Packit 90a5c9
/* error ID values... */
Packit 90a5c9
Packit 90a5c9
/* IF: header errors */
Packit 90a5c9
#define DAV_ERR_IF_PARSE                100    /* general parsing error */
Packit 90a5c9
#define DAV_ERR_IF_MULTIPLE_NOT         101    /* multiple "Not" found */
Packit 90a5c9
#define DAV_ERR_IF_UNK_CHAR             102    /* unknown char in header */
Packit 90a5c9
#define DAV_ERR_IF_ABSENT               103    /* no locktokens given */
Packit 90a5c9
#define DAV_ERR_IF_TAGGED               104    /* in parsing tagged-list */
Packit 90a5c9
#define DAV_ERR_IF_UNCLOSED_PAREN       105    /* in no-tagged-list */
Packit 90a5c9
Packit 90a5c9
/* Prop DB errors */
Packit 90a5c9
#define DAV_ERR_PROP_BAD_MAJOR          200    /* major version was wrong */
Packit 90a5c9
#define DAV_ERR_PROP_READONLY           201    /* prop is read-only */
Packit 90a5c9
#define DAV_ERR_PROP_NO_DATABASE        202    /* writable db not avail */
Packit 90a5c9
#define DAV_ERR_PROP_NOT_FOUND          203    /* prop not found */
Packit 90a5c9
#define DAV_ERR_PROP_BAD_LOCKDB         204    /* could not open lockdb */
Packit 90a5c9
#define DAV_ERR_PROP_OPENING            205    /* problem opening propdb */
Packit 90a5c9
#define DAV_ERR_PROP_EXEC               206    /* problem exec'ing patch */
Packit 90a5c9
Packit 90a5c9
/* Predefined DB errors */
Packit 90a5c9
/* ### any to define?? */
Packit 90a5c9
Packit 90a5c9
/* Predefined locking system errors */
Packit 90a5c9
#define DAV_ERR_LOCK_OPENDB             400    /* could not open lockdb */
Packit 90a5c9
#define DAV_ERR_LOCK_NO_DB              401    /* no database defined */
Packit 90a5c9
#define DAV_ERR_LOCK_CORRUPT_DB         402    /* DB is corrupt */
Packit 90a5c9
#define DAV_ERR_LOCK_UNK_STATE_TOKEN    403    /* unknown State-token */
Packit 90a5c9
#define DAV_ERR_LOCK_PARSE_TOKEN        404    /* bad opaquelocktoken */
Packit 90a5c9
#define DAV_ERR_LOCK_SAVE_LOCK          405    /* err saving locks */
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** Some comments on Error ID values:
Packit 90a5c9
**
Packit 90a5c9
** The numbers do not necessarily need to be unique. Uniqueness simply means
Packit 90a5c9
** that two errors that have not been predefined above can be distinguished
Packit 90a5c9
** from each other. At the moment, mod_dav does not use this distinguishing
Packit 90a5c9
** feature, but it could be used in the future to collapse <response> elements
Packit 90a5c9
** into groups based on the error ID (and associated responsedescription).
Packit 90a5c9
**
Packit 90a5c9
** If a compute_desc is provided, then the error ID should be unique within
Packit 90a5c9
** the context of the compute_desc function (so the function can figure out
Packit 90a5c9
** what to filled into the desc).
Packit 90a5c9
**
Packit 90a5c9
** Basically, subsystems can ignore defining new error ID values if they want
Packit 90a5c9
** to. The subsystems *do* need to return the predefined errors when
Packit 90a5c9
** appropriate, so that mod_dav can figure out what to do. Subsystems can
Packit 90a5c9
** simply leave the error ID field unfilled (zero) if there isn't an error
Packit 90a5c9
** that must be placed there.
Packit 90a5c9
*/
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/* --------------------------------------------------------------------
Packit 90a5c9
**
Packit 90a5c9
** HOOK STRUCTURES
Packit 90a5c9
**
Packit 90a5c9
** These are here for forward-declaration purposes. For more info, see
Packit 90a5c9
** the section title "HOOK HANDLING" for more information, plus each
Packit 90a5c9
** structure definition.
Packit 90a5c9
*/
Packit 90a5c9
Packit 90a5c9
/* forward-declare this structure */
Packit 90a5c9
typedef struct dav_hooks_propdb dav_hooks_propdb;
Packit 90a5c9
typedef struct dav_hooks_locks dav_hooks_locks;
Packit 90a5c9
typedef struct dav_hooks_vsn dav_hooks_vsn;
Packit 90a5c9
typedef struct dav_hooks_repository dav_hooks_repository;
Packit 90a5c9
typedef struct dav_hooks_liveprop dav_hooks_liveprop;
Packit 90a5c9
typedef struct dav_hooks_binding dav_hooks_binding;
Packit 90a5c9
typedef struct dav_hooks_search dav_hooks_search;
Packit 90a5c9
Packit 90a5c9
/* ### deprecated name */
Packit 90a5c9
typedef dav_hooks_propdb dav_hooks_db;
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/* --------------------------------------------------------------------
Packit 90a5c9
**
Packit 90a5c9
** RESOURCE HANDLING
Packit 90a5c9
*/
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** Resource Types:
Packit 90a5c9
** The base protocol defines only file and collection resources.
Packit 90a5c9
** The versioning protocol defines several additional resource types
Packit 90a5c9
** to represent artifacts of a version control system.
Packit 90a5c9
**
Packit 90a5c9
** This enumeration identifies the type of URL used to identify the
Packit 90a5c9
** resource. Since the same resource may have more than one type of
Packit 90a5c9
** URL which can identify it, dav_resource_type cannot be used
Packit 90a5c9
** alone to determine the type of the resource; attributes of the
Packit 90a5c9
** dav_resource object must also be consulted.
Packit 90a5c9
*/
Packit 90a5c9
typedef enum {
Packit 90a5c9
    DAV_RESOURCE_TYPE_UNKNOWN,
Packit 90a5c9
Packit 90a5c9
    DAV_RESOURCE_TYPE_REGULAR,          /* file or collection; could be
Packit 90a5c9
                                         * unversioned, or version selector,
Packit 90a5c9
                                         * or baseline selector */
Packit 90a5c9
Packit 90a5c9
    DAV_RESOURCE_TYPE_VERSION,          /* version or baseline URL */
Packit 90a5c9
Packit 90a5c9
    DAV_RESOURCE_TYPE_HISTORY,          /* version or baseline history URL */
Packit 90a5c9
Packit 90a5c9
    DAV_RESOURCE_TYPE_WORKING,          /* working resource URL */
Packit 90a5c9
Packit 90a5c9
    DAV_RESOURCE_TYPE_WORKSPACE,        /* workspace URL */
Packit 90a5c9
Packit 90a5c9
    DAV_RESOURCE_TYPE_ACTIVITY,         /* activity URL */
Packit 90a5c9
Packit 90a5c9
    DAV_RESOURCE_TYPE_PRIVATE           /* repository-private type */
Packit 90a5c9
Packit 90a5c9
} dav_resource_type;
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** Opaque, repository-specific information for a resource.
Packit 90a5c9
*/
Packit 90a5c9
typedef struct dav_resource_private dav_resource_private;
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** Resource descriptor, generated by a repository provider.
Packit 90a5c9
**
Packit 90a5c9
** Note: the lock-null state is not explicitly represented here,
Packit 90a5c9
** since it may be expensive to compute. Use dav_get_resource_state()
Packit 90a5c9
** to determine whether a non-existent resource is a lock-null resource.
Packit 90a5c9
**
Packit 90a5c9
** A quick explanation of how the flags can apply to different resources:
Packit 90a5c9
**
Packit 90a5c9
** unversioned file or collection:
Packit 90a5c9
**     type       = DAV_RESOURCE_TYPE_REGULAR
Packit 90a5c9
**     exists     = ? (1 if exists)
Packit 90a5c9
**     collection = ? (1 if collection)
Packit 90a5c9
**     versioned  = 0
Packit 90a5c9
**     baselined  = 0
Packit 90a5c9
**     working    = 0
Packit 90a5c9
**
Packit 90a5c9
** version-controlled resource or configuration:
Packit 90a5c9
**     type       = DAV_RESOURCE_TYPE_REGULAR
Packit 90a5c9
**     exists     = 1
Packit 90a5c9
**     collection = ? (1 if collection)
Packit 90a5c9
**     versioned  = 1
Packit 90a5c9
**     baselined  = ? (1 if configuration)
Packit 90a5c9
**     working    = ? (1 if checked out)
Packit 90a5c9
**
Packit 90a5c9
** version/baseline history:
Packit 90a5c9
**     type       = DAV_RESOURCE_TYPE_HISTORY
Packit 90a5c9
**     exists     = 1
Packit 90a5c9
**     collection = 0
Packit 90a5c9
**     versioned  = 0
Packit 90a5c9
**     baselined  = 0
Packit 90a5c9
**     working    = 0
Packit 90a5c9
**
Packit 90a5c9
** version/baseline:
Packit 90a5c9
**     type       = DAV_RESOURCE_TYPE_VERSION
Packit 90a5c9
**     exists     = 1
Packit 90a5c9
**     collection = ? (1 if collection)
Packit 90a5c9
**     versioned  = 1
Packit 90a5c9
**     baselined  = ? (1 if baseline)
Packit 90a5c9
**     working    = 0
Packit 90a5c9
**
Packit 90a5c9
** working resource:
Packit 90a5c9
**     type       = DAV_RESOURCE_TYPE_WORKING
Packit 90a5c9
**     exists     = 1
Packit 90a5c9
**     collection = ? (1 if collection)
Packit 90a5c9
**     versioned  = 1
Packit 90a5c9
**     baselined  = 0
Packit 90a5c9
**     working    = 1
Packit 90a5c9
**
Packit 90a5c9
** workspace:
Packit 90a5c9
**     type       = DAV_RESOURCE_TYPE_WORKSPACE
Packit 90a5c9
**     exists     = ? (1 if exists)
Packit 90a5c9
**     collection = 1
Packit 90a5c9
**     versioned  = ? (1 if version-controlled)
Packit 90a5c9
**     baselined  = ? (1 if baseline-controlled)
Packit 90a5c9
**     working    = ? (1 if checked out)
Packit 90a5c9
**
Packit 90a5c9
** activity:
Packit 90a5c9
**     type       = DAV_RESOURCE_TYPE_ACTIVITY
Packit 90a5c9
**     exists     = ? (1 if exists)
Packit 90a5c9
**     collection = 0
Packit 90a5c9
**     versioned  = 0
Packit 90a5c9
**     baselined  = 0
Packit 90a5c9
**     working    = 0
Packit 90a5c9
*/
Packit 90a5c9
typedef struct dav_resource {
Packit 90a5c9
    dav_resource_type type;
Packit 90a5c9
Packit 90a5c9
    int exists;         /* 0 => null resource */
Packit 90a5c9
Packit 90a5c9
    int collection;     /* 0 => file; can be 1 for
Packit 90a5c9
                         * REGULAR, VERSION, and WORKING resources,
Packit 90a5c9
                         * and is always 1 for WORKSPACE */
Packit 90a5c9
Packit 90a5c9
    int versioned;      /* 0 => unversioned; can be 1 for
Packit 90a5c9
                         * REGULAR and WORKSPACE resources,
Packit 90a5c9
                         * and is always 1 for VERSION and WORKING */
Packit 90a5c9
Packit 90a5c9
    int baselined;      /* 0 => not baselined; can be 1 for
Packit 90a5c9
                         * REGULAR, VERSION, and WORKSPACE resources;
Packit 90a5c9
                         * versioned == 1 when baselined == 1 */
Packit 90a5c9
Packit 90a5c9
    int working;        /* 0 => not checked out; can be 1 for
Packit 90a5c9
                         * REGULAR and WORKSPACE resources,
Packit 90a5c9
                         * and is always 1 for WORKING */
Packit 90a5c9
Packit 90a5c9
    const char *uri;    /* the URI for this resource;
Packit 90a5c9
                         * currently has an ABI flaw where sometimes it is
Packit 90a5c9
                         * assumed to be encoded and sometimes not */
Packit 90a5c9
Packit 90a5c9
    dav_resource_private *info;         /* the provider's private info */
Packit 90a5c9
Packit 90a5c9
    const dav_hooks_repository *hooks;  /* hooks used for this resource */
Packit 90a5c9
Packit 90a5c9
    /* When allocating items related specifically to this resource, the
Packit 90a5c9
       following pool should be used. Its lifetime will be at least as
Packit 90a5c9
       long as the dav_resource structure. */
Packit 90a5c9
    apr_pool_t *pool;
Packit 90a5c9
Packit 90a5c9
} dav_resource;
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** Lock token type. Lock providers define the details of a lock token.
Packit 90a5c9
** However, all providers are expected to at least be able to parse
Packit 90a5c9
** the "opaquelocktoken" scheme, which is represented by a uuid_t.
Packit 90a5c9
*/
Packit 90a5c9
typedef struct dav_locktoken dav_locktoken;
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/* --------------------------------------------------------------------
Packit 90a5c9
**
Packit 90a5c9
** BUFFER HANDLING
Packit 90a5c9
**
Packit 90a5c9
** These buffers are used as a lightweight buffer reuse mechanism. Apache
Packit 90a5c9
** provides sub-pool creation and destruction to much the same effect, but
Packit 90a5c9
** the sub-pools are a bit more general and heavyweight than these buffers.
Packit 90a5c9
*/
Packit 90a5c9
Packit 90a5c9
/* buffer for reuse; can grow to accommodate needed size */
Packit 90a5c9
typedef struct
Packit 90a5c9
{
Packit 90a5c9
    apr_size_t alloc_len;       /* how much has been allocated */
Packit 90a5c9
    apr_size_t cur_len;         /* how much is currently being used */
Packit 90a5c9
    char *buf;                  /* buffer contents */
Packit 90a5c9
} dav_buffer;
Packit 90a5c9
#define DAV_BUFFER_MINSIZE      256    /* minimum size for buffer */
Packit 90a5c9
#define DAV_BUFFER_PAD          64     /* amount of pad when growing */
Packit 90a5c9
Packit 90a5c9
/* set the cur_len to the given size and ensure space is available */
Packit 90a5c9
DAV_DECLARE(void) dav_set_bufsize(apr_pool_t *p, dav_buffer *pbuf,
Packit 90a5c9
                                  apr_size_t size);
Packit 90a5c9
Packit 90a5c9
/* initialize a buffer and copy the specified (null-term'd) string into it */
Packit 90a5c9
DAV_DECLARE(void) dav_buffer_init(apr_pool_t *p, dav_buffer *pbuf,
Packit 90a5c9
                                  const char *str);
Packit 90a5c9
Packit 90a5c9
/* check that the buffer can accommodate <extra_needed> more bytes */
Packit 90a5c9
DAV_DECLARE(void) dav_check_bufsize(apr_pool_t *p, dav_buffer *pbuf,
Packit 90a5c9
                                    apr_size_t extra_needed);
Packit 90a5c9
Packit 90a5c9
/* append a string to the end of the buffer, adjust length */
Packit 90a5c9
DAV_DECLARE(void) dav_buffer_append(apr_pool_t *p, dav_buffer *pbuf,
Packit 90a5c9
                                    const char *str);
Packit 90a5c9
Packit 90a5c9
/* place a string on the end of the buffer, do NOT adjust length */
Packit 90a5c9
DAV_DECLARE(void) dav_buffer_place(apr_pool_t *p, dav_buffer *pbuf,
Packit 90a5c9
                                   const char *str);
Packit 90a5c9
Packit 90a5c9
/* place some memory on the end of a buffer; do NOT adjust length */
Packit 90a5c9
DAV_DECLARE(void) dav_buffer_place_mem(apr_pool_t *p, dav_buffer *pbuf,
Packit 90a5c9
                                       const void *mem, apr_size_t amt,
Packit 90a5c9
                                       apr_size_t pad);
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/* --------------------------------------------------------------------
Packit 90a5c9
**
Packit 90a5c9
** HANDY UTILITIES
Packit 90a5c9
*/
Packit 90a5c9
Packit 90a5c9
/* contains results from one of the getprop functions */
Packit 90a5c9
typedef struct
Packit 90a5c9
{
Packit 90a5c9
    apr_text * propstats;       /* <propstat> element text */
Packit 90a5c9
    apr_text * xmlns;           /* namespace decls for <response> elem */
Packit 90a5c9
} dav_get_props_result;
Packit 90a5c9
Packit 90a5c9
/* holds the contents of a <response> element */
Packit 90a5c9
struct dav_response
Packit 90a5c9
{
Packit 90a5c9
    const char *href;           /* always */
Packit 90a5c9
    const char *desc;           /* optional description at <response> level */
Packit 90a5c9
Packit 90a5c9
    /* use status if propresult.propstats is NULL. */
Packit 90a5c9
    dav_get_props_result propresult;
Packit 90a5c9
Packit 90a5c9
    int status;
Packit 90a5c9
Packit 90a5c9
    struct dav_response *next;
Packit 90a5c9
};
Packit 90a5c9
Packit 90a5c9
typedef struct
Packit 90a5c9
{
Packit 90a5c9
    request_rec *rnew;          /* new subrequest */
Packit 90a5c9
    dav_error err;              /* potential error response */
Packit 90a5c9
} dav_lookup_result;
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
DAV_DECLARE(dav_lookup_result) dav_lookup_uri(const char *uri, request_rec *r,
Packit 90a5c9
                                              int must_be_absolute);
Packit 90a5c9
Packit 90a5c9
/* defines type of property info a provider is to return */
Packit 90a5c9
typedef enum {
Packit 90a5c9
    DAV_PROP_INSERT_NOTDEF,     /* property is defined by this provider,
Packit 90a5c9
                                   but nothing was inserted because the
Packit 90a5c9
                                   (live) property is not defined for this
Packit 90a5c9
                                   resource (it may be present as a dead
Packit 90a5c9
                                   property). */
Packit 90a5c9
    DAV_PROP_INSERT_NOTSUPP,    /* property is recognized by this provider,
Packit 90a5c9
                                   but it is not supported, and cannot be
Packit 90a5c9
                                   treated as a dead property */
Packit 90a5c9
    DAV_PROP_INSERT_NAME,       /* a property name (empty elem) was
Packit 90a5c9
                                   inserted into the text block */
Packit 90a5c9
    DAV_PROP_INSERT_VALUE,      /* a property name/value pair was inserted
Packit 90a5c9
                                   into the text block */
Packit 90a5c9
    DAV_PROP_INSERT_SUPPORTED   /* a supported live property was added to
Packit 90a5c9
                                   the text block as a
Packit 90a5c9
                                   <DAV:supported-live-property> element */
Packit 90a5c9
} dav_prop_insert;
Packit 90a5c9
Packit 90a5c9
/* ### this stuff is private to dav/fs/repos.c; move it... */
Packit 90a5c9
/* format a time string (buf must be at least DAV_TIMEBUF_SIZE chars) */
Packit 90a5c9
#define DAV_STYLE_ISO8601       1
Packit 90a5c9
#define DAV_STYLE_RFC822        2
Packit 90a5c9
#define DAV_TIMEBUF_SIZE        30
Packit 90a5c9
Packit 90a5c9
/* Write a complete RESPONSE object out as a <DAV:response> xml
Packit 90a5c9
 * element.  Data is sent into brigade BB, which is auto-flushed into
Packit 90a5c9
 * the output filter stack for request R.  Use POOL for any temporary
Packit 90a5c9
 * allocations.
Packit 90a5c9
 *
Packit 90a5c9
 * [Presumably the <multistatus> tag has already been written;  this
Packit 90a5c9
 * routine is shared by dav_send_multistatus and dav_stream_response.]
Packit 90a5c9
 */
Packit 90a5c9
DAV_DECLARE(void) dav_send_one_response(dav_response *response,
Packit 90a5c9
                                        apr_bucket_brigade *bb,
Packit 90a5c9
                                        request_rec *r,
Packit 90a5c9
                                        apr_pool_t *pool);
Packit 90a5c9
Packit 90a5c9
/* Factorized helper function: prep request_rec R for a multistatus
Packit 90a5c9
 * response and write <multistatus> tag into BB, destined for
Packit 90a5c9
 * R->output_filters.  Use xml NAMESPACES in initial tag, if
Packit 90a5c9
 * non-NULL.
Packit 90a5c9
 */
Packit 90a5c9
DAV_DECLARE(void) dav_begin_multistatus(apr_bucket_brigade *bb,
Packit 90a5c9
                                        request_rec *r, int status,
Packit 90a5c9
                                        apr_array_header_t *namespaces);
Packit 90a5c9
Packit 90a5c9
/* Finish a multistatus response started by dav_begin_multistatus: */
Packit 90a5c9
DAV_DECLARE(apr_status_t) dav_finish_multistatus(request_rec *r,
Packit 90a5c9
                                                 apr_bucket_brigade *bb);
Packit 90a5c9
Packit 90a5c9
/* Send a multistatus response */
Packit 90a5c9
DAV_DECLARE(void) dav_send_multistatus(request_rec *r, int status,
Packit 90a5c9
                                       dav_response *first,
Packit 90a5c9
                                       apr_array_header_t *namespaces);
Packit 90a5c9
Packit 90a5c9
DAV_DECLARE(apr_text *) dav_failed_proppatch(apr_pool_t *p,
Packit 90a5c9
                                             apr_array_header_t *prop_ctx);
Packit 90a5c9
DAV_DECLARE(apr_text *) dav_success_proppatch(apr_pool_t *p,
Packit 90a5c9
                                              apr_array_header_t *prop_ctx);
Packit 90a5c9
Packit 90a5c9
DAV_DECLARE(int) dav_get_depth(request_rec *r, int def_depth);
Packit 90a5c9
Packit 90a5c9
DAV_DECLARE(int) dav_validate_root(const apr_xml_doc *doc,
Packit 90a5c9
                                   const char *tagname);
Packit 90a5c9
DAV_DECLARE(apr_xml_elem *) dav_find_child(const apr_xml_elem *elem,
Packit 90a5c9
                                           const char *tagname);
Packit 90a5c9
Packit 90a5c9
/* gather up all the CDATA into a single string */
Packit 90a5c9
DAV_DECLARE(const char *) dav_xml_get_cdata(const apr_xml_elem *elem, apr_pool_t *pool,
Packit 90a5c9
                              int strip_white);
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** XML namespace handling
Packit 90a5c9
**
Packit 90a5c9
** This structure tracks namespace declarations (xmlns:prefix="URI").
Packit 90a5c9
** It maintains a one-to-many relationship of URIs-to-prefixes. In other
Packit 90a5c9
** words, one URI may be defined by many prefixes, but any specific
Packit 90a5c9
** prefix will specify only one URI.
Packit 90a5c9
**
Packit 90a5c9
** Prefixes using the "g###" pattern can be generated automatically if
Packit 90a5c9
** the caller does not have specific prefix requirements.
Packit 90a5c9
*/
Packit 90a5c9
typedef struct {
Packit 90a5c9
    apr_pool_t *pool;
Packit 90a5c9
    apr_hash_t *uri_prefix;     /* map URIs to an available prefix */
Packit 90a5c9
    apr_hash_t *prefix_uri;     /* map all prefixes to their URIs */
Packit 90a5c9
    int count;                  /* counter for "g###" prefixes */
Packit 90a5c9
} dav_xmlns_info;
Packit 90a5c9
Packit 90a5c9
/* create an empty dav_xmlns_info structure */
Packit 90a5c9
DAV_DECLARE(dav_xmlns_info *) dav_xmlns_create(apr_pool_t *pool);
Packit 90a5c9
Packit 90a5c9
/* add a specific prefix/URI pair. the prefix/uri should have a lifetime
Packit 90a5c9
   at least that of xmlns->pool */
Packit 90a5c9
DAV_DECLARE(void) dav_xmlns_add(dav_xmlns_info *xi,
Packit 90a5c9
                                const char *prefix, const char *uri);
Packit 90a5c9
Packit 90a5c9
/* add a URI (if not present); any prefix is acceptable and is returned.
Packit 90a5c9
   the uri should have a lifetime at least that xmlns->pool */
Packit 90a5c9
DAV_DECLARE(const char *) dav_xmlns_add_uri(dav_xmlns_info *xi,
Packit 90a5c9
                                            const char *uri);
Packit 90a5c9
Packit 90a5c9
/* return the URI for a specified prefix (or NULL if the prefix is unknown) */
Packit 90a5c9
DAV_DECLARE(const char *) dav_xmlns_get_uri(dav_xmlns_info *xi,
Packit 90a5c9
                                            const char *prefix);
Packit 90a5c9
Packit 90a5c9
/* return an available prefix for a specified URI (or NULL if the URI
Packit 90a5c9
   is unknown) */
Packit 90a5c9
DAV_DECLARE(const char *) dav_xmlns_get_prefix(dav_xmlns_info *xi,
Packit 90a5c9
                                               const char *uri);
Packit 90a5c9
Packit 90a5c9
/* generate xmlns declarations (appending into the given text) */
Packit 90a5c9
DAV_DECLARE(void) dav_xmlns_generate(dav_xmlns_info *xi,
Packit 90a5c9
                                     apr_text_header *phdr);
Packit 90a5c9
Packit 90a5c9
/* --------------------------------------------------------------------
Packit 90a5c9
**
Packit 90a5c9
** DAV PLUGINS
Packit 90a5c9
*/
Packit 90a5c9
Packit 90a5c9
/* ### docco ... */
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** dav_provider
Packit 90a5c9
**
Packit 90a5c9
** This structure wraps up all of the hooks that a mod_dav provider can
Packit 90a5c9
** supply. The provider MUST supply <repos> and <propdb>. The rest are
Packit 90a5c9
** optional and should contain NULL if that feature is not supplied.
Packit 90a5c9
**
Packit 90a5c9
** Note that a provider cannot pick and choose portions from various
Packit 90a5c9
** underlying implementations (which was theoretically possible in
Packit 90a5c9
** mod_dav 1.0). There are too many dependencies between a dav_resource
Packit 90a5c9
** (defined by <repos>) and the other functionality.
Packit 90a5c9
**
Packit 90a5c9
** Live properties are not part of the dav_provider structure because they
Packit 90a5c9
** are handled through the APR_HOOK interface (to allow for multiple liveprop
Packit 90a5c9
** providers). The core always provides some properties, and then a given
Packit 90a5c9
** provider will add more properties.
Packit 90a5c9
**
Packit 90a5c9
** Some providers may need to associate a context with the dav_provider
Packit 90a5c9
** structure -- the ctx field is available for storing this context. Just
Packit 90a5c9
** leave it NULL if it isn't required.
Packit 90a5c9
*/
Packit 90a5c9
typedef struct {
Packit 90a5c9
    const dav_hooks_repository *repos;
Packit 90a5c9
    const dav_hooks_propdb *propdb;
Packit 90a5c9
    const dav_hooks_locks *locks;
Packit 90a5c9
    const dav_hooks_vsn *vsn;
Packit 90a5c9
    const dav_hooks_binding *binding;
Packit 90a5c9
    const dav_hooks_search *search;
Packit 90a5c9
Packit 90a5c9
    void *ctx;
Packit 90a5c9
} dav_provider;
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** gather_propsets: gather all live property propset-URIs
Packit 90a5c9
**
Packit 90a5c9
** The hook implementor should push one or more URIs into the specified
Packit 90a5c9
** array. These URIs are returned in the DAV: header to let clients know
Packit 90a5c9
** what sets of live properties are supported by the installation. mod_dav
Packit 90a5c9
** will place open/close angle brackets around each value (much like
Packit 90a5c9
** a Coded-URL); quotes and brackets should not be in the value.
Packit 90a5c9
**
Packit 90a5c9
** Example:    http://apache.org/dav/props/
Packit 90a5c9
**
Packit 90a5c9
** (of course, use your own domain to ensure a unique value)
Packit 90a5c9
*/
Packit 90a5c9
APR_DECLARE_EXTERNAL_HOOK(dav, DAV, void, gather_propsets,
Packit 90a5c9
                         (apr_array_header_t *uris))
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** find_liveprop: find a live property, returning a non-zero, unique,
Packit 90a5c9
**                opaque identifier.
Packit 90a5c9
**
Packit 90a5c9
** If the hook implementor determines the specified URI/name refers to
Packit 90a5c9
** one of its properties, then it should fill in HOOKS and return a
Packit 90a5c9
** non-zero value. The returned value is the "property ID" and will
Packit 90a5c9
** be passed to the various liveprop hook functions.
Packit 90a5c9
**
Packit 90a5c9
** Return 0 if the property is not defined by the hook implementor.
Packit 90a5c9
*/
Packit 90a5c9
APR_DECLARE_EXTERNAL_HOOK(dav, DAV, int, find_liveprop,
Packit 90a5c9
                         (const dav_resource *resource,
Packit 90a5c9
                          const char *ns_uri, const char *name,
Packit 90a5c9
                          const dav_hooks_liveprop **hooks))
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** insert_all_liveprops: insert all (known) live property names/values.
Packit 90a5c9
**
Packit 90a5c9
** The hook implementor should append XML text to PHDR, containing liveprop
Packit 90a5c9
** names. If INSVALUE is true, then the property values should also be
Packit 90a5c9
** inserted into the output XML stream.
Packit 90a5c9
**
Packit 90a5c9
** The liveprop provider should insert *all* known and *defined* live
Packit 90a5c9
** properties on the specified resource. If a particular liveprop is
Packit 90a5c9
** not defined for this resource, then it should not be inserted.
Packit 90a5c9
*/
Packit 90a5c9
APR_DECLARE_EXTERNAL_HOOK(dav, DAV, void, insert_all_liveprops,
Packit 90a5c9
                         (request_rec *r, const dav_resource *resource,
Packit 90a5c9
                          dav_prop_insert what, apr_text_header *phdr))
Packit 90a5c9
Packit 90a5c9
DAV_DECLARE(const dav_hooks_locks *) dav_get_lock_hooks(request_rec *r);
Packit 90a5c9
DAV_DECLARE(const dav_hooks_propdb *) dav_get_propdb_hooks(request_rec *r);
Packit 90a5c9
DAV_DECLARE(const dav_hooks_vsn *) dav_get_vsn_hooks(request_rec *r);
Packit 90a5c9
DAV_DECLARE(const dav_hooks_binding *) dav_get_binding_hooks(request_rec *r);
Packit 90a5c9
DAV_DECLARE(const dav_hooks_search *) dav_get_search_hooks(request_rec *r);
Packit 90a5c9
Packit 90a5c9
DAV_DECLARE(void) dav_register_provider(apr_pool_t *p, const char *name,
Packit 90a5c9
                                        const dav_provider *hooks);
Packit 90a5c9
DAV_DECLARE(const dav_provider *) dav_lookup_provider(const char *name);
Packit 90a5c9
DAV_DECLARE(const char *) dav_get_provider_name(request_rec *r);
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/* ### deprecated */
Packit 90a5c9
#define DAV_GET_HOOKS_PROPDB(r)         dav_get_propdb_hooks(r)
Packit 90a5c9
#define DAV_GET_HOOKS_LOCKS(r)          dav_get_lock_hooks(r)
Packit 90a5c9
#define DAV_GET_HOOKS_VSN(r)            dav_get_vsn_hooks(r)
Packit 90a5c9
#define DAV_GET_HOOKS_BINDING(r)        dav_get_binding_hooks(r)
Packit 90a5c9
#define DAV_GET_HOOKS_SEARCH(r)         dav_get_search_hooks(r)
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/* --------------------------------------------------------------------
Packit 90a5c9
**
Packit 90a5c9
** IF HEADER PROCESSING
Packit 90a5c9
**
Packit 90a5c9
** Here is the definition of the If: header from RFC 2518, S9.4:
Packit 90a5c9
**
Packit 90a5c9
**    If = "If" ":" (1*No-tag-list | 1*Tagged-list)
Packit 90a5c9
**    No-tag-list = List
Packit 90a5c9
**    Tagged-list = Resource 1*List
Packit 90a5c9
**    Resource = Coded-URL
Packit 90a5c9
**    List = "(" 1*(["Not"](State-token | "[" entity-tag "]")) ")"
Packit 90a5c9
**    State-token = Coded-URL
Packit 90a5c9
**    Coded-URL = "<" absoluteURI ">"        ; absoluteURI from RFC 2616
Packit 90a5c9
**
Packit 90a5c9
** List corresponds to dav_if_state_list. No-tag-list corresponds to
Packit 90a5c9
** dav_if_header with uri==NULL. Tagged-list corresponds to a sequence of
Packit 90a5c9
** dav_if_header structures with (duplicate) uri==Resource -- one
Packit 90a5c9
** dav_if_header per state_list. A second Tagged-list will start a new
Packit 90a5c9
** sequence of dav_if_header structures with the new URI.
Packit 90a5c9
**
Packit 90a5c9
** A summary of the semantics, mapped into our structures:
Packit 90a5c9
**    - Chained dav_if_headers: OR
Packit 90a5c9
**    - Chained dav_if_state_lists: AND
Packit 90a5c9
**    - NULL uri matches all resources
Packit 90a5c9
*/
Packit 90a5c9
Packit 90a5c9
typedef enum
Packit 90a5c9
{
Packit 90a5c9
    dav_if_etag,
Packit 90a5c9
    dav_if_opaquelock,
Packit 90a5c9
    dav_if_unknown /* the "unknown" state type; always matches false. */
Packit 90a5c9
} dav_if_state_type;
Packit 90a5c9
Packit 90a5c9
typedef struct dav_if_state_list
Packit 90a5c9
{
Packit 90a5c9
    dav_if_state_type type;
Packit 90a5c9
Packit 90a5c9
    int condition;
Packit 90a5c9
#define DAV_IF_COND_NORMAL      0
Packit 90a5c9
#define DAV_IF_COND_NOT         1    /* "Not" was applied */
Packit 90a5c9
Packit 90a5c9
    const char *etag;
Packit 90a5c9
    dav_locktoken *locktoken;
Packit 90a5c9
Packit 90a5c9
    struct dav_if_state_list *next;
Packit 90a5c9
} dav_if_state_list;
Packit 90a5c9
Packit 90a5c9
typedef struct dav_if_header
Packit 90a5c9
{
Packit 90a5c9
    const char *uri;
Packit 90a5c9
    apr_size_t uri_len;
Packit 90a5c9
    struct dav_if_state_list *state;
Packit 90a5c9
    struct dav_if_header *next;
Packit 90a5c9
Packit 90a5c9
    int dummy_header;   /* used internally by the lock/etag validation */
Packit 90a5c9
} dav_if_header;
Packit 90a5c9
Packit 90a5c9
typedef struct dav_locktoken_list
Packit 90a5c9
{
Packit 90a5c9
    dav_locktoken *locktoken;
Packit 90a5c9
    struct dav_locktoken_list *next;
Packit 90a5c9
} dav_locktoken_list;
Packit 90a5c9
Packit 90a5c9
DAV_DECLARE(dav_error *) dav_get_locktoken_list(request_rec *r,
Packit 90a5c9
                                                dav_locktoken_list **ltl);
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/* --------------------------------------------------------------------
Packit 90a5c9
**
Packit 90a5c9
** LIVE PROPERTY HANDLING
Packit 90a5c9
*/
Packit 90a5c9
Packit 90a5c9
/* opaque type for PROPPATCH rollback information */
Packit 90a5c9
typedef struct dav_liveprop_rollback dav_liveprop_rollback;
Packit 90a5c9
Packit 90a5c9
struct dav_hooks_liveprop
Packit 90a5c9
{
Packit 90a5c9
    /*
Packit 90a5c9
    ** Insert property information into a text block. The property to
Packit 90a5c9
    ** insert is identified by the propid value. The information to insert
Packit 90a5c9
    ** is identified by the "what" argument, as follows:
Packit 90a5c9
    **   DAV_PROP_INSERT_NAME
Packit 90a5c9
    **      property name, as an empty XML element
Packit 90a5c9
    **   DAV_PROP_INSERT_VALUE
Packit 90a5c9
    **      property name/value, as an XML element
Packit 90a5c9
    **   DAV_PROP_INSERT_SUPPORTED
Packit 90a5c9
    **      if the property is defined on the resource, then
Packit 90a5c9
    **      a DAV:supported-live-property element, as defined
Packit 90a5c9
    **      by the DeltaV extensions to RFC2518.
Packit 90a5c9
    **
Packit 90a5c9
    ** Providers should return DAV_PROP_INSERT_NOTDEF if the property is
Packit 90a5c9
    ** known and not defined for this resource, so should be handled as a
Packit 90a5c9
    ** dead property. If a provider recognizes, but does not support, a
Packit 90a5c9
    ** property, and does not want it handled as a dead property, it should
Packit 90a5c9
    ** return DAV_PROP_INSERT_NOTSUPP.
Packit 90a5c9
    **
Packit 90a5c9
    ** Returns one of DAV_PROP_INSERT_* based on what happened.
Packit 90a5c9
    **
Packit 90a5c9
    ** ### we may need more context... ie. the lock database
Packit 90a5c9
    */
Packit 90a5c9
    dav_prop_insert (*insert_prop)(const dav_resource *resource,
Packit 90a5c9
                                   int propid, dav_prop_insert what,
Packit 90a5c9
                                   apr_text_header *phdr);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Determine whether a given property is writable.
Packit 90a5c9
    **
Packit 90a5c9
    ** ### we may want a different semantic. i.e. maybe it should be
Packit 90a5c9
    ** ### "can we write <value> into this property?"
Packit 90a5c9
    **
Packit 90a5c9
    ** Returns 1 if the live property can be written, 0 if read-only.
Packit 90a5c9
    */
Packit 90a5c9
    int (*is_writable)(const dav_resource *resource, int propid);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** This member defines the set of namespace URIs that the provider
Packit 90a5c9
    ** uses for its properties. When insert_all is called, it will be
Packit 90a5c9
    ** passed a list of integers that map from indices into this list
Packit 90a5c9
    ** to namespace IDs for output generation.
Packit 90a5c9
    **
Packit 90a5c9
    ** The last entry in this list should be a NULL value (sentinel).
Packit 90a5c9
    */
Packit 90a5c9
    const char * const * namespace_uris;
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** ### this is not the final design. we want an open-ended way for
Packit 90a5c9
    ** ### liveprop providers to attach *new* properties. To this end,
Packit 90a5c9
    ** ### we'll have a "give me a list of the props you define", a way
Packit 90a5c9
    ** ### to check for a prop's existence, a way to validate a set/remove
Packit 90a5c9
    ** ### of a prop, and a way to execute/commit/rollback that change.
Packit 90a5c9
    */
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Validate that the live property can be assigned a value, and that
Packit 90a5c9
    ** the provided value is valid.
Packit 90a5c9
    **
Packit 90a5c9
    ** elem will point to the XML element that names the property. For
Packit 90a5c9
    ** example:
Packit 90a5c9
    **     <lp1:executable>T</lp1:executable>
Packit 90a5c9
    **
Packit 90a5c9
    ** The provider can access the cdata fields and the child elements
Packit 90a5c9
    ** to extract the relevant pieces.
Packit 90a5c9
    **
Packit 90a5c9
    ** operation is one of DAV_PROP_OP_SET or _DELETE.
Packit 90a5c9
    **
Packit 90a5c9
    ** The provider may return a value in *context which will be passed
Packit 90a5c9
    ** to each of the exec/commit/rollback functions. For example, this
Packit 90a5c9
    ** may contain an internal value which has been processed from the
Packit 90a5c9
    ** input element.
Packit 90a5c9
    **
Packit 90a5c9
    ** The provider must set defer_to_dead to true (non-zero) or false.
Packit 90a5c9
    ** If true, then the set/remove is deferred to the dead property
Packit 90a5c9
    ** database. Note: it will be set to zero on entry.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*patch_validate)(const dav_resource *resource,
Packit 90a5c9
                                  const apr_xml_elem *elem,
Packit 90a5c9
                                  int operation,
Packit 90a5c9
                                  void **context,
Packit 90a5c9
                                  int *defer_to_dead);
Packit 90a5c9
Packit 90a5c9
    /* ### doc... */
Packit 90a5c9
    dav_error * (*patch_exec)(const dav_resource *resource,
Packit 90a5c9
                              const apr_xml_elem *elem,
Packit 90a5c9
                              int operation,
Packit 90a5c9
                              void *context,
Packit 90a5c9
                              dav_liveprop_rollback **rollback_ctx);
Packit 90a5c9
Packit 90a5c9
    /* ### doc... */
Packit 90a5c9
    void (*patch_commit)(const dav_resource *resource,
Packit 90a5c9
                         int operation,
Packit 90a5c9
                         void *context,
Packit 90a5c9
                         dav_liveprop_rollback *rollback_ctx);
Packit 90a5c9
Packit 90a5c9
    /* ### doc... */
Packit 90a5c9
    dav_error * (*patch_rollback)(const dav_resource *resource,
Packit 90a5c9
                                  int operation,
Packit 90a5c9
                                  void *context,
Packit 90a5c9
                                  dav_liveprop_rollback *rollback_ctx);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** If a provider needs a context to associate with this hooks structure,
Packit 90a5c9
    ** then this field may be used. In most cases, it will just be NULL.
Packit 90a5c9
    */
Packit 90a5c9
    void *ctx;
Packit 90a5c9
};
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** dav_liveprop_spec: specify a live property
Packit 90a5c9
**
Packit 90a5c9
** This structure is used as a standard way to determine if a particular
Packit 90a5c9
** property is a live property. Its use is not part of the mandated liveprop
Packit 90a5c9
** interface, but can be used by liveprop providers in conjunction with the
Packit 90a5c9
** utility routines below.
Packit 90a5c9
**
Packit 90a5c9
** spec->name == NULL is the defined end-sentinel for a list of specs.
Packit 90a5c9
*/
Packit 90a5c9
typedef struct {
Packit 90a5c9
    int ns;             /* provider-local namespace index */
Packit 90a5c9
    const char *name;   /* name of the property */
Packit 90a5c9
Packit 90a5c9
    int propid;         /* provider-local property ID */
Packit 90a5c9
Packit 90a5c9
    int is_writable;    /* is the property writable? */
Packit 90a5c9
Packit 90a5c9
} dav_liveprop_spec;
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** dav_liveprop_group: specify a group of liveprops
Packit 90a5c9
**
Packit 90a5c9
** This structure specifies a group of live properties, their namespaces,
Packit 90a5c9
** and how to handle them.
Packit 90a5c9
*/
Packit 90a5c9
typedef struct {
Packit 90a5c9
    const dav_liveprop_spec *specs;
Packit 90a5c9
    const char * const *namespace_uris;
Packit 90a5c9
    const dav_hooks_liveprop *hooks;
Packit 90a5c9
Packit 90a5c9
} dav_liveprop_group;
Packit 90a5c9
Packit 90a5c9
/* ### docco */
Packit 90a5c9
DAV_DECLARE(int) dav_do_find_liveprop(const char *ns_uri, const char *name,
Packit 90a5c9
                                      const dav_liveprop_group *group,
Packit 90a5c9
                                      const dav_hooks_liveprop **hooks);
Packit 90a5c9
Packit 90a5c9
/* ### docco */
Packit 90a5c9
DAV_DECLARE(long) dav_get_liveprop_info(int propid,
Packit 90a5c9
                                        const dav_liveprop_group *group,
Packit 90a5c9
                                        const dav_liveprop_spec **info);
Packit 90a5c9
Packit 90a5c9
/* ### docco */
Packit 90a5c9
DAV_DECLARE(void) dav_register_liveprop_group(apr_pool_t *pool,
Packit 90a5c9
                                              const dav_liveprop_group *group);
Packit 90a5c9
Packit 90a5c9
/* ### docco */
Packit 90a5c9
DAV_DECLARE(long) dav_get_liveprop_ns_index(const char *uri);
Packit 90a5c9
Packit 90a5c9
/* ### docco */
Packit 90a5c9
DAV_DECLARE(long) dav_get_liveprop_ns_count(void);
Packit 90a5c9
Packit 90a5c9
/* ### docco */
Packit 90a5c9
DAV_DECLARE(void) dav_add_all_liveprop_xmlns(apr_pool_t *p,
Packit 90a5c9
                                             apr_text_header *phdr);
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** The following three functions are part of mod_dav's internal handling
Packit 90a5c9
** for the core WebDAV properties. They are not part of mod_dav's API.
Packit 90a5c9
*/
Packit 90a5c9
DAV_DECLARE_NONSTD(int) dav_core_find_liveprop(
Packit 90a5c9
    const dav_resource *resource,
Packit 90a5c9
    const char *ns_uri,
Packit 90a5c9
    const char *name,
Packit 90a5c9
    const dav_hooks_liveprop **hooks);
Packit 90a5c9
DAV_DECLARE_NONSTD(void) dav_core_insert_all_liveprops(
Packit 90a5c9
    request_rec *r,
Packit 90a5c9
    const dav_resource *resource,
Packit 90a5c9
    dav_prop_insert what,
Packit 90a5c9
    apr_text_header *phdr);
Packit 90a5c9
DAV_DECLARE_NONSTD(void) dav_core_register_uris(apr_pool_t *p);
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** Standard WebDAV Property Identifiers
Packit 90a5c9
**
Packit 90a5c9
** A live property provider does not need to use these; they are simply
Packit 90a5c9
** provided for convenience.
Packit 90a5c9
**
Packit 90a5c9
** Property identifiers need to be unique within a given provider, but not
Packit 90a5c9
** *across* providers (note: this uniqueness constraint was different in
Packit 90a5c9
** older versions of mod_dav).
Packit 90a5c9
**
Packit 90a5c9
** The identifiers start at 20000 to make it easier for providers to avoid
Packit 90a5c9
** conflicts with the standard properties. The properties are arranged
Packit 90a5c9
** alphabetically, and may be reordered from time to time (as properties
Packit 90a5c9
** are introduced).
Packit 90a5c9
**
Packit 90a5c9
** NOTE: there is no problem with reordering (e.g. binary compat) since the
Packit 90a5c9
** identifiers are only used within a given provider, which would pick up
Packit 90a5c9
** the entire set of changes upon a recompile.
Packit 90a5c9
*/
Packit 90a5c9
enum {
Packit 90a5c9
    DAV_PROPID_BEGIN = 20000,
Packit 90a5c9
Packit 90a5c9
    /* Standard WebDAV properties (RFC 2518) */
Packit 90a5c9
    DAV_PROPID_creationdate,
Packit 90a5c9
    DAV_PROPID_displayname,
Packit 90a5c9
    DAV_PROPID_getcontentlanguage,
Packit 90a5c9
    DAV_PROPID_getcontentlength,
Packit 90a5c9
    DAV_PROPID_getcontenttype,
Packit 90a5c9
    DAV_PROPID_getetag,
Packit 90a5c9
    DAV_PROPID_getlastmodified,
Packit 90a5c9
    DAV_PROPID_lockdiscovery,
Packit 90a5c9
    DAV_PROPID_resourcetype,
Packit 90a5c9
    DAV_PROPID_source,
Packit 90a5c9
    DAV_PROPID_supportedlock,
Packit 90a5c9
Packit 90a5c9
    /* DeltaV properties (from the I-D (#14)) */
Packit 90a5c9
    DAV_PROPID_activity_checkout_set,
Packit 90a5c9
    DAV_PROPID_activity_set,
Packit 90a5c9
    DAV_PROPID_activity_version_set,
Packit 90a5c9
    DAV_PROPID_auto_merge_set,
Packit 90a5c9
    DAV_PROPID_auto_version,
Packit 90a5c9
    DAV_PROPID_baseline_collection,
Packit 90a5c9
    DAV_PROPID_baseline_controlled_collection,
Packit 90a5c9
    DAV_PROPID_baseline_controlled_collection_set,
Packit 90a5c9
    DAV_PROPID_checked_in,
Packit 90a5c9
    DAV_PROPID_checked_out,
Packit 90a5c9
    DAV_PROPID_checkin_fork,
Packit 90a5c9
    DAV_PROPID_checkout_fork,
Packit 90a5c9
    DAV_PROPID_checkout_set,
Packit 90a5c9
    DAV_PROPID_comment,
Packit 90a5c9
    DAV_PROPID_creator_displayname,
Packit 90a5c9
    DAV_PROPID_current_activity_set,
Packit 90a5c9
    DAV_PROPID_current_workspace_set,
Packit 90a5c9
    DAV_PROPID_default_variant,
Packit 90a5c9
    DAV_PROPID_eclipsed_set,
Packit 90a5c9
    DAV_PROPID_label_name_set,
Packit 90a5c9
    DAV_PROPID_merge_set,
Packit 90a5c9
    DAV_PROPID_precursor_set,
Packit 90a5c9
    DAV_PROPID_predecessor_set,
Packit 90a5c9
    DAV_PROPID_root_version,
Packit 90a5c9
    DAV_PROPID_subactivity_set,
Packit 90a5c9
    DAV_PROPID_subbaseline_set,
Packit 90a5c9
    DAV_PROPID_successor_set,
Packit 90a5c9
    DAV_PROPID_supported_method_set,
Packit 90a5c9
    DAV_PROPID_supported_live_property_set,
Packit 90a5c9
    DAV_PROPID_supported_report_set,
Packit 90a5c9
    DAV_PROPID_unreserved,
Packit 90a5c9
    DAV_PROPID_variant_set,
Packit 90a5c9
    DAV_PROPID_version_controlled_binding_set,
Packit 90a5c9
    DAV_PROPID_version_controlled_configuration,
Packit 90a5c9
    DAV_PROPID_version_history,
Packit 90a5c9
    DAV_PROPID_version_name,
Packit 90a5c9
    DAV_PROPID_workspace,
Packit 90a5c9
    DAV_PROPID_workspace_checkout_set,
Packit 90a5c9
Packit 90a5c9
    DAV_PROPID_END
Packit 90a5c9
};
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** Property Identifier Registration
Packit 90a5c9
**
Packit 90a5c9
** At the moment, mod_dav requires live property providers to ensure that
Packit 90a5c9
** each property returned has a unique value. For now, this is done through
Packit 90a5c9
** central registration (there are no known providers other than the default,
Packit 90a5c9
** so this remains manageable).
Packit 90a5c9
**
Packit 90a5c9
** WARNING: the TEST ranges should never be "shipped".
Packit 90a5c9
*/
Packit 90a5c9
#define DAV_PROPID_CORE         10000   /* ..10099. defined by mod_dav */
Packit 90a5c9
#define DAV_PROPID_FS           10100   /* ..10299.
Packit 90a5c9
                                           mod_dav filesystem provider. */
Packit 90a5c9
#define DAV_PROPID_TEST1        10300   /* ..10399 */
Packit 90a5c9
#define DAV_PROPID_TEST2        10400   /* ..10499 */
Packit 90a5c9
#define DAV_PROPID_TEST3        10500   /* ..10599 */
Packit 90a5c9
/* Next: 10600 */
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/* --------------------------------------------------------------------
Packit 90a5c9
**
Packit 90a5c9
** DATABASE FUNCTIONS
Packit 90a5c9
*/
Packit 90a5c9
Packit 90a5c9
typedef struct dav_db dav_db;
Packit 90a5c9
typedef struct dav_namespace_map dav_namespace_map;
Packit 90a5c9
typedef struct dav_deadprop_rollback dav_deadprop_rollback;
Packit 90a5c9
Packit 90a5c9
typedef struct {
Packit 90a5c9
    const char *ns;     /* "" signals "no namespace" */
Packit 90a5c9
    const char *name;
Packit 90a5c9
} dav_prop_name;
Packit 90a5c9
Packit 90a5c9
/* hook functions to enable pluggable databases */
Packit 90a5c9
struct dav_hooks_propdb
Packit 90a5c9
{
Packit 90a5c9
    dav_error * (*open)(apr_pool_t *p, const dav_resource *resource, int ro,
Packit 90a5c9
                        dav_db **pdb);
Packit 90a5c9
    void (*close)(dav_db *db);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** In bulk, define any namespaces that the values and their name
Packit 90a5c9
    ** elements may need.
Packit 90a5c9
    **
Packit 90a5c9
    ** Note: sometimes mod_dav will defer calling this until output_value
Packit 90a5c9
    ** returns found==1. If the output process needs the dav_xmlns_info
Packit 90a5c9
    ** filled for its work, then it will need to fill it on demand rather
Packit 90a5c9
    ** than depending upon this hook to fill in the structure.
Packit 90a5c9
    **
Packit 90a5c9
    ** Note: this will *always* be called during an output sequence. Thus,
Packit 90a5c9
    ** the provider may rely solely on using this to fill the xmlns info.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*define_namespaces)(dav_db *db, dav_xmlns_info *xi);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Output the value from the database (i.e. add an element name and
Packit 90a5c9
    ** the value into *phdr). Set *found based on whether the name/value
Packit 90a5c9
    ** was found in the propdb.
Packit 90a5c9
    **
Packit 90a5c9
    ** Note: it is NOT an error for the key/value pair to not exist.
Packit 90a5c9
    **
Packit 90a5c9
    ** The dav_xmlns_info passed to define_namespaces() is also passed to
Packit 90a5c9
    ** each output_value() call so that namespaces can be added on-demand.
Packit 90a5c9
    ** It can also be used to look up prefixes or URIs during the output
Packit 90a5c9
    ** process.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*output_value)(dav_db *db, const dav_prop_name *name,
Packit 90a5c9
                                dav_xmlns_info *xi,
Packit 90a5c9
                                apr_text_header *phdr, int *found);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Build a mapping from "global" namespaces (stored in apr_xml_*)
Packit 90a5c9
    ** into provider-local namespace identifiers.
Packit 90a5c9
    **
Packit 90a5c9
    ** This mapping should be done once per set of namespaces, and the
Packit 90a5c9
    ** resulting mapping should be passed into the store() hook function.
Packit 90a5c9
    **
Packit 90a5c9
    ** Note: usually, there is just a single document/namespaces for all
Packit 90a5c9
    ** elements passed. However, the generality of creating multiple
Packit 90a5c9
    ** mappings and passing them to store() is provided here.
Packit 90a5c9
    **
Packit 90a5c9
    ** Note: this is only in preparation for a series of store() calls.
Packit 90a5c9
    ** As a result, the propdb must be open for read/write access when
Packit 90a5c9
    ** this function is called.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*map_namespaces)(dav_db *db,
Packit 90a5c9
                                  const apr_array_header_t *namespaces,
Packit 90a5c9
                                  dav_namespace_map **mapping);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Store a property value for a given name. The value->combined field
Packit 90a5c9
    ** MUST be set for this call.
Packit 90a5c9
    **
Packit 90a5c9
    ** ### WARNING: current providers will quote the text within ELEM.
Packit 90a5c9
    ** ### this implies you can call this function only once with a given
Packit 90a5c9
    ** ### element structure (a second time will quote it again).
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*store)(dav_db *db, const dav_prop_name *name,
Packit 90a5c9
                         const apr_xml_elem *elem,
Packit 90a5c9
                         dav_namespace_map *mapping);
Packit 90a5c9
Packit 90a5c9
    /* remove a given property */
Packit 90a5c9
    dav_error * (*remove)(dav_db *db, const dav_prop_name *name);
Packit 90a5c9
Packit 90a5c9
    /* returns 1 if the record specified by "key" exists; 0 otherwise */
Packit 90a5c9
    int (*exists)(dav_db *db, const dav_prop_name *name);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Iterate over the property names in the database.
Packit 90a5c9
    **
Packit 90a5c9
    ** iter->name.ns == iter->name.name == NULL when there are no more names.
Packit 90a5c9
    **
Packit 90a5c9
    ** Note: only one iteration may occur over the propdb at a time.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*first_name)(dav_db *db, dav_prop_name *pname);
Packit 90a5c9
    dav_error * (*next_name)(dav_db *db, dav_prop_name *pname);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Rollback support: get rollback context, and apply it.
Packit 90a5c9
    **
Packit 90a5c9
    ** struct dav_deadprop_rollback is a provider-private structure; it
Packit 90a5c9
    ** should remember the name, and the name's old value (or the fact that
Packit 90a5c9
    ** the value was not present, and should be deleted if a rollback occurs).
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*get_rollback)(dav_db *db, const dav_prop_name *name,
Packit 90a5c9
                                dav_deadprop_rollback **prollback);
Packit 90a5c9
    dav_error * (*apply_rollback)(dav_db *db,
Packit 90a5c9
                                  dav_deadprop_rollback *rollback);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** If a provider needs a context to associate with this hooks structure,
Packit 90a5c9
    ** then this field may be used. In most cases, it will just be NULL.
Packit 90a5c9
    */
Packit 90a5c9
    void *ctx;
Packit 90a5c9
};
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/* --------------------------------------------------------------------
Packit 90a5c9
**
Packit 90a5c9
** LOCK FUNCTIONS
Packit 90a5c9
*/
Packit 90a5c9
Packit 90a5c9
/* Used to represent a Timeout header of "Infinity" */
Packit 90a5c9
#define DAV_TIMEOUT_INFINITE 0
Packit 90a5c9
Packit 90a5c9
DAV_DECLARE(time_t) dav_get_timeout(request_rec *r);
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** Opaque, provider-specific information for a lock database.
Packit 90a5c9
*/
Packit 90a5c9
typedef struct dav_lockdb_private dav_lockdb_private;
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** Opaque, provider-specific information for a lock record.
Packit 90a5c9
*/
Packit 90a5c9
typedef struct dav_lock_private dav_lock_private;
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** Lock database type. Lock providers are urged to implement a "lazy" open, so
Packit 90a5c9
** doing an "open" is cheap until something is actually needed from the DB.
Packit 90a5c9
*/
Packit 90a5c9
typedef struct
Packit 90a5c9
{
Packit 90a5c9
    const dav_hooks_locks *hooks;   /* the hooks used for this lockdb */
Packit 90a5c9
    int ro;                         /* was it opened readonly? */
Packit 90a5c9
Packit 90a5c9
    dav_lockdb_private *info;
Packit 90a5c9
Packit 90a5c9
} dav_lockdb;
Packit 90a5c9
Packit 90a5c9
typedef enum {
Packit 90a5c9
    DAV_LOCKSCOPE_UNKNOWN,
Packit 90a5c9
    DAV_LOCKSCOPE_EXCLUSIVE,
Packit 90a5c9
    DAV_LOCKSCOPE_SHARED
Packit 90a5c9
} dav_lock_scope;
Packit 90a5c9
Packit 90a5c9
typedef enum {
Packit 90a5c9
    DAV_LOCKTYPE_UNKNOWN,
Packit 90a5c9
    DAV_LOCKTYPE_WRITE
Packit 90a5c9
} dav_lock_type;
Packit 90a5c9
Packit 90a5c9
typedef enum {
Packit 90a5c9
    DAV_LOCKREC_DIRECT,             /* lock asserted on this resource */
Packit 90a5c9
    DAV_LOCKREC_INDIRECT,           /* lock inherited from a parent */
Packit 90a5c9
    DAV_LOCKREC_INDIRECT_PARTIAL    /* most info is not filled in */
Packit 90a5c9
} dav_lock_rectype;
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** dav_lock: hold information about a lock on a resource.
Packit 90a5c9
**
Packit 90a5c9
** This structure is used for both direct and indirect locks. A direct lock
Packit 90a5c9
** is a lock applied to a specific resource by the client. An indirect lock
Packit 90a5c9
** is one that is inherited from a parent resource by virtue of a non-zero
Packit 90a5c9
** Depth: header when the lock was applied.
Packit 90a5c9
**
Packit 90a5c9
** mod_dav records both types of locks in the lock database, managing their
Packit 90a5c9
** addition/removal as resources are moved about the namespace.
Packit 90a5c9
**
Packit 90a5c9
** Note that the lockdb is free to marshal this structure in any form that
Packit 90a5c9
** it likes.
Packit 90a5c9
**
Packit 90a5c9
** For a "partial" lock, the <rectype> and <locktoken> fields must be filled
Packit 90a5c9
** in. All other (user) fields should be zeroed. The lock provider will
Packit 90a5c9
** usually fill in the <info> field, and the <next> field may be used to
Packit 90a5c9
** construct a list of partial locks.
Packit 90a5c9
**
Packit 90a5c9
** The lock provider MUST use the info field to store a value such that a
Packit 90a5c9
** dav_lock structure can locate itself in the underlying lock database.
Packit 90a5c9
** This requirement is needed for refreshing: when an indirect dav_lock is
Packit 90a5c9
** refreshed, its reference to the direct lock does not specify the direct's
Packit 90a5c9
** resource, so the only way to locate the (refreshed, direct) lock in the
Packit 90a5c9
** database is to use the info field.
Packit 90a5c9
**
Packit 90a5c9
** Note that <is_locknull> only refers to the resource where this lock was
Packit 90a5c9
** found.
Packit 90a5c9
** ### hrm. that says the abstraction is wrong. is_locknull may disappear.
Packit 90a5c9
*/
Packit 90a5c9
typedef struct dav_lock
Packit 90a5c9
{
Packit 90a5c9
    dav_lock_rectype rectype;   /* type of lock record */
Packit 90a5c9
    int is_locknull;            /* lock establishes a locknull resource */
Packit 90a5c9
Packit 90a5c9
    /* ### put the resource in here? */
Packit 90a5c9
Packit 90a5c9
    dav_lock_scope scope;       /* scope of the lock */
Packit 90a5c9
    dav_lock_type type;         /* type of lock */
Packit 90a5c9
    int depth;                  /* depth of the lock */
Packit 90a5c9
    time_t timeout;             /* when the lock will timeout */
Packit 90a5c9
Packit 90a5c9
    const dav_locktoken *locktoken;  /* the token that was issued */
Packit 90a5c9
Packit 90a5c9
    const char *owner;          /* (XML) owner of the lock */
Packit 90a5c9
    const char *auth_user;      /* auth'd username owning lock */
Packit 90a5c9
Packit 90a5c9
    dav_lock_private *info;     /* private to the lockdb */
Packit 90a5c9
Packit 90a5c9
    struct dav_lock *next;      /* for managing a list of locks */
Packit 90a5c9
} dav_lock;
Packit 90a5c9
Packit 90a5c9
/* Property-related public lock functions */
Packit 90a5c9
DAV_DECLARE(const char *)dav_lock_get_activelock(request_rec *r,
Packit 90a5c9
                                                 dav_lock *locks,
Packit 90a5c9
                                                 dav_buffer *pbuf);
Packit 90a5c9
Packit 90a5c9
/* LockDB-related public lock functions */
Packit 90a5c9
DAV_DECLARE(dav_error *) dav_lock_parse_lockinfo(request_rec *r,
Packit 90a5c9
                                                 const dav_resource *resrouce,
Packit 90a5c9
                                                 dav_lockdb *lockdb,
Packit 90a5c9
                                                 const apr_xml_doc *doc,
Packit 90a5c9
                                                 dav_lock **lock_request);
Packit 90a5c9
DAV_DECLARE(int) dav_unlock(request_rec *r,
Packit 90a5c9
                            const dav_resource *resource,
Packit 90a5c9
                            const dav_locktoken *locktoken);
Packit 90a5c9
DAV_DECLARE(dav_error *) dav_add_lock(request_rec *r,
Packit 90a5c9
                                      const dav_resource *resource,
Packit 90a5c9
                                      dav_lockdb *lockdb, dav_lock *request,
Packit 90a5c9
                                      dav_response **response);
Packit 90a5c9
DAV_DECLARE(dav_error *) dav_notify_created(request_rec *r,
Packit 90a5c9
                                            dav_lockdb *lockdb,
Packit 90a5c9
                                            const dav_resource *resource,
Packit 90a5c9
                                            int resource_state,
Packit 90a5c9
                                            int depth);
Packit 90a5c9
Packit 90a5c9
DAV_DECLARE(dav_error*) dav_lock_query(dav_lockdb *lockdb,
Packit 90a5c9
                                       const dav_resource *resource,
Packit 90a5c9
                                       dav_lock **locks);
Packit 90a5c9
Packit 90a5c9
DAV_DECLARE(dav_error *) dav_validate_request(request_rec *r,
Packit 90a5c9
                                              dav_resource *resource,
Packit 90a5c9
                                              int depth,
Packit 90a5c9
                                              dav_locktoken *locktoken,
Packit 90a5c9
                                              dav_response **response,
Packit 90a5c9
                                              int flags,
Packit 90a5c9
                                              dav_lockdb *lockdb);
Packit 90a5c9
/*
Packit 90a5c9
** flags:
Packit 90a5c9
**    0x0F -- reserved for <dav_lock_scope> values
Packit 90a5c9
**
Packit 90a5c9
**    other flags, detailed below
Packit 90a5c9
*/
Packit 90a5c9
#define DAV_VALIDATE_RESOURCE   0x0010  /* validate just the resource */
Packit 90a5c9
#define DAV_VALIDATE_PARENT     0x0020  /* validate resource AND its parent */
Packit 90a5c9
#define DAV_VALIDATE_ADD_LD     0x0040  /* add DAV:lockdiscovery into
Packit 90a5c9
                                           the 424 DAV:response */
Packit 90a5c9
#define DAV_VALIDATE_USE_424    0x0080  /* return 424 status, not 207 */
Packit 90a5c9
#define DAV_VALIDATE_IS_PARENT  0x0100  /* for internal use */
Packit 90a5c9
#define DAV_VALIDATE_NO_MODIFY  0x0200  /* resource is not being modified
Packit 90a5c9
                                           so allow even if lock token
Packit 90a5c9
                                           is not provided */
Packit 90a5c9
Packit 90a5c9
/* Lock-null related public lock functions */
Packit 90a5c9
DAV_DECLARE(int) dav_get_resource_state(request_rec *r,
Packit 90a5c9
                                        const dav_resource *resource);
Packit 90a5c9
Packit 90a5c9
/* Lock provider hooks. Locking is optional, so there may be no
Packit 90a5c9
 * lock provider for a given repository.
Packit 90a5c9
 */
Packit 90a5c9
struct dav_hooks_locks
Packit 90a5c9
{
Packit 90a5c9
    /* Return the supportedlock property for a resource */
Packit 90a5c9
    const char * (*get_supportedlock)(
Packit 90a5c9
        const dav_resource *resource
Packit 90a5c9
    );
Packit 90a5c9
Packit 90a5c9
    /* Parse a lock token URI, returning a lock token object allocated
Packit 90a5c9
     * in the given pool.
Packit 90a5c9
     */
Packit 90a5c9
    dav_error * (*parse_locktoken)(
Packit 90a5c9
        apr_pool_t *p,
Packit 90a5c9
        const char *char_token,
Packit 90a5c9
        dav_locktoken **locktoken_p
Packit 90a5c9
    );
Packit 90a5c9
Packit 90a5c9
    /* Format a lock token object into a URI string, allocated in
Packit 90a5c9
     * the given pool.
Packit 90a5c9
     *
Packit 90a5c9
     * Always returns non-NULL.
Packit 90a5c9
     */
Packit 90a5c9
    const char * (*format_locktoken)(
Packit 90a5c9
        apr_pool_t *p,
Packit 90a5c9
        const dav_locktoken *locktoken
Packit 90a5c9
    );
Packit 90a5c9
Packit 90a5c9
    /* Compare two lock tokens.
Packit 90a5c9
     *
Packit 90a5c9
     * Result < 0  => lt1 < lt2
Packit 90a5c9
     * Result == 0 => lt1 == lt2
Packit 90a5c9
     * Result > 0  => lt1 > lt2
Packit 90a5c9
     */
Packit 90a5c9
    int (*compare_locktoken)(
Packit 90a5c9
        const dav_locktoken *lt1,
Packit 90a5c9
        const dav_locktoken *lt2
Packit 90a5c9
    );
Packit 90a5c9
Packit 90a5c9
    /* Open the provider's lock database.
Packit 90a5c9
     *
Packit 90a5c9
     * The provider may or may not use a "real" database for locks
Packit 90a5c9
     * (a lock could be an attribute on a resource, for example).
Packit 90a5c9
     *
Packit 90a5c9
     * The provider may choose to use the value of the DAVLockDB directive
Packit 90a5c9
     * (as returned by dav_get_lockdb_path()) to decide where to place
Packit 90a5c9
     * any storage it may need.
Packit 90a5c9
     *
Packit 90a5c9
     * The request storage pool should be associated with the lockdb,
Packit 90a5c9
     * so it can be used in subsequent operations.
Packit 90a5c9
     *
Packit 90a5c9
     * If ro != 0, only readonly operations will be performed.
Packit 90a5c9
     * If force == 0, the open can be "lazy"; no subsequent locking operations
Packit 90a5c9
     * may occur.
Packit 90a5c9
     * If force != 0, locking operations will definitely occur.
Packit 90a5c9
     */
Packit 90a5c9
    dav_error * (*open_lockdb)(
Packit 90a5c9
        request_rec *r,
Packit 90a5c9
        int ro,
Packit 90a5c9
        int force,
Packit 90a5c9
        dav_lockdb **lockdb
Packit 90a5c9
    );
Packit 90a5c9
Packit 90a5c9
    /* Indicates completion of locking operations */
Packit 90a5c9
    void (*close_lockdb)(
Packit 90a5c9
        dav_lockdb *lockdb
Packit 90a5c9
    );
Packit 90a5c9
Packit 90a5c9
    /* Take a resource out of the lock-null state. */
Packit 90a5c9
    dav_error * (*remove_locknull_state)(
Packit 90a5c9
        dav_lockdb *lockdb,
Packit 90a5c9
        const dav_resource *resource
Packit 90a5c9
    );
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Create a (direct) lock structure for the given resource. A locktoken
Packit 90a5c9
    ** will be created.
Packit 90a5c9
    **
Packit 90a5c9
    ** The lock provider may store private information into lock->info.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*create_lock)(dav_lockdb *lockdb,
Packit 90a5c9
                               const dav_resource *resource,
Packit 90a5c9
                               dav_lock **lock);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Get the locks associated with the specified resource.
Packit 90a5c9
    **
Packit 90a5c9
    ** If resolve_locks is true (non-zero), then any indirect locks are
Packit 90a5c9
    ** resolved to their actual, direct lock (i.e. the reference to followed
Packit 90a5c9
    ** to the original lock).
Packit 90a5c9
    **
Packit 90a5c9
    ** The locks, if any, are returned as a linked list in no particular
Packit 90a5c9
    ** order. If no locks are present, then *locks will be NULL.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*get_locks)(dav_lockdb *lockdb,
Packit 90a5c9
                             const dav_resource *resource,
Packit 90a5c9
                             int calltype,
Packit 90a5c9
                             dav_lock **locks);
Packit 90a5c9
Packit 90a5c9
#define DAV_GETLOCKS_RESOLVED   0    /* resolve indirects to directs */
Packit 90a5c9
#define DAV_GETLOCKS_PARTIAL    1    /* leave indirects partially filled */
Packit 90a5c9
#define DAV_GETLOCKS_COMPLETE   2    /* fill out indirect locks */
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Find a particular lock on a resource (specified by its locktoken).
Packit 90a5c9
    **
Packit 90a5c9
    ** *lock will be set to NULL if the lock is not found.
Packit 90a5c9
    **
Packit 90a5c9
    ** Note that the provider can optimize the unmarshalling -- only one
Packit 90a5c9
    ** lock (or none) must be constructed and returned.
Packit 90a5c9
    **
Packit 90a5c9
    ** If partial_ok is true (non-zero), then an indirect lock can be
Packit 90a5c9
    ** partially filled in. Otherwise, another lookup is done and the
Packit 90a5c9
    ** lock structure will be filled out as a DAV_LOCKREC_INDIRECT.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*find_lock)(dav_lockdb *lockdb,
Packit 90a5c9
                             const dav_resource *resource,
Packit 90a5c9
                             const dav_locktoken *locktoken,
Packit 90a5c9
                             int partial_ok,
Packit 90a5c9
                             dav_lock **lock);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Quick test to see if the resource has *any* locks on it.
Packit 90a5c9
    **
Packit 90a5c9
    ** This is typically used to determine if a non-existent resource
Packit 90a5c9
    ** has a lock and is (therefore) a locknull resource.
Packit 90a5c9
    **
Packit 90a5c9
    ** WARNING: this function may return TRUE even when timed-out locks
Packit 90a5c9
    **          exist (i.e. it may not perform timeout checks).
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*has_locks)(dav_lockdb *lockdb,
Packit 90a5c9
                             const dav_resource *resource,
Packit 90a5c9
                             int *locks_present);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Append the specified lock(s) to the set of locks on this resource.
Packit 90a5c9
    **
Packit 90a5c9
    ** If "make_indirect" is true (non-zero), then the specified lock(s)
Packit 90a5c9
    ** should be converted to an indirect lock (if it is a direct lock)
Packit 90a5c9
    ** before appending. Note that the conversion to an indirect lock does
Packit 90a5c9
    ** not alter the passed-in lock -- the change is internal the
Packit 90a5c9
    ** append_locks function.
Packit 90a5c9
    **
Packit 90a5c9
    ** Multiple locks are specified using the lock->next links.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*append_locks)(dav_lockdb *lockdb,
Packit 90a5c9
                                const dav_resource *resource,
Packit 90a5c9
                                int make_indirect,
Packit 90a5c9
                                const dav_lock *lock);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Remove any lock that has the specified locktoken.
Packit 90a5c9
    **
Packit 90a5c9
    ** If locktoken == NULL, then ALL locks are removed.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*remove_lock)(dav_lockdb *lockdb,
Packit 90a5c9
                               const dav_resource *resource,
Packit 90a5c9
                               const dav_locktoken *locktoken);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Refresh all locks, found on the specified resource, which has a
Packit 90a5c9
    ** locktoken in the provided list.
Packit 90a5c9
    **
Packit 90a5c9
    ** If the lock is indirect, then the direct lock is referenced and
Packit 90a5c9
    ** refreshed.
Packit 90a5c9
    **
Packit 90a5c9
    ** Each lock that is updated is returned in the <locks> argument.
Packit 90a5c9
    ** Note that the locks will be fully resolved.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*refresh_locks)(dav_lockdb *lockdb,
Packit 90a5c9
                                 const dav_resource *resource,
Packit 90a5c9
                                 const dav_locktoken_list *ltl,
Packit 90a5c9
                                 time_t new_time,
Packit 90a5c9
                                 dav_lock **locks);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Look up the resource associated with a particular locktoken.
Packit 90a5c9
    **
Packit 90a5c9
    ** The search begins at the specified <start_resource> and the lock
Packit 90a5c9
    ** specified by <locktoken>.
Packit 90a5c9
    **
Packit 90a5c9
    ** If the resource/token specifies an indirect lock, then the direct
Packit 90a5c9
    ** lock will be looked up, and THAT resource will be returned. In other
Packit 90a5c9
    ** words, this function always returns the resource where a particular
Packit 90a5c9
    ** lock (token) was asserted.
Packit 90a5c9
    **
Packit 90a5c9
    ** NOTE: this function pointer is allowed to be NULL, indicating that
Packit 90a5c9
    **       the provider does not support this type of functionality. The
Packit 90a5c9
    **       caller should then traverse up the repository hierarchy looking
Packit 90a5c9
    **       for the resource defining a lock with this locktoken.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*lookup_resource)(dav_lockdb *lockdb,
Packit 90a5c9
                                   const dav_locktoken *locktoken,
Packit 90a5c9
                                   const dav_resource *start_resource,
Packit 90a5c9
                                   const dav_resource **resource);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** If a provider needs a context to associate with this hooks structure,
Packit 90a5c9
    ** then this field may be used. In most cases, it will just be NULL.
Packit 90a5c9
    */
Packit 90a5c9
    void *ctx;
Packit 90a5c9
};
Packit 90a5c9
Packit 90a5c9
/* what types of resources can be discovered by dav_get_resource_state() */
Packit 90a5c9
#define DAV_RESOURCE_LOCK_NULL  10    /* resource lock-null */
Packit 90a5c9
#define DAV_RESOURCE_NULL       11    /* resource null */
Packit 90a5c9
#define DAV_RESOURCE_EXISTS     12    /* resource exists */
Packit 90a5c9
#define DAV_RESOURCE_ERROR      13    /* an error occurred */
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/* --------------------------------------------------------------------
Packit 90a5c9
**
Packit 90a5c9
** PROPERTY HANDLING
Packit 90a5c9
*/
Packit 90a5c9
Packit 90a5c9
typedef struct dav_propdb dav_propdb;
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
DAV_DECLARE(dav_error *) dav_open_propdb(
Packit 90a5c9
    request_rec *r,
Packit 90a5c9
    dav_lockdb *lockdb,
Packit 90a5c9
    const dav_resource *resource,
Packit 90a5c9
    int ro,
Packit 90a5c9
    apr_array_header_t *ns_xlate,
Packit 90a5c9
    dav_propdb **propdb);
Packit 90a5c9
Packit 90a5c9
DAV_DECLARE(void) dav_close_propdb(dav_propdb *db);
Packit 90a5c9
Packit 90a5c9
DAV_DECLARE(dav_get_props_result) dav_get_props(
Packit 90a5c9
    dav_propdb *db,
Packit 90a5c9
    apr_xml_doc *doc);
Packit 90a5c9
Packit 90a5c9
DAV_DECLARE(dav_get_props_result) dav_get_allprops(
Packit 90a5c9
    dav_propdb *db,
Packit 90a5c9
    dav_prop_insert what);
Packit 90a5c9
Packit 90a5c9
DAV_DECLARE(void) dav_get_liveprop_supported(
Packit 90a5c9
    dav_propdb *propdb,
Packit 90a5c9
    const char *ns_uri,
Packit 90a5c9
    const char *propname,
Packit 90a5c9
    apr_text_header *body);
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** 3-phase property modification.
Packit 90a5c9
**
Packit 90a5c9
**   1) validate props. readable? unlocked? ACLs allow access?
Packit 90a5c9
**   2) execute operation (set/delete)
Packit 90a5c9
**   3) commit or rollback
Packit 90a5c9
**
Packit 90a5c9
** ### eventually, auth must be available. a ref to the request_rec (which
Packit 90a5c9
** ### contains the auth info) should be in the shared context struct.
Packit 90a5c9
**
Packit 90a5c9
** Each function may alter the error values and information contained within
Packit 90a5c9
** the context record. This should be done as an "increasing" level of
Packit 90a5c9
** error, rather than overwriting any previous error.
Packit 90a5c9
**
Packit 90a5c9
** Note that commit() cannot generate errors. It should simply free the
Packit 90a5c9
** rollback information.
Packit 90a5c9
**
Packit 90a5c9
** rollback() may generate additional errors because the rollback operation
Packit 90a5c9
** can sometimes fail(!).
Packit 90a5c9
**
Packit 90a5c9
** The caller should allocate an array of these, one per operation. It should
Packit 90a5c9
** be zero-initialized, then the db, operation, and prop fields should be
Packit 90a5c9
** filled in before calling dav_prop_validate. Note that the set/delete
Packit 90a5c9
** operations are order-dependent. For a given (logical) context, the same
Packit 90a5c9
** pointer must be passed to each phase.
Packit 90a5c9
**
Packit 90a5c9
** error_type is an internal value, but will have the same numeric value
Packit 90a5c9
** for each possible "desc" value. This allows the caller to group the
Packit 90a5c9
** descriptions via the error_type variable, rather than through string
Packit 90a5c9
** comparisons. Note that "status" does not provide enough granularity to
Packit 90a5c9
** differentiate/group the "desc" values.
Packit 90a5c9
**
Packit 90a5c9
** Note that the propdb will maintain some (global) context across all
Packit 90a5c9
** of the property change contexts. This implies that you can have only
Packit 90a5c9
** one open transaction per propdb.
Packit 90a5c9
*/
Packit 90a5c9
typedef struct dav_prop_ctx
Packit 90a5c9
{
Packit 90a5c9
    dav_propdb *propdb;
Packit 90a5c9
Packit 90a5c9
    apr_xml_elem *prop;             /* property to affect */
Packit 90a5c9
Packit 90a5c9
    int operation;
Packit 90a5c9
#define DAV_PROP_OP_SET        1    /* set a property value */
Packit 90a5c9
#define DAV_PROP_OP_DELETE     2    /* delete a prop value */
Packit 90a5c9
/* ### add a GET? */
Packit 90a5c9
Packit 90a5c9
    /* private items to the propdb */
Packit 90a5c9
    int is_liveprop;
Packit 90a5c9
    void *liveprop_ctx;
Packit 90a5c9
    struct dav_rollback_item *rollback;  /* optional rollback info */
Packit 90a5c9
Packit 90a5c9
    dav_error *err;                 /* error (if any) */
Packit 90a5c9
Packit 90a5c9
    /* private to mod_dav.c */
Packit 90a5c9
    request_rec *r;
Packit 90a5c9
Packit 90a5c9
} dav_prop_ctx;
Packit 90a5c9
Packit 90a5c9
DAV_DECLARE_NONSTD(void) dav_prop_validate(dav_prop_ctx *ctx);
Packit 90a5c9
DAV_DECLARE_NONSTD(void) dav_prop_exec(dav_prop_ctx *ctx);
Packit 90a5c9
DAV_DECLARE_NONSTD(void) dav_prop_commit(dav_prop_ctx *ctx);
Packit 90a5c9
DAV_DECLARE_NONSTD(void) dav_prop_rollback(dav_prop_ctx *ctx);
Packit 90a5c9
Packit 90a5c9
#define DAV_PROP_CTX_HAS_ERR(dpc)  ((dpc).err && (dpc).err->status >= 300)
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/* --------------------------------------------------------------------
Packit 90a5c9
**
Packit 90a5c9
** WALKER STRUCTURE
Packit 90a5c9
*/
Packit 90a5c9
Packit 90a5c9
enum {
Packit 90a5c9
    DAV_CALLTYPE_MEMBER = 1,    /* called for a member resource */
Packit 90a5c9
    DAV_CALLTYPE_COLLECTION,    /* called for a collection */
Packit 90a5c9
    DAV_CALLTYPE_LOCKNULL       /* called for a locknull resource */
Packit 90a5c9
};
Packit 90a5c9
Packit 90a5c9
typedef struct
Packit 90a5c9
{
Packit 90a5c9
    /* the client-provided context */
Packit 90a5c9
    void *walk_ctx;
Packit 90a5c9
Packit 90a5c9
    /* pool to use for allocations in the callback */
Packit 90a5c9
    apr_pool_t *pool;
Packit 90a5c9
Packit 90a5c9
    /* the current resource */
Packit 90a5c9
    const dav_resource *resource;
Packit 90a5c9
Packit 90a5c9
    /* OUTPUT: add responses to this */
Packit 90a5c9
    dav_response *response;
Packit 90a5c9
Packit 90a5c9
} dav_walk_resource;
Packit 90a5c9
Packit 90a5c9
typedef struct
Packit 90a5c9
{
Packit 90a5c9
    int walk_type;
Packit 90a5c9
#define DAV_WALKTYPE_AUTH       0x0001  /* limit to authorized files */
Packit 90a5c9
#define DAV_WALKTYPE_NORMAL     0x0002  /* walk normal files */
Packit 90a5c9
#define DAV_WALKTYPE_LOCKNULL   0x0004  /* walk locknull resources */
Packit 90a5c9
Packit 90a5c9
    /* callback function and a client context for the walk */
Packit 90a5c9
    dav_error * (*func)(dav_walk_resource *wres, int calltype);
Packit 90a5c9
    void *walk_ctx;
Packit 90a5c9
Packit 90a5c9
    /* what pool to use for allocations needed by walk logic */
Packit 90a5c9
    apr_pool_t *pool;
Packit 90a5c9
Packit 90a5c9
    /* beginning root of the walk */
Packit 90a5c9
    const dav_resource *root;
Packit 90a5c9
Packit 90a5c9
    /* lock database to enable walking LOCKNULL resources */
Packit 90a5c9
    dav_lockdb *lockdb;
Packit 90a5c9
Packit 90a5c9
} dav_walk_params;
Packit 90a5c9
Packit 90a5c9
/* directory tree walking context */
Packit 90a5c9
typedef struct dav_walker_ctx
Packit 90a5c9
{
Packit 90a5c9
    /* input: */
Packit 90a5c9
    dav_walk_params w;
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
    /* ### client data... phasing out this big glom */
Packit 90a5c9
Packit 90a5c9
    /* this brigade buffers data being sent to r->output_filters */
Packit 90a5c9
    apr_bucket_brigade *bb;
Packit 90a5c9
Packit 90a5c9
    /* a scratch pool, used to stream responses and iteratively cleared. */
Packit 90a5c9
    apr_pool_t *scratchpool;
Packit 90a5c9
Packit 90a5c9
    request_rec *r;                 /* original request */
Packit 90a5c9
Packit 90a5c9
    /* for PROPFIND operations */
Packit 90a5c9
    apr_xml_doc *doc;
Packit 90a5c9
    int propfind_type;
Packit 90a5c9
#define DAV_PROPFIND_IS_ALLPROP     1
Packit 90a5c9
#define DAV_PROPFIND_IS_PROPNAME    2
Packit 90a5c9
#define DAV_PROPFIND_IS_PROP        3
Packit 90a5c9
Packit 90a5c9
    apr_text *propstat_404;         /* (cached) propstat giving a 404 error */
Packit 90a5c9
Packit 90a5c9
    const dav_if_header *if_header; /* for validation */
Packit 90a5c9
    const dav_locktoken *locktoken; /* for UNLOCK */
Packit 90a5c9
    const dav_lock *lock;           /* for LOCK */
Packit 90a5c9
    int skip_root;                  /* for dav_inherit_locks() */
Packit 90a5c9
Packit 90a5c9
    int flags;
Packit 90a5c9
Packit 90a5c9
    dav_buffer work_buf;            /* for dav_validate_request() */
Packit 90a5c9
Packit 90a5c9
} dav_walker_ctx;
Packit 90a5c9
Packit 90a5c9
DAV_DECLARE(void) dav_add_response(dav_walk_resource *wres,
Packit 90a5c9
                                   int status,
Packit 90a5c9
                                   dav_get_props_result *propstats);
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/* --------------------------------------------------------------------
Packit 90a5c9
**
Packit 90a5c9
** "STREAM" STRUCTURE
Packit 90a5c9
**
Packit 90a5c9
** mod_dav uses this abstraction for interacting with the repository
Packit 90a5c9
** while fetching/storing resources. mod_dav views resources as a stream
Packit 90a5c9
** of bytes.
Packit 90a5c9
**
Packit 90a5c9
** Note that the structure is opaque -- it is private to the repository
Packit 90a5c9
** that created the stream in the repository's "open" function.
Packit 90a5c9
**
Packit 90a5c9
** ### THIS STUFF IS GOING AWAY ... GET/read requests are handled by
Packit 90a5c9
** ### having the provider jam stuff straight into the filter stack.
Packit 90a5c9
** ### this is only left for handling PUT/write requests.
Packit 90a5c9
*/
Packit 90a5c9
Packit 90a5c9
typedef struct dav_stream dav_stream;
Packit 90a5c9
Packit 90a5c9
typedef enum {
Packit 90a5c9
    DAV_MODE_WRITE_TRUNC,      /* truncate and open for writing */
Packit 90a5c9
    DAV_MODE_WRITE_SEEKABLE    /* open for writing; random access */
Packit 90a5c9
} dav_stream_mode;
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/* --------------------------------------------------------------------
Packit 90a5c9
**
Packit 90a5c9
** REPOSITORY FUNCTIONS
Packit 90a5c9
*/
Packit 90a5c9
Packit 90a5c9
/* Repository provider hooks */
Packit 90a5c9
struct dav_hooks_repository
Packit 90a5c9
{
Packit 90a5c9
    /* Flag for whether repository requires special GET handling.
Packit 90a5c9
     * If resources in the repository are not visible in the
Packit 90a5c9
     * filesystem location which URLs map to, then special handling
Packit 90a5c9
     * is required to first fetch a resource from the repository,
Packit 90a5c9
     * respond to the GET request, then free the resource copy.
Packit 90a5c9
     */
Packit 90a5c9
    int handle_get;
Packit 90a5c9
Packit 90a5c9
    /* Get a resource descriptor for the URI in a request. A descriptor
Packit 90a5c9
     * should always be returned even if the resource does not exist. This
Packit 90a5c9
     * repository has been identified as handling the resource given by
Packit 90a5c9
     * the URI, so an answer must be given. If there is a problem with the
Packit 90a5c9
     * URI or accessing the resource or whatever, then an error should be
Packit 90a5c9
     * returned.
Packit 90a5c9
     *
Packit 90a5c9
     * root_dir:
Packit 90a5c9
     *   the root of the directory for which this repository is configured.
Packit 90a5c9
     *
Packit 90a5c9
     * label:
Packit 90a5c9
     *   if a Label: header is present (and allowed), this is the label
Packit 90a5c9
     *   to use to identify a version resource from the resource's
Packit 90a5c9
     *   corresponding version history. Otherwise, it will be NULL.
Packit 90a5c9
     *
Packit 90a5c9
     * use_checked_in:
Packit 90a5c9
     *   use the DAV:checked-in property of the resource identified by the
Packit 90a5c9
     *   Request-URI to identify and return a version resource
Packit 90a5c9
     *
Packit 90a5c9
     * The provider may associate the request storage pool with the resource
Packit 90a5c9
     * (in the resource->pool field), to use in other operations on that
Packit 90a5c9
     * resource.
Packit 90a5c9
     */
Packit 90a5c9
    dav_error * (*get_resource)(
Packit 90a5c9
        request_rec *r,
Packit 90a5c9
        const char *root_dir,
Packit 90a5c9
        const char *label,
Packit 90a5c9
        int use_checked_in,
Packit 90a5c9
        dav_resource **resource
Packit 90a5c9
    );
Packit 90a5c9
Packit 90a5c9
    /* Get a resource descriptor for the parent of the given resource.
Packit 90a5c9
     * The resources need not exist.  NULL is returned if the resource
Packit 90a5c9
     * is the root collection.
Packit 90a5c9
     *
Packit 90a5c9
     * An error should be returned only if there is a fatal error in
Packit 90a5c9
     * fetching information about the parent resource.
Packit 90a5c9
     */
Packit 90a5c9
    dav_error * (*get_parent_resource)(
Packit 90a5c9
        const dav_resource *resource,
Packit 90a5c9
        dav_resource **parent_resource
Packit 90a5c9
    );
Packit 90a5c9
Packit 90a5c9
    /* Determine whether two resource descriptors refer to the same resource.
Packit 90a5c9
    *
Packit 90a5c9
     * Result != 0 => the resources are the same.
Packit 90a5c9
     */
Packit 90a5c9
    int (*is_same_resource)(
Packit 90a5c9
        const dav_resource *res1,
Packit 90a5c9
        const dav_resource *res2
Packit 90a5c9
    );
Packit 90a5c9
Packit 90a5c9
    /* Determine whether one resource is a parent (immediate or otherwise)
Packit 90a5c9
     * of another.
Packit 90a5c9
     *
Packit 90a5c9
     * Result != 0 => res1 is a parent of res2.
Packit 90a5c9
     */
Packit 90a5c9
    int (*is_parent_resource)(
Packit 90a5c9
        const dav_resource *res1,
Packit 90a5c9
        const dav_resource *res2
Packit 90a5c9
    );
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Open a stream for this resource, using the specified mode. The
Packit 90a5c9
    ** stream will be returned in *stream.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*open_stream)(const dav_resource *resource,
Packit 90a5c9
                               dav_stream_mode mode,
Packit 90a5c9
                               dav_stream **stream);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Close the specified stream.
Packit 90a5c9
    **
Packit 90a5c9
    ** mod_dav will (ideally) make sure to call this. For safety purposes,
Packit 90a5c9
    ** a provider should (ideally) register a cleanup function with the
Packit 90a5c9
    ** request pool to get this closed and cleaned up.
Packit 90a5c9
    **
Packit 90a5c9
    ** Note the possibility of an error from the close -- it is entirely
Packit 90a5c9
    ** feasible that the close does a "commit" of some kind, which can
Packit 90a5c9
    ** produce an error.
Packit 90a5c9
    **
Packit 90a5c9
    ** commit should be TRUE (non-zero) or FALSE (0) if the stream was
Packit 90a5c9
    ** opened for writing. This flag states whether to retain the file
Packit 90a5c9
    ** or not.
Packit 90a5c9
    ** Note: the commit flag is ignored for streams opened for reading.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*close_stream)(dav_stream *stream, int commit);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Write data to the stream.
Packit 90a5c9
    **
Packit 90a5c9
    ** All of the bytes must be written, or an error should be returned.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*write_stream)(dav_stream *stream,
Packit 90a5c9
                                const void *buf, apr_size_t bufsize);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Seek to an absolute position in the stream. This is used to support
Packit 90a5c9
    ** Content-Range in a GET/PUT.
Packit 90a5c9
    **
Packit 90a5c9
    ** NOTE: if this function is NULL (which is allowed), then any
Packit 90a5c9
    **       operations using Content-Range will be refused.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*seek_stream)(dav_stream *stream, apr_off_t abs_position);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** If a GET is processed using a stream (open_stream, read_stream)
Packit 90a5c9
    ** rather than via a sub-request (on get_pathname), then this function
Packit 90a5c9
    ** is used to provide the repository with a way to set the headers
Packit 90a5c9
    ** in the response.
Packit 90a5c9
    **
Packit 90a5c9
    ** This function may be called without a following deliver(), to
Packit 90a5c9
    ** handle a HEAD request.
Packit 90a5c9
    **
Packit 90a5c9
    ** This may be NULL if handle_get is FALSE.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*set_headers)(request_rec *r,
Packit 90a5c9
                               const dav_resource *resource);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** The provider should deliver the resource into the specified filter.
Packit 90a5c9
    ** Basically, this is the response to the GET method.
Packit 90a5c9
    **
Packit 90a5c9
    ** Note that this is called for all resources, including collections.
Packit 90a5c9
    ** The provider should determine what has content to deliver or not.
Packit 90a5c9
    **
Packit 90a5c9
    ** set_headers will be called prior to this function, allowing the
Packit 90a5c9
    ** provider to set the appropriate response headers.
Packit 90a5c9
    **
Packit 90a5c9
    ** This may be NULL if handle_get is FALSE.
Packit 90a5c9
    ** ### maybe toss handle_get and just use this function as the marker
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*deliver)(const dav_resource *resource,
Packit 90a5c9
                           ap_filter_t *output);
Packit 90a5c9
Packit 90a5c9
    /* Create a collection resource. The resource must not already exist.
Packit 90a5c9
     *
Packit 90a5c9
     * Result == NULL if the collection was created successfully. Also, the
Packit 90a5c9
     * resource object is updated to reflect that the resource exists, and
Packit 90a5c9
     * is a collection.
Packit 90a5c9
     */
Packit 90a5c9
    dav_error * (*create_collection)(
Packit 90a5c9
        dav_resource *resource
Packit 90a5c9
    );
Packit 90a5c9
Packit 90a5c9
    /* Copy one resource to another. The destination may exist, if it is
Packit 90a5c9
     * versioned.
Packit 90a5c9
     * Handles both files and collections. Properties are copied as well.
Packit 90a5c9
     * If the destination exists and is versioned, the provider must update
Packit 90a5c9
     * the destination to have identical content to the source,
Packit 90a5c9
     * recursively for collections.
Packit 90a5c9
     * The depth argument is ignored for a file, and can be either 0 or
Packit 90a5c9
     * DAV_INFINITY for a collection.
Packit 90a5c9
     * If an error occurs in a child resource, then the return value is
Packit 90a5c9
     * non-NULL, and *response is set to a multistatus response.
Packit 90a5c9
     * If the copy is successful, the dst resource object is
Packit 90a5c9
     * updated to reflect that the resource exists.
Packit 90a5c9
     */
Packit 90a5c9
    dav_error * (*copy_resource)(
Packit 90a5c9
        const dav_resource *src,
Packit 90a5c9
        dav_resource *dst,
Packit 90a5c9
        int depth,
Packit 90a5c9
        dav_response **response
Packit 90a5c9
    );
Packit 90a5c9
Packit 90a5c9
    /* Move one resource to another. The destination must not exist.
Packit 90a5c9
     * Handles both files and collections. Properties are moved as well.
Packit 90a5c9
     * If an error occurs in a child resource, then the return value is
Packit 90a5c9
     * non-NULL, and *response is set to a multistatus response.
Packit 90a5c9
     * If the move is successful, the src and dst resource objects are
Packit 90a5c9
     * updated to reflect that the source no longer exists, and the
Packit 90a5c9
     * destination does.
Packit 90a5c9
     */
Packit 90a5c9
    dav_error * (*move_resource)(
Packit 90a5c9
        dav_resource *src,
Packit 90a5c9
        dav_resource *dst,
Packit 90a5c9
        dav_response **response
Packit 90a5c9
    );
Packit 90a5c9
Packit 90a5c9
    /* Remove a resource. Handles both files and collections.
Packit 90a5c9
     * Removes any associated properties as well.
Packit 90a5c9
     * If an error occurs in a child resource, then the return value is
Packit 90a5c9
     * non-NULL, and *response is set to a multistatus response.
Packit 90a5c9
     * If the delete is successful, the resource object is updated to
Packit 90a5c9
     * reflect that the resource no longer exists.
Packit 90a5c9
     */
Packit 90a5c9
    dav_error * (*remove_resource)(
Packit 90a5c9
        dav_resource *resource,
Packit 90a5c9
        dav_response **response
Packit 90a5c9
    );
Packit 90a5c9
Packit 90a5c9
    /* Walk a resource hierarchy.
Packit 90a5c9
     *
Packit 90a5c9
     * Iterates over the resource hierarchy specified by params->root.
Packit 90a5c9
     * Control of the walk and the callback are specified by 'params'.
Packit 90a5c9
     *
Packit 90a5c9
     * An error may be returned. *response will contain multistatus
Packit 90a5c9
     * responses (if any) suitable for the body of the error. It is also
Packit 90a5c9
     * possible to return NULL, yet still have multistatus responses.
Packit 90a5c9
     * In this case, typically the caller should return a 207 (Multistatus)
Packit 90a5c9
     * and the responses (in the body) as the HTTP response.
Packit 90a5c9
     */
Packit 90a5c9
    dav_error * (*walk)(const dav_walk_params *params, int depth,
Packit 90a5c9
                        dav_response **response);
Packit 90a5c9
Packit 90a5c9
    /* Get the entity tag for a resource */
Packit 90a5c9
    const char * (*getetag)(const dav_resource *resource);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** If a provider needs a context to associate with this hooks structure,
Packit 90a5c9
    ** then this field may be used. In most cases, it will just be NULL.
Packit 90a5c9
    */
Packit 90a5c9
    void *ctx;
Packit 90a5c9
Packit 90a5c9
    /* Get the request rec for a resource */
Packit 90a5c9
    request_rec * (*get_request_rec)(const dav_resource *resource);
Packit 90a5c9
Packit 90a5c9
    /* Get the pathname for a resource */
Packit 90a5c9
    const char * (*get_pathname)(const dav_resource *resource);
Packit 90a5c9
};
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/* --------------------------------------------------------------------
Packit 90a5c9
**
Packit 90a5c9
** VERSIONING FUNCTIONS
Packit 90a5c9
*/
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/* dav_add_vary_header
Packit 90a5c9
 *
Packit 90a5c9
 * If there were any headers in the request which require a Vary header
Packit 90a5c9
 * in the response, add it.
Packit 90a5c9
 */
Packit 90a5c9
DAV_DECLARE(void) dav_add_vary_header(request_rec *in_req,
Packit 90a5c9
                                      request_rec *out_req,
Packit 90a5c9
                                      const dav_resource *resource);
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** Flags specifying auto-versioning behavior, returned by
Packit 90a5c9
** the auto_versionable hook. The value returned depends
Packit 90a5c9
** on both the state of the resource and the value of the
Packit 90a5c9
** DAV:auto-versioning property for the resource.
Packit 90a5c9
**
Packit 90a5c9
** If the resource does not exist (null or lock-null),
Packit 90a5c9
** DAV_AUTO_VERSION_ALWAYS causes creation of a new version-controlled resource
Packit 90a5c9
**
Packit 90a5c9
** If the resource is checked in,
Packit 90a5c9
** DAV_AUTO_VERSION_ALWAYS causes it to be checked out always,
Packit 90a5c9
** DAV_AUTO_VERSION_LOCKED causes it to be checked out only when locked
Packit 90a5c9
**
Packit 90a5c9
** If the resource is checked out,
Packit 90a5c9
** DAV_AUTO_VERSION_ALWAYS causes it to be checked in always,
Packit 90a5c9
** DAV_AUTO_VERSION_LOCKED causes it to be checked in when unlocked
Packit 90a5c9
** (note: a provider should allow auto-checkin only for resources which
Packit 90a5c9
** were automatically checked out)
Packit 90a5c9
**
Packit 90a5c9
** In all cases, DAV_AUTO_VERSION_NEVER results in no auto-versioning behavior.
Packit 90a5c9
*/
Packit 90a5c9
typedef enum {
Packit 90a5c9
    DAV_AUTO_VERSION_NEVER,
Packit 90a5c9
    DAV_AUTO_VERSION_ALWAYS,
Packit 90a5c9
    DAV_AUTO_VERSION_LOCKED
Packit 90a5c9
} dav_auto_version;
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** This structure is used to record what auto-versioning operations
Packit 90a5c9
** were done to make a resource writable, so that they can be undone
Packit 90a5c9
** at the end of a request.
Packit 90a5c9
*/
Packit 90a5c9
typedef struct {
Packit 90a5c9
    int resource_versioned;             /* 1 => resource was auto-version-controlled */
Packit 90a5c9
    int resource_checkedout;            /* 1 => resource was auto-checked-out */
Packit 90a5c9
    int parent_checkedout;              /* 1 => parent was auto-checked-out */
Packit 90a5c9
    dav_resource *parent_resource;      /* parent resource, if it was needed */
Packit 90a5c9
} dav_auto_version_info;
Packit 90a5c9
Packit 90a5c9
/* Ensure that a resource is writable. If there is no versioning
Packit 90a5c9
 * provider, then this is essentially a no-op. Versioning repositories
Packit 90a5c9
 * require explicit resource creation and checkout before they can
Packit 90a5c9
 * be written to. If a new resource is to be created, or an existing
Packit 90a5c9
 * resource deleted, the parent collection must be checked out as well.
Packit 90a5c9
 *
Packit 90a5c9
 * Set the parent_only flag to only make the parent collection writable.
Packit 90a5c9
 * Otherwise, both parent and child are made writable as needed. If the
Packit 90a5c9
 * child does not exist, then a new versioned resource is created and
Packit 90a5c9
 * checked out.
Packit 90a5c9
 *
Packit 90a5c9
 * If auto-versioning is not enabled for a versioned resource, then an error is
Packit 90a5c9
 * returned, since the resource cannot be modified.
Packit 90a5c9
 *
Packit 90a5c9
 * The dav_auto_version_info structure is filled in with enough information
Packit 90a5c9
 * to restore both parent and child resources to the state they were in
Packit 90a5c9
 * before the auto-versioning operations occurred.
Packit 90a5c9
 */
Packit 90a5c9
DAV_DECLARE(dav_error *) dav_auto_checkout(
Packit 90a5c9
    request_rec *r,
Packit 90a5c9
    dav_resource *resource,
Packit 90a5c9
    int parent_only,
Packit 90a5c9
    dav_auto_version_info *av_info);
Packit 90a5c9
Packit 90a5c9
/* Revert the writability of resources back to what they were
Packit 90a5c9
 * before they were modified. If undo == 0, then the resource
Packit 90a5c9
 * modifications are maintained (i.e. they are checked in).
Packit 90a5c9
 * If undo != 0, then resource modifications are discarded
Packit 90a5c9
 * (i.e. they are unchecked out).
Packit 90a5c9
 *
Packit 90a5c9
 * Set the unlock flag to indicate that the resource is about
Packit 90a5c9
 * to be unlocked; it will be checked in if the resource
Packit 90a5c9
 * auto-versioning property indicates it should be. In this case,
Packit 90a5c9
 * av_info is ignored, so it can be NULL.
Packit 90a5c9
 *
Packit 90a5c9
 * The resource argument may be NULL if only the parent resource
Packit 90a5c9
 * was checked out (i.e. the parent_only was != 0 in the
Packit 90a5c9
 * dav_auto_checkout call).
Packit 90a5c9
 */
Packit 90a5c9
DAV_DECLARE(dav_error *) dav_auto_checkin(
Packit 90a5c9
    request_rec *r,
Packit 90a5c9
    dav_resource *resource,
Packit 90a5c9
    int undo,
Packit 90a5c9
    int unlock,
Packit 90a5c9
    dav_auto_version_info *av_info);
Packit 90a5c9
Packit 90a5c9
/*
Packit 90a5c9
** This structure is used to describe available reports
Packit 90a5c9
**
Packit 90a5c9
** "nmspace" should be valid XML and URL-quoted. mod_dav will place
Packit 90a5c9
** double-quotes around it and use it in an xmlns declaration.
Packit 90a5c9
*/
Packit 90a5c9
typedef struct {
Packit 90a5c9
    const char *nmspace;        /* namespace of the XML report element */
Packit 90a5c9
    const char *name;           /* element name for the XML report */
Packit 90a5c9
} dav_report_elem;
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/* Versioning provider hooks */
Packit 90a5c9
struct dav_hooks_vsn
Packit 90a5c9
{
Packit 90a5c9
    /*
Packit 90a5c9
    ** MANDATORY HOOKS
Packit 90a5c9
    ** The following hooks are mandatory for all versioning providers;
Packit 90a5c9
    ** they define the functionality needed to implement "core" versioning.
Packit 90a5c9
    */
Packit 90a5c9
Packit 90a5c9
    /* Return supported versioning options.
Packit 90a5c9
     * Each dav_text item in the list will be returned as a separate
Packit 90a5c9
     * DAV header. Providers are advised to limit the length of an
Packit 90a5c9
     * individual text item to 63 characters, to conform to the limit
Packit 90a5c9
     * used by MS Web Folders.
Packit 90a5c9
     */
Packit 90a5c9
    void (*get_vsn_options)(apr_pool_t *p, apr_text_header *phdr);
Packit 90a5c9
Packit 90a5c9
    /* Get the value of a specific option for an OPTIONS request.
Packit 90a5c9
     * The option being requested is given by the parsed XML
Packit 90a5c9
     * element object "elem". The value of the option should be
Packit 90a5c9
     * appended to the "option" text object.
Packit 90a5c9
     */
Packit 90a5c9
    dav_error * (*get_option)(const dav_resource *resource,
Packit 90a5c9
                              const apr_xml_elem *elem,
Packit 90a5c9
                              apr_text_header *option);
Packit 90a5c9
Packit 90a5c9
    /* Determine whether a non-versioned (or non-existent) resource
Packit 90a5c9
     * is versionable. Returns != 0 if resource can be versioned.
Packit 90a5c9
     */
Packit 90a5c9
    int (*versionable)(const dav_resource *resource);
Packit 90a5c9
Packit 90a5c9
    /* Determine whether auto-versioning is enabled for a resource
Packit 90a5c9
     * (which may not exist, or may not be versioned). If the resource
Packit 90a5c9
     * is a checked-out resource, the provider must only enable
Packit 90a5c9
     * auto-checkin if the resource was automatically checked out.
Packit 90a5c9
     *
Packit 90a5c9
     * The value returned depends on both the state of the resource
Packit 90a5c9
     * and the value of its DAV:auto-version property. See the description
Packit 90a5c9
     * of the dav_auto_version enumeration above for the details.
Packit 90a5c9
     */
Packit 90a5c9
    dav_auto_version (*auto_versionable)(const dav_resource *resource);
Packit 90a5c9
Packit 90a5c9
    /* Put a resource under version control. If the resource already
Packit 90a5c9
     * exists unversioned, then it becomes the initial version of the
Packit 90a5c9
     * new version history, and it is replaced by a version selector
Packit 90a5c9
     * which targets the new version.
Packit 90a5c9
     *
Packit 90a5c9
     * If the resource does not exist, then a new version-controlled
Packit 90a5c9
     * resource is created which either targets an existing version (if the
Packit 90a5c9
     * "target" argument is not NULL), or the initial, empty version
Packit 90a5c9
     * in a new history resource (if the "target" argument is NULL).
Packit 90a5c9
     *
Packit 90a5c9
     * If successful, the resource object state is updated appropriately
Packit 90a5c9
     * (that is, changed to refer to the new version-controlled resource).
Packit 90a5c9
     */
Packit 90a5c9
    dav_error * (*vsn_control)(dav_resource *resource,
Packit 90a5c9
                               const char *target);
Packit 90a5c9
Packit 90a5c9
    /* Checkout a resource. If successful, the resource
Packit 90a5c9
     * object state is updated appropriately.
Packit 90a5c9
     *
Packit 90a5c9
     * The auto_checkout flag will be set if this checkout is being
Packit 90a5c9
     * done automatically, as part of some method which modifies
Packit 90a5c9
     * the resource. The provider must remember that the resource
Packit 90a5c9
     * was automatically checked out, so it can determine whether it
Packit 90a5c9
     * can be automatically checked in. (Auto-checkin should only be
Packit 90a5c9
     * enabled for resources which were automatically checked out.)
Packit 90a5c9
     *
Packit 90a5c9
     * If the working resource has a different URL from the
Packit 90a5c9
     * target resource, a dav_resource descriptor is returned
Packit 90a5c9
     * for the new working resource. Otherwise, the original
Packit 90a5c9
     * resource descriptor will refer to the working resource.
Packit 90a5c9
     * The working_resource argument can be NULL if the caller
Packit 90a5c9
     * is not interested in the working resource.
Packit 90a5c9
     *
Packit 90a5c9
     * If the client has specified DAV:unreserved or DAV:fork-ok in the
Packit 90a5c9
     * checkout request, then the corresponding flags are set. If
Packit 90a5c9
     * DAV:activity-set has been specified, then create_activity is set
Packit 90a5c9
     * if DAV:new was specified; otherwise, the DAV:href elements' CDATA
Packit 90a5c9
     * (the actual href text) is passed in the "activities" array (each
Packit 90a5c9
     * element of the array is a const char *). activities will be NULL
Packit 90a5c9
     * no DAV:activity-set was provided or when create_activity is set.
Packit 90a5c9
     */
Packit 90a5c9
    dav_error * (*checkout)(dav_resource *resource,
Packit 90a5c9
                            int auto_checkout,
Packit 90a5c9
                            int is_unreserved, int is_fork_ok,
Packit 90a5c9
                            int create_activity,
Packit 90a5c9
                            apr_array_header_t *activities,
Packit 90a5c9
                            dav_resource **working_resource);
Packit 90a5c9
Packit 90a5c9
    /* Uncheckout a checked-out resource. If successful, the resource
Packit 90a5c9
     * object state is updated appropriately.
Packit 90a5c9
     */
Packit 90a5c9
    dav_error * (*uncheckout)(dav_resource *resource);
Packit 90a5c9
Packit 90a5c9
    /* Checkin a checked-out resource. If successful, the resource
Packit 90a5c9
     * object state is updated appropriately, and the
Packit 90a5c9
     * version_resource descriptor will refer to the new version.
Packit 90a5c9
     * The version_resource argument can be NULL if the caller
Packit 90a5c9
     * is not interested in the new version resource.
Packit 90a5c9
     *
Packit 90a5c9
     * If the client has specified DAV:keep-checked-out in the checkin
Packit 90a5c9
     * request, then the keep_checked_out flag is set. The provider
Packit 90a5c9
     * should create a new version, but keep the resource in the
Packit 90a5c9
     * checked-out state.
Packit 90a5c9
     */
Packit 90a5c9
    dav_error * (*checkin)(dav_resource *resource,
Packit 90a5c9
                           int keep_checked_out,
Packit 90a5c9
                           dav_resource **version_resource);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Return the set of reports available at this resource.
Packit 90a5c9
    **
Packit 90a5c9
    ** An array of report elements should be returned, with an end-marker
Packit 90a5c9
    ** element containing namespace==NULL. The value of the
Packit 90a5c9
    ** DAV:supported-report-set property will be constructed and
Packit 90a5c9
    ** returned.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*avail_reports)(const dav_resource *resource,
Packit 90a5c9
                                 const dav_report_elem **reports);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Determine whether a Label header can be used
Packit 90a5c9
    ** with a particular report. The dav_xml_doc structure
Packit 90a5c9
    ** contains the parsed report request body.
Packit 90a5c9
    ** Returns 0 if the Label header is not allowed.
Packit 90a5c9
    */
Packit 90a5c9
    int (*report_label_header_allowed)(const apr_xml_doc *doc);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Generate a report on a resource. Since a provider is free
Packit 90a5c9
    ** to define its own reports, and the value of request headers
Packit 90a5c9
    ** may affect the interpretation of a report, the request record
Packit 90a5c9
    ** must be passed to this routine.
Packit 90a5c9
    **
Packit 90a5c9
    ** The dav_xml_doc structure contains the parsed report request
Packit 90a5c9
    ** body. The report response should be generated into the specified
Packit 90a5c9
    ** output filter.
Packit 90a5c9
    **
Packit 90a5c9
    ** If an error occurs, and a response has not yet been generated,
Packit 90a5c9
    ** then an error can be returned from this function. mod_dav will
Packit 90a5c9
    ** construct an appropriate error response. Once some output has
Packit 90a5c9
    ** been placed into the filter, however, the provider should not
Packit 90a5c9
    ** return an error -- there is no way that mod_dav can deliver it
Packit 90a5c9
    ** properly.
Packit 90a5c9
    **
Packit 90a5c9
    ** ### maybe we need a way to signal an error anyways, and then
Packit 90a5c9
    ** ### apache can abort the connection?
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*deliver_report)(request_rec *r,
Packit 90a5c9
                                  const dav_resource *resource,
Packit 90a5c9
                                  const apr_xml_doc *doc,
Packit 90a5c9
                                  ap_filter_t *output);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** OPTIONAL HOOKS
Packit 90a5c9
    ** The following hooks are optional; if not defined, then the
Packit 90a5c9
    ** corresponding protocol methods will be unsupported.
Packit 90a5c9
    */
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Set the state of a checked-in version-controlled resource.
Packit 90a5c9
    **
Packit 90a5c9
    ** If the request specified a version, the version resource
Packit 90a5c9
    ** represents that version. If the request specified a label,
Packit 90a5c9
    ** then "version" is NULL, and "label" is the label.
Packit 90a5c9
    **
Packit 90a5c9
    ** The depth argument is ignored for a file, and can be 0, 1, or
Packit 90a5c9
    ** DAV_INFINITY for a collection. The depth argument only applies
Packit 90a5c9
    ** with a label, not a version.
Packit 90a5c9
    **
Packit 90a5c9
    ** If an error occurs in a child resource, then the return value is
Packit 90a5c9
    ** non-NULL, and *response is set to a multistatus response.
Packit 90a5c9
    **
Packit 90a5c9
    ** This hook is optional; if not defined, then the UPDATE method
Packit 90a5c9
    ** will not be supported.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*update)(const dav_resource *resource,
Packit 90a5c9
                          const dav_resource *version,
Packit 90a5c9
                          const char *label,
Packit 90a5c9
                          int depth,
Packit 90a5c9
                          dav_response **response);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Add a label to a version. The resource is either a specific
Packit 90a5c9
    ** version, or a version selector, in which case the label should
Packit 90a5c9
    ** be added to the current target of the version selector. The
Packit 90a5c9
    ** version selector cannot be checked out.
Packit 90a5c9
    **
Packit 90a5c9
    ** If replace != 0, any existing label by the same name is
Packit 90a5c9
    ** effectively deleted first. Otherwise, it is an error to
Packit 90a5c9
    ** attempt to add a label which already exists on some version
Packit 90a5c9
    ** of the same history resource.
Packit 90a5c9
    **
Packit 90a5c9
    ** This hook is optional; if not defined, then the LABEL method
Packit 90a5c9
    ** will not be supported. If it is defined, then the remove_label
Packit 90a5c9
    ** hook must be defined also.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*add_label)(const dav_resource *resource,
Packit 90a5c9
                             const char *label,
Packit 90a5c9
                             int replace);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Remove a label from a version. The resource is either a specific
Packit 90a5c9
    ** version, or a version selector, in which case the label should
Packit 90a5c9
    ** be added to the current target of the version selector. The
Packit 90a5c9
    ** version selector cannot be checked out.
Packit 90a5c9
    **
Packit 90a5c9
    ** It is an error if no such label exists on the specified version.
Packit 90a5c9
    **
Packit 90a5c9
    ** This hook is optional, but if defined, the add_label hook
Packit 90a5c9
    ** must be defined also.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*remove_label)(const dav_resource *resource,
Packit 90a5c9
                                const char *label);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Determine whether a null resource can be created as a workspace.
Packit 90a5c9
    ** The provider may restrict workspaces to certain locations.
Packit 90a5c9
    ** Returns 0 if the resource cannot be a workspace.
Packit 90a5c9
    **
Packit 90a5c9
    ** This hook is optional; if the provider does not support workspaces,
Packit 90a5c9
    ** it should be set to NULL.
Packit 90a5c9
    */
Packit 90a5c9
    int (*can_be_workspace)(const dav_resource *resource);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Create a workspace resource. The resource must not already
Packit 90a5c9
    ** exist. Any <DAV:mkworkspace> element is passed to the provider
Packit 90a5c9
    ** in the "doc" structure; it may be empty.
Packit 90a5c9
    **
Packit 90a5c9
    ** If workspace creation is successful, the state of the resource
Packit 90a5c9
    ** object is updated appropriately.
Packit 90a5c9
    **
Packit 90a5c9
    ** This hook is optional; if the provider does not support workspaces,
Packit 90a5c9
    ** it should be set to NULL.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*make_workspace)(dav_resource *resource,
Packit 90a5c9
                                  apr_xml_doc *doc);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Determine whether a null resource can be created as an activity.
Packit 90a5c9
    ** The provider may restrict activities to certain locations.
Packit 90a5c9
    ** Returns 0 if the resource cannot be an activity.
Packit 90a5c9
    **
Packit 90a5c9
    ** This hook is optional; if the provider does not support activities,
Packit 90a5c9
    ** it should be set to NULL.
Packit 90a5c9
    */
Packit 90a5c9
    int (*can_be_activity)(const dav_resource *resource);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Create an activity resource. The resource must not already
Packit 90a5c9
    ** exist.
Packit 90a5c9
    **
Packit 90a5c9
    ** If activity creation is successful, the state of the resource
Packit 90a5c9
    ** object is updated appropriately.
Packit 90a5c9
    **
Packit 90a5c9
    ** This hook is optional; if the provider does not support activities,
Packit 90a5c9
    ** it should be set to NULL.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*make_activity)(dav_resource *resource);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** Merge a resource (tree) into target resource (tree).
Packit 90a5c9
    **
Packit 90a5c9
    ** ### more doc...
Packit 90a5c9
    **
Packit 90a5c9
    ** This hook is optional; if the provider does not support merging,
Packit 90a5c9
    ** then this should be set to NULL.
Packit 90a5c9
    */
Packit 90a5c9
    dav_error * (*merge)(dav_resource *target, dav_resource *source,
Packit 90a5c9
                         int no_auto_merge, int no_checkout,
Packit 90a5c9
                         apr_xml_elem *prop_elem,
Packit 90a5c9
                         ap_filter_t *output);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** If a provider needs a context to associate with this hooks structure,
Packit 90a5c9
    ** then this field may be used. In most cases, it will just be NULL.
Packit 90a5c9
    */
Packit 90a5c9
    void *ctx;
Packit 90a5c9
};
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/* --------------------------------------------------------------------
Packit 90a5c9
**
Packit 90a5c9
** BINDING FUNCTIONS
Packit 90a5c9
*/
Packit 90a5c9
Packit 90a5c9
/* binding provider hooks */
Packit 90a5c9
struct dav_hooks_binding {
Packit 90a5c9
Packit 90a5c9
    /* Determine whether a resource can be the target of a binding.
Packit 90a5c9
     * Returns 0 if the resource cannot be a binding target.
Packit 90a5c9
     */
Packit 90a5c9
    int (*is_bindable)(const dav_resource *resource);
Packit 90a5c9
Packit 90a5c9
    /* Create a binding to a resource.
Packit 90a5c9
     * The resource argument is the target of the binding;
Packit 90a5c9
     * the binding argument must be a resource which does not already
Packit 90a5c9
     * exist.
Packit 90a5c9
     */
Packit 90a5c9
    dav_error * (*bind_resource)(const dav_resource *resource,
Packit 90a5c9
                                 dav_resource *binding);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** If a provider needs a context to associate with this hooks structure,
Packit 90a5c9
    ** then this field may be used. In most cases, it will just be NULL.
Packit 90a5c9
    */
Packit 90a5c9
    void *ctx;
Packit 90a5c9
Packit 90a5c9
};
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/* --------------------------------------------------------------------
Packit 90a5c9
**
Packit 90a5c9
** SEARCH(DASL) FUNCTIONS
Packit 90a5c9
*/
Packit 90a5c9
Packit 90a5c9
/* search provider hooks */
Packit 90a5c9
struct dav_hooks_search {
Packit 90a5c9
    /* Set header for a OPTION method
Packit 90a5c9
     * An error may be returned.
Packit 90a5c9
     * To set a hadder, this function might call
Packit 90a5c9
     * apr_table_setn(r->headers_out, "DASL", dasl_optin1);
Packit 90a5c9
     *
Packit 90a5c9
     * Examples:
Packit 90a5c9
     * DASL: <DAV:basicsearch>
Packit 90a5c9
     * DASL: <http://foo.bar.com/syntax1>
Packit 90a5c9
     * DASL: <http://akuma.com/syntax2>
Packit 90a5c9
     */
Packit 90a5c9
    dav_error * (*set_option_head)(request_rec *r);
Packit 90a5c9
Packit 90a5c9
    /* Search resources
Packit 90a5c9
     * An error may be returned. *response will contain multistatus
Packit 90a5c9
     * responses (if any) suitable for the body of the error. It is also
Packit 90a5c9
     * possible to return NULL, yet still have multistatus responses.
Packit 90a5c9
     * In this case, typically the caller should return a 207 (Multistatus)
Packit 90a5c9
     * and the responses (in the body) as the HTTP response.
Packit 90a5c9
     */
Packit 90a5c9
    dav_error * (*search_resource)(request_rec *r,
Packit 90a5c9
                                   dav_response **response);
Packit 90a5c9
Packit 90a5c9
    /*
Packit 90a5c9
    ** If a provider needs a context to associate with this hooks structure,
Packit 90a5c9
    ** then this field may be used. In most cases, it will just be NULL.
Packit 90a5c9
    */
Packit 90a5c9
    void *ctx;
Packit 90a5c9
Packit 90a5c9
};
Packit 90a5c9
Packit 90a5c9
Packit 90a5c9
/* --------------------------------------------------------------------
Packit 90a5c9
**
Packit 90a5c9
** MISCELLANEOUS STUFF
Packit 90a5c9
*/
Packit 90a5c9
Packit 90a5c9
typedef struct {
Packit 90a5c9
    int propid;                          /* live property ID */
Packit 90a5c9
    const dav_hooks_liveprop *provider;  /* the provider defining this prop */
Packit 90a5c9
} dav_elem_private;
Packit 90a5c9
Packit 90a5c9
/* --------------------------------------------------------------------
Packit 90a5c9
**
Packit 90a5c9
** DAV OPTIONS
Packit 90a5c9
*/
Packit 90a5c9
#define DAV_OPTIONS_EXTENSION_GROUP "dav_options"
Packit 90a5c9
Packit 90a5c9
typedef struct dav_options_provider
Packit 90a5c9
{
Packit 90a5c9
    dav_error* (*dav_header)(request_rec *r,
Packit 90a5c9
                             const dav_resource *resource,
Packit 90a5c9
                             apr_text_header *phdr);
Packit 90a5c9
Packit 90a5c9
    dav_error* (*dav_method)(request_rec *r,
Packit 90a5c9
                             const dav_resource *resource,
Packit 90a5c9
                             apr_text_header *phdr);
Packit 90a5c9
Packit 90a5c9
    void *ctx;
Packit 90a5c9
} dav_options_provider;
Packit 90a5c9
Packit 90a5c9
extern DAV_DECLARE(const dav_options_provider *) dav_get_options_providers(const char *name);
Packit 90a5c9
Packit 90a5c9
extern DAV_DECLARE(void) dav_options_provider_register(apr_pool_t *p,
Packit 90a5c9
                               const char *name,
Packit 90a5c9
                               const dav_options_provider *provider);
Packit 90a5c9
Packit 90a5c9
/* --------------------------------------------------------------------
Packit 90a5c9
**
Packit 90a5c9
** DAV RESOURCE TYPE HOOKS
Packit 90a5c9
*/
Packit 90a5c9
Packit 90a5c9
typedef struct dav_resource_type_provider
Packit 90a5c9
{
Packit 90a5c9
    int (*get_resource_type)(const dav_resource *resource,
Packit 90a5c9
                  const char **name,
Packit 90a5c9
                  const char **uri);
Packit 90a5c9
} dav_resource_type_provider;
Packit 90a5c9
Packit 90a5c9
#define DAV_RESOURCE_TYPE_GROUP "dav_resource_type"
Packit 90a5c9
Packit 90a5c9
DAV_DECLARE(void) dav_resource_type_provider_register(apr_pool_t *p,
Packit 90a5c9
                                        const char *name,
Packit 90a5c9
                                    const dav_resource_type_provider *provider);
Packit 90a5c9
Packit 90a5c9
DAV_DECLARE(const dav_resource_type_provider *) dav_get_resource_type_providers(const char *name);
Packit 90a5c9
Packit 90a5c9
#ifdef __cplusplus
Packit 90a5c9
}
Packit 90a5c9
#endif
Packit 90a5c9
Packit 90a5c9
#endif /* _MOD_DAV_H_ */
Packit 90a5c9
/** @} */
Packit 90a5c9