Back to index

webcit  8.12-dfsg
dav_get.c
Go to the documentation of this file.
00001 /*
00002  * Handles GroupDAV GET requests.
00003  *
00004  * Copyright (c) 2005-2012 by the citadel.org team
00005  *
00006  * This program is open source software.  You can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License, version 3.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  */
00014 
00015 #include "webcit.h"
00016 #include "webserver.h"
00017 #include "dav.h"
00018 
00019 
00020 /*
00021  * Fetch the entire contents of the room as one big ics file.
00022  * This is for "webcal://" type access.
00023  */    
00024 void dav_get_big_ics(void) {
00025        char buf[1024];
00026 
00027        serv_puts("ICAL getics");
00028        serv_getln(buf, sizeof buf);
00029        if (buf[0] != '1') {
00030               hprintf("HTTP/1.1 404 not found\r\n");
00031               dav_common_headers();
00032               hprintf("Content-Type: text/plain\r\n");
00033               begin_burst();
00034               wc_printf("%s\r\n",
00035                      &buf[4]
00036                      );
00037               end_burst();
00038               return;
00039        }
00040 
00041        hprintf("HTTP/1.1 200 OK\r\n");
00042        dav_common_headers();
00043        hprintf("Content-type: text/calendar; charset=UTF-8\r\n");
00044        begin_burst();
00045        while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
00046               wc_printf("%s\r\n", buf);
00047        }
00048        end_burst();
00049 }
00050 
00051 
00052 /* 
00053  * MIME parser callback function for dav_get()
00054  * Helps identify the relevant section of a multipart message
00055  */
00056 void extract_preferred(char *name, char *filename, char *partnum, char *disp,
00057                      void *content, char *cbtype, char *cbcharset,
00058                      size_t length, char *encoding, char *cbid, void *userdata)
00059 {
00060        struct epdata *epdata = (struct epdata *)userdata;
00061        int hit = 0;
00062 
00063        /* We only want the first one that we found */
00064        if (!IsEmptyStr(epdata->found_section)) return;
00065 
00066        /* Check for a content type match */
00067        if (strlen(epdata->desired_content_type_1) > 0) {
00068               if (!strcasecmp(epdata->desired_content_type_1, cbtype)) {
00069                      hit = 1;
00070               }
00071        }
00072        if (!IsEmptyStr(epdata->desired_content_type_2)) {
00073               if (!strcasecmp(epdata->desired_content_type_2, cbtype)) {
00074                      hit = 1;
00075               }
00076        }
00077 
00078        /* Is this the one?  If so, output it. */
00079        if (hit) {
00080               safestrncpy(epdata->found_section, partnum, sizeof epdata->found_section);
00081               if (!IsEmptyStr(cbcharset)) {
00082                      safestrncpy(epdata->charset, cbcharset, sizeof epdata->charset);
00083               }
00084               hprintf("Content-type: %s; charset=%s\r\n", cbtype, epdata->charset);
00085               begin_burst();
00086               StrBufAppendBufPlain(WC->WBuf, content, length, 0);
00087               end_burst();
00088        }
00089 }
00090 
00091 
00092 
00093 /*
00094  * The pathname is always going to take one of two formats:
00095  * /groupdav/room_name/euid (GroupDAV)
00096  * /groupdav/room_name             (webcal)
00097  */
00098 void dav_get(void)
00099 {
00100        wcsession *WCC = WC;
00101        StrBuf *dav_roomname;
00102        StrBuf *dav_uid;
00103        long dav_msgnum = (-1);
00104        char buf[1024];
00105        int in_body = 0;
00106        char *ptr;
00107        char *endptr;
00108        char *msgtext = NULL;
00109        size_t msglen = 0;
00110        size_t msgalloc = 0;
00111        int linelen;
00112        char content_type[128];
00113        char charset[128];
00114        char date[128];
00115        struct epdata epdata;
00116 
00117        if (StrBufNum_tokens(WCC->Hdr->HR.ReqLine, '/') < 2) {
00118               hprintf("HTTP/1.1 404 not found\r\n");
00119               dav_common_headers();
00120               hprintf("Content-Type: text/plain\r\n");
00121               wc_printf("The object you requested was not found.\r\n");
00122               end_burst();
00123               return;
00124        }
00125 
00126        dav_roomname = NewStrBuf();;
00127        dav_uid = NewStrBuf();;
00128        StrBufExtract_token(dav_roomname, WCC->Hdr->HR.ReqLine, 0, '/');
00129        StrBufExtract_token(dav_uid, WCC->Hdr->HR.ReqLine, 1, '/');
00130        if ((!strcasecmp(ChrPtr(dav_uid), "ics")) || 
00131            (!strcasecmp(ChrPtr(dav_uid), "calendar.ics"))) {
00132               FlushStrBuf(dav_uid);
00133        }
00134 
00135        /* Go to the correct room. */
00136        if (strcasecmp(ChrPtr(WCC->CurRoom.name), ChrPtr(dav_roomname))) {
00137               gotoroom(dav_roomname);
00138        }
00139        if (strcasecmp(ChrPtr(WCC->CurRoom.name), ChrPtr(dav_roomname))) {
00140               hprintf("HTTP/1.1 404 not found\r\n");
00141               dav_common_headers();
00142               hprintf("Content-Type: text/plain\r\n");
00143               wc_printf("There is no folder called \"%s\" on this server.\r\n",
00144                      ChrPtr(dav_roomname));
00145               end_burst();
00146               FreeStrBuf(&dav_roomname);
00147               FreeStrBuf(&dav_uid);
00148               return;
00149        }
00150 
00153        if (StrLength(dav_uid) == 0) {
00154               dav_get_big_ics();
00155               FreeStrBuf(&dav_roomname);
00156               FreeStrBuf(&dav_uid);
00157               return;
00158        }
00159 
00160        dav_msgnum = locate_message_by_uid(ChrPtr(dav_uid));
00161        serv_printf("MSG2 %ld", dav_msgnum);
00162        serv_getln(buf, sizeof buf);
00163        if (buf[0] != '1') {
00164               hprintf("HTTP/1.1 404 not found\r\n");
00165               dav_common_headers();
00166               hprintf("Content-Type: text/plain\r\n");
00167               wc_printf("Object \"%s\" was not found in the \"%s\" folder.\r\n",
00168                      ChrPtr(dav_uid),
00169                      ChrPtr(dav_roomname));
00170               end_burst();
00171               FreeStrBuf(&dav_roomname);
00172               FreeStrBuf(&dav_uid);
00173               return;
00174        }
00175        FreeStrBuf(&dav_roomname);
00176        FreeStrBuf(&dav_uid);
00177 
00178        /* We got it; a message is now arriving from the server.  Read it in. */
00179 
00180        in_body = 0;
00181        strcpy(charset, "UTF-8");
00182        strcpy(content_type, "text/plain");
00183        strcpy(date, "");
00184        while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
00185               linelen = strlen(buf);
00186 
00187               /* Append it to the buffer */
00188               if ((msglen + linelen + 3) > msgalloc) {
00189                      msgalloc = ( (msgalloc > 0) ? (msgalloc * 2) : 1024 );
00190                      msgtext = realloc(msgtext, msgalloc);
00191               }
00192               strcpy(&msgtext[msglen], buf);
00193               msglen += linelen;
00194               strcpy(&msgtext[msglen], "\n");
00195               msglen += 1;
00196 
00197               /* Also learn some things about the message */
00198               if (linelen == 0) {
00199                      in_body = 1;
00200               }
00201               if (!in_body) {
00202                      if (!strncasecmp(buf, "Date:", 5)) {
00203                             safestrncpy(date, &buf[5], sizeof date);
00204                             striplt(date);
00205                      }
00206                      if (!strncasecmp(buf, "Content-type:", 13)) {
00207                             safestrncpy(content_type, &buf[13], sizeof content_type);
00208                             striplt(content_type);
00209                             ptr = bmstrcasestr(&buf[13], "charset=");
00210                             if (ptr) {
00211                                    safestrncpy(charset, ptr+8, sizeof charset);
00212                                    striplt(charset);
00213                                    endptr = strchr(charset, ';');
00214                                    if (endptr != NULL) strcpy(endptr, "");
00215                             }
00216                             endptr = strchr(content_type, ';');
00217                             if (endptr != NULL) strcpy(endptr, "");
00218                      }
00219               }
00220        }
00221        msgtext[msglen] = 0;
00222 
00223        /* Output headers common to single or multi part messages */
00224 
00225        hprintf("HTTP/1.1 200 OK\r\n");
00226        dav_common_headers();
00227        hprintf("etag: \"%ld\"\r\n", dav_msgnum);
00228        hprintf("Date: %s\r\n", date);
00229 
00230        memset(&epdata, 0, sizeof(struct epdata));
00231        safestrncpy(epdata.charset, charset, sizeof epdata.charset);
00232 
00233        /* If we have a multipart message on our hands, and we are in a groupware room,
00234         * strip it down to only the relevant part.
00235         */
00236        if (!strncasecmp(content_type, "multipart/", 10)) {
00237 
00238               if ( (WCC->CurRoom.defview == VIEW_CALENDAR) || (WCC->CurRoom.defview == VIEW_TASKS) ) {
00239                      strcpy(epdata.desired_content_type_1, "text/calendar");
00240               }
00241 
00242               else if (WCC->CurRoom.defview == VIEW_ADDRESSBOOK) {
00243                      strcpy(epdata.desired_content_type_1, "text/vcard");
00244                      strcpy(epdata.desired_content_type_2, "text/x-vcard");
00245               }
00246 
00247               mime_parser(msgtext, &msgtext[msglen], extract_preferred, NULL, NULL, (void *)&epdata, 0);
00248        }
00249 
00250        /* If epdata.found_section is empty, we haven't output anything yet, so output the whole thing */
00251 
00252        if (IsEmptyStr(epdata.found_section)) {
00253               ptr = msgtext;
00254               endptr = &msgtext[msglen];
00255        
00256               hprintf("Content-type: %s; charset=%s\r\n", content_type, charset);
00257        
00258               in_body = 0;
00259               do {
00260                      ptr = memreadline(ptr, buf, sizeof buf);
00261        
00262                      if (in_body) {
00263                             wc_printf("%s\r\n", buf);
00264                      }
00265                      else if ((buf[0] == 0) && (in_body == 0)) {
00266                             in_body = 1;
00267                             begin_burst();
00268                      }
00269               } while (ptr < endptr);
00270        
00271               end_burst();
00272        }
00273 
00274        free(msgtext);
00275 }