Fix CID 1439996 and remove unnecessary comparison
[claws.git] / src / procmime.c
index f62487c85d86cefa2f0b5923728b5f8a1e8f7e0f..02c49a02bbad48f12bae70ba8e35ac4212e7df1b 100644 (file)
@@ -52,6 +52,7 @@
 #include "alertpanel.h"
 #include "timing.h"
 #include "privacy.h"
+#include "account.h"
 
 static GHashTable *procmime_get_mime_type_table        (void);
 static MimeInfo *procmime_scan_file_short(const gchar *filename);
@@ -63,6 +64,7 @@ MimeInfo *procmime_mimeinfo_new(void)
        MimeInfo *mimeinfo;
 
        mimeinfo = g_new0(MimeInfo, 1);
+
        mimeinfo->content        = MIMECONTENT_EMPTY;
        mimeinfo->data.filename  = NULL;
 
@@ -137,6 +139,8 @@ static gboolean free_func(GNode *node, gpointer data)
        if (mimeinfo->privacy)
                privacy_free_privacydata(mimeinfo->privacy);
 
+       g_free(mimeinfo);
+
        return FALSE;
 }
 
@@ -153,7 +157,6 @@ void procmime_mimeinfo_free_all(MimeInfo **mimeinfo_ptr)
 
        g_node_destroy(node);
 
-       g_free(mimeinfo);
        *mimeinfo_ptr = NULL;
 }
 
@@ -293,7 +296,8 @@ static int procmime_fclose(FILE *fp)
                gint llen = 0;                                                  \
                strretchomp(lastline);                                          \
                llen = strlen(lastline);                                        \
-               if (lastline[llen-1] == ' ' && strcmp(lastline,"-- ")) {        \
+               if (lastline[llen-1] == ' ' && !account_signatures_matchlist_str_found(lastline, "%s") &&       \
+                   !(llen == 2 && lastline[1] == ' ' && strchr(prefs_common.quote_chars, lastline[0]))) {                                      \
                        /* this is flowed */                                    \
                        if (delsp)                                              \
                                lastline[llen-1] = '\0';                        \
@@ -323,14 +327,14 @@ gboolean procmime_decode_content(MimeInfo *mimeinfo)
        gint state = 0;
        guint save = 0;
 
+       cm_return_val_if_fail(mimeinfo != NULL, FALSE);
+
        EncodingType encoding = forced_encoding 
                                ? forced_encoding
                                : mimeinfo->encoding_type;
        gchar lastline[BUFFSIZE];
        memset(lastline, 0, BUFFSIZE);
 
-       cm_return_val_if_fail(mimeinfo != NULL, FALSE);
-
        if (prefs_common.respect_flowed_format &&
            mimeinfo->type == MIMETYPE_TEXT && 
            !strcasecmp(mimeinfo->subtype, "plain")) {
@@ -380,11 +384,14 @@ gboolean procmime_decode_content(MimeInfo *mimeinfo)
        tmp_file = TRUE;
        readend = mimeinfo->offset + mimeinfo->length;
 
+       account_signatures_matchlist_create(); /* FLUSH_LASTLINE will use it */
+
+       *buf = '\0';
        if (encoding == ENC_QUOTED_PRINTABLE) {
                while ((ftell(infp) < readend) && (SC_FGETS(buf, sizeof(buf), infp) != NULL)) {
                        gint len;
                        len = qp_decode_line(buf);
-                       buf[len]='\0';
+                       buf[len] = '\0';
                        if (!flowed) {
                                if (SC_FWRITE(buf, 1, len, outfp) < len)
                                        err = TRUE;
@@ -460,7 +467,8 @@ gboolean procmime_decode_content(MimeInfo *mimeinfo)
                                        err = TRUE;
                        }
                }
-               procmime_fclose(tmpfp);
+               if (tmpfp != outfp)
+                       procmime_fclose(tmpfp);
        } else if (encoding == ENC_X_UUENCODE) {
                gchar outbuf[BUFFSIZE];
                gint len;
@@ -499,6 +507,8 @@ gboolean procmime_decode_content(MimeInfo *mimeinfo)
        procmime_fclose(outfp);
        procmime_fclose(infp);
 
+       account_signatures_matchlist_delete();
+
        if (err == TRUE) {
                return FALSE;
        }
@@ -693,14 +703,14 @@ gboolean procmime_encode_content(MimeInfo *mimeinfo, EncodingType encoding)
        return TRUE;
 }
 
-gint procmime_get_part(const gchar *outfile, MimeInfo *mimeinfo)
+static gint procmime_get_part_to_stream(FILE *outfp, MimeInfo *mimeinfo)
 {
-       FILE *infp, *outfp;
+       FILE *infp;
        gchar buf[BUFFSIZE];
        gint restlength, readlength;
        gint saved_errno = 0;
 
-       cm_return_val_if_fail(outfile != NULL, -1);
+       cm_return_val_if_fail(outfp != NULL, -1);
        cm_return_val_if_fail(mimeinfo != NULL, -1);
 
        if (mimeinfo->encoding_type != ENC_BINARY && !procmime_decode_content(mimeinfo))
@@ -717,12 +727,6 @@ gint procmime_get_part(const gchar *outfile, MimeInfo *mimeinfo)
                procmime_fclose(infp);
                return -(saved_errno);
        }
-       if ((outfp = procmime_fopen(outfile, "wb")) == NULL) {
-               saved_errno = errno;
-               FILE_OP_ERROR(outfile, "fopen");
-               procmime_fclose(infp);
-               return -(saved_errno);
-       }
 
        restlength = mimeinfo->length;
 
@@ -730,13 +734,33 @@ gint procmime_get_part(const gchar *outfile, MimeInfo *mimeinfo)
                if (SC_FWRITE(buf, 1, readlength, outfp) != readlength) {
                        saved_errno = errno;
                        procmime_fclose(infp);
-                       procmime_fclose(outfp);
                        return -(saved_errno);
                }
                restlength -= readlength;
        }
 
        procmime_fclose(infp);
+       rewind(outfp);
+
+       return 0;
+}
+
+gint procmime_get_part(const gchar *outfile, MimeInfo *mimeinfo)
+{
+       FILE *outfp;
+       gint result;
+       gint saved_errno = 0;
+
+       cm_return_val_if_fail(outfile != NULL, -1);
+
+       if ((outfp = procmime_fopen(outfile, "wb")) == NULL) {
+               saved_errno = errno;
+               FILE_OP_ERROR(outfile, "fopen");
+               return -(saved_errno);
+       }
+
+       result = procmime_get_part_to_stream(outfp, mimeinfo);
+
        if (procmime_fclose(outfp) == EOF) {
                saved_errno = errno;
                FILE_OP_ERROR(outfile, "fclose");
@@ -744,7 +768,7 @@ gint procmime_get_part(const gchar *outfile, MimeInfo *mimeinfo)
                return -(saved_errno);
        }
 
-       return 0;
+       return result;
 }
 
 gboolean procmime_scan_text_content(MimeInfo *mimeinfo,
@@ -756,8 +780,9 @@ gboolean procmime_scan_text_content(MimeInfo *mimeinfo,
        gboolean conv_fail = FALSE;
        gchar buf[BUFFSIZE];
        gchar *str;
-       gchar *tmpfile;
        gboolean scan_ret = FALSE;
+       gchar *tmpfile = NULL;
+       int r;
 
        cm_return_val_if_fail(mimeinfo != NULL, TRUE);
        cm_return_val_if_fail(scan_callback != NULL, TRUE);
@@ -765,17 +790,26 @@ gboolean procmime_scan_text_content(MimeInfo *mimeinfo,
        if (!procmime_decode_content(mimeinfo))
                return TRUE;
 
+#if HAVE_FMEMOPEN
+       tmpfp = fmemopen(NULL, mimeinfo->length * 2, "w+");
+#else
        tmpfile = procmime_get_tmp_file_name(mimeinfo);
-       if (tmpfile == NULL)
+       if (tmpfile == NULL) {
+               g_warning("no filename\n");
                return TRUE;
+       }
+
+       tmpfp = procmime_fopen(tmpfile, "w+");
+#endif
 
-       if (procmime_get_part(tmpfile, mimeinfo) < 0) {
+       if (tmpfp == NULL) {
                g_free(tmpfile);
+               FILE_OP_ERROR(tmpfile, "open");
                return TRUE;
        }
 
-       tmpfp = procmime_fopen(tmpfile, "rb");
-       if (tmpfp == NULL) {
+       if ((r = procmime_get_part_to_stream(tmpfp, mimeinfo)) < 0) {
+               g_warning("procmime_get_part_to_stream error %d\n", r);
                g_free(tmpfile);
                return TRUE;
        }
@@ -841,8 +875,11 @@ gboolean procmime_scan_text_content(MimeInfo *mimeinfo,
                g_warning("procmime_get_text_content(): Code conversion failed.");
 
        procmime_fclose(tmpfp);
+
+#if !HAVE_FMEMOPEN
        claws_unlink(tmpfile);
        g_free(tmpfile);
+#endif
 
        return scan_ret;
 }
@@ -885,31 +922,31 @@ FILE *procmime_get_text_content(MimeInfo *mimeinfo)
 FILE *procmime_get_binary_content(MimeInfo *mimeinfo)
 {
        FILE *outfp;
-       gchar *tmpfile;
+       gchar *tmpfile = NULL;
 
        cm_return_val_if_fail(mimeinfo != NULL, NULL);
 
        if (!procmime_decode_content(mimeinfo))
                return NULL;
 
+#if HAVE_FMEMOPEN
+       outfp = fmemopen(NULL, mimeinfo->length * 2, "w+");
+#else
        tmpfile = procmime_get_tmp_file_name(mimeinfo);
-       if (tmpfile == NULL)
-               return NULL;
-
-       if (procmime_get_part(tmpfile, mimeinfo) < 0) {
-               g_free(tmpfile);
-               return NULL;
+       if (tmpfile == NULL) {
+               g_warning("no filename\n");
+               return TRUE;
        }
 
-       outfp = procmime_fopen(tmpfile, "rb");
-       if (outfp == NULL) {
-               g_unlink(tmpfile);
-               g_free(tmpfile);
-               return NULL;
-       }
+       outfp = procmime_fopen(tmpfile, "w+");
 
        g_unlink(tmpfile);
        g_free(tmpfile);
+#endif
+
+       if (procmime_get_part_to_stream(outfp, mimeinfo) < 0) {
+               return NULL;
+       }
 
 #ifdef HAVE_FGETS_UNLOCKED
        funlockfile(outfp);
@@ -1119,7 +1156,8 @@ gchar *procmime_get_mime_type(const gchar *filename)
                debug_print("got type %s for %s\n", str, ext);
                g_free(ext);
                return str;
-       } 
+       }
+       g_free(ext);
        return NULL;
 #else
        gchar *str = get_content_type_from_registry_with_ext(ext);