groupdav_put.c

00001 /*
00002  * $Id: groupdav_put.c 5147 2007-05-08 15:36:22Z ajc $
00003  *
00004  * Handles GroupDAV PUT requests.
00005  *
00006  */
00007 
00008 #include "webcit.h"
00009 #include "webserver.h"
00010 #include "groupdav.h"
00011 
00012 
00013 /*
00014  * This function is for uploading an ENTIRE calendar, not just one
00015  * component.  This would be for webcal:// 'publish' operations, not
00016  * for GroupDAV.
00017  */
00018 void groupdav_put_bigics(char *dav_content, int dav_content_length)
00019 {
00020         char buf[1024];
00021 
00022         serv_puts("ICAL putics");
00023         serv_getln(buf, sizeof buf);
00024         if (buf[0] != '4') {
00025                 wprintf("HTTP/1.1 502 Bad Gateway\r\n");
00026                 groupdav_common_headers();
00027                 wprintf("Content-type: text/plain\r\n"
00028                         "\r\n"
00029                         "%s\r\n", &buf[4]
00030                 );
00031                 return;
00032         }
00033 
00034         serv_write(dav_content, dav_content_length);
00035         serv_printf("\n000");
00036 
00037         /* Report success and not much else. */
00038         wprintf("HTTP/1.1 204 No Content\r\n");
00039         lprintf(9, "HTTP/1.1 204 No Content\r\n");
00040         groupdav_common_headers();
00041         wprintf("Content-Length: 0\r\n\r\n");
00042 }
00043 
00044 
00045 
00046 /*
00047  * The pathname is always going to take one of two formats:
00048  * /groupdav/room_name/euid     (GroupDAV)
00049  * /groupdav/room_name          (webcal)
00050  */
00051 void groupdav_put(char *dav_pathname, char *dav_ifmatch,
00052                 char *dav_content_type, char *dav_content,
00053                 int dav_content_length
00054 ) {
00055         char dav_roomname[1024];
00056         char dav_uid[1024];
00057         long new_msgnum = (-2L);
00058         long old_msgnum = (-1L);
00059         char buf[SIZ];
00060         int n = 0;
00061 
00062         if (num_tokens(dav_pathname, '/') < 3) {
00063                 wprintf("HTTP/1.1 404 not found\r\n");
00064                 groupdav_common_headers();
00065                 wprintf(
00066                         "Content-Type: text/plain\r\n"
00067                         "\r\n"
00068                         "The object you requested was not found.\r\n"
00069                 );
00070                 return;
00071         }
00072 
00073         extract_token(dav_roomname, dav_pathname, 2, '/', sizeof dav_roomname);
00074         extract_token(dav_uid, dav_pathname, 3, '/', sizeof dav_uid);
00075         if ((!strcasecmp(dav_uid, "ics")) || (!strcasecmp(dav_uid, "calendar.ics"))) {
00076                 strcpy(dav_uid, "");
00077         }
00078 
00079         /* Go to the correct room. */
00080         if (strcasecmp(WC->wc_roomname, dav_roomname)) {
00081                 gotoroom(dav_roomname);
00082         }
00083         if (strcasecmp(WC->wc_roomname, dav_roomname)) {
00084                 wprintf("HTTP/1.1 404 not found\r\n");
00085                 groupdav_common_headers();
00086                 wprintf(
00087                         "Content-Type: text/plain\r\n"
00088                         "\r\n"
00089                         "There is no folder called \"%s\" on this server.\r\n",
00090                         dav_roomname
00091                 );
00092                 return;
00093         }
00094 
00095         /*
00096          * If an HTTP If-Match: header is present, the client is attempting
00097          * to replace an existing item.  We have to check to see if the
00098          * message number associated with the supplied uid matches what the
00099          * client is expecting.  If not, the server probably contains a newer
00100          * version, so we fail...
00101          */
00102         if (strlen(dav_ifmatch) > 0) {
00103                 lprintf(9, "dav_ifmatch: %s\n", dav_ifmatch);
00104                 old_msgnum = locate_message_by_uid(dav_uid);
00105                 lprintf(9, "old_msgnum:  %ld\n", old_msgnum);
00106                 if (atol(dav_ifmatch) != old_msgnum) {
00107                         wprintf("HTTP/1.1 412 Precondition Failed\r\n");
00108                         lprintf(9, "HTTP/1.1 412 Precondition Failed (ifmatch=%ld, old_msgnum=%ld)\r\n",
00109                                 atol(dav_ifmatch), old_msgnum);
00110                         groupdav_common_headers();
00111                         wprintf("Content-Length: 0\r\n\r\n");
00112                         return;
00113                 }
00114         }
00115 
00118         if (!strcasecmp(dav_uid, "")) {
00119                 groupdav_put_bigics(dav_content, dav_content_length);
00120                 return;
00121         }
00122 
00123         /*
00124          * We are cleared for upload!  We use the new calling syntax for ENT0
00125          * which allows a confirmation to be sent back to us.  That's how we
00126          * extract the message ID.
00127          */
00128         serv_puts("ENT0 1|||4|||1|");
00129         serv_getln(buf, sizeof buf);
00130         if (buf[0] != '8') {
00131                 wprintf("HTTP/1.1 502 Bad Gateway\r\n");
00132                 groupdav_common_headers();
00133                 wprintf("Content-type: text/plain\r\n"
00134                         "\r\n"
00135                         "%s\r\n", &buf[4]
00136                 );
00137                 return;
00138         }
00139 
00140         /* Send the content to the Citadel server */
00141         serv_printf("Content-type: %s\n\n", dav_content_type);
00142         serv_puts(dav_content);
00143         serv_puts("\n000");
00144 
00145         /* Fetch the reply from the Citadel server */
00146         n = 0;
00147         strcpy(dav_uid, "");
00148         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
00149                 switch(n++) {
00150                         case 0: new_msgnum = atol(buf);
00151                                 break;
00152                         case 1: lprintf(9, "new_msgnum=%ld (%s)\n", new_msgnum, buf);
00153                                 break;
00154                         case 2: strcpy(dav_uid, buf);
00155                                 break;
00156                         default:
00157                                 break;
00158                 }
00159         }
00160 
00161         /* Tell the client what happened. */
00162 
00163         /* Citadel failed in some way? */
00164         if (new_msgnum < 0L) {
00165                 wprintf("HTTP/1.1 502 Bad Gateway\r\n");
00166                 groupdav_common_headers();
00167                 wprintf("Content-type: text/plain\r\n"
00168                         "\r\n"
00169                         "new_msgnum is %ld\r\n"
00170                         "\r\n", new_msgnum
00171                 );
00172                 return;
00173         }
00174 
00175         /* We created this item for the first time. */
00176         if (old_msgnum < 0L) {
00177                 wprintf("HTTP/1.1 201 Created\r\n");
00178                 lprintf(9, "HTTP/1.1 201 Created\r\n");
00179                 groupdav_common_headers();
00180                 wprintf("etag: \"%ld\"\r\n", new_msgnum);
00181                 wprintf("Content-Length: 0\r\n");
00182                 wprintf("Location: ");
00183                 groupdav_identify_host();
00184                 wprintf("/groupdav/");
00185                 urlescputs(dav_roomname);
00186                 wprintf("/%s\r\n", dav_uid);
00187                 wprintf("\r\n");
00188                 return;
00189         }
00190 
00191         /* We modified an existing item. */
00192         wprintf("HTTP/1.1 204 No Content\r\n");
00193         lprintf(9, "HTTP/1.1 204 No Content\r\n");
00194         groupdav_common_headers();
00195         wprintf("etag: \"%ld\"\r\n", new_msgnum);
00196         wprintf("Content-Length: 0\r\n\r\n");
00197 
00198         /* The item we replaced has probably already been deleted by
00199          * the Citadel server, but we'll do this anyway, just in case.
00200          */
00201         serv_printf("DELE %ld", old_msgnum);
00202         serv_getln(buf, sizeof buf);
00203 
00204         return;
00205 }

Generated on Wed Jun 20 23:13:08 2007 for webcit by  doxygen 1.5.2