X-Git-Url: https://code.citadel.org/?a=blobdiff_plain;f=webcit%2Fmessages.c;h=9e05d552d03a1d2d606ad32ba43519e5faf9b4fa;hb=8d8c5af38e5026933ea3b9d5eb1b75f276df1d99;hp=9af483f6a7df928bf57cde866846d625ba1c59fb;hpb=ef84280cb2739fe9e0c2772ed2b1f505af01054c;p=citadel.git diff --git a/webcit/messages.c b/webcit/messages.c index 9af483f6a..9e05d552d 100644 --- a/webcit/messages.c +++ b/webcit/messages.c @@ -3,6 +3,7 @@ */ /** * \defgroup MsgDisp Functions which deal with the fetching and displaying of messages. + * \ingroup WebcitDisplayItems * */ /*@{*/ @@ -11,9 +12,9 @@ #include "webserver.h" #include "groupdav.h" -#define SUBJ_COL_WIDTH_PCT 50 /**< ??? */ -#define SENDER_COL_WIDTH_PCT 30 /**< ??? */ -#define DATE_PLUS_BUTTONS_WIDTH_PCT 20 /**< ??? */ +#define SUBJ_COL_WIDTH_PCT 50 /**< Mailbox view column width */ +#define SENDER_COL_WIDTH_PCT 30 /**< Mailbox view column width */ +#define DATE_PLUS_BUTTONS_WIDTH_PCT 20 /**< Mailbox view column width */ /** * Address book entry (keep it short and sweet, it's just a quickie lookup @@ -21,12 +22,38 @@ */ struct addrbookent { char ab_name[64]; /**< name string */ - long ab_msgnum; /**< number in the citadel???? */ + long ab_msgnum; /**< message number of address book entry */ }; #ifdef HAVE_ICONV + +/** + * \brief Wrapper around iconv_open() + * Our version adds aliases for non-standard Microsoft charsets + * such as 'MS950', aliasing them to names like 'CP950' + * + * \param tocode Target encoding + * \param fromcode Source encoding + */ +iconv_t ctdl_iconv_open(const char *tocode, const char *fromcode) +{ + iconv_t ic = (iconv_t)(-1) ; + ic = iconv_open(tocode, fromcode); + if (ic == (iconv_t)(-1) ) { + char alias_fromcode[64]; + if ( (strlen(fromcode) == 5) && (!strncasecmp(fromcode, "MS", 2)) ) { + safestrncpy(alias_fromcode, fromcode, sizeof alias_fromcode); + alias_fromcode[0] = 'C'; + alias_fromcode[1] = 'P'; + ic = iconv_open(tocode, alias_fromcode); + } + } + return(ic); +} + + /** * \brief Handle subjects with RFC2047 encoding * such as: @@ -40,14 +67,53 @@ void utf8ify_rfc822_string(char *buf) { char encoding[16]; char istr[1024]; 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 *isav; /**< Saved pointer to input buffer */ - char *osav; /**< Saved pointer to output buffer */ + 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 *isav; /**< Saved pointer to input buffer */ + char *osav; /**< Saved pointer to output buffer */ int passes = 0; + int i; + int illegal_non_rfc2047_encoding = 0; + /** Sometimes, badly formed messages contain strings which were simply + * written out directly in some foreign character set instead of + * using RFC2047 encoding. This is illegal but we will attempt to + * handle it anyway by converting from a user-specified default + * charset to UTF-8 if we see any nonprintable characters. + */ + for (i=0; i 126)) { + illegal_non_rfc2047_encoding = 1; + } + } + if (illegal_non_rfc2047_encoding) { + char default_header_charset[128]; + get_preference("default_header_charset", default_header_charset, sizeof default_header_charset); + if ( (strcasecmp(default_header_charset, "UTF-8")) && (strcasecmp(default_header_charset, "us-ascii")) ) { + ic = ctdl_iconv_open("UTF-8", default_header_charset); + if (ic != (iconv_t)(-1) ) { + ibuf = malloc(1024); + isav = ibuf; + safestrncpy(ibuf, buf, 1024); + ibuflen = strlen(ibuf); + obuflen = 1024; + obuf = (char *) malloc(obuflen); + osav = obuf; + iconv(ic, &ibuf, &ibuflen, &obuf, &obuflen); + osav[1024-obuflen] = 0; + strcpy(buf, osav); + free(osav); + iconv_close(ic); + free(isav); + } + } + } + + /** Now we handle foreign character sets properly encoded + * in RFC2047 format. + */ while (start=strstr(buf, "=?"), end=strstr(buf, "?="), ((start != NULL) && (end != NULL) && (end > start)) ) { @@ -55,10 +121,6 @@ void utf8ify_rfc822_string(char *buf) { extract_token(encoding, start, 2, '?', sizeof encoding); extract_token(istr, start, 3, '?', sizeof istr); - /*strcpy(start, ""); - ++end; - ++end;*/ - ibuf = malloc(1024); isav = ibuf; if (!strcasecmp(encoding, "B")) { /**< base64 */ @@ -68,13 +130,12 @@ void utf8ify_rfc822_string(char *buf) { ibuflen = CtdlDecodeQuotedPrintable(ibuf, istr, strlen(istr)); } else { - strcpy(ibuf, istr); /**< huh? */ + strcpy(ibuf, istr); /**< unknown encoding */ ibuflen = strlen(istr); } - ic = iconv_open("UTF-8", charset); + ic = ctdl_iconv_open("UTF-8", charset); if (ic != (iconv_t)(-1) ) { - obuf = malloc(1024); obuflen = 1024; obuf = (char *) malloc(obuflen); osav = obuf; @@ -125,6 +186,53 @@ void utf8ify_rfc822_string(char *buf) { #endif + + +/** + * \brief RFC2047-encode a header field if necessary. + * If no non-ASCII characters are found, the string + * will be copied verbatim without encoding. + * + * \param target Target buffer. + * \param maxlen Maximum size of target buffer. + * \param source Source string to be encoded. + */ +void rfc2047encode(char *target, int maxlen, char *source) +{ + int need_to_encode = 0; + int i; + unsigned char ch; + + if (target == NULL) return; + + for (i=0; i 126)) { + need_to_encode = 1; + } + } + + if (!need_to_encode) { + safestrncpy(target, source, maxlen); + return; + } + + strcpy(target, "=?UTF-8?Q?"); + for (i=0; i 126) || (ch == 61)) { + sprintf(&target[strlen(target)], "=%02X", ch); + } + else { + sprintf(&target[strlen(target)], "%c", ch); + } + } + + strcat(target, "?="); +} + + + + /** * \brief Look for URL's embedded in a buffer and make them linkable. We use a * target window in order to keep the BBS session in its own window. @@ -654,13 +762,16 @@ void read_message(long msgnum, int printable_view, char *section) { } if (!strncasecmp(buf, "rcpt=", 5)) { wprintf(_("to ")); - escputs(&buf[5]); - wprintf(" "); if (strlen(reply_all) > 0) { strcat(reply_all, ", "); } safestrncpy(&reply_all[strlen(reply_all)], &buf[5], (sizeof reply_all - strlen(reply_all)) ); +#ifdef HAVE_ICONV + utf8ify_rfc822_string(&buf[5]); +#endif + escputs(&buf[5]); + wprintf(" "); } if (!strncasecmp(buf, "time=", 5)) { fmt_date(now, atol(&buf[5]), 0); @@ -691,15 +802,21 @@ void read_message(long msgnum, int printable_view, char *section) { || (!strcasecmp(mime_disposition, "inline")) ) { snprintf(&mime_http[strlen(mime_http)], (sizeof(mime_http) - strlen(mime_http) - 1), - "" "\n" - "%s (%s, %d bytes)
\n", + "%s (%s, %d bytes) [ " + "%s" + " | " + "%s" + " ]
\n", + mime_filename, + mime_content_type, mime_length, msgnum, mime_partnum, mime_filename, msgnum, mime_partnum, - mime_filename, - mime_content_type, mime_length + _("View"), + msgnum, mime_partnum, mime_filename, + _("Download") ); } @@ -849,7 +966,7 @@ void read_message(long msgnum, int printable_view, char *section) { wprintf("\n"); /** Begin body */ - wprintf("
"); /** @@ -877,6 +994,11 @@ void read_message(long msgnum, int printable_view, char *section) { mime_content_type[i] = 0; } } + for (i=0; i