$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.
1998-12-03 Nathan Bryant <bryant@cs.usm.maine.edu>
* webserver.c: warning fix
-
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 \
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:
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 *);
--- /dev/null
+/*
+ * $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;
+}
/*
- * 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];
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);
+ }
}
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.
*/
}
/*
- * 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;
}