rename wprintf to wc_printf; wchar.h also has a wprintf
[citadel.git] / webcit / groupdav_get.c
1 /*
2  * $Id$
3  *
4  * Handles GroupDAV GET requests.
5  *
6  */
7
8 #include "webcit.h"
9 #include "webserver.h"
10 #include "groupdav.h"
11
12
13 /*
14  * Fetch the entire contents of the room as one big ics file.
15  * This is for "webcal://" type access.
16  */     
17 void groupdav_get_big_ics(void) {
18         char buf[1024];
19
20         serv_puts("ICAL getics");
21         serv_getln(buf, sizeof buf);
22         if (buf[0] != '1') {
23                 hprintf("HTTP/1.1 404 not found\r\n");
24                 groupdav_common_headers();
25                 hprintf("Content-Type: text/plain\r\n");
26                 begin_burst();
27                 wc_printf("%s\r\n",
28                         &buf[4]
29                         );
30                 end_burst();
31                 return;
32         }
33
34         hprintf("HTTP/1.1 200 OK\r\n");
35         groupdav_common_headers();
36         hprintf("Content-type: text/calendar; charset=UTF-8\r\n");
37         begin_burst();
38         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
39                 wc_printf("%s\r\n", buf);
40         }
41         end_burst();
42 }
43
44
45 /* 
46  * MIME parser callback function for groupdav_get()
47  * Helps identify the relevant section of a multipart message
48  */
49 void extract_preferred(char *name, char *filename, char *partnum, char *disp,
50                         void *content, char *cbtype, char *cbcharset,
51                         size_t length, char *encoding, char *cbid, void *userdata)
52 {
53         struct epdata *epdata = (struct epdata *)userdata;
54         int hit = 0;
55
56         /* We only want the first one that we found */
57         if (!IsEmptyStr(epdata->found_section)) return;
58
59         /* Check for a content type match */
60         if (strlen(epdata->desired_content_type_1) > 0) {
61                 if (!strcasecmp(epdata->desired_content_type_1, cbtype)) {
62                         hit = 1;
63                 }
64         }
65         if (!IsEmptyStr(epdata->desired_content_type_2)) {
66                 if (!strcasecmp(epdata->desired_content_type_2, cbtype)) {
67                         hit = 1;
68                 }
69         }
70
71         /* Is this the one?  If so, output it. */
72         if (hit) {
73                 safestrncpy(epdata->found_section, partnum, sizeof epdata->found_section);
74                 if (!IsEmptyStr(cbcharset)) {
75                         safestrncpy(epdata->charset, cbcharset, sizeof epdata->charset);
76                 }
77                 hprintf("Content-type: %s; charset=%s\r\n", cbtype, epdata->charset);
78                 begin_burst();
79                 StrBufAppendBufPlain(WC->WBuf, content, length, 0);
80                 end_burst();
81         }
82 }
83
84
85
86 /*
87  * The pathname is always going to take one of two formats:
88  * /groupdav/room_name/euid     (GroupDAV)
89  * /groupdav/room_name          (webcal)
90  */
91 void groupdav_get(void)
92 {
93         wcsession *WCC = WC;
94         StrBuf *dav_roomname;
95         StrBuf *dav_uid;
96         long dav_msgnum = (-1);
97         char buf[1024];
98         int in_body = 0;
99         int found_content_type = 0;
100         char *ptr;
101         char *endptr;
102         char *msgtext = NULL;
103         size_t msglen = 0;
104         size_t msgalloc = 0;
105         int linelen;
106         char content_type[128];
107         char charset[128];
108         char date[128];
109         struct epdata epdata;
110
111         if (StrBufNum_tokens(WCC->Hdr->HR.ReqLine, '/') < 2) {
112                 hprintf("HTTP/1.1 404 not found\r\n");
113                 groupdav_common_headers();
114                 hprintf("Content-Type: text/plain\r\n");
115                 wc_printf("The object you requested was not found.\r\n");
116                 end_burst();
117                 return;
118         }
119
120         dav_roomname = NewStrBuf();;
121         dav_uid = NewStrBuf();;
122         StrBufExtract_token(dav_roomname, WCC->Hdr->HR.ReqLine, 0, '/');
123         StrBufExtract_token(dav_uid, WCC->Hdr->HR.ReqLine, 1, '/');
124         if ((!strcasecmp(ChrPtr(dav_uid), "ics")) || 
125             (!strcasecmp(ChrPtr(dav_uid), "calendar.ics"))) {
126                 FlushStrBuf(dav_uid);
127         }
128
129         /* Go to the correct room. */
130         if (strcasecmp(ChrPtr(WCC->wc_roomname), ChrPtr(dav_roomname))) {
131                 gotoroom(dav_roomname);
132         }
133         if (strcasecmp(ChrPtr(WCC->wc_roomname), ChrPtr(dav_roomname))) {
134                 hprintf("HTTP/1.1 404 not found\r\n");
135                 groupdav_common_headers();
136                 hprintf("Content-Type: text/plain\r\n");
137                 wc_printf("There is no folder called \"%s\" on this server.\r\n",
138                         ChrPtr(dav_roomname));
139                 end_burst();
140                 FreeStrBuf(&dav_roomname);
141                 FreeStrBuf(&dav_uid);
142                 return;
143         }
144
145         /** GET on the collection itself returns an ICS of the entire collection.
146          */
147         if (StrLength(dav_uid) == 0) {
148                 groupdav_get_big_ics();
149                 FreeStrBuf(&dav_roomname);
150                 FreeStrBuf(&dav_uid);
151                 return;
152         }
153
154         dav_msgnum = locate_message_by_uid(ChrPtr(dav_uid));
155         serv_printf("MSG2 %ld", dav_msgnum);
156         serv_getln(buf, sizeof buf);
157         if (buf[0] != '1') {
158                 hprintf("HTTP/1.1 404 not found\r\n");
159                 groupdav_common_headers();
160                 hprintf("Content-Type: text/plain\r\n");
161                 wc_printf("Object \"%s\" was not found in the \"%s\" folder.\r\n",
162                         ChrPtr(dav_uid),
163                         ChrPtr(dav_roomname));
164                 end_burst();
165                 FreeStrBuf(&dav_roomname);
166                 FreeStrBuf(&dav_uid);
167                 return;
168         }
169         FreeStrBuf(&dav_roomname);
170         FreeStrBuf(&dav_uid);
171
172         /* We got it; a message is now arriving from the server.  Read it in. */
173
174         in_body = 0;
175         found_content_type = 0;
176         strcpy(charset, "UTF-8");
177         strcpy(content_type, "text/plain");
178         strcpy(date, "");
179         while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
180                 linelen = strlen(buf);
181
182                 /* Append it to the buffer */
183                 if ((msglen + linelen + 3) > msgalloc) {
184                         msgalloc = ( (msgalloc > 0) ? (msgalloc * 2) : 1024 );
185                         msgtext = realloc(msgtext, msgalloc);
186                 }
187                 strcpy(&msgtext[msglen], buf);
188                 msglen += linelen;
189                 strcpy(&msgtext[msglen], "\n");
190                 msglen += 1;
191
192                 /* Also learn some things about the message */
193                 if (linelen == 0) {
194                         in_body = 1;
195                 }
196                 if (!in_body) {
197                         if (!strncasecmp(buf, "Date:", 5)) {
198                                 safestrncpy(date, &buf[5], sizeof date);
199                                 striplt(date);
200                         }
201                         if (!strncasecmp(buf, "Content-type:", 13)) {
202                                 safestrncpy(content_type, &buf[13], sizeof content_type);
203                                 striplt(content_type);
204                                 ptr = bmstrcasestr(&buf[13], "charset=");
205                                 if (ptr) {
206                                         safestrncpy(charset, ptr+8, sizeof charset);
207                                         striplt(charset);
208                                         endptr = strchr(charset, ';');
209                                         if (endptr != NULL) strcpy(endptr, "");
210                                 }
211                                 endptr = strchr(content_type, ';');
212                                 if (endptr != NULL) strcpy(endptr, "");
213                         }
214                 }
215         }
216         msgtext[msglen] = 0;
217
218         /* Output headers common to single or multi part messages */
219
220         hprintf("HTTP/1.1 200 OK\r\n");
221         groupdav_common_headers();
222         hprintf("etag: \"%ld\"\r\n", dav_msgnum);
223         hprintf("Date: %s\r\n", date);
224
225         memset(&epdata, 0, sizeof(struct epdata));
226         safestrncpy(epdata.charset, charset, sizeof epdata.charset);
227
228         /* If we have a multipart message on our hands, and we are in a groupware room,
229          * strip it down to only the relevant part.
230          */
231         if (!strncasecmp(content_type, "multipart/", 10)) {
232
233                 if ( (WCC->wc_default_view == VIEW_CALENDAR) || (WCC->wc_default_view == VIEW_TASKS) ) {
234                         strcpy(epdata.desired_content_type_1, "text/calendar");
235                 }
236
237                 else if (WCC->wc_default_view == VIEW_ADDRESSBOOK) {
238                         strcpy(epdata.desired_content_type_1, "text/vcard");
239                         strcpy(epdata.desired_content_type_2, "text/x-vcard");
240                 }
241
242                 mime_parser(msgtext, &msgtext[msglen], extract_preferred, NULL, NULL, (void *)&epdata, 0);
243         }
244
245         /* If epdata.found_section is empty, we haven't output anything yet, so output the whole thing */
246
247         if (IsEmptyStr(epdata.found_section)) {
248                 ptr = msgtext;
249                 endptr = &msgtext[msglen];
250         
251                 hprintf("Content-type: %s; charset=%s\r\n", content_type, charset);
252         
253                 in_body = 0;
254                 do {
255                         ptr = memreadline(ptr, buf, sizeof buf);
256         
257                         if (in_body) {
258                                 wc_printf("%s\r\n", buf);
259                         }
260                         else if ((buf[0] == 0) && (in_body == 0)) {
261                                 in_body = 1;
262                                 begin_burst();
263                         }
264                 } while (ptr < endptr);
265         
266                 end_burst();
267         }
268
269         free(msgtext);
270 }