From b8395fd95e322ccff54434781faa29fce6053baa Mon Sep 17 00:00:00 2001 From: =?utf8?q?Wilfried=20G=C3=B6esgens?= Date: Tue, 23 Jun 2009 12:15:10 +0000 Subject: [PATCH] * fix groupdav handling * add common logic for outputting 401; centralize it, register it as handler. * remove params to groupdav functions, since WC gives them all information they need. * use the general post handler for groupdav too. * since /groupdav/ isn't left in the path by the current logic anymore, we need to count less when parsing. --- webcit/context_loop.c | 12 +++- webcit/groupdav.h | 19 ++----- webcit/groupdav_delete.c | 31 +++++------ webcit/groupdav_get.c | 18 +++--- webcit/groupdav_main.c | 111 +++++++++++++------------------------ webcit/groupdav_options.c | 8 ++- webcit/groupdav_propfind.c | 56 +++++++++++-------- webcit/groupdav_put.c | 34 ++++++------ webcit/webcit.c | 46 ++++++++++++--- webcit/webcit.h | 4 +- 10 files changed, 175 insertions(+), 164 deletions(-) diff --git a/webcit/context_loop.c b/webcit/context_loop.c index 3a20c7e82..e0c8072b0 100644 --- a/webcit/context_loop.c +++ b/webcit/context_loop.c @@ -544,8 +544,16 @@ void context_loop(ParsedHttpHdrs *Hdr) if ((StrLength(Hdr->c_username) == 0) && (!Hdr->HR.DontNeedAuth)) { - OverrideRequest(Hdr, HKEY("GET /static/nocookies.html?force_close_session=yes HTTP/1.0")); - Hdr->HR.prohibit_caching = 1; + + if ((Hdr->HR.Handler != NULL) && + (XHTTP_COMMANDS & Hdr->HR.Handler->Flags) == XHTTP_COMMANDS) { + OverrideRequest(Hdr, HKEY("GET /401 HTTP/1.0")); + Hdr->HR.prohibit_caching = 1; + } + else { + OverrideRequest(Hdr, HKEY("GET /static/nocookies.html?force_close_session=yes HTTP/1.0")); + Hdr->HR.prohibit_caching = 1; + } } if (StrLength(Hdr->c_language) > 0) { diff --git a/webcit/groupdav.h b/webcit/groupdav.h index 82b532192..49b3f4923 100644 --- a/webcit/groupdav.h +++ b/webcit/groupdav.h @@ -14,19 +14,12 @@ struct epdata { void groupdav_common_headers(void); -void groupdav_main(HashList *HTTPHeaders, - StrBuf *DavPathname, - StrBuf *dav_content_type, - int dav_content_length, - StrBuf *dav_content, - int Offset); -void groupdav_get(StrBuf *dav_pathname); -void groupdav_put(StrBuf *dav_pathname, char *dav_ifmatch, - const char *dav_content_type, StrBuf *dav_content, - int offset); -void groupdav_delete(StrBuf *dav_pathname, char *dav_ifmatch); -void groupdav_propfind(StrBuf *dav_pathname, int dav_depth, StrBuf *dav_content_type, StrBuf *dav_content, int offset); -void groupdav_options(StrBuf *dav_pathname); +void groupdav_get(void); +void groupdav_put(void); +void groupdav_delete(void); +void groupdav_propfind(void); +void groupdav_options(void); + long locate_message_by_uid(const char *); void groupdav_folder_list(void); void euid_escapize(char *, const char *); diff --git a/webcit/groupdav_delete.c b/webcit/groupdav_delete.c index cdc65becb..e18f1a86f 100644 --- a/webcit/groupdav_delete.c +++ b/webcit/groupdav_delete.c @@ -13,32 +13,31 @@ /* * The pathname is always going to be /groupdav/room_name/euid */ -void groupdav_delete(StrBuf *dav_pathname, char *dav_ifmatch) { +void groupdav_delete(void) +{ + wcsession *WCC = WC; char dav_uid[SIZ]; long dav_msgnum = (-1); char buf[SIZ]; int n = 0; - /* First, break off the "/groupdav/" prefix */ - StrBufCutLeft(dav_pathname, 9); - /* Now extract the message euid */ - n = StrBufNum_tokens(dav_pathname, '/'); - extract_token(dav_uid, ChrPtr(dav_pathname), n-1, '/', sizeof dav_uid); - StrBufRemove_token(dav_pathname, n-1, '/'); + n = StrBufNum_tokens(WCC->Hdr->HR.ReqLine, '/'); + extract_token(dav_uid, ChrPtr(WCC->Hdr->HR.ReqLine), n-1, '/', sizeof dav_uid); + StrBufRemove_token(WCC->Hdr->HR.ReqLine, n-1, '/'); /* What's left is the room name. Remove trailing slashes. */ - //len = StrLength(dav_pathname); - //if ((len > 0) && (ChrPtr(dav_pathname)[len-1] == '/')) { - // StrBufCutRight(dav_pathname, 1); + //len = StrLength(WCC->Hdr->HR.ReqLine); + //if ((len > 0) && (ChrPtr(WCC->Hdr->HR.ReqLinee)[len-1] == '/')) { + // StrBufCutRight(WCC->Hdr->HR.ReqLine, 1); //} - StrBufCutLeft(dav_pathname, 1); + StrBufCutLeft(WCC->Hdr->HR.ReqLine, 1); /* Go to the correct room. */ - if (strcasecmp(ChrPtr(WC->wc_roomname), ChrPtr(dav_pathname))) { - gotoroom(dav_pathname); + if (strcasecmp(ChrPtr(WC->wc_roomname), ChrPtr(WCC->Hdr->HR.ReqLine))) { + gotoroom(WCC->Hdr->HR.ReqLine); } - if (strcasecmp(ChrPtr(WC->wc_roomname), ChrPtr(dav_pathname))) { + if (strcasecmp(ChrPtr(WC->wc_roomname), ChrPtr(WCC->Hdr->HR.ReqLine))) { hprintf("HTTP/1.1 404 not found\r\n"); groupdav_common_headers(); hprintf("Content-Length: 0\r\n\r\n"); @@ -61,8 +60,8 @@ void groupdav_delete(StrBuf *dav_pathname, char *dav_ifmatch) { * It's there ... check the ETag and make sure it matches * the message number. */ - if (!IsEmptyStr(dav_ifmatch)) { - if (atol(dav_ifmatch) != dav_msgnum) { + if (StrLength(WCC->Hdr->HR.dav_ifmatch) > 0) { + if (StrTol(WCC->Hdr->HR.dav_ifmatch) != dav_msgnum) { hprintf("HTTP/1.1 412 Precondition Failed\r\n"); groupdav_common_headers(); hprintf("Content-Length: 0\r\n\r\n"); diff --git a/webcit/groupdav_get.c b/webcit/groupdav_get.c index 2a4d4cb54..1c6e48307 100644 --- a/webcit/groupdav_get.c +++ b/webcit/groupdav_get.c @@ -86,7 +86,9 @@ void extract_preferred(char *name, char *filename, char *partnum, char *disp, * /groupdav/room_name/euid (GroupDAV) * /groupdav/room_name (webcal) */ -void groupdav_get(StrBuf *dav_pathname) { +void groupdav_get(void) +{ + wcsession *WCC = WC; StrBuf *dav_roomname; StrBuf *dav_uid; long dav_msgnum = (-1); @@ -104,7 +106,7 @@ void groupdav_get(StrBuf *dav_pathname) { char date[128]; struct epdata epdata; - if (StrBufNum_tokens(dav_pathname, '/') < 3) { + if (StrBufNum_tokens(WCC->Hdr->HR.ReqLine, '/') < 2) { hprintf("HTTP/1.1 404 not found\r\n"); groupdav_common_headers(); hprintf("Content-Type: text/plain\r\n"); @@ -115,18 +117,18 @@ void groupdav_get(StrBuf *dav_pathname) { dav_roomname = NewStrBuf();; dav_uid = NewStrBuf();; - StrBufExtract_token(dav_roomname, dav_pathname, 2, '/'); - StrBufExtract_token(dav_uid, dav_pathname, 3, '/'); + StrBufExtract_token(dav_roomname, WCC->Hdr->HR.ReqLine, 0, '/'); + StrBufExtract_token(dav_uid, WCC->Hdr->HR.ReqLine, 1, '/'); if ((!strcasecmp(ChrPtr(dav_uid), "ics")) || (!strcasecmp(ChrPtr(dav_uid), "calendar.ics"))) { FlushStrBuf(dav_uid); } /* Go to the correct room. */ - if (strcasecmp(ChrPtr(WC->wc_roomname), ChrPtr(dav_roomname))) { + if (strcasecmp(ChrPtr(WCC->wc_roomname), ChrPtr(dav_roomname))) { gotoroom(dav_roomname); } - if (strcasecmp(ChrPtr(WC->wc_roomname), ChrPtr(dav_roomname))) { + if (strcasecmp(ChrPtr(WCC->wc_roomname), ChrPtr(dav_roomname))) { hprintf("HTTP/1.1 404 not found\r\n"); groupdav_common_headers(); hprintf("Content-Type: text/plain\r\n"); @@ -226,11 +228,11 @@ void groupdav_get(StrBuf *dav_pathname) { */ if (!strncasecmp(content_type, "multipart/", 10)) { - if ( (WC->wc_default_view == VIEW_CALENDAR) || (WC->wc_default_view == VIEW_TASKS) ) { + if ( (WCC->wc_default_view == VIEW_CALENDAR) || (WCC->wc_default_view == VIEW_TASKS) ) { strcpy(epdata.desired_content_type_1, "text/calendar"); } - else if (WC->wc_default_view == VIEW_ADDRESSBOOK) { + else if (WCC->wc_default_view == VIEW_ADDRESSBOOK) { strcpy(epdata.desired_content_type_1, "text/vcard"); strcpy(epdata.desired_content_type_2, "text/x-vcard"); } diff --git a/webcit/groupdav_main.c b/webcit/groupdav_main.c index c31b40b9e..5df6188f2 100644 --- a/webcit/groupdav_main.c +++ b/webcit/groupdav_main.c @@ -84,82 +84,34 @@ void euid_unescapize(char *target, const char *source) { /* * Main entry point for GroupDAV requests */ -void groupdav_main(HashList *HTTPHeaders, - StrBuf *DavPathname, - StrBuf *dav_content_type, - int dav_content_length, - StrBuf *dav_content, - int Offset -) { +void groupdav_main(void) +{ wcsession *WCC = WC; - void *vLine; - char dav_ifmatch[256]; - int dav_depth; - char *ds; int i, len; - strcpy(dav_ifmatch, ""); - dav_depth = 0; - - if ((StrLength(WCC->Hdr->HR.http_host) == 0) && - GetHash(HTTPHeaders, HKEY("HOST"), &vLine) && - (vLine != NULL)) { - WCC->Hdr->HR.http_host = (StrBuf*)vLine; - } - if (GetHash(HTTPHeaders, HKEY("IF-MATCH"), &vLine) && - (vLine != NULL)) { - safestrncpy(dav_ifmatch, ChrPtr((StrBuf*)vLine), - sizeof dav_ifmatch); - } - if (GetHash(HTTPHeaders, HKEY("DEPTH"), &vLine) && - (vLine != NULL)) { - if (!strcasecmp(ChrPtr((StrBuf*)vLine), "infinity")) { - dav_depth = 32767; - } - else if (strcmp(ChrPtr((StrBuf*)vLine), "0") == 0) { - dav_depth = 0; - } - else if (strcmp(ChrPtr((StrBuf*)vLine), "1") == 0) { - dav_depth = 1; - } - } - - if (!WC->logged_in) { - hprintf("HTTP/1.1 401 Unauthorized\r\n"); - groupdav_common_headers(); - hprintf("WWW-Authenticate: Basic realm=\"%s\"\r\n", - ChrPtr(WCC->serv_info->serv_humannode)); - hprintf("Content-Length: 0\r\n"); - end_burst(); - return; - } - - StrBufUnescape(DavPathname, 0); + StrBufUnescape(WCC->Hdr->HR.ReqLine, 0); - /* Remove any stray double-slashes in pathname */ - while (ds=strstr(ChrPtr(DavPathname), "//"), ds != NULL) { - strcpy(ds, ds+1); - } + StrBufStripSlashes(WCC->Hdr->HR.ReqLine, 0); /* * If there's an If-Match: header, strip out the quotes if present, and * then if all that's left is an asterisk, make it go away entirely. */ - len = strlen(dav_ifmatch); + len = StrLength(WCC->Hdr->HR.dav_ifmatch); if (len > 0) { - stripltlen(dav_ifmatch, &len); - if (dav_ifmatch[0] == '\"') { - memmove (dav_ifmatch, &dav_ifmatch[1], len); + StrBufTrim(WCC->Hdr->HR.dav_ifmatch); + if (ChrPtr(WCC->Hdr->HR.dav_ifmatch)[0] == '\"') { + StrBufCutLeft(WCC->Hdr->HR.dav_ifmatch, 1); len --; for (i=0; iHdr->HR.dav_ifmatch)[i] == '\"') { + StrBufCutAt(WCC->Hdr->HR.dav_ifmatch, i, NULL); + len = StrLength(WCC->Hdr->HR.dav_ifmatch); } } } - if (!strcmp(dav_ifmatch, "*")) { - strcpy(dav_ifmatch, ""); + if (!strcmp(ChrPtr(WCC->Hdr->HR.dav_ifmatch), "*")) { + FlushStrBuf(WCC->Hdr->HR.dav_ifmatch); } } @@ -171,7 +123,7 @@ void groupdav_main(HashList *HTTPHeaders, * other variants of DAV in the future. */ case eOPTIONS: - groupdav_options(DavPathname); + groupdav_options(); break; @@ -180,32 +132,28 @@ void groupdav_main(HashList *HTTPHeaders, * room, or to list all relevant rooms on the server. */ case ePROPFIND: - groupdav_propfind(DavPathname, dav_depth, - dav_content_type, dav_content, - Offset); + groupdav_propfind(); break; /* * The GET method is used for fetching individual items. */ case eGET: - groupdav_get(DavPathname); + groupdav_get(); break; /* * The PUT method is used to add or modify items. */ case ePUT: - groupdav_put(DavPathname, dav_ifmatch, - ChrPtr(dav_content_type), dav_content, - Offset); + groupdav_put(); break; /* * The DELETE method kills, maims, and destroys. */ case eDELETE: - groupdav_delete(DavPathname, dav_ifmatch); + groupdav_delete(); break; default: @@ -236,11 +184,30 @@ void groupdav_identify_host(void) { } +void Header_HandleIfMatch(StrBuf *Line, ParsedHttpHdrs *hdr) +{ + hdr->HR.dav_ifmatch = Line; +} + +void Header_HandleDepth(StrBuf *Line, ParsedHttpHdrs *hdr) +{ + if (!strcasecmp(ChrPtr(Line), "infinity")) { + hdr->HR.dav_depth = 32767; + } + else if (strcmp(ChrPtr(Line), "0") == 0) { + hdr->HR.dav_depth = 0; + } + else if (strcmp(ChrPtr(Line), "1") == 0) { + hdr->HR.dav_depth = 1; + } +} + void InitModule_GROUPDAV (void) { - - WebcitAddUrlHandler(HKEY("groupdav"), do_logout, XHTTP_COMMANDS|COOKIEUNNEEDED|FORCE_SESSIONCLOSE); + WebcitAddUrlHandler(HKEY("groupdav"), groupdav_main, XHTTP_COMMANDS|COOKIEUNNEEDED|FORCE_SESSIONCLOSE); + RegisterHeaderHandler(HKEY("IF-MATCH"), Header_HandleIfMatch); + RegisterHeaderHandler(HKEY("DEPTH"), Header_HandleDepth); } diff --git a/webcit/groupdav_options.c b/webcit/groupdav_options.c index 5f678c1e6..9f1fefcef 100644 --- a/webcit/groupdav_options.c +++ b/webcit/groupdav_options.c @@ -12,7 +12,9 @@ /* * The pathname is always going to be /groupdav/room_name/msg_num */ -void groupdav_options(StrBuf *dav_pathname) { +void groupdav_options(void) +{ + wcsession *WCC = WC; StrBuf *dav_roomname; StrBuf *dav_uid; long dav_msgnum = (-1); @@ -24,8 +26,8 @@ void groupdav_options(StrBuf *dav_pathname) { dav_roomname = NewStrBuf(); dav_uid = NewStrBuf(); - StrBufExtract_token(dav_roomname, dav_pathname, 2, '/'); - StrBufExtract_token(dav_uid, dav_pathname, 3, '/'); + StrBufExtract_token(dav_roomname, WCC->Hdr->HR.ReqLine, 0, '/'); + StrBufExtract_token(dav_uid, WCC->Hdr->HR.ReqLine, 1, '/'); /* * If the room name is blank, the client is doing a top-level OPTIONS. diff --git a/webcit/groupdav_propfind.c b/webcit/groupdav_propfind.c index 00c8d5e3a..b28cb636a 100644 --- a/webcit/groupdav_propfind.c +++ b/webcit/groupdav_propfind.c @@ -49,8 +49,9 @@ long locate_message_by_uid(const char *uid) { * List rooms (or "collections" in DAV terminology) which contain * interesting groupware objects. */ -void groupdav_collection_list(const char *dav_pathname, int dav_depth) +void groupdav_collection_list(void) { + wcsession *WCC = WC; char buf[256]; char roomname[256]; int view; @@ -60,16 +61,13 @@ void groupdav_collection_list(const char *dav_pathname, int dav_depth) int is_groupware_collection = 0; int starting_point = 1; /**< 0 for /, 1 for /groupdav/ */ - if (!strcmp(dav_pathname, "/")) { + if (WCC->Hdr->HR.Handler == NULL) { starting_point = 0; } - else if (!strcasecmp(dav_pathname, "/groupdav")) { + else if (StrLength(WCC->Hdr->HR.ReqLine) == 0) { starting_point = 1; } - else if (!strcasecmp(dav_pathname, "/groupdav/")) { - starting_point = 1; - } - else if ( (!strncasecmp(dav_pathname, "/groupdav/", 10)) && (strlen(dav_pathname) > 10) ) { + else { starting_point = 2; } @@ -117,7 +115,7 @@ void groupdav_collection_list(const char *dav_pathname, int dav_depth) /** * If the client is requesting "/groupdav", show a /groupdav subdirectory. */ - if ((starting_point + dav_depth) >= 1) { + if ((starting_point + WCC->Hdr->HR.dav_depth) >= 1) { wprintf(""); wprintf(""); groupdav_identify_host(); @@ -159,14 +157,18 @@ void groupdav_collection_list(const char *dav_pathname, int dav_depth) * GroupDAV calendar even if the user has switched it to a * Calendar List view. */ - if ((view == VIEW_CALENDAR) || (view == VIEW_TASKS) || (view == VIEW_ADDRESSBOOK) ) { + if ((view == VIEW_CALENDAR) || + (view == VIEW_TASKS) || + (view == VIEW_ADDRESSBOOK) || + (view == VIEW_NOTES) || + (view == VIEW_JOURNAL) ) { is_groupware_collection = 1; } else { is_groupware_collection = 0; } - if ( (is_groupware_collection) && ((starting_point + dav_depth) >= 2) ) { + if ( (is_groupware_collection) && ((starting_point + WCC->Hdr->HR.dav_depth) >= 2) ) { wprintf(""); wprintf(""); @@ -184,15 +186,21 @@ void groupdav_collection_list(const char *dav_pathname, int dav_depth) wprintf(""); switch(view) { - case VIEW_CALENDAR: - wprintf(""); - break; - case VIEW_TASKS: - wprintf(""); - break; - case VIEW_ADDRESSBOOK: - wprintf(""); - break; + case VIEW_CALENDAR: + wprintf(""); + break; + case VIEW_TASKS: + wprintf(""); + break; + case VIEW_ADDRESSBOOK: + wprintf(""); + break; + case VIEW_NOTES: + wprintf(""); + break; + case VIEW_JOURNAL: + wprintf(""); + break; } wprintf(""); @@ -214,7 +222,9 @@ void groupdav_collection_list(const char *dav_pathname, int dav_depth) /* * The pathname is always going to be /groupdav/room_name/msg_num */ -void groupdav_propfind(StrBuf *dav_pathname, int dav_depth, StrBuf *dav_content_type, StrBuf *dav_content, int offset) { +void groupdav_propfind(void) +{ + wcsession *WCC = WC; StrBuf *dav_roomname; StrBuf *dav_uid; StrBuf *MsgNum; @@ -233,15 +243,15 @@ void groupdav_propfind(StrBuf *dav_pathname, int dav_depth, StrBuf *dav_content_ dav_roomname = NewStrBuf(); dav_uid = NewStrBuf(); - StrBufExtract_token(dav_roomname, dav_pathname, 2, '/'); - StrBufExtract_token(dav_uid, dav_pathname, 3, '/'); + StrBufExtract_token(dav_roomname, WCC->Hdr->HR.ReqLine, 0, '/'); + StrBufExtract_token(dav_uid, WCC->Hdr->HR.ReqLine, 1, '/'); /* * If the room name is blank, the client is requesting a * folder list. */ if (StrLength(dav_roomname) == 0) { - groupdav_collection_list(ChrPtr(dav_pathname), dav_depth); + groupdav_collection_list(); FreeStrBuf(&dav_roomname); FreeStrBuf(&dav_uid); return; diff --git a/webcit/groupdav_put.c b/webcit/groupdav_put.c index 7f4cc810c..bacd77e0d 100644 --- a/webcit/groupdav_put.c +++ b/webcit/groupdav_put.c @@ -15,8 +15,9 @@ * component. This would be for webcal:// 'publish' operations, not * for GroupDAV. */ -void groupdav_put_bigics(StrBuf *dav_content, int offset) +void groupdav_put_bigics(void) { + wcsession *WCC = WC; char buf[1024]; /* @@ -37,7 +38,7 @@ void groupdav_put_bigics(StrBuf *dav_content, int offset) return; } - serv_write(ChrPtr(dav_content) + offset, StrLength(dav_content) - offset); + serv_write(WCC->upload, WCC->upload_length); serv_printf("\n000"); /* Report success and not much else. */ @@ -52,13 +53,12 @@ void groupdav_put_bigics(StrBuf *dav_content, int offset) /* * The pathname is always going to take one of two formats: - * /groupdav/room_name/euid (GroupDAV) - * /groupdav/room_name (webcal) + * [/groupdav/]room_name/euid (GroupDAV) + * [/groupdav/]room_name (webcal) */ -void groupdav_put(StrBuf *dav_pathname, char *dav_ifmatch, - const char *dav_content_type, StrBuf *dav_content, - int offset) +void groupdav_put(void) { + wcsession *WCC = WC; StrBuf *dav_roomname; StrBuf *dav_uid; long new_msgnum = (-2L); @@ -66,7 +66,7 @@ void groupdav_put(StrBuf *dav_pathname, char *dav_ifmatch, char buf[SIZ]; int n = 0; - if (StrBufNum_tokens(dav_pathname, '/') < 3) { + if (StrBufNum_tokens(WCC->Hdr->HR.ReqLine, '/') < 2) { hprintf("HTTP/1.1 404 not found\r\n"); groupdav_common_headers(); hprintf("Content-Type: text/plain\r\n"); @@ -77,8 +77,8 @@ void groupdav_put(StrBuf *dav_pathname, char *dav_ifmatch, dav_roomname = NewStrBuf();; dav_uid = NewStrBuf();; - StrBufExtract_token(dav_roomname, dav_pathname, 2, '/'); - StrBufExtract_token(dav_uid, dav_pathname, 3, '/'); + StrBufExtract_token(dav_roomname, WCC->Hdr->HR.ReqLine, 0, '/'); + StrBufExtract_token(dav_uid, WCC->Hdr->HR.ReqLine, 1, '/'); if ((!strcasecmp(ChrPtr(dav_uid), "ics")) || (!strcasecmp(ChrPtr(dav_uid), "calendar.ics"))) { FlushStrBuf(dav_uid); @@ -107,14 +107,14 @@ void groupdav_put(StrBuf *dav_pathname, char *dav_ifmatch, * client is expecting. If not, the server probably contains a newer * version, so we fail... */ - if (!IsEmptyStr(dav_ifmatch)) { - lprintf(9, "dav_ifmatch: %s\n", dav_ifmatch); + if (StrLength(WCC->Hdr->HR.dav_ifmatch) > 0) { + lprintf(9, "dav_ifmatch: %s\n", WCC->Hdr->HR.dav_ifmatch); old_msgnum = locate_message_by_uid(ChrPtr(dav_uid)); lprintf(9, "old_msgnum: %ld\n", old_msgnum); - if (atol(dav_ifmatch) != old_msgnum) { + if (StrTol(WCC->Hdr->HR.dav_ifmatch) != old_msgnum) { hprintf("HTTP/1.1 412 Precondition Failed\r\n"); lprintf(9, "HTTP/1.1 412 Precondition Failed (ifmatch=%ld, old_msgnum=%ld)\r\n", - atol(dav_ifmatch), old_msgnum); + StrTol(WCC->Hdr->HR.dav_ifmatch), old_msgnum); groupdav_common_headers(); hprintf("Content-Length: 0\r\n"); end_burst(); @@ -127,7 +127,7 @@ void groupdav_put(StrBuf *dav_pathname, char *dav_ifmatch, /** PUT on the collection itself uploads an ICS of the entire collection. */ if (StrLength(dav_uid) == 0) { - groupdav_put_bigics(dav_content, offset); + groupdav_put_bigics(); FreeStrBuf(&dav_roomname); FreeStrBuf(&dav_uid); return; @@ -151,8 +151,8 @@ void groupdav_put(StrBuf *dav_pathname, char *dav_ifmatch, } /* Send the content to the Citadel server */ - serv_printf("Content-type: %s\n\n", dav_content_type); - serv_puts(ChrPtr(dav_content) + offset); + serv_printf("Content-type: %s\n\n", WCC->upload_content_type); + serv_puts(WCC->upload); serv_puts("\n000"); /* Fetch the reply from the Citadel server */ diff --git a/webcit/webcit.c b/webcit/webcit.c index 08dff5259..1f9fd521d 100644 --- a/webcit/webcit.c +++ b/webcit/webcit.c @@ -366,14 +366,29 @@ void display_success(char *successmessage) * Authorization required page * This is probably temporary and should be revisited */ -void authorization_required(const char *message) +void authorization_required(void) { + wcsession *WCC = WC; + const char *message = ""; + hprintf("HTTP/1.1 401 Authorization Required\r\n"); + hprintf( + "Server: %s / %s\r\n" + "Connection: close\r\n", + PACKAGE_STRING, ChrPtr(WC->serv_info->serv_software) + ); hprintf("WWW-Authenticate: Basic realm=\"%s\"\r\n", ChrPtr(WC->serv_info->serv_humannode)); hprintf("Content-Type: text/html\r\n"); wprintf("

"); wprintf(_("Authorization Required")); wprintf("

\r\n"); + + + if (WCC->ImportantMsg != NULL) + message = ChrPtr(WCC->ImportantMsg); + else if (WCC->ImportantMessage != NULL) + message = WCC->ImportantMessage; + wprintf(_("The resource you requested requires a valid username and password. " "You could not be logged in: %s\n"), message); wDumpContent(0); @@ -548,8 +563,6 @@ void session_loop(void) int xhttp; StrBuf *Buf; - char buf[SIZ]; - /* * We stuff these with the values coming from the client cookies, * so we can use them to reconnect a timed out session if we have to. @@ -620,7 +633,8 @@ void session_loop(void) WCC->Hdr->c_password, Buf); } else { /* Should only display when password is wrong */ - authorization_required(&buf[4]); + WCC->ImportantMsg = NewStrBufPlain(ChrPtr(Buf) + 4, StrLength(Buf) - 4); + authorization_required(); FreeStrBuf(&Buf); goto SKIP_ALL_THIS_CRAP; } @@ -676,10 +690,25 @@ void session_loop(void) } /* When all else fais, display the main menu. */ else { - if (!WCC->logged_in) - display_login(NULL); - else - display_main_menu(); + /* + * ordinary browser users get a nice login screen, DAV etc. requsets + * are given a 401 so they can handle it appropriate. + */ + if (!WCC->logged_in) { + if (xhttp) + authorization_required(); + else + display_login(NULL); + } + /* + * Toplevel dav requests? or just a flat browser request? + */ + else { + if (xhttp) + groupdav_main(); + else + display_main_menu(); + } } SKIP_ALL_THIS_CRAP: @@ -755,6 +784,7 @@ InitModule_WEBCIT WebcitAddUrlHandler(HKEY("ajax_servcmd"), ajax_servcmd, 0); WebcitAddUrlHandler(HKEY("webcit"), blank_page, URLNAMESPACE); + WebcitAddUrlHandler(HKEY("401"), authorization_required, ANONYMOUS|COOKIEUNNEEDED); RegisterConditional(HKEY("COND:IMPMSG"), 0, ConditionalImportantMesage, CTX_NONE); RegisterNamespace("CSSLOCAL", 0, 0, tmplput_csslocal, CTX_NONE); RegisterNamespace("IMPORTANTMESSAGE", 0, 0, tmplput_importantmessage, CTX_NONE); diff --git a/webcit/webcit.h b/webcit/webcit.h index bc7341dc7..b1f619ea0 100644 --- a/webcit/webcit.h +++ b/webcit/webcit.h @@ -415,6 +415,7 @@ typedef struct _HdrRefs { time_t if_modified_since; int gzip_ok; /**< Nonzero if Accept-encoding: gzip */ int prohibit_caching; + int dav_depth; /* these are references into Hdr->HTTPHeaders, so we don't need to free them. */ StrBuf *ContentType; @@ -424,7 +425,7 @@ typedef struct _HdrRefs { StrBuf *browser_host; StrBuf *user_agent; StrBuf *plainauth; - + StrBuf *dav_ifmatch; const WebcitHandler *Handler; } HdrRefs; @@ -725,7 +726,6 @@ void text_to_server(char *ptr); void text_to_server_qp(char *ptr); void confirm_delete_msg(void); void display_success(char *); -void authorization_required(const char *message); void CheckAuthBasic(ParsedHttpHdrs *hdr); void GetAuthBasic(ParsedHttpHdrs *hdr); void server_to_text(void); -- 2.30.2