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