/*
** WebDAV MANAGER
**
** (c) COPYRIGHT MIT 1995.
** Please first read the full copyright statement in the file COPYRIGH.
**
** Authors
** MKP Manuele Kirsch Pinheiro, Manuele.Kirsch_Pinheiro@inrialpes.fr
** manuele@inf.ufrgs.br
**
** History
** 15 Fev 02 Writen
** 15 Mar 02 Changed - All methods will use entity callback and not the
** message body functions. This modification was demanded by
** Jose Kahan.
** 30 May 02 Changed - wwwsys.h becames the first include file
**
** $Log: HTDAV.c,v $
** Revision 1.3 2002/05/30 18:08:56 kirschpi
** Minor changes concerning windows plataform (as STDIN_FILENO reference at
** myext.c and myext2.c) and concerning code readability.
**
** Revision 1.2 2002/05/29 16:09:13 kirschpi
**
** Fixes for windows plataform concerning WebDAV and Extension
** methods. In HTMethod and HTRequest, functions defined for
** the Extension Methods are now defined always, but return
** fail values when HT_EXT is not defined. In addition, the
** files "Library/src/WWWDAV.html" and "Library/src/windows/wwwdav.files"
** have been added. These files and modifications were needed
** to produce the correct "*.def" files, for windows plataform.
**
** Revision 1.1 2002/03/21 14:16:27 kirschpi
** Missing files
** Manuele Kirsch
**
**
** $Id: HTDAV.c,v 1.3 2002/05/30 18:08:56 kirschpi Exp $
*/
/* Library include files */
#include "wwwsys.h"
#include "WWWLib.h"
#include "WWWInit.h"
#include "WWWUtil.h"
#include "WWWStream.h"
#include "HTDAV.h" /* implemented here */
#ifdef HT_DAV
struct _HTStream {
const HTStreamClass * isa;
HTStream * target;
HTRequest * request;
int version;
BOOL endHeader;
BOOL transparent;
};
/* --------------------------------------------------------------------------*/
/* WebDAV REQUEST HEADERS */
/* --------------------------------------------------------------------------*/
/* Headers defined in WebDAV - RC2518
** If: state list _ may be a tagged or a non-tag list of state tokens and Etags
** Depth: how depth the method should be executed. Values are: 0,1,infinity
** Destination: destination URI for COPY and MOVE methods
** Overwrite: should the method overwrite any existant resource? Values: T or F
** LockToken: lock identification (used only in UNLOCK method)
** Timeout: lock timeout. Values: Second-nnn,Infinite or Extend file (RFC2068)
*/
struct _HTDAVHeaders {
char * If;
char * Depth;
char * Destination;
char * LockToken;
char * Timeout;
char Overwrite;
};
/*
** Creates a new HTDAVHeaders struct
*/
PUBLIC HTDAVHeaders * HTDAVHeaders_new (void) {
HTDAVHeaders *me;
if ( (me = (HTDAVHeaders *) HT_CALLOC (1,sizeof(HTDAVHeaders))) == NULL)
HT_OUTOFMEM ("HTDAVHeaders_new");
/* set everything to an empty value */
me->If = NULL;
me->Depth = NULL;
me->Destination = NULL;
me->LockToken = NULL;
me->Timeout = NULL;
me->Overwrite = ' ';
HTTRACE (PROT_TRACE,"HTDAV.... HTDAVHeaders object created\n");
return me;
}
/*
** Deletes a HTDAVHeaders object
*/
PUBLIC BOOL HTDAVHeaders_delete (HTDAVHeaders *me) {
if (me) {
if (me->If) HT_FREE (me->If);
if (me->Depth) HT_FREE (me->Depth);
if (me->Destination) HT_FREE (me->Destination);
if (me->LockToken) HT_FREE (me->LockToken);
if (me->Timeout) HT_FREE (me->Timeout);
HT_FREE (me);
HTTRACE (PROT_TRACE,"HTDAV.... HTDAVHeaders object removed\n");
return YES;
}
return NO;
}
/*
** Set the If header - see section 9.4 of RFC2518
*/
PUBLIC BOOL HTDAV_setIfHeader (HTDAVHeaders *me, const char *If) {
if (me && If && *If) {
HTTRACE (PROT_TRACE,"HTDAV.... If Header set\n");
StrAllocCopy (me->If,If);
return YES;
}
return NO;
}
/*
** Removes the "If" header.
*/
PUBLIC BOOL HTDAV_deleteIfHeader (HTDAVHeaders * me) {
if (me && me->If) {
HT_FREE(me->If);
me->If = NULL;
return YES;
}
return NO;
}
/*
** Return the "If" header, NULL if this header is not set.
** The caller should FREE the returned string
*/
PUBLIC char * HTDAV_ifHeader (HTDAVHeaders *me) {
char *copy = NULL;
if (me && me->If) {
StrAllocCopy (copy,me->If);
}
return copy;
}
/*
** Set the Depth header - see section 9.2 of RFC2518
*/
PUBLIC BOOL HTDAV_setDepthHeader (HTDAVHeaders *me, const char *Depth) {
if (me && Depth && *Depth) {
HTTRACE (PROT_TRACE,"HTDAV.... Depth Header set\n");
StrAllocCopy (me->Depth,Depth);
return YES;
}
return NO;
}
/*
** Removes the "Depth" header.
*/
PUBLIC BOOL HTDAV_deleteDepthHeader (HTDAVHeaders * me) {
if (me && me->Depth) {
HT_FREE (me->Depth);
me->Depth = NULL;
return YES;
}
return NO;
}
/*
** Return the "Depth" header, NULL if this header is not set.
** The caller should FREE the returned string
*/
PUBLIC char * HTDAV_DepthHeader (HTDAVHeaders *me) {
char *copy = NULL;
if (me && me->Depth) {
StrAllocCopy (copy,me->Depth);
}
return copy;
}
/*
** Set the LockToken header - see section 9.5 of RFC2518
*/
PUBLIC BOOL HTDAV_setLockTokenHeader (HTDAVHeaders *me, const char *LockToken) {
if (me && LockToken && *LockToken) {
HTTRACE (PROT_TRACE,"HTDAV.... Lock-Token Header set\n");
StrAllocCopy (me->LockToken,LockToken);
return YES;
}
return NO;
}
/*
** Removes the "LockToken" header.
*/
PUBLIC BOOL HTDAV_deleteLockTokenHeader (HTDAVHeaders * me) {
if (me && me->LockToken) {
HT_FREE (me->LockToken);
me->LockToken = NULL;
return YES;
}
return NO;
}
/*
** Return the "LockToken" header, NULL if this header is not set.
** The caller should FREE the returned string
*/
PUBLIC char * HTDAV_LockTokenHeader (HTDAVHeaders *me) {
char *copy = NULL;
if (me && me->LockToken) {
StrAllocCopy (copy,me->LockToken);
}
return copy;
}
/*
** Set the Destination header - see section 9.3 of RFC2518
*/
PUBLIC BOOL HTDAV_setDestinationHeader (HTDAVHeaders *me, const char *Destination) {
if (me && Destination && *Destination) {
HTTRACE (PROT_TRACE,"HTDAV.... Destination Header set\n");
StrAllocCopy (me->Destination,Destination);
return YES;
}
return NO;
}
/*
** Removes the "Destination" header.
*/
PUBLIC BOOL HTDAV_deleteDestinationHeader (HTDAVHeaders * me) {
if (me && me->Destination) {
HT_FREE (me->Destination);
me->Destination = NULL;
return YES;
}
return NO;
}
/*
** Return the "Destination" header, NULL if this header is not set.
** The caller should FREE the returned string
*/
PUBLIC char * HTDAV_DestinationHeader (HTDAVHeaders *me) {
char *copy = NULL;
if (me && me->Destination) {
StrAllocCopy (copy,me->Destination);
}
return copy;
}
/*
** Set the Timeout header - see section 9.8 of RFC2518
*/
PUBLIC BOOL HTDAV_setTimeoutHeader (HTDAVHeaders *me, const char *Timeout) {
if (me && Timeout && *Timeout) {
HTTRACE (PROT_TRACE,"HTDAV.... Timeout Header set\n");
StrAllocCopy (me->Timeout,Timeout);
return YES;
}
return NO;
}
/*
** Removes the "Timeout" header.
*/
PUBLIC BOOL HTDAV_deleteTimeoutHeader (HTDAVHeaders * me) {
if (me && me->Timeout) {
HT_FREE (me->Timeout);
me->Timeout = NULL;
return YES;
}
return NO;
}
/*
** Return the "Timeout" header, NULL if this header is not set.
** The caller should FREE the returned string
*/
PUBLIC char * HTDAV_TimeoutHeader (HTDAVHeaders *me) {
char *copy = NULL;
if (me && me->Timeout) {
StrAllocCopy (copy,me->Timeout);
}
return copy;
}
/*
** Set the Overwrite header - see section 9.6 of RFC2518
*/
PUBLIC BOOL HTDAV_setOverwriteHeader (HTDAVHeaders *me, BOOL Overwrite) {
if (me) {
HTTRACE (PROT_TRACE,"HTDAV.... Overwrite Header set\n");
me->Overwrite = (Overwrite)?'T':'F';
return YES;
}
return NO;
}
/*
** Removes the "Overwirte" header.
*/
PUBLIC BOOL HTDAV_deleteOverwriteHeader (HTDAVHeaders * me) {
if (me) {
me->Overwrite = ' ';
return YES;
}
return NO;
}
/*
** Returns the "Overwrite" header. If it is not set, returns the
** default value (YES == TRUE)
*/
PUBLIC BOOL HTDAV_OverwriteHeader (HTDAVHeaders * me) {
if (me) {
return (me->Overwrite==' ' || me->Overwrite=='T')?YES:NO;
}
return YES;
}
/* --------------------------------------------------------------------------*/
/* ENTITY CALLBACK */
/* --------------------------------------------------------------------------*/
/*
** Entity Callback - IDEM HTAccess.c
*/
PRIVATE int HTEntity_callback (HTRequest * request, HTStream * target)
{
HTParentAnchor * entity = HTRequest_entityAnchor(request);
HTTRACE(APP_TRACE, "Posting Data from callback function\n");
if (!request || !entity || !target) return HT_ERROR;
{
BOOL chunking = NO;
int status;
char * document = (char *) HTAnchor_document(entity);
int len = HTAnchor_length(entity);
if (!document) {
HTTRACE(PROT_TRACE, "Posting Data No document\n");
return HT_ERROR;
}
/*
** If the length is unknown (-1) then see if the document is a text
** type and in that case take the strlen. If not then we don't know
** how much data we can write and must stop
*/
if (len < 0) {
HTFormat actual = HTAnchor_format(entity);
HTFormat tmplate = HTAtom_for("text/*");
if (HTMIMEMatch(tmplate, actual)) {
len = strlen(document); /* Naive! */
chunking = YES;
} else {
HTTRACE(PROT_TRACE, "Posting Data Must know the length of document %p\n" _
document);
return HT_ERROR;
}
}
/* Send the data down the pipe */
status = (*target->isa->put_block)(target, document, len);
if (status == HT_WOULD_BLOCK) {
HTTRACE(PROT_TRACE, "Posting Data Target WOULD BLOCK\n");
return HT_WOULD_BLOCK;
} else if (status == HT_PAUSE) {
HTTRACE(PROT_TRACE, "Posting Data Target PAUSED\n");
return HT_PAUSE;
} else if (chunking && status == HT_OK) {
HTTRACE(PROT_TRACE, "Posting Data Target is SAVED using chunked\n");
return (*target->isa->put_block)(target, "", 0);
} else if (status == HT_LOADED || status == HT_OK) {
HTTRACE(PROT_TRACE, "Posting Data Target is SAVED\n");
(*target->isa->flush)(target);
return HT_LOADED;
} else if (status > 0) { /* Stream specific return code */
HTTRACE(PROT_TRACE, "Posting Data. Target returns %d\n" _ status);
return status;
} else { /* we have a real error */
HTTRACE(PROT_TRACE, "Posting Data Target ERROR %d\n" _ status);
return status;
}
}
}
/* --------------------------------------------------------------------------*/
/* LOCK REQUESTS */
/* --------------------------------------------------------------------------*/
/*
** LOCK REQUESTS
**
** LOCK requests may create a lock specified by "lockinfo" XML element
** on the Request URI. LOCK request should have a XML request entity body,
** which contains "owner" XML element, or the request should be a lock
** refresh request.
** Headers:
** If header is mandatory for lock refresh request
** Depth header may be "0" or "infinity" (default: infinity)
** Timeout header may be used
*/
PUBLIC BOOL HTLOCKDocumentAnchor (HTRequest * request,
HTAnchor * dst,
HTParentAnchor * xmlbody,
HTDAVHeaders * headers) {
if (request && dst) {
/* set method and request-URI */
HTRequest_setMethod (request,METHOD_LOCK);
HTRequest_setAnchor (request,dst);
HTTRACE (PROT_TRACE,"HTDAV.... Method set to LOCK\n");
/* set headers */
HTTRACE (PROT_TRACE,"HTDAV.... Seting default Headers \n");
HTRequest_addCacheControl (request,"no-cache","");
HTRequest_addEnHd (request,HT_E_CONTENT_ENCODING);
HTRequest_addEnHd (request,HT_E_CONTENT_LENGTH);
HTRequest_addGnHd (request,HT_G_PRAGMA_NO_CACHE);
if (headers) { /* WebDAV specific headers */
HTTRACE (PROT_TRACE,"HTDAV.... Setting WebDAV headers \n");
if (headers->If)
HTRequest_addExtraHeader (request,"If",headers->If);
if (headers->Depth) { /* Depth: 0 or infinity only */
if (!strcasecomp(headers->Depth,"0") ||
!strcasecomp(headers->Depth,"infinity"))
HTRequest_addExtraHeader (request,"Depth",headers->Depth);
}
if (headers->Timeout)
HTRequest_addExtraHeader (request,"Timeout",headers->Timeout);
}
/* set body - if there is no body, we expect that is a lock refresh */
if (xmlbody) {
HTTRACE (PROT_TRACE,"HTDAV.... Setting Entity Body \n");
HTRequest_setEntityAnchor (request,xmlbody);
HTRequest_setPostCallback(request, HTEntity_callback);
}
return HTLoad (request,NO);
}
return NO;
}
/*
** LOCK the URI indicated by HTAnchor *dst using the informations
** in xmlbody string.
*/
PUBLIC BOOL HTLOCKAnchor (HTRequest * request,
HTAnchor * dst,
char * xmlbody,
HTDAVHeaders * headers) {
if (request && dst) {
HTParentAnchor * src = NULL;
if (xmlbody) {
src = HTTmpAnchor(NULL);
HTAnchor_setDocument(src, xmlbody);
HTAnchor_setFormat(src, HTAtom_for ("text/xml"));
HTAnchor_setLength(src, strlen(xmlbody));
}
return (HTLOCKDocumentAnchor (request,dst,src,headers));
}
return NO;
}
/*
** LOCK the resource indicated by an absolute URI, using the informations
** in xmlbody string.
*/
PUBLIC BOOL HTLOCKAbsolute (HTRequest * request,
const char * uri,
char * xmlbody,
HTDAVHeaders * headers){
if (request && uri && *uri) {
HTAnchor *dst = HTAnchor_findAddress (uri);
HTParentAnchor *src = NULL;
if (xmlbody) {
src = HTTmpAnchor(NULL);
HTAnchor_setDocument(src, xmlbody);
HTAnchor_setFormat(src, HTAtom_for ("text/xml"));
HTAnchor_setLength(src, strlen(xmlbody));
}
return (HTLOCKDocumentAnchor (request,dst,src,headers));
}
return NO;
}
/*
** LOCK the resource indicated by a relative URI, which is made
** absolute by using the base anchor.
*/
PUBLIC BOOL HTLOCKRelative (HTRequest * request,
const char * relative,
HTParentAnchor * base,
char * xmlbody,
HTDAVHeaders * headers){
BOOL status = NO;
if (request && relative && base) {
char * base_uri = HTAnchor_address ((HTAnchor *)base);
char * full_uri = HTParse(relative,base_uri,PARSE_ACCESS|PARSE_HOST| \
PARSE_PATH|PARSE_PUNCTUATION);
status = HTLOCKAbsolute (request,full_uri,xmlbody,headers);
HT_FREE (full_uri);
HT_FREE (base_uri);
}
return status;
}
/* --------------------------------------------------------------------------*/
/* UNLOCK REQUESTS */
/* --------------------------------------------------------------------------*/
/*
** UNLOCK REQUEST
**
** UNLOCK request removes the lock identified by Lock-Token header from
** the Request-URI.
** Headers:
** Lock-Token header must be present
*/
PUBLIC BOOL HTUNLOCKAnchor (HTRequest * request,
HTAnchor * dst,
HTDAVHeaders * headers) {
if (request && dst) {
/* set method and request-uri */
HTRequest_setMethod (request,METHOD_UNLOCK);
HTRequest_setAnchor (request,dst);
HTTRACE (PROT_TRACE,"HTDAV.... Method set to UNLOCK\n");
/* set headers */
HTTRACE (PROT_TRACE,"HTDAV.... Setting default Headers \n");
HTRequest_addCacheControl (request, "no-cache","");
HTRequest_addEnHd (request,HT_E_CONTENT_ENCODING);
HTRequest_addEnHd (request,HT_E_CONTENT_LENGTH);
HTRequest_addGnHd (request,HT_G_PRAGMA_NO_CACHE);
if (headers && headers->LockToken) {
HTTRACE (PROT_TRACE,"HTDAV.... Seting Lock-Token \n");
if (headers->LockToken == NULL) {
HTTRACE (PROT_TRACE,"HTDAV.... FAILED Lock-Token is NULL\n");
return NO;
}
HTRequest_addExtraHeader (request,"Lock-Token",headers->LockToken);
return HTLoad (request,NO);
}
}
return NO;
}
/*
** UNLOCK the resource indicated by an absolute URI, using the lock tocken
** defined in HTDAVHeaders * headers parameter.
*/
PUBLIC BOOL HTUNLOCKAbsolute (HTRequest * request,
const char * uri,
HTDAVHeaders * headers) {
if (request && uri && *uri) {
HTAnchor *dst = HTAnchor_findAddress (uri);
return HTUNLOCKAnchor (request,dst,headers);
}
return NO;
}
/*
** UNLOCK the resource indicated by a relative URI, which is made
** absolute by using the base anchor.
*/
PUBLIC BOOL HTUNLOCKRelative (HTRequest * request,
const char * relative,
HTParentAnchor * base,
HTDAVHeaders * headers) {
BOOL status = NO;
if (request && relative && base) {
char * base_uri = HTAnchor_address ((HTAnchor *)base);
char * full_uri = HTParse (relative,base_uri,PARSE_ACCESS|PARSE_HOST| \
PARSE_PATH|PARSE_PUNCTUATION);
status = HTUNLOCKAbsolute (request,full_uri,headers);
HT_FREE (full_uri);
HT_FREE (base_uri);
}
return status;
}
/* --------------------------------------------------------------------------*/
/* PROPFIND REQUESTS */
/* --------------------------------------------------------------------------*/
/*
** PROPFIND Requests
** PROPFIND requests returns properties defined for the resource.
** The request may contain xml message body with a "propfind" element,
** which may include an "allprop" element (to get all properties), a
** "propname" element (the name of all properties defined), and a "prop"
** element containing the desired properties.
** Headers:
** Depth header may be "0", "1" or "infinity".
*/
PUBLIC BOOL HTPROPFINDDocumentAnchor (HTRequest * request,
HTAnchor * dst,
HTParentAnchor * xmlbody,
HTDAVHeaders * headers) {
if (request && dst) {
/* set method and request-URI */
HTRequest_setMethod (request,METHOD_PROPFIND);
HTRequest_setAnchor (request,dst);
HTTRACE (PROT_TRACE,"HTDAV.... Method set to PROPFIND\n");
/* set headers */
HTTRACE (PROT_TRACE,"HTDAV.... Seting default Headers \n");
HTRequest_addCacheControl (request,"no-cache","");
HTRequest_addGnHd (request,HT_G_PRAGMA_NO_CACHE);
if (headers) { /* WebDAV specific headers */
HTTRACE (PROT_TRACE,"HTDAV.... Setting WebDAV headers \n");
if (headers->Depth) /* only Depth header may be used */
if (!strcasecomp(headers->Depth,"0") || /* values 0, 1 */
!strcasecomp(headers->Depth,"1") || /* or infinity */
!strcasecomp(headers->Depth,"infinity"))
HTRequest_addExtraHeader(request,"Depth",headers->Depth);
}
/* set body - if there is a body */
if (xmlbody) {
HTTRACE (PROT_TRACE,"HTDAV.... Setting WebDAV Entity Request Body \n");
HTRequest_setEntityAnchor (request,xmlbody);
HTRequest_setPostCallback (request, HTEntity_callback);
}
return HTLoad (request,NO);
}
return NO;
}
PUBLIC BOOL HTPROPFINDAnchor (HTRequest * request,
HTAnchor * dst,
const char * xmlbody,
HTDAVHeaders * headers) {
if (request && dst) {
HTParentAnchor * body = NULL;
if (xmlbody) {
body = HTTmpAnchor(NULL);
HTAnchor_setDocument(body, (void *)xmlbody);
HTAnchor_setFormat(body, HTAtom_for ("text/xml"));
HTAnchor_setLength(body, strlen(xmlbody));
}
return HTPROPFINDDocumentAnchor (request,dst,body,headers);
}
return NO;
}
/*
** This PROPFIND request returns the properties of the resource
** indicated by the absolute URI (parameter uri).
*/
PUBLIC BOOL HTPROPFINDAbsolute (HTRequest * request,
const char * uri,
const char * xmlbody,
HTDAVHeaders * headers) {
if (request && uri && *uri) {
HTAnchor *dst = HTAnchor_findAddress (uri);
return HTPROPFINDAnchor (request,dst,xmlbody,headers);
}
return NO;
}
/*
** This PROPFIND request returns the properties of the resource
** indicated by a relative URI, which is made absolute by using
** the base anchor.
*/
PUBLIC BOOL HTPROPFINDRelative (HTRequest * request,
const char * relative,
HTParentAnchor * base,
const char * xmlbody,
HTDAVHeaders * headers) {
BOOL status = NO;
if (request && relative && base) {
char * base_uri = HTAnchor_address ((HTAnchor *)base);
char * full_uri = HTParse(relative,base_uri,PARSE_ACCESS|PARSE_HOST| \
PARSE_PATH|PARSE_PUNCTUATION);
status = HTPROPFINDAbsolute (request,full_uri,xmlbody,headers);
HT_FREE (full_uri);
HT_FREE (base_uri);
}
return status;
}
/* --------------------------------------------------------------------------*/
/* PROPPATCH REQUESTS */
/* --------------------------------------------------------------------------*/
/*
** PROPPATCH Requests
** PROPPATCH requests sets/removes the properties values for the resource.
** The request must contain a xml message body with a "propertyupdate" element,
** which may include an "set" element (to set the properties value) or
** a "remove" element (to remove the properties).
** Headers: (the RFC is not very clair about it)
** If header, indicating a state token for the resource.
*/
PUBLIC BOOL HTPROPPATCHDocumentAnchor (HTRequest * request,
HTAnchor * dst,
HTParentAnchor * xmlbody,
HTDAVHeaders * headers) {
if (request && dst && xmlbody) {
/* set method and request-URI */
HTRequest_setMethod (request,METHOD_PROPPATCH);
HTRequest_setAnchor (request,dst);
HTTRACE (PROT_TRACE,"HTDAV.... Method set to PROPPATCH\n");
/* set headers */
HTTRACE (PROT_TRACE,"HTDAV.... Seting default Headers \n");
HTRequest_addCacheControl (request,"no-cache","");
HTRequest_addGnHd (request,HT_G_PRAGMA_NO_CACHE);
if (headers) { /* WebDAV specific headers*/
HTTRACE (PROT_TRACE,"HTDAV.... Setting WebDAV headers \n");
if (headers->If)
HTRequest_addExtraHeader (request,"If",headers->If);
}
/* set body - mandatory! */
HTTRACE (PROT_TRACE,"HTDAV.... Setting Entity Body \n");
HTRequest_setEntityAnchor (request,xmlbody);
HTRequest_setPostCallback (request, HTEntity_callback);
return HTLoad (request,NO);
}
return NO;
}
PUBLIC BOOL HTPROPPATCHAnchor (HTRequest * request,
HTAnchor * dst,
const char * xmlbody,
HTDAVHeaders * headers) {
if (request && dst && xmlbody) {
HTParentAnchor * body = HTTmpAnchor(NULL);
HTAnchor_setDocument (body, (void *)xmlbody);
HTAnchor_setFormat (body, HTAtom_for ("text/xml"));
HTAnchor_setLength (body, strlen(xmlbody));
return HTPROPPATCHDocumentAnchor (request,dst,body,headers);
}
return NO;
}
/*
** This PROPPATCH request set or removes properties from the resource
** indicated by the absolute URI (parameter uri).
*/
PUBLIC BOOL HTPROPPATCHAbsolute (HTRequest * request,
const char * uri,
const char * xmlbody,
HTDAVHeaders * headers) {
if (request && uri && *uri && xmlbody && *xmlbody) {
HTAnchor *dst = HTAnchor_findAddress (uri);
return HTPROPPATCHAnchor (request,dst,xmlbody,headers);
}
return NO;
}
/*
** This PROPPATCH request sets/removes the properties from the resource
** indicated by a relative URI, which is made absolute by using
** the base anchor.
*/
PUBLIC BOOL HTPROPPATCHRelative (HTRequest * request,
const char * relative,
HTParentAnchor * base,
const char * xmlbody,
HTDAVHeaders * headers) {
BOOL status = NO;
if (request && relative && base && xmlbody && *xmlbody) {
char * base_uri = HTAnchor_address ((HTAnchor *)base);
char * full_uri = HTParse (relative,base_uri,PARSE_ACCESS|PARSE_HOST| \
PARSE_PATH|PARSE_PUNCTUATION);
status = HTPROPPATCHAbsolute (request,full_uri,xmlbody,headers);
HT_FREE (full_uri);
HT_FREE (base_uri);
}
return status;
}
/* --------------------------------------------------------------------------*/
/* MKCOL REQUESTS */
/* --------------------------------------------------------------------------*/
/*
** MKCOL Requests
** MKCOL requests creates a collection. The resource indicated by HTAnchor *
** dst parameter must not be a "non-null" resource, but all it ancestors
** must exist.
** Headers:
** If header may be used.
*/
PUBLIC BOOL HTMKCOLAnchor (HTRequest * request,
HTAnchor * dst,
HTDAVHeaders * headers) {
if (request && dst) {
/* set method and request-URI */
HTRequest_setMethod (request,METHOD_MKCOL);
HTRequest_setAnchor (request,dst);
HTTRACE (PROT_TRACE,"HTDAV.... Method set to MKCOL\n");
/* set headers */
HTTRACE (PROT_TRACE,"HTDAV.... Seting default Headers \n");
HTRequest_addCacheControl (request,"no-cache","");
HTRequest_addGnHd (request,HT_G_PRAGMA_NO_CACHE);
if (headers) { /* WebDAV specific headers */
HTTRACE (PROT_TRACE,"HTDAV.... Setting WebDAV headers \n");
if (headers->If) /* only IF header may be used */
HTRequest_addExtraHeader (request,"If",headers->If);
}
return HTLoad (request,NO);
}
return NO;
}
/*
** This MKCOL request tries to create the resource
** indicated by the absolute URI (parameter uri).
*/
PUBLIC BOOL HTMKCOLAbsolute (HTRequest * request,
const char * uri,
HTDAVHeaders * headers) {
if (request && uri && *uri) {
HTAnchor *dst = HTAnchor_findAddress (uri);
return HTMKCOLAnchor (request,dst,headers);
}
return NO;
}
/*
** This MKCOL request tries to create the resource indicated
** by a relative URI, which is made absolute by using the
** base anchor.
*/
PUBLIC BOOL HTMKCOLRelative (HTRequest * request,
const char * relative,
HTParentAnchor * base,
HTDAVHeaders * headers) {
BOOL status = NO;
if (request && relative && base) {
char * base_uri = HTAnchor_address ((HTAnchor *)base);
char * full_uri = HTParse (relative,base_uri,PARSE_ACCESS|PARSE_HOST| \
PARSE_PATH|PARSE_PUNCTUATION);
status = HTMKCOLAbsolute (request,full_uri,headers);
HT_FREE (full_uri);
HT_FREE (base_uri);
}
return status;
}
/* --------------------------------------------------------------------------*/
/* COPY REQUESTS */
/* --------------------------------------------------------------------------*/
/*
** COPY Requests
** COPY requests copies the Request-URI resource (indicated by the parameter
** HTAnchor *src) to the resource indicated by the Destination header (it must
** be set in HTDAVHeaders object - so, this object must NOT be NULL).
** A xml message body may also be set, with the propertybehavior xml element,
** which indicates what should be the server behavior when copying the resouce
** properties.
** Headers:
** Destination header is mandatory!
** If header may be used.
** Depth header may be "0" or "infinity"
** Overwrite header may be used
*/
PUBLIC BOOL HTCOPYDocumentAnchor (HTRequest * request,
HTAnchor * src,
HTParentAnchor * xmlbody,
HTDAVHeaders * headers) {
if (request && src && headers) {
/* set method and request-URI */
HTRequest_setMethod (request,METHOD_COPY);
HTRequest_setAnchor (request,src);
HTTRACE (PROT_TRACE,"HTDAV.... Method set to COPY\n");
/* set headers */
HTTRACE (PROT_TRACE,"HTDAV.... Seting default Headers \n");
HTRequest_addCacheControl (request,"no-cache","");
HTRequest_addGnHd (request,HT_G_PRAGMA_NO_CACHE);
/* WebDAV specific headers - Destination is mandatory! */
if (headers->Destination && *headers->Destination) {
HTTRACE (PROT_TRACE,"HTDAV.... Setting WebDAV headers \n");
HTRequest_addExtraHeader (request,"Destination",headers->Destination);
if (headers->If) /* If header may be used */
HTRequest_addExtraHeader (request,"If",headers->If);
if (headers->Overwrite != ' ') {
char over[] = { headers->Overwrite, '\0' };
HTRequest_addExtraHeader (request,"Overwirte", over );
}
if (headers->Depth) {
if (!strcasecomp (headers->Depth,"0") ||
!strcasecomp (headers->Depth,"infinity"))
HTRequest_addExtraHeader (request,"Depth",headers->Depth);
}
}
else return NO;
/* set body - if there is a body */
if (xmlbody) {
HTTRACE (PROT_TRACE,"HTDAV.... Setting Entity Body \n");
HTRequest_setEntityAnchor (request,xmlbody);
HTRequest_setPostCallback (request, HTEntity_callback);
}
return HTLoad (request,NO);
}
return NO;
}
PUBLIC BOOL HTCOPYAnchor (HTRequest * request,
HTAnchor * src,
const char * xmlbody,
HTDAVHeaders * headers) {
if (request && src && headers) {
HTParentAnchor * body = NULL;
if (xmlbody) {
body = HTTmpAnchor(NULL);
HTAnchor_setDocument (body, (void *)xmlbody);
HTAnchor_setFormat (body, HTAtom_for ("text/xml"));
HTAnchor_setLength (body, strlen(xmlbody));
}
return HTCOPYDocumentAnchor (request,src,body,headers);
}
return NO;
}
/*
** This COPY request copies the resource indicated by an absolute URI
** (parameter uri) to the URI in Destination header.
*/
PUBLIC BOOL HTCOPYAbsolute (HTRequest * request,
const char * uri,
const char * xmlbody,
HTDAVHeaders * headers) {
if (request && uri && *uri && headers) {
HTAnchor *src = HTAnchor_findAddress (uri);
return HTCOPYAnchor (request,src,xmlbody,headers);
}
return NO;
}
/*
** This COPY request copies the resource indicated by a relative URI,
** which is made absolute by using the base anchor.
*/
PUBLIC BOOL HTCOPYRelative (HTRequest * request,
const char * relative,
HTParentAnchor * base,
const char * xmlbody,
HTDAVHeaders * headers) {
BOOL status = NO;
if (request && relative && base && headers) {
char * base_uri = HTAnchor_address ((HTAnchor *)base);
char * full_uri = HTParse (relative,base_uri,PARSE_ACCESS|PARSE_HOST| \
PARSE_PATH|PARSE_PUNCTUATION);
status = HTCOPYAbsolute (request,full_uri,xmlbody,headers);
HT_FREE (full_uri);
HT_FREE (base_uri);
}
return status;
}
/* --------------------------------------------------------------------------*/
/* MOVE REQUESTS */
/* --------------------------------------------------------------------------*/
/*
** MOVE Requests
** MOVE requests moves the Request-URI resource (indicated by the parameter
** HTAnchor *src) to the resource indicated by the Destination header (it must
** be set in HTDAVHeaders object - so, this object must NOT be NULL).
** A xml message body may also be set, with the propertybehavior xml element,
** which indicates what should be the server behavior when copying the resouce
** properties.
** Headers:
** Destination header is mandatory!
** If header may be used.
** Depth header may be "0" or "infinity" (for collections, it MUST be "infinity")
** Overwrite header may be used
*/
PUBLIC BOOL HTMOVEDocumentAnchor (HTRequest * request,
HTAnchor * src,
HTParentAnchor * xmlbody,
HTDAVHeaders * headers) {
if (request && src && headers) {
/* set method and request-URI */
HTRequest_setMethod (request,METHOD_MOVE);
HTRequest_setAnchor (request,src);
HTTRACE (PROT_TRACE,"HTDAV.... Method set to MOVE\n");
/* set headers */
HTTRACE (PROT_TRACE,"HTDAV.... Seting default Headers \n");
HTRequest_addCacheControl (request,"no-cache","");
HTRequest_addGnHd (request,HT_G_PRAGMA_NO_CACHE);
/* WebDAV specific headers - Destination is mandatory! */
if (headers->Destination && *headers->Destination) {
HTTRACE (PROT_TRACE,"HTDAV.... Setting WebDAV headers \n");
HTRequest_addExtraHeader (request,"Destination",headers->Destination);
if (headers->If) /* If header may be used */
HTRequest_addExtraHeader (request,"If",headers->If);
if (headers->Overwrite != ' ') {
char over[] = { headers->Overwrite, '\0' };
HTRequest_addExtraHeader (request,"Overwirte", over );
}
if (headers->Depth) {
if (!strcasecomp (headers->Depth,"0") ||
!strcasecomp (headers->Depth,"infinity"))
HTRequest_addExtraHeader(request,"Depth",headers->Depth);
}
}
else return NO;
/* set body - if there is a body */
if (xmlbody) {
HTTRACE (PROT_TRACE,"HTDAV.... Setting Entity Body \n");
HTRequest_setEntityAnchor (request,xmlbody);
HTRequest_setPostCallback (request,HTEntity_callback);
}
return HTLoad (request,NO);
}
return NO;
}
PUBLIC BOOL HTMOVEAnchor (HTRequest * request,
HTAnchor * src,
const char * xmlbody,
HTDAVHeaders * headers) {
if (request && src && headers) {
HTParentAnchor * body = NULL;
if (xmlbody) {
body = HTTmpAnchor (NULL);
HTAnchor_setDocument(body, (void *) xmlbody);
HTAnchor_setFormat (body, HTAtom_for ("text/xml"));
HTAnchor_setLength (body, strlen(xmlbody));
}
return HTMOVEDocumentAnchor (request,src,body,headers);
}
return NO;
}
/*
** This MOVE request moves the resource indicated by an absolute URI
** (parameter uri) to the URI in Destination header.
*/
PUBLIC BOOL HTMOVEAbsolute (HTRequest * request,
const char * uri,
const char * xmlbody,
HTDAVHeaders * headers) {
if (request && uri && *uri && headers) {
HTAnchor *src = HTAnchor_findAddress (uri);
return HTMOVEAnchor (request,src,xmlbody,headers);
}
return NO;
}
/*
** This MOVE request moves the resource indicated by a relative URI,
** which is made absolute by using the base anchor.
*/
PUBLIC BOOL HTMOVERelative (HTRequest * request,
const char * relative,
HTParentAnchor * base,
const char * xmlbody,
HTDAVHeaders * headers) {
BOOL status = NO;
if (request && relative && base && headers) {
char * base_uri = HTAnchor_address ((HTAnchor *)base);
char * full_uri = HTParse (relative,base_uri,PARSE_ACCESS|PARSE_HOST| \
PARSE_PATH|PARSE_PUNCTUATION);
status = HTMOVEAbsolute (request,full_uri,xmlbody,headers);
HT_FREE (full_uri);
HT_FREE (base_uri);
}
return status;
}
#endif /* HT_DAV */
Webmaster