Encrypt message just before writing it to queue dir.
authorAndrej Kacian <ticho@claws-mail.org>
Thu, 18 Jun 2015 11:07:47 +0000 (13:07 +0200)
committerAndrej Kacian <ticho@claws-mail.org>
Thu, 25 Jun 2015 11:01:58 +0000 (13:01 +0200)
This fixes bug #2965.
As a side effect, if "Save sent encrypted messages as clear text" is
enabled, a copy will be saved to outbox when queuing, not when sending.

src/compose.c
src/compose.h
src/procmsg.c
src/procmsg.h

index 2cf8df8..d854340 100644 (file)
@@ -1307,11 +1307,15 @@ static void compose_force_encryption(Compose *compose, PrefsAccount *account,
                if (system) {
                        g_free(compose->privacy_system);
                        compose->privacy_system = NULL;
+                       g_free(compose->encdata);
+                       compose->encdata = NULL;
                }
                if (compose->privacy_system == NULL)
                        compose->privacy_system = g_strdup(privacy);
                else if (*(compose->privacy_system) == '\0') {
                        g_free(compose->privacy_system);
+                       g_free(compose->encdata);
+                       compose->encdata = NULL;
                        compose->privacy_system = g_strdup(privacy);
                }
                compose_update_privacy_system_menu_item(compose, FALSE);
@@ -1338,6 +1342,8 @@ static void compose_force_signing(Compose *compose, PrefsAccount *account, const
                if (system) {
                        g_free(compose->privacy_system);
                        compose->privacy_system = NULL;
+                       g_free(compose->encdata);
+                       compose->encdata = NULL;
                }
                if (compose->privacy_system == NULL)
                        compose->privacy_system = g_strdup(privacy);
@@ -5512,8 +5518,8 @@ static gint compose_write_to_file(Compose *compose, FILE *fp, gint action, gbool
 {
        GtkTextBuffer *buffer;
        GtkTextIter start, end;
-       gchar *chars;
-       gchar *buf;
+       gchar *chars, *tmp_enc_file, *content;
+       gchar *buf, *msg;
        const gchar *out_codeset;
        EncodingType encoding = ENC_UNKNOWN;
        MimeInfo *mimemsg, *mimetext;
@@ -5521,6 +5527,7 @@ static gint compose_write_to_file(Compose *compose, FILE *fp, gint action, gbool
        const gchar *src_codeset = CS_INTERNAL;
        gchar *from_addr = NULL;
        gchar *from_name = NULL;
+       FolderItem *outbox;
 
        if (action == COMPOSE_WRITE_FOR_SEND)
                attach_parts = TRUE;
@@ -5601,7 +5608,6 @@ static gint compose_write_to_file(Compose *compose, FILE *fp, gint action, gbool
 
                if (!buf) {
                        AlertValue aval;
-                       gchar *msg;
 
                        msg = g_strdup_printf(_("Can't convert the character encoding of the message \n"
                                                "to the specified %s charset.\n"
@@ -5658,7 +5664,6 @@ static gint compose_write_to_file(Compose *compose, FILE *fp, gint action, gbool
            encoding != ENC_QUOTED_PRINTABLE && encoding != ENC_BASE64 &&
            check_line_length(buf, 1000, &line) < 0) {
                AlertValue aval;
-               gchar *msg;
 
                msg = g_strdup_printf
                        (_("Line %d exceeds the line length limit (998 bytes).\n"
@@ -5730,6 +5735,53 @@ static gint compose_write_to_file(Compose *compose, FILE *fp, gint action, gbool
        }
        g_free(from_name);
        g_free(from_addr);
+
+       if (compose->use_encryption) {
+               if (compose->encdata != NULL &&
+                               strcmp(compose->encdata, "_DONT_ENCRYPT_")) {
+
+                       /* First, write an unencrypted copy and save it to outbox, if
+                        * user wants that. */
+                       if (compose->account->save_encrypted_as_clear_text) {
+                               debug_print("saving sent message unencrypted...\n");
+                               FILE *tmpfp = get_tmpfile_in_dir(get_mime_tmp_dir(), &tmp_enc_file);
+                               if (tmpfp) {
+                                       fclose(tmpfp);
+
+                                       /* fp now points to a file with headers written,
+                                        * let's make a copy. */
+                                       rewind(fp);
+                                       content = file_read_stream_to_str(fp);
+
+                                       str_write_to_file(content, tmp_enc_file);
+                                       g_free(content);
+
+                                       /* Now write the unencrypted body. */
+                                       tmpfp = g_fopen(tmp_enc_file, "a");
+                                       procmime_write_mimeinfo(mimemsg, tmpfp);
+                                       fclose(tmpfp);
+
+                                       outbox = folder_find_item_from_identifier(compose_get_save_to(compose));
+                                       if (!outbox)
+                                               outbox = folder_get_default_outbox();
+
+                                       procmsg_save_to_outbox(outbox, tmp_enc_file, TRUE);
+                                       claws_unlink(tmp_enc_file);
+                               } else {
+                                       g_warning("couldn't get tempfile\n");
+                               }
+                       }
+                       if (!privacy_encrypt(compose->privacy_system, mimemsg, compose->encdata)) {
+                               debug_print("Couldn't encrypt mime structure: %s.\n",
+                                               privacy_get_error());
+                               msg = g_strdup_printf("Couldn't encrypt the email: %s",
+                                               privacy_get_error());
+                               alertpanel_error(msg);
+                               g_free(msg);
+                       }
+               }
+       }
+
        procmime_write_mimeinfo(mimemsg, fp);
        
        procmime_mimeinfo_free_all(mimemsg);
@@ -5913,7 +5965,7 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
        tmp = g_strdup_printf("%s%cqueue.%p%08x", get_tmp_dir(),
                              G_DIR_SEPARATOR, compose, (guint) rand());
        debug_print("queuing to %s\n", tmp);
-       if ((fp = g_fopen(tmp, "wb")) == NULL) {
+       if ((fp = g_fopen(tmp, "w+b")) == NULL) {
                FILE_OP_ERROR(tmp, "fopen");
                g_free(tmp);
                return -2;
@@ -5975,7 +6027,6 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
                err |= (fprintf(fp, "X-Claws-Privacy-System:%s\n", compose->privacy_system) < 0);
                err |= (fprintf(fp, "X-Claws-Sign:%d\n", compose->use_signing) < 0);
                if (compose->use_encryption) {
-                       gchar *encdata;
                        if (!compose_warn_encryption(compose)) {
                                fclose(fp);
                                claws_unlink(tmp);
@@ -5985,16 +6036,16 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
                        if (mailac && mailac->encrypt_to_self) {
                                GSList *tmp_list = g_slist_copy(compose->to_list);
                                tmp_list = g_slist_append(tmp_list, compose->account->address);
-                               encdata = privacy_get_encrypt_data(compose->privacy_system, tmp_list);
+                               compose->encdata = privacy_get_encrypt_data(compose->privacy_system, tmp_list);
                                g_slist_free(tmp_list);
                        } else {
-                               encdata = privacy_get_encrypt_data(compose->privacy_system, compose->to_list);
+                               compose->encdata = privacy_get_encrypt_data(compose->privacy_system, compose->to_list);
                        }
-                       if (encdata != NULL) {
-                               if (strcmp(encdata, "_DONT_ENCRYPT_")) {
+                       if (compose->encdata != NULL) {
+                               if (strcmp(compose->encdata, "_DONT_ENCRYPT_")) {
                                        err |= (fprintf(fp, "X-Claws-Encrypt:%d\n", compose->use_encryption) < 0);
                                        err |= (fprintf(fp, "X-Claws-Encrypt-Data:%s\n", 
-                                               encdata) < 0);
+                                               compose->encdata) < 0);
                                } /* else we finally dont want to encrypt */
                        } else {
                                err |= (fprintf(fp, "X-Claws-Encrypt:%d\n", compose->use_encryption) < 0);
@@ -6007,7 +6058,6 @@ static gint compose_queue_sub(Compose *compose, gint *msgnum, FolderItem **item,
                                g_free(tmp);
                                return -5;
                        }
-                       g_free(encdata);
                }
        }
 
@@ -7941,6 +7991,7 @@ static Compose *compose_create(PrefsAccount *account,
        compose->use_signing    = FALSE;
        compose->use_encryption = FALSE;
        compose->privacy_system = NULL;
+       compose->encdata        = NULL;
 
        compose->modified = FALSE;
 
@@ -8245,6 +8296,8 @@ static void compose_set_privacy_system_cb(GtkWidget *widget, gpointer data)
        systemid = g_object_get_data(G_OBJECT(widget), "privacy_system");
        g_free(compose->privacy_system);
        compose->privacy_system = NULL;
+       g_free(compose->encdata);
+       compose->encdata = NULL;
        if (systemid != NULL) {
                compose->privacy_system = g_strdup(systemid);
 
@@ -8782,6 +8835,7 @@ static void compose_destroy(Compose *compose)
        g_free(compose->orig_charset);
 
        g_free(compose->privacy_system);
+       g_free(compose->encdata);
 
 #ifndef USE_NEW_ADDRBOOK
        if (addressbook_get_target_compose() == compose)
@@ -11035,6 +11089,7 @@ static void compose_toggle_encrypt_cb(GtkToggleAction *action, gpointer data)
 static void activate_privacy_system(Compose *compose, PrefsAccount *account, gboolean warn) 
 {
        g_free(compose->privacy_system);
+       g_free(compose->encdata);
 
        compose->privacy_system = g_strdup(account->default_privacy_system);
        compose_update_privacy_system_menu_item(compose, warn);
index 114ee89..dbad032 100644 (file)
@@ -187,6 +187,7 @@ struct _Compose
        gboolean use_signing;
        gboolean use_encryption;
        gchar *privacy_system;
+       gchar *encdata;
 
        gboolean modified;
 
index 5bf6513..5ff5f4d 100644 (file)
@@ -1136,7 +1136,7 @@ gint procmsg_remove_special_headers(const gchar *in, const gchar *out)
        return 0;
 }
 
-static gint procmsg_save_to_outbox(FolderItem *outbox, const gchar *file,
+gint procmsg_save_to_outbox(FolderItem *outbox, const gchar *file,
                            gboolean is_queued)
 {
        gint num;
@@ -1514,22 +1514,23 @@ guint procmsg_msginfo_memusage(MsgInfo *msginfo)
 static gint procmsg_send_message_queue_full(const gchar *file, gboolean keep_session, gchar **errstr,
                                            FolderItem *queue, gint msgnum, gboolean *queued_removed)
 {
-       static HeaderEntry qentry[] = {{"S:",    NULL, FALSE},
+       static HeaderEntry qentry[] = {
+                                      {"S:",    NULL, FALSE}, /* 0 */
                                       {"SSV:",  NULL, FALSE},
                                       {"R:",    NULL, FALSE},
                                       {"NG:",   NULL, FALSE},
                                       {"MAID:", NULL, FALSE},
-                                      {"NAID:", NULL, FALSE},
+                                      {"NAID:", NULL, FALSE}, /* 5 */
                                       {"SCF:",  NULL, FALSE},
                                       {"RMID:", NULL, FALSE},
                                       {"FMID:", NULL, FALSE},
                                       {"X-Claws-Privacy-System:", NULL, FALSE},
-                                      {"X-Claws-Encrypt:", NULL, FALSE},
+                                      {"X-Claws-Encrypt:", NULL, FALSE}, /* 10 */
                                       {"X-Claws-Encrypt-Data:", NULL, FALSE},
                                       {"X-Claws-End-Special-Headers:", NULL, FALSE},
                                       {"X-Sylpheed-Privacy-System:", NULL, FALSE},
                                       {"X-Sylpheed-Encrypt:", NULL, FALSE},
-                                      {"X-Sylpheed-Encrypt-Data:", NULL, FALSE},
+                                      {"X-Sylpheed-Encrypt-Data:", NULL, FALSE}, /* 15 */
                                       {"X-Sylpheed-End-Special-Headers:", NULL, FALSE},
                                       {NULL,    NULL, FALSE}};
        FILE *fp;
@@ -1542,14 +1543,11 @@ static gint procmsg_send_message_queue_full(const gchar *file, gboolean keep_ses
        gchar *savecopyfolder = NULL;
        gchar *replymessageid = NULL;
        gchar *fwdmessageid = NULL;
-       gchar *privacy_system = NULL;
-       gboolean encrypt = FALSE;
-       gchar *encrypt_data = NULL;
        gchar buf[BUFFSIZE];
        gint hnum;
        PrefsAccount *mailac = NULL, *newsac = NULL;
-       gboolean save_clear_text = TRUE;
-       gchar *tmp_enc_file = NULL;
+       gboolean encrypt = FALSE;
+       FolderItem *outbox;
 
        cm_return_val_if_fail(file != NULL, -1);
 
@@ -1599,21 +1597,11 @@ static gint procmsg_send_message_queue_full(const gchar *file, gboolean keep_ses
                        if (fwdmessageid == NULL) 
                                fwdmessageid = g_strdup(p);
                        break;
-               case Q_PRIVACY_SYSTEM:
-               case Q_PRIVACY_SYSTEM_OLD:
-                       if (privacy_system == NULL) 
-                               privacy_system = g_strdup(p);
-                       break;
                case Q_ENCRYPT:
                case Q_ENCRYPT_OLD:
                        if (p[0] == '1') 
                                encrypt = TRUE;
                        break;
-               case Q_ENCRYPT_DATA:
-               case Q_ENCRYPT_DATA_OLD:
-                       if (encrypt_data == NULL) 
-                               encrypt_data = g_strdup(p);
-                       break;
                case Q_CLAWS_HDRS:
                case Q_CLAWS_HDRS_OLD:
                        /* end of special headers reached */
@@ -1631,64 +1619,6 @@ send_mail:
                return -1;
        }
 
-       if (encrypt) {
-               MimeInfo *mimeinfo;
-
-               if (mailac && mailac->save_encrypted_as_clear_text 
-               &&  !mailac->encrypt_to_self)
-                       save_clear_text = TRUE;
-               else
-                       save_clear_text = FALSE;
-
-               fclose(fp);
-               fp = NULL;
-
-               mimeinfo = procmime_scan_queue_file(file);
-               if (!privacy_encrypt(privacy_system, mimeinfo, encrypt_data)
-               || (fp = my_tmpfile()) == NULL
-               ||  procmime_write_mimeinfo(mimeinfo, fp) < 0) {
-                       if (fp)
-                               fclose(fp);
-                       procmime_mimeinfo_free_all(mimeinfo);
-                       g_free(from);
-                       g_free(smtpserver);
-                       slist_free_strings_full(to_list);
-                       slist_free_strings_full(newsgroup_list);
-                       g_free(savecopyfolder);
-                       g_free(replymessageid);
-                       g_free(fwdmessageid);
-                       g_free(privacy_system);
-                       g_free(encrypt_data);
-                       if (errstr) {
-                               if (*errstr) g_free(*errstr);
-                               *errstr = g_strdup_printf(_("Couldn't encrypt the email: %s"),
-                                               privacy_get_error());
-                       }
-                       return -1;
-               }
-               
-               rewind(fp);
-               if (!save_clear_text) {
-                       gchar *content = NULL;
-                       FILE *tmpfp = get_tmpfile_in_dir(get_mime_tmp_dir(), &tmp_enc_file);
-                       if (tmpfp) {
-                               fclose(tmpfp);
-
-                               content = file_read_stream_to_str(fp);
-                               rewind(fp);
-
-                               str_write_to_file(content, tmp_enc_file);
-                               g_free(content);
-                       } else {
-                               g_warning("couldn't get tempfile\n");
-                       }
-               } 
-               
-               procmime_mimeinfo_free_all(mimeinfo);
-               
-               filepos = 0;
-       }
-
        if (to_list) {
                debug_print("Sending message by mail\n");
                if (!from) {
@@ -1809,15 +1739,14 @@ send_mail:
 
        /* save message to outbox */
        if (mailval == 0 && newsval == 0 && savecopyfolder) {
-               FolderItem *outbox;
-
                debug_print("saving sent message...\n");
 
-               outbox = folder_find_item_from_identifier(savecopyfolder);
-               if (!outbox)
-                       outbox = folder_get_default_outbox();
-                       
-               if (save_clear_text || tmp_enc_file == NULL) {
+               if (!encrypt || !mailac->save_encrypted_as_clear_text) {
+                       outbox = folder_find_item_from_identifier(savecopyfolder);
+                       if (!outbox)
+                               outbox = folder_get_default_outbox();
+
+                       /* Mail was not saved to outbox before encrypting, save it now. */
                        gboolean saved = FALSE;
                        *queued_removed = FALSE;
                        if (queue && msgnum > 0) {
@@ -1833,21 +1762,12 @@ send_mail:
                                procmsg_msginfo_free(queued_mail);
                        }
                        if (!saved) {
-                               debug_print("resaving clear text queued mail to sent folder\n");
+                               debug_print("resaving queued mail to sent folder\n");
                                procmsg_save_to_outbox(outbox, file, TRUE);
                        }
-               } else {
-                       debug_print("saving encrpyted queued mail to sent folder\n");
-                       procmsg_save_to_outbox(outbox, tmp_enc_file, FALSE);
                }
        }
 
-       if (tmp_enc_file != NULL) {
-               claws_unlink(tmp_enc_file);
-               free(tmp_enc_file);
-               tmp_enc_file = NULL;
-       }
-
        if (replymessageid != NULL || fwdmessageid != NULL) {
                gchar **tokens;
                FolderItem *item;
@@ -1901,8 +1821,6 @@ send_mail:
        g_free(savecopyfolder);
        g_free(replymessageid);
        g_free(fwdmessageid);
-       g_free(privacy_system);
-       g_free(encrypt_data);
 
        return (newsval != 0 ? newsval : mailval);
 }
index b7fb870..5152c05 100644 (file)
@@ -371,6 +371,8 @@ void procmsg_msginfo_change_flags   (MsgInfo *msginfo,
 gint procmsg_remove_special_headers    (const gchar    *in, 
                                         const gchar    *out);
 
+gint procmsg_save_to_outbox(FolderItem *outbox, const gchar *file,
+                           gboolean is_queued);
 gboolean procmsg_msg_has_flagged_parent        (MsgInfo        *info,
                                         MsgPermFlags    perm_flags);
 gboolean procmsg_msg_has_marked_parent (MsgInfo        *info);