New patches to improve claws' handling of long lines in attachments.
Mails with attached text files with long lines are rejected by
OpenSMTPd.
Christopher
Index: Makefile
===================================================================
RCS file: /cvs/ports/mail/claws-mail/Makefile,v
retrieving revision 1.51
diff -u -p -r1.51 Makefile
--- Makefile 23 Jan 2012 18:57:33 -0000 1.51
+++ Makefile 3 Apr 2012 13:33:20 -0000
@@ -12,6 +12,8 @@ DISTNAME= claws-mail-${V}
PKGNAME-main= ${DISTNAME}
PKGNAME-bogofilter= claws-mail-bogofilter-${V}
PKGNAME-spamassassin= claws-mail-spamassassin-${V}
+REVISION= 0
+
CATEGORIES= mail news
HOMEPAGE= http://www.claws-mail.org/
Index: patches/patch-autogen_sh
===================================================================
RCS file: patches/patch-autogen_sh
diff -N patches/patch-autogen_sh
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-autogen_sh 3 Apr 2012 13:33:20 -0000
@@ -0,0 +1,12 @@
+$OpenBSD$
+--- autogen.sh.orig Fri Dec 16 09:09:32 2011
++++ autogen.sh Tue Apr 3 13:07:33 2012
+@@ -55,7 +55,7 @@ if [ "$bisonver" = "" ]; then
+ exit 1
+ fi
+
+-flexver=`flex --version|sed "s/.* //"`
++flexver=`($LEX --version || flex --version)|sed "s/.* //"`
+
+ if [ "$flexver" = "" ]; then
+ echo Flex 2.5.31 or greater is needed to compile Claws Mail CVS
Index: patches/patch-src_common_defs_h
===================================================================
RCS file: patches/patch-src_common_defs_h
diff -N patches/patch-src_common_defs_h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_common_defs_h 3 Apr 2012 13:33:20 -0000
@@ -0,0 +1,13 @@
+$OpenBSD$
+--- src/common/defs.h.orig Fri Dec 16 09:09:34 2011
++++ src/common/defs.h Tue Apr 3 13:07:33 2012
+@@ -148,6 +148,9 @@
+
+ #define BUFFSIZE 8192
+
++/* according to RFC 821 1000 characters including CRLF */
++#define MAXSMTPTEXTLEN 1000
++
+ #ifndef MAXPATHLEN
+ # define MAXPATHLEN 4095
+ #endif
Index: patches/patch-src_common_quoted-printable_c
===================================================================
RCS file: patches/patch-src_common_quoted-printable_c
diff -N patches/patch-src_common_quoted-printable_c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_common_quoted-printable_c 3 Apr 2012 13:33:20 -0000
@@ -0,0 +1,133 @@
+$OpenBSD$
+--- src/common/quoted-printable.c.orig Fri Dec 16 09:09:34 2011
++++ src/common/quoted-printable.c Tue Apr 3 13:07:33 2012
+@@ -22,66 +22,78 @@
+
+ #include "utils.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. */
++
+ #define MAX_LINELEN 76
+
+ #define IS_LBREAK(p) \
+- (*(p) == '\0' || *(p) == '\n' || (*(p) == '\r' && *((p) + 1) == '\n'))
++ ((p)[0] == '\n' ? 1 : ((p)[0] == '\r' && (p)[1] == '\n') ? 2 : 0)
+
+-#define SOFT_LBREAK_IF_REQUIRED(n) \
+- if (len + (n) > MAX_LINELEN || \
+- (len + (n) == MAX_LINELEN && (!IS_LBREAK(inp + 1)))) { \
+- *outp++ = '='; \
+- *outp++ = '\n'; \
+- len = 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;
++ /* counters of input/output characters */
++ gint inc = 0;
++ gint outc = 1; /* one character reserved for '=' soft line break */
+
+- 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++;
++ 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;
++ }
+ }
+-
+- if (len > 0)
+- *outp++ = '\n';
+-
+- *outp = '\0';
++ g_assert(outc <= MAX_LINELEN);
++ *out++ = '=';
++ *out = '\0';
++ return inc;
+ }
+
+ gint qp_decode_line(gchar *str)
Index: patches/patch-src_common_quoted-printable_h
===================================================================
RCS file: patches/patch-src_common_quoted-printable_h
diff -N patches/patch-src_common_quoted-printable_h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_common_quoted-printable_h 3 Apr 2012 13:33:20 -0000
@@ -0,0 +1,16 @@
+$OpenBSD$
+--- src/common/quoted-printable.h.orig Fri Dec 16 09:09:34 2011
++++ src/common/quoted-printable.h Tue Apr 3 13:07:33 2012
+@@ -22,8 +22,10 @@
+
+ #include <glib.h>
+
+-void qp_encode_line (gchar *out,
+- const guchar *in);
++gint qp_encode (gboolean text,
++ gchar *out,
++ const guchar *in,
++ gint len);
+ gint qp_decode_line (gchar *str);
+ gint qp_decode_const (gchar *out,
+ gint avail,
Index: patches/patch-src_common_smtp_c
===================================================================
RCS file: /cvs/ports/mail/claws-mail/patches/patch-src_common_smtp_c,v
retrieving revision 1.1
diff -u -p -r1.1 patch-src_common_smtp_c
--- patches/patch-src_common_smtp_c 17 Oct 2008 12:46:33 -0000 1.1
+++ patches/patch-src_common_smtp_c 3 Apr 2012 13:33:20 -0000
@@ -1,6 +1,6 @@
$OpenBSD: patch-src_common_smtp_c,v 1.1 2008/10/17 12:46:33 landry Exp $
---- src/common/smtp.c.orig Sat Oct 4 16:19:23 2008
-+++ src/common/smtp.c Sat Oct 4 16:21:59 2008
+--- src/common/smtp.c.orig Fri Dec 16 09:09:34 2011
++++ src/common/smtp.c Tue Apr 3 13:03:02 2012
@@ -124,7 +124,7 @@ static void smtp_session_destroy(Session *session)
gint smtp_from(SMTPSession *session)
@@ -9,8 +9,8 @@ $OpenBSD: patch-src_common_smtp_c,v 1.1
+ gchar buf[MESSAGEBUFSIZE];
gchar *mail_size = NULL;
- g_return_val_if_fail(session->from != NULL, SM_ERROR);
-@@ -182,7 +182,7 @@ static gint smtp_auth(SMTPSession *session)
+ cm_return_val_if_fail(session->from != NULL, SM_ERROR);
+@@ -188,7 +188,7 @@ static gint smtp_auth(SMTPSession *session)
static gint smtp_auth_recv(SMTPSession *session, const gchar *msg)
{
@@ -19,7 +19,7 @@ $OpenBSD: patch-src_common_smtp_c,v 1.1
switch (session->auth_type) {
case SMTPAUTH_LOGIN:
-@@ -258,7 +258,7 @@ static gint smtp_auth_recv(SMTPSession *session, const
+@@ -264,7 +264,7 @@ static gint smtp_auth_recv(SMTPSession *session, const
static gint smtp_auth_login_user_recv(SMTPSession *session, const gchar *msg)
{
@@ -28,7 +28,7 @@ $OpenBSD: patch-src_common_smtp_c,v 1.1
session->state = SMTP_AUTH_LOGIN_PASS;
-@@ -278,7 +278,7 @@ static gint smtp_auth_login_user_recv(SMTPSession *ses
+@@ -284,7 +284,7 @@ static gint smtp_auth_login_user_recv(SMTPSession *ses
static gint smtp_ehlo(SMTPSession *session)
{
@@ -37,7 +37,7 @@ $OpenBSD: patch-src_common_smtp_c,v 1.1
session->state = SMTP_EHLO;
-@@ -357,7 +357,7 @@ static gint smtp_auth_cram_md5(SMTPSession *session)
+@@ -363,7 +363,7 @@ static gint smtp_auth_cram_md5(SMTPSession *session)
static gint smtp_auth_plain(SMTPSession *session)
{
@@ -46,7 +46,7 @@ $OpenBSD: patch-src_common_smtp_c,v 1.1
/*
* +1 +1 +1
-@@ -422,7 +422,7 @@ static gint smtp_auth_login(SMTPSession *session)
+@@ -428,7 +428,7 @@ static gint smtp_auth_login(SMTPSession *session)
static gint smtp_helo(SMTPSession *session)
{
@@ -55,7 +55,7 @@ $OpenBSD: patch-src_common_smtp_c,v 1.1
session->state = SMTP_HELO;
-@@ -437,7 +437,7 @@ static gint smtp_helo(SMTPSession *session)
+@@ -443,7 +443,7 @@ static gint smtp_helo(SMTPSession *session)
static gint smtp_rcpt(SMTPSession *session)
{
@@ -63,4 +63,4 @@ $OpenBSD: patch-src_common_smtp_c,v 1.1
+ gchar buf[MESSAGEBUFSIZE];
gchar *to;
- g_return_val_if_fail(session->cur_to != NULL, SM_ERROR);
+ cm_return_val_if_fail(session->cur_to != NULL, SM_ERROR);
Index: patches/patch-src_inc_c
===================================================================
RCS file: /cvs/ports/mail/claws-mail/patches/patch-src_inc_c,v
retrieving revision 1.6
diff -u -p -r1.6 patch-src_inc_c
--- patches/patch-src_inc_c 17 Oct 2008 12:46:33 -0000 1.6
+++ patches/patch-src_inc_c 3 Apr 2012 13:33:20 -0000
@@ -1,6 +1,6 @@
$OpenBSD: patch-src_inc_c,v 1.6 2008/10/17 12:46:33 landry Exp $
---- src/inc.c.orig Thu Sep 18 05:44:28 2008
-+++ src/inc.c Sat Oct 4 16:02:19 2008
+--- src/inc.c.orig Fri Dec 16 09:09:32 2011
++++ src/inc.c Tue Apr 3 13:03:02 2012
@@ -85,7 +85,7 @@ static GdkPixbuf *currentpix;
static GdkPixbuf *errorpix;
static GdkPixbuf *okpix;
@@ -10,7 +10,7 @@ $OpenBSD: patch-src_inc_c,v 1.6 2008/10/
static void inc_finished (MainWindow *mainwin,
gboolean new_messages,
-@@ -946,7 +946,7 @@ static void inc_progress_dialog_set_label(IncProgressD
+@@ -949,7 +949,7 @@ static void inc_progress_dialog_set_label(IncProgressD
static void inc_progress_dialog_set_progress(IncProgressDialog *inc_dialog,
IncSession *inc_session)
{
Index: patches/patch-src_messageview_c
===================================================================
RCS file: patches/patch-src_messageview_c
diff -N patches/patch-src_messageview_c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_messageview_c 3 Apr 2012 13:33:20 -0000
@@ -0,0 +1,15 @@
+$OpenBSD$
+--- src/messageview.c.orig Fri Dec 16 09:09:32 2011
++++ src/messageview.c Tue Apr 3 13:07:33 2012
+@@ -977,8 +977,9 @@ static gint disposition_notification_send(MsgInfo *msg
+ 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: patches/patch-src_procmime_c
===================================================================
RCS file: /cvs/ports/mail/claws-mail/patches/patch-src_procmime_c,v
retrieving revision 1.6
diff -u -p -r1.6 patch-src_procmime_c
--- patches/patch-src_procmime_c 17 Oct 2008 12:46:33 -0000 1.6
+++ patches/patch-src_procmime_c 3 Apr 2012 13:33:20 -0000
@@ -1,7 +1,87 @@
$OpenBSD: patch-src_procmime_c,v 1.6 2008/10/17 12:46:33 landry Exp $
---- src/procmime.c.orig Wed Oct 1 03:10:29 2008
-+++ src/procmime.c Sat Oct 4 16:02:19 2008
-@@ -1085,7 +1085,7 @@ GList *procmime_get_mime_type_list(void)
+--- src/procmime.c.orig Fri Dec 16 09:09:32 2011
++++ src/procmime.c Tue Apr 3 14:59:40 2012
+@@ -562,16 +562,29 @@ gboolean procmime_encode_content(MimeInfo *mimeinfo, E
+ 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 (fgets(inbuf, sizeof(inbuf), infp) != NULL) {
+- qp_encode_line(outbuf, inbuf);
++ while ((len += fread(inbuf + len, 1,
++ sizeof(inbuf) - len - 1,
++ infp)) > 0)
++ {
++ if (firstrun == FALSE)
++ if (fputs("\r\n", outfp) == EOF)
++ err = TRUE;
+
++ 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,14 +593,40 @@ gboolean procmime_encode_content(MimeInfo *mimeinfo, E
+ if (fputs(outbuf, outfp) == EOF)
+ err = TRUE;
+ }
++ firstrun = FALSE;
+ }
+ } else {
+- gchar buf[BUFFSIZE];
++ gchar buf[MAXSMTPTEXTLEN+1];
++ gint leftover = 0;
+
+- while (fgets(buf, sizeof(buf), infp) != NULL) {
+- strcrchomp(buf);
+- if (fputs(buf, outfp) == EOF)
++ while (fgets(buf + leftover,
++ sizeof(buf) - leftover,
++ infp) != NULL)
++ {
++ gchar *l, *c = buf;
++ leftover = 0;
++
++ while (*c != '\0') {
++ if (
++ *c == '\n'
++ || (*c == '\r' && *(c+1) == '\n'))
++ {
++ *c = '\0';
++ break;
++ }
++ c++;
++ }
++ while (c - buf > MAXSMTPTEXTLEN - 2) {
++ *c = *(c-1);
++ *--c = '\0';
++ leftover++;
++ }
++
++ if (fputs(buf, outfp) == EOF || putc('\n', outfp) ==
EOF)
+ err = TRUE;
++
++ for (l = buf; l-buf < leftover; l++)
++ *l = *++c;
+ }
+ }
+
+@@ -1094,7 +1133,7 @@ GList *procmime_get_mime_type_list(void)
#endif
{
fp_is_glob_file = FALSE;
@@ -10,3 +90,74 @@ $OpenBSD: patch-src_procmime_c,v 1.6 200
if ((fp = g_fopen(SYSCONFDIR "/mime.types", "rb"))
== NULL) {
FILE_OP_ERROR(SYSCONFDIR "/mime.types",
+@@ -1174,11 +1213,12 @@ EncodingType procmime_get_encoding_for_text_file(const
+ {
+ FILE *fp;
+ guchar buf[BUFFSIZE];
++ gboolean cr = FALSE;
+ size_t len;
++ gint linelen = 0, maxlinelen = 0;
+ size_t octet_chars = 0;
+ size_t total_len = 0;
+ gfloat octet_percentage;
+- gboolean force_b64 = FALSE;
+
+ if ((fp = g_fopen(file, "rb")) == NULL) {
+ FILE_OP_ERROR(file, "fopen");
+@@ -1190,11 +1230,27 @@ EncodingType procmime_get_encoding_for_text_file(const
+ gint i;
+
+ for (p = buf, i = 0; i < len; ++p, ++i) {
+- if (*p & 0x80)
+- ++octet_chars;
+- if (*p == '\0') {
+- force_b64 = TRUE;
++ switch (*p) {
++ case '\n':
++ if (cr) linelen--;
++ maxlinelen = MAX(linelen, maxlinelen);
++ linelen = 0;
++ cr = FALSE;
++ break;
++ case '\r':
++ cr = TRUE;
++ linelen++;
++ break;
++ case '\0':
+ *has_binary = TRUE;
++ maxlinelen = G_MAXINT;
++ cr = FALSE;
++ break;
++ default:
++ if (*p & 0x80)
++ octet_chars++;
++ linelen++;
++ cr = FALSE;
+ }
+ }
+ total_len += len;
+@@ -1208,15 +1264,20 @@ EncodingType procmime_get_encoding_for_text_file(const
+ octet_percentage = 0.0;
+
+ debug_print("procmime_get_encoding_for_text_file(): "
+- "8bit chars: %zd / %zd (%f%%)\n", octet_chars, total_len,
+- 100.0 * octet_percentage);
++ "8bit chars: %zd / %zd (%f%%). "
++ "maximum line length: %d chars\n",
++ octet_chars, total_len, 100.0 * octet_percentage,
++ maxlinelen);
+
+- if (octet_percentage > 0.20 || force_b64) {
++ if (octet_percentage > 0.20) {
+ debug_print("using BASE64\n");
+ return ENC_BASE64;
+- } else if (octet_chars > 0) {
++ } else if (maxlinelen > MAXSMTPTEXTLEN-2) {
+ debug_print("using quoted-printable\n");
+ return ENC_QUOTED_PRINTABLE;
++ } else if (octet_chars > 0) {
++ debug_print("using 8bit\n");
++ return ENC_8BIT;
+ } else {
+ debug_print("using 7bit\n");
+ return ENC_7BIT;