+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
( 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
MICRO_VERSION=1
INTERFACE_AGE=0
BINARY_AGE=0
-EXTRA_VERSION=1
+EXTRA_VERSION=2
EXTRA_RELEASE=
EXTRA_GTK2_VERSION=
#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)
#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);
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"
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)
if (fputs(outbuf, outfp) == EOF)
err = TRUE;
}
+ firstrun = FALSE;
}
} else {
gchar buf[BUFFSIZE];