2 * Handles GroupDAV GET requests.
4 * Copyright (c) 2005-2010 by the citadel.org team
6 * This program is open source software. You can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 3 of the
9 * License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "webserver.h"
27 * Fetch the entire contents of the room as one big ics file.
28 * This is for "webcal://" type access.
30 void groupdav_get_big_ics(void) {
33 serv_puts("ICAL getics");
34 serv_getln(buf, sizeof buf);
36 hprintf("HTTP/1.1 404 not found\r\n");
37 groupdav_common_headers();
38 hprintf("Content-Type: text/plain\r\n");
47 hprintf("HTTP/1.1 200 OK\r\n");
48 groupdav_common_headers();
49 hprintf("Content-type: text/calendar; charset=UTF-8\r\n");
51 while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
52 wc_printf("%s\r\n", buf);
59 * MIME parser callback function for groupdav_get()
60 * Helps identify the relevant section of a multipart message
62 void extract_preferred(char *name, char *filename, char *partnum, char *disp,
63 void *content, char *cbtype, char *cbcharset,
64 size_t length, char *encoding, char *cbid, void *userdata)
66 struct epdata *epdata = (struct epdata *)userdata;
69 /* We only want the first one that we found */
70 if (!IsEmptyStr(epdata->found_section)) return;
72 /* Check for a content type match */
73 if (strlen(epdata->desired_content_type_1) > 0) {
74 if (!strcasecmp(epdata->desired_content_type_1, cbtype)) {
78 if (!IsEmptyStr(epdata->desired_content_type_2)) {
79 if (!strcasecmp(epdata->desired_content_type_2, cbtype)) {
84 /* Is this the one? If so, output it. */
86 safestrncpy(epdata->found_section, partnum, sizeof epdata->found_section);
87 if (!IsEmptyStr(cbcharset)) {
88 safestrncpy(epdata->charset, cbcharset, sizeof epdata->charset);
90 hprintf("Content-type: %s; charset=%s\r\n", cbtype, epdata->charset);
92 StrBufAppendBufPlain(WC->WBuf, content, length, 0);
100 * The pathname is always going to take one of two formats:
101 * /groupdav/room_name/euid (GroupDAV)
102 * /groupdav/room_name (webcal)
104 void groupdav_get(void)
107 StrBuf *dav_roomname;
109 long dav_msgnum = (-1);
114 char *msgtext = NULL;
118 char content_type[128];
121 struct epdata epdata;
123 if (StrBufNum_tokens(WCC->Hdr->HR.ReqLine, '/') < 2) {
124 hprintf("HTTP/1.1 404 not found\r\n");
125 groupdav_common_headers();
126 hprintf("Content-Type: text/plain\r\n");
127 wc_printf("The object you requested was not found.\r\n");
132 dav_roomname = NewStrBuf();;
133 dav_uid = NewStrBuf();;
134 StrBufExtract_token(dav_roomname, WCC->Hdr->HR.ReqLine, 0, '/');
135 StrBufExtract_token(dav_uid, WCC->Hdr->HR.ReqLine, 1, '/');
136 if ((!strcasecmp(ChrPtr(dav_uid), "ics")) ||
137 (!strcasecmp(ChrPtr(dav_uid), "calendar.ics"))) {
138 FlushStrBuf(dav_uid);
141 /* Go to the correct room. */
142 if (strcasecmp(ChrPtr(WCC->CurRoom.name), ChrPtr(dav_roomname))) {
143 gotoroom(dav_roomname);
145 if (strcasecmp(ChrPtr(WCC->CurRoom.name), ChrPtr(dav_roomname))) {
146 hprintf("HTTP/1.1 404 not found\r\n");
147 groupdav_common_headers();
148 hprintf("Content-Type: text/plain\r\n");
149 wc_printf("There is no folder called \"%s\" on this server.\r\n",
150 ChrPtr(dav_roomname));
152 FreeStrBuf(&dav_roomname);
153 FreeStrBuf(&dav_uid);
157 /* GET on the collection itself returns an ICS of the entire collection. */
158 if (StrLength(dav_uid) == 0) {
159 groupdav_get_big_ics();
160 FreeStrBuf(&dav_roomname);
161 FreeStrBuf(&dav_uid);
165 dav_msgnum = locate_message_by_uid(ChrPtr(dav_uid));
166 serv_printf("MSG2 %ld", dav_msgnum);
167 serv_getln(buf, sizeof buf);
169 hprintf("HTTP/1.1 404 not found\r\n");
170 groupdav_common_headers();
171 hprintf("Content-Type: text/plain\r\n");
172 wc_printf("Object \"%s\" was not found in the \"%s\" folder.\r\n",
174 ChrPtr(dav_roomname));
176 FreeStrBuf(&dav_roomname);
177 FreeStrBuf(&dav_uid);
180 FreeStrBuf(&dav_roomname);
181 FreeStrBuf(&dav_uid);
183 /* We got it; a message is now arriving from the server. Read it in. */
186 strcpy(charset, "UTF-8");
187 strcpy(content_type, "text/plain");
189 while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
190 linelen = strlen(buf);
192 /* Append it to the buffer */
193 if ((msglen + linelen + 3) > msgalloc) {
194 msgalloc = ( (msgalloc > 0) ? (msgalloc * 2) : 1024 );
195 msgtext = realloc(msgtext, msgalloc);
197 strcpy(&msgtext[msglen], buf);
199 strcpy(&msgtext[msglen], "\n");
202 /* Also learn some things about the message */
207 if (!strncasecmp(buf, "Date:", 5)) {
208 safestrncpy(date, &buf[5], sizeof date);
211 if (!strncasecmp(buf, "Content-type:", 13)) {
212 safestrncpy(content_type, &buf[13], sizeof content_type);
213 striplt(content_type);
214 ptr = bmstrcasestr(&buf[13], "charset=");
216 safestrncpy(charset, ptr+8, sizeof charset);
218 endptr = strchr(charset, ';');
219 if (endptr != NULL) strcpy(endptr, "");
221 endptr = strchr(content_type, ';');
222 if (endptr != NULL) strcpy(endptr, "");
228 /* Output headers common to single or multi part messages */
230 hprintf("HTTP/1.1 200 OK\r\n");
231 groupdav_common_headers();
232 hprintf("etag: \"%ld\"\r\n", dav_msgnum);
233 hprintf("Date: %s\r\n", date);
235 memset(&epdata, 0, sizeof(struct epdata));
236 safestrncpy(epdata.charset, charset, sizeof epdata.charset);
238 /* If we have a multipart message on our hands, and we are in a groupware room,
239 * strip it down to only the relevant part.
241 if (!strncasecmp(content_type, "multipart/", 10)) {
243 if ( (WCC->CurRoom.defview == VIEW_CALENDAR) || (WCC->CurRoom.defview == VIEW_TASKS) ) {
244 strcpy(epdata.desired_content_type_1, "text/calendar");
247 else if (WCC->CurRoom.defview == VIEW_ADDRESSBOOK) {
248 strcpy(epdata.desired_content_type_1, "text/vcard");
249 strcpy(epdata.desired_content_type_2, "text/x-vcard");
252 mime_parser(msgtext, &msgtext[msglen], extract_preferred, NULL, NULL, (void *)&epdata, 0);
255 /* If epdata.found_section is empty, we haven't output anything yet, so output the whole thing */
257 if (IsEmptyStr(epdata.found_section)) {
259 endptr = &msgtext[msglen];
261 hprintf("Content-type: %s; charset=%s\r\n", content_type, charset);
265 ptr = memreadline(ptr, buf, sizeof buf);
268 wc_printf("%s\r\n", buf);
270 else if ((buf[0] == 0) && (in_body == 0)) {
274 } while (ptr < endptr);