4 * Handles GroupDAV GET requests.
14 * Fetch the entire contents of the room as one big ics file.
15 * This is for "webcal://" type access.
17 void groupdav_get_big_ics(void) {
20 serv_puts("ICAL getics");
21 serv_getln(buf
, sizeof buf
);
23 hprintf("HTTP/1.1 404 not found\r\n");
24 groupdav_common_headers();
25 hprintf("Content-Type: text/plain\r\n");
28 );/* TODO: do we need to end-burst here? */
32 hprintf("HTTP/1.1 200 OK\r\n");
33 groupdav_common_headers();
34 hprintf("Content-type: text/calendar; charset=UTF-8\r\n");
36 while (serv_getln(buf
, sizeof buf
), strcmp(buf
, "000")) {
37 wprintf("%s\r\n", buf
);
44 * MIME parser callback function for groupdav_get()
45 * Helps identify the relevant section of a multipart message
47 void extract_preferred(char *name
, char *filename
, char *partnum
, char *disp
,
48 void *content
, char *cbtype
, char *cbcharset
,
49 size_t length
, char *encoding
, char *cbid
, void *userdata
)
51 struct epdata
*epdata
= (struct epdata
*)userdata
;
54 /* We only want the first one that we found */
55 if (!IsEmptyStr(epdata
->found_section
)) return;
57 /* Check for a content type match */
58 if (strlen(epdata
->desired_content_type_1
) > 0) {
59 if (!strcasecmp(epdata
->desired_content_type_1
, cbtype
)) {
63 if (!IsEmptyStr(epdata
->desired_content_type_2
)) {
64 if (!strcasecmp(epdata
->desired_content_type_2
, cbtype
)) {
69 /* Is this the one? If so, output it. */
71 safestrncpy(epdata
->found_section
, partnum
, sizeof epdata
->found_section
);
72 if (!IsEmptyStr(cbcharset
)) {
73 safestrncpy(epdata
->charset
, cbcharset
, sizeof epdata
->charset
);
75 hprintf("Content-type: %s; charset=%s\r\n", cbtype
, epdata
->charset
);
77 StrBufAppendBufPlain(WC
->WBuf
, content
, length
, 0);
85 * The pathname is always going to take one of two formats:
86 * /groupdav/room_name/euid (GroupDAV)
87 * /groupdav/room_name (webcal)
89 void groupdav_get(StrBuf
*dav_pathname
) {
92 long dav_msgnum
= (-1);
95 int found_content_type
= 0;
102 char content_type
[128];
105 struct epdata epdata
;
107 if (StrBufNum_tokens(dav_pathname
, '/') < 3) {
108 hprintf("HTTP/1.1 404 not found\r\n");
109 groupdav_common_headers();
110 hprintf("Content-Type: text/plain\r\n");
111 wprintf("The object you requested was not found.\r\n");
116 dav_roomname
= NewStrBuf();;
117 dav_uid
= NewStrBuf();;
118 StrBufExtract_token(dav_roomname
, dav_pathname
, 2, '/');
119 StrBufExtract_token(dav_uid
, dav_pathname
, 3, '/');
120 if ((!strcasecmp(ChrPtr(dav_uid
), "ics")) ||
121 (!strcasecmp(ChrPtr(dav_uid
), "calendar.ics"))) {
122 FlushStrBuf(dav_uid
);
125 /* Go to the correct room. */
126 if (strcasecmp(ChrPtr(WC
->wc_roomname
), ChrPtr(dav_roomname
))) {
127 gotoroom(dav_roomname
);
129 if (strcasecmp(ChrPtr(WC
->wc_roomname
), ChrPtr(dav_roomname
))) {
130 hprintf("HTTP/1.1 404 not found\r\n");
131 groupdav_common_headers();
132 hprintf("Content-Type: text/plain\r\n");
133 wprintf("There is no folder called \"%s\" on this server.\r\n",
134 ChrPtr(dav_roomname
));
136 FreeStrBuf(&dav_roomname
);
137 FreeStrBuf(&dav_uid
);
141 /** GET on the collection itself returns an ICS of the entire collection.
143 if (StrLength(dav_uid
) == 0) {
144 groupdav_get_big_ics();
145 FreeStrBuf(&dav_roomname
);
146 FreeStrBuf(&dav_uid
);
150 dav_msgnum
= locate_message_by_uid(ChrPtr(dav_uid
));
151 serv_printf("MSG2 %ld", dav_msgnum
);
152 serv_getln(buf
, sizeof buf
);
154 hprintf("HTTP/1.1 404 not found\r\n");
155 groupdav_common_headers();
156 hprintf("Content-Type: text/plain\r\n");
157 wprintf("Object \"%s\" was not found in the \"%s\" folder.\r\n",
159 ChrPtr(dav_roomname
));
161 FreeStrBuf(&dav_roomname
);
162 FreeStrBuf(&dav_uid
);
165 FreeStrBuf(&dav_roomname
);
166 FreeStrBuf(&dav_uid
);
168 /* We got it; a message is now arriving from the server. Read it in. */
171 found_content_type
= 0;
172 strcpy(charset
, "UTF-8");
173 strcpy(content_type
, "text/plain");
175 while (serv_getln(buf
, sizeof buf
), strcmp(buf
, "000")) {
176 linelen
= strlen(buf
);
178 /* Append it to the buffer */
179 if ((msglen
+ linelen
+ 3) > msgalloc
) {
180 msgalloc
= ( (msgalloc
> 0) ? (msgalloc
* 2) : 1024 );
181 msgtext
= realloc(msgtext
, msgalloc
);
183 strcpy(&msgtext
[msglen
], buf
);
185 strcpy(&msgtext
[msglen
], "\n");
188 /* Also learn some things about the message */
193 if (!strncasecmp(buf
, "Date:", 5)) {
194 safestrncpy(date
, &buf
[5], sizeof date
);
197 if (!strncasecmp(buf
, "Content-type:", 13)) {
198 safestrncpy(content_type
, &buf
[13], sizeof content_type
);
199 striplt(content_type
);
200 ptr
= bmstrcasestr(&buf
[13], "charset=");
202 safestrncpy(charset
, ptr
+8, sizeof charset
);
204 endptr
= strchr(charset
, ';');
205 if (endptr
!= NULL
) strcpy(endptr
, "");
207 endptr
= strchr(content_type
, ';');
208 if (endptr
!= NULL
) strcpy(endptr
, "");
214 /* Output headers common to single or multi part messages */
216 hprintf("HTTP/1.1 200 OK\r\n");
217 groupdav_common_headers();
218 hprintf("etag: \"%ld\"\r\n", dav_msgnum
);
219 hprintf("Date: %s\r\n", date
);
221 memset(&epdata
, 0, sizeof(struct epdata
));
222 safestrncpy(epdata
.charset
, charset
, sizeof epdata
.charset
);
224 /* If we have a multipart message on our hands, and we are in a groupware room,
225 * strip it down to only the relevant part.
227 if (!strncasecmp(content_type
, "multipart/", 10)) {
229 if ( (WC
->wc_default_view
== VIEW_CALENDAR
) || (WC
->wc_default_view
== VIEW_TASKS
) ) {
230 strcpy(epdata
.desired_content_type_1
, "text/calendar");
233 else if (WC
->wc_default_view
== VIEW_ADDRESSBOOK
) {
234 strcpy(epdata
.desired_content_type_1
, "text/vcard");
235 strcpy(epdata
.desired_content_type_2
, "text/x-vcard");
238 mime_parser(msgtext
, &msgtext
[msglen
], extract_preferred
, NULL
, NULL
, (void *)&epdata
, 0);
241 /* If epdata.found_section is empty, we haven't output anything yet, so output the whole thing */
243 if (IsEmptyStr(epdata
.found_section
)) {
245 endptr
= &msgtext
[msglen
];
247 hprintf("Content-type: %s; charset=%s\r\n", content_type
, charset
);
251 ptr
= memreadline(ptr
, buf
, sizeof buf
);
254 wprintf("%s\r\n", buf
);
256 else if ((buf
[0] == 0) && (in_body
== 0)) {
260 } while (ptr
< endptr
);