From 1a9e08616fa839db9a46a4f2c6d9e34420150b81 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Wilfried=20G=C3=B6esgens?= Date: Sun, 24 Jan 2010 21:59:37 +0000 Subject: [PATCH] * merge from dav_rework: * modularize the parser for load_msg_ptrs * add parser that has the euid * add work on the URL parsers * unfinished: new propfind; is #ifdefed --- webcit/bbsview_renderer.c | 1 + webcit/calendar.c | 2 + webcit/event.c | 2 +- webcit/groupdav.h | 2 + webcit/groupdav_main.c | 104 ++++++++++++++- webcit/groupdav_propfind.c | 261 +++++++++++++++++++++++++++++++++++++ webcit/marchlist.c | 6 +- webcit/messages.c | 87 +++++-------- webcit/messages.h | 38 +++++- webcit/msg_renderers.c | 59 +++++++++ webcit/notes.c | 3 +- webcit/roomlist.c | 166 ++++++++++++++--------- webcit/roomops.c | 4 +- webcit/roomops.h | 8 ++ webcit/smtpqueue.c | 2 +- webcit/summary.c | 4 +- webcit/tasks.c | 3 +- webcit/useredit.c | 2 +- webcit/vcard_edit.c | 7 +- webcit/webcit.c | 55 ++++++-- webcit/webcit.h | 8 +- webcit/wiki.c | 1 + 22 files changed, 675 insertions(+), 150 deletions(-) diff --git a/webcit/bbsview_renderer.c b/webcit/bbsview_renderer.c index 11b7734e0..fec17d117 100644 --- a/webcit/bbsview_renderer.c +++ b/webcit/bbsview_renderer.c @@ -311,6 +311,7 @@ InitModule_BBSVIEWRENDERERS VIEW_BBS, bbsview_GetParamsGetServerCall, bbsview_PrintViewHeader, + NULL, bbsview_LoadMsgFromServer, bbsview_RenderView_or_Tail, bbsview_Cleanup); diff --git a/webcit/calendar.c b/webcit/calendar.c index 20949a2de..0c280372f 100644 --- a/webcit/calendar.c +++ b/webcit/calendar.c @@ -885,6 +885,7 @@ InitModule_CALENDAR VIEW_CALENDAR, calendar_GetParamsGetServerCall, NULL, + NULL, calendar_LoadMsgFromServer, calendar_RenderView_or_Tail, calendar_Cleanup); @@ -893,6 +894,7 @@ InitModule_CALENDAR VIEW_CALBRIEF, calendar_GetParamsGetServerCall, NULL, + NULL, calendar_LoadMsgFromServer, calendar_RenderView_or_Tail, calendar_Cleanup); diff --git a/webcit/event.c b/webcit/event.c index 7433e5312..3d2be8cb7 100644 --- a/webcit/event.c +++ b/webcit/event.c @@ -1196,7 +1196,7 @@ STARTOVER: for (attendee = icalcomponent_get_first_property(vevent, ICAL_ATTENDE summary(); } else { - readloop(readfwd); + readloop(readfwd, eUseDefault); } } } diff --git a/webcit/groupdav.h b/webcit/groupdav.h index fdeed3cf4..773444a90 100644 --- a/webcit/groupdav.h +++ b/webcit/groupdav.h @@ -27,3 +27,5 @@ void euid_escapize(char *, const char *); void euid_unescapize(char *, const char *); void groupdav_identify_host(void); void groupdav_identify_hosthdr(void); + +void RegisterDAVNamespace(const char * UrlString, long UrlSLen, const char *DisplayName, long dslen, WebcitHandlerFunc F, long Flags); diff --git a/webcit/groupdav_main.c b/webcit/groupdav_main.c index 9b75c5041..b63a0da50 100644 --- a/webcit/groupdav_main.c +++ b/webcit/groupdav_main.c @@ -9,6 +9,9 @@ #include "webserver.h" #include "groupdav.h" +extern HashList *HandlerHash; + +HashList *DavNamespaces = NULL; /* * Output HTTP headers which are common to all requests. @@ -183,6 +186,19 @@ void groupdav_identify_host(void) { } } + +void tmplput_GROUPDAV_HOSTNAME(StrBuf *Target, WCTemplputParams *TP) +{ + wcsession *WCC = WC; + + if (StrLength(WCC->Hdr->HR.http_host)!=0) { + StrBufAppendPrintf(Target, + "%s://%s", + (is_https ? "https" : "http"), + ChrPtr(WCC->Hdr->HR.http_host)); + } +} + /* * Output our host prefix for globally absolute URL's. */ @@ -214,13 +230,99 @@ void Header_HandleDepth(StrBuf *Line, ParsedHttpHdrs *hdr) hdr->HR.dav_depth = 1; } } +int Conditional_DAV_DEPTH(StrBuf *Target, WCTemplputParams *TP) +{ + return WC->Hdr->HR.dav_depth == GetTemplateTokenNumber(Target, TP, 2, 0); +} + + +void RegisterDAVNamespace(const char * UrlString, long UrlSLen, const char *DisplayName, long dslen, WebcitHandlerFunc F, long Flags) +{ + void *vHandler; + + /* first put it in... */ + WebcitAddUrlHandler(UrlString, UrlSLen, DisplayName, dslen, F, Flags|PARSE_REST_URL); + /* get it out again... */ + GetHash(HandlerHash, UrlString, UrlSLen, &vHandler); + /* and keep a copy of it, so we can compare it later */ + Put(DavNamespaces, UrlString, UrlSLen, vHandler, reference_free_handler); +} + +int Conditional_DAV_NS(StrBuf *Target, WCTemplputParams *TP) +{ + wcsession *WCC = WC; + void *vHandler; + const char *NS; + long NSLen; + + GetTemplateTokenString(NULL, TP, 2, &NS, &NSLen); + GetHash(HandlerHash, NS, NSLen, &vHandler); + return WCC->Hdr->HR.Handler == vHandler; +} + + +int Conditional_DAV_NSCURRENT(StrBuf *Target, WCTemplputParams *TP) +{ + wcsession *WCC = WC; + void *vHandler; + + vHandler = CTX; + return WCC->Hdr->HR.Handler == vHandler; +} + +void tmplput_DAV_NAMESPACE(StrBuf *Target, WCTemplputParams *TP) +{ + wcsession *WCC = WC; + + if (TP->Filter.ContextType == CTX_DAVNS) { + WebcitHandler *H; + H = (WebcitHandler*) CTX; + StrBufAppendTemplate(Target, TP, H->Name, 0); + } + else if (WCC->Hdr->HR.Handler != NULL) { + StrBufAppendTemplate(Target, TP, WCC->Hdr->HR.Handler->Name, 0); + } +} + +void +ServerStartModule_DAV +(void) +{ + + DavNamespaces = NewHash(1, NULL); + +} + +void +ServerShutdownModule_DAV +(void) +{ + DeleteHash(&DavNamespaces); +} + + + void InitModule_GROUPDAV (void) { - WebcitAddUrlHandler(HKEY("groupdav"), "", 0, groupdav_main, XHTTP_COMMANDS|COOKIEUNNEEDED|FORCE_SESSIONCLOSE); +// WebcitAddUrlHandler(HKEY("groupdav"), "", 0, groupdav_main, XHTTP_COMMANDS|COOKIEUNNEEDED|FORCE_SESSIONCLOSE); + RegisterDAVNamespace(HKEY("groupdav"), HKEY("GroupDAV"), groupdav_main, XHTTP_COMMANDS|COOKIEUNNEEDED|FORCE_SESSIONCLOSE); + + RegisterNamespace("DAV:HOSTNAME", 0, 0, tmplput_GROUPDAV_HOSTNAME, NULL, CTX_NONE); + + RegisterConditional(HKEY("COND:DAV:NS"), 0, Conditional_DAV_NS, CTX_NONE); + + RegisterIterator("DAV:NS", 0, DavNamespaces, NULL, + NULL, NULL, CTX_DAVNS, CTX_NONE, IT_NOFLAG); + + + RegisterConditional(HKEY("COND:DAV:NSCURRENT"), 0, Conditional_DAV_NSCURRENT, CTX_DAVNS); + RegisterNamespace("DAV:NAMESPACE", 0, 1, tmplput_DAV_NAMESPACE, NULL, CTX_NONE); + RegisterHeaderHandler(HKEY("IF-MATCH"), Header_HandleIfMatch); RegisterHeaderHandler(HKEY("DEPTH"), Header_HandleDepth); + RegisterConditional(HKEY("COND:DAV:DEPTH"), 1, Conditional_DAV_DEPTH, CTX_NONE); } diff --git a/webcit/groupdav_propfind.c b/webcit/groupdav_propfind.c index fbfae2309..5973bf240 100644 --- a/webcit/groupdav_propfind.c +++ b/webcit/groupdav_propfind.c @@ -42,6 +42,160 @@ long locate_message_by_uid(const char *uid) { return(retval); } +const folder *GetRESTFolder(int IgnoreFloor) +{ + wcsession *WCC = WC; + void *vFolder; + const folder *ThisFolder = NULL; + HashPos *itd, *itfl; + StrBuf * Dir; + void *vDir; + long len; + const char *Key; + int i, j, urlp; + int delta; + + + + itfl = GetNewHashPos(WCC->Floors, 0); + + while (GetNextHashPos(WCC->Floors, itfl, &len, &Key, &vFolder) && + (ThisFolder == NULL)) + { + ThisFolder = vFolder; + if (!IgnoreFloor && /* so we can handle legacy URLS... */ + (ThisFolder->Floor != WCC->CurrentFloor)) + continue; + + + if (ThisFolder->nRoomNameParts > 1) + { + /*TODO: is that number all right? */ + if (GetCount(WCC->Directory) - ThisFolder->nRoomNameParts != 2) + continue; + + itd = GetNewHashPos(WCC->Directory, 0); + GetNextHashPos(WCC->Directory, itd, &len, &Key, &vDir); //TODO: how many to fast forward? + /* Fast forward the floorname we checked above... */ + for (i = 0, j = 1; + (i > ThisFolder->nRoomNameParts) && (j > urlp); + i++, j++, GetNextHashPos(WCC->Directory, itd, &len, &Key, &vDir)) + { + Dir = (StrBuf*)vDir; + if (strcmp(ChrPtr(ThisFolder->RoomNameParts[i]), + ChrPtr(Dir)) != 0) + { + DeleteHashPos(&itd); + continue; + } + } + DeleteHashPos(&itd); + DeleteHashPos(&itfl); + return ThisFolder; + } + else { + + if (GetCount(WCC->Directory) - ThisFolder->nRoomNameParts != 2) + continue; + itd = GetNewHashPos(WCC->Directory, 0); + + + if (!GetNextHashPos(WCC->Directory, + itd, &len, &Key, &vDir) || + (vDir == NULL)) + { + DeleteHashPos(&itd); + + lprintf(0, "5\n"); + continue; + } + DeleteHashPos(&itd); + Dir = (StrBuf*) vDir; + if (strcmp(ChrPtr(ThisFolder->name), + ChrPtr(Dir)) + != 0) + { + DeleteHashPos(&itd); + + lprintf(0, "5\n"); + continue; + } + + DeleteHashPos(&itfl); + DeleteHashPos(&itd); + + return ThisFolder;; + } + } + DeleteHashPos(&itfl); + return NULL; +} + + + + +long GotoRestRoom() +{ + wcsession *WCC = WC; + long Count; + long State; + const folder *ThisFolder; + + State = REST_TOPLEVEL; + + if (WCC->Hdr->HR.Handler != NULL) + State |= REST_IN_NAMESPACE; + + Count = GetCount(WCC->Directory); + + if (Count == 0) return State; + + if (Count >= 1) State |=REST_IN_FLOOR; + if (Count == 1) return State; + + if (Count >= 3) { + State |= REST_IN_FLOOR; + ThisFolder = GetRESTFolder(0); + WCC->ThisRoom = ThisFolder; + if (ThisFolder != NULL) + { + gotoroom(ThisFolder->name); + State |= REST_IN_ROOM; + return State; + } + + } + + + /* + * More than 3 params and no floor found? + * -> fall back to old non-floored notation + */ + + if ((Count >= 3) && (WCC->CurrentFloor == NULL)) + { + ThisFolder = GetRESTFolder(1); + WCC->ThisRoom = ThisFolder; + if (ThisFolder != NULL) + { + gotoroom(ThisFolder->name); + State |= REST_IN_ROOM; + return State; + } + + + } + + + if (Count == 3) return State; + + /// TODO: ID detection + /// TODO: File detection + + + return State; +} + /* @@ -241,6 +395,7 @@ void groupdav_propfind(void) int i; char datestring[256]; time_t now; + long State; now = time(NULL); http_datestring(datestring, sizeof datestring, now); @@ -249,6 +404,48 @@ void groupdav_propfind(void) dav_uid = NewStrBuf(); StrBufExtract_token(dav_roomname, WCC->Hdr->HR.ReqLine, 0, '/'); StrBufExtract_token(dav_uid, WCC->Hdr->HR.ReqLine, 1, '/'); +#ifdef DEV_RESTDAV + /* + * If the room name is blank, the client is requesting a + * folder list. + */ + State = GotoRestRoom(); + if (((State & REST_IN_ROOM) == 0) || + (((State & (REST_GOT_EUID|REST_GOT_ID|REST_GOT_FILENAME)) == 0) && + (WCC->Hdr->HR.dav_depth == 0))) + { + 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. + */ + hprintf("HTTP/1.0 207 Multi-Status\r\n"); + groupdav_common_headers(); + hprintf("Date: %s\r\n", datestring); + hprintf("Content-type: text/xml\r\n"); + hprintf("Content-encoding: identity\r\n"); + + begin_burst(); + + + /* + * If the client is requesting the root, show a root node. + */ + do_template("dav_propfind_top", NULL); + end_burst(); + FreeStrBuf(&dav_roomname); + FreeStrBuf(&dav_uid); + return; + } + + if ((State & (REST_GOT_EUID|REST_GOT_ID|REST_GOT_FILENAME)) == 0) { + readloop(headers, eReadEUIDS); + return; + + } +#endif /* * If the room name is blank, the client is requesting a @@ -479,3 +676,67 @@ void groupdav_propfind(void) free(msgs); } } + + + +int ParseMessageListHeaders_EUID(StrBuf *Line, + const char **pos, + message_summary *Msg, + StrBuf *ConversionBuffer) +{ + Msg->euid = NewStrBuf(); + StrBufExtract_NextToken(Msg->euid, Line, pos, '|'); + return StrLength(Msg->euid) > 0; +} + +int DavUIDL_GetParamsGetServerCall(SharedMessageStatus *Stat, + void **ViewSpecific, + long oper, + char *cmd, + long len) +{ + Stat->defaultsortorder = 0; + Stat->sortit = 0; + Stat->load_seen = 0; + Stat->maxmsgs = 9999999; + + snprintf(cmd, len, "MSGS ALL|||2"); + return 200; +} + +int DavUIDL_RenderView_or_Tail(SharedMessageStatus *Stat, + void **ViewSpecific, + long oper) +{ + + DoTemplate(HKEY("msg_listview"),NULL,&NoCtx); + + return 0; +} + +int DavUIDL_Cleanup(void **ViewSpecific) +{ + /* Note: wDumpContent() will output one additional tag. */ + /* We ought to move this out into template */ + wDumpContent(1); + + return 0; +} + + + + +void +InitModule_PROPFIND +(void) +{ + RegisterReadLoopHandlerset( + eReadEUIDS, + DavUIDL_GetParamsGetServerCall, + NULL, /// TODO: is this right? + ParseMessageListHeaders_EUID, + NULL, //// "" + DavUIDL_RenderView_or_Tail, + DavUIDL_Cleanup); + +} diff --git a/webcit/marchlist.c b/webcit/marchlist.c index 8f17d9a52..63cd84cc4 100644 --- a/webcit/marchlist.c +++ b/webcit/marchlist.c @@ -113,8 +113,8 @@ void gotonext(void) * If it is, pop the first room off the list and go there. */ if (havebstr("startmsg")) { - readloop(readnew); - return; + readloop(readnew, eUseDefault); + return; } if (WC->march == NULL) { @@ -187,7 +187,7 @@ void ungoto(void) StrBuf *Buf; if (havebstr("startmsg")) { - readloop(readnew); + readloop(readnew, eUseDefault); return; } diff --git a/webcit/messages.c b/webcit/messages.c index 39a1ecf95..bb17f7296 100644 --- a/webcit/messages.c +++ b/webcit/messages.c @@ -572,9 +572,10 @@ message_summary *ReadOneMessageSummary(StrBuf *RawMessage, const char *DefaultSu * * servcmd: the citadel command to send to the citserver */ -int load_msg_ptrs(const char *servcmd, SharedMessageStatus *Stat) +int load_msg_ptrs(const char *servcmd, + SharedMessageStatus *Stat, + load_msg_ptrs_detailheaders LH) { - StrBuf* FoundCharset = NULL; wcsession *WCC = WC; message_summary *Msg; StrBuf *Buf, *Buf2; @@ -633,47 +634,11 @@ int load_msg_ptrs(const char *servcmd, SharedMessageStatus *Stat) if (StrLength(Buf) < 32) skipit = 1; } - if (!skipit) { - Msg->from = NewStrBufPlain(NULL, StrLength(Buf)); - StrBufExtract_NextToken(Buf2, Buf, &Ptr, '|'); - if (StrLength(Buf2) != 0) { - /* Handle senders with RFC2047 encoding */ - StrBuf_RFC822_to_Utf8(Msg->from, Buf2, WCC->DefaultCharset, FoundCharset); - } - - /* node name */ - StrBufExtract_NextToken(Buf2, Buf, &Ptr, '|'); - if ((StrLength(Buf2) !=0 ) && - ( ((WCC->CurRoom.QRFlags & QR_NETWORK) - || ((strcasecmp(ChrPtr(Buf2), ChrPtr(WCC->serv_info->serv_nodename)) - && (strcasecmp(ChrPtr(Buf2), ChrPtr(WCC->serv_info->serv_fqdn)))))))) - { - StrBufAppendBufPlain(Msg->from, HKEY(" @ "), 0); - StrBufAppendBuf(Msg->from, Buf2, 0); - } - - /* Internet address (not used) - * StrBufExtract_token(Msg->inetaddr, Buf, 4, '|'); - */ - StrBufSkip_NTokenS(Buf, &Ptr, '|', 1); - Msg->subj = NewStrBufPlain(NULL, StrLength(Buf)); - StrBufExtract_NextToken(Buf2, Buf, &Ptr, '|'); - if (StrLength(Buf2) == 0) - StrBufAppendBufPlain(Msg->subj, _("(no subject)"), -1,0); - else { - StrBuf_RFC822_to_Utf8(Msg->subj, Buf2, WCC->DefaultCharset, FoundCharset); - if ((StrLength(Msg->subj) > 75) && - (StrBuf_Utf8StrLen(Msg->subj) > 75)) { - StrBuf_Utf8StrCut(Msg->subj, 72); - StrBufAppendBufPlain(Msg->subj, HKEY("..."), 0); - } - } - - if ((StrLength(Msg->from) > 25) && - (StrBuf_Utf8StrLen(Msg->from) > 25)) { - StrBuf_Utf8StrCut(Msg->from, 23); - StrBufAppendBufPlain(Msg->from, HKEY("..."), 0); - } + if ((!skipit) && (LH != NULL)) { + if (!LH(Buf, &Ptr, Msg, Buf2)){ + free(Msg); + continue; + } } n = Msg->msgnum; Put(WCC->summ, (const char *)&n, sizeof(n), Msg, DestroyMessageSummary); @@ -745,6 +710,7 @@ typedef struct _RoomRenderer{ LoadMsgFromServer_func LoadMsgFromServer; RenderView_or_Tail_func RenderView_or_Tail; View_Cleanup_func ViewCleanup; + load_msg_ptrs_detailheaders LHParse; } RoomRenderer; @@ -753,7 +719,7 @@ typedef struct _RoomRenderer{ * * Set oper to "readnew" or "readold" or "readfwd" or "headers" or "readgt" or "readlt" or "do_search" */ -void readloop(long oper) +void readloop(long oper, eCustomRoomRenderer ForceRenderer) { RoomRenderer *ViewMsg; void *vViewMsg; @@ -786,7 +752,10 @@ void readloop(long oper) Stat.maxload = 10000; Stat.lowest_found = (-1); Stat.highest_found = (-1); - GetHash(ReadLoopHandler, IKEY(WCC->CurRoom.view), &vViewMsg); + if (ForceRenderer == eUseDefault) + GetHash(ReadLoopHandler, IKEY(WCC->CurRoom.view), &vViewMsg); + else + GetHash(ReadLoopHandler, IKEY(ForceRenderer), &vViewMsg); if (vViewMsg == NULL) { WCC->CurRoom.view = VIEW_BBS; GetHash(ReadLoopHandler, IKEY(WCC->CurRoom.view), &vViewMsg); @@ -825,7 +794,7 @@ void readloop(long oper) break; } if (!IsEmptyStr(cmd)) - Stat.nummsgs = load_msg_ptrs(cmd, &Stat); + Stat.nummsgs = load_msg_ptrs(cmd, &Stat, ViewMsg->LHParse); if (Stat.sortit) { CompareFunc SortIt; @@ -1243,7 +1212,7 @@ void post_message(void) * Otherwise, just go to the "read messages" loop. */ else { - readloop(readnew); + readloop(readnew, eUseDefault); } } @@ -1285,7 +1254,7 @@ void display_enter(void) } else if (buf[0] != '2') { /* Any other error means that we cannot continue */ sprintf(WCC->ImportantMessage, "%s", &buf[4]); - readloop(readnew); + readloop(readnew, eUseDefault); return; } @@ -1401,7 +1370,7 @@ void delete_msg(void) serv_getln(buf, sizeof buf); sprintf(WC->ImportantMessage, "%s", &buf[4]); - readloop(readnew); + readloop(readnew, eUseDefault); } @@ -1424,7 +1393,7 @@ void move_msg(void) sprintf(WC->ImportantMessage, (_("The message was not moved."))); } - readloop(readnew); + readloop(readnew, eUseDefault); } @@ -1668,13 +1637,13 @@ void download_postpart(void) { FreeStrBuf(&partnum); } -void h_readnew(void) { readloop(readnew);} -void h_readold(void) { readloop(readold);} -void h_readfwd(void) { readloop(readfwd);} -void h_headers(void) { readloop(headers);} -void h_do_search(void) { readloop(do_search);} -void h_readgt(void) { readloop(readgt);} -void h_readlt(void) { readloop(readlt);} +void h_readnew(void) { readloop(readnew, eUseDefault);} +void h_readold(void) { readloop(readold, eUseDefault);} +void h_readfwd(void) { readloop(readfwd, eUseDefault);} +void h_headers(void) { readloop(headers, eUseDefault);} +void h_do_search(void) { readloop(do_search, eUseDefault);} +void h_readgt(void) { readloop(readgt, eUseDefault);} +void h_readlt(void) { readloop(readlt, eUseDefault);} void jsonMessageListHdr(void) { @@ -1694,7 +1663,7 @@ void jsonMessageList(void) { long oper = (havebstr("query")) ? do_search : readnew; WC->is_ajax = 1; gotoroom(room); - readloop(oper); + readloop(oper, eUseDefault); WC->is_ajax = 0; } @@ -1702,6 +1671,7 @@ void RegisterReadLoopHandlerset( int RoomType, GetParamsGetServerCall_func GetParamsGetServerCall, PrintViewHeader_func PrintViewHeader, + load_msg_ptrs_detailheaders LH, LoadMsgFromServer_func LoadMsgFromServer, RenderView_or_Tail_func RenderView_or_Tail, View_Cleanup_func ViewCleanup @@ -1717,6 +1687,7 @@ void RegisterReadLoopHandlerset( Handler->LoadMsgFromServer = LoadMsgFromServer; Handler->RenderView_or_Tail = RenderView_or_Tail; Handler->ViewCleanup = ViewCleanup; + Handler->LHParse = LH; Put(ReadLoopHandler, IKEY(RoomType), Handler, NULL); } diff --git a/webcit/messages.h b/webcit/messages.h index df6b5f7ef..387cbccff 100644 --- a/webcit/messages.h +++ b/webcit/messages.h @@ -31,6 +31,7 @@ typedef struct _message_summary { long msgnum; /* the message number on the citadel server */ int nhdr; int format_type; + StrBuf *euid; StrBuf *from; /* the author */ StrBuf *to; /* the recipient */ StrBuf *subj; /* the title / subject */ @@ -65,6 +66,12 @@ typedef void (*ExamineMsgHeaderFunc)(message_summary *Msg, StrBuf *HdrLine, StrB void evaluate_mime_part(message_summary *Msg, wc_mime_attachment *Mime); + +typedef enum _eCustomRoomRenderer { + eUseDefault = VIEW_JOURNAL + 100, + eReadEUIDS +}eCustomRoomRenderer; + enum { do_search, headers, @@ -75,6 +82,18 @@ enum { readlt }; +/** + * @brief function to parse the | separated message headers list + * @param Line the raw line with your message data + * @param Msg put your parser results here... + * @param ConversionBuffer if you need some workbuffer, don't free me! + * @returns 0: failure, trash this message. 1: all right, store it + */ +typedef int (*load_msg_ptrs_detailheaders) (StrBuf *Line, + const char **pos, + message_summary *Msg, + StrBuf *ConversionBuffer); + typedef void (*readloop_servcmd)(char *buf, long bufsize); typedef struct _readloopstruct { @@ -84,8 +103,7 @@ typedef struct _readloopstruct { extern readloop_struct rlid[]; - -void readloop(long oper); +void readloop(long oper, eCustomRoomRenderer ForceRenderer); int read_message(StrBuf *Target, const char *tmpl, long tmpllen, long msgnum, @@ -115,7 +133,9 @@ typedef struct _SharedMessageStatus { } SharedMessageStatus; -int load_msg_ptrs(const char *servcmd, SharedMessageStatus *Stat); +int load_msg_ptrs(const char *servcmd, + SharedMessageStatus *Stat, + load_msg_ptrs_detailheaders LH); typedef int (*GetParamsGetServerCall_func)(SharedMessageStatus *Stat, void **ViewSpecific, @@ -161,6 +181,12 @@ void RegisterReadLoopHandlerset( */ PrintViewHeader_func PrintViewHeader, + /** + * LH is the function, you specify if you want to load more than just message + * numbers from the server during the listing fetch operation. + */ + load_msg_ptrs_detailheaders LH, + /** * LoadMsgFromServer is called for every message in the message list: * * which is @@ -196,3 +222,9 @@ LoadMsgFromServer RenderView_or_Tail */ + + +int ParseMessageListHeaders_Detail(StrBuf *Line, + const char **pos, + message_summary *Msg, + StrBuf *ConversionBuffer); diff --git a/webcit/msg_renderers.c b/webcit/msg_renderers.c index 459f8e955..f8fc38e67 100644 --- a/webcit/msg_renderers.c +++ b/webcit/msg_renderers.c @@ -449,6 +449,12 @@ void tmplput_MAIL_SUMM_DATE_BRIEF(StrBuf *Target, WCTemplputParams *TP) StrBufAppendBufPlain(Target, datebuf, -1, 0); } +void tmplput_MAIL_SUMM_EUID(StrBuf *Target, WCTemplputParams *TP) +{ + message_summary *Msg = (message_summary*) CTX; + StrBufAppendTemplate(Target, TP, Msg->euid, 0); +} + void tmplput_MAIL_SUMM_DATE_FULL(StrBuf *Target, WCTemplputParams *TP) { char datebuf[64]; @@ -1155,6 +1161,57 @@ readloop_struct rlid[] = { { {HKEY("readlt")}, servcmd_readlt } }; + +int ParseMessageListHeaders_Detail(StrBuf *Line, + const char **pos, + message_summary *Msg, + StrBuf *ConversionBuffer) +{ + wcsession *WCC = WC; + + Msg->from = NewStrBufPlain(NULL, StrLength(Line)); + StrBufExtract_NextToken(ConversionBuffer, Line, pos, '|'); + if (StrLength(ConversionBuffer) != 0) { + /* Handle senders with RFC2047 encoding */ + StrBuf_RFC822_to_Utf8(Msg->from, ConversionBuffer, WCC->DefaultCharset, NULL); + } + + /* node name */ + StrBufExtract_NextToken(ConversionBuffer, Line, pos, '|'); + if ((StrLength(ConversionBuffer) !=0 ) && + ( ((WCC->CurRoom.QRFlags & QR_NETWORK) + || ((strcasecmp(ChrPtr(ConversionBuffer), ChrPtr(WCC->serv_info->serv_nodename)) + && (strcasecmp(ChrPtr(ConversionBuffer), ChrPtr(WCC->serv_info->serv_fqdn)))))))) + { + StrBufAppendBufPlain(Msg->from, HKEY(" @ "), 0); + StrBufAppendBuf(Msg->from, ConversionBuffer, 0); + } + + /* Internet address (not used) + * StrBufExtract_token(Msg->inetaddr, Line, 4, '|'); + */ + StrBufSkip_NTokenS(Line, pos, '|', 1); + Msg->subj = NewStrBufPlain(NULL, StrLength(Line)); + StrBufExtract_NextToken(ConversionBuffer, Line, pos, '|'); + if (StrLength(ConversionBuffer) == 0) + StrBufAppendBufPlain(Msg->subj, _("(no subject)"), -1,0); + else { + StrBuf_RFC822_to_Utf8(Msg->subj, ConversionBuffer, WCC->DefaultCharset, NULL); + if ((StrLength(Msg->subj) > 75) && + (StrBuf_Utf8StrLen(Msg->subj) > 75)) { + StrBuf_Utf8StrCut(Msg->subj, 72); + StrBufAppendBufPlain(Msg->subj, HKEY("..."), 0); + } + } + + if ((StrLength(Msg->from) > 25) && + (StrBuf_Utf8StrLen(Msg->from) > 25)) { + StrBuf_Utf8StrCut(Msg->from, 23); + StrBufAppendBufPlain(Msg->from, HKEY("..."), 0); + } + return 1; +} + /* Spit out the new summary view. This is basically a static page, so clients can cache the layout, all the dirty work is javascript :) */ void new_summary_view(void) { DoTemplate(HKEY("msg_listview"),NULL,&NoCtx); @@ -1222,6 +1279,7 @@ InitModule_MSGRENDERERS VIEW_MAILBOX, mailview_GetParamsGetServerCall, NULL, /// TODO: is this right? + ParseMessageListHeaders_Detail, NULL, //// "" mailview_RenderView_or_Tail, mailview_Cleanup); @@ -1250,6 +1308,7 @@ InitModule_MSGRENDERERS RegisterIterator("MAIL:SUMM:MSGS", 0, NULL, iterate_get_mailsumm_All, NULL,NULL, CTX_MAILSUM, CTX_NONE, IT_NOFLAG); + RegisterNamespace("MAIL:SUMM:EUID", 0, 1, tmplput_MAIL_SUMM_EUID, NULL, CTX_MAILSUM); RegisterNamespace("MAIL:SUMM:DATEBRIEF", 0, 0, tmplput_MAIL_SUMM_DATE_BRIEF, NULL, CTX_MAILSUM); RegisterNamespace("MAIL:SUMM:DATEFULL", 0, 0, tmplput_MAIL_SUMM_DATE_FULL, NULL, CTX_MAILSUM); RegisterNamespace("MAIL:SUMM:DATENO", 0, 0, tmplput_MAIL_SUMM_DATE_NO, NULL, CTX_MAILSUM); diff --git a/webcit/notes.c b/webcit/notes.c index 4001d4b40..835c61f2d 100644 --- a/webcit/notes.c +++ b/webcit/notes.c @@ -351,7 +351,7 @@ void add_new_note(void) { vnote_free(v); } - readloop(readfwd); + readloop(readfwd, eUseDefault); } @@ -446,6 +446,7 @@ InitModule_NOTES VIEW_NOTES, notes_GetParamsGetServerCall, NULL, + NULL, notes_LoadMsgFromServer, NULL, notes_Cleanup); diff --git a/webcit/roomlist.c b/webcit/roomlist.c index 0370a4dce..4405b5c24 100644 --- a/webcit/roomlist.c +++ b/webcit/roomlist.c @@ -35,6 +35,7 @@ HashList *GetFloorListHash(StrBuf *Target, WCTemplputParams *TP) const char *Err; StrBuf *Buf; HashList *floors; + HashList *floorsbyname; HashPos *it; Floor *pFloor; void *vFloor; @@ -48,6 +49,7 @@ HashList *GetFloorListHash(StrBuf *Target, WCTemplputParams *TP) if (WCC->Floors != NULL) return WCC->Floors; WCC->Floors = floors = NewHash(1, Flathash); + WCC->FloorsByName = floorsbyname = NewHash(1, NULL); Buf = NewStrBuf(); pFloor = (Floor*) malloc(sizeof(Floor)); @@ -56,6 +58,7 @@ HashList *GetFloorListHash(StrBuf *Target, WCTemplputParams *TP) pFloor->NRooms = 0; Put(floors, IKEY(pFloor->ID), pFloor, DeleteFloor); + Put(floorsbyname, SKEY(pFloor->Name), pFloor, reference_free_handler); serv_puts("LFLR"); /* get floors */ StrBufTCP_read_line(Buf, &WC->serv_sock, 0, &Err); /* '100', we hope */ @@ -79,6 +82,7 @@ HashList *GetFloorListHash(StrBuf *Target, WCTemplputParams *TP) pFloor->NRooms = StrBufExtractNext_long(Buf, &Pos, '|'); Put(floors, IKEY(pFloor->ID), pFloor, DeleteFloor); + Put(floorsbyname, SKEY(pFloor->Name), pFloor, reference_free_handler); } } FreeStrBuf(&Buf); @@ -97,23 +101,23 @@ HashList *GetFloorListHash(StrBuf *Target, WCTemplputParams *TP) void tmplput_FLOOR_ID(StrBuf *Target, WCTemplputParams *TP) { - Floor *pFloor = (Floor *)(TP->Context); + Floor *myFloor = (Floor *)CTX; - StrBufAppendPrintf(Target, "%d", pFloor->ID); + StrBufAppendPrintf(Target, "%d", myFloor->ID); } void tmplput_FLOOR_NAME(StrBuf *Target, WCTemplputParams *TP) { - Floor *pFloor = (Floor *)(TP->Context); + Floor *myFloor = (Floor *)CTX; - StrBufAppendTemplate(Target, TP, pFloor->Name, 0); + StrBufAppendTemplate(Target, TP, myFloor->Name, 0); } void tmplput_FLOOR_NROOMS(StrBuf *Target, WCTemplputParams *TP) { - Floor *pFloor = (Floor *)(TP->Context); + Floor *myFloor = (Floor *)CTX; - StrBufAppendPrintf(Target, "%d", pFloor->NRooms); + StrBufAppendPrintf(Target, "%d", myFloor->NRooms); } HashList *GetRoomListHashLKRA(StrBuf *Target, WCTemplputParams *TP) { @@ -122,7 +126,9 @@ HashList *GetRoomListHashLKRA(StrBuf *Target, WCTemplputParams *TP) if (WCC->Floors == NULL) GetFloorListHash(Target, TP); serv_puts("LKRA"); - return GetRoomListHash(Target, TP); + if (WCC->Rooms == NULL) + WCC->Rooms = GetRoomListHash(Target, TP); + return WCC->Rooms; } void FlushFolder(folder *room) @@ -444,13 +450,13 @@ int GroupchangeRoomListByFloorRoomPrivFirst(const void *room1, const void *room2 void tmplput_ROOM_NAME(StrBuf *Target, WCTemplputParams *TP) { - folder *Folder = (folder *)(TP->Context); + folder *Folder = (folder *)CTX; StrBufAppendTemplate(Target, TP, Folder->name, 0); } void tmplput_ROOM_BASENAME(StrBuf *Target, WCTemplputParams *TP) { - folder *room = (folder *)(TP->Context); + folder *room = (folder *)CTX; if (room->nRoomNameParts > 1) StrBufAppendTemplate(Target, TP, @@ -460,7 +466,7 @@ void tmplput_ROOM_BASENAME(StrBuf *Target, WCTemplputParams *TP) } void tmplput_ROOM_LEVEL_N_TIMES(StrBuf *Target, WCTemplputParams *TP) { - folder *room = (folder *)(TP->Context); + folder *room = (folder *)CTX; int i; const char *AppendMe; long AppendMeLen; @@ -476,7 +482,7 @@ void tmplput_ROOM_LEVEL_N_TIMES(StrBuf *Target, WCTemplputParams *TP) void tmplput_ROOM_ACL(StrBuf *Target, WCTemplputParams *TP) { - folder *Folder = (folder *)(TP->Context); + folder *Folder = (folder *)CTX; StrBufAppendPrintf(Target, "%ld", Folder->RAFlags, 0); } @@ -484,7 +490,7 @@ void tmplput_ROOM_ACL(StrBuf *Target, WCTemplputParams *TP) void tmplput_ROOM_QRFLAGS(StrBuf *Target, WCTemplputParams *TP) { - folder *Folder = (folder *)(TP->Context); + folder *Folder = (folder *)CTX; StrBufAppendPrintf(Target, "%d", Folder->QRFlags); } @@ -497,33 +503,33 @@ void tmplput_ROOM_RAFLAGS(StrBuf *Target, WCTemplputParams *TP) void tmplput_ROOM_FLOORID(StrBuf *Target, WCTemplputParams *TP) { - folder *Folder = (folder *)(TP->Context); + folder *Folder = (folder *)CTX; StrBufAppendPrintf(Target, "%d", Folder->floorid); } void tmplput_ROOM_LISTORDER(StrBuf *Target, WCTemplputParams *TP) { - folder *Folder = (folder *)(TP->Context); + folder *Folder = (folder *)CTX; StrBufAppendPrintf(Target, "%d", Folder->listorder); } void tmplput_ROOM_VIEW(StrBuf *Target, WCTemplputParams *TP) { - folder *Folder = (folder *)(TP->Context); + folder *Folder = (folder *)CTX; StrBufAppendPrintf(Target, "%d", Folder->view); } void tmplput_ROOM_DEFVIEW(StrBuf *Target, WCTemplputParams *TP) { - folder *Folder = (folder *)(TP->Context); + folder *Folder = (folder *)CTX; StrBufAppendPrintf(Target, "%d", Folder->defview); } void tmplput_ROOM_LASTCHANGE(StrBuf *Target, WCTemplputParams *TP) { - folder *Folder = (folder *)(TP->Context); + folder *Folder = (folder *)CTX; StrBufAppendPrintf(Target, "%d", Folder->lastchange); } void tmplput_ROOM_FLOOR_ID(StrBuf *Target, WCTemplputParams *TP) { - folder *Folder = (folder *)(TP->Context); + folder *Folder = (folder *)CTX; const Floor *pFloor = Folder->Floor; if (pFloor == NULL) @@ -534,7 +540,7 @@ void tmplput_ROOM_FLOOR_ID(StrBuf *Target, WCTemplputParams *TP) void tmplput_ROOM_FLOOR_NAME(StrBuf *Target, WCTemplputParams *TP) { - folder *Folder = (folder *)(TP->Context); + folder *Folder = (folder *)CTX; const Floor *pFloor = Folder->Floor; if (pFloor == NULL) @@ -545,7 +551,7 @@ void tmplput_ROOM_FLOOR_NAME(StrBuf *Target, WCTemplputParams *TP) void tmplput_ROOM_FLOOR_NROOMS(StrBuf *Target, WCTemplputParams *TP) { - folder *Folder = (folder *)(TP->Context); + folder *Folder = (folder *)CTX; const Floor *pFloor = Folder->Floor; if (pFloor == NULL) @@ -557,56 +563,56 @@ void tmplput_ROOM_FLOOR_NROOMS(StrBuf *Target, WCTemplputParams *TP) int ConditionalRoomHas_UA_KNOWN(StrBuf *Target, WCTemplputParams *TP) { - folder *Folder = (folder *)(TP->Context); + folder *Folder = (folder *)CTX; return (Folder->RAFlags & UA_KNOWN) != 0; } int ConditionalRoomHas_UA_GOTOALLOWED(StrBuf *Target, WCTemplputParams *TP) { - folder *Folder = (folder *)(TP->Context); + folder *Folder = (folder *)CTX; return (Folder->RAFlags & UA_GOTOALLOWED) != 0; } int ConditionalRoomHas_UA_HASNEWMSGS(StrBuf *Target, WCTemplputParams *TP) { - folder *Folder = (folder *)(TP->Context); + folder *Folder = (folder *)CTX; return (Folder->RAFlags & UA_HASNEWMSGS) != 0; } int ConditionalRoomHas_UA_ZAPPED(StrBuf *Target, WCTemplputParams *TP) { - folder *Folder = (folder *)(TP->Context); + folder *Folder = (folder *)CTX; return (Folder->RAFlags & UA_ZAPPED) != 0; } int ConditionalRoomHas_UA_POSTALLOWED(StrBuf *Target, WCTemplputParams *TP) { - folder *Folder = (folder *)(TP->Context); + folder *Folder = (folder *)CTX; return (Folder->RAFlags & UA_POSTALLOWED) != 0; } int ConditionalRoomHas_UA_ADMINALLOWED(StrBuf *Target, WCTemplputParams *TP) { - folder *Folder = (folder *)(TP->Context); + folder *Folder = (folder *)CTX; return (Folder->RAFlags & UA_ADMINALLOWED) != 0; } int ConditionalRoomHas_UA_DELETEALLOWED(StrBuf *Target, WCTemplputParams *TP) { - folder *Folder = (folder *)(TP->Context); + folder *Folder = (folder *)CTX; return (Folder->RAFlags & UA_DELETEALLOWED) != 0; } int ConditionalRoomIsInbox(StrBuf *Target, WCTemplputParams *TP) { - folder *Folder = (folder *)(TP->Context); + folder *Folder = (folder *)CTX; return Folder->is_inbox; } void tmplput_ROOM_COLLECTIONTYPE(StrBuf *Target, WCTemplputParams *TP) { - folder *Folder = (folder *)(TP->Context); + folder *Folder = (folder *)CTX; switch(Folder->view) { case VIEW_CALENDAR: @@ -624,6 +630,9 @@ void tmplput_ROOM_COLLECTIONTYPE(StrBuf *Target, WCTemplputParams *TP) case VIEW_JOURNAL: StrBufAppendBufPlain(Target, HKEY("vjournal"), 0); break; + case VIEW_WIKI: + StrBufAppendBufPlain(Target, HKEY("wiki"), 0); + break; } } @@ -632,7 +641,9 @@ void tmplput_ROOM_COLLECTIONTYPE(StrBuf *Target, WCTemplputParams *TP) int ConditionalRoomHasGroupdavContent(StrBuf *Target, WCTemplputParams *TP) { - folder *Folder = (folder *)(TP->Context); + folder *Folder = (folder *)CTX; + + lprintf(0, "-> %s: %ld\n", ChrPtr(Folder->name), Folder->view); return ((Folder->view == VIEW_CALENDAR) || (Folder->view == VIEW_TASKS) || @@ -646,59 +657,94 @@ int ConditionalRoomHasGroupdavContent(StrBuf *Target, WCTemplputParams *TP) int ConditionalFloorIsRESTSubFloor(StrBuf *Target, WCTemplputParams *TP) { wcsession *WCC = WC; - - /** If we have dav_depth the client just wants the _current_ room without subfloors */ - if (WCC->Hdr->HR.dav_depth == 0) - return 0; - - return 1; + Floor *MyFloor = (Floor *)CTX; + /** if we have dav_depth the client just wants the subfloors */ + if ((WCC->Hdr->HR.dav_depth == 1) && + (GetCount(WCC->Directory) == 0)) + return 1; + return WCC->CurrentFloor == MyFloor; } int ConditionalRoomIsRESTSubRoom(StrBuf *Target, WCTemplputParams *TP) { wcsession *WCC = WC; - folder *Folder = (folder *)(TP->Context); + folder *Folder = (folder *)CTX; HashPos *it; StrBuf * Dir; void *vDir; long len; const char *Key; - int i; - + int i, j, urlp; + int delta; + /* list only folders relative to the current floor... */ if (Folder->Floor != WCC->CurrentFloor) return 0; - if (GetCount(WCC->Directory) != Folder->nRoomNameParts) + urlp = GetCount(WCC->Directory); + delta = Folder->nRoomNameParts - urlp + 1; + + lprintf(0, "\n->%s: %ld - %ld ", ChrPtr(Folder->name), urlp, + Folder->nRoomNameParts); + /* list only the floors which are in relation to the dav_depth header */ + if (WCC->Hdr->HR.dav_depth != delta) { + lprintf(0, "1\n"); return 0; + } + it = GetNewHashPos(WCC->Directory, 0); - for (i = 0; i < Folder->nRoomNameParts; i++) - { - if (!GetNextHashPos(WCC->Directory, it, &len, &Key, &vDir) || - (vDir == NULL)) + /* Fast forward the floorname we checked above... */ + GetNextHashPos(WCC->Directory, it, &len, &Key, &vDir); + + if (Folder->nRoomNameParts > 1) { + for (i = 0, j = 1; + (i > Folder->nRoomNameParts) && (j > urlp); + i++, j++) { - DeleteHashPos(&it); - return 0; + if (!GetNextHashPos(WCC->Directory, + it, &len, &Key, &vDir) || + (vDir == NULL)) + { + DeleteHashPos(&it); + + lprintf(0, "3\n"); + return 0; + } + Dir = (StrBuf*) vDir; + if (strcmp(ChrPtr(Folder->RoomNameParts[i]), + ChrPtr(Dir)) != 0) + { + DeleteHashPos(&it); + lprintf(0, "4\n"); + return 0; + } } - Dir = (StrBuf*) vDir; - if (strcmp(ChrPtr(Folder->RoomNameParts[i]), - ChrPtr(Dir)) != 0) + DeleteHashPos(&it); + return 1; + } + else { + if (!GetNextHashPos(WCC->Directory, + it, &len, &Key, &vDir) || + (vDir == NULL)) { DeleteHashPos(&it); - return 0; + + lprintf(0, "5\n"); + return WCC->Hdr->HR.dav_depth == 1; } - } - DeleteHashPos(&it); + DeleteHashPos(&it); + Dir = (StrBuf*) vDir; + if (WCC->Hdr->HR.dav_depth == 0) { + return (strcmp(ChrPtr(Folder->name), + ChrPtr(Dir)) + == 0); - /** If we have dav_depth the client just wants the _current_ room without subfloors */ - if ((WCC->Hdr->HR.dav_depth == 0) && - (i != Folder->nRoomNameParts)) + } return 0; - - return 1; + } } @@ -715,14 +761,16 @@ void jsonRoomFlr(void) end_burst(); } + void SessionDetachModule_ROOMLIST (wcsession *sess) { DeleteHash(&sess->Floors); + DeleteHash(&sess->Rooms); + DeleteHash(&sess->FloorsByName); } - void InitModule_ROOMLIST (void) @@ -737,7 +785,7 @@ InitModule_ROOMLIST RegisterIterator("LFLR", 0, NULL, GetFloorListHash, NULL, NULL, CTX_FLOORS, CTX_NONE, IT_FLAG_DETECT_GROUPCHANGE); - RegisterIterator("LKRA", 0, NULL, GetRoomListHashLKRA, NULL, DeleteHash, CTX_ROOMS, CTX_NONE, IT_FLAG_DETECT_GROUPCHANGE); + RegisterIterator("LKRA", 0, NULL, GetRoomListHashLKRA, NULL, NULL, CTX_ROOMS, CTX_NONE, IT_FLAG_DETECT_GROUPCHANGE); RegisterNamespace("ROOM:INFO:FLOORID", 0, 1, tmplput_ROOM_FLOORID, NULL, CTX_ROOMS); RegisterNamespace("ROOM:INFO:NAME", 0, 1, tmplput_ROOM_NAME, NULL, CTX_ROOMS); diff --git a/webcit/roomops.c b/webcit/roomops.c index 1ca41c288..ef14c2026 100644 --- a/webcit/roomops.c +++ b/webcit/roomops.c @@ -902,7 +902,7 @@ void ParseGoto(folder *room, StrBuf *Line) */ void smart_goto(const StrBuf *next_room) { gotoroom(next_room); - readloop(readnew); + readloop(readnew, eUseDefault); } @@ -3063,7 +3063,7 @@ void _display_private(void) { void dotgoto(void) { if (!havebstr("room")) { - readloop(readnew); + readloop(readnew, eUseDefault); return; } if (WC->CurRoom.view != VIEW_MAILBOX) { /* dotgoto acts like dotskip when we're in a mailbox view */ diff --git a/webcit/roomops.h b/webcit/roomops.h index 13a96d3ce..726dcc3d2 100644 --- a/webcit/roomops.h +++ b/webcit/roomops.h @@ -99,3 +99,11 @@ HashList *GetFloorListHash(StrBuf *Target, WCTemplputParams *TP); void vDeleteFolder(void *vFolder); void FlushFolder(folder *room); void ParseGoto(folder *proom, StrBuf *Line); + +#define REST_TOPLEVEL 0 +#define REST_IN_NAMESPACE (1<<0) +#define REST_IN_FLOOR (1<<1) +#define REST_IN_ROOM (1<<2) +#define REST_GOT_EUID (1<<3) +#define REST_GOT_ID (1<<4) +#define REST_GOT_FILENAME (1<<5) diff --git a/webcit/smtpqueue.c b/webcit/smtpqueue.c index dc8eb3eff..52fee09f9 100644 --- a/webcit/smtpqueue.c +++ b/webcit/smtpqueue.c @@ -183,7 +183,7 @@ void display_smtpqueue_inner_div(void) { Stat.maxload = 10000; Stat.lowest_found = (-1); Stat.highest_found = (-1); - num_msgs = load_msg_ptrs("MSGS ALL", &Stat); + num_msgs = load_msg_ptrs("MSGS ALL", &Stat, NULL); if (num_msgs > 0) { wc_printf("" diff --git a/webcit/summary.c b/webcit/summary.c index 1e81a59d0..240485070 100644 --- a/webcit/summary.c +++ b/webcit/summary.c @@ -100,7 +100,7 @@ void tasks_section(void) { num_msgs = 0; } else { - num_msgs = load_msg_ptrs("MSGS ALL", &Stat); + num_msgs = load_msg_ptrs("MSGS ALL", &Stat, NULL); } if (num_msgs > 0) { @@ -148,7 +148,7 @@ void calendar_section(void) { num_msgs = 0; } else { - num_msgs = load_msg_ptrs("MSGS ALL", &Stat); + num_msgs = load_msg_ptrs("MSGS ALL", &Stat, NULL); } calendar_GetParamsGetServerCall(&Stat, &v, diff --git a/webcit/tasks.c b/webcit/tasks.c index 373da4fcf..42ae949ba 100644 --- a/webcit/tasks.c +++ b/webcit/tasks.c @@ -578,7 +578,7 @@ void save_individual_task(icalcomponent *supplied_vtodo, long msgnum, char* from summary(); } else { - readloop(readfwd); + readloop(readfwd, eUseDefault); } } @@ -669,6 +669,7 @@ InitModule_TASKS VIEW_TASKS, tasks_GetParamsGetServerCall, NULL, + NULL, tasks_LoadMsgFromServer, tasks_RenderView_or_Tail, tasks_Cleanup); diff --git a/webcit/useredit.c b/webcit/useredit.c index acc763ee3..3194c0159 100644 --- a/webcit/useredit.c +++ b/webcit/useredit.c @@ -429,7 +429,7 @@ TRYAGAIN: Stat.highest_found = (-1); Done = 0; /* Search for the user's vCard */ - if (load_msg_ptrs("MSGS ALL||||1", &Stat) > 0) { + if (load_msg_ptrs("MSGS ALL||||1", &Stat, NULL) > 0) { at = GetNewHashPos(WCC->summ, 0); while (GetNextHashPos(WCC->summ, at, &HKLen, &HashKey, &vMsg)) { Msg = (message_summary*) vMsg; diff --git a/webcit/vcard_edit.c b/webcit/vcard_edit.c index cca07c265..ae513934c 100644 --- a/webcit/vcard_edit.c +++ b/webcit/vcard_edit.c @@ -1078,7 +1078,7 @@ void submit_vcard(void) { int i; if (!havebstr("ok_button")) { - readloop(readnew); + readloop(readnew, eUseDefault); return; } @@ -1107,7 +1107,7 @@ void submit_vcard(void) { http_redirect(bstr("return_to")); } else { - readloop(readnew); + readloop(readnew, eUseDefault); } return; } @@ -1199,7 +1199,7 @@ void submit_vcard(void) { http_redirect(bstr("return_to")); } else { - readloop(readnew); + readloop(readnew, eUseDefault); } } @@ -1335,6 +1335,7 @@ InitModule_VCARD VIEW_ADDRESSBOOK, vcard_GetParamsGetServerCall, NULL, + NULL, vcard_LoadMsgFromServer, vcard_RenderView_or_Tail, vcard_Cleanup); diff --git a/webcit/webcit.c b/webcit/webcit.c index 5912de4f7..e88ebf006 100644 --- a/webcit/webcit.c +++ b/webcit/webcit.c @@ -41,7 +41,12 @@ void WebcitAddUrlHandler(const char * UrlString, long UrlSLen, Put(HandlerHash, UrlString, UrlSLen, NewHandler, DeleteWebcitHandler); } - +void tmplput_HANDLER_DISPLAYNAME(StrBuf *Target, WCTemplputParams *TP) +{ + wcsession *WCC = WC; + if (WCC->Hdr->HR.Handler != NULL) + StrBufAppendTemplate(Target, TP, WCC->Hdr->HR.Handler->DisplayName, 0); +} /* * web-printing funcion. uses our vsnprintf wrapper */ @@ -515,32 +520,57 @@ void ParseREST_URL(void) HashList *Floors; void *vFloor; + lprintf(1, "parsing rest URL: %s\n", ChrPtr(WCC->Hdr->HR.ReqLine)); + WCC->Directory = NewHash(1, Flathash); + WCC->CurrentFloor = NULL; Buf = NewStrBuf(); - while (StrBufExtract_NextToken(WCC->Hdr->HR.ReqLine, - Buf, &pCh, '/') >= 0) + while (StrBufExtract_NextToken(Buf, WCC->Hdr->HR.ReqLine, &pCh, '/') >= 0) { - Put(WCC->Directory, IKEY(i), Buf, HFreeStrBuf); - if (i==0) - pFloor = Buf; + if (StrLength(Buf) != 0) { + /* ignore empty path segments */ + StrBufUnescape(Buf, 1); + Put(WCC->Directory, IKEY(i), Buf, HFreeStrBuf); + if (i==0) + pFloor = Buf; + Buf = NewStrBuf(); + } i++; - Buf = NewStrBuf(); } - if (i == 0) - FreeStrBuf(&Buf); - else if (pFloor != NULL) + + FreeStrBuf(&Buf); + if (pFloor != NULL) { Floors = GetFloorListHash(NULL, NULL); if (Floors != NULL) { - if (GetHash(Floors, SKEY(pFloor), &vFloor)) + if (GetHash(WCC->FloorsByName, SKEY(pFloor), &vFloor)) WCC->CurrentFloor = (Floor*) vFloor; } } } +int Conditional_REST_DEPTH(StrBuf *Target, WCTemplputParams *TP) +{ + long Depth, IsDepth; + long offset = 0; + wcsession *WCC = WC; + + if (WCC->Hdr->HR.Handler != NULL) + offset ++; + Depth = GetTemplateTokenNumber(Target, TP, 2, 0); + IsDepth = GetCount(WCC->Directory) + offset; + +// LogTemplateError(Target, "bla", 1, TP, "REST_DEPTH: %ld : %ld\n", Depth, IsDepth); + if (Depth < 0) { + Depth = -Depth; + return IsDepth > Depth; + } + else + return Depth == IsDepth; +} @@ -781,9 +811,12 @@ InitModule_WEBCIT WebcitAddUrlHandler(HKEY("401"), "", 0, authorization_required, ANONYMOUS|COOKIEUNNEEDED); RegisterConditional(HKEY("COND:IMPMSG"), 0, ConditionalImportantMesage, CTX_NONE); + RegisterConditional(HKEY("COND:REST:DEPTH"), 0, Conditional_REST_DEPTH, CTX_NONE); + RegisterNamespace("CSSLOCAL", 0, 0, tmplput_csslocal, NULL, CTX_NONE); RegisterNamespace("IMPORTANTMESSAGE", 0, 0, tmplput_importantmessage, NULL, CTX_NONE); RegisterNamespace("TRAILING_JAVASCRIPT", 0, 0, tmplput_trailing_javascript, NULL, CTX_NONE); + RegisterNamespace("URL:DISPLAYNAME", 0, 1, tmplput_HANDLER_DISPLAYNAME, NULL, CTX_NONE); snprintf(dir, SIZ, "%s/webcit.css", static_local_dir); if (!access(dir, R_OK)) { diff --git a/webcit/webcit.h b/webcit/webcit.h index 1217ab8f7..3bd09471e 100644 --- a/webcit/webcit.h +++ b/webcit/webcit.h @@ -317,7 +317,7 @@ typedef struct _addrbookent { #define COOKIEUNNEEDED (1<<6) #define ISSTATIC (1<<7) #define FORCE_SESSIONCLOSE (1<<8) -#define PARSE_REST_URL (1<<0) +#define PARSE_REST_URL (1<<9) typedef void (*WebcitHandlerFunc)(void); typedef struct _WebcitHandler{ @@ -490,7 +490,7 @@ struct wcsession { /* int is_mailbox; / * the current room is a private mailbox */ folder CurRoom; /* information about our current room */ - + const folder *ThisRoom; /* if REST found a room, remember it here. */ /* next/previous room thingabob */ struct march *march; /* march mode room list */ char ugname[128]; /* where does 'ungoto' take us */ @@ -507,7 +507,9 @@ struct wcsession { int remember_new_mail; /* last count of new mail messages */ /* Roomiew control */ - HashList *Floors; /* floors our citserver has... */ + HashList *Floors; /* floors our citserver has hashed numeric for quicker access*/ + HashList *FloorsByName; /* same but hashed by its name */ + HashList *Rooms; /* our directory structure as loaded by LKRA */ HashList *summ; /* list of messages for mailbox summary view */ /** Perhaps these should be within a struct instead */ long startmsg; /* message number to start at */ diff --git a/webcit/wiki.c b/webcit/wiki.c index b8701d108..2b0ba7f88 100644 --- a/webcit/wiki.c +++ b/webcit/wiki.c @@ -342,6 +342,7 @@ InitModule_WIKI NULL, NULL, NULL, + NULL, wiki_Cleanup ); -- 2.30.2