talons

Fork of Claws Mail https://www.claws-mail
Log | Files | Refs | README | LICENSE

commit a7c02553954b694238e1dd4422614923083b809c
parent 3dc44ceb67c99ae91783b9f2f438f8b1d2aeea4d
Author: Andrej Kacian <ticho@claws-mail.org>
Date:   Thu, 18 Jun 2015 13:07:47 +0200

Encrypt message just before writing it to queue dir.

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.

Diffstat:
Msrc/compose.c | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Msrc/compose.h | 1+
Msrc/procmsg.c | 112+++++++++++--------------------------------------------------------------------
Msrc/procmsg.h | 2++
4 files changed, 85 insertions(+), 109 deletions(-)

diff --git a/src/compose.c b/src/compose.c @@ -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); diff --git a/src/compose.h b/src/compose.h @@ -187,6 +187,7 @@ struct _Compose gboolean use_signing; gboolean use_encryption; gchar *privacy_system; + gchar *encdata; gboolean modified; diff --git a/src/procmsg.c b/src/procmsg.c @@ -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); } diff --git a/src/procmsg.h b/src/procmsg.h @@ -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);