/*
- * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
- * Copyright (C) 1999-2013 Hiroyuki Yamamoto and the Claws Mail team
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 1999-2015 Hiroyuki Yamamoto and 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
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
+ *
*/
#ifdef HAVE_CONFIG_H
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);
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);
gint len;
FILE *fp;
gboolean prev_autowrap;
- struct stat file_stat;
+ GStatBuf file_stat;
int ret;
GString *file_contents = NULL;
ComposeInsertResult result = COMPOSE_INSERT_SUCCESS;
outfile = procmime_get_tmp_file_name(child);
if ((err = procmime_get_part(outfile, child)) < 0)
- g_warning("Can't get the part of multipart message. (%s)", strerror(-err));
+ g_warning("Can't get the part of multipart message. (%s)", g_strerror(-err));
else {
gchar *content_type;
alertpanel_error(_("Could not queue message for sending:\n\n"
"Signature failed: %s"), privacy_get_error());
} else if (val == -2 && errno != 0) {
- alertpanel_error(_("Could not queue message for sending:\n\n%s."), strerror(errno));
+ alertpanel_error(_("Could not queue message for sending:\n\n%s."), g_strerror(errno));
} else {
alertpanel_error(_("Could not queue message for sending."));
}
{
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;
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;
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"
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"
}
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. */
+ if ((tmpfp = g_fopen(tmp_enc_file, "a")) != NULL) {
+ 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("Can't open file %s\n", 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());
+ alertpanel_error(_("Couldn't encrypt the email: %s"),
+ privacy_get_error());
+ }
+ }
+ }
+
procmime_write_mimeinfo(mimemsg, fp);
procmime_mimeinfo_free_all(mimemsg);
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;
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);
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);
g_free(tmp);
return -5;
}
- g_free(encdata);
}
}
AttachInfo *ainfo;
GtkTreeView *tree_view = GTK_TREE_VIEW(compose->attach_clist);
MimeInfo *mimepart;
- struct stat statbuf;
+ GStatBuf statbuf;
gchar *type, *subtype;
GtkTreeModel *model;
GtkTreeIter iter;
if (header)
gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN((combo)))), header);
+ gtk_editable_set_editable(
+ GTK_EDITABLE(gtk_bin_get_child(GTK_BIN((combo)))),
+ prefs_common.type_any_header);
+
g_signal_connect_after(G_OBJECT(gtk_bin_get_child(GTK_BIN((combo)))), "grab_focus",
G_CALLBACK(compose_grab_focus_cb), compose);
compose->use_signing = FALSE;
compose->use_encryption = FALSE;
compose->privacy_system = NULL;
+ compose->encdata = NULL;
compose->modified = FALSE;
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);
g_free(compose->orig_charset);
g_free(compose->privacy_system);
+ g_free(compose->encdata);
#ifndef USE_NEW_ADDRBOOK
if (addressbook_get_target_compose() == compose)
Compose *compose = (Compose *)data;
GtkTreeSelection *attach_selection;
gint attach_nr_selected;
+ GtkTreePath *path;
if (!event) return FALSE;
if (event->button == 3) {
attach_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
attach_nr_selected = gtk_tree_selection_count_selected_rows(attach_selection);
-
+
+ /* If no rows, or just one row is selected, right-click should
+ * open menu relevant to the row being right-clicked on. We
+ * achieve that by selecting the clicked row first. If more
+ * than one row is selected, we shouldn't modify the selection,
+ * as user may want to remove selected rows (attachments). */
+ if (attach_nr_selected < 2) {
+ gtk_tree_selection_unselect_all(attach_selection);
+ attach_nr_selected = 0;
+ gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(widget),
+ event->x, event->y, &path, NULL, NULL, NULL);
+ if (path != NULL) {
+ gtk_tree_selection_select_path(attach_selection, path);
+ gtk_tree_path_free(path);
+ attach_nr_selected++;
+ }
+ }
+
cm_menu_set_sensitive_full(compose->ui_manager, "Popup/Compose/Remove", (attach_nr_selected > 0));
- cm_menu_set_sensitive_full(compose->ui_manager, "Popup/Compose/Properties", (attach_nr_selected > 0));
+ /* Properties menu item makes no sense with more than one row
+ * selected, the properties dialog can only edit one attachment. */
+ cm_menu_set_sensitive_full(compose->ui_manager, "Popup/Compose/Properties", (attach_nr_selected == 1));
gtk_menu_popup(GTK_MENU(compose->popupmenu), NULL, NULL,
NULL, NULL, event->button, event->time);
} else if (val == -1) {
alertpanel_error(_("Could not queue message."));
} else if (val == -2) {
- alertpanel_error(_("Could not queue message:\n\n%s."), strerror(errno));
+ alertpanel_error(_("Could not queue message:\n\n%s."), g_strerror(errno));
} else if (val == -3) {
if (privacy_peek_error())
alertpanel_error(_("Could not queue message for sending:\n\n"
compose_close(compose);
return TRUE;
} else {
- struct stat s;
+ GStatBuf s;
gchar *path;
path = folder_item_fetch_msg(draft, msgnum);
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);
GdkAtom type;
type = gtk_selection_data_get_data_type(data);
- if (((gdk_atom_name(type) && !strcmp(gdk_atom_name(type), "text/uri-list"))
-#ifdef G_OS_WIN32
- || (gdk_atom_name(type) && !strcmp(gdk_atom_name(type), "DROPFILES_DND"))
-#endif
- ) && gtk_drag_get_source_widget(context) !=
+ if ((gdk_atom_name(type) && !strcmp(gdk_atom_name(type), "text/uri-list"))
+ && gtk_drag_get_source_widget(context) !=
summary_get_main_widget(mainwindow_get_mainwindow()->summaryview)) {
list = uri_list_extract_filenames(
(const gchar *)gtk_selection_data_get_data(data));
/* strangely, testing data->type == gdk_atom_intern("text/uri-list", TRUE)
* does not work */
type = gtk_selection_data_get_data_type(data);
-#ifndef G_OS_WIN32
if (gdk_atom_name(type) && !strcmp(gdk_atom_name(type), "text/uri-list")) {
-#else
- if (gdk_atom_name(type) && !strcmp(gdk_atom_name(type), "DROPFILES_DND")) {
-#endif
AlertValue val = G_ALERTDEFAULT;
const gchar* ddata = (const gchar *)gtk_selection_data_get_data(data);