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