X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fdav_main.c;fp=webcit%2Fdav_main.c;h=31cbfafffe1399af58ecc6876a1404b7515c2374;hb=8611acef7ff4213c28ad20ff755d34509870bc96;hp=0000000000000000000000000000000000000000;hpb=76a0f8571de023fe6bd20390174a2302e0a0b982;p=citadel.git diff --git a/webcit/dav_main.c b/webcit/dav_main.c new file mode 100644 index 000000000..31cbfafff --- /dev/null +++ b/webcit/dav_main.c @@ -0,0 +1,357 @@ +/* + * Entry point for GroupDAV functions + * + * Copyright (c) 2005-2012 by the citadel.org team + * + * This program is open source software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "webcit.h" +#include "webserver.h" +#include "dav.h" + +CtxType CTX_DAVNS = CTX_NONE; +extern HashList *HandlerHash; + +HashList *DavNamespaces = NULL; + +/* + * Output HTTP headers which are common to all requests. + * + * Please observe that we don't use the usual output_headers() + * and wDumpContent() functions in the GroupDAV subsystem, so we + * do our own header stuff here. + * + */ +void dav_common_headers(void) { + hprintf( + "Server: %s / %s\r\n" + "Connection: close\r\n", + PACKAGE_STRING, ChrPtr(WC->serv_info->serv_software) + ); +} + + + +/* + * string conversion function + */ +void euid_escapize(char *target, const char *source) { + int i, len; + int target_length = 0; + + strcpy(target, ""); + len = strlen(source); + for (i=0; iHdr->HR.dav_ifmatch); + if (len > 0) { + StrBufTrim(WCC->Hdr->HR.dav_ifmatch); + if (ChrPtr(WCC->Hdr->HR.dav_ifmatch)[0] == '\"') { + StrBufCutLeft(WCC->Hdr->HR.dav_ifmatch, 1); + len --; + for (i=0; iHdr->HR.dav_ifmatch)[i] == '\"') { + StrBufCutAt(WCC->Hdr->HR.dav_ifmatch, i, NULL); + len = StrLength(WCC->Hdr->HR.dav_ifmatch); + } + } + } + if (!strcmp(ChrPtr(WCC->Hdr->HR.dav_ifmatch), "*")) { + FlushStrBuf(WCC->Hdr->HR.dav_ifmatch); + } + } + + switch (WCC->Hdr->HR.eReqType) + { + /* + * The OPTIONS method is not required by GroupDAV but it will be + * needed for future implementations of other DAV-based protocols. + */ + case eOPTIONS: + dav_options(); + break; + + /* + * The PROPFIND method is basically used to list all objects in a + * room, or to list all relevant rooms on the server. + */ + case ePROPFIND: + dav_propfind(); + break; + + /* + * The GET method is used for fetching individual items. + */ + case eGET: + dav_get(); + break; + + /* + * The PUT method is used to add or modify items. + */ + case ePUT: + dav_put(); + break; + + /* + * The DELETE method kills, maims, and destroys. + */ + case eDELETE: + dav_delete(); + break; + + /* + * The REPORT method tells us that Mike Shaver is a self-righteous asshole. + */ + case eREPORT: + dav_report(); + break; + + default: + /* + * Couldn't find what we were looking for. Die in a car fire. + */ + hprintf("HTTP/1.1 501 Method not implemented\r\n"); + dav_common_headers(); + hprintf("Content-Type: text/plain\r\n"); + wc_printf("GroupDAV method \"%s\" is not implemented.\r\n", + ReqStrs[WCC->Hdr->HR.eReqType]); + end_burst(); + } +} + + +/* + * Output our host prefix for globally absolute URL's. + */ +void dav_identify_host(void) { + wc_printf("%s", ChrPtr(site_prefix)); +} + + +void tmplput_dav_HOSTNAME(StrBuf *Target, WCTemplputParams *TP) +{ + StrBufAppendPrintf(Target, "%s", ChrPtr(site_prefix)); +} + +/* + * Output our host prefix for globally absolute URL's. + */ +void dav_identify_hosthdr(void) { + hprintf("%s", ChrPtr(site_prefix)); +} + + +void Header_HandleIfMatch(StrBuf *Line, ParsedHttpHdrs *hdr) +{ + hdr->HR.dav_ifmatch = Line; +} + + +void Header_HandleDepth(StrBuf *Line, ParsedHttpHdrs *hdr) +{ + if (!strcasecmp(ChrPtr(Line), "infinity")) { + hdr->HR.dav_depth = 32767; + } + else if (strcmp(ChrPtr(Line), "0") == 0) { + hdr->HR.dav_depth = 0; + } + else if (strcmp(ChrPtr(Line), "1") == 0) { + hdr->HR.dav_depth = 1; + } +} + + +int Conditional_DAV_DEPTH(StrBuf *Target, WCTemplputParams *TP) +{ + return WC->Hdr->HR.dav_depth == GetTemplateTokenNumber(Target, TP, 2, 0); +} + + +void RegisterDAVNamespace(const char * UrlString, + long UrlSLen, + const char *DisplayName, + long dslen, + WebcitHandlerFunc F, + WebcitRESTDispatchID RID, + long Flags) +{ + void *vHandler; + + /* first put it in... */ + WebcitAddUrlHandler(UrlString, UrlSLen, DisplayName, dslen, F, Flags|PARSE_REST_URL); + /* get it out again... */ + GetHash(HandlerHash, UrlString, UrlSLen, &vHandler); + ((WebcitHandler*)vHandler)->RID = RID; + /* and keep a copy of it, so we can compare it later */ + Put(DavNamespaces, UrlString, UrlSLen, vHandler, reference_free_handler); +} + + +int Conditional_DAV_NS(StrBuf *Target, WCTemplputParams *TP) +{ + wcsession *WCC = WC; + void *vHandler; + const char *NS; + long NSLen; + + GetTemplateTokenString(NULL, TP, 2, &NS, &NSLen); + GetHash(HandlerHash, NS, NSLen, &vHandler); + return WCC->Hdr->HR.Handler == vHandler; +} + + +int Conditional_DAV_NSCURRENT(StrBuf *Target, WCTemplputParams *TP) +{ + wcsession *WCC = WC; + void *vHandler; + + vHandler = CTX(CTX_NONE); + return WCC->Hdr->HR.Handler == vHandler; +} + + +void tmplput_DAV_NAMESPACE(StrBuf *Target, WCTemplputParams *TP) +{ + wcsession *WCC = WC; + + if (TP->Filter.ContextType == CTX_DAVNS) { + WebcitHandler *H; + H = (WebcitHandler*) CTX(CTX_DAVNS); + if (H != NULL) + StrBufAppendTemplate(Target, TP, H->Name, 0); + } + else if (WCC->Hdr->HR.Handler != NULL) { + StrBufAppendTemplate(Target, TP, WCC->Hdr->HR.Handler->Name, 0); + } +} + + +int GroupdavDispatchREST(RESTDispatchID WhichAction, int IgnoreFloor) +{ + wcsession *WCC = WC; + void *vDir; + + switch(WhichAction){ + case ExistsID: + GetHash(WCC->Directory, IKEY(WCC->ThisRoom->nRoomNameParts + 1), &vDir); + return locate_message_by_uid(ChrPtr((StrBuf*)vDir)) != -1; + /* TODO: remember euid */ + case PutID: + case DeleteID: + break; + + + } + return 0; +} + + +void +ServerStartModule_DAV +(void) +{ + + DavNamespaces = NewHash(1, NULL); +} + + +void +ServerShutdownModule_DAV +(void) +{ + DeleteHash(&DavNamespaces); +} + + +void +InitModule_GROUPDAV +(void) +{ + RegisterCTX(CTX_DAVNS); + RegisterDAVNamespace(HKEY("groupdav"), HKEY("GroupDAV"), + dav_main, GroupdavDispatchREST, + XHTTP_COMMANDS|COOKIEUNNEEDED|FORCE_SESSIONCLOSE + ); + + RegisterNamespace("DAV:HOSTNAME", 0, 0, tmplput_dav_HOSTNAME, NULL, CTX_NONE); + + RegisterConditional("COND:DAV:NS", 0, Conditional_DAV_NS, CTX_NONE); + + RegisterIterator("DAV:NS", 0, DavNamespaces, NULL, + NULL, NULL, CTX_DAVNS, CTX_NONE, IT_NOFLAG + ); + + RegisterConditional("COND:DAV:NSCURRENT", 0, Conditional_DAV_NSCURRENT, CTX_DAVNS); + RegisterNamespace("DAV:NAMESPACE", 0, 1, tmplput_DAV_NAMESPACE, NULL, CTX_NONE); + + RegisterHeaderHandler(HKEY("IF-MATCH"), Header_HandleIfMatch); + RegisterHeaderHandler(HKEY("DEPTH"), Header_HandleDepth); + RegisterConditional("COND:DAV:DEPTH", 1, Conditional_DAV_DEPTH, CTX_NONE); +}