X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fgroupdav_propfind.c;h=2385d9900fdc7cc3186fe0f9eb80726f93e63e2e;hb=d120028b4c45f3c26d05186c8ba488fd2feef13f;hp=709aec43515d6faa7c3a4b9e5bd3417deb5b72c0;hpb=f8b6357914f9fb02f1b1bd4ecd8f07e637301ca3;p=citadel.git diff --git a/webcit/groupdav_propfind.c b/webcit/groupdav_propfind.c index 709aec435..2385d9900 100644 --- a/webcit/groupdav_propfind.c +++ b/webcit/groupdav_propfind.c @@ -3,24 +3,18 @@ * * Handles GroupDAV PROPFIND requests. * + * A few notes about our XML output: + * + * --> Yes, we are spewing tags directly instead of using an XML library. + * If you would like to rewrite this using libxml2, code it up and submit + * a patch. Whining will be summarily ignored. + * + * --> XML is deliberately output with no whitespace/newlines between tags. + * This makes it difficult to read, but we have discovered clients which + * crash when you try to pretty it up. + * */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include "webcit.h" #include "webserver.h" #include "groupdav.h" @@ -42,14 +36,10 @@ long locate_message_by_uid(char *uid) { /* Decode the uid */ euid_unescapize(decoded_uid, uid); - serv_puts("MSGS ALL|0|1"); - serv_gets(buf); - if (buf[0] == '8') { - serv_printf("exti|%s", decoded_uid); - serv_puts("000"); - while (serv_gets(buf), strcmp(buf, "000")) { - retval = atol(buf); - } + serv_printf("EUID %s", decoded_uid); + serv_getln(buf, sizeof buf); + if (buf[0] == '2') { + retval = extract_long(&buf[4], 0); } return(retval); } @@ -62,26 +52,33 @@ void groupdav_folder_list(void) { char buf[SIZ]; char roomname[SIZ]; int view; + char datestring[SIZ]; + time_t now; + + now = time(NULL); + http_datestring(datestring, sizeof datestring, now); /* * Be rude. Completely ignore the XML request and simply send them * everything we know about. Let the client sort it out. */ - wprintf("HTTP/1.0 207 Multi-Status\n"); + wprintf("HTTP/1.1 207 Multi-Status\r\n"); groupdav_common_headers(); - wprintf("Content-type: text/xml\n"); + wprintf("Date: %s\r\n", datestring); + wprintf("Content-type: text/xml\r\n"); + wprintf("Content-encoding: identity\r\n"); begin_burst(); - wprintf("\n" - "\n" + wprintf("" + "" ); serv_puts("LKRA"); - serv_gets(buf); - if (buf[0] == '1') while (serv_gets(buf), strcmp(buf, "000")) { + serv_getln(buf, sizeof buf); + if (buf[0] == '1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) { - extract(roomname, buf, 0); + extract_token(roomname, buf, 0, '|', sizeof roomname); view = extract_int(buf, 6); /* @@ -89,11 +86,13 @@ void groupdav_folder_list(void) { * might be interested in. In the future we may add * the rest. */ - if ((view == VIEW_CALENDAR) || (view == VIEW_TASKS) || (view == VIEW_ADDRESSBOOK) ) { + if ((view == VIEW_CALENDAR) + || (view == VIEW_TASKS) + || (view == VIEW_ADDRESSBOOK) ) { - wprintf(" \n"); + wprintf(""); - wprintf(" "); + wprintf(""); if (strlen(WC->http_host) > 0) { wprintf("%s://%s", (is_https ? "https" : "http"), @@ -101,35 +100,35 @@ void groupdav_folder_list(void) { } wprintf("/groupdav/"); urlescputs(roomname); - wprintf("/\n"); + wprintf("/"); - wprintf(" \n"); - wprintf(" HTTP/1.1 200 OK\n"); - wprintf(" \n"); - wprintf(" "); - escputs( roomname); - wprintf( "\n"); - wprintf(" "); + wprintf(""); + wprintf("HTTP/1.1 200 OK"); + wprintf(""); + wprintf(""); + escputs(roomname); + wprintf(""); + wprintf(""); switch(view) { case VIEW_CALENDAR: - wprintf(" \n"); + wprintf(""); break; case VIEW_TASKS: - wprintf(" \n"); + wprintf(""); break; case VIEW_ADDRESSBOOK: - wprintf(" \n"); + wprintf(""); break; } - wprintf( "\n"); - wprintf(" \n"); - wprintf(" \n"); - wprintf(" \n"); + wprintf(""); + wprintf(""); + wprintf(""); + wprintf(""); } } - wprintf("\n\n\n"); + wprintf("\n"); end_burst(); } @@ -140,25 +139,30 @@ void groupdav_folder_list(void) { * The pathname is always going to be /groupdav/room_name/msg_num */ void groupdav_propfind(char *dav_pathname) { - char dav_roomname[SIZ]; - char msgnum[SIZ]; - char buf[SIZ]; - char uid[SIZ]; - char encoded_uid[SIZ]; + char dav_roomname[256]; + char dav_uid[256]; + char msgnum[256]; + long dav_msgnum = (-1); + char buf[256]; + char uid[256]; + char encoded_uid[256]; long *msgs = NULL; int num_msgs = 0; int i; + char datestring[256]; + time_t now; - /* First, break off the "/groupdav/" prefix */ - remove_token(dav_pathname, 0, '/'); - remove_token(dav_pathname, 0, '/'); + now = time(NULL); + http_datestring(datestring, sizeof datestring, now); - /* What's left is the room name. Remove trailing slashes. */ - if (dav_pathname[strlen(dav_pathname)-1] == '/') { - dav_pathname[strlen(dav_pathname)-1] = 0; - } - strcpy(dav_roomname, dav_pathname); + extract_token(dav_roomname, dav_pathname, 2, '/', sizeof dav_roomname); + extract_token(dav_uid, dav_pathname, 3, '/', sizeof dav_uid); + /* + lprintf(9, "dav_pathname: %s\n", dav_pathname); + lprintf(9, "dav_roomname: %s\n", dav_roomname); + lprintf(9, " dav_uid: %s\n", dav_uid); + */ /* * If the room name is blank, the client is requesting a @@ -174,35 +178,103 @@ void groupdav_propfind(char *dav_pathname) { gotoroom(dav_roomname); } if (strcasecmp(WC->wc_roomname, dav_roomname)) { - wprintf("HTTP/1.1 404 not found\n"); + wprintf("HTTP/1.1 404 not found\r\n"); groupdav_common_headers(); + wprintf("Date: %s\r\n", datestring); wprintf( - "Content-Type: text/plain\n" - "\n" - "There is no folder called \"%s\" on this server.\n", + "Content-Type: text/plain\r\n" + "\r\n" + "There is no folder called \"%s\" on this server.\r\n", dav_roomname ); return; } + /* If dav_uid is non-empty, client is requesting a PROPFIND on + * a specific item in the room. This is not valid GroupDAV, but + * we try to honor it anyway because some clients are expecting + * it to work... + */ + if (strlen(dav_uid) > 0) { + + dav_msgnum = locate_message_by_uid(dav_uid); + if (dav_msgnum < 0) { + wprintf("HTTP/1.1 404 not found\r\n"); + groupdav_common_headers(); + wprintf( + "Content-Type: text/plain\r\n" + "\r\n" + "Object \"%s\" was not found in the \"%s\" folder.\r\n", + dav_uid, + dav_roomname + ); + return; + } + + /* Be rude. Completely ignore the XML request and simply send them + * everything we know about (which is going to simply be the ETag and + * nothing else). Let the client-side parser sort it out. + */ + wprintf("HTTP/1.1 207 Multi-Status\r\n"); + groupdav_common_headers(); + wprintf("Date: %s\r\n", datestring); + wprintf("Content-type: text/xml\r\n"); + wprintf("Content-encoding: identity\r\n"); + + begin_burst(); + + wprintf("" + "" + ); + + wprintf(""); + + wprintf(""); + if (strlen(WC->http_host) > 0) { + wprintf("%s://%s", + (is_https ? "https" : "http"), + WC->http_host); + } + wprintf("/groupdav/"); + urlescputs(WC->wc_roomname); + euid_escapize(encoded_uid, dav_uid); + wprintf("/%s", encoded_uid); + wprintf(""); + wprintf(""); + wprintf("HTTP/1.1 200 OK"); + wprintf("\"%ld\"", dav_msgnum); + wprintf(""); + + wprintf("\n"); + wprintf("\n"); + end_burst(); + return; + } + + /* + * We got to this point, which means that the client is requesting + * a 'collection' (i.e. a list of all items in the room). + * * Be rude. Completely ignore the XML request and simply send them * everything we know about (which is going to simply be the ETag and * nothing else). Let the client-side parser sort it out. */ - wprintf("HTTP/1.0 207 Multi-Status\n"); + wprintf("HTTP/1.1 207 Multi-Status\r\n"); groupdav_common_headers(); - wprintf("Content-type: text/xml\n"); + wprintf("Date: %s\r\n", datestring); + wprintf("Content-type: text/xml\r\n"); + wprintf("Content-encoding: identity\r\n"); begin_burst(); - wprintf("\n" - "\n" + wprintf("" + "" ); serv_puts("MSGS ALL"); - serv_gets(buf); - if (buf[0] == '1') while (serv_gets(msgnum), strcmp(msgnum, "000")) { + serv_getln(buf, sizeof buf); + if (buf[0] == '1') while (serv_getln(msgnum, sizeof msgnum), strcmp(msgnum, "000")) { msgs = realloc(msgs, ++num_msgs * sizeof(long)); msgs[num_msgs-1] = atol(msgnum); } @@ -211,16 +283,16 @@ void groupdav_propfind(char *dav_pathname) { strcpy(uid, ""); serv_printf("MSG0 %ld|3", msgs[i]); - serv_gets(buf); - if (buf[0] == '1') while (serv_gets(buf), strcmp(buf, "000")) { + serv_getln(buf, sizeof buf); + if (buf[0] == '1') while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) { if (!strncasecmp(buf, "exti=", 5)) { strcpy(uid, &buf[5]); } } if (strlen(uid) > 0) { - wprintf(" \n"); - wprintf(" "); + wprintf(""); + wprintf(""); if (strlen(WC->http_host) > 0) { wprintf("%s://%s", (is_https ? "https" : "http"), @@ -230,16 +302,16 @@ void groupdav_propfind(char *dav_pathname) { urlescputs(WC->wc_roomname); euid_escapize(encoded_uid, uid); wprintf("/%s", encoded_uid); - wprintf("\n"); - wprintf(" \n"); - wprintf(" HTTP/1.1 200 OK\n"); - wprintf(" \"%ld\"\n", msgs[i]); - wprintf(" \n"); - wprintf(" \n"); + wprintf(""); + wprintf(""); + wprintf("HTTP/1.1 200 OK"); + wprintf("\"%ld\"", msgs[i]); + wprintf(""); + wprintf(""); } } - wprintf("\n\n\n"); + wprintf("\n"); end_burst(); if (msgs != NULL) {