From 25cccc9f7cfe02266538d289301606f5a97b9a2b Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Sun, 11 Nov 2007 04:46:40 +0000 Subject: [PATCH] * moved CtdlDecodeQuotedPrintable() into tools.c (later we will move most or all of tools.c into libcitadel) * amended citadel_ipc.c message reading loop. When using MSG4 (nearly always), parse base64 and quoted-printable encodings, and decode them. MSG4 does not *yet* send these, instead performing the decoding on the server side. During experimentation I told the server not to decode, and this will resolve Bug #289. All that's left to do is to add something to the protocol so that the client can tell the server that it wants non-decoded message text. I'll do that tomorrow. --- citadel/citadel_ipc.c | 24 ++++++++++++++++++++++++ citadel/mime_parser.c | 37 ------------------------------------- citadel/tools.c | 37 +++++++++++++++++++++++++++++++++++++ citadel/tools.h | 1 + webcit/mime_parser.c | 37 ------------------------------------- webcit/tools.c | 37 +++++++++++++++++++++++++++++++++++++ webcit/webcit.h | 1 + 7 files changed, 100 insertions(+), 74 deletions(-) diff --git a/citadel/citadel_ipc.c b/citadel/citadel_ipc.c index d40b837d6..0a16b3107 100644 --- a/citadel/citadel_ipc.c +++ b/citadel/citadel_ipc.c @@ -477,6 +477,7 @@ int CtdlIPCGetSingleMessage(CtdlIPC *ipc, long msgnum, int headers, int as_mime, size_t bbb_len; int multipart_hunting = 0; char multipart_prefix[128]; + char encoding[256]; if (!cret) return -1; if (!mret) return -1; @@ -484,6 +485,7 @@ int CtdlIPCGetSingleMessage(CtdlIPC *ipc, long msgnum, int headers, int as_mime, if (!*mret) return -1; if (!msgnum) return -1; + strcpy(encoding, ""); strcpy(mret[0]->content_type, ""); sprintf(aaa, "MSG%d %ld|%d", as_mime, msgnum, headers); ret = CtdlIPCGenericCommand(ipc, aaa, NULL, 0, &bbb, &bbb_len, cret); @@ -596,6 +598,11 @@ int CtdlIPCGetSingleMessage(CtdlIPC *ipc, long msgnum, int headers, int as_mime, strcpy(mret[0]->mime_chosen, &mret[0]->mime_chosen[23]); striplt(mret[0]->mime_chosen); } + if (!strncasecmp(bbb, "Content-transfer-encoding:", 26)) { + extract_token(encoding, bbb, 0, '\n', sizeof encoding); + strcpy(encoding, &encoding[26]); + striplt(encoding); + } remove_token(bbb, 0, '\n'); } while ((bbb[0] != 0) && (bbb[0] != '\n')); remove_token(bbb, 0, '\n'); @@ -604,8 +611,25 @@ int CtdlIPCGetSingleMessage(CtdlIPC *ipc, long msgnum, int headers, int as_mime, } if (strlen(bbb)) { + + if ( (!strcasecmp(encoding, "base64")) || (!strcasecmp(encoding, "quoted-printable")) ) { + char *ccc = NULL; + int bytes_decoded = 0; + ccc = malloc(strlen(bbb) + 32768); + if (!strcasecmp(encoding, "base64")) { + bytes_decoded = CtdlDecodeBase64(ccc, bbb, strlen(bbb)); + } + else if (!strcasecmp(encoding, "quoted-printable")) { + bytes_decoded = CtdlDecodeQuotedPrintable(ccc, bbb, strlen(bbb)); + } + ccc[bytes_decoded] = 0; + free(bbb); + bbb = ccc; + } + /* FIXME: Strip trailing whitespace */ bbb = (char *)realloc(bbb, (size_t)(strlen(bbb) + 1)); + } else { bbb = (char *)realloc(bbb, 1); *bbb = '\0'; diff --git a/citadel/mime_parser.c b/citadel/mime_parser.c index 9569d68eb..a1a4965e9 100644 --- a/citadel/mime_parser.c +++ b/citadel/mime_parser.c @@ -74,43 +74,6 @@ char *fixed_partnum(char *supplied_partnum) { -/* - * Convert "quoted-printable" to binary. Returns number of bytes decoded. - * according to RFC2045 section 6.7 - */ -int CtdlDecodeQuotedPrintable(char *decoded, char *encoded, int sourcelen) { - unsigned int ch; - int decoded_length = 0; - int pos = 0; - - while (pos < sourcelen) - { - if (!strncmp(&encoded[pos], "=\r\n", 3)) - { - pos += 3; - } - else if (!strncmp(&encoded[pos], "=\n", 2)) - { - pos += 2; - } - else if (encoded[pos] == '=') - { - ch = 0; - sscanf(&encoded[pos+1], "%02x", &ch); - pos += 3; - decoded[decoded_length++] = ch; - } - else - { - decoded[decoded_length++] = encoded[pos]; - pos += 1; - } - } - decoded[decoded_length] = 0; - return(decoded_length); -} - - /* * Given a message or message-part body and a length, handle any necessary * decoding and pass the request up the stack. diff --git a/citadel/tools.c b/citadel/tools.c index 725b9daed..b86464259 100644 --- a/citadel/tools.c +++ b/citadel/tools.c @@ -416,6 +416,43 @@ int CtdlDecodeBase64(char *dest, const char *source, size_t length) } } +/* + * Convert "quoted-printable" to binary. Returns number of bytes decoded. + * according to RFC2045 section 6.7 + */ +int CtdlDecodeQuotedPrintable(char *decoded, char *encoded, int sourcelen) { + unsigned int ch; + int decoded_length = 0; + int pos = 0; + + while (pos < sourcelen) + { + if (!strncmp(&encoded[pos], "=\r\n", 3)) + { + pos += 3; + } + else if (!strncmp(&encoded[pos], "=\n", 2)) + { + pos += 2; + } + else if (encoded[pos] == '=') + { + ch = 0; + sscanf(&encoded[pos+1], "%02x", &ch); + pos += 3; + decoded[decoded_length++] = ch; + } + else + { + decoded[decoded_length++] = encoded[pos]; + pos += 1; + } + } + decoded[decoded_length] = 0; + return(decoded_length); +} + + /* * if we send out non ascii subjects, we encode it this way. */ diff --git a/citadel/tools.h b/citadel/tools.h index 4f205d6fa..7c9f5c017 100644 --- a/citadel/tools.h +++ b/citadel/tools.h @@ -9,6 +9,7 @@ unsigned long extract_unsigned_long(const char *source, int parmnum); void CtdlInitBase64Table(void); void CtdlEncodeBase64(char *dest, const char *source, size_t sourcelen); int CtdlDecodeBase64(char *dest, const char *source, size_t length); +int CtdlDecodeQuotedPrintable(char *decoded, char *encoded, int sourcelen); void striplt(char *); int haschar(const char *st, int ch); void remove_token(char *source, int parmnum, char separator); diff --git a/webcit/mime_parser.c b/webcit/mime_parser.c index d6a849ebd..c41fb26ad 100644 --- a/webcit/mime_parser.c +++ b/webcit/mime_parser.c @@ -61,43 +61,6 @@ char *fixed_partnum(char *supplied_partnum) { -/* - * Convert "quoted-printable" to binary. Returns number of bytes decoded. - * according to RFC2045 section 6.7 - */ -int CtdlDecodeQuotedPrintable(char *decoded, char *encoded, int sourcelen) { - unsigned int ch; - int decoded_length = 0; - int pos = 0; - - while (pos < sourcelen) - { - if (!strncmp(&encoded[pos], "=\r\n", 3)) - { - pos += 3; - } - else if (!strncmp(&encoded[pos], "=\n", 2)) - { - pos += 2; - } - else if (encoded[pos] == '=') - { - ch = 0; - sscanf(&encoded[pos+1], "%02x", &ch); - pos += 3; - decoded[decoded_length++] = ch; - } - else - { - decoded[decoded_length++] = encoded[pos]; - pos += 1; - } - } - decoded[decoded_length] = 0; - return(decoded_length); -} - - /* * Given a message or message-part body and a length, handle any necessary * decoding and pass the request up the stack. diff --git a/webcit/tools.c b/webcit/tools.c index c7a4c099a..591af0d97 100644 --- a/webcit/tools.c +++ b/webcit/tools.c @@ -632,6 +632,43 @@ void generate_uuid(char *buf) { } +/* + * Convert "quoted-printable" to binary. Returns number of bytes decoded. + * according to RFC2045 section 6.7 + */ +int CtdlDecodeQuotedPrintable(char *decoded, char *encoded, int sourcelen) { + unsigned int ch; + int decoded_length = 0; + int pos = 0; + + while (pos < sourcelen) + { + if (!strncmp(&encoded[pos], "=\r\n", 3)) + { + pos += 3; + } + else if (!strncmp(&encoded[pos], "=\n", 2)) + { + pos += 2; + } + else if (encoded[pos] == '=') + { + ch = 0; + sscanf(&encoded[pos+1], "%02x", &ch); + pos += 3; + decoded[decoded_length++] = ch; + } + else + { + decoded[decoded_length++] = encoded[pos]; + pos += 1; + } + } + decoded[decoded_length] = 0; + return(decoded_length); +} + + /** * \brief Local replacement for controversial C library function that generates * names for temporary files. Included to shut up compiler warnings. diff --git a/webcit/webcit.h b/webcit/webcit.h index b10ed8ddc..49fed8dc7 100644 --- a/webcit/webcit.h +++ b/webcit/webcit.h @@ -634,6 +634,7 @@ void calendar_summary_view(void); int load_msg_ptrs(char *servcmd, int with_headers); size_t CtdlEncodeBase64(char **dest, const char *source, size_t sourcelen, size_t *destlen, int linebreaks); int CtdlDecodeBase64(char *dest, const char *source, size_t length); +int CtdlDecodeQuotedPrintable(char *decoded, char *encoded, int sourcelen); void free_attachments(struct wcsession *sess); void free_march_list(struct wcsession *wcf); void set_room_policy(void); -- 2.39.2