* chop messages.c into handy pieces
authorWilfried Göesgens <willi@citadel.org>
Sun, 9 Nov 2008 09:54:55 +0000 (09:54 +0000)
committerWilfried Göesgens <willi@citadel.org>
Sun, 9 Nov 2008 09:54:55 +0000 (09:54 +0000)
webcit/Makefile.in
webcit/messages.c
webcit/msg_renderers.c [new file with mode: 0644]
webcit/vcard_edit.c
webcit/webcit.h

index 67155e218e4a9ec55f168b0a3e958aa88e96d287..fce0b3e88bea15db1c2ebea6f2e55f1273e16c22 100644 (file)
@@ -42,8 +42,8 @@ setup: setup.o
 webcit: webserver.o context_loop.o ical_dezonify.o \
        cookie_conversion.o locate_host.o floors.o summary.o \
        webcit.o auth.o tcp_sockets.o mainmenu.o serv_func.o who.o \
-       roomops.o messages.o userlist.o paging.o sysmsgs.o useredit.o \
-       vcard_edit.o preferences.o html2html.o listsub.o \
+       roomops.o messages.o msg_renderers.o userlist.o paging.o sysmsgs.o \
+       useredit.o vcard_edit.o preferences.o html2html.o listsub.o \
        graphics.o netconf.o siteconfig.o subst.o rss.o \
        calendar.o calendar_tools.o calendar_view.o event.o smtpqueue.o \
        availability.o iconbar.o crypto.o inetconf.o notes.o wiki.o \
@@ -56,8 +56,8 @@ webcit: webserver.o context_loop.o ical_dezonify.o \
        $(CC) $(LDFLAGS) $(LIBOBJS) $(LIBS) \
        webserver.o context_loop.o cookie_conversion.o \
        webcit.o auth.o tcp_sockets.o mainmenu.o serv_func.o who.o listsub.o \
-       roomops.o messages.o userlist.o paging.o sysmsgs.o useredit.o \
-       locate_host.o siteconfig.o subst.o vcard_edit.o floors.o \
+       roomops.o messages.o msg_renderers.o userlist.o paging.o sysmsgs.o \
+       useredit.o locate_host.o siteconfig.o subst.o vcard_edit.o floors.o \
        graphics.o netconf.o preferences.o html2html.o rss.o openid.o \
        summary.o calendar.o calendar_tools.o calendar_view.o event.o wiki.o \
        availability.o ical_dezonify.o iconbar.o crypto.o inetconf.o notes.o \
index 093a123e1c9d4a197f7b72b24fe4b5cfb865c75e..fe4d9be455f6c210aa5a225a768bc815c151a52b 100644 (file)
@@ -17,7 +17,6 @@ HashList *MimeRenderHandler = NULL;
 #define SENDER_COL_WIDTH_PCT           30      /**< Mailbox view column width */
 #define DATE_PLUS_BUTTONS_WIDTH_PCT    20      /**< Mailbox view column width */
 
-void display_vcard(StrBuf *Target, const char *vcard_source, char alpha, int full, char *storename, long msgnum);
 
 
 void display_enter(void);
@@ -35,25 +34,6 @@ int summcmp_rdate(const void *s1, const void *s2);
 typedef void (*MsgPartEvaluatorFunc)(message_summary *Sum, StrBuf *Buf);
 
 
-struct attach_link {
-       char partnum[32];
-       char html[1024];
-};
-
-
-
-typedef struct _headereval {
-       ExamineMsgHeaderFunc evaluator;
-       int Type;
-} headereval;
-
-
-
-enum {
-       eUp,
-       eDown,
-       eNone
-};
 
 const char* SortIcons[3] = {
        "static/up_pointer.gif",
@@ -107,16 +87,6 @@ const int SenderInvertSortString[eUnSet] =  { eSender, eSender, eSender, eSender
 
 
 
-
-/*
- * Address book entry (keep it short and sweet, it's just a quickie lookup
- * which we can use to get to the real meat and bones later)
- */
-struct addrbookent {
-       char ab_name[64]; /**< name string */
-       long ab_msgnum;   /**< message number of address book entry */
-};
-
 /*----------------------------------------------------------------------------*/
 
 /*
@@ -238,720 +208,6 @@ int summcmp_rdate(const void *s1, const void *s2) {
 
 
 
-/*----------------------------------------------------------------------------*/
-
-/**
- * message index functions
- */
-
-void DestroyMimeParts(wc_mime_attachment *Mime)
-{
-       FreeStrBuf(&Mime->Name);
-       FreeStrBuf(&Mime->FileName);
-       FreeStrBuf(&Mime->PartNum);
-       FreeStrBuf(&Mime->Disposition);
-       FreeStrBuf(&Mime->ContentType);
-       FreeStrBuf(&Mime->Charset);
-       FreeStrBuf(&Mime->Data);
-}
-
-void DestroyMime(void *vMime)
-{
-       wc_mime_attachment *Mime = (wc_mime_attachment*)vMime;
-       DestroyMimeParts(Mime);
-       free(Mime);
-}
-
-void DestroyMessageSummary(void *vMsg)
-{
-       message_summary *Msg = (message_summary*) vMsg;
-
-       FreeStrBuf(&Msg->from);
-       FreeStrBuf(&Msg->to);
-       FreeStrBuf(&Msg->subj);
-       FreeStrBuf(&Msg->reply_inreplyto);
-       FreeStrBuf(&Msg->reply_references);
-       FreeStrBuf(&Msg->cccc);
-       FreeStrBuf(&Msg->hnod);
-       FreeStrBuf(&Msg->AllRcpt);
-       FreeStrBuf(&Msg->Room);
-       FreeStrBuf(&Msg->Rfca);
-       FreeStrBuf(&Msg->OtherNode);
-
-       FreeStrBuf(&Msg->reply_to);
-
-       DeleteHash(&Msg->Attachments);  /**< list of Accachments */
-       DeleteHash(&Msg->Submessages);
-       DeleteHash(&Msg->AttachLinks);
-       DeleteHash(&Msg->AllAttach);
-
-       DestroyMimeParts(&Msg->MsgBody);
-
-       free(Msg);
-}
-
-
-
-void RegisterMsgHdr(const char *HeaderName, long HdrNLen, ExamineMsgHeaderFunc evaluator, int type)
-{
-       headereval *ev;
-       ev = (headereval*) malloc(sizeof(headereval));
-       ev->evaluator = evaluator;
-       ev->Type = type;
-       Put(MsgHeaderHandler, HeaderName, HdrNLen, ev, NULL);
-}
-
-void RegisterMimeRenderer(const char *HeaderName, long HdrNLen, RenderMimeFunc MimeRenderer)
-{
-       Put(MimeRenderHandler, HeaderName, HdrNLen, MimeRenderer, reference_free_handler);
-       
-}
-
-/*----------------------------------------------------------------------------*/
-
-
-void examine_nhdr(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
-{
-       Msg->nhdr = 0;
-       if (!strncasecmp(ChrPtr(HdrLine), "yes", 8))
-               Msg->nhdr = 1;
-}
-int Conditional_ANONYMOUS_MESSAGE(WCTemplateToken *Tokens, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       return Msg->nhdr != 0;
-}
-
-
-void examine_type(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
-{
-       Msg->format_type = StrToi(HdrLine);
-                       
-}
-
-void examine_from(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
-{
-       FreeStrBuf(&Msg->from);
-       Msg->from = NewStrBufPlain(NULL, StrLength(HdrLine));
-       StrBuf_RFC822_to_Utf8(Msg->from, HdrLine, WC->DefaultCharset, FoundCharset);
-}
-void tmplput_MAIL_SUMM_FROM(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       StrBufAppendBuf(Target, Msg->from, 0);
-       lprintf(1,"%s", ChrPtr(Msg->from));
-}
-
-
-
-void examine_subj(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
-{
-       FreeStrBuf(&Msg->subj);
-       Msg->subj = NewStrBufPlain(NULL, StrLength(HdrLine));
-       StrBuf_RFC822_to_Utf8(Msg->subj, HdrLine, WC->DefaultCharset, FoundCharset);
-       lprintf(1,"%s", ChrPtr(Msg->subj));
-}
-void tmplput_MAIL_SUMM_SUBJECT(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{/////TODO: Fwd: and RE: filter!!
-       message_summary *Msg = (message_summary*) Context;
-       StrBufAppendBuf(Target, Msg->subj, 0);
-}
-
-
-void examine_msgn(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
-{
-       FreeStrBuf(&Msg->reply_inreplyto);
-       Msg->reply_inreplyto = NewStrBufPlain(NULL, StrLength(HdrLine));
-       StrBuf_RFC822_to_Utf8(Msg->reply_inreplyto, HdrLine, WC->DefaultCharset, FoundCharset);
-}
-void tmplput_MAIL_SUMM_INREPLYTO(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       StrBufAppendBuf(Target, Msg->reply_inreplyto, 0);
-}
-
-int Conditional_MAIL_SUMM_UNREAD(WCTemplateToken *Tokens, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       return Msg->is_new != 0;
-}
-
-void examine_wefw(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
-{
-       FreeStrBuf(&Msg->reply_references);
-       Msg->reply_references = NewStrBufPlain(NULL, StrLength(HdrLine));
-       StrBuf_RFC822_to_Utf8(Msg->reply_references, HdrLine, WC->DefaultCharset, FoundCharset);
-}
-void tmplput_MAIL_SUMM_REFIDS(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       StrBufAppendBuf(Target, Msg->reply_references, 0);
-}
-
-
-void examine_cccc(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
-{
-       FreeStrBuf(&Msg->cccc);
-       Msg->cccc = NewStrBufPlain(NULL, StrLength(HdrLine));
-       StrBuf_RFC822_to_Utf8(Msg->cccc, HdrLine, WC->DefaultCharset, FoundCharset);
-       if (Msg->AllRcpt == NULL)
-               Msg->AllRcpt = NewStrBufPlain(NULL, StrLength(HdrLine));
-       if (StrLength(Msg->AllRcpt) > 0) {
-               StrBufAppendBufPlain(Msg->AllRcpt, HKEY(", "), 0);
-       }
-       StrBufAppendBuf(Msg->AllRcpt, Msg->cccc, 0);
-}
-void tmplput_MAIL_SUMM_CCCC(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       StrBufAppendBuf(Target, Msg->cccc, 0);
-}
-
-
-
-
-void examine_room(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
-{
-       if ((StrLength(HdrLine) > 0) &&
-           (strcasecmp(ChrPtr(HdrLine), WC->wc_roomname))) {
-               FreeStrBuf(&Msg->Room);
-               Msg->Room = NewStrBufDup(HdrLine);              
-       }
-}
-void tmplput_MAIL_SUMM_ORGROOM(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       StrBufAppendBuf(Target, Msg->Room, 0);
-}
-
-
-void examine_rfca(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
-{
-       FreeStrBuf(&Msg->Rfca);
-       Msg->Rfca = NewStrBufDup(HdrLine);
-}
-void tmplput_MAIL_SUMM_RFCA(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       StrBufAppendBuf(Target, Msg->Rfca, 0);
-}
-
-
-void examine_node(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
-{
-       if ( (StrLength(HdrLine) > 0) &&
-            ((WC->room_flags & QR_NETWORK)
-             || ((strcasecmp(ChrPtr(HdrLine), serv_info.serv_nodename)
-                  && (strcasecmp(ChrPtr(HdrLine), serv_info.serv_fqdn)))))) {
-               FreeStrBuf(&Msg->OtherNode);
-               Msg->OtherNode = NewStrBufDup(HdrLine);
-       }
-}
-void tmplput_MAIL_SUMM_OTHERNODE(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       StrBufAppendBuf(Target, Msg->OtherNode, 0);
-}
-int Conditional_MAIL_SUMM_OTHERNODE(WCTemplateToken *Tokens, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       return StrLength(Msg->OtherNode) > 0;
-}
-
-
-void examine_rcpt(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
-{
-       FreeStrBuf(&Msg->to);
-       Msg->to = NewStrBufPlain(NULL, StrLength(HdrLine));
-       StrBuf_RFC822_to_Utf8(Msg->to, HdrLine, WC->DefaultCharset, FoundCharset);
-       if (Msg->AllRcpt == NULL)
-               Msg->AllRcpt = NewStrBufPlain(NULL, StrLength(HdrLine));
-       if (StrLength(Msg->AllRcpt) > 0) {
-               StrBufAppendBufPlain(Msg->AllRcpt, HKEY(", "), 0);
-       }
-       StrBufAppendBuf(Msg->AllRcpt, Msg->to, 0);
-}
-void tmplput_MAIL_SUMM_TO(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       StrBufAppendBuf(Target, Msg->to, 0);
-}
-void tmplput_MAIL_SUMM_ALLRCPT(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       StrBufAppendBuf(Target, Msg->AllRcpt, 0);
-}
-
-
-
-void examine_time(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
-{
-       Msg->date = StrTol(HdrLine);
-}
-void tmplput_MAIL_SUMM_DATE_STR(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       char datebuf[64];
-       message_summary *Msg = (message_summary*) Context;
-       webcit_fmt_date(datebuf, Msg->date, 1);
-       StrBufAppendBufPlain(Target, datebuf, -1, 0);
-}
-void tmplput_MAIL_SUMM_DATE_NO(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       StrBufAppendPrintf(Target, "%ld", Msg->date, 0);
-}
-
-
-
-void render_MAIL(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
-{
-}
-
-void render_MIME_VCard(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
-{
-       MimeLoadData(Mime);
-       if (StrLength(Mime->Data) > 0) {
-               StrBuf *Buf;
-               Buf = NewStrBuf();
-               /** If it's my vCard I can edit it */
-               if (    (!strcasecmp(WC->wc_roomname, USERCONFIGROOM))
-                       || (!strcasecmp(&WC->wc_roomname[11], USERCONFIGROOM))
-                       || (WC->wc_view == VIEW_ADDRESSBOOK)
-                       ) {
-                       StrBufAppendPrintf(Buf, "<a href=\"edit_vcard?msgnum=%ld&partnum=%s\">",
-                               Mime->msgnum, ChrPtr(Mime->PartNum));
-                       StrBufAppendPrintf(Buf, "[%s]</a>", _("edit"));
-               }
-
-               /* In all cases, display the full card */
-               display_vcard(Buf, ChrPtr(Mime->Data), 0, 1, NULL, Mime->msgnum);
-               FreeStrBuf(&Mime->Data);
-               Mime->Data = Buf;
-       }
-
-}
-void render_MIME_ICS(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
-{
-       MimeLoadData(Mime);
-       if (StrLength(Mime->Data) > 0) {
-               cal_process_attachment(Mime);
-       }
-}
-
-
-
-void examine_mime_part(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
-{
-       wc_mime_attachment *mime;
-       StrBuf *Buf;
-       void *vMimeRenderer;
-
-       mime = (wc_mime_attachment*) malloc(sizeof(wc_mime_attachment));
-       memset(mime, 0, sizeof(wc_mime_attachment));
-       mime->msgnum = Msg->msgnum;
-       Buf = NewStrBuf();
-
-       mime->Name = NewStrBuf();
-       StrBufExtract_token(mime->Name, HdrLine, 0, '|');
-
-       StrBufExtract_token(Buf, HdrLine, 1, '|');
-       mime->FileName = NewStrBuf();
-       StrBuf_RFC822_to_Utf8(mime->FileName, Buf, WC->DefaultCharset, FoundCharset);
-
-       mime->PartNum = NewStrBuf();
-       StrBufExtract_token(mime->PartNum, HdrLine, 2, '|');
-
-       mime->Disposition = NewStrBuf();
-       StrBufExtract_token(mime->Disposition, HdrLine, 3, '|');
-
-       mime->ContentType = NewStrBuf();
-       StrBufExtract_token(mime->ContentType, HdrLine, 4, '|');
-
-       mime->length = StrBufExtract_int(HdrLine, 5, '|');
-
-       StrBufTrim(mime->Name);
-       StrBufTrim(mime->FileName);
-
-       if ( (StrLength(mime->FileName) == 0) && (StrLength(mime->Name) > 0) ) {
-               StrBufAppendBuf(mime->FileName, mime->Name, 0);
-       }
-
-       if (Msg->AllAttach == NULL)
-               Msg->AllAttach = NewHash(1,NULL);
-       Put(Msg->AllAttach, SKEY(mime->PartNum), mime, DestroyMime);
-
-
-       if (GetHash(MimeRenderHandler, SKEY(mime->ContentType), &vMimeRenderer) &&
-           vMimeRenderer != NULL)
-       {
-               mime->Renderer = (RenderMimeFunc) vMimeRenderer;
-               if (Msg->Submessages == NULL)
-                       Msg->Submessages = NewHash(1,NULL);
-               Put(Msg->Submessages, SKEY(mime->PartNum), mime, reference_free_handler);
-       }
-       else if ((!strcasecmp(ChrPtr(mime->Disposition), "inline"))
-                && (!strncasecmp(ChrPtr(mime->ContentType), "image/", 6)) ){
-               if (Msg->AttachLinks == NULL)
-                       Msg->AttachLinks = NewHash(1,NULL);
-               Put(Msg->AttachLinks, SKEY(mime->PartNum), mime, reference_free_handler);
-       }
-       else if ((StrLength(mime->ContentType) > 0) &&
-                 ( (!strcasecmp(ChrPtr(mime->Disposition), "attachment")) 
-                   || (!strcasecmp(ChrPtr(mime->Disposition), "inline"))
-                   || (!strcasecmp(ChrPtr(mime->Disposition), ""))))
-       {               
-               if (Msg->AttachLinks == NULL)
-                       Msg->AttachLinks = NewHash(1,NULL);
-               Put(Msg->AttachLinks, SKEY(mime->PartNum), mime, reference_free_handler);
-               if (strcasecmp(ChrPtr(mime->ContentType), "application/octet-stream") == 0) {
-                       FlushStrBuf(mime->ContentType);
-                       StrBufAppendBufPlain(mime->ContentType,
-                                            GuessMimeByFilename(SKEY(mime->FileName)),
-                                            -1, 0);
-               }
-       }
-
-       FreeStrBuf(&Buf);
-}
-
-void tmplput_MAIL_SUMM_NATTACH(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       StrBufAppendPrintf(Target, "%ld", GetCount(Msg->Attachments));
-}
-
-
-
-
-
-
-
-void examine_hnod(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
-{
-       FreeStrBuf(&Msg->hnod);
-       Msg->hnod = NewStrBufPlain(NULL, StrLength(HdrLine));
-       StrBuf_RFC822_to_Utf8(Msg->hnod, HdrLine, WC->DefaultCharset, FoundCharset);
-}
-void tmplput_MAIL_SUMM_H_NODE(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       StrBufAppendBuf(Target, Msg->hnod, 0);
-}
-int Conditional_MAIL_SUMM_H_NODE(WCTemplateToken *Tokens, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       return StrLength(Msg->hnod) > 0;
-}
-
-
-
-void examine_text(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
-{////TODO: read messages here
-       Msg->MsgBody.Data = NewStrBuf();
-}
-
-void examine_msg4_partnum(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
-{
-       Msg->MsgBody.PartNum = NewStrBufDup(HdrLine);
-       StrBufTrim(Msg->MsgBody.PartNum);/////TODO: striplt == trim?
-}
-
-void examine_content_encoding(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
-{
-////TODO: do we care?
-}
-
-void examine_content_lengh(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
-{
-       Msg->MsgBody.length = StrTol(HdrLine);
-       Msg->MsgBody.size_known = 1;
-}
-
-void examine_content_type(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
-{////TODO
-       int len, i;
-       Msg->MsgBody.ContentType = NewStrBufDup(HdrLine);
-       StrBufTrim(Msg->MsgBody.ContentType);/////todo==striplt?
-       len = StrLength(Msg->MsgBody.ContentType);
-       for (i=0; i<len; ++i) {
-               if (!strncasecmp(ChrPtr(Msg->MsgBody.ContentType) + i, "charset=", 8)) {/// TODO: WHUT?
-//                     safestrncpy(mime_charset, &mime_content_type[i+8],
-                       ///                         sizeof mime_charset);
-               }
-       }/****
-       for (i=0; i<len; ++i) {
-               if (mime_content_type[i] == ';') {
-                       mime_content_type[i] = 0;
-                       len = i - 1;
-               }
-       }
-       len = strlen(mime_charset);
-       for (i=0; i<len; ++i) {
-               if (mime_charset[i] == ';') {
-                       mime_charset[i] = 0;
-                       len = i - 1;
-               }
-       }
-        */
-}
-
-void tmplput_MAIL_SUMM_N(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       StrBufAppendPrintf(Target, "%ld", Msg->msgnum);
-}
-
-
-
-int Conditional_MAIL_MIME_ALL(WCTemplateToken *Tokens, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       return GetCount(Msg->Attachments) > 0;
-}
-
-int Conditional_MAIL_MIME_SUBMESSAGES(WCTemplateToken *Tokens, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       return GetCount(Msg->Submessages) > 0;
-}
-
-int Conditional_MAIL_MIME_ATTACHLINKS(WCTemplateToken *Tokens, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       return GetCount(Msg->AttachLinks) > 0;
-}
-
-int Conditional_MAIL_MIME_ATTACH(WCTemplateToken *Tokens, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       return GetCount(Msg->AllAttach) > 0;
-}
-
-
-
-/*----------------------------------------------------------------------------*/
-
-
-void tmplput_MAIL_BODY(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       StrBufAppendBuf(Target, Msg->MsgBody.Data, 0);
-}
-
-
-void render_MAIL_variformat(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
-{
-       /* Messages in legacy Citadel variformat get handled thusly... */
-       StrBuf *Target = NewStrBufPlain(NULL, StrLength(Mime->Data));
-       FmOut(Target, "JUSTIFY", Mime->Data);
-       FreeStrBuf(&Mime->Data);
-       Mime->Data = Target;
-}
-
-void render_MAIL_text_plain(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
-{
-       StrBuf *cs = NULL;
-       const char *ptr, *pte;
-       const char *BufPtr = NULL;
-       StrBuf *Line = NewStrBuf();
-       StrBuf *Line1 = NewStrBuf();
-       StrBuf *Line2 = NewStrBuf();
-       StrBuf *Target = NewStrBufPlain(NULL, StrLength(Mime->Data));
-       int ConvertIt = 1;
-       int bn = 0;
-       int bq = 0;
-       int i, n, done = 0;
-       long len;
-#ifdef HAVE_ICONV
-       iconv_t ic = (iconv_t)(-1) ;
-#endif
-
-       /* Boring old 80-column fixed format text gets handled this way... */
-       if ((strcasecmp(ChrPtr(Mime->Charset), "us-ascii") == 0) &&
-           (strcasecmp(ChrPtr(Mime->Charset), "UTF-8") == 0))
-               ConvertIt = 0;
-
-#ifdef HAVE_ICONV
-       if (ConvertIt) {
-               if (StrLength(Mime->Charset) != 0)
-                       cs = Mime->Charset;
-               else if (StrLength(FoundCharset) > 0)
-                       cs = FoundCharset;
-               else if (StrLength(WC->DefaultCharset) > 0)
-                       cs = WC->DefaultCharset;
-               if (cs == 0) {
-                       ConvertIt = 0;
-               }
-               else {
-                       ctdl_iconv_open("UTF-8", ChrPtr(cs), &ic);
-                       if (ic == (iconv_t)(-1) ) {
-                               lprintf(5, "%s:%d iconv_open(UTF-8, %s) failed: %s\n",
-                                       __FILE__, __LINE__, ChrPtr(Mime->Charset), strerror(errno));
-                       }
-               }
-       }
-#endif
-
-       while ((n = StrBufSipLine(Line, Mime->Data, &BufPtr), n >= 0) && !done)
-       {
-               done = n == 0;
-               bq = 0;
-               i = 0;
-               ptr = ChrPtr(Line);
-               len = StrLength(Line);
-               pte = ptr + len;
-               
-               while ((ptr < pte) &&
-                      ((*ptr == '>') ||
-                       isspace(*ptr)))
-               {
-                       if (*ptr == '>')
-                               bq++;
-                       ptr ++;
-                       i++;
-               }
-               if (i > 0) StrBufCutLeft(Line, i);
-               
-               if (StrLength(Line) == 0)
-                       continue;
-
-               for (i = bn; i < bq; i++)                               
-                       StrBufAppendBufPlain(Target, HKEY("<blockquote>"), 0);
-               for (i = bq; i < bn; i++)                               
-                       StrBufAppendBufPlain(Target, HKEY("</blockquote>"), 0);
-
-               if (ConvertIt == 1) {
-                       StrBufConvert(Line, Line1, &ic);
-               }
-
-               StrBufAppendBufPlain(Target, HKEY("<tt>"), 0);
-               UrlizeText(Line1, Line, Line2);
-
-               StrEscAppend(Target, Line1, NULL, 0, 0);
-               StrBufAppendBufPlain(Target, HKEY("</tt><br />\n"), 0);
-               bn = bq;
-       }
-
-       for (i = 0; i < bn; i++)                                
-               StrBufAppendBufPlain(Target, HKEY("</blockquote>"), 0);
-
-       StrBufAppendBufPlain(Target, HKEY("</i><br />"), 0);
-#ifdef HAVE_ICONV
-       if (ic != (iconv_t)(-1) ) {
-               iconv_close(ic);
-       }
-#endif
-       FreeStrBuf(&Mime->Data);
-       Mime->Data = Target;
-       FreeStrBuf(&Line);
-       FreeStrBuf(&Line1);
-       FreeStrBuf(&Line2);
-}
-
-void render_MAIL_html(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
-{
-       StrBuf *Buf;
-       /* HTML is fun, but we've got to strip it first */
-       Buf = NewStrBufPlain(NULL, StrLength(Mime->Data));
-       output_html(ChrPtr(Mime->Charset), 
-                   (WC->wc_view == VIEW_WIKI ? 1 : 0), 
-                   StrToi(Mime->PartNum), 
-                   Mime->Data, Buf);
-       FreeStrBuf(&Mime->Data);
-       Mime->Data = Buf;
-}
-
-void render_MAIL_UNKNOWN(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
-{
-       /* Unknown weirdness */
-       FlushStrBuf(Mime->Data);
-       StrBufAppendBufPlain(Mime->Data, _("I don't know how to display "), -1, 0);
-       StrBufAppendBuf(Mime->Data, Mime->ContentType, 0);
-       StrBufAppendBufPlain(Mime->Data, HKEY("<br />\n"), 0);
-}
-
-
-
-
-
-
-HashList *iterate_get_mime_All(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       return Msg->Attachments;
-}
-HashList *iterate_get_mime_Submessages(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       return Msg->Submessages;
-}
-HashList *iterate_get_mime_AttachLinks(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       return Msg->AttachLinks;
-}
-HashList *iterate_get_mime_Attachments(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
-{
-       message_summary *Msg = (message_summary*) Context;
-       return Msg->AllAttach;
-}
-
-void tmplput_MIME_Name(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       wc_mime_attachment *mime = (wc_mime_attachment*) Context;
-       StrBufAppendBuf(Target, mime->Name, 0);
-}
-
-void tmplput_MIME_FileName(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       wc_mime_attachment *mime = (wc_mime_attachment*) Context;
-       StrBufAppendBuf(Target, mime->FileName, 0);
-}
-
-void tmplput_MIME_PartNum(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       wc_mime_attachment *mime = (wc_mime_attachment*) Context;
-       StrBufAppendBuf(Target, mime->PartNum, 0);
-}
-
-void tmplput_MIME_MsgNum(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       wc_mime_attachment *mime = (wc_mime_attachment*) Context;
-       StrBufAppendPrintf(Target, "%ld", mime->msgnum);
-}
-
-void tmplput_MIME_Disposition(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       wc_mime_attachment *mime = (wc_mime_attachment*) Context;
-       StrBufAppendBuf(Target, mime->Disposition, 0);
-}
-
-void tmplput_MIME_ContentType(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       wc_mime_attachment *mime = (wc_mime_attachment*) Context;
-       StrBufAppendBuf(Target, mime->ContentType, 0);
-}
-
-void tmplput_MIME_Charset(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       wc_mime_attachment *mime = (wc_mime_attachment*) Context;
-       StrBufAppendBuf(Target, mime->Charset, 0);
-}
-
-void tmplput_MIME_Data(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       wc_mime_attachment *mime = (wc_mime_attachment*) Context;
-       if (mime->Renderer != NULL)
-               mime->Renderer(mime, NULL, NULL);
-       StrBufAppendBuf(Target, mime->Data, 0); /// TODO: check whether we need to load it now?
-}
-
-void tmplput_MIME_Length(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
-{
-       wc_mime_attachment *mime = (wc_mime_attachment*) Context;
-       StrBufAppendPrintf(Target, "%ld", mime->length);
-}
-
 
 
 /*
@@ -1090,372 +346,6 @@ void url(char *buf, size_t bufsize)
 }
 
 
-/**
- * \brief Turn a vCard "n" (name) field into something displayable.
- * \param name the name field to convert
- */
-void vcard_n_prettyize(char *name)
-{
-       char *original_name;
-       int i, j, len;
-
-       original_name = strdup(name);
-       len = strlen(original_name);
-       for (i=0; i<5; ++i) {
-               if (len > 0) {
-                       if (original_name[len-1] == ' ') {
-                               original_name[--len] = 0;
-                       }
-                       if (original_name[len-1] == ';') {
-                               original_name[--len] = 0;
-                       }
-               }
-       }
-       strcpy(name, "");
-       j=0;
-       for (i=0; i<len; ++i) {
-               if (original_name[i] == ';') {
-                       name[j++] = ',';
-                       name[j++] = ' ';                        
-               }
-               else {
-                       name[j++] = original_name[i];
-               }
-       }
-       name[j] = '\0';
-       free(original_name);
-}
-
-
-
-
-/**
- * \brief preparse a vcard name
- * display_vcard() calls this after parsing the textual vCard into
- * our 'struct vCard' data object.
- * This gets called instead of display_parsed_vcard() if we are only looking
- * to extract the person's name instead of displaying the card.
- * \param v the vcard to retrieve the name from
- * \param storename where to put the name at
- */
-void fetchname_parsed_vcard(struct vCard *v, char *storename) {
-       char *name;
-
-       strcpy(storename, "");
-
-       name = vcard_get_prop(v, "n", 1, 0, 0);
-       if (name != NULL) {
-               strcpy(storename, name);
-               /* vcard_n_prettyize(storename); */
-       }
-
-}
-
-
-
-/**
- * \brief html print a vcard
- * display_vcard() calls this after parsing the textual vCard into
- * our 'struct vCard' data object.
- *
- * Set 'full' to nonzero to display the full card, otherwise it will only
- * show a summary line.
- *
- * This code is a bit ugly, so perhaps an explanation is due: we do this
- * in two passes through the vCard fields.  On the first pass, we process
- * fields we understand, and then render them in a pretty fashion at the
- * end.  Then we make a second pass, outputting all the fields we don't
- * understand in a simple two-column name/value format.
- * \param v the vCard to display
- * \param full display all items of the vcard?
- * \param msgnum Citadel message pointer
- */
-void display_parsed_vcard(StrBuf *Target, struct vCard *v, int full, long msgnum) {
-       int i, j;
-       char buf[SIZ];
-       char *name;
-       int is_qp = 0;
-       int is_b64 = 0;
-       char *thisname, *thisvalue;
-       char firsttoken[SIZ];
-       int pass;
-
-       char fullname[SIZ];
-       char title[SIZ];
-       char org[SIZ];
-       char phone[SIZ];
-       char mailto[SIZ];
-
-       strcpy(fullname, "");
-       strcpy(phone, "");
-       strcpy(mailto, "");
-       strcpy(title, "");
-       strcpy(org, "");
-
-       if (!full) {
-               StrBufAppendPrintf(Target, "<TD>");
-               name = vcard_get_prop(v, "fn", 1, 0, 0);
-               if (name != NULL) {
-                       StrEscAppend(Target, NULL, name, 0, 0);
-               }
-               else if (name = vcard_get_prop(v, "n", 1, 0, 0), name != NULL) {
-                       strcpy(fullname, name);
-                       vcard_n_prettyize(fullname);
-                       StrEscAppend(Target, NULL, fullname, 0, 0);
-               }
-               else {
-                       StrBufAppendPrintf(Target, "&nbsp;");
-               }
-               StrBufAppendPrintf(Target, "</TD>");
-               return;
-       }
-
-       StrBufAppendPrintf(Target, "<div align=center>"
-               "<table bgcolor=#aaaaaa width=50%%>");
-       for (pass=1; pass<=2; ++pass) {
-
-               if (v->numprops) for (i=0; i<(v->numprops); ++i) {
-                       int len;
-                       thisname = strdup(v->prop[i].name);
-                       extract_token(firsttoken, thisname, 0, ';', sizeof firsttoken);
-       
-                       for (j=0; j<num_tokens(thisname, ';'); ++j) {
-                               extract_token(buf, thisname, j, ';', sizeof buf);
-                               if (!strcasecmp(buf, "encoding=quoted-printable")) {
-                                       is_qp = 1;
-                                       remove_token(thisname, j, ';');
-                               }
-                               if (!strcasecmp(buf, "encoding=base64")) {
-                                       is_b64 = 1;
-                                       remove_token(thisname, j, ';');
-                               }
-                       }
-                       
-                       len = strlen(v->prop[i].value);
-                       /* if we have some untagged QP, detect it here. */
-                       if (!is_qp && (strstr(v->prop[i].value, "=?")!=NULL))
-                               utf8ify_rfc822_string(v->prop[i].value);
-
-                       if (is_qp) {
-                               // %ff can become 6 bytes in utf8 
-                               thisvalue = malloc(len * 2 + 3); 
-                               j = CtdlDecodeQuotedPrintable(
-                                       thisvalue, v->prop[i].value,
-                                       len);
-                               thisvalue[j] = 0;
-                       }
-                       else if (is_b64) {
-                               // ff will become one byte..
-                               thisvalue = malloc(len + 50);
-                               CtdlDecodeBase64(
-                                       thisvalue, v->prop[i].value,
-                                       strlen(v->prop[i].value) );
-                       }
-                       else {
-                               thisvalue = strdup(v->prop[i].value);
-                       }
-       
-                       /** Various fields we may encounter ***/
-       
-                       /** N is name, but only if there's no FN already there */
-                       if (!strcasecmp(firsttoken, "n")) {
-                               if (IsEmptyStr(fullname)) {
-                                       strcpy(fullname, thisvalue);
-                                       vcard_n_prettyize(fullname);
-                               }
-                       }
-       
-                       /** FN (full name) is a true 'display name' field */
-                       else if (!strcasecmp(firsttoken, "fn")) {
-                               strcpy(fullname, thisvalue);
-                       }
-
-                       /** title */
-                       else if (!strcasecmp(firsttoken, "title")) {
-                               strcpy(title, thisvalue);
-                       }
-       
-                       /** organization */
-                       else if (!strcasecmp(firsttoken, "org")) {
-                               strcpy(org, thisvalue);
-                       }
-       
-                       else if (!strcasecmp(firsttoken, "email")) {
-                               size_t len;
-                               if (!IsEmptyStr(mailto)) strcat(mailto, "<br />");
-                               strcat(mailto,
-                                       "<a href=\"display_enter"
-                                       "?force_room=_MAIL_?recp=");
-
-                               len = strlen(mailto);
-                               urlesc(&mailto[len], SIZ - len, "\"");
-                               len = strlen(mailto);
-                               urlesc(&mailto[len], SIZ - len,  fullname);
-                               len = strlen(mailto);
-                               urlesc(&mailto[len], SIZ - len, "\" <");
-                               len = strlen(mailto);
-                               urlesc(&mailto[len], SIZ - len, thisvalue);
-                               len = strlen(mailto);
-                               urlesc(&mailto[len], SIZ - len, ">");
-
-                               strcat(mailto, "\">");
-                               len = strlen(mailto);
-                               stresc(mailto+len, SIZ - len, thisvalue, 1, 1);
-                               strcat(mailto, "</A>");
-                       }
-                       else if (!strcasecmp(firsttoken, "tel")) {
-                               if (!IsEmptyStr(phone)) strcat(phone, "<br />");
-                               strcat(phone, thisvalue);
-                               for (j=0; j<num_tokens(thisname, ';'); ++j) {
-                                       extract_token(buf, thisname, j, ';', sizeof buf);
-                                       if (!strcasecmp(buf, "tel"))
-                                               strcat(phone, "");
-                                       else if (!strcasecmp(buf, "work"))
-                                               strcat(phone, _(" (work)"));
-                                       else if (!strcasecmp(buf, "home"))
-                                               strcat(phone, _(" (home)"));
-                                       else if (!strcasecmp(buf, "cell"))
-                                               strcat(phone, _(" (cell)"));
-                                       else {
-                                               strcat(phone, " (");
-                                               strcat(phone, buf);
-                                               strcat(phone, ")");
-                                       }
-                               }
-                       }
-                       else if (!strcasecmp(firsttoken, "adr")) {
-                               if (pass == 2) {
-                                       StrBufAppendPrintf(Target, "<TR><TD>");
-                                       StrBufAppendPrintf(Target, _("Address:"));
-                                       StrBufAppendPrintf(Target, "</TD><TD>");
-                                       for (j=0; j<num_tokens(thisvalue, ';'); ++j) {
-                                               extract_token(buf, thisvalue, j, ';', sizeof buf);
-                                               if (!IsEmptyStr(buf)) {
-                                                       StrEscAppend(Target, NULL, buf, 0, 0);
-                                                       if (j<3) StrBufAppendPrintf(Target, "<br />");
-                                                       else StrBufAppendPrintf(Target, " ");
-                                               }
-                                       }
-                                       StrBufAppendPrintf(Target, "</TD></TR>\n");
-                               }
-                       }
-                       /* else if (!strcasecmp(firsttoken, "photo") && full && pass == 2) { 
-                               // Only output on second pass
-                               StrBufAppendPrintf(Target, "<tr><td>");
-                               StrBufAppendPrintf(Target, _("Photo:"));
-                               StrBufAppendPrintf(Target, "</td><td>");
-                               StrBufAppendPrintf(Target, "<img src=\"/vcardphoto/%ld/\" alt=\"Contact photo\"/>",msgnum);
-                               StrBufAppendPrintf(Target, "</td></tr>\n");
-                       } */
-                       else if (!strcasecmp(firsttoken, "version")) {
-                               /* ignore */
-                       }
-                       else if (!strcasecmp(firsttoken, "rev")) {
-                               /* ignore */
-                       }
-                       else if (!strcasecmp(firsttoken, "label")) {
-                               /* ignore */
-                       }
-                       else {
-
-                               /*** Don't show extra fields.  They're ugly.
-                               if (pass == 2) {
-                                       StrBufAppendPrintf(Target, "<TR><TD>");
-                                       StrEscAppend(Target, NULL, thisname, 0, 0);
-                                       StrBufAppendPrintf(Target, "</TD><TD>");
-                                       StrEscAppend(Target, NULL, thisvalue, 0, 0);
-                                       StrBufAppendPrintf(Target, "</TD></TR>\n");
-                               }
-                               ***/
-                       }
-       
-                       free(thisname);
-                       free(thisvalue);
-               }
-       
-               if (pass == 1) {
-                       StrBufAppendPrintf(Target, "<TR BGCOLOR=\"#AAAAAA\">"
-                       "<TD COLSPAN=2 BGCOLOR=\"#FFFFFF\">"
-                       "<IMG ALIGN=CENTER src=\"static/viewcontacts_48x.gif\">"
-                       "<FONT SIZE=+1><B>");
-                       StrEscAppend(Target, NULL, fullname, 0, 0);
-                       StrBufAppendPrintf(Target, "</B></FONT>");
-                       if (!IsEmptyStr(title)) {
-                               StrBufAppendPrintf(Target, "<div align=right>");
-                               StrEscAppend(Target, NULL, title, 0, 0);
-                               StrBufAppendPrintf(Target, "</div>");
-                       }
-                       if (!IsEmptyStr(org)) {
-                               StrBufAppendPrintf(Target, "<div align=right>");
-                               StrEscAppend(Target, NULL, org, 0, 0);
-                               StrBufAppendPrintf(Target, "</div>");
-                       }
-                       StrBufAppendPrintf(Target, "</TD></TR>\n");
-               
-                       if (!IsEmptyStr(phone)) {
-                               StrBufAppendPrintf(Target, "<tr><td>");
-                               StrBufAppendPrintf(Target, _("Telephone:"));
-                               StrBufAppendPrintf(Target, "</td><td>%s</td></tr>\n", phone);
-                       }
-                       if (!IsEmptyStr(mailto)) {
-                               StrBufAppendPrintf(Target, "<tr><td>");
-                               StrBufAppendPrintf(Target, _("E-mail:"));
-                               StrBufAppendPrintf(Target, "</td><td>%s</td></tr>\n", mailto);
-                       }
-               }
-
-       }
-
-       StrBufAppendPrintf(Target, "</table></div>\n");
-}
-
-
-
-/**
- * \brief  Display a textual vCard
- * (Converts to a vCard object and then calls the actual display function)
- * Set 'full' to nonzero to display the whole card instead of a one-liner.
- * Or, if "storename" is non-NULL, just store the person's name in that
- * buffer instead of displaying the card at all.
- * \param vcard_source the buffer containing the vcard text
- * \param alpha what???
- * \param full should we usse all lines?
- * \param storename where to store???
- * \param msgnum Citadel message pointer
- */
-void display_vcard(StrBuf *Target, const char *vcard_source, char alpha, int full, char *storename, 
-       long msgnum) {
-       struct vCard *v;
-       char *name;
-       char buf[SIZ];
-       char this_alpha = 0;
-
-       v = vcard_load((char*)vcard_source); ///TODO
-
-       if (v == NULL) return;
-
-       name = vcard_get_prop(v, "n", 1, 0, 0);
-       if (name != NULL) {
-               utf8ify_rfc822_string(name);
-               strcpy(buf, name);
-               this_alpha = buf[0];
-       }
-
-       if (storename != NULL) {
-               fetchname_parsed_vcard(v, storename);
-       }
-       else if (       (alpha == 0)
-                       || ((isalpha(alpha)) && (tolower(alpha) == tolower(this_alpha)) )
-                       || ((!isalpha(alpha)) && (!isalpha(this_alpha)))
-               ) {
-               display_parsed_vcard(Target, v, full,msgnum);
-       }
-
-       vcard_free(v);
-}
-
-
-
 
 
 
@@ -2333,141 +1223,6 @@ void fetch_ab_name(message_summary *Msg, char *namebuf) {
 
 
 
-/**
- * \brief Record compare function for sorting address book indices
- * \param ab1 adressbook one
- * \param ab2 adressbook two
- */
-int abcmp(const void *ab1, const void *ab2) {
-       return(strcasecmp(
-               (((const struct addrbookent *)ab1)->ab_name),
-               (((const struct addrbookent *)ab2)->ab_name)
-       ));
-}
-
-
-/**
- * \brief Helper function for do_addrbook_view()
- * Converts a name into a three-letter tab label
- * \param tabbuf the tabbuffer to add name to
- * \param name the name to add to the tabbuffer
- */
-void nametab(char *tabbuf, long len, char *name) {
-       stresc(tabbuf, len, name, 0, 0);
-       tabbuf[0] = toupper(tabbuf[0]);
-       tabbuf[1] = tolower(tabbuf[1]);
-       tabbuf[2] = tolower(tabbuf[2]);
-       tabbuf[3] = 0;
-}
-
-
-/**
- * \brief Render the address book using info we gathered during the scan
- * \param addrbook the addressbook to render
- * \param num_ab the number of the addressbook
- */
-void do_addrbook_view(struct addrbookent *addrbook, int num_ab) {
-       int i = 0;
-       int displayed = 0;
-       int bg = 0;
-       static int NAMESPERPAGE = 60;
-       int num_pages = 0;
-       int tabfirst = 0;
-       char tabfirst_label[64];
-       int tablast = 0;
-       char tablast_label[64];
-       char this_tablabel[64];
-       int page = 0;
-       char **tablabels;
-
-       if (num_ab == 0) {
-               wprintf("<br /><br /><br /><div align=\"center\"><i>");
-               wprintf(_("This address book is empty."));
-               wprintf("</i></div>\n");
-               return;
-       }
-
-       if (num_ab > 1) {
-               qsort(addrbook, num_ab, sizeof(struct addrbookent), abcmp);
-       }
-
-       num_pages = (num_ab / NAMESPERPAGE) + 1;
-
-       tablabels = malloc(num_pages * sizeof (char *));
-       if (tablabels == NULL) {
-               wprintf("<br /><br /><br /><div align=\"center\"><i>");
-               wprintf(_("An internal error has occurred."));
-               wprintf("</i></div>\n");
-               return;
-       }
-
-       for (i=0; i<num_pages; ++i) {
-               tabfirst = i * NAMESPERPAGE;
-               tablast = tabfirst + NAMESPERPAGE - 1;
-               if (tablast > (num_ab - 1)) tablast = (num_ab - 1);
-               nametab(tabfirst_label, 64, addrbook[tabfirst].ab_name);
-               nametab(tablast_label, 64, addrbook[tablast].ab_name);
-               sprintf(this_tablabel, "%s&nbsp;-&nbsp;%s", tabfirst_label, tablast_label);
-               tablabels[i] = strdup(this_tablabel);
-       }
-
-       tabbed_dialog(num_pages, tablabels);
-       page = (-1);
-
-       for (i=0; i<num_ab; ++i) {
-
-               if ((i / NAMESPERPAGE) != page) {       /* New tab */
-                       page = (i / NAMESPERPAGE);
-                       if (page > 0) {
-                               wprintf("</tr></table>\n");
-                               end_tab(page-1, num_pages);
-                       }
-                       begin_tab(page, num_pages);
-                       wprintf("<table border=0 cellspacing=0 cellpadding=3 width=100%%>\n");
-                       displayed = 0;
-               }
-
-               if ((displayed % 4) == 0) {
-                       if (displayed > 0) {
-                               wprintf("</tr>\n");
-                       }
-                       bg = 1 - bg;
-                       wprintf("<tr bgcolor=\"#%s\">",
-                               (bg ? "DDDDDD" : "FFFFFF")
-                       );
-               }
-       
-               wprintf("<td>");
-
-               wprintf("<a href=\"readfwd?startmsg=%ld?is_singlecard=1",
-                       addrbook[i].ab_msgnum);
-               wprintf("?maxmsgs=1?is_summary=0?alpha=%s\">", bstr("alpha"));
-               vcard_n_prettyize(addrbook[i].ab_name);
-               escputs(addrbook[i].ab_name);
-               wprintf("</a></td>\n");
-               ++displayed;
-       }
-
-       /* Placeholders for empty columns at end */
-       if ((num_ab % 4) != 0) {
-               for (i=0; i<(4-(num_ab % 4)); ++i) {
-                       wprintf("<td>&nbsp;</td>");
-               }
-       }
-
-       wprintf("</tr></table>\n");
-       end_tab((num_pages-1), num_pages);
-
-       begin_tab(num_pages, num_pages);
-       /* FIXME there ought to be something here */
-       end_tab(num_pages, num_pages);
-
-       for (i=0; i<num_pages; ++i) {
-               free(tablabels[i]);
-       }
-       free(tablabels);
-}
-
 
 
 /*
@@ -2609,7 +1364,7 @@ void readloop(char *oper)
        int lo, hi;
        int lowest_displayed = (-1);
        int highest_displayed = 0;
-       struct addrbookent *addrbook = NULL;
+       addrbookent *addrbook = NULL;
        int num_ab = 0;
        const StrBuf *sortby = NULL;
        //SortByEnum 
@@ -2954,7 +1709,7 @@ void readloop(char *oper)
                                fetch_ab_name(Msg, buf);
                                ++num_ab;
                                addrbook = realloc(addrbook,
-                                                  (sizeof(struct addrbookent) * num_ab) );
+                                                  (sizeof(addrbookent) * num_ab) );
                                safestrncpy(addrbook[num_ab-1].ab_name, buf,
                                            sizeof(addrbook[num_ab-1].ab_name));
                                addrbook[num_ab-1].ab_msgnum = Msg->msgnum;
@@ -3995,85 +2750,5 @@ InitModule_MSG
        WebcitAddUrlHandler(HKEY("mobilemsg"), mobile_message_view, NEED_URL);
        WebcitAddUrlHandler(HKEY("msgheaders"), display_headers, NEED_URL);
 
-       RegisterNamespace("MAIL:SUMM:DATESTR", 0, 0, tmplput_MAIL_SUMM_DATE_STR, CTX_MAILSUM);
-       RegisterNamespace("MAIL:SUMM:DATENO",  0, 0, tmplput_MAIL_SUMM_DATE_NO,  CTX_MAILSUM);
-       RegisterNamespace("MAIL:SUMM:N",       0, 0, tmplput_MAIL_SUMM_N,        CTX_MAILSUM);
-       RegisterNamespace("MAIL:SUMM:FROM",    0, 2, tmplput_MAIL_SUMM_FROM,     CTX_MAILSUM);
-       RegisterNamespace("MAIL:SUMM:TO",      0, 2, tmplput_MAIL_SUMM_TO,       CTX_MAILSUM);
-       RegisterNamespace("MAIL:SUMM:SUBJECT", 0, 4, tmplput_MAIL_SUMM_SUBJECT,  CTX_MAILSUM);
-       RegisterNamespace("MAIL:SUMM:NTATACH", 0, 0, tmplput_MAIL_SUMM_NATTACH,  CTX_MAILSUM);
-       RegisterNamespace("MAIL:SUMM:CCCC", 0, 2, tmplput_MAIL_SUMM_CCCC,  CTX_MAILSUM);
-       RegisterNamespace("MAIL:SUMM:H_NODE", 0, 2, tmplput_MAIL_SUMM_H_NODE,  CTX_MAILSUM);
-       RegisterNamespace("MAIL:SUMM:ALLRCPT", 0, 2, tmplput_MAIL_SUMM_ALLRCPT,  CTX_MAILSUM);
-       RegisterNamespace("MAIL:SUMM:ORGROOM", 0, 2, tmplput_MAIL_SUMM_ORGROOM,  CTX_MAILSUM);
-       RegisterNamespace("MAIL:SUMM:RFCA", 0, 2, tmplput_MAIL_SUMM_RFCA,  CTX_MAILSUM);
-       RegisterNamespace("MAIL:SUMM:OTHERNODE", 2, 0, tmplput_MAIL_SUMM_OTHERNODE,  CTX_MAILSUM);
-       RegisterNamespace("MAIL:SUMM:REFIDS", 0, 0, tmplput_MAIL_SUMM_REFIDS,  CTX_MAILSUM);
-       RegisterNamespace("MAIL:SUMM:INREPLYTO", 0, 2, tmplput_MAIL_SUMM_INREPLYTO,  CTX_MAILSUM);
-       RegisterNamespace("MAIL:BODY", 0, 2, tmplput_MAIL_BODY,  CTX_MAILSUM);
-
-
-       RegisterConditional(HKEY("COND:MAIL:SUMM:UNREAD"), 0, Conditional_MAIL_SUMM_UNREAD, CTX_MAILSUM);
-       RegisterConditional(HKEY("COND:MAIL:SUMM:H_NODE"), 0, Conditional_MAIL_SUMM_H_NODE, CTX_MAILSUM);
-       RegisterConditional(HKEY("COND:MAIL:SUMM:OTHERNODE"), 0, Conditional_MAIL_SUMM_OTHERNODE, CTX_MAILSUM);
-       RegisterConditional(HKEY("COND:MAIL:ANON"), 0, Conditional_ANONYMOUS_MESSAGE, CTX_MAILSUM);
-
-       RegisterConditional(HKEY("COND:MAIL:MIME:ATTACH"), 0, Conditional_MAIL_MIME_ALL, CTX_MAILSUM);
-       RegisterConditional(HKEY("COND:MAIL:MIME:ATTACH:SUBMESSAGES"), 0, Conditional_MAIL_MIME_SUBMESSAGES, CTX_MAILSUM);
-       RegisterConditional(HKEY("COND:MAIL:MIME:ATTACH:LINKS"), 0, Conditional_MAIL_MIME_ATTACHLINKS, CTX_MAILSUM);
-       RegisterConditional(HKEY("COND:MAIL:MIME:ATTACH:ATT"), 0, Conditional_MAIL_MIME_ATTACH, CTX_MAILSUM);
-
-       RegisterIterator("MAIL:MIME:ATTACH", 0, NULL, iterate_get_mime_All, 
-                        NULL, NULL, CTX_MIME_ATACH, CTX_MAILSUM);
-       RegisterIterator("MAIL:MIME:ATTACH:SUBMESSAGES", 0, NULL, iterate_get_mime_Submessages, 
-                        NULL, NULL, CTX_MIME_ATACH, CTX_MAILSUM);
-       RegisterIterator("MAIL:MIME:ATTACH:LINKS", 0, NULL, iterate_get_mime_AttachLinks, 
-                        NULL, NULL, CTX_MIME_ATACH, CTX_MAILSUM);
-       RegisterIterator("MAIL:MIME:ATTACH:ATT", 0, NULL, iterate_get_mime_Attachments, 
-                        NULL, NULL, CTX_MIME_ATACH, CTX_MAILSUM);
-
-       RegisterNamespace("MAIL:MIME:NAME", 0, 2, tmplput_MIME_Name, CTX_MIME_ATACH);
-       RegisterNamespace("MAIL:MIME:FILENAME", 0, 2, tmplput_MIME_FileName, CTX_MIME_ATACH);
-       RegisterNamespace("MAIL:MIME:PARTNUM", 0, 2, tmplput_MIME_PartNum, CTX_MIME_ATACH);
-       RegisterNamespace("MAIL:MIME:MSGNUM", 0, 2, tmplput_MIME_MsgNum, CTX_MIME_ATACH);
-       RegisterNamespace("MAIL:MIME:DISPOSITION", 0, 2, tmplput_MIME_Disposition, CTX_MIME_ATACH);
-       RegisterNamespace("MAIL:MIME:CONTENTTYPE", 0, 2, tmplput_MIME_ContentType, CTX_MIME_ATACH);
-       RegisterNamespace("MAIL:MIME:CHARSET", 0, 2, tmplput_MIME_Charset, CTX_MIME_ATACH);
-       RegisterNamespace("MAIL:MIME:LENGTH", 0, 2, tmplput_MIME_Length, CTX_MIME_ATACH);
-       RegisterNamespace("MAIL:MIME:DATA", 0, 2, tmplput_MIME_Data, CTX_MIME_ATACH);
-
-
-
-       RegisterMimeRenderer(HKEY("message/rfc822"), render_MAIL);
-       RegisterMimeRenderer(HKEY("text/x-vcard"), render_MIME_VCard);
-       RegisterMimeRenderer(HKEY("text/vcard"), render_MIME_VCard);
-       RegisterMimeRenderer(HKEY("text/calendar"), render_MIME_ICS);
-       RegisterMimeRenderer(HKEY("application/ics"), render_MIME_ICS);
-
-       RegisterMimeRenderer(HKEY("text/x-citadel-variformat"), render_MAIL_variformat);
-       RegisterMimeRenderer(HKEY("text/plain"), render_MAIL_text_plain);
-       RegisterMimeRenderer(HKEY("text"), render_MAIL_text_plain);
-       RegisterMimeRenderer(HKEY("text/html"), render_MAIL_html);
-       RegisterMimeRenderer(HKEY(""), render_MAIL_UNKNOWN);
-
-       RegisterMsgHdr(HKEY("nhdr"), examine_nhdr, 0);
-       RegisterMsgHdr(HKEY("type"), examine_type, 0);
-       RegisterMsgHdr(HKEY("from"), examine_from, 0);
-       RegisterMsgHdr(HKEY("subj"), examine_subj, 0);
-       RegisterMsgHdr(HKEY("msgn"), examine_msgn, 0);
-       RegisterMsgHdr(HKEY("wefw"), examine_wefw, 0);
-       RegisterMsgHdr(HKEY("cccc"), examine_cccc, 0);
-       RegisterMsgHdr(HKEY("hnod"), examine_hnod, 0);
-       RegisterMsgHdr(HKEY("room"), examine_room, 0);
-       RegisterMsgHdr(HKEY("rfca"), examine_rfca, 0);
-       RegisterMsgHdr(HKEY("node"), examine_node, 0);
-       RegisterMsgHdr(HKEY("rcpt"), examine_rcpt, 0);
-       RegisterMsgHdr(HKEY("time"), examine_time, 0);
-       RegisterMsgHdr(HKEY("part"), examine_mime_part, 0);
-       RegisterMsgHdr(HKEY("text"), examine_text, 1);
-       RegisterMsgHdr(HKEY("X-Citadel-MSG4-Partnum"), examine_msg4_partnum, 0);
-       RegisterMsgHdr(HKEY("Content-type"), examine_content_type, 0);
-       RegisterMsgHdr(HKEY("Content-length"), examine_content_lengh, 0);
-       RegisterMsgHdr(HKEY("Content-transfer-encoding"), examine_content_encoding, 0);
        return ;
 }
diff --git a/webcit/msg_renderers.c b/webcit/msg_renderers.c
new file mode 100644 (file)
index 0000000..489b029
--- /dev/null
@@ -0,0 +1,816 @@
+/*----------------------------------------------------------------------------*/
+#include "webcit.h"
+#include "webserver.h"
+
+/**
+ * message index functions
+ */
+
+void DestroyMimeParts(wc_mime_attachment *Mime)
+{
+       FreeStrBuf(&Mime->Name);
+       FreeStrBuf(&Mime->FileName);
+       FreeStrBuf(&Mime->PartNum);
+       FreeStrBuf(&Mime->Disposition);
+       FreeStrBuf(&Mime->ContentType);
+       FreeStrBuf(&Mime->Charset);
+       FreeStrBuf(&Mime->Data);
+}
+
+void DestroyMime(void *vMime)
+{
+       wc_mime_attachment *Mime = (wc_mime_attachment*)vMime;
+       DestroyMimeParts(Mime);
+       free(Mime);
+}
+
+void DestroyMessageSummary(void *vMsg)
+{
+       message_summary *Msg = (message_summary*) vMsg;
+
+       FreeStrBuf(&Msg->from);
+       FreeStrBuf(&Msg->to);
+       FreeStrBuf(&Msg->subj);
+       FreeStrBuf(&Msg->reply_inreplyto);
+       FreeStrBuf(&Msg->reply_references);
+       FreeStrBuf(&Msg->cccc);
+       FreeStrBuf(&Msg->hnod);
+       FreeStrBuf(&Msg->AllRcpt);
+       FreeStrBuf(&Msg->Room);
+       FreeStrBuf(&Msg->Rfca);
+       FreeStrBuf(&Msg->OtherNode);
+
+       FreeStrBuf(&Msg->reply_to);
+
+       DeleteHash(&Msg->Attachments);  /**< list of Accachments */
+       DeleteHash(&Msg->Submessages);
+       DeleteHash(&Msg->AttachLinks);
+       DeleteHash(&Msg->AllAttach);
+
+       DestroyMimeParts(&Msg->MsgBody);
+
+       free(Msg);
+}
+
+
+
+void RegisterMsgHdr(const char *HeaderName, long HdrNLen, ExamineMsgHeaderFunc evaluator, int type)
+{
+       headereval *ev;
+       ev = (headereval*) malloc(sizeof(headereval));
+       ev->evaluator = evaluator;
+       ev->Type = type;
+       Put(MsgHeaderHandler, HeaderName, HdrNLen, ev, NULL);
+}
+
+void RegisterMimeRenderer(const char *HeaderName, long HdrNLen, RenderMimeFunc MimeRenderer)
+{
+       Put(MimeRenderHandler, HeaderName, HdrNLen, MimeRenderer, reference_free_handler);
+       
+}
+
+/*----------------------------------------------------------------------------*/
+
+
+void examine_nhdr(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
+{
+       Msg->nhdr = 0;
+       if (!strncasecmp(ChrPtr(HdrLine), "yes", 8))
+               Msg->nhdr = 1;
+}
+int Conditional_ANONYMOUS_MESSAGE(WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       return Msg->nhdr != 0;
+}
+
+
+void examine_type(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
+{
+       Msg->format_type = StrToi(HdrLine);
+                       
+}
+
+void examine_from(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
+{
+       FreeStrBuf(&Msg->from);
+       Msg->from = NewStrBufPlain(NULL, StrLength(HdrLine));
+       StrBuf_RFC822_to_Utf8(Msg->from, HdrLine, WC->DefaultCharset, FoundCharset);
+}
+void tmplput_MAIL_SUMM_FROM(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       StrBufAppendBuf(Target, Msg->from, 0);
+       lprintf(1,"%s", ChrPtr(Msg->from));
+}
+
+
+
+void examine_subj(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
+{
+       FreeStrBuf(&Msg->subj);
+       Msg->subj = NewStrBufPlain(NULL, StrLength(HdrLine));
+       StrBuf_RFC822_to_Utf8(Msg->subj, HdrLine, WC->DefaultCharset, FoundCharset);
+       lprintf(1,"%s", ChrPtr(Msg->subj));
+}
+void tmplput_MAIL_SUMM_SUBJECT(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{/////TODO: Fwd: and RE: filter!!
+       message_summary *Msg = (message_summary*) Context;
+       StrBufAppendBuf(Target, Msg->subj, 0);
+}
+
+
+void examine_msgn(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
+{
+       FreeStrBuf(&Msg->reply_inreplyto);
+       Msg->reply_inreplyto = NewStrBufPlain(NULL, StrLength(HdrLine));
+       StrBuf_RFC822_to_Utf8(Msg->reply_inreplyto, HdrLine, WC->DefaultCharset, FoundCharset);
+}
+void tmplput_MAIL_SUMM_INREPLYTO(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       StrBufAppendBuf(Target, Msg->reply_inreplyto, 0);
+}
+
+int Conditional_MAIL_SUMM_UNREAD(WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       return Msg->is_new != 0;
+}
+
+void examine_wefw(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
+{
+       FreeStrBuf(&Msg->reply_references);
+       Msg->reply_references = NewStrBufPlain(NULL, StrLength(HdrLine));
+       StrBuf_RFC822_to_Utf8(Msg->reply_references, HdrLine, WC->DefaultCharset, FoundCharset);
+}
+void tmplput_MAIL_SUMM_REFIDS(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       StrBufAppendBuf(Target, Msg->reply_references, 0);
+}
+
+
+void examine_cccc(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
+{
+       FreeStrBuf(&Msg->cccc);
+       Msg->cccc = NewStrBufPlain(NULL, StrLength(HdrLine));
+       StrBuf_RFC822_to_Utf8(Msg->cccc, HdrLine, WC->DefaultCharset, FoundCharset);
+       if (Msg->AllRcpt == NULL)
+               Msg->AllRcpt = NewStrBufPlain(NULL, StrLength(HdrLine));
+       if (StrLength(Msg->AllRcpt) > 0) {
+               StrBufAppendBufPlain(Msg->AllRcpt, HKEY(", "), 0);
+       }
+       StrBufAppendBuf(Msg->AllRcpt, Msg->cccc, 0);
+}
+void tmplput_MAIL_SUMM_CCCC(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       StrBufAppendBuf(Target, Msg->cccc, 0);
+}
+
+
+
+
+void examine_room(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
+{
+       if ((StrLength(HdrLine) > 0) &&
+           (strcasecmp(ChrPtr(HdrLine), WC->wc_roomname))) {
+               FreeStrBuf(&Msg->Room);
+               Msg->Room = NewStrBufDup(HdrLine);              
+       }
+}
+void tmplput_MAIL_SUMM_ORGROOM(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       StrBufAppendBuf(Target, Msg->Room, 0);
+}
+
+
+void examine_rfca(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
+{
+       FreeStrBuf(&Msg->Rfca);
+       Msg->Rfca = NewStrBufDup(HdrLine);
+}
+void tmplput_MAIL_SUMM_RFCA(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       StrBufAppendBuf(Target, Msg->Rfca, 0);
+}
+
+
+void examine_node(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
+{
+       if ( (StrLength(HdrLine) > 0) &&
+            ((WC->room_flags & QR_NETWORK)
+             || ((strcasecmp(ChrPtr(HdrLine), serv_info.serv_nodename)
+                  && (strcasecmp(ChrPtr(HdrLine), serv_info.serv_fqdn)))))) {
+               FreeStrBuf(&Msg->OtherNode);
+               Msg->OtherNode = NewStrBufDup(HdrLine);
+       }
+}
+void tmplput_MAIL_SUMM_OTHERNODE(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       StrBufAppendBuf(Target, Msg->OtherNode, 0);
+}
+int Conditional_MAIL_SUMM_OTHERNODE(WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       return StrLength(Msg->OtherNode) > 0;
+}
+
+
+void examine_rcpt(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
+{
+       FreeStrBuf(&Msg->to);
+       Msg->to = NewStrBufPlain(NULL, StrLength(HdrLine));
+       StrBuf_RFC822_to_Utf8(Msg->to, HdrLine, WC->DefaultCharset, FoundCharset);
+       if (Msg->AllRcpt == NULL)
+               Msg->AllRcpt = NewStrBufPlain(NULL, StrLength(HdrLine));
+       if (StrLength(Msg->AllRcpt) > 0) {
+               StrBufAppendBufPlain(Msg->AllRcpt, HKEY(", "), 0);
+       }
+       StrBufAppendBuf(Msg->AllRcpt, Msg->to, 0);
+}
+void tmplput_MAIL_SUMM_TO(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       StrBufAppendBuf(Target, Msg->to, 0);
+}
+void tmplput_MAIL_SUMM_ALLRCPT(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       StrBufAppendBuf(Target, Msg->AllRcpt, 0);
+}
+
+
+
+void examine_time(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
+{
+       Msg->date = StrTol(HdrLine);
+}
+void tmplput_MAIL_SUMM_DATE_STR(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       char datebuf[64];
+       message_summary *Msg = (message_summary*) Context;
+       webcit_fmt_date(datebuf, Msg->date, 1);
+       StrBufAppendBufPlain(Target, datebuf, -1, 0);
+}
+void tmplput_MAIL_SUMM_DATE_NO(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       StrBufAppendPrintf(Target, "%ld", Msg->date, 0);
+}
+
+
+
+void render_MAIL(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
+{
+/*
+       if ( (!IsEmptyStr(mime_submessages)) && (!section[0]) ) {
+               for (i=0; i<num_tokens(mime_submessages, '|'); ++i) {
+                       extract_token(buf, mime_submessages, i, '|', sizeof buf);
+                       /** use printable_view to suppress buttons * /
+                       wprintf("<blockquote>");
+                       read_message(Mime->msgnum, 1, ChrPtr(Mime->Section));
+                       wprintf("</blockquote>");
+               }
+       }
+*/
+}
+
+void render_MIME_VCard(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
+{
+       MimeLoadData(Mime);
+       if (StrLength(Mime->Data) > 0) {
+               StrBuf *Buf;
+               Buf = NewStrBuf();
+               /** If it's my vCard I can edit it */
+               if (    (!strcasecmp(WC->wc_roomname, USERCONFIGROOM))
+                       || (!strcasecmp(&WC->wc_roomname[11], USERCONFIGROOM))
+                       || (WC->wc_view == VIEW_ADDRESSBOOK)
+                       ) {
+                       StrBufAppendPrintf(Buf, "<a href=\"edit_vcard?msgnum=%ld&partnum=%s\">",
+                               Mime->msgnum, ChrPtr(Mime->PartNum));
+                       StrBufAppendPrintf(Buf, "[%s]</a>", _("edit"));
+               }
+
+               /* In all cases, display the full card */
+               display_vcard(Buf, ChrPtr(Mime->Data), 0, 1, NULL, Mime->msgnum);
+               FreeStrBuf(&Mime->Data);
+               Mime->Data = Buf;
+       }
+
+}
+void render_MIME_ICS(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
+{
+       MimeLoadData(Mime);
+       if (StrLength(Mime->Data) > 0) {
+               cal_process_attachment(Mime);
+       }
+}
+
+
+
+void examine_mime_part(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
+{
+       wc_mime_attachment *mime;
+       StrBuf *Buf;
+       void *vMimeRenderer;
+
+       mime = (wc_mime_attachment*) malloc(sizeof(wc_mime_attachment));
+       memset(mime, 0, sizeof(wc_mime_attachment));
+       mime->msgnum = Msg->msgnum;
+       Buf = NewStrBuf();
+
+       mime->Name = NewStrBuf();
+       StrBufExtract_token(mime->Name, HdrLine, 0, '|');
+
+       StrBufExtract_token(Buf, HdrLine, 1, '|');
+       mime->FileName = NewStrBuf();
+       StrBuf_RFC822_to_Utf8(mime->FileName, Buf, WC->DefaultCharset, FoundCharset);
+
+       mime->PartNum = NewStrBuf();
+       StrBufExtract_token(mime->PartNum, HdrLine, 2, '|');
+
+       mime->Disposition = NewStrBuf();
+       StrBufExtract_token(mime->Disposition, HdrLine, 3, '|');
+
+       mime->ContentType = NewStrBuf();
+       StrBufExtract_token(mime->ContentType, HdrLine, 4, '|');
+
+       mime->length = StrBufExtract_int(HdrLine, 5, '|');
+
+       StrBufTrim(mime->Name);
+       StrBufTrim(mime->FileName);
+
+       if ( (StrLength(mime->FileName) == 0) && (StrLength(mime->Name) > 0) ) {
+               StrBufAppendBuf(mime->FileName, mime->Name, 0);
+       }
+
+       if (Msg->AllAttach == NULL)
+               Msg->AllAttach = NewHash(1,NULL);
+       Put(Msg->AllAttach, SKEY(mime->PartNum), mime, DestroyMime);
+
+
+       if (GetHash(MimeRenderHandler, SKEY(mime->ContentType), &vMimeRenderer) &&
+           vMimeRenderer != NULL)
+       {
+               mime->Renderer = (RenderMimeFunc) vMimeRenderer;
+               if (Msg->Submessages == NULL)
+                       Msg->Submessages = NewHash(1,NULL);
+               Put(Msg->Submessages, SKEY(mime->PartNum), mime, reference_free_handler);
+       }
+       else if ((!strcasecmp(ChrPtr(mime->Disposition), "inline"))
+                && (!strncasecmp(ChrPtr(mime->ContentType), "image/", 6)) ){
+               if (Msg->AttachLinks == NULL)
+                       Msg->AttachLinks = NewHash(1,NULL);
+               Put(Msg->AttachLinks, SKEY(mime->PartNum), mime, reference_free_handler);
+       }
+       else if ((StrLength(mime->ContentType) > 0) &&
+                 ( (!strcasecmp(ChrPtr(mime->Disposition), "attachment")) 
+                   || (!strcasecmp(ChrPtr(mime->Disposition), "inline"))
+                   || (!strcasecmp(ChrPtr(mime->Disposition), ""))))
+       {               
+               if (Msg->AttachLinks == NULL)
+                       Msg->AttachLinks = NewHash(1,NULL);
+               Put(Msg->AttachLinks, SKEY(mime->PartNum), mime, reference_free_handler);
+               if (strcasecmp(ChrPtr(mime->ContentType), "application/octet-stream") == 0) {
+                       FlushStrBuf(mime->ContentType);
+                       StrBufAppendBufPlain(mime->ContentType,
+                                            GuessMimeByFilename(SKEY(mime->FileName)),
+                                            -1, 0);
+               }
+       }
+
+       FreeStrBuf(&Buf);
+}
+
+void tmplput_MAIL_SUMM_NATTACH(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       StrBufAppendPrintf(Target, "%ld", GetCount(Msg->Attachments));
+}
+
+
+
+
+
+
+
+void examine_hnod(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
+{
+       FreeStrBuf(&Msg->hnod);
+       Msg->hnod = NewStrBufPlain(NULL, StrLength(HdrLine));
+       StrBuf_RFC822_to_Utf8(Msg->hnod, HdrLine, WC->DefaultCharset, FoundCharset);
+}
+void tmplput_MAIL_SUMM_H_NODE(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       StrBufAppendBuf(Target, Msg->hnod, 0);
+}
+int Conditional_MAIL_SUMM_H_NODE(WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       return StrLength(Msg->hnod) > 0;
+}
+
+
+
+void examine_text(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
+{////TODO: read messages here
+       Msg->MsgBody.Data = NewStrBuf();
+}
+
+void examine_msg4_partnum(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
+{
+       Msg->MsgBody.PartNum = NewStrBufDup(HdrLine);
+       StrBufTrim(Msg->MsgBody.PartNum);/////TODO: striplt == trim?
+}
+
+void examine_content_encoding(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
+{
+////TODO: do we care?
+}
+
+void examine_content_lengh(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
+{
+       Msg->MsgBody.length = StrTol(HdrLine);
+       Msg->MsgBody.size_known = 1;
+}
+
+void examine_content_type(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
+{////TODO
+       int len, i;
+       Msg->MsgBody.ContentType = NewStrBufDup(HdrLine);
+       StrBufTrim(Msg->MsgBody.ContentType);/////todo==striplt?
+       len = StrLength(Msg->MsgBody.ContentType);
+       for (i=0; i<len; ++i) {
+               if (!strncasecmp(ChrPtr(Msg->MsgBody.ContentType) + i, "charset=", 8)) {/// TODO: WHUT?
+//                     safestrncpy(mime_charset, &mime_content_type[i+8],
+                       ///                         sizeof mime_charset);
+               }
+       }/****
+       for (i=0; i<len; ++i) {
+               if (mime_content_type[i] == ';') {
+                       mime_content_type[i] = 0;
+                       len = i - 1;
+               }
+       }
+       len = strlen(mime_charset);
+       for (i=0; i<len; ++i) {
+               if (mime_charset[i] == ';') {
+                       mime_charset[i] = 0;
+                       len = i - 1;
+               }
+       }
+        */
+}
+
+void tmplput_MAIL_SUMM_N(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       StrBufAppendPrintf(Target, "%ld", Msg->msgnum);
+}
+
+
+
+int Conditional_MAIL_MIME_ALL(WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       return GetCount(Msg->Attachments) > 0;
+}
+
+int Conditional_MAIL_MIME_SUBMESSAGES(WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       return GetCount(Msg->Submessages) > 0;
+}
+
+int Conditional_MAIL_MIME_ATTACHLINKS(WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       return GetCount(Msg->AttachLinks) > 0;
+}
+
+int Conditional_MAIL_MIME_ATTACH(WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       return GetCount(Msg->AllAttach) > 0;
+}
+
+
+
+/*----------------------------------------------------------------------------*/
+
+
+void tmplput_MAIL_BODY(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       StrBufAppendBuf(Target, Msg->MsgBody.Data, 0);
+}
+
+
+void render_MAIL_variformat(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
+{
+       /* Messages in legacy Citadel variformat get handled thusly... */
+       StrBuf *Target = NewStrBufPlain(NULL, StrLength(Mime->Data));
+       FmOut(Target, "JUSTIFY", Mime->Data);
+       FreeStrBuf(&Mime->Data);
+       Mime->Data = Target;
+}
+
+void render_MAIL_text_plain(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
+{
+       StrBuf *cs = NULL;
+       const char *ptr, *pte;
+       const char *BufPtr = NULL;
+       StrBuf *Line = NewStrBuf();
+       StrBuf *Line1 = NewStrBuf();
+       StrBuf *Line2 = NewStrBuf();
+       StrBuf *Target = NewStrBufPlain(NULL, StrLength(Mime->Data));
+       int ConvertIt = 1;
+       int bn = 0;
+       int bq = 0;
+       int i, n, done = 0;
+       long len;
+#ifdef HAVE_ICONV
+       iconv_t ic = (iconv_t)(-1) ;
+#endif
+
+       /* Boring old 80-column fixed format text gets handled this way... */
+       if ((strcasecmp(ChrPtr(Mime->Charset), "us-ascii") == 0) &&
+           (strcasecmp(ChrPtr(Mime->Charset), "UTF-8") == 0))
+               ConvertIt = 0;
+
+#ifdef HAVE_ICONV
+       if (ConvertIt) {
+               if (StrLength(Mime->Charset) != 0)
+                       cs = Mime->Charset;
+               else if (StrLength(FoundCharset) > 0)
+                       cs = FoundCharset;
+               else if (StrLength(WC->DefaultCharset) > 0)
+                       cs = WC->DefaultCharset;
+               if (cs == 0) {
+                       ConvertIt = 0;
+               }
+               else {
+                       ctdl_iconv_open("UTF-8", ChrPtr(cs), &ic);
+                       if (ic == (iconv_t)(-1) ) {
+                               lprintf(5, "%s:%d iconv_open(UTF-8, %s) failed: %s\n",
+                                       __FILE__, __LINE__, ChrPtr(Mime->Charset), strerror(errno));
+                       }
+               }
+       }
+#endif
+
+       while ((n = StrBufSipLine(Line, Mime->Data, &BufPtr), n >= 0) && !done)
+       {
+               done = n == 0;
+               bq = 0;
+               i = 0;
+               ptr = ChrPtr(Line);
+               len = StrLength(Line);
+               pte = ptr + len;
+               
+               while ((ptr < pte) &&
+                      ((*ptr == '>') ||
+                       isspace(*ptr)))
+               {
+                       if (*ptr == '>')
+                               bq++;
+                       ptr ++;
+                       i++;
+               }
+               if (i > 0) StrBufCutLeft(Line, i);
+               
+               if (StrLength(Line) == 0)
+                       continue;
+
+               for (i = bn; i < bq; i++)                               
+                       StrBufAppendBufPlain(Target, HKEY("<blockquote>"), 0);
+               for (i = bq; i < bn; i++)                               
+                       StrBufAppendBufPlain(Target, HKEY("</blockquote>"), 0);
+
+               if (ConvertIt == 1) {
+                       StrBufConvert(Line, Line1, &ic);
+               }
+
+               StrBufAppendBufPlain(Target, HKEY("<tt>"), 0);
+               UrlizeText(Line1, Line, Line2);
+
+               StrEscAppend(Target, Line1, NULL, 0, 0);
+               StrBufAppendBufPlain(Target, HKEY("</tt><br />\n"), 0);
+               bn = bq;
+       }
+
+       for (i = 0; i < bn; i++)                                
+               StrBufAppendBufPlain(Target, HKEY("</blockquote>"), 0);
+
+       StrBufAppendBufPlain(Target, HKEY("</i><br />"), 0);
+#ifdef HAVE_ICONV
+       if (ic != (iconv_t)(-1) ) {
+               iconv_close(ic);
+       }
+#endif
+       FreeStrBuf(&Mime->Data);
+       Mime->Data = Target;
+       FreeStrBuf(&Line);
+       FreeStrBuf(&Line1);
+       FreeStrBuf(&Line2);
+}
+
+void render_MAIL_html(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
+{
+       StrBuf *Buf;
+       /* HTML is fun, but we've got to strip it first */
+       Buf = NewStrBufPlain(NULL, StrLength(Mime->Data));
+       output_html(ChrPtr(Mime->Charset), 
+                   (WC->wc_view == VIEW_WIKI ? 1 : 0), 
+                   StrToi(Mime->PartNum), 
+                   Mime->Data, Buf);
+       FreeStrBuf(&Mime->Data);
+       Mime->Data = Buf;
+}
+
+void render_MAIL_UNKNOWN(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
+{
+       /* Unknown weirdness */
+       FlushStrBuf(Mime->Data);
+       StrBufAppendBufPlain(Mime->Data, _("I don't know how to display "), -1, 0);
+       StrBufAppendBuf(Mime->Data, Mime->ContentType, 0);
+       StrBufAppendBufPlain(Mime->Data, HKEY("<br />\n"), 0);
+}
+
+
+
+
+
+
+HashList *iterate_get_mime_All(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       return Msg->Attachments;
+}
+HashList *iterate_get_mime_Submessages(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       return Msg->Submessages;
+}
+HashList *iterate_get_mime_AttachLinks(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       return Msg->AttachLinks;
+}
+HashList *iterate_get_mime_Attachments(StrBuf *Target, int nArgs, WCTemplateToken *Tokens, void *Context, int ContextType)
+{
+       message_summary *Msg = (message_summary*) Context;
+       return Msg->AllAttach;
+}
+
+void tmplput_MIME_Name(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       wc_mime_attachment *mime = (wc_mime_attachment*) Context;
+       StrBufAppendBuf(Target, mime->Name, 0);
+}
+
+void tmplput_MIME_FileName(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       wc_mime_attachment *mime = (wc_mime_attachment*) Context;
+       StrBufAppendBuf(Target, mime->FileName, 0);
+}
+
+void tmplput_MIME_PartNum(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       wc_mime_attachment *mime = (wc_mime_attachment*) Context;
+       StrBufAppendBuf(Target, mime->PartNum, 0);
+}
+
+void tmplput_MIME_MsgNum(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       wc_mime_attachment *mime = (wc_mime_attachment*) Context;
+       StrBufAppendPrintf(Target, "%ld", mime->msgnum);
+}
+
+void tmplput_MIME_Disposition(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       wc_mime_attachment *mime = (wc_mime_attachment*) Context;
+       StrBufAppendBuf(Target, mime->Disposition, 0);
+}
+
+void tmplput_MIME_ContentType(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       wc_mime_attachment *mime = (wc_mime_attachment*) Context;
+       StrBufAppendBuf(Target, mime->ContentType, 0);
+}
+
+void tmplput_MIME_Charset(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       wc_mime_attachment *mime = (wc_mime_attachment*) Context;
+       StrBufAppendBuf(Target, mime->Charset, 0);
+}
+
+void tmplput_MIME_Data(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       wc_mime_attachment *mime = (wc_mime_attachment*) Context;
+       if (mime->Renderer != NULL)
+               mime->Renderer(mime, NULL, NULL);
+       StrBufAppendBuf(Target, mime->Data, 0); /// TODO: check whether we need to load it now?
+}
+
+void tmplput_MIME_Length(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
+{
+       wc_mime_attachment *mime = (wc_mime_attachment*) Context;
+       StrBufAppendPrintf(Target, "%ld", mime->length);
+}
+
+
+
+
+
+void 
+InitModule_MSGRENDERERS
+(void)
+{
+       RegisterNamespace("MAIL:SUMM:DATESTR", 0, 0, tmplput_MAIL_SUMM_DATE_STR, CTX_MAILSUM);
+       RegisterNamespace("MAIL:SUMM:DATENO",  0, 0, tmplput_MAIL_SUMM_DATE_NO,  CTX_MAILSUM);
+       RegisterNamespace("MAIL:SUMM:N",       0, 0, tmplput_MAIL_SUMM_N,        CTX_MAILSUM);
+       RegisterNamespace("MAIL:SUMM:FROM",    0, 2, tmplput_MAIL_SUMM_FROM,     CTX_MAILSUM);
+       RegisterNamespace("MAIL:SUMM:TO",      0, 2, tmplput_MAIL_SUMM_TO,       CTX_MAILSUM);
+       RegisterNamespace("MAIL:SUMM:SUBJECT", 0, 4, tmplput_MAIL_SUMM_SUBJECT,  CTX_MAILSUM);
+       RegisterNamespace("MAIL:SUMM:NTATACH", 0, 0, tmplput_MAIL_SUMM_NATTACH,  CTX_MAILSUM);
+       RegisterNamespace("MAIL:SUMM:CCCC", 0, 2, tmplput_MAIL_SUMM_CCCC,  CTX_MAILSUM);
+       RegisterNamespace("MAIL:SUMM:H_NODE", 0, 2, tmplput_MAIL_SUMM_H_NODE,  CTX_MAILSUM);
+       RegisterNamespace("MAIL:SUMM:ALLRCPT", 0, 2, tmplput_MAIL_SUMM_ALLRCPT,  CTX_MAILSUM);
+       RegisterNamespace("MAIL:SUMM:ORGROOM", 0, 2, tmplput_MAIL_SUMM_ORGROOM,  CTX_MAILSUM);
+       RegisterNamespace("MAIL:SUMM:RFCA", 0, 2, tmplput_MAIL_SUMM_RFCA,  CTX_MAILSUM);
+       RegisterNamespace("MAIL:SUMM:OTHERNODE", 2, 0, tmplput_MAIL_SUMM_OTHERNODE,  CTX_MAILSUM);
+       RegisterNamespace("MAIL:SUMM:REFIDS", 0, 0, tmplput_MAIL_SUMM_REFIDS,  CTX_MAILSUM);
+       RegisterNamespace("MAIL:SUMM:INREPLYTO", 0, 2, tmplput_MAIL_SUMM_INREPLYTO,  CTX_MAILSUM);
+       RegisterNamespace("MAIL:BODY", 0, 2, tmplput_MAIL_BODY,  CTX_MAILSUM);
+
+
+       RegisterConditional(HKEY("COND:MAIL:SUMM:UNREAD"), 0, Conditional_MAIL_SUMM_UNREAD, CTX_MAILSUM);
+       RegisterConditional(HKEY("COND:MAIL:SUMM:H_NODE"), 0, Conditional_MAIL_SUMM_H_NODE, CTX_MAILSUM);
+       RegisterConditional(HKEY("COND:MAIL:SUMM:OTHERNODE"), 0, Conditional_MAIL_SUMM_OTHERNODE, CTX_MAILSUM);
+       RegisterConditional(HKEY("COND:MAIL:ANON"), 0, Conditional_ANONYMOUS_MESSAGE, CTX_MAILSUM);
+
+       RegisterConditional(HKEY("COND:MAIL:MIME:ATTACH"), 0, Conditional_MAIL_MIME_ALL, CTX_MAILSUM);
+       RegisterConditional(HKEY("COND:MAIL:MIME:ATTACH:SUBMESSAGES"), 0, Conditional_MAIL_MIME_SUBMESSAGES, CTX_MAILSUM);
+       RegisterConditional(HKEY("COND:MAIL:MIME:ATTACH:LINKS"), 0, Conditional_MAIL_MIME_ATTACHLINKS, CTX_MAILSUM);
+       RegisterConditional(HKEY("COND:MAIL:MIME:ATTACH:ATT"), 0, Conditional_MAIL_MIME_ATTACH, CTX_MAILSUM);
+
+       RegisterIterator("MAIL:MIME:ATTACH", 0, NULL, iterate_get_mime_All, 
+                        NULL, NULL, CTX_MIME_ATACH, CTX_MAILSUM);
+       RegisterIterator("MAIL:MIME:ATTACH:SUBMESSAGES", 0, NULL, iterate_get_mime_Submessages, 
+                        NULL, NULL, CTX_MIME_ATACH, CTX_MAILSUM);
+       RegisterIterator("MAIL:MIME:ATTACH:LINKS", 0, NULL, iterate_get_mime_AttachLinks, 
+                        NULL, NULL, CTX_MIME_ATACH, CTX_MAILSUM);
+       RegisterIterator("MAIL:MIME:ATTACH:ATT", 0, NULL, iterate_get_mime_Attachments, 
+                        NULL, NULL, CTX_MIME_ATACH, CTX_MAILSUM);
+
+       RegisterNamespace("MAIL:MIME:NAME", 0, 2, tmplput_MIME_Name, CTX_MIME_ATACH);
+       RegisterNamespace("MAIL:MIME:FILENAME", 0, 2, tmplput_MIME_FileName, CTX_MIME_ATACH);
+       RegisterNamespace("MAIL:MIME:PARTNUM", 0, 2, tmplput_MIME_PartNum, CTX_MIME_ATACH);
+       RegisterNamespace("MAIL:MIME:MSGNUM", 0, 2, tmplput_MIME_MsgNum, CTX_MIME_ATACH);
+       RegisterNamespace("MAIL:MIME:DISPOSITION", 0, 2, tmplput_MIME_Disposition, CTX_MIME_ATACH);
+       RegisterNamespace("MAIL:MIME:CONTENTTYPE", 0, 2, tmplput_MIME_ContentType, CTX_MIME_ATACH);
+       RegisterNamespace("MAIL:MIME:CHARSET", 0, 2, tmplput_MIME_Charset, CTX_MIME_ATACH);
+       RegisterNamespace("MAIL:MIME:LENGTH", 0, 2, tmplput_MIME_Length, CTX_MIME_ATACH);
+       RegisterNamespace("MAIL:MIME:DATA", 0, 2, tmplput_MIME_Data, CTX_MIME_ATACH);
+
+
+
+       RegisterMimeRenderer(HKEY("message/rfc822"), render_MAIL);
+       RegisterMimeRenderer(HKEY("text/x-vcard"), render_MIME_VCard);
+       RegisterMimeRenderer(HKEY("text/vcard"), render_MIME_VCard);
+       RegisterMimeRenderer(HKEY("text/calendar"), render_MIME_ICS);
+       RegisterMimeRenderer(HKEY("application/ics"), render_MIME_ICS);
+
+       RegisterMimeRenderer(HKEY("text/x-citadel-variformat"), render_MAIL_variformat);
+       RegisterMimeRenderer(HKEY("text/plain"), render_MAIL_text_plain);
+       RegisterMimeRenderer(HKEY("text"), render_MAIL_text_plain);
+       RegisterMimeRenderer(HKEY("text/html"), render_MAIL_html);
+       RegisterMimeRenderer(HKEY(""), render_MAIL_UNKNOWN);
+
+       RegisterMsgHdr(HKEY("nhdr"), examine_nhdr, 0);
+       RegisterMsgHdr(HKEY("type"), examine_type, 0);
+       RegisterMsgHdr(HKEY("from"), examine_from, 0);
+       RegisterMsgHdr(HKEY("subj"), examine_subj, 0);
+       RegisterMsgHdr(HKEY("msgn"), examine_msgn, 0);
+       RegisterMsgHdr(HKEY("wefw"), examine_wefw, 0);
+       RegisterMsgHdr(HKEY("cccc"), examine_cccc, 0);
+       RegisterMsgHdr(HKEY("hnod"), examine_hnod, 0);
+       RegisterMsgHdr(HKEY("room"), examine_room, 0);
+       RegisterMsgHdr(HKEY("rfca"), examine_rfca, 0);
+       RegisterMsgHdr(HKEY("node"), examine_node, 0);
+       RegisterMsgHdr(HKEY("rcpt"), examine_rcpt, 0);
+       RegisterMsgHdr(HKEY("time"), examine_time, 0);
+       RegisterMsgHdr(HKEY("part"), examine_mime_part, 0);
+       RegisterMsgHdr(HKEY("text"), examine_text, 1);
+       RegisterMsgHdr(HKEY("X-Citadel-MSG4-Partnum"), examine_msg4_partnum, 0);
+       RegisterMsgHdr(HKEY("Content-type"), examine_content_type, 0);
+       RegisterMsgHdr(HKEY("Content-length"), examine_content_lengh, 0);
+       RegisterMsgHdr(HKEY("Content-transfer-encoding"), examine_content_encoding, 0);
+}
index c5deb98225f32bb1da1d6fa503789579efec3aa9..27cbc4379db1d795b661898f6f37662f329ae0a0 100644 (file)
@@ -4,6 +4,512 @@
 
 #include "webcit.h"
 
+
+/**
+ * \brief Record compare function for sorting address book indices
+ * \param ab1 adressbook one
+ * \param ab2 adressbook two
+ */
+int abcmp(const void *ab1, const void *ab2) {
+       return(strcasecmp(
+               (((const addrbookent *)ab1)->ab_name),
+               (((const addrbookent *)ab2)->ab_name)
+       ));
+}
+
+
+/**
+ * \brief Helper function for do_addrbook_view()
+ * Converts a name into a three-letter tab label
+ * \param tabbuf the tabbuffer to add name to
+ * \param name the name to add to the tabbuffer
+ */
+void nametab(char *tabbuf, long len, char *name) {
+       stresc(tabbuf, len, name, 0, 0);
+       tabbuf[0] = toupper(tabbuf[0]);
+       tabbuf[1] = tolower(tabbuf[1]);
+       tabbuf[2] = tolower(tabbuf[2]);
+       tabbuf[3] = 0;
+}
+
+
+
+/**
+ * \brief Turn a vCard "n" (name) field into something displayable.
+ * \param name the name field to convert
+ */
+void vcard_n_prettyize(char *name)
+{
+       char *original_name;
+       int i, j, len;
+
+       original_name = strdup(name);
+       len = strlen(original_name);
+       for (i=0; i<5; ++i) {
+               if (len > 0) {
+                       if (original_name[len-1] == ' ') {
+                               original_name[--len] = 0;
+                       }
+                       if (original_name[len-1] == ';') {
+                               original_name[--len] = 0;
+                       }
+               }
+       }
+       strcpy(name, "");
+       j=0;
+       for (i=0; i<len; ++i) {
+               if (original_name[i] == ';') {
+                       name[j++] = ',';
+                       name[j++] = ' ';                        
+               }
+               else {
+                       name[j++] = original_name[i];
+               }
+       }
+       name[j] = '\0';
+       free(original_name);
+}
+
+
+
+
+/**
+ * \brief preparse a vcard name
+ * display_vcard() calls this after parsing the textual vCard into
+ * our 'struct vCard' data object.
+ * This gets called instead of display_parsed_vcard() if we are only looking
+ * to extract the person's name instead of displaying the card.
+ * \param v the vcard to retrieve the name from
+ * \param storename where to put the name at
+ */
+void fetchname_parsed_vcard(struct vCard *v, char *storename) {
+       char *name;
+
+       strcpy(storename, "");
+
+       name = vcard_get_prop(v, "n", 1, 0, 0);
+       if (name != NULL) {
+               strcpy(storename, name);
+               /* vcard_n_prettyize(storename); */
+       }
+
+}
+
+
+
+/**
+ * \brief html print a vcard
+ * display_vcard() calls this after parsing the textual vCard into
+ * our 'struct vCard' data object.
+ *
+ * Set 'full' to nonzero to display the full card, otherwise it will only
+ * show a summary line.
+ *
+ * This code is a bit ugly, so perhaps an explanation is due: we do this
+ * in two passes through the vCard fields.  On the first pass, we process
+ * fields we understand, and then render them in a pretty fashion at the
+ * end.  Then we make a second pass, outputting all the fields we don't
+ * understand in a simple two-column name/value format.
+ * \param v the vCard to display
+ * \param full display all items of the vcard?
+ * \param msgnum Citadel message pointer
+ */
+void display_parsed_vcard(StrBuf *Target, struct vCard *v, int full, long msgnum) {
+       int i, j;
+       char buf[SIZ];
+       char *name;
+       int is_qp = 0;
+       int is_b64 = 0;
+       char *thisname, *thisvalue;
+       char firsttoken[SIZ];
+       int pass;
+
+       char fullname[SIZ];
+       char title[SIZ];
+       char org[SIZ];
+       char phone[SIZ];
+       char mailto[SIZ];
+
+       strcpy(fullname, "");
+       strcpy(phone, "");
+       strcpy(mailto, "");
+       strcpy(title, "");
+       strcpy(org, "");
+
+       if (!full) {
+               StrBufAppendPrintf(Target, "<TD>");
+               name = vcard_get_prop(v, "fn", 1, 0, 0);
+               if (name != NULL) {
+                       StrEscAppend(Target, NULL, name, 0, 0);
+               }
+               else if (name = vcard_get_prop(v, "n", 1, 0, 0), name != NULL) {
+                       strcpy(fullname, name);
+                       vcard_n_prettyize(fullname);
+                       StrEscAppend(Target, NULL, fullname, 0, 0);
+               }
+               else {
+                       StrBufAppendPrintf(Target, "&nbsp;");
+               }
+               StrBufAppendPrintf(Target, "</TD>");
+               return;
+       }
+
+       StrBufAppendPrintf(Target, "<div align=center>"
+               "<table bgcolor=#aaaaaa width=50%%>");
+       for (pass=1; pass<=2; ++pass) {
+
+               if (v->numprops) for (i=0; i<(v->numprops); ++i) {
+                       int len;
+                       thisname = strdup(v->prop[i].name);
+                       extract_token(firsttoken, thisname, 0, ';', sizeof firsttoken);
+       
+                       for (j=0; j<num_tokens(thisname, ';'); ++j) {
+                               extract_token(buf, thisname, j, ';', sizeof buf);
+                               if (!strcasecmp(buf, "encoding=quoted-printable")) {
+                                       is_qp = 1;
+                                       remove_token(thisname, j, ';');
+                               }
+                               if (!strcasecmp(buf, "encoding=base64")) {
+                                       is_b64 = 1;
+                                       remove_token(thisname, j, ';');
+                               }
+                       }
+                       
+                       len = strlen(v->prop[i].value);
+                       /* if we have some untagged QP, detect it here. */
+                       if (!is_qp && (strstr(v->prop[i].value, "=?")!=NULL))
+                               utf8ify_rfc822_string(v->prop[i].value);
+
+                       if (is_qp) {
+                               // %ff can become 6 bytes in utf8 
+                               thisvalue = malloc(len * 2 + 3); 
+                               j = CtdlDecodeQuotedPrintable(
+                                       thisvalue, v->prop[i].value,
+                                       len);
+                               thisvalue[j] = 0;
+                       }
+                       else if (is_b64) {
+                               // ff will become one byte..
+                               thisvalue = malloc(len + 50);
+                               CtdlDecodeBase64(
+                                       thisvalue, v->prop[i].value,
+                                       strlen(v->prop[i].value) );
+                       }
+                       else {
+                               thisvalue = strdup(v->prop[i].value);
+                       }
+       
+                       /** Various fields we may encounter ***/
+       
+                       /** N is name, but only if there's no FN already there */
+                       if (!strcasecmp(firsttoken, "n")) {
+                               if (IsEmptyStr(fullname)) {
+                                       strcpy(fullname, thisvalue);
+                                       vcard_n_prettyize(fullname);
+                               }
+                       }
+       
+                       /** FN (full name) is a true 'display name' field */
+                       else if (!strcasecmp(firsttoken, "fn")) {
+                               strcpy(fullname, thisvalue);
+                       }
+
+                       /** title */
+                       else if (!strcasecmp(firsttoken, "title")) {
+                               strcpy(title, thisvalue);
+                       }
+       
+                       /** organization */
+                       else if (!strcasecmp(firsttoken, "org")) {
+                               strcpy(org, thisvalue);
+                       }
+       
+                       else if (!strcasecmp(firsttoken, "email")) {
+                               size_t len;
+                               if (!IsEmptyStr(mailto)) strcat(mailto, "<br />");
+                               strcat(mailto,
+                                       "<a href=\"display_enter"
+                                       "?force_room=_MAIL_?recp=");
+
+                               len = strlen(mailto);
+                               urlesc(&mailto[len], SIZ - len, "\"");
+                               len = strlen(mailto);
+                               urlesc(&mailto[len], SIZ - len,  fullname);
+                               len = strlen(mailto);
+                               urlesc(&mailto[len], SIZ - len, "\" <");
+                               len = strlen(mailto);
+                               urlesc(&mailto[len], SIZ - len, thisvalue);
+                               len = strlen(mailto);
+                               urlesc(&mailto[len], SIZ - len, ">");
+
+                               strcat(mailto, "\">");
+                               len = strlen(mailto);
+                               stresc(mailto+len, SIZ - len, thisvalue, 1, 1);
+                               strcat(mailto, "</A>");
+                       }
+                       else if (!strcasecmp(firsttoken, "tel")) {
+                               if (!IsEmptyStr(phone)) strcat(phone, "<br />");
+                               strcat(phone, thisvalue);
+                               for (j=0; j<num_tokens(thisname, ';'); ++j) {
+                                       extract_token(buf, thisname, j, ';', sizeof buf);
+                                       if (!strcasecmp(buf, "tel"))
+                                               strcat(phone, "");
+                                       else if (!strcasecmp(buf, "work"))
+                                               strcat(phone, _(" (work)"));
+                                       else if (!strcasecmp(buf, "home"))
+                                               strcat(phone, _(" (home)"));
+                                       else if (!strcasecmp(buf, "cell"))
+                                               strcat(phone, _(" (cell)"));
+                                       else {
+                                               strcat(phone, " (");
+                                               strcat(phone, buf);
+                                               strcat(phone, ")");
+                                       }
+                               }
+                       }
+                       else if (!strcasecmp(firsttoken, "adr")) {
+                               if (pass == 2) {
+                                       StrBufAppendPrintf(Target, "<TR><TD>");
+                                       StrBufAppendPrintf(Target, _("Address:"));
+                                       StrBufAppendPrintf(Target, "</TD><TD>");
+                                       for (j=0; j<num_tokens(thisvalue, ';'); ++j) {
+                                               extract_token(buf, thisvalue, j, ';', sizeof buf);
+                                               if (!IsEmptyStr(buf)) {
+                                                       StrEscAppend(Target, NULL, buf, 0, 0);
+                                                       if (j<3) StrBufAppendPrintf(Target, "<br />");
+                                                       else StrBufAppendPrintf(Target, " ");
+                                               }
+                                       }
+                                       StrBufAppendPrintf(Target, "</TD></TR>\n");
+                               }
+                       }
+                       /* else if (!strcasecmp(firsttoken, "photo") && full && pass == 2) { 
+                               // Only output on second pass
+                               StrBufAppendPrintf(Target, "<tr><td>");
+                               StrBufAppendPrintf(Target, _("Photo:"));
+                               StrBufAppendPrintf(Target, "</td><td>");
+                               StrBufAppendPrintf(Target, "<img src=\"/vcardphoto/%ld/\" alt=\"Contact photo\"/>",msgnum);
+                               StrBufAppendPrintf(Target, "</td></tr>\n");
+                       } */
+                       else if (!strcasecmp(firsttoken, "version")) {
+                               /* ignore */
+                       }
+                       else if (!strcasecmp(firsttoken, "rev")) {
+                               /* ignore */
+                       }
+                       else if (!strcasecmp(firsttoken, "label")) {
+                               /* ignore */
+                       }
+                       else {
+
+                               /*** Don't show extra fields.  They're ugly.
+                               if (pass == 2) {
+                                       StrBufAppendPrintf(Target, "<TR><TD>");
+                                       StrEscAppend(Target, NULL, thisname, 0, 0);
+                                       StrBufAppendPrintf(Target, "</TD><TD>");
+                                       StrEscAppend(Target, NULL, thisvalue, 0, 0);
+                                       StrBufAppendPrintf(Target, "</TD></TR>\n");
+                               }
+                               ***/
+                       }
+       
+                       free(thisname);
+                       free(thisvalue);
+               }
+       
+               if (pass == 1) {
+                       StrBufAppendPrintf(Target, "<TR BGCOLOR=\"#AAAAAA\">"
+                       "<TD COLSPAN=2 BGCOLOR=\"#FFFFFF\">"
+                       "<IMG ALIGN=CENTER src=\"static/viewcontacts_48x.gif\">"
+                       "<FONT SIZE=+1><B>");
+                       StrEscAppend(Target, NULL, fullname, 0, 0);
+                       StrBufAppendPrintf(Target, "</B></FONT>");
+                       if (!IsEmptyStr(title)) {
+                               StrBufAppendPrintf(Target, "<div align=right>");
+                               StrEscAppend(Target, NULL, title, 0, 0);
+                               StrBufAppendPrintf(Target, "</div>");
+                       }
+                       if (!IsEmptyStr(org)) {
+                               StrBufAppendPrintf(Target, "<div align=right>");
+                               StrEscAppend(Target, NULL, org, 0, 0);
+                               StrBufAppendPrintf(Target, "</div>");
+                       }
+                       StrBufAppendPrintf(Target, "</TD></TR>\n");
+               
+                       if (!IsEmptyStr(phone)) {
+                               StrBufAppendPrintf(Target, "<tr><td>");
+                               StrBufAppendPrintf(Target, _("Telephone:"));
+                               StrBufAppendPrintf(Target, "</td><td>%s</td></tr>\n", phone);
+                       }
+                       if (!IsEmptyStr(mailto)) {
+                               StrBufAppendPrintf(Target, "<tr><td>");
+                               StrBufAppendPrintf(Target, _("E-mail:"));
+                               StrBufAppendPrintf(Target, "</td><td>%s</td></tr>\n", mailto);
+                       }
+               }
+
+       }
+
+       StrBufAppendPrintf(Target, "</table></div>\n");
+}
+
+
+
+/**
+ * \brief  Display a textual vCard
+ * (Converts to a vCard object and then calls the actual display function)
+ * Set 'full' to nonzero to display the whole card instead of a one-liner.
+ * Or, if "storename" is non-NULL, just store the person's name in that
+ * buffer instead of displaying the card at all.
+ * \param vcard_source the buffer containing the vcard text
+ * \param alpha what???
+ * \param full should we usse all lines?
+ * \param storename where to store???
+ * \param msgnum Citadel message pointer
+ */
+void display_vcard(StrBuf *Target, const char *vcard_source, char alpha, int full, char *storename, 
+       long msgnum) {
+       struct vCard *v;
+       char *name;
+       char buf[SIZ];
+       char this_alpha = 0;
+
+       v = vcard_load((char*)vcard_source); ///TODO
+
+       if (v == NULL) return;
+
+       name = vcard_get_prop(v, "n", 1, 0, 0);
+       if (name != NULL) {
+               utf8ify_rfc822_string(name);
+               strcpy(buf, name);
+               this_alpha = buf[0];
+       }
+
+       if (storename != NULL) {
+               fetchname_parsed_vcard(v, storename);
+       }
+       else if (       (alpha == 0)
+                       || ((isalpha(alpha)) && (tolower(alpha) == tolower(this_alpha)) )
+                       || ((!isalpha(alpha)) && (!isalpha(this_alpha)))
+               ) {
+               display_parsed_vcard(Target, v, full,msgnum);
+       }
+
+       vcard_free(v);
+}
+
+
+
+/**
+ * \brief Render the address book using info we gathered during the scan
+ * \param addrbook the addressbook to render
+ * \param num_ab the number of the addressbook
+ */
+void do_addrbook_view(addrbookent *addrbook, int num_ab) {
+       int i = 0;
+       int displayed = 0;
+       int bg = 0;
+       static int NAMESPERPAGE = 60;
+       int num_pages = 0;
+       int tabfirst = 0;
+       char tabfirst_label[64];
+       int tablast = 0;
+       char tablast_label[64];
+       char this_tablabel[64];
+       int page = 0;
+       char **tablabels;
+
+       if (num_ab == 0) {
+               wprintf("<br /><br /><br /><div align=\"center\"><i>");
+               wprintf(_("This address book is empty."));
+               wprintf("</i></div>\n");
+               return;
+       }
+
+       if (num_ab > 1) {
+               qsort(addrbook, num_ab, sizeof(addrbookent), abcmp);
+       }
+
+       num_pages = (num_ab / NAMESPERPAGE) + 1;
+
+       tablabels = malloc(num_pages * sizeof (char *));
+       if (tablabels == NULL) {
+               wprintf("<br /><br /><br /><div align=\"center\"><i>");
+               wprintf(_("An internal error has occurred."));
+               wprintf("</i></div>\n");
+               return;
+       }
+
+       for (i=0; i<num_pages; ++i) {
+               tabfirst = i * NAMESPERPAGE;
+               tablast = tabfirst + NAMESPERPAGE - 1;
+               if (tablast > (num_ab - 1)) tablast = (num_ab - 1);
+               nametab(tabfirst_label, 64, addrbook[tabfirst].ab_name);
+               nametab(tablast_label, 64, addrbook[tablast].ab_name);
+               sprintf(this_tablabel, "%s&nbsp;-&nbsp;%s", tabfirst_label, tablast_label);
+               tablabels[i] = strdup(this_tablabel);
+       }
+
+       tabbed_dialog(num_pages, tablabels);
+       page = (-1);
+
+       for (i=0; i<num_ab; ++i) {
+
+               if ((i / NAMESPERPAGE) != page) {       /* New tab */
+                       page = (i / NAMESPERPAGE);
+                       if (page > 0) {
+                               wprintf("</tr></table>\n");
+                               end_tab(page-1, num_pages);
+                       }
+                       begin_tab(page, num_pages);
+                       wprintf("<table border=0 cellspacing=0 cellpadding=3 width=100%%>\n");
+                       displayed = 0;
+               }
+
+               if ((displayed % 4) == 0) {
+                       if (displayed > 0) {
+                               wprintf("</tr>\n");
+                       }
+                       bg = 1 - bg;
+                       wprintf("<tr bgcolor=\"#%s\">",
+                               (bg ? "DDDDDD" : "FFFFFF")
+                       );
+               }
+       
+               wprintf("<td>");
+
+               wprintf("<a href=\"readfwd?startmsg=%ld?is_singlecard=1",
+                       addrbook[i].ab_msgnum);
+               wprintf("?maxmsgs=1?is_summary=0?alpha=%s\">", bstr("alpha"));
+               vcard_n_prettyize(addrbook[i].ab_name);
+               escputs(addrbook[i].ab_name);
+               wprintf("</a></td>\n");
+               ++displayed;
+       }
+
+       /* Placeholders for empty columns at end */
+       if ((num_ab % 4) != 0) {
+               for (i=0; i<(4-(num_ab % 4)); ++i) {
+                       wprintf("<td>&nbsp;</td>");
+               }
+       }
+
+       wprintf("</tr></table>\n");
+       end_tab((num_pages-1), num_pages);
+
+       begin_tab(num_pages, num_pages);
+       /* FIXME there ought to be something here */
+       end_tab(num_pages, num_pages);
+
+       for (i=0; i<num_pages; ++i) {
+               free(tablabels[i]);
+       }
+       free(tablabels);
+}
+
+
+
+
 /*
  * Edit the vCard component of a MIME message.  
  * Supply the message number
index 033262460a4d8471d74271ff02be5e438075f92a..4509ecb1ffa3a26fe3b116afcfbe11249d42a56a 100644 (file)
@@ -414,6 +414,7 @@ struct wc_mime_attachment {
        long msgnum;            /**< the message number on the citadel server derived from message_summary */
        RenderMimeFunc Renderer;
 };
+void DestroyMime(void *vMime);
 
 
 /*
@@ -455,6 +456,7 @@ typedef struct _message_summary {
        wc_mime_attachment *cal_partnum_ref;
        wc_mime_attachment *vcard_partnum_ref;
 } message_summary;
+void DestroyMessageSummary(void *vMsg);
 
 typedef void (*ExamineMsgHeaderFunc)(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset);
 
@@ -489,6 +491,35 @@ typedef struct _disp_cal {
 } disp_cal;                                            
 
 
+
+/*
+ * Address book entry (keep it short and sweet, it's just a quickie lookup
+ * which we can use to get to the real meat and bones later)
+ */
+typedef struct _addrbookent {
+       char ab_name[64]; /**< name string */
+       long ab_msgnum;   /**< message number of address book entry */
+} addrbookent;
+
+
+typedef struct _headereval {
+       ExamineMsgHeaderFunc evaluator;
+       int Type;
+} headereval;
+
+
+struct attach_link {
+       char partnum[32];
+       char html[1024];
+};
+
+
+enum {
+       eUp,
+       eDown,
+       eNone
+};
+
 /*
  * One of these is kept for each active Citadel session.
  * HTTP transactions are bound to one at a time.
@@ -750,6 +781,8 @@ void embed_main_menu(void);
 void serv_read(char *buf, int bytes);
 void readloop(char *oper);
 void read_message(long msgnum, int printable_view, char *section);
+void do_addrbook_view(addrbookent *addrbook, int num_ab);
+void display_vcard(StrBuf *Target, const char *vcard_source, char alpha, int full, char *storename, long msgnum);
 void text_to_server(char *ptr);
 void text_to_server_qp(char *ptr);
 void confirm_delete_msg(void);