*
* 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
#include "timing.h"
#include "manage_window.h"
#include "privacy.h"
+#include "file-utils.h"
typedef enum
{
COL_SIZE = 1,
COL_NAME = 2,
COL_DATA = 3,
+ N_MIMEVIEW_COLUMNS
} MimeViewColumnPos;
-#define N_MIMEVIEW_COLS 4
+#define N_MIMEVIEW_COLS (N_MIMEVIEW_COLUMNS)
static void mimeview_set_multipart_tree (MimeView *mimeview,
MimeInfo *mimeinfo,
MimeInfo *partinfo);
static void mimeview_change_view_type (MimeView *mimeview,
MimeViewType type);
-static gchar *mimeview_get_filename_for_part (MimeInfo *partinfo,
+static gchar *mimeview_get_filename_for_part (MimeInfo *partinfo,
const gchar *basedir,
gint number);
static gboolean mimeview_write_part (const gchar *filename,
- MimeInfo *partinfo);
+ MimeInfo *partinfo,
+ gboolean handle_error);
static void mimeview_selected (GtkTreeSelection *selection,
MimeView *mimeview);
}
#endif
+static void mimeview_copy_cb(GtkAction *action, gpointer data)
+{
+ MimeView *mimeview = (MimeView *)data;
+ MimeInfo *mimeinfo = mimeview_get_part_to_use(mimeview);
+
+ if (mimeinfo == NULL)
+ return;
+
+ if (mimeinfo->type == MIMETYPE_IMAGE) {
+ GError *error = NULL;
+ GdkPixbuf *pixbuf = procmime_get_part_as_pixbuf(mimeinfo, &error);
+ if (error != NULL) {
+ g_warning("could not copy: %s", error->message);
+ g_error_free(error);
+ } else {
+ gtk_clipboard_set_image(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),
+ pixbuf);
+ }
+ g_object_unref(pixbuf);
+ } else {
+ void *data = procmime_get_part_as_string(mimeinfo, FALSE);
+ gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD),
+ data, mimeinfo->length);
+ g_free(data);
+ }
+}
+
static void mimeview_send_to_cb(GtkAction *action, gpointer data)
{
MimeView *mimeview = (MimeView *)data;
}
static GtkActionEntry mimeview_menu_actions[] = {
- { "MimeView", NULL, "MimeView" },
+ { "MimeView", NULL, "MimeView", NULL, NULL, NULL },
{ "MimeView/Open", NULL, N_("_Open"), NULL, "Open MIME part", G_CALLBACK(mimeview_launch_cb) },
#if (!defined G_OS_WIN32)
{ "MimeView/OpenWith", NULL, N_("Open _with..."), NULL, "Open MIME part with...", G_CALLBACK(mimeview_open_with_cb) },
#endif
+ { "MimeView/Copy", NULL, N_("Copy"), NULL, "Copy", G_CALLBACK(mimeview_copy_cb) },
{ "MimeView/SendTo", NULL, N_("Send to..."), NULL, "Send to", G_CALLBACK(mimeview_send_to_cb) },
{ "MimeView/DisplayAsText", NULL, N_("_Display as text"), NULL, "Display as text", G_CALLBACK(mimeview_display_as_text_cb) },
{ "MimeView/SaveAs", NULL, N_("_Save as..."), NULL, "Save as", G_CALLBACK(mimeview_save_as_cb) },
G_TYPE_POINTER);
ctree = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
+ g_object_unref(model);
gtk_tree_view_set_enable_search(GTK_TREE_VIEW(ctree), FALSE);
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(ctree),
prefs_common.use_stripes_everywhere);
column = gtk_tree_view_get_column(GTK_TREE_VIEW(ctree), cols-1);
renderer = gtk_cell_renderer_text_new();
-#if(GTK_CHECK_VERSION(2,18,0))
gtk_cell_renderer_set_alignment(renderer, 1, 0.5);
-#endif
cols = gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(ctree),
-1, titles[COL_SIZE], renderer,
"text", COL_SIZE, NULL);
mime_notebook = gtk_notebook_new();
gtk_widget_show(mime_notebook);
- gtkut_widget_set_can_focus(mime_notebook, FALSE);
+ gtk_widget_set_can_focus(mime_notebook, FALSE);
gtk_notebook_set_show_tabs(GTK_NOTEBOOK(mime_notebook), FALSE);
gtk_notebook_set_show_border(GTK_NOTEBOOK(mime_notebook), FALSE);
GTK_UI_MANAGER_MENUITEM);
#endif
MENUITEM_ADDUI_MANAGER(mimeview->ui_manager,
+ "/Menus/MimeView/", "Copy", "MimeView/Copy",
+ GTK_UI_MANAGER_MENUITEM);
+ MENUITEM_ADDUI_MANAGER(mimeview->ui_manager,
"/Menus/MimeView/", "SendTo", "MimeView/SendTo",
GTK_UI_MANAGER_MENUITEM);
MENUITEM_ADDUI_MANAGER(mimeview->ui_manager,
MimeInfo *mimeview_get_selected_part(MimeView *mimeview)
{
- GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(mimeview->ctree));
- GtkTreeIter iter;
- GtkTreeSelection *selection;
- MimeInfo *partinfo = NULL;
-
- selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(mimeview->ctree));
- if (gtk_tree_selection_get_selected(selection, NULL, &iter))
- gtk_tree_model_get(model, &iter, COL_DATA, &partinfo, -1);
-
- return partinfo;
+ return gtkut_tree_view_get_selected_pointer(
+ GTK_TREE_VIEW(mimeview->ctree), COL_DATA,
+ NULL, NULL, NULL);
}
MimeInfo *mimeview_get_node_part(MimeView *mimeview, GtkTreePath *path)
GtkTreePath *path;
gint i = 0;
- gtk_tree_model_get_iter_first(model, &iter);
+ if (!gtk_tree_model_get_iter_first(model, &iter))
+ return -1;
path = gtk_tree_model_get_path(model, &iter);
do {
if (i < 0)
return;
- gtk_tree_model_get_iter_first(model, &iter);
+ if (!gtk_tree_model_get_iter_first(model, &iter))
+ return;
path = gtk_tree_model_get_path(model, &iter);
while (x != i) {
fname = mimeview->file;
if (!fname) return;
- if ((fp = g_fopen(fname, "rb")) == NULL) {
- FILE_OP_ERROR(fname, "fopen");
+ if ((fp = claws_fopen(fname, "rb")) == NULL) {
+ FILE_OP_ERROR(fname, "claws_fopen");
return;
}
if (fseek(fp, partinfo->offset, SEEK_SET) < 0) {
FILE_OP_ERROR(mimeview->file, "fseek");
- fclose(fp);
+ claws_fclose(fp);
return;
}
mimeview_change_view_type(mimeview, MIMEVIEW_TEXT);
textview_show_part(mimeview->textview, partinfo, fp);
- fclose(fp);
+ claws_fclose(fp);
}
static MimeViewer *get_viewer_for_content_type(MimeView *mimeview, const gchar *content_type)
mimeview_check_sig_worker_thread,
mimeview) != 0) {
/* arh. We'll do it synchronously. */
- g_warning("can't create thread");
+ g_warning("can't create checked thread");
g_free(mimeview->check_data);
mimeview->check_data = NULL;
return;
}
/* create the killer thread */
- pthread_create(&th2, &detach2,
+ if (pthread_create(&th2, &detach2,
mimeview_check_sig_cancel_thread,
- mimeview);
-
- mimeview->check_data->cancel_th = th2;
- mimeview->check_data->cancel_th_init = TRUE;
+ mimeview) != 0) {
+ g_warning("can't create killer thread");
+ g_free(mimeview->check_data);
+ mimeview->check_data = NULL;
+ return;
+ } else {
+ mimeview->check_data->cancel_th = th2;
+ mimeview->check_data->cancel_th_init = TRUE;
+ }
}
#endif
GtkTreeIter iter;
GtkTreePath *path;
MimeInfo *partinfo;
+ MainWindow *mainwin;
selection = gtk_tree_view_get_selection(ctree);
if (!gtk_tree_selection_get_selected(selection, &model, &iter))
break;
}
}
+ mainwin = mainwindow_get_mainwindow();
+ if (mainwin)
+ main_window_set_menu_sensitive(mainwin);
if (mimeview->siginfo && privacy_auto_check_signatures(mimeview->siginfo)
&& privacy_mimeinfo_get_sig_status(mimeview->siginfo) == SIGNATURE_UNCHECKED) {
return TRUE;
}
-/* from gdkevents.c */
-#define DOUBLE_CLICK_TIME 250
-
static gboolean part_button_pressed(MimeView *mimeview, GdkEventButton *event,
MimeInfo *partinfo)
{
static MimeInfo *lastinfo;
static guint32 lasttime;
+ gint double_click_time;
+ g_object_get(gtk_settings_get_default(), "gtk-double-click-time", &double_click_time, NULL);
+
if (event->button == 2 ||
- (event->button == 1 && (event->time - lasttime) < DOUBLE_CLICK_TIME && lastinfo == partinfo)) {
+ (event->button == 1 && (event->time - lasttime) < double_click_time && lastinfo == partinfo)) {
/* call external program for image, audio or html */
mimeview_launch(mimeview, partinfo);
return TRUE;
} else if (event->button == 3) {
+ MainWindow *mainwin = mainwindow_get_mainwindow();
+
if (partinfo && (partinfo->type == MIMETYPE_MESSAGE ||
partinfo->type == MIMETYPE_IMAGE ||
partinfo->type == MIMETYPE_MULTIPART))
cm_menu_set_sensitive_full(mimeview->ui_manager, "Menus/MimeView/DisplayAsText", FALSE);
else
cm_menu_set_sensitive_full(mimeview->ui_manager, "Menus/MimeView/DisplayAsText", TRUE);
+
+ if (partinfo && (partinfo->type == MIMETYPE_MESSAGE ||
+ partinfo->type == MIMETYPE_IMAGE ||
+ partinfo->type == MIMETYPE_TEXT))
+ cm_menu_set_sensitive_full(mimeview->ui_manager, "Menus/MimeView/Copy", TRUE);
+ else
+ cm_menu_set_sensitive_full(mimeview->ui_manager, "Menus/MimeView/Copy", FALSE);
#ifndef G_OS_WIN32
if (partinfo &&
partinfo->type == MIMETYPE_APPLICATION &&
else
#endif
cm_menu_set_sensitive_full(mimeview->ui_manager, "Menus/MimeView/Open", TRUE);
-
+ if (mainwin)
+ main_window_set_menu_sensitive(mainwin);
g_object_set_data(G_OBJECT(mimeview->popupmenu),
"pop_partinfo", partinfo);
GPtrArray *headers = NULL;
FILE *fp;
- fp = g_fopen(partinfo->data.filename, "rb");
+ fp = claws_fopen(partinfo->data.filename, "rb");
if (fp != NULL && fseek(fp, partinfo->offset, SEEK_SET) == 0) {
headers = procheader_get_header_array_asis(fp);
if (headers) {
}
}
if (fp != NULL)
- fclose(fp);
+ claws_fclose(fp);
if (name)
filename = g_path_get_basename(name);
g_free(name);
* \param partinfo Attachment to save
*/
static gboolean mimeview_write_part(const gchar *filename,
- MimeInfo *partinfo)
+ MimeInfo *partinfo,
+ gboolean handle_error)
{
gchar *dir;
gint err;
res = g_strdup_printf(_("Overwrite existing file '%s'?"),
tmp);
g_free(tmp);
- aval = alertpanel(_("Overwrite"), res, GTK_STOCK_CANCEL,
- GTK_STOCK_OK, NULL);
- g_free(res);
+ aval = alertpanel(_("Overwrite"), res, GTK_STOCK_CANCEL,
+ GTK_STOCK_OK, NULL, ALERTFOCUS_FIRST);
+ g_free(res);
if (G_ALERTALTERNATE != aval) return FALSE;
}
if ((err = procmime_get_part(filename, partinfo)) < 0) {
- alertpanel_error
- (_("Couldn't save the part of multipart message: %s"),
- g_strerror(-err));
+ debug_print("error saving MIME part: %d\n", err);
+ if (handle_error)
+ alertpanel_error
+ (_("Couldn't save the part of multipart message: %s"),
+ g_strerror(-err));
return FALSE;
}
return TRUE;
}
+static AlertValue mimeview_save_all_error_ask(gint n)
+{
+ gchar *message = g_strdup_printf(
+ _("An error has occurred while saving message part #%d. "
+ "Do you want to cancel operation or skip error and "
+ "continue?"), n);
+ AlertValue av = alertpanel_full(_("Error saving all message parts"),
+ message, GTK_STOCK_CANCEL, _("Skip"), _("Skip all"),
+ ALERTFOCUS_FIRST, FALSE, NULL, ALERT_WARNING);
+ g_free(message);
+ return av;
+}
+
+static void mimeview_save_all_info(gint errors, gint total)
+{
+ if (!errors) {
+ gchar *msg = g_strdup_printf(
+ ngettext("%d file saved successfully.",
+ "%d files saved successfully.",
+ total),
+ total);
+ alertpanel_notice("%s", msg);
+ g_free(msg);
+ } else {
+ gchar *msg1 = g_strdup_printf(
+ ngettext("%d file saved successfully",
+ "%d files saved successfully",
+ total - errors),
+ total - errors);
+ gchar *msg2 = g_strdup_printf(
+ ngettext("%s, %d file failed.",
+ "%s, %d files failed.",
+ errors),
+ msg1, errors);
+ alertpanel_warning("%s", msg2);
+ g_free(msg2);
+ g_free(msg1);
+ }
+}
+
/**
* Menu callback: Save all attached files
* \param mimeview Current display
MimeInfo *partinfo;
gchar *dirname;
gchar *startdir = NULL;
- gint number = 1;
+ gint number = 1, errors = 0;
+ gboolean skip_errors = FALSE;
if (!mimeview->opened) return;
if (!mimeview->file) return;
partinfo = mimeview->mimeinfo;
if (prefs_common.attach_save_dir && *prefs_common.attach_save_dir)
- startdir = g_strconcat(prefs_common.attach_save_dir,
- G_DIR_SEPARATOR_S, NULL);
+ startdir = g_strconcat(prefs_common.attach_save_dir, G_DIR_SEPARATOR_S, NULL);
else
startdir = g_strdup(get_home_dir());
}
if (!is_dir_exist (dirname)) {
- alertpanel_error(_("'%s' is not a directory."),
- dirname);
+ alertpanel_error(_("'%s' is not a directory."), dirname);
g_free(startdir);
g_free(dirname);
return;
if (partinfo && partinfo->type == MIMETYPE_TEXT)
partinfo = procmime_mimeinfo_next(partinfo);
}
-
+
while (partinfo != NULL) {
if (partinfo->type != MIMETYPE_MESSAGE &&
partinfo->type != MIMETYPE_MULTIPART &&
(partinfo->disposition != DISPOSITIONTYPE_INLINE
|| get_real_part_name(partinfo) != NULL)) {
- gchar *filename = mimeview_get_filename_for_part
- (partinfo, dirname, number++);
+ gchar *filename = mimeview_get_filename_for_part(
+ partinfo, dirname, number++);
- mimeview_write_part(filename, partinfo);
+ gboolean ok = mimeview_write_part(filename, partinfo, FALSE);
g_free(filename);
+ if (!ok) {
+ ++errors;
+ if (!skip_errors) {
+ AlertValue av = mimeview_save_all_error_ask(number - 1);
+ skip_errors = (av == G_ALERTOTHER);
+ if (av == G_ALERTDEFAULT) /* cancel */
+ break;
+ }
+ }
}
partinfo = procmime_mimeinfo_next(partinfo);
}
prefs_common.attach_save_dir = g_filename_to_utf8(dirname,
-1, NULL, NULL, NULL);
g_free(dirname);
+
+ mimeview_save_all_info(errors, number - 1);
}
static MimeInfo *mimeview_get_part_to_use(MimeView *mimeview)
return;
}
- mimeview_write_part(filename, partinfo);
+ mimeview_write_part(filename, partinfo, TRUE);
filedir = g_path_get_dirname(filename);
if (filedir && strcmp(filedir, ".")) {
g_warning("MIME viewer command-line is invalid: '%s'", cmd);
mimeview_open_part_with(mimeview, partinfo, FALSE);
}
- if (execute_command_line(buf, TRUE) != 0) {
+ if (execute_command_line(buf, TRUE, NULL) != 0) {
if (!prefs_common.save_parts_readwrite)
g_chmod(filename, S_IRUSR|S_IWUSR);
mimeview_open_part_with(mimeview, partinfo, FALSE);
if ((SHGetFileInfo((LPCWSTR)fn16, 0, &file_info, sizeof(SHFILEINFO), SHGFI_EXETYPE)) != 0) {
AlertValue val = alertpanel_full(_("Execute untrusted binary?"),
_("This attachment is an executable file. Executing "
- "untrusted binaries is dangerous and could probably "
- "lead to compromission of your computer.\n\n"
+ "untrusted binaries is dangerous and could compromise "
+ "your computer.\n\n"
"Do you want to run this file?"), GTK_STOCK_CANCEL,
_("Run binary"),
- NULL, FALSE, NULL, ALERT_WARNING, G_ALERTDEFAULT);
+ NULL, ALERTFOCUS_FIRST, FALSE, NULL, ALERT_WARNING);
if (val == G_ALERTALTERNATE) {
debug_print("executing binary\n");
ShellExecute(NULL, L"open", (LPCWSTR)fn16, NULL, NULL, SW_SHOW);
GtkTreePath *path;
MimeInfo *curr = NULL;
- gtk_tree_model_get_iter_first(model, &iter);
+ if (!gtk_tree_model_get_iter_first(model, &iter))
+ return;
path = gtk_tree_model_get_path(model, &iter);
do {
case SIGNATURE_UNCHECKED:
case SIGNATURE_CHECK_FAILED:
case SIGNATURE_CHECK_TIMEOUT:
- pixmap = stock_pixmap_widget_with_overlay(mimeview->mainwin->window, stockp,
+ pixmap = stock_pixmap_widget_with_overlay(stockp,
STOCK_PIXMAP_PRIVACY_EMBLEM_SIGNED, OVERLAY_BOTTOM_RIGHT, 6, 3);
break;
case SIGNATURE_OK:
- pixmap = stock_pixmap_widget_with_overlay(mimeview->mainwin->window, stockp,
+ pixmap = stock_pixmap_widget_with_overlay(stockp,
STOCK_PIXMAP_PRIVACY_EMBLEM_PASSED, OVERLAY_BOTTOM_RIGHT, 6, 3);
break;
case SIGNATURE_WARN:
case SIGNATURE_KEY_EXPIRED:
- pixmap = stock_pixmap_widget_with_overlay(mimeview->mainwin->window, stockp,
+ pixmap = stock_pixmap_widget_with_overlay(stockp,
STOCK_PIXMAP_PRIVACY_EMBLEM_WARN, OVERLAY_BOTTOM_RIGHT, 6, 3);
break;
case SIGNATURE_INVALID:
- pixmap = stock_pixmap_widget_with_overlay(mimeview->mainwin->window, stockp,
+ pixmap = stock_pixmap_widget_with_overlay(stockp,
STOCK_PIXMAP_PRIVACY_EMBLEM_FAILED, OVERLAY_BOTTOM_RIGHT, 6, 3);
break;
}
sigshort = privacy_mimeinfo_sig_info_short(siginfo);
} else if (encrypted != NULL) {
- pixmap = stock_pixmap_widget_with_overlay(mimeview->mainwin->window, stockp,
+ pixmap = stock_pixmap_widget_with_overlay(stockp,
STOCK_PIXMAP_PRIVACY_EMBLEM_ENCRYPTED, OVERLAY_BOTTOM_RIGHT, 6, 3);
} else {
- pixmap = stock_pixmap_widget_with_overlay(mimeview->mainwin->window, stockp, 0,
+ pixmap = stock_pixmap_widget_with_overlay(stockp, 0,
OVERLAY_NONE, 6, 3);
}
gtk_container_add(GTK_CONTAINER(button), pixmap);
g_free(escaped);
}
if (sigshort && *sigshort) {
- tiptmp = g_strjoin("\n", tip, g_markup_escape_text(sigshort, -1), NULL);
+ gchar *sigshort_escaped =
+ g_markup_escape_text(sigshort, -1);
+
+ tiptmp = g_strjoin("\n", tip, sigshort_escaped, NULL);
g_free(tip);
+ g_free(sigshort_escaped);
tip = tiptmp;
}
g_free(sigshort);