commit 70ce86405fd0e7b24fbf6f7ff5bc19d49e7b2147
parent f9259e9578b3f7cfdf66f119d2df744a39b0da3c
Author: Colin Leroy <colin@colino.net>
Date: Wed, 25 Aug 2010 06:37:16 +0000
2010-08-25 [colin] 3.7.6cvs31
* src/procmime.c
* AUTHORS
* src/gtk/authors.h
* src/common/base64.c
* src/common/base64.h
Fix bug #2245, "base64 decoding fails with line breaks"
Patch by Yotam Medini
Diffstat:
8 files changed, 43 insertions(+), 26 deletions(-)
diff --git a/AUTHORS b/AUTHORS
@@ -279,3 +279,4 @@ contributors (in addition to the above; based on Changelog)
Jacob Head
Fabian Keil
Didier Barvaux
+ Yotam Medini
diff --git a/ChangeLog b/ChangeLog
@@ -1,3 +1,13 @@
+2010-08-25 [colin] 3.7.6cvs31
+
+ * src/procmime.c
+ * AUTHORS
+ * src/gtk/authors.h
+ * src/common/base64.c
+ * src/common/base64.h
+ Fix bug #2245, "base64 decoding fails with line breaks"
+ Patch by Yotam Medini
+
2010-08-25 [colin] 3.7.6cvs30
* src/main.c
diff --git a/PATCHSETS b/PATCHSETS
@@ -4026,3 +4026,4 @@
( cvs diff -u -r 1.115.2.227 -r 1.115.2.228 src/main.c; ) > 3.7.6cvs28.patchset
( cvs diff -u -r 1.149.2.100 -r 1.149.2.101 src/inc.c; cvs diff -u -r 1.17.2.56 -r 1.17.2.57 src/send_message.c; cvs diff -u -r 1.5.2.26 -r 1.5.2.27 src/statusbar.c; cvs diff -u -r 1.43.2.116 -r 1.43.2.117 src/toolbar.c; ) > 3.7.6cvs29.patchset
( cvs diff -u -r 1.115.2.228 -r 1.115.2.229 src/main.c; ) > 3.7.6cvs30.patchset
+( cvs diff -u -r 1.49.2.132 -r 1.49.2.133 src/procmime.c; cvs diff -u -r 1.100.2.74 -r 1.100.2.75 AUTHORS; cvs diff -u -r 1.1.2.67 -r 1.1.2.68 src/gtk/authors.h; cvs diff -u -r 1.1.4.9 -r 1.1.4.10 src/common/base64.c; cvs diff -u -r 1.1.4.7 -r 1.1.4.8 src/common/base64.h; ) > 3.7.6cvs31.patchset
diff --git a/configure.ac b/configure.ac
@@ -12,7 +12,7 @@ MINOR_VERSION=7
MICRO_VERSION=6
INTERFACE_AGE=0
BINARY_AGE=0
-EXTRA_VERSION=30
+EXTRA_VERSION=31
EXTRA_RELEASE=
EXTRA_GTK2_VERSION=
diff --git a/src/common/base64.c b/src/common/base64.c
@@ -128,9 +128,12 @@ void base64_decoder_free(Base64Decoder *decoder)
}
gint base64_decoder_decode(Base64Decoder *decoder,
- const gchar *in, guchar *out)
+ const gchar *in, guchar *out, gint inlen)
{
+ const gchar *in_end = in + inlen;
gint len, total_len = 0;
+ gboolean in_more = inlen > 0;
+ gboolean got_eq = FALSE;
gint buf_len;
gchar buf[4];
@@ -138,32 +141,31 @@ gint base64_decoder_decode(Base64Decoder *decoder,
cm_return_val_if_fail(in != NULL, -1);
cm_return_val_if_fail(out != NULL, -1);
+ /* Start with previous saved tail */
buf_len = decoder->buf_len;
memcpy(buf, decoder->buf, sizeof(buf));
- for (;;) {
- while (buf_len < 4) {
+ while (in_more) {
+ while (buf_len < 4 && in_more) {
gchar c = *in;
in++;
- if (c == '\0') break;
- if (c == '\r' || c == '\n') continue;
- if (c != '=' && BASE64VAL(c) == -1)
- return -1;
- buf[buf_len++] = c;
+ got_eq = (c == '=');
+ if (got_eq || BASE64VAL(c) >= 0)
+ buf[buf_len++] = c;
+ in_more = (in < in_end) && !(got_eq && (buf_len == 4));
}
- if (buf_len < 4 || buf[0] == '=' || buf[1] == '=') {
- decoder->buf_len = buf_len;
- memcpy(decoder->buf, buf, sizeof(buf));
- return total_len;
- }
- len = base64_decode(out, buf, 4);
- out += len;
- total_len += len;
- buf_len = 0;
- if (len < 3) {
- decoder->buf_len = 0;
- return total_len;
+ if (buf_len == 4) {
+ len = base64_decode(out, buf, 4);
+ out += len;
+ total_len += len;
+ buf_len = 0;
}
}
+ if (buf_len < 4) {
+ /* Save tail for next iteration call. It wll be ignored if ends here. */
+ decoder->buf_len = buf_len;
+ memcpy(decoder->buf, buf, buf_len);
+ }
+ return total_len;
}
diff --git a/src/common/base64.h b/src/common/base64.h
@@ -43,6 +43,7 @@ Base64Decoder *base64_decoder_new (void);
void base64_decoder_free (Base64Decoder *decoder);
gint base64_decoder_decode (Base64Decoder *decoder,
const gchar *in,
- guchar *out);
+ guchar *out,
+ gint inlen);
#endif /* __BASE64_H__ */
diff --git a/src/gtk/authors.h b/src/gtk/authors.h
@@ -176,6 +176,7 @@ static char *CONTRIBS_LIST[] = {
"HIRAMATSU Masami",
"Yasuzaki Masayoshi",
"Jason McCarver",
+"Yotam Medini",
"David Mehrmann",
"Christian Mertes",
"Bram Metsch",
diff --git a/src/procmime.c b/src/procmime.c
@@ -345,7 +345,7 @@ gboolean procmime_decode_content(MimeInfo *mimeinfo)
FLUSH_LASTLINE();
} else if (encoding == ENC_BASE64) {
gchar outbuf[BUFFSIZE];
- gint len;
+ gint len, inlen, inread;
Base64Decoder *decoder;
gboolean got_error = FALSE;
gboolean uncanonicalize = FALSE;
@@ -366,14 +366,15 @@ gboolean procmime_decode_content(MimeInfo *mimeinfo)
}
decoder = base64_decoder_new();
- while ((ftell(infp) < readend) && (fgets(buf, sizeof(buf), infp) != NULL)) {
- len = base64_decoder_decode(decoder, buf, outbuf);
+ while ((inlen = MIN(readend - ftell(infp), sizeof(buf))) > 0 && !err) {
+ inread = fread(buf, 1, inlen, infp);
+ len = base64_decoder_decode(decoder, buf, outbuf, inread);
if (uncanonicalize == TRUE && strlen(outbuf) < len && starting) {
uncanonicalize = FALSE;
null_bytes = TRUE;
}
starting = FALSE;
- if (len < 0 && !got_error) {
+ if (((inread != inlen) || len < 0) && !got_error) {
g_warning("Bad BASE64 content.\n");
if (fwrite(_("[Error decoding BASE64]\n"),
sizeof(gchar),