* fix freeing.. well, most of it
[citadel.git] / webcit / messages.c
index 5cf8d6b896fc1a82fd91e2dc8dff2bd33af82e05..473b1e04985e971f2782c86e026c1d47683572f0 100644 (file)
@@ -241,8 +241,23 @@ 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)
 {
@@ -260,6 +275,14 @@ void DestroyMessageSummary(void *vMsg)
        FreeStrBuf(&Msg->Rfca);
        FreeStrBuf(&Msg->OtherNode);
 
+       FreeStrBuf(&Msg->reply_to);
+
+       DeleteHash(&Msg->Attachments);  /**< list of Accachments */
+       DeleteHash(&Msg->Submessages);
+       DeleteHash(&Msg->AttachLinks);
+
+       DestroyMimeParts(&Msg->MsgBody);
+
        free(Msg);
 }
 
@@ -283,24 +306,24 @@ void RegisterMimeRenderer(const char *HeaderName, long HdrNLen, RenderMimeFunc M
 /*----------------------------------------------------------------------------*/
 
 
-void examine_nhdr(message_summary *Msg, StrBuf *HdrLine)
+void examine_nhdr(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
 {
        Msg->nhdr = 0;
        if (!strncasecmp(ChrPtr(HdrLine), "yes", 8))
                Msg->nhdr = 1;
 }
 
-void examine_type(message_summary *Msg, StrBuf *HdrLine)
+void examine_type(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
 {
        Msg->format_type = StrToi(HdrLine);
                        
 }
 
-void examine_from(message_summary *Msg, StrBuf *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);
+       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)
 {
@@ -311,11 +334,11 @@ void tmplput_MAIL_SUMM_FROM(StrBuf *Target, int nArgs, WCTemplateToken *Token, v
 
 
 
-void examine_subj(message_summary *Msg, StrBuf *HdrLine)
+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);
+       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)
@@ -325,11 +348,11 @@ void tmplput_MAIL_SUMM_SUBJECT(StrBuf *Target, int nArgs, WCTemplateToken *Token
 }
 
 
-void examine_msgn(message_summary *Msg, StrBuf *HdrLine)
+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);
+       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)
 {
@@ -338,11 +361,11 @@ void tmplput_MAIL_SUMM_INREPLYTO(StrBuf *Target, int nArgs, WCTemplateToken *Tok
 }
 
 
-void examine_wefw(message_summary *Msg, StrBuf *HdrLine)
+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);
+       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)
 {
@@ -351,11 +374,11 @@ void tmplput_MAIL_SUMM_REFIDS(StrBuf *Target, int nArgs, WCTemplateToken *Token,
 }
 
 
-void examine_cccc(message_summary *Msg, StrBuf *HdrLine)
+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);
+       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) {
@@ -372,7 +395,7 @@ void tmplput_MAIL_SUMM_CCCC(StrBuf *Target, int nArgs, WCTemplateToken *Token, v
 
 
 
-void examine_room(message_summary *Msg, StrBuf *HdrLine)
+void examine_room(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
 {
        if ((StrLength(HdrLine) > 0) &&
            (strcasecmp(ChrPtr(HdrLine), WC->wc_roomname))) {
@@ -387,7 +410,7 @@ void tmplput_MAIL_SUMM_ORGROOM(StrBuf *Target, int nArgs, WCTemplateToken *Token
 }
 
 
-void examine_rfca(message_summary *Msg, StrBuf *HdrLine)
+void examine_rfca(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
 {
        FreeStrBuf(&Msg->Rfca);
        Msg->Rfca = NewStrBufDup(HdrLine);
@@ -399,7 +422,7 @@ void tmplput_MAIL_SUMM_RFCA(StrBuf *Target, int nArgs, WCTemplateToken *Token, v
 }
 
 
-void examine_node(message_summary *Msg, StrBuf *HdrLine)
+void examine_node(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
 {
        if ( (StrLength(HdrLine) > 0) &&
             ((WC->room_flags & QR_NETWORK)
@@ -421,11 +444,11 @@ int Conditional_MAIL_SUMM_OTHERNODE(WCTemplateToken *Tokens, void *Context, int
 }
 
 
-void examine_rcpt(message_summary *Msg, StrBuf *HdrLine)
+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);
+       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) {
@@ -446,7 +469,7 @@ void tmplput_MAIL_SUMM_ALLRCPT(StrBuf *Target, int nArgs, WCTemplateToken *Token
 
 
 
-void examine_time(message_summary *Msg, StrBuf *HdrLine)
+void examine_time(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
 {
        Msg->date = StrTol(HdrLine);
 }
@@ -465,29 +488,35 @@ void tmplput_MAIL_SUMM_DATE_NO(StrBuf *Target, int nArgs, WCTemplateToken *Token
 
 
 
-void examine_mime_part(message_summary *Msg, StrBuf *HdrLine)
+void examine_mime_part(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
 {
        wc_mime_attachment *mime;
        StrBuf *Buf;
 
        mime = (wc_mime_attachment*) malloc(sizeof(wc_mime_attachment));
        memset(mime, 0, sizeof(wc_mime_attachment));
-       Buf=NewStrBuf();
+       Buf = NewStrBuf();
 
        mime->Name = NewStrBuf();
        StrBufExtract_token(mime->Name, HdrLine, 0, '|');
+
        StrBufExtract_token(Buf, HdrLine, 1, '|');
-       StrBuf_RFC822_to_Utf8(mime->FileName, Buf, WC->DefaultCharset);
+       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);
        }
@@ -530,6 +559,9 @@ void examine_mime_part(message_summary *Msg, StrBuf *HdrLine)
                Msg->cal_partnum_ref = mime;
        }
        /** end handler prep ***/
+
+       FreeStrBuf(&Buf);
+
 }
 void tmplput_MAIL_SUMM_NATTACH(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *Context, int ContextType)
 {
@@ -543,11 +575,11 @@ void tmplput_MAIL_SUMM_NATTACH(StrBuf *Target, int nArgs, WCTemplateToken *Token
 
 
 
-void examine_hnod(message_summary *Msg, StrBuf *HdrLine)
+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);
+       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)
 {
@@ -562,28 +594,29 @@ int Conditional_MAIL_SUMM_H_NODE(WCTemplateToken *Tokens, void *Context, int Con
 
 
 
-void examine_text(message_summary *Msg, StrBuf *HdrLine)
+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)
+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)
+void examine_content_encoding(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
 {
 ////TODO: do we care?
 }
 
-void examine_content_lengh(message_summary *Msg, StrBuf *HdrLine)
+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)
+void examine_content_type(message_summary *Msg, StrBuf *HdrLine, StrBuf *FoundCharset)
 {////TODO
        int len, i;
        Msg->MsgBody.ContentType = NewStrBufDup(HdrLine);
@@ -636,103 +669,135 @@ void tmplput_MAIL_BODY(StrBuf *Target, int nArgs, WCTemplateToken *Token, void *
 }
 
 
-void render_MAIL_variformat(wc_mime_attachment *Mime, StrBuf *RawData)
+void render_MAIL_variformat(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
 {
        /* Messages in legacy Citadel variformat get handled thusly... */
-       fmout("JUSTIFY");///todo: this won't work that way.
-       
+       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)
+void render_MAIL_text_plain(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
 {
-       /* Boring old 80-column fixed format text gets handled this way... * /
+       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) ;
-       char *ibuf;                / **< Buffer of characters to be converted * /
-       char *obuf;                / **< Buffer for converted characters      * /
-       size_t ibuflen;    / **< Length of input buffer        * /
-       size_t obuflen;    / **< Length of output buffer              * /
-       char *osav;                / **< Saved pointer to output buffer       * /
 #endif
 
-       / * Set up a character set conversion if we need to (and if we can) * /
+       /* 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 (strchr(mime_charset, ';')) strcpy(strchr(mime_charset, ';'), "");
-       if ( (strcasecmp(mime_charset, "us-ascii"))
-          && (strcasecmp(mime_charset, "UTF-8"))
-          && (strcasecmp(mime_charset, ""))
-       ) {
-               ic = ctdl_iconv_open("UTF-8", mime_charset);
-               if (ic == (iconv_t)(-1) ) {
-                       lprintf(5, "%s:%d iconv_open(UTF-8, %s) failed: %s\n",
-                               __FILE__, __LINE__, mime_charset, strerror(errno));
+       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
 
-       buf [0] = '\0';
-       while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
-               int len;
-               len = strlen(buf);
-               if ((len > 0) && buf[len-1] == '\n') buf[--len] = 0;
-               if ((len > 0) && buf[len-1] == '\r') buf[--len] = 0;
+       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;
                
-#ifdef HAVE_ICONV
-               if (ic != (iconv_t)(-1) ) {
-                       ibuf = buf;
-                       ibuflen = strlen(ibuf);
-                       obuflen = SIZ;
-                       obuf = (char *) malloc(obuflen);
-                       osav = obuf;
-                       iconv(ic, &ibuf, &ibuflen, &obuf, &obuflen);
-                       osav[SIZ-obuflen] = 0;
-                       safestrncpy(buf, osav, sizeof buf);
-                       free(osav);
+               while ((ptr < pte) &&
+                      ((*ptr == '>') ||
+                       isspace(*ptr)))
+               {
+                       if (*ptr == '>')
+                               bq++;
+                       ptr ++;
+                       i++;
                }
-#endif
+               if (i > 0) StrBufCutLeft(Line, i);
                
-               len = strlen(buf);
-               while ((!IsEmptyStr(buf)) && (isspace(buf[len-1])))
-                       buf[--len] = 0;
-               if ((bq == 0) &&
-                   ((!strncmp(buf, ">", 1)) || (!strncmp(buf, " >", 2)) )) {
-                       wprintf("<blockquote>");
-                       bq = 1;
-               } else if ((bq == 1) &&
-                          (strncmp(buf, ">", 1)) && (strncmp(buf, " >", 2)) ) {
-                       wprintf("</blockquote>");
-                       bq = 0;
-               }
-               wprintf("<tt>");
-               url(buf, sizeof(buf));
-               escputs(buf);
-               wprintf("</tt><br />\n");
-       }
-       wprintf("</i><br />")
+               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)
+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), Mime->PartNum, Mime->Data, Buf);
+       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)
+void render_MAIL_UNKNOWN(wc_mime_attachment *Mime, StrBuf *RawData, StrBuf *FoundCharset)
 {
        /* Unknown weirdness */
-////   wprintf(_("I don't know how to display %s"), Msg->MsgBody->ContentType);
-       wprintf("<br />\n");
+       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);
 }
 
 
@@ -745,6 +810,63 @@ void render_MAIL_UNKNOWN(wc_mime_attachment *Mime, StrBuf *RawData)
  * Look for URL's embedded in a buffer and make them linkable.  We use a
  * target window in order to keep the Citadel session in its own window.
  */
+void UrlizeText(StrBuf* Target, StrBuf *Source, StrBuf *WrkBuf)
+{
+       int len, UrlLen, Offset, TrailerLen;
+       const char *start, *end, *pos;
+       
+       FlushStrBuf(Target);
+
+       start = NULL;
+       len = StrLength(Source);
+       end = ChrPtr(Source) + len;
+       for (pos = ChrPtr(Source); (pos < end) && (start == NULL); ++pos) {
+               if (!strncasecmp(pos, "http://", 7))
+                       start = pos;
+               if (!strncasecmp(pos, "ftp://", 6))
+                       start = pos;
+       }
+
+       if (start == NULL) {
+               StrBufAppendBuf(Target, Source, 0);
+               return;
+       }
+       FlushStrBuf(WrkBuf);
+
+       for (pos = ChrPtr(Source) + len; pos > start; --pos) {
+               if (  (!isprint(*pos))
+                  || (isspace(*pos))
+                  || (*pos == '{')
+                  || (*pos == '}')
+                  || (*pos == '|')
+                  || (*pos == '\\')
+                  || (*pos == '^')
+                  || (*pos == '[')
+                  || (*pos == ']')
+                  || (*pos == '`')
+                  || (*pos == '<')
+                  || (*pos == '>')
+                  || (*pos == '(')
+                  || (*pos == ')')
+               ) {
+                       end = pos;
+               }
+       }
+       
+       UrlLen = end - start;
+       StrBufAppendBufPlain(WrkBuf, start, UrlLen, 0);
+
+       Offset = start - ChrPtr(Source);
+       if (Offset != 0)
+               StrBufAppendBufPlain(Target, ChrPtr(Source), Offset, 0);
+       StrBufAppendPrintf(Target, "%ca href=%c%s%c TARGET=%c%s%c%c%s%c/A%c",
+                          LB, QU, ChrPtr(WrkBuf), QU, QU, TARGET, 
+                          QU, RB, ChrPtr(WrkBuf), LB, RB);
+
+       TrailerLen = len - (end - start);
+       if (TrailerLen > 0)
+               StrBufAppendBufPlain(Target, end, TrailerLen, 0);
+}
 void url(char *buf, size_t bufsize)
 {
        int len, UrlLen, Offset, TrailerLen, outpos;
@@ -1205,7 +1327,8 @@ void read_message(long msgnum, int printable_view, char *section) {
        struct wcsession *WCC = WC;
        StrBuf *Buf;
        StrBuf *Token;
-       message_summary *Msg;
+       StrBuf *FoundCharset;
+       message_summary *Msg = NULL;
        headereval *Hdr;
        void *vHdr;
        char buf[SIZ];
@@ -1241,7 +1364,7 @@ void read_message(long msgnum, int printable_view, char *section) {
        Token = NewStrBuf();
        Msg = (message_summary *)malloc(sizeof(message_summary));
        memset(Msg, 0, sizeof(message_summary));
-       Msg->MsgBody.length=-1;
+       FoundCharset = NewStrBuf();
        while ((StrBuf_ServGetln(Buf)>=0) && !Done) {
                if ( (StrLength(Buf)==3) && 
                    !strcmp(ChrPtr(Buf), "000")) 
@@ -1255,6 +1378,7 @@ void read_message(long msgnum, int printable_view, char *section) {
                                FreeStrBuf(&Buf);
                                FreeStrBuf(&Token);
                                DestroyMessageSummary(Msg);
+                               FreeStrBuf(&FoundCharset);
                                return;
                        }
                        else {
@@ -1274,7 +1398,7 @@ void read_message(long msgnum, int printable_view, char *section) {
                        if (GetHash(MsgHeaderHandler, SKEY(Token), &vHdr) &&
                            (vHdr != NULL)) {
                                Hdr = (headereval*)vHdr;
-                               Hdr->evaluator(Msg, Buf);
+                               Hdr->evaluator(Msg, Buf, FoundCharset);
                                if (Hdr->Type == 1) {
                                        state++;
                                }
@@ -1298,14 +1422,14 @@ void read_message(long msgnum, int printable_view, char *section) {
                                        if (GetHash(MsgHeaderHandler, SKEY(Token), &vHdr) &&
                                            (vHdr != NULL)) {
                                                Hdr = (headereval*)vHdr;
-                                               Hdr->evaluator(Msg, Buf);
+                                               Hdr->evaluator(Msg, Buf, FoundCharset);
                                        }
                                        break;
                                }
                        }
                case 2: /* Message Body */
                        
-                       if (Msg->MsgBody.length > 0) {
+                       if (Msg->MsgBody.size_known > 0) {
                                StrBuf_ServGetBLOB(Msg->MsgBody.Data, Msg->MsgBody.length);
                                state ++;
                                        /// todo: check next line, if not 000, append following lines
@@ -1321,6 +1445,17 @@ void read_message(long msgnum, int printable_view, char *section) {
                        break;
                }
        }
+       
+       /* strip the bare contenttype, so we ommit charset etc. */
+       StrBufExtract_token(Buf, Msg->MsgBody.ContentType, 0, ';');
+       StrBufTrim(Buf);
+       if (GetHash(MimeRenderHandler, SKEY(Buf), &vHdr) &&
+           (vHdr != NULL)) {
+               RenderMimeFunc Render;
+               Render = (RenderMimeFunc)vHdr;
+               Render(&Msg->MsgBody, NULL, FoundCharset);
+       }
+
 
        if (StrLength(Msg->reply_references)> 0) {
                /* Trim down excessively long lists of thread references.  We eliminate the
@@ -1369,22 +1504,6 @@ void read_message(long msgnum, int printable_view, char *section) {
        if (nhdr == 1) {
                wprintf("****");
        }
-
-       if (StrLength(Msg->cccc)> 0) {
-               StrBuf *tmp;
-               tmp = Msg->cccc;
-               Msg->cccc = Buf;
-               StrBuf_RFC822_to_Utf8(Msg->cccc, tmp, WCC->DefaultCharset);
-               Buf = tmp;
-       }
-       if (StrLength(Msg->subj)> 0) {
-               StrBuf *tmp;
-               tmp = Msg->subj;
-               Msg->subj = Buf;
-               StrBuf_RFC822_to_Utf8(Msg->subj, tmp, WCC->DefaultCharset);
-               Buf = tmp;
-       }
-
        DoTemplate(HKEY("view_message"), NULL, Msg, CTX_MAILSUM);
 
 
@@ -1455,7 +1574,10 @@ void read_message(long msgnum, int printable_view, char *section) {
        if (num_attach_links > 0) {
                free(attach_links);
        }
-
+       DestroyMessageSummary(Msg);
+       FreeStrBuf(&FoundCharset);
+       FreeStrBuf(&Token);
+       FreeStrBuf(&Buf);
 }
 
 
@@ -1747,7 +1869,7 @@ void pullquote_message(long msgnum, int forward_attachments, int include_headers
           && (strcasecmp(mime_charset, "UTF-8"))
           && (strcasecmp(mime_charset, ""))
        ) {
-               ic = ctdl_iconv_open("UTF-8", mime_charset);
+               ctdl_iconv_open("UTF-8", mime_charset, &ic);
                if (ic == (iconv_t)(-1) ) {
                        lprintf(5, "%s:%d iconv_open(%s, %s) failed: %s\n",
                                __FILE__, __LINE__, "UTF-8", mime_charset, strerror(errno));
@@ -2215,6 +2337,7 @@ void do_addrbook_view(struct addrbookent *addrbook, int num_ab) {
  */
 int load_msg_ptrs(char *servcmd, int with_headers)
 {
+       StrBuf* FoundCharset = NULL;
         struct wcsession *WCC = WC;
        message_summary *Msg;
        StrBuf *Buf, *Buf2;
@@ -2264,7 +2387,7 @@ int load_msg_ptrs(char *servcmd, int with_headers)
                        StrBufExtract_token(Buf2, Buf, 2, '|');
                        if (StrLength(Buf2) != 0) {
                                /** Handle senders with RFC2047 encoding */
-                               StrBuf_RFC822_to_Utf8(Msg->from, Buf2, WCC->DefaultCharset);
+                               StrBuf_RFC822_to_Utf8(Msg->from, Buf2, WCC->DefaultCharset, FoundCharset);
                        }
                        
                        /** Nodename */
@@ -2287,7 +2410,7 @@ int load_msg_ptrs(char *servcmd, int with_headers)
                        if (StrLength(Buf2) == 0)
                                StrBufAppendBufPlain(Msg->subj, _("(no subj)"), 0, -1);
                        else {
-                               StrBuf_RFC822_to_Utf8(Msg->subj, Buf2, WCC->DefaultCharset);
+                               StrBuf_RFC822_to_Utf8(Msg->subj, Buf2, WCC->DefaultCharset, FoundCharset);
                                if ((StrLength(Msg->subj) > 75) && 
                                    (StrBuf_Utf8StrLen(Msg->subj) > 75)) {
                                        StrBuf_Utf8StrCut(Msg->subj, 72);
@@ -2327,7 +2450,8 @@ void readloop(char *oper)
        char cmd[256] = "";
        char buf[SIZ];
        char old_msgs[SIZ];
-       int a, b;
+       int a = 0;
+       int b = 0;
        int nummsgs;
        long startmsg;
        int maxmsgs;