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