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;


Reply via email to