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