Annotation of libwww/Library/src/HTDAV.c, revision 1.1
1.1 ! kirschpi 1: /*
! 2: ** WebDAV MANAGER
! 3: **
! 4: ** (c) COPYRIGHT MIT 1995.
! 5: ** Please first read the full copyright statement in the file COPYRIGH.
! 6: ** @(#) $Id$
! 7: **
! 8: ** Authors
! 9: ** MKP Manuele Kirsch Pinheiro, Manuele.Kirsch_Pinheiro@inrialpes.fr
! 10: ** manuele@inf.ufrgs.br
! 11: **
! 12: ** History
! 13: ** 15 Fev 02 Writen
! 14: ** 15 Mar 02 Changed - All methods will use entity callback and not the
! 15: ** message body functions. This modification was demanded by
! 16: ** Jose Kahan.
! 17: **
! 18: ** $Log$
! 19: **
! 20: ** $Id$
! 21: */
! 22:
! 23: /* Library include files */
! 24: #include "WWWLib.h"
! 25: #include "WWWInit.h"
! 26: #include "wwwsys.h"
! 27: #include "WWWUtil.h"
! 28: #include "WWWStream.h"
! 29: #include "HTDAV.h" /* implemented here */
! 30:
! 31: #ifdef HT_DAV
! 32:
! 33: struct _HTStream {
! 34: const HTStreamClass * isa;
! 35: HTStream * target;
! 36: HTRequest * request;
! 37: int version;
! 38: BOOL endHeader;
! 39: BOOL transparent;
! 40: };
! 41:
! 42:
! 43: /* --------------------------------------------------------------------------*/
! 44: /* WebDAV REQUEST HEADERS */
! 45: /* --------------------------------------------------------------------------*/
! 46:
! 47: /* Headers defined in WebDAV - RC2518
! 48: ** If: state list _ may be a tagged or a non-tag list of state tokens and Etags
! 49: ** Depth: how depth the method should be executed. Values are: 0,1,infinity
! 50: ** Destination: destination URI for COPY and MOVE methods
! 51: ** Overwrite: should the method overwrite any existant resource? Values: T or F
! 52: ** LockToken: lock identification (used only in UNLOCK method)
! 53: ** Timeout: lock timeout. Values: Second-nnn,Infinite or Extend file (RFC2068)
! 54: */
! 55: struct _HTDAVHeaders {
! 56: char * If;
! 57: char * Depth;
! 58: char * Destination;
! 59: char * LockToken;
! 60: char * Timeout;
! 61: char Overwrite;
! 62: };
! 63:
! 64:
! 65: /*
! 66: ** Creates a new HTDAVHeaders struct
! 67: */
! 68: PUBLIC HTDAVHeaders * HTDAVHeaders_new (void) {
! 69: HTDAVHeaders *me;
! 70:
! 71: if ( (me = (HTDAVHeaders *) HT_CALLOC (1,sizeof(HTDAVHeaders))) == NULL)
! 72: HT_OUTOFMEM ("HTDAVHeaders_new");
! 73:
! 74: /* set everything to an empty value */
! 75: me->If = NULL;
! 76: me->Depth = NULL;
! 77: me->Destination = NULL;
! 78: me->LockToken = NULL;
! 79: me->Timeout = NULL;
! 80: me->Overwrite = ' ';
! 81:
! 82: HTTRACE (PROT_TRACE,"HTDAV.... HTDAVHeaders object created\n");
! 83:
! 84: return me;
! 85: }
! 86:
! 87:
! 88: /*
! 89: ** Deletes a HTDAVHeaders object
! 90: */
! 91: PUBLIC BOOL HTDAVHeaders_delete (HTDAVHeaders *me) {
! 92: if (me) {
! 93: if (me->If) HT_FREE (me->If);
! 94: if (me->Depth) HT_FREE (me->Depth);
! 95: if (me->Destination) HT_FREE (me->Destination);
! 96: if (me->LockToken) HT_FREE (me->LockToken);
! 97: if (me->Timeout) HT_FREE (me->Timeout);
! 98: HT_FREE (me);
! 99:
! 100: HTTRACE (PROT_TRACE,"HTDAV.... HTDAVHeaders object removed\n");
! 101:
! 102: return YES;
! 103: }
! 104: return NO;
! 105: }
! 106:
! 107:
! 108: /*
! 109: ** Set the If header - see section 9.4 of RFC2518
! 110: */
! 111: PUBLIC BOOL HTDAV_setIfHeader (HTDAVHeaders *me, const char *If) {
! 112: if (me && If && *If) {
! 113: HTTRACE (PROT_TRACE,"HTDAV.... If Header set\n");
! 114: StrAllocCopy (me->If,If);
! 115: return YES;
! 116: }
! 117: return NO;
! 118: }
! 119:
! 120: /*
! 121: ** Removes the "If" header.
! 122: */
! 123: PUBLIC BOOL HTDAV_deleteIfHeader (HTDAVHeaders * me) {
! 124: if (me && me->If) {
! 125: HT_FREE(me->If);
! 126: me->If = NULL;
! 127: return YES;
! 128: }
! 129: return NO;
! 130: }
! 131:
! 132: /*
! 133: ** Return the "If" header, NULL if this header is not set.
! 134: ** The caller should FREE the returned string
! 135: */
! 136: PUBLIC char * HTDAV_ifHeader (HTDAVHeaders *me) {
! 137: char *copy = NULL;
! 138: if (me && me->If) {
! 139: StrAllocCopy (copy,me->If);
! 140: }
! 141: return copy;
! 142: }
! 143:
! 144:
! 145: /*
! 146: ** Set the Depth header - see section 9.2 of RFC2518
! 147: */
! 148: PUBLIC BOOL HTDAV_setDepthHeader (HTDAVHeaders *me, const char *Depth) {
! 149: if (me && Depth && *Depth) {
! 150: HTTRACE (PROT_TRACE,"HTDAV.... Depth Header set\n");
! 151: StrAllocCopy (me->Depth,Depth);
! 152: return YES;
! 153: }
! 154: return NO;
! 155: }
! 156:
! 157:
! 158: /*
! 159: ** Removes the "Depth" header.
! 160: */
! 161: PUBLIC BOOL HTDAV_deleteDepthHeader (HTDAVHeaders * me) {
! 162: if (me && me->Depth) {
! 163: HT_FREE(me->Depth);
! 164: me->Depth = NULL;
! 165: return YES;
! 166: }
! 167: return NO;
! 168: }
! 169:
! 170:
! 171: /*
! 172: ** Return the "Depth" header, NULL if this header is not set.
! 173: ** The caller should FREE the returned string
! 174: */
! 175: PUBLIC char * HTDAV_DepthHeader (HTDAVHeaders *me) {
! 176: char *copy = NULL;
! 177: if (me && me->Depth) {
! 178: StrAllocCopy (copy,me->Depth);
! 179: }
! 180: return copy;
! 181: }
! 182:
! 183:
! 184: /*
! 185: ** Set the LockToken header - see section 9.5 of RFC2518
! 186: */
! 187: PUBLIC BOOL HTDAV_setLockTokenHeader (HTDAVHeaders *me, const char *LockToken) {
! 188: if (me && LockToken && *LockToken) {
! 189: HTTRACE (PROT_TRACE,"HTDAV.... Lock-Token Header set\n");
! 190: StrAllocCopy (me->LockToken,LockToken);
! 191: return YES;
! 192: }
! 193: return NO;
! 194: }
! 195:
! 196:
! 197: /*
! 198: ** Removes the "LockToken" header.
! 199: */
! 200: PUBLIC BOOL HTDAV_deleteLockTokenHeader (HTDAVHeaders * me) {
! 201: if (me && me->LockToken) {
! 202: HT_FREE(me->LockToken);
! 203: me->LockToken = NULL;
! 204: return YES;
! 205: }
! 206: return NO;
! 207: }
! 208:
! 209:
! 210: /*
! 211: ** Return the "LockToken" header, NULL if this header is not set.
! 212: ** The caller should FREE the returned string
! 213: */
! 214: PUBLIC char * HTDAV_LockTokenHeader (HTDAVHeaders *me) {
! 215: char *copy = NULL;
! 216: if (me && me->LockToken) {
! 217: StrAllocCopy (copy,me->LockToken);
! 218: }
! 219: return copy;
! 220: }
! 221:
! 222:
! 223: /*
! 224: ** Set the Destination header - see section 9.3 of RFC2518
! 225: */
! 226: PUBLIC BOOL HTDAV_setDestinationHeader (HTDAVHeaders *me, const char *Destination) {
! 227: if (me && Destination && *Destination) {
! 228: HTTRACE (PROT_TRACE,"HTDAV.... Destination Header set\n");
! 229: StrAllocCopy (me->Destination,Destination);
! 230: return YES;
! 231: }
! 232: return NO;
! 233: }
! 234:
! 235:
! 236: /*
! 237: ** Removes the "Destination" header.
! 238: */
! 239: PUBLIC BOOL HTDAV_deleteDestinationHeader (HTDAVHeaders * me) {
! 240: if (me && me->Destination) {
! 241: HT_FREE(me->Destination);
! 242: me->Destination = NULL;
! 243: return YES;
! 244: }
! 245: return NO;
! 246: }
! 247:
! 248:
! 249: /*
! 250: ** Return the "Destination" header, NULL if this header is not set.
! 251: ** The caller should FREE the returned string
! 252: */
! 253: PUBLIC char * HTDAV_DestinationHeader (HTDAVHeaders *me) {
! 254: char *copy = NULL;
! 255: if (me && me->Destination) {
! 256: StrAllocCopy (copy,me->Destination);
! 257: }
! 258: return copy;
! 259: }
! 260:
! 261:
! 262:
! 263: /*
! 264: ** Set the Timeout header - see section 9.8 of RFC2518
! 265: */
! 266: PUBLIC BOOL HTDAV_setTimeoutHeader (HTDAVHeaders *me, const char *Timeout) {
! 267: if (me && Timeout && *Timeout) {
! 268: HTTRACE (PROT_TRACE,"HTDAV.... Timeout Header set\n");
! 269: StrAllocCopy (me->Timeout,Timeout);
! 270: return YES;
! 271: }
! 272: return NO;
! 273: }
! 274:
! 275:
! 276: /*
! 277: ** Removes the "Timeout" header.
! 278: */
! 279: PUBLIC BOOL HTDAV_deleteTimeoutHeader (HTDAVHeaders * me) {
! 280: if (me && me->Timeout) {
! 281: HT_FREE(me->Timeout);
! 282: me->Timeout = NULL;
! 283: return YES;
! 284: }
! 285: return NO;
! 286: }
! 287:
! 288:
! 289: /*
! 290: ** Return the "Timeout" header, NULL if this header is not set.
! 291: ** The caller should FREE the returned string
! 292: */
! 293: PUBLIC char * HTDAV_TimeoutHeader (HTDAVHeaders *me) {
! 294: char *copy = NULL;
! 295: if (me && me->Timeout) {
! 296: StrAllocCopy (copy,me->Timeout);
! 297: }
! 298: return copy;
! 299: }
! 300:
! 301:
! 302: /*
! 303: ** Set the Overwrite header - see section 9.6 of RFC2518
! 304: */
! 305: PUBLIC BOOL HTDAV_setOverwriteHeader (HTDAVHeaders *me, BOOL Overwrite) {
! 306: if (me) {
! 307: HTTRACE (PROT_TRACE,"HTDAV.... Overwrite Header set\n");
! 308: me->Overwrite = (Overwrite)?'T':'F';
! 309: return YES;
! 310: }
! 311: return NO;
! 312: }
! 313:
! 314: /*
! 315: ** Removes the "Overwirte" header.
! 316: */
! 317: PUBLIC BOOL HTDAV_deleteOverwriteHeader (HTDAVHeaders * me) {
! 318: if (me) {
! 319: me->Overwrite = ' ';
! 320: return YES;
! 321: }
! 322: return NO;
! 323: }
! 324:
! 325:
! 326: /*
! 327: ** Returns the "Overwrite" header. If it is not set, returns the
! 328: ** default value (YES == TRUE)
! 329: */
! 330: PUBLIC BOOL HTDAV_OverwriteHeader (HTDAVHeaders * me) {
! 331: if (me) {
! 332: return (me->Overwrite==' ' || me->Overwrite=='T')?YES:NO;
! 333: }
! 334: return YES;
! 335: }
! 336:
! 337:
! 338:
! 339: /* --------------------------------------------------------------------------*/
! 340: /* ENTITY CALLBACK */
! 341: /* --------------------------------------------------------------------------*/
! 342:
! 343:
! 344: /*
! 345: ** Entity Callback - IDEM HTAccess.c
! 346: */
! 347: PRIVATE int HTEntity_callback (HTRequest * request, HTStream * target)
! 348: {
! 349: HTParentAnchor * entity = HTRequest_entityAnchor(request);
! 350: HTTRACE(APP_TRACE, "Posting Data from callback function\n");
! 351: if (!request || !entity || !target) return HT_ERROR;
! 352: {
! 353: BOOL chunking = NO;
! 354: int status;
! 355: char * document = (char *) HTAnchor_document(entity);
! 356: int len = HTAnchor_length(entity);
! 357: if (!document) {
! 358: HTTRACE(PROT_TRACE, "Posting Data No document\n");
! 359: return HT_ERROR;
! 360: }
! 361:
! 362: /*
! 363: ** If the length is unknown (-1) then see if the document is a text
! 364: ** type and in that case take the strlen. If not then we don't know
! 365: ** how much data we can write and must stop
! 366: */
! 367: if (len < 0) {
! 368: HTFormat actual = HTAnchor_format(entity);
! 369: HTFormat tmplate = HTAtom_for("text/*");
! 370: if (HTMIMEMatch(tmplate, actual)) {
! 371: len = strlen(document); /* Naive! */
! 372: chunking = YES;
! 373: } else {
! 374: HTTRACE(PROT_TRACE, "Posting Data Must know the length of document %p\n" _
! 375: document);
! 376: return HT_ERROR;
! 377: }
! 378: }
! 379:
! 380: /* Send the data down the pipe */
! 381: status = (*target->isa->put_block)(target, document, len);
! 382: if (status == HT_WOULD_BLOCK) {
! 383: HTTRACE(PROT_TRACE, "Posting Data Target WOULD BLOCK\n");
! 384: return HT_WOULD_BLOCK;
! 385: } else if (status == HT_PAUSE) {
! 386: HTTRACE(PROT_TRACE, "Posting Data Target PAUSED\n");
! 387: return HT_PAUSE;
! 388: } else if (chunking && status == HT_OK) {
! 389: HTTRACE(PROT_TRACE, "Posting Data Target is SAVED using chunked\n");
! 390: return (*target->isa->put_block)(target, "", 0);
! 391: } else if (status == HT_LOADED || status == HT_OK) {
! 392: HTTRACE(PROT_TRACE, "Posting Data Target is SAVED\n");
! 393: (*target->isa->flush)(target);
! 394: return HT_LOADED;
! 395: } else if (status > 0) { /* Stream specific return code */
! 396: HTTRACE(PROT_TRACE, "Posting Data. Target returns %d\n" _ status);
! 397: return status;
! 398: } else { /* we have a real error */
! 399: HTTRACE(PROT_TRACE, "Posting Data Target ERROR %d\n" _ status);
! 400: return status;
! 401: }
! 402: }
! 403: }
! 404:
! 405:
! 406:
! 407: /* --------------------------------------------------------------------------*/
! 408: /* LOCK REQUESTS */
! 409: /* --------------------------------------------------------------------------*/
! 410:
! 411:
! 412: /*
! 413: ** LOCK REQUESTS
! 414: **
! 415: ** LOCK requests may create a lock specified by "lockinfo" XML element
! 416: ** on the Request URI. LOCK request should have a XML request entity body,
! 417: ** which contains "owner" XML element, or the request should be a lock
! 418: ** refresh request.
! 419: ** Headers:
! 420: ** If header is mandatory for lock refresh request
! 421: ** Depth header may be "0" or "infinity" (default: infinity)
! 422: ** Timeout header may be used
! 423: */
! 424:
! 425: PUBLIC BOOL HTLOCKDocumentAnchor (HTRequest * request,
! 426: HTAnchor * dst,
! 427: HTParentAnchor * xmlbody,
! 428: HTDAVHeaders * headers) {
! 429:
! 430: if (request && dst) {
! 431: /* set method and request-URI */
! 432: HTRequest_setMethod (request,METHOD_LOCK);
! 433: HTRequest_setAnchor (request,dst);
! 434: HTTRACE (PROT_TRACE,"HTDAV.... Method set to LOCK\n");
! 435:
! 436: /* set headers */
! 437: HTTRACE (PROT_TRACE,"HTDAV.... Seting default Headers \n");
! 438: HTRequest_addCacheControl (request,"no-cache","");
! 439: HTRequest_addEnHd (request,HT_E_CONTENT_ENCODING);
! 440: HTRequest_addEnHd (request,HT_E_CONTENT_LENGTH);
! 441: HTRequest_addGnHd (request,HT_G_PRAGMA_NO_CACHE);
! 442:
! 443: if (headers) { /* WebDAV specific headers */
! 444: HTTRACE (PROT_TRACE,"HTDAV.... Setting WebDAV headers \n");
! 445: if (headers->If)
! 446: HTRequest_addExtraHeader (request,"If",headers->If);
! 447:
! 448: if (headers->Depth) { /* Depth: 0 or infinity only */
! 449: if (!strcasecomp(headers->Depth,"0") ||
! 450: !strcasecomp(headers->Depth,"infinity"))
! 451: HTRequest_addExtraHeader (request,"Depth",headers->Depth);
! 452: }
! 453:
! 454: if (headers->Timeout)
! 455: HTRequest_addExtraHeader (request,"Timeout",headers->Timeout);
! 456: }
! 457:
! 458: /* set body - if there is no body, we expect that is a lock refresh */
! 459: if (xmlbody) {
! 460: HTTRACE (PROT_TRACE,"HTDAV.... Setting Entity Body \n");
! 461: HTRequest_setEntityAnchor (request,xmlbody);
! 462: HTRequest_setPostCallback(request, HTEntity_callback);
! 463: }
! 464:
! 465: return HTLoad (request,NO);
! 466: }
! 467: return NO;
! 468: }
! 469:
! 470:
! 471: /*
! 472: ** LOCK the URI indicated by HTAnchor *dst using the informations
! 473: ** in xmlbody string.
! 474: */
! 475: PUBLIC BOOL HTLOCKAnchor (HTRequest * request,
! 476: HTAnchor * dst,
! 477: char * xmlbody,
! 478: HTDAVHeaders * headers) {
! 479:
! 480: if (request && dst) {
! 481: HTParentAnchor * src = NULL;
! 482: if (xmlbody) {
! 483: src = HTTmpAnchor(NULL);
! 484: HTAnchor_setDocument(src, xmlbody);
! 485: HTAnchor_setFormat(src, HTAtom_for ("text/xml"));
! 486: HTAnchor_setLength(src, strlen(xmlbody));
! 487: }
! 488: return (HTLOCKDocumentAnchor (request,dst,src,headers));
! 489: }
! 490: return NO;
! 491: }
! 492:
! 493:
! 494: /*
! 495: ** LOCK the resource indicated by an absolute URI, using the informations
! 496: ** in xmlbody string.
! 497: */
! 498: PUBLIC BOOL HTLOCKAbsolute (HTRequest * request,
! 499: const char * uri,
! 500: char * xmlbody,
! 501: HTDAVHeaders * headers){
! 502: if (request && uri && *uri) {
! 503: HTAnchor *dst = HTAnchor_findAddress (uri);
! 504: HTParentAnchor *src = NULL;
! 505:
! 506: if (xmlbody) {
! 507: src = HTTmpAnchor(NULL);
! 508: HTAnchor_setDocument(src, xmlbody);
! 509: HTAnchor_setFormat(src, HTAtom_for ("text/xml"));
! 510: HTAnchor_setLength(src, strlen(xmlbody));
! 511: }
! 512:
! 513: return (HTLOCKDocumentAnchor (request,dst,src,headers));
! 514: }
! 515: return NO;
! 516: }
! 517:
! 518:
! 519: /*
! 520: ** LOCK the resource indicated by a relative URI, which is made
! 521: ** absolute by using the base anchor.
! 522: */
! 523: PUBLIC BOOL HTLOCKRelative (HTRequest * request,
! 524: const char * relative,
! 525: HTParentAnchor * base,
! 526: char * xmlbody,
! 527: HTDAVHeaders * headers){
! 528: BOOL status = NO;
! 529: if (request && relative && base) {
! 530: char * base_uri = HTAnchor_address ((HTAnchor *)base);
! 531: char * full_uri = HTParse(relative,base_uri,PARSE_ACCESS|PARSE_HOST| \
! 532: PARSE_PATH|PARSE_PUNCTUATION);
! 533:
! 534: status = HTLOCKAbsolute (request,full_uri,xmlbody,headers);
! 535: HT_FREE (full_uri);
! 536: HT_FREE (base_uri);
! 537: }
! 538: return status;
! 539: }
! 540:
! 541:
! 542: /* --------------------------------------------------------------------------*/
! 543: /* UNLOCK REQUESTS */
! 544: /* --------------------------------------------------------------------------*/
! 545:
! 546: /*
! 547: ** UNLOCK REQUEST
! 548: **
! 549: ** UNLOCK request removes the lock identified by Lock-Token header from
! 550: ** the Request-URI.
! 551: ** Headers:
! 552: ** Lock-Token header must be present
! 553: */
! 554: PUBLIC BOOL HTUNLOCKAnchor (HTRequest * request,
! 555: HTAnchor * dst,
! 556: HTDAVHeaders * headers) {
! 557: if (request && dst) {
! 558: /* set method and request-uri */
! 559: HTRequest_setMethod (request,METHOD_UNLOCK);
! 560: HTRequest_setAnchor (request,dst);
! 561: HTTRACE (PROT_TRACE,"HTDAV.... Method set to UNLOCK\n");
! 562:
! 563: /* set headers */
! 564: HTTRACE (PROT_TRACE,"HTDAV.... Setting default Headers \n");
! 565: HTRequest_addCacheControl (request, "no-cache","");
! 566: HTRequest_addEnHd (request,HT_E_CONTENT_ENCODING);
! 567: HTRequest_addEnHd (request,HT_E_CONTENT_LENGTH);
! 568: HTRequest_addGnHd (request,HT_G_PRAGMA_NO_CACHE);
! 569:
! 570: if (headers && headers->LockToken) {
! 571: HTTRACE (PROT_TRACE,"HTDAV.... Seting Lock-Token \n");
! 572: if (headers->LockToken == NULL) {
! 573: HTTRACE (PROT_TRACE,"HTDAV.... FAILED Lock-Token is NULL\n");
! 574: return NO;
! 575: }
! 576: HTRequest_addExtraHeader (request,"Lock-Token",headers->LockToken);
! 577:
! 578: return HTLoad (request,NO);
! 579: }
! 580: }
! 581: return NO;
! 582: }
! 583:
! 584:
! 585: /*
! 586: ** UNLOCK the resource indicated by an absolute URI, using the lock tocken
! 587: ** defined in HTDAVHeaders * headers parameter.
! 588: */
! 589: PUBLIC BOOL HTUNLOCKAbsolute (HTRequest * request,
! 590: const char * uri,
! 591: HTDAVHeaders * headers) {
! 592:
! 593: if (request && uri && *uri) {
! 594: HTAnchor *dst = HTAnchor_findAddress (uri);
! 595: return HTUNLOCKAnchor (request,dst,headers);
! 596: }
! 597: return NO;
! 598: }
! 599:
! 600:
! 601: /*
! 602: ** UNLOCK the resource indicated by a relative URI, which is made
! 603: ** absolute by using the base anchor.
! 604: */
! 605: PUBLIC BOOL HTUNLOCKRelative (HTRequest * request,
! 606: const char * relative,
! 607: HTParentAnchor * base,
! 608: HTDAVHeaders * headers) {
! 609: BOOL status = NO;
! 610: if (request && relative && base) {
! 611: char * base_uri = HTAnchor_address ((HTAnchor *)base);
! 612: char * full_uri = HTParse(relative,base_uri,PARSE_ACCESS|PARSE_HOST| \
! 613: PARSE_PATH|PARSE_PUNCTUATION);
! 614:
! 615: status = HTUNLOCKAbsolute (request,full_uri,headers);
! 616: HT_FREE (full_uri);
! 617: HT_FREE (base_uri);
! 618: }
! 619: return status;
! 620: }
! 621:
! 622:
! 623: /* --------------------------------------------------------------------------*/
! 624: /* PROPFIND REQUESTS */
! 625: /* --------------------------------------------------------------------------*/
! 626:
! 627:
! 628: /*
! 629: ** PROPFIND Requests
! 630: ** PROPFIND requests returns properties defined for the resource.
! 631: ** The request may contain xml message body with a "propfind" element,
! 632: ** which may include an "allprop" element (to get all properties), a
! 633: ** "propname" element (the name of all properties defined), and a "prop"
! 634: ** element containing the desired properties.
! 635: ** Headers:
! 636: ** Depth header may be "0", "1" or "infinity".
! 637: */
! 638: PUBLIC BOOL HTPROPFINDDocumentAnchor (HTRequest * request,
! 639: HTAnchor * dst,
! 640: HTParentAnchor * xmlbody,
! 641: HTDAVHeaders * headers) {
! 642:
! 643: if (request && dst) {
! 644: /* set method and request-URI */
! 645: HTRequest_setMethod (request,METHOD_PROPFIND);
! 646: HTRequest_setAnchor (request,dst);
! 647: HTTRACE (PROT_TRACE,"HTDAV.... Method set to PROPFIND\n");
! 648:
! 649: /* set headers */
! 650: HTTRACE (PROT_TRACE,"HTDAV.... Seting default Headers \n");
! 651: HTRequest_addCacheControl (request,"no-cache","");
! 652: HTRequest_addGnHd (request,HT_G_PRAGMA_NO_CACHE);
! 653:
! 654: if (headers) { /* WebDAV specific headers */
! 655: HTTRACE (PROT_TRACE,"HTDAV.... Setting WebDAV headers \n");
! 656: if (headers->Depth) /* only Depth header may be used */
! 657: if (!strcasecomp(headers->Depth,"0") || /* values 0, 1 */
! 658: !strcasecomp(headers->Depth,"1") || /* or infinity */
! 659: !strcasecomp(headers->Depth,"infinity"))
! 660: HTRequest_addExtraHeader(request,"Depth",headers->Depth);
! 661: }
! 662:
! 663: /* set body - if there is a body */
! 664: if (xmlbody) {
! 665: HTTRACE (PROT_TRACE,"HTDAV.... Setting WebDAV Entity Request Body \n");
! 666: HTRequest_setEntityAnchor (request,xmlbody);
! 667: HTRequest_setPostCallback (request, HTEntity_callback);
! 668: }
! 669:
! 670: return HTLoad (request,NO);
! 671: }
! 672:
! 673: return NO;
! 674: }
! 675:
! 676:
! 677:
! 678: PUBLIC BOOL HTPROPFINDAnchor (HTRequest * request,
! 679: HTAnchor * dst,
! 680: const char * xmlbody,
! 681: HTDAVHeaders * headers) {
! 682: if (request && dst) {
! 683: HTParentAnchor * body = NULL;
! 684: if (xmlbody) {
! 685: body = HTTmpAnchor(NULL);
! 686: HTAnchor_setDocument(body, (void *)xmlbody);
! 687: HTAnchor_setFormat(body, HTAtom_for ("text/xml"));
! 688: HTAnchor_setLength(body, strlen(xmlbody));
! 689: }
! 690: return HTPROPFINDDocumentAnchor (request,dst,body,headers);
! 691: }
! 692:
! 693: return NO;
! 694: }
! 695:
! 696:
! 697: /*
! 698: ** This PROPFIND request returns the properties of the resource
! 699: ** indicated by the absolute URI (parameter uri).
! 700: */
! 701: PUBLIC BOOL HTPROPFINDAbsolute (HTRequest * request,
! 702: const char * uri,
! 703: const char * xmlbody,
! 704: HTDAVHeaders * headers) {
! 705: if (request && uri && *uri) {
! 706: HTAnchor *dst = HTAnchor_findAddress (uri);
! 707: return HTPROPFINDAnchor (request,dst,xmlbody,headers);
! 708: }
! 709: return NO;
! 710: }
! 711:
! 712:
! 713: /*
! 714: ** This PROPFIND request returns the properties of the resource
! 715: ** indicated by a relative URI, which is made absolute by using
! 716: ** the base anchor.
! 717: */
! 718: PUBLIC BOOL HTPROPFINDRelative (HTRequest * request,
! 719: const char * relative,
! 720: HTParentAnchor * base,
! 721: const char * xmlbody,
! 722: HTDAVHeaders * headers) {
! 723: BOOL status = NO;
! 724: if (request && relative && base) {
! 725: char * base_uri = HTAnchor_address ((HTAnchor *)base);
! 726: char * full_uri = HTParse(relative,base_uri,PARSE_ACCESS|PARSE_HOST| \
! 727: PARSE_PATH|PARSE_PUNCTUATION);
! 728:
! 729: status = HTPROPFINDAbsolute (request,full_uri,xmlbody,headers);
! 730: HT_FREE (full_uri);
! 731: HT_FREE (base_uri);
! 732: }
! 733: return status;
! 734: }
! 735:
! 736:
! 737:
! 738: /* --------------------------------------------------------------------------*/
! 739: /* PROPPATCH REQUESTS */
! 740: /* --------------------------------------------------------------------------*/
! 741:
! 742:
! 743: /*
! 744: ** PROPPATCH Requests
! 745: ** PROPPATCH requests sets/removes the properties values for the resource.
! 746: ** The request must contain a xml message body with a "propertyupdate" element,
! 747: ** which may include an "set" element (to set the properties value) or
! 748: ** a "remove" element (to remove the properties).
! 749: ** Headers: (the RFC is not very clair about it)
! 750: ** If header, indicating a state token for the resource.
! 751: */
! 752: PUBLIC BOOL HTPROPPATCHDocumentAnchor (HTRequest * request,
! 753: HTAnchor * dst,
! 754: HTParentAnchor * xmlbody,
! 755: HTDAVHeaders * headers) {
! 756:
! 757: if (request && dst && xmlbody) {
! 758:
! 759: /* set method and request-URI */
! 760: HTRequest_setMethod (request,METHOD_PROPPATCH);
! 761: HTRequest_setAnchor (request,dst);
! 762: HTTRACE (PROT_TRACE,"HTDAV.... Method set to PROPPATCH\n");
! 763:
! 764: /* set headers */
! 765: HTTRACE (PROT_TRACE,"HTDAV.... Seting default Headers \n");
! 766: HTRequest_addCacheControl (request,"no-cache","");
! 767: HTRequest_addGnHd (request,HT_G_PRAGMA_NO_CACHE);
! 768:
! 769: if (headers) { /* WebDAV specific headers*/
! 770: HTTRACE (PROT_TRACE,"HTDAV.... Setting WebDAV headers \n");
! 771: if (headers->If)
! 772: HTRequest_addExtraHeader (request,"If",headers->If);
! 773: }
! 774:
! 775: /* set body - mandatory! */
! 776: HTTRACE (PROT_TRACE,"HTDAV.... Setting Entity Body \n");
! 777: HTRequest_setEntityAnchor (request,xmlbody);
! 778: HTRequest_setPostCallback (request, HTEntity_callback);
! 779:
! 780: return HTLoad (request,NO);
! 781: }
! 782: return NO;
! 783:
! 784: }
! 785:
! 786:
! 787:
! 788: PUBLIC BOOL HTPROPPATCHAnchor (HTRequest * request,
! 789: HTAnchor * dst,
! 790: const char * xmlbody,
! 791: HTDAVHeaders * headers) {
! 792: if (request && dst && xmlbody) {
! 793: HTParentAnchor * body = HTTmpAnchor(NULL);
! 794: HTAnchor_setDocument(body, (void *)xmlbody);
! 795: HTAnchor_setFormat(body, HTAtom_for ("text/xml"));
! 796: HTAnchor_setLength(body, strlen(xmlbody));
! 797:
! 798: return HTPROPPATCHDocumentAnchor (request,dst,body,headers);
! 799: }
! 800: return NO;
! 801: }
! 802:
! 803:
! 804: /*
! 805: ** This PROPPATCH request set or removes properties from the resource
! 806: ** indicated by the absolute URI (parameter uri).
! 807: */
! 808: PUBLIC BOOL HTPROPPATCHAbsolute (HTRequest * request,
! 809: const char * uri,
! 810: const char * xmlbody,
! 811: HTDAVHeaders * headers) {
! 812: if (request && uri && *uri && xmlbody && *xmlbody) {
! 813: HTAnchor *dst = HTAnchor_findAddress (uri);
! 814: return HTPROPPATCHAnchor (request,dst,xmlbody,headers);
! 815: }
! 816: return NO;
! 817: }
! 818:
! 819:
! 820: /*
! 821: ** This PROPPATCH request sets/removes the properties from the resource
! 822: ** indicated by a relative URI, which is made absolute by using
! 823: ** the base anchor.
! 824: */
! 825: PUBLIC BOOL HTPROPPATCHRelative (HTRequest * request,
! 826: const char * relative,
! 827: HTParentAnchor * base,
! 828: const char * xmlbody,
! 829: HTDAVHeaders * headers) {
! 830: BOOL status = NO;
! 831: if (request && relative && base && xmlbody && *xmlbody) {
! 832: char * base_uri = HTAnchor_address ((HTAnchor *)base);
! 833: char * full_uri = HTParse(relative,base_uri,PARSE_ACCESS|PARSE_HOST| \
! 834: PARSE_PATH|PARSE_PUNCTUATION);
! 835:
! 836: status = HTPROPPATCHAbsolute (request,full_uri,xmlbody,headers);
! 837: HT_FREE (full_uri);
! 838: HT_FREE (base_uri);
! 839: }
! 840: return status;
! 841: }
! 842:
! 843:
! 844: /* --------------------------------------------------------------------------*/
! 845: /* MKCOL REQUESTS */
! 846: /* --------------------------------------------------------------------------*/
! 847:
! 848:
! 849: /*
! 850: ** MKCOL Requests
! 851: ** MKCOL requests creates a collection. The resource indicated by HTAnchor *
! 852: ** dst parameter must not be a "non-null" resource, but all it ancestors
! 853: ** must exist.
! 854: ** Headers:
! 855: ** If header may be used.
! 856: */
! 857: PUBLIC BOOL HTMKCOLAnchor (HTRequest * request,
! 858: HTAnchor * dst,
! 859: HTDAVHeaders * headers) {
! 860: if (request && dst) {
! 861: /* set method and request-URI */
! 862: HTRequest_setMethod (request,METHOD_MKCOL);
! 863: HTRequest_setAnchor (request,dst);
! 864: HTTRACE (PROT_TRACE,"HTDAV.... Method set to MKCOL\n");
! 865:
! 866: /* set headers */
! 867: HTTRACE (PROT_TRACE,"HTDAV.... Seting default Headers \n");
! 868: HTRequest_addCacheControl (request,"no-cache","");
! 869: HTRequest_addGnHd (request,HT_G_PRAGMA_NO_CACHE);
! 870:
! 871: if (headers) { /* WebDAV specific headers */
! 872: HTTRACE (PROT_TRACE,"HTDAV.... Setting WebDAV headers \n");
! 873: if (headers->If) /* only IF header may be used */
! 874: HTRequest_addExtraHeader(request,"If",headers->If);
! 875: }
! 876:
! 877: return HTLoad (request,NO);
! 878: }
! 879:
! 880: return NO;
! 881: }
! 882:
! 883:
! 884:
! 885: /*
! 886: ** This MKCOL request tries to create the resource
! 887: ** indicated by the absolute URI (parameter uri).
! 888: */
! 889: PUBLIC BOOL HTMKCOLAbsolute (HTRequest * request,
! 890: const char * uri,
! 891: HTDAVHeaders * headers) {
! 892: if (request && uri && *uri) {
! 893: HTAnchor *dst = HTAnchor_findAddress (uri);
! 894: return HTMKCOLAnchor (request,dst,headers);
! 895: }
! 896: return NO;
! 897: }
! 898:
! 899:
! 900: /*
! 901: ** This MKCOL request tries to create the resource indicated
! 902: ** by a relative URI, which is made absolute by using the
! 903: ** base anchor.
! 904: */
! 905: PUBLIC BOOL HTMKCOLRelative (HTRequest * request,
! 906: const char * relative,
! 907: HTParentAnchor * base,
! 908: HTDAVHeaders * headers) {
! 909: BOOL status = NO;
! 910: if (request && relative && base) {
! 911: char * base_uri = HTAnchor_address ((HTAnchor *)base);
! 912: char * full_uri = HTParse(relative,base_uri,PARSE_ACCESS|PARSE_HOST| \
! 913: PARSE_PATH|PARSE_PUNCTUATION);
! 914:
! 915: status = HTMKCOLAbsolute (request,full_uri,headers);
! 916: HT_FREE (full_uri);
! 917: HT_FREE (base_uri);
! 918: }
! 919: return status;
! 920: }
! 921:
! 922:
! 923:
! 924: /* --------------------------------------------------------------------------*/
! 925: /* COPY REQUESTS */
! 926: /* --------------------------------------------------------------------------*/
! 927:
! 928:
! 929: /*
! 930: ** COPY Requests
! 931: ** COPY requests copies the Request-URI resource (indicated by the parameter
! 932: ** HTAnchor *src) to the resource indicated by the Destination header (it must
! 933: ** be set in HTDAVHeaders object - so, this object must NOT be NULL).
! 934: ** A xml message body may also be set, with the propertybehavior xml element,
! 935: ** which indicates what should be the server behavior when copying the resouce
! 936: ** properties.
! 937: ** Headers:
! 938: ** Destination header is mandatory!
! 939: ** If header may be used.
! 940: ** Depth header may be "0" or "infinity"
! 941: ** Overwrite header may be used
! 942: */
! 943: PUBLIC BOOL HTCOPYDocumentAnchor (HTRequest * request,
! 944: HTAnchor * src,
! 945: HTParentAnchor * xmlbody,
! 946: HTDAVHeaders * headers) {
! 947:
! 948: if (request && src && headers) {
! 949:
! 950: /* set method and request-URI */
! 951: HTRequest_setMethod (request,METHOD_COPY);
! 952: HTRequest_setAnchor (request,src);
! 953: HTTRACE (PROT_TRACE,"HTDAV.... Method set to COPY\n");
! 954:
! 955: /* set headers */
! 956: HTTRACE (PROT_TRACE,"HTDAV.... Seting default Headers \n");
! 957: HTRequest_addCacheControl (request,"no-cache","");
! 958: HTRequest_addGnHd (request,HT_G_PRAGMA_NO_CACHE);
! 959:
! 960: /* WebDAV specific headers - Destination is mandatory! */
! 961: if (headers->Destination && *headers->Destination) {
! 962: HTTRACE (PROT_TRACE,"HTDAV.... Setting WebDAV headers \n");
! 963: HTRequest_addExtraHeader(request,"Destination",headers->Destination);
! 964:
! 965: if (headers->If) /* If header may be used */
! 966: HTRequest_addExtraHeader(request,"If",headers->If);
! 967:
! 968: if (headers->Overwrite != ' ') {
! 969: char over[] = { headers->Overwrite, '\0' };
! 970: HTRequest_addExtraHeader(request,"Overwirte", over );
! 971: }
! 972:
! 973: if (headers->Depth) {
! 974: if (!strcasecomp(headers->Depth,"0") ||
! 975: !strcasecomp(headers->Depth,"infinity"))
! 976: HTRequest_addExtraHeader(request,"Depth",headers->Depth);
! 977: }
! 978: }
! 979: else return NO;
! 980:
! 981: /* set body - if there is a body */
! 982: if (xmlbody) {
! 983: HTTRACE (PROT_TRACE,"HTDAV.... Setting Entity Body \n");
! 984: HTRequest_setEntityAnchor (request,xmlbody);
! 985: HTRequest_setPostCallback (request, HTEntity_callback);
! 986: }
! 987: return HTLoad (request,NO);
! 988: }
! 989:
! 990: return NO;
! 991: }
! 992:
! 993:
! 994:
! 995: PUBLIC BOOL HTCOPYAnchor (HTRequest * request,
! 996: HTAnchor * src,
! 997: const char * xmlbody,
! 998: HTDAVHeaders * headers) {
! 999:
! 1000: if (request && src && headers) {
! 1001: HTParentAnchor * body = NULL;
! 1002: if (xmlbody) {
! 1003: body = HTTmpAnchor(NULL);
! 1004: HTAnchor_setDocument(body, (void *)xmlbody);
! 1005: HTAnchor_setFormat(body, HTAtom_for ("text/xml"));
! 1006: HTAnchor_setLength(body, strlen(xmlbody));
! 1007: }
! 1008: return HTCOPYDocumentAnchor (request,src,body,headers);
! 1009: }
! 1010: return NO;
! 1011: }
! 1012:
! 1013:
! 1014: /*
! 1015: ** This COPY request copies the resource indicated by an absolute URI
! 1016: ** (parameter uri) to the URI in Destination header.
! 1017: */
! 1018: PUBLIC BOOL HTCOPYAbsolute (HTRequest * request,
! 1019: const char * uri,
! 1020: const char * xmlbody,
! 1021: HTDAVHeaders * headers) {
! 1022: if (request && uri && *uri && headers) {
! 1023: HTAnchor *src = HTAnchor_findAddress (uri);
! 1024: return HTCOPYAnchor (request,src,xmlbody,headers);
! 1025: }
! 1026: return NO;
! 1027: }
! 1028:
! 1029:
! 1030: /*
! 1031: ** This COPY request copies the resource indicated by a relative URI,
! 1032: ** which is made absolute by using the base anchor.
! 1033: */
! 1034: PUBLIC BOOL HTCOPYRelative (HTRequest * request,
! 1035: const char * relative,
! 1036: HTParentAnchor * base,
! 1037: const char * xmlbody,
! 1038: HTDAVHeaders * headers) {
! 1039: BOOL status = NO;
! 1040: if (request && relative && base && headers) {
! 1041: char * base_uri = HTAnchor_address ((HTAnchor *)base);
! 1042: char * full_uri = HTParse(relative,base_uri,PARSE_ACCESS|PARSE_HOST| \
! 1043: PARSE_PATH|PARSE_PUNCTUATION);
! 1044:
! 1045: status = HTCOPYAbsolute (request,full_uri,xmlbody,headers);
! 1046: HT_FREE (full_uri);
! 1047: HT_FREE (base_uri);
! 1048: }
! 1049: return status;
! 1050: }
! 1051:
! 1052:
! 1053:
! 1054: /* --------------------------------------------------------------------------*/
! 1055: /* MOVE REQUESTS */
! 1056: /* --------------------------------------------------------------------------*/
! 1057:
! 1058:
! 1059: /*
! 1060: ** MOVE Requests
! 1061: ** MOVE requests moves the Request-URI resource (indicated by the parameter
! 1062: ** HTAnchor *src) to the resource indicated by the Destination header (it must
! 1063: ** be set in HTDAVHeaders object - so, this object must NOT be NULL).
! 1064: ** A xml message body may also be set, with the propertybehavior xml element,
! 1065: ** which indicates what should be the server behavior when copying the resouce
! 1066: ** properties.
! 1067: ** Headers:
! 1068: ** Destination header is mandatory!
! 1069: ** If header may be used.
! 1070: ** Depth header may be "0" or "infinity" (for collections, it MUST be "infinity")
! 1071: ** Overwrite header may be used
! 1072: */
! 1073: PUBLIC BOOL HTMOVEDocumentAnchor (HTRequest * request,
! 1074: HTAnchor * src,
! 1075: HTParentAnchor * xmlbody,
! 1076: HTDAVHeaders * headers) {
! 1077:
! 1078: if (request && src && headers) {
! 1079:
! 1080: /* set method and request-URI */
! 1081: HTRequest_setMethod (request,METHOD_MOVE);
! 1082: HTRequest_setAnchor (request,src);
! 1083: HTTRACE (PROT_TRACE,"HTDAV.... Method set to MOVE\n");
! 1084:
! 1085: /* set headers */
! 1086: HTTRACE (PROT_TRACE,"HTDAV.... Seting default Headers \n");
! 1087: HTRequest_addCacheControl (request,"no-cache","");
! 1088: HTRequest_addGnHd (request,HT_G_PRAGMA_NO_CACHE);
! 1089:
! 1090: /* WebDAV specific headers - Destination is mandatory! */
! 1091: if (headers->Destination && *headers->Destination) {
! 1092: HTTRACE (PROT_TRACE,"HTDAV.... Setting WebDAV headers \n");
! 1093: HTRequest_addExtraHeader(request,"Destination",headers->Destination);
! 1094:
! 1095: if (headers->If) /* If header may be used */
! 1096: HTRequest_addExtraHeader(request,"If",headers->If);
! 1097:
! 1098: if (headers->Overwrite != ' ') {
! 1099: char over[] = { headers->Overwrite, '\0' };
! 1100: HTRequest_addExtraHeader(request,"Overwirte", over );
! 1101: }
! 1102:
! 1103: if (headers->Depth) {
! 1104: if (!strcasecomp(headers->Depth,"0") ||
! 1105: !strcasecomp(headers->Depth,"infinity"))
! 1106: HTRequest_addExtraHeader(request,"Depth",headers->Depth);
! 1107: }
! 1108: }
! 1109: else return NO;
! 1110:
! 1111: /* set body - if there is a body */
! 1112: if (xmlbody) {
! 1113: HTTRACE (PROT_TRACE,"HTDAV.... Setting Entity Body \n");
! 1114: HTRequest_setEntityAnchor (request,xmlbody);
! 1115: HTRequest_setPostCallback (request,HTEntity_callback);
! 1116: }
! 1117: return HTLoad (request,NO);
! 1118: }
! 1119:
! 1120: return NO;
! 1121: }
! 1122:
! 1123:
! 1124:
! 1125: PUBLIC BOOL HTMOVEAnchor (HTRequest * request,
! 1126: HTAnchor * src,
! 1127: const char * xmlbody,
! 1128: HTDAVHeaders * headers) {
! 1129:
! 1130: if (request && src && headers) {
! 1131: HTParentAnchor * body = NULL;
! 1132: if (xmlbody) {
! 1133: body = HTTmpAnchor(NULL);
! 1134: HTAnchor_setDocument(body, (void *) xmlbody);
! 1135: HTAnchor_setFormat(body, HTAtom_for ("text/xml"));
! 1136: HTAnchor_setLength(body, strlen(xmlbody));
! 1137: }
! 1138: return HTMOVEDocumentAnchor (request,src,body,headers);
! 1139: }
! 1140: return NO;
! 1141: }
! 1142:
! 1143:
! 1144: /*
! 1145: ** This MOVE request moves the resource indicated by an absolute URI
! 1146: ** (parameter uri) to the URI in Destination header.
! 1147: */
! 1148: PUBLIC BOOL HTMOVEAbsolute (HTRequest * request,
! 1149: const char * uri,
! 1150: const char * xmlbody,
! 1151: HTDAVHeaders * headers) {
! 1152: if (request && uri && *uri && headers) {
! 1153: HTAnchor *src = HTAnchor_findAddress (uri);
! 1154: return HTMOVEAnchor (request,src,xmlbody,headers);
! 1155: }
! 1156: return NO;
! 1157: }
! 1158:
! 1159:
! 1160: /*
! 1161: ** This MOVE request moves the resource indicated by a relative URI,
! 1162: ** which is made absolute by using the base anchor.
! 1163: */
! 1164: PUBLIC BOOL HTMOVERelative (HTRequest * request,
! 1165: const char * relative,
! 1166: HTParentAnchor * base,
! 1167: const char * xmlbody,
! 1168: HTDAVHeaders * headers) {
! 1169: BOOL status = NO;
! 1170: if (request && relative && base && headers) {
! 1171: char * base_uri = HTAnchor_address ((HTAnchor *)base);
! 1172: char * full_uri = HTParse(relative,base_uri,PARSE_ACCESS|PARSE_HOST| \
! 1173: PARSE_PATH|PARSE_PUNCTUATION);
! 1174:
! 1175: status = HTMOVEAbsolute (request,full_uri,xmlbody,headers);
! 1176: HT_FREE (full_uri);
! 1177: HT_FREE (base_uri);
! 1178: }
! 1179: return status;
! 1180: }
! 1181:
! 1182:
! 1183: #endif /* HT_DAV */
Webmaster