From 9a7542729c71498086c105eb416fb172e574574c Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Sat, 29 Jan 2005 03:59:25 +0000 Subject: [PATCH] * Implemented the GroupDAV DELETE method. --- webcit/ChangeLog | 4 +- webcit/Makefile.in | 3 +- webcit/groupdav.h | 1 + webcit/groupdav_delete.c | 107 +++++++++++++++++++++++++++++++++++++++ webcit/groupdav_get.c | 2 +- webcit/groupdav_main.c | 38 ++++++++++++-- 6 files changed, 149 insertions(+), 6 deletions(-) create mode 100644 webcit/groupdav_delete.c diff --git a/webcit/ChangeLog b/webcit/ChangeLog index 7d5b649ce..08fc1a0af 100644 --- a/webcit/ChangeLog +++ b/webcit/ChangeLog @@ -1,4 +1,7 @@ $Log$ +Revision 528.26 2005/01/29 03:59:25 ajc +* Implemented the GroupDAV DELETE method. + Revision 528.25 2005/01/28 05:25:43 ajc * iconbar no longer uses the beginbox/endbox semantics, but instead lives directly inside the iconbar div. @@ -2251,4 +2254,3 @@ Sun Dec 6 19:50:55 EST 1998 Art Cancro 1998-12-03 Nathan Bryant * webserver.c: warning fix - diff --git a/webcit/Makefile.in b/webcit/Makefile.in index 212ae266d..194180519 100644 --- a/webcit/Makefile.in +++ b/webcit/Makefile.in @@ -38,6 +38,7 @@ webserver: webserver.o context_loop.o tools.o ical_dezonify.o \ calendar.o calendar_tools.o calendar_view.o event.o \ availability.o iconbar.o crypto.o inetconf.o notes.o \ groupdav_main.o groupdav_get.o groupdav_propfind.o \ + groupdav_delete.o \ $(LIBOBJS) $(CC) webserver.o context_loop.o tools.o cookie_conversion.o \ webcit.o auth.o tcp_sockets.o mainmenu.o serv_func.o who.o listsub.o \ @@ -46,7 +47,7 @@ webserver: webserver.o context_loop.o tools.o ical_dezonify.o \ mime_parser.o graphics.o netconf.o preferences.o html2html.o \ summary.o calendar.o calendar_tools.o calendar_view.o event.o \ availability.o ical_dezonify.o iconbar.o crypto.o inetconf.o notes.o \ - groupdav_main.o groupdav_get.o groupdav_propfind.o \ + groupdav_main.o groupdav_get.o groupdav_propfind.o groupdav_delete.o \ $(LIBOBJS) $(LIBS) $(LDFLAGS) -o webserver .c.o: diff --git a/webcit/groupdav.h b/webcit/groupdav.h index 2fce1ac73..36083327a 100644 --- a/webcit/groupdav.h +++ b/webcit/groupdav.h @@ -3,5 +3,6 @@ void groupdav_common_headers(void); void groupdav_main(struct httprequest *); void groupdav_get(char *); +void groupdav_delete(char *, char *); void groupdav_propfind(char *); long locate_message_by_uid(char *); diff --git a/webcit/groupdav_delete.c b/webcit/groupdav_delete.c new file mode 100644 index 000000000..c75fcd90f --- /dev/null +++ b/webcit/groupdav_delete.c @@ -0,0 +1,107 @@ +/* + * $Id$ + * + * Handles GroupDAV DELETE requests. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "webcit.h" +#include "webserver.h" +#include "groupdav.h" + + +/* + * The pathname is always going to be /groupdav/room_name/euid + */ +void groupdav_delete(char *dav_pathname, char *dav_ifmatch) { + char dav_roomname[SIZ]; + char dav_uid[SIZ]; + long dav_msgnum = (-1); + char buf[SIZ]; + int found_content_type = 0; + int n = 0; + + /* First, break off the "/groupdav/" prefix */ + remove_token(dav_pathname, 0, '/'); + remove_token(dav_pathname, 0, '/'); + + /* Now extract the message euid */ + n = num_tokens(dav_pathname, '/'); + extract_token(dav_uid, dav_pathname, n-1, '/'); + remove_token(dav_pathname, n-1, '/'); + + /* What's left is the room name. Remove trailing slashes. */ + if (dav_pathname[strlen(dav_pathname)-1] == '/') { + dav_pathname[strlen(dav_pathname)-1] = 0; + } + strcpy(dav_roomname, dav_pathname); + + /* Go to the correct room. */ + if (strcasecmp(WC->wc_roomname, dav_roomname)) { + gotoroom(dav_roomname); + } + if (strcasecmp(WC->wc_roomname, dav_roomname)) { + wprintf("HTTP/1.1 404 not found\n"); + groupdav_common_headers(); + wprintf("Content-Length: 0\n\n"); + return; + } + + dav_msgnum = locate_message_by_uid(dav_uid); + + /* + * If no item exists with the requested uid ... simple error. + */ + if (dav_msgnum < 0L) { + wprintf("HTTP/1.1 404 Not Found\n"); + groupdav_common_headers(); + wprintf("Content-Length: 0\n\n"); + return; + } + + /* + * It's there ... check the ETag and make sure it matches + * the message number. + */ + if (strlen(dav_ifmatch) > 0) { + if (atol(dav_ifmatch) != dav_msgnum) { + wprintf("HTTP/1.1 412 Precondition Failed\n"); + groupdav_common_headers(); + wprintf("Content-Length: 0\n\n"); + return; + } + } + + /* + * Ok, attempt to delete the item. + */ + serv_printf("DELE %ld", dav_msgnum); + serv_gets(buf); + if (buf[0] == '2') { + wprintf("HTTP/1.1 204 No Content\n"); /* success */ + groupdav_common_headers(); + wprintf("Content-Length: 0\n\n"); + } + else { + wprintf("HTTP/1.1 403 Forbidden\n"); /* access denied */ + groupdav_common_headers(); + wprintf("Content-Length: 0\n\n"); + } + return; +} diff --git a/webcit/groupdav_get.c b/webcit/groupdav_get.c index b61ffae83..9e6edc514 100644 --- a/webcit/groupdav_get.c +++ b/webcit/groupdav_get.c @@ -27,7 +27,7 @@ /* - * The pathname is always going to be /groupdav/room_name/msg_num + * The pathname is always going to be /groupdav/room_name/euid */ void groupdav_get(char *dav_pathname) { char dav_roomname[SIZ]; diff --git a/webcit/groupdav_main.c b/webcit/groupdav_main.c index 545548979..1473d5519 100644 --- a/webcit/groupdav_main.c +++ b/webcit/groupdav_main.c @@ -46,12 +46,20 @@ void groupdav_main(struct httprequest *req) { struct httprequest *rptr; char dav_method[SIZ]; char dav_pathname[SIZ]; + char dav_ifmatch[SIZ]; + + strcpy(dav_method, ""); + strcpy(dav_pathname, ""); + strcpy(dav_ifmatch, ""); for (rptr=req; rptr!=NULL; rptr=rptr->next) { lprintf(9, "> %s\n", rptr->line); /* FIXME we can eventually remove this trace */ if (!strncasecmp(rptr->line, "Host: ", 6)) { safestrncpy(WC->http_host, &rptr->line[6], sizeof WC->http_host); } + if (!strncasecmp(rptr->line, "If-Match: ", 10)) { + safestrncpy(dav_ifmatch, &rptr->line[10], sizeof dav_ifmatch); + } } @@ -69,6 +77,30 @@ void groupdav_main(struct httprequest *req) { extract_token(dav_pathname, req->line, 1, ' '); unescape_input(dav_pathname); + /* + * If there's an If-Match: header, strip out the quotes if present, and + * then if all that's left is an asterisk, make it go away entirely. + */ + if (strlen(dav_ifmatch) > 0) { + if (dav_ifmatch[0] == '\"') { + strcpy(dav_ifmatch, &dav_ifmatch[1]); + if (strtok(dav_ifmatch, "\"") != NULL) { + strcpy(strtok(dav_ifmatch, "\""), ""); + } + } + if (!strcmp(dav_ifmatch, "*")) { + strcpy(dav_ifmatch, ""); + } + } + + /* + * The PROPFIND method is basically used to list all objects in a room. + */ + if (!strcasecmp(dav_method, "PROPFIND")) { + groupdav_propfind(dav_pathname); + return; + } + /* * We like the GET method ... it's nice and simple. */ @@ -78,10 +110,10 @@ void groupdav_main(struct httprequest *req) { } /* - * The PROPFIND method is basically used to list all objects in a room. + * The DELETE method kills, maims, and destroys. */ - if (!strcasecmp(dav_method, "PROPFIND")) { - groupdav_propfind(dav_pathname); + if (!strcasecmp(dav_method, "DELETE")) { + groupdav_delete(dav_pathname, dav_ifmatch); return; } -- 2.39.2