* Implemented the GroupDAV DELETE method.
authorArt Cancro <ajc@citadel.org>
Sat, 29 Jan 2005 03:59:25 +0000 (03:59 +0000)
committerArt Cancro <ajc@citadel.org>
Sat, 29 Jan 2005 03:59:25 +0000 (03:59 +0000)
webcit/ChangeLog
webcit/Makefile.in
webcit/groupdav.h
webcit/groupdav_delete.c [new file with mode: 0644]
webcit/groupdav_get.c
webcit/groupdav_main.c

index 7d5b649ceb4fe428ae3f9c846a7ad0902a12411d..08fc1a0afb1a342b8f737a6e312332481ec7a895 100644 (file)
@@ -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 <ajc@uncnsrd.mt-kisco.ny.us>
 
 1998-12-03 Nathan Bryant <bryant@cs.usm.maine.edu>
        * webserver.c: warning fix
-
index 212ae266d07047a93399c0008a8b60bd656ae278..19418051931c216165d9a2f6c8d1279c80bd440c 100644 (file)
@@ -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:
index 2fce1ac73e46588834031d9ec72f5c7c506ae06b..36083327abaf27be57e699cf9a0fb396f9c46e49 100644 (file)
@@ -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 (file)
index 0000000..c75fcd9
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * $Id$
+ *
+ * Handles GroupDAV DELETE requests.
+ *
+ */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <limits.h>
+#include <string.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <time.h>
+#include <pthread.h>
+#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;
+}
index b61ffae83db59074f650061e1300cc157ba0ed9f..9e6edc51445dfa5f85ea70f554082b062e19748d 100644 (file)
@@ -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];
index 54554897926e3adbbff8a5fd8e8bbd189812418a..1473d55196d06422105879422b5e67ea4a8da2d1 100644 (file)
@@ -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;
        }