talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

commit 957eeb15f88683c769f68053083166e7008332f3
parent dd6369e9b929389cb17a02893e1b04a4e1a98815
Author: Michael Rasmussen <mir@datanom.net>
Date:   Tue,  3 Jul 2012 17:23:00 +0000

2012-07-03 [mir]	3.8.1cvs2

	* src/messageview.c
	* src/procmime.c
	* src/common/quoted-printable.c
	* src/common/quoted-printable.h
	    Patch fixes bug 2640.
	    Patch provided by madroach claws at gmerlin dot de

Diffstat:
MChangeLog | 9+++++++++
MPATCHSETS | 1+
Mconfigure.ac | 2+-
Msrc/common/quoted-printable.c | 115+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Msrc/common/quoted-printable.h | 12++++++++++++
Msrc/messageview.c | 5+++--
Msrc/procmime.c | 24+++++++++++++++++++-----
7 files changed, 110 insertions(+), 58 deletions(-)

diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,12 @@ +2012-07-03 [mir] 3.8.1cvs2 + + * src/messageview.c + * src/procmime.c + * src/common/quoted-printable.c + * src/common/quoted-printable.h + Patch fixes bug 2640. + Patch provided by madroach claws at gmerlin dot de + 2012-06-30 [paul] 3.8.1cvs1 * Makefile.am diff --git a/PATCHSETS b/PATCHSETS @@ -4376,3 +4376,4 @@ ( cvs diff -u -r 1.654.2.4451 -r 1.654.2.4452 configure.ac; cvs diff -u -r 1.9.2.24 -r 1.9.2.25 po/cs.po; cvs diff -u -r 1.58.2.49 -r 1.58.2.50 po/de.po; cvs diff -u -r 1.60.2.64 -r 1.60.2.65 po/es.po; cvs diff -u -r 1.42.2.57 -r 1.42.2.58 po/fr.po; cvs diff -u -r 1.5.2.21 -r 1.5.2.22 po/hu.po; cvs diff -u -r 1.1.2.1 -r 1.1.2.2 po/id_ID.po; cvs diff -u -r 1.1.2.4 -r 1.1.2.5 po/lt.po; cvs diff -u -r 1.50.2.43 -r 1.50.2.44 po/pt_BR.po; cvs diff -u -r 1.2.2.35 -r 1.2.2.36 po/sk.po; cvs diff -u -r 1.4.2.11 -r 1.4.2.12 po/sv.po; cvs diff -u -r 1.5.2.30 -r 1.5.2.31 po/zh_CN.po; cvs diff -u -r 1.1.2.3 -r 1.1.2.4 po/zh_TW.po; cvs diff -u -r 1.1.2.78 -r 1.1.2.79 src/gtk/authors.h; cvs diff -u -r 1.1.2.26 -r 1.1.2.27 tools/claws.i18n.status.pl; ) > 3.8.0cvs57.patchset ( cvs diff -u -r 1.654.2.4452 -r 1.654.2.4453 configure.ac; ) > 3.8.0cvs58.patchset ( cvs diff -u -r 1.24.2.29 -r 1.24.2.30 Makefile.am; ) > 3.8.1cvs1.patchset +( cvs diff -u -r 1.94.2.233 -r 1.94.2.234 src/messageview.c; cvs diff -u -r 1.49.2.142 -r 1.49.2.143 src/procmime.c; cvs diff -u -r 1.3.2.17 -r 1.3.2.18 src/common/quoted-printable.c; cvs diff -u -r 1.3.2.9 -r 1.3.2.10 src/common/quoted-printable.h; ) > 3.8.1cvs2.patchset diff --git a/configure.ac b/configure.ac @@ -12,7 +12,7 @@ MINOR_VERSION=8 MICRO_VERSION=1 INTERFACE_AGE=0 BINARY_AGE=0 -EXTRA_VERSION=1 +EXTRA_VERSION=2 EXTRA_RELEASE= EXTRA_GTK2_VERSION= diff --git a/src/common/quoted-printable.c b/src/common/quoted-printable.c @@ -22,66 +22,81 @@ #include "utils.h" + #define MAX_LINELEN 76 #define IS_LBREAK(p) \ - (*(p) == '\0' || *(p) == '\n' || (*(p) == '\r' && *((p) + 1) == '\n')) - -#define SOFT_LBREAK_IF_REQUIRED(n) \ - if (len + (n) > MAX_LINELEN || \ - (len + (n) == MAX_LINELEN && (!IS_LBREAK(inp + 1)))) { \ - *outp++ = '='; \ - *outp++ = '\n'; \ - len = 0; \ - } + ((p)[0] == '\n' ? 1 : ((p)[0] == '\r' && (p)[1] == '\n') ? 2 : 0) -void qp_encode_line(gchar *out, const guchar *in) +gint qp_encode(gboolean text, gchar *out, const guchar *in, gint len) { - const guchar *inp = in; - gchar *outp = out; - guchar ch; - gint len = 0; - - while (*inp != '\0') { - ch = *inp; - - if (IS_LBREAK(inp)) { - *outp++ = '\n'; - len = 0; - if (*inp == '\r') - inp++; - inp++; - } else if (ch == '\t' || ch == ' ') { - if (IS_LBREAK(inp + 1)) { - SOFT_LBREAK_IF_REQUIRED(3); - *outp++ = '='; - get_hex_str(outp, ch); - outp += 2; - len += 3; - inp++; - } else { - SOFT_LBREAK_IF_REQUIRED(1); - *outp++ = *inp++; - len++; + /* counters of input/output characters */ + gint inc = 0; + gint outc = 1; /* one character reserved for '=' soft line break */ + + while(inc < len) { + /* allow literal linebreaks in text */ + if(text) { + if(IS_LBREAK(in)) { + /* inserting linebreaks is the job of our caller */ + g_assert(outc <= MAX_LINELEN); + *out = '\0'; + return inc + IS_LBREAK(in); } - } else if ((ch >= 33 && ch <= 60) || (ch >= 62 && ch <= 126)) { - SOFT_LBREAK_IF_REQUIRED(1); - *outp++ = *inp++; - len++; - } else { - SOFT_LBREAK_IF_REQUIRED(3); - *outp++ = '='; - get_hex_str(outp, ch); - outp += 2; - len += 3; - inp++; + if(IS_LBREAK(in+1)) { + /* free the reserved character since no softbreak + * will be needed after the current character */ + outc--; + /* guard against whitespace before a literal linebreak */ + if(*in == ' ' || *in == '\t') { + goto escape; + } + } + } + if(*in == '=') { + goto escape; + } + /* Cave: Whitespace is unconditionally output literally, + * but according to the RFC it must not be output before a + * linebreak. + * This requirement is obeyed by quoting all linebreaks + * and therefore ending all lines with '='. */ + else if((*in >= ' ' && *in <= '~') || *in == '\t') { + if(outc + 1 <= MAX_LINELEN) { + *out++ = *in++; + outc++; + inc++; + } + else break; + } + else { +escape: + if(outc + 3 <= MAX_LINELEN) { + *out++ = '='; + outc++; + get_hex_str(out, *in); + out += 2; + outc += 2; + in++; + inc++; + } + else break; } } + g_assert(outc <= MAX_LINELEN); + *out++ = '='; + *out = '\0'; + return inc; +} - if (len > 0) - *outp++ = '\n'; +void qp_encode_line(gchar *out, const guchar *in) { + while (*in != '\0') { + in += qp_encode(TRUE, out, in, strlen(in)); - *outp = '\0'; + while(*out != '\0') out++; + *out++ = '\n'; + *out++ = '\0'; + } } gint qp_decode_line(gchar *str) diff --git a/src/common/quoted-printable.h b/src/common/quoted-printable.h @@ -22,6 +22,18 @@ #include <glib.h> +/* Processes at most 78 characters from in buffer, + * and stores one NULL-terminated line of at most 76 characters (excl. \0) of + * quoted-printable output without terminating newline characters in out buffer. + * Except when encoding text, every output line ends in a soft line break. + * Therefore the caller can chain multiple lines of encoded data resulting from + * sequential runs by glueing them together with line breaks. + * The number of processed input characters is returned. */ +gint qp_encode (gboolean text, + gchar *out, + const guchar *in, + gint len); +/* Deprecated */ void qp_encode_line (gchar *out, const guchar *in); gint qp_decode_line (gchar *str); diff --git a/src/messageview.c b/src/messageview.c @@ -988,8 +988,9 @@ static gint disposition_notification_send(MsgInfo *msginfo) extract_address(orig_to); } if (msginfo->subject && *(msginfo->subject)) { - enc_sub = g_malloc0(strlen(msginfo->subject)*8); - qp_encode_line(enc_sub, (const guchar *)msginfo->subject); + gint len = strlen(msginfo->subject); + enc_sub = g_malloc0(len*8); + qp_encode(TRUE, enc_sub, (const guchar *)msginfo->subject, len); g_strstrip(enc_sub); } ok = fprintf(fp,"MIME-Version: 1.0\n" diff --git a/src/procmime.c b/src/procmime.c @@ -562,16 +562,29 @@ gboolean procmime_encode_content(MimeInfo *mimeinfo, EncodingType encoding) g_free(tmp_file); } } else if (encoding == ENC_QUOTED_PRINTABLE) { - gchar inbuf[BUFFSIZE], outbuf[BUFFSIZE * 4]; + gchar inbuf[79], outbuf[77]; + gint n, len = 0; + gboolean firstrun = TRUE; + + while ((len += fread(inbuf + len, 1, + sizeof(inbuf) - len - 1, + infp)) > 0) + { + if (firstrun == FALSE) + if (fputs("\r\n", outfp) == EOF) + err = TRUE; - while (fgets(inbuf, sizeof(inbuf), infp) != NULL) { - qp_encode_line(outbuf, inbuf); + inbuf[len] = '\0'; + n = qp_encode(mimeinfo->type == MIMETYPE_TEXT, + outbuf, inbuf, len); + len -= n; + memmove(inbuf, inbuf + n, len); if (!strncmp("From ", outbuf, sizeof("From ")-1)) { gchar *tmpbuf = outbuf; - + tmpbuf += sizeof("From ")-1; - + if (fputs("=46rom ", outfp) == EOF) err = TRUE; if (fputs(tmpbuf, outfp) == EOF) @@ -580,6 +593,7 @@ gboolean procmime_encode_content(MimeInfo *mimeinfo, EncodingType encoding) if (fputs(outbuf, outfp) == EOF) err = TRUE; } + firstrun = FALSE; } } else { gchar buf[BUFFSIZE];