2007-01-16 [paul] 2.7.1cvs6
[claws.git] / src / procmime.c
index 3e64f262826ab66637079255898096191d8c3f8c..0ab8d1d91c733ed300992f310b5a0757cb0addca 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2006 Hiroyuki Yamamoto & The Sylpheed-Claws Team
+ * Copyright (C) 1999-2007 Hiroyuki Yamamoto & The Claws Mail Team
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -227,6 +227,24 @@ const gchar *procmime_mimeinfo_get_parameter(MimeInfo *mimeinfo, const gchar *na
        return value;
 }
 
+#define FLUSH_LASTLINE() {                                                     \
+       if (*lastline != '\0') {                                                \
+               gint llen = 0;                                                  \
+               strretchomp(lastline);                                          \
+               llen = strlen(lastline);                                        \
+               if (lastline[llen-1] == ' ' && strcmp(lastline,"-- ")) {        \
+                       /* this is flowed */                                    \
+                       if (delsp)                                              \
+                               lastline[llen-1] = '\0';                        \
+                       fputs(lastline, outfp);                                 \
+               } else {                                                        \
+                       fputs(lastline, outfp);                                 \
+                       fputs("\n", outfp);                                     \
+               }                                                               \
+       }                                                                       \
+       strcpy(lastline, buf);                                                  \
+}
+
 gboolean procmime_decode_content(MimeInfo *mimeinfo)
 {
        gchar buf[BUFFSIZE];
@@ -235,17 +253,34 @@ gboolean procmime_decode_content(MimeInfo *mimeinfo)
        FILE *outfp, *infp;
        struct stat statbuf;
        gboolean tmp_file = FALSE;
-
+       gboolean flowed = FALSE;
+       gboolean delsp = FALSE; 
        EncodingType encoding = forced_encoding 
                                ? forced_encoding
                                : mimeinfo->encoding_type;
+       gchar lastline[BUFFSIZE];
+       memset(lastline, 0, BUFFSIZE);
                   
        g_return_val_if_fail(mimeinfo != NULL, FALSE);
 
-       if (encoding == ENC_UNKNOWN ||
-           encoding == ENC_BINARY ||
-           encoding == ENC_7BIT ||
-           encoding == ENC_8BIT)
+       if (prefs_common.respect_flowed_format &&
+           mimeinfo->type == MIMETYPE_TEXT && 
+           !strcasecmp(mimeinfo->subtype, "plain")) {
+               if (procmime_mimeinfo_get_parameter(mimeinfo, "format") != NULL &&
+                   !strcasecmp(procmime_mimeinfo_get_parameter(mimeinfo, "format"),"flowed"))
+                       flowed = TRUE;
+               if (flowed &&
+                   procmime_mimeinfo_get_parameter(mimeinfo, "delsp") != NULL &&
+                   !strcasecmp(procmime_mimeinfo_get_parameter(mimeinfo, "delsp"),"yes"))
+                       delsp = TRUE;
+       }
+       
+       if (!flowed && (
+            encoding == ENC_UNKNOWN ||
+            encoding == ENC_BINARY ||
+            encoding == ENC_7BIT ||
+            encoding == ENC_8BIT
+           ))
                return TRUE;
 
        infp = g_fopen(mimeinfo->data.filename, "rb");
@@ -268,8 +303,15 @@ gboolean procmime_decode_content(MimeInfo *mimeinfo)
                while ((ftell(infp) < readend) && (fgets(buf, sizeof(buf), infp) != NULL)) {
                        gint len;
                        len = qp_decode_line(buf);
-                       fwrite(buf, 1, len, outfp);
+                       buf[len]='\0';
+                       if (!flowed) {
+                               fwrite(buf, 1, len, outfp);
+                       } else {
+                               FLUSH_LASTLINE();
+                       }
                }
+               if (flowed)
+                       FLUSH_LASTLINE();
        } else if (encoding == ENC_BASE64) {
                gchar outbuf[BUFFSIZE];
                gint len;
@@ -339,8 +381,14 @@ gboolean procmime_decode_content(MimeInfo *mimeinfo)
                }
        } else {
                while ((ftell(infp) < readend) && (fgets(buf, sizeof(buf), infp) != NULL)) {
-                       fputs(buf, outfp);
+                       if (!flowed) {
+                               fputs(buf, outfp);
+                       } else {
+                               FLUSH_LASTLINE();
+                       }
                }
+               if (flowed)
+                       FLUSH_LASTLINE();
        }
 
        fclose(outfp);
@@ -499,40 +547,49 @@ gint procmime_get_part(const gchar *outfile, MimeInfo *mimeinfo)
        FILE *infp, *outfp;
        gchar buf[BUFFSIZE];
        gint restlength, readlength;
+       gint saved_errno = 0;
 
        g_return_val_if_fail(outfile != NULL, -1);
        g_return_val_if_fail(mimeinfo != NULL, -1);
 
        if (mimeinfo->encoding_type != ENC_BINARY && !procmime_decode_content(mimeinfo))
-               return -1;
+               return -EINVAL;
 
        if ((infp = g_fopen(mimeinfo->data.filename, "rb")) == NULL) {
+               saved_errno = errno;
                FILE_OP_ERROR(mimeinfo->data.filename, "fopen");
-               return -1;
+               return -(saved_errno);
        }
        if (fseek(infp, mimeinfo->offset, SEEK_SET) < 0) {
+               saved_errno = errno;
                FILE_OP_ERROR(mimeinfo->data.filename, "fseek");
                fclose(infp);
-               return -1;
+               return -(saved_errno);
        }
        if ((outfp = g_fopen(outfile, "wb")) == NULL) {
+               saved_errno = errno;
                FILE_OP_ERROR(outfile, "fopen");
                fclose(infp);
-               return -1;
+               return -(saved_errno);
        }
 
        restlength = mimeinfo->length;
 
        while ((restlength > 0) && ((readlength = fread(buf, 1, restlength > BUFFSIZE ? BUFFSIZE : restlength, infp)) > 0)) {
-               fwrite(buf, 1, readlength, outfp);
+               if (fwrite(buf, 1, readlength, outfp) != readlength) {
+                       saved_errno = errno;
+                       fclose(outfp);
+                       return -(saved_errno);
+               }
                restlength -= readlength;
        }
 
        fclose(infp);
        if (fclose(outfp) == EOF) {
+               saved_errno = errno;
                FILE_OP_ERROR(outfile, "fclose");
                g_unlink(outfile);
-               return -1;
+               return -(saved_errno);
        }
 
        return 0;
@@ -1137,7 +1194,9 @@ EncodingType procmime_get_encoding_for_charset(const gchar *charset)
                return ENC_8BIT;
        else if (!g_ascii_strncasecmp(charset, "ISO-8859-", 9))
                return ENC_QUOTED_PRINTABLE;
-       else
+       else if (!g_ascii_strncasecmp(charset, "UTF-8", 5))
+               return ENC_QUOTED_PRINTABLE;
+       else 
                return ENC_8BIT;
 }
 
@@ -1849,8 +1908,10 @@ MimeInfo *procmime_scan_queue_file(const gchar *filename)
        /* Skip queue header */
        while (fgets(buf, sizeof(buf), fp) != NULL) {
                /* new way */
-               if (!strncmp(buf, "X-Sylpheed-End-Special-Headers: 1",
-                       strlen("X-Sylpheed-End-Special-Headers:")))
+               if ((!strncmp(buf, "X-Claws-End-Special-Headers: 1",
+                       strlen("X-Claws-End-Special-Headers:"))) ||
+                  (!strncmp(buf, "X-Sylpheed-End-Special-Headers: 1",
+                       strlen("X-Sylpheed-End-Special-Headers:"))))
                        break;
                /* old way */
                if (buf[0] == '\r' || buf[0] == '\n') break;
@@ -2062,6 +2123,7 @@ gint procmime_write_message_rfc822(MimeInfo *mimeinfo, FILE *fp)
                }
                fseek(infp, mimeinfo->offset, SEEK_SET);
                while (fgets(buf, sizeof(buf), infp) == buf) {
+                       strcrchomp(buf);
                        if (buf[0] == '\n' && buf[1] == '\0')
                                break;
                        if (skip && (buf[0] == ' ' || buf[0] == '\t'))