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