2012-07-03 [mir] 3.8.1cvs2
authorMichael Rasmussen <mir@datanom.net>
Tue, 3 Jul 2012 17:23:00 +0000 (17:23 +0000)
committerMichael Rasmussen <mir@datanom.net>
Tue, 3 Jul 2012 17:23:00 +0000 (17:23 +0000)
* 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

ChangeLog
PATCHSETS
configure.ac
src/common/quoted-printable.c
src/common/quoted-printable.h
src/messageview.c
src/procmime.c

index ff3bcdd..42da45c 100644 (file)
--- 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
index 0c87250..0930569 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( 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
index 8dc1b9e..096af30 100644 (file)
@@ -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=
 
index dd0a6bb..dcc637d 100644 (file)
 
 #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)
index 92f53b6..3cdc2c1 100644 (file)
 
 #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);
index bfd8d1b..6a3e0ee 100644 (file)
@@ -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"
index 252ec29..5bd3363 100644 (file)
@@ -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];