4 * Handles GroupDAV GET requests.
11 #include "mime_parser.h"
15 * Fetch the entire contents of the room as one big ics file.
16 * This is for "webcal://" type access.
18 void groupdav_get_big_ics(void) {
21 serv_puts("ICAL getics");
22 serv_getln(buf, sizeof buf);
24 wprintf("HTTP/1.1 404 not found\r\n");
25 groupdav_common_headers();
27 "Content-Type: text/plain\r\n"
35 wprintf("HTTP/1.1 200 OK\r\n");
36 groupdav_common_headers();
37 wprintf("Content-type: text/calendar; charset=UTF-8\r\n");
39 while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
40 wprintf("%s\r\n", buf);
47 * MIME parser callback function for groupdav_get()
48 * Helps identify the relevant section of a multipart message
50 void extract_preferred(char *name, char *filename, char *partnum, char *disp,
51 void *content, char *cbtype, char *cbcharset,
52 size_t length, char *encoding, void *userdata)
54 struct epdata *epdata = (struct epdata *)userdata;
57 /* We only want the first one that we found */
58 if (strlen(epdata->found_section) > 0) return;
60 /* Check for a content type match */
61 if (strlen(epdata->desired_content_type_1) > 0) {
62 if (!strcasecmp(epdata->desired_content_type_1, cbtype)) {
66 if (strlen(epdata->desired_content_type_2) > 0) {
67 if (!strcasecmp(epdata->desired_content_type_2, cbtype)) {
72 /* Is this the one? If so, output it. */
74 safestrncpy(epdata->found_section, partnum, sizeof epdata->found_section);
75 if (strlen(cbcharset) > 0) {
76 safestrncpy(epdata->charset, cbcharset, sizeof epdata->charset);
78 wprintf("Content-type: %s; charset=%s\r\n", cbtype, epdata->charset);
80 client_write(content, length);
88 * The pathname is always going to take one of two formats:
89 * /groupdav/room_name/euid (GroupDAV)
90 * /groupdav/room_name (webcal)
92 void groupdav_get(char *dav_pathname) {
93 char dav_roomname[1024];
95 long dav_msgnum = (-1);
98 int found_content_type = 0;
101 char *msgtext = NULL;
105 char content_type[128];
108 struct epdata epdata;
110 if (num_tokens(dav_pathname, '/') < 3) {
111 wprintf("HTTP/1.1 404 not found\r\n");
112 groupdav_common_headers();
114 "Content-Type: text/plain\r\n"
116 "The object you requested was not found.\r\n"
121 extract_token(dav_roomname, dav_pathname, 2, '/', sizeof dav_roomname);
122 extract_token(dav_uid, dav_pathname, 3, '/', sizeof dav_uid);
123 if ((!strcasecmp(dav_uid, "ics")) || (!strcasecmp(dav_uid, "calendar.ics"))) {
127 /* Go to the correct room. */
128 if (strcasecmp(WC->wc_roomname, dav_roomname)) {
129 gotoroom(dav_roomname);
131 if (strcasecmp(WC->wc_roomname, dav_roomname)) {
132 wprintf("HTTP/1.1 404 not found\r\n");
133 groupdav_common_headers();
135 "Content-Type: text/plain\r\n"
137 "There is no folder called \"%s\" on this server.\r\n",
143 /** GET on the collection itself returns an ICS of the entire collection.
145 if (!strcasecmp(dav_uid, "")) {
146 groupdav_get_big_ics();
150 dav_msgnum = locate_message_by_uid(dav_uid);
151 serv_printf("MSG2 %ld", dav_msgnum);
152 serv_getln(buf, sizeof buf);
154 wprintf("HTTP/1.1 404 not found\r\n");
155 groupdav_common_headers();
157 "Content-Type: text/plain\r\n"
159 "Object \"%s\" was not found in the \"%s\" folder.\r\n",
166 /* We got it; a message is now arriving from the server. Read it in. */
169 found_content_type = 0;
170 strcpy(charset, "UTF-8");
171 strcpy(content_type, "text/plain");
173 while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
174 linelen = strlen(buf);
176 /* Append it to the buffer */
177 if ((msglen + linelen + 3) > msgalloc) {
178 msgalloc = ( (msgalloc > 0) ? (msgalloc * 2) : 1024 );
179 msgtext = realloc(msgtext, msgalloc);
181 strcpy(&msgtext[msglen], buf);
183 strcpy(&msgtext[msglen], "\n");
186 /* Also learn some things about the message */
191 if (!strncasecmp(buf, "Date:", 5)) {
192 safestrncpy(date, &buf[5], sizeof date);
195 if (!strncasecmp(buf, "Content-type:", 13)) {
196 safestrncpy(content_type, &buf[13], sizeof content_type);
197 striplt(content_type);
198 ptr = bmstrcasestr(&buf[13], "charset=");
200 safestrncpy(charset, ptr+8, sizeof charset);
202 endptr = strchr(charset, ';');
203 if (endptr != NULL) strcpy(endptr, "");
205 endptr = strchr(content_type, ';');
206 if (endptr != NULL) strcpy(endptr, "");
212 /* Output headers common to single or multi part messages */
214 wprintf("HTTP/1.1 200 OK\r\n");
215 groupdav_common_headers();
216 wprintf("etag: \"%ld\"\r\n", dav_msgnum);
217 wprintf("Date: %s\r\n", date);
219 memset(&epdata, 0, sizeof(struct epdata));
220 safestrncpy(epdata.charset, charset, sizeof epdata.charset);
222 /* If we have a multipart message on our hands, and we are in a groupware room,
223 * strip it down to only the relevant part.
225 if (!strncasecmp(content_type, "multipart/", 10)) {
227 if ( (WC->wc_default_view == VIEW_CALENDAR) || (WC->wc_default_view == VIEW_TASKS) ) {
228 strcpy(epdata.desired_content_type_1, "text/calendar");
231 else if (WC->wc_default_view == VIEW_ADDRESSBOOK) {
232 strcpy(epdata.desired_content_type_1, "text/vcard");
233 strcpy(epdata.desired_content_type_2, "text/x-vcard");
236 mime_parser(msgtext, &msgtext[msglen], extract_preferred, NULL, NULL, (void *)&epdata, 0);
239 /* If epdata.found_section is empty, we haven't output anything yet, so output the whole thing */
241 if (strlen(epdata.found_section) == 0) {
243 endptr = &msgtext[msglen];
245 wprintf("Content-type: %s; charset=%s\r\n", content_type, charset);
249 ptr = memreadline(ptr, buf, sizeof buf);
252 wprintf("%s\r\n", buf);
254 else if ((buf[0] == 0) && (in_body == 0)) {
258 } while (ptr < endptr);