From d77a77c7e5d0d3aa9a8363a6a1ab7bfdd8235041 Mon Sep 17 00:00:00 2001 From: Dan Winship Date: Sat, 29 Apr 2000 21:28:00 +0000 Subject: Handle clicks on "cid" URLs by popping up a "Save Attachment" dialog. * mail-display.c (on_link_clicked): Handle clicks on "cid" URLs by popping up a "Save Attachment" dialog. * mail-format.c (get_cid): if the part has a Content-Disposition with a filename specified, record (a sanitized version of) that on the wrapper when creating the cid reference, so the "save attachment" code can use it later. (handle_mystery): fix a bug in the cid generation here. svn path=/trunk/; revision=2685 --- mail/ChangeLog | 11 +++++++ mail/mail-display.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++ mail/mail-format.c | 26 ++++++++++++++- 3 files changed, 127 insertions(+), 1 deletion(-) (limited to 'mail') diff --git a/mail/ChangeLog b/mail/ChangeLog index 50b7d6c11a..aae11b2708 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,14 @@ +2000-04-29 Dan Winship + + * mail-display.c (on_link_clicked): Handle clicks on "cid" URLs by + popping up a "Save Attachment" dialog. + + * mail-format.c (get_cid): if the part has a Content-Disposition + with a filename specified, record (a sanitized version of) that on + the wrapper when creating the cid reference, so the "save + attachment" code can use it later. + (handle_mystery): fix a bug in the cid generation here. + 2000-04-29 Dan Winship * mail-format.c (lookup_handler, etc): Improve the builtin vs diff --git a/mail/mail-display.c b/mail/mail-display.c index 448426d70c..9605456935 100644 --- a/mail/mail-display.c +++ b/mail/mail-display.c @@ -9,7 +9,10 @@ * (C) 2000 Helix Code, Inc. */ #include +#include +#include #include +#include "e-util/e-setup.h" #include "e-util/e-util.h" #include "mail-display.h" #include "mail-format.h" @@ -24,6 +27,92 @@ static GtkObjectClass *mail_display_parent_class; * Callbacks *----------------------------------------------------------------------*/ +static void +save_data_eexist_cb (int reply, gpointer user_data) +{ + gboolean *ok = user_data; + + *ok = reply == 0; + gtk_main_quit (); +} + +static void +save_data_cb (GtkWidget *widget, gpointer user_data) +{ + CamelStream *output = CAMEL_STREAM (user_data); + GtkFileSelection *file_select = (GtkFileSelection *) + gtk_widget_get_ancestor (widget, GTK_TYPE_FILE_SELECTION); + char *name, buf[1024]; + int fd, nread; + + name = gtk_file_selection_get_filename (file_select); + + fd = open (name, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); + if (fd == -1 && errno == EEXIST) { + gboolean ok = FALSE; + + gnome_ok_cancel_dialog_modal_parented ( + "A file by that name already exists.\nOverwrite it?", + save_data_eexist_cb, &ok, GTK_WINDOW (file_select)); + gtk_main (); + if (!ok) + return; + fd = open (name, O_WRONLY | O_TRUNC); + } + + if (fd == -1) { + char *msg; + + msg = g_strdup_printf ("Could not open file %s:\n%s", + name, g_strerror (errno)); + gnome_error_dialog_parented (msg, GTK_WINDOW (file_select)); + return; + } + + camel_stream_reset (output); + do { + nread = camel_stream_read (output, buf, sizeof (buf)); + if (nread > 0) + write (fd, buf, nread); + } while (!camel_stream_eos (output)); + close (fd); + + gtk_widget_destroy (GTK_WIDGET (file_select)); +} + +static void +save_data (const char *cid, CamelMimeMessage *message) +{ + CamelDataWrapper *data; + CamelStream *output; + GtkFileSelection *file_select; + char *filename; + + g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message)); + data = gtk_object_get_data (GTK_OBJECT (message), cid); + g_return_if_fail (CAMEL_IS_DATA_WRAPPER (data)); + output = camel_data_wrapper_get_output_stream (data); + g_return_if_fail (CAMEL_IS_STREAM (output)); + + file_select = GTK_FILE_SELECTION (gtk_file_selection_new ("Save Attachment")); + filename = gtk_object_get_data (GTK_OBJECT (data), "filename"); + if (filename) + filename = g_strdup_printf ("%s/%s", evolution_dir, filename); + else + filename = g_strdup_printf ("%s/attachment", evolution_dir); + gtk_file_selection_set_filename (file_select, filename); + g_free (filename); + + gtk_signal_connect (GTK_OBJECT (file_select->ok_button), "clicked", + GTK_SIGNAL_FUNC (save_data_cb), output); + gtk_signal_connect_object (GTK_OBJECT (file_select->cancel_button), + "clicked", + GTK_SIGNAL_FUNC (gtk_widget_destroy), + GTK_OBJECT (file_select)); + + gtk_widget_show (GTK_WIDGET (file_select)); +} + static void on_link_clicked (GtkHTML *html, const char *url, gpointer user_data) { @@ -32,6 +121,8 @@ on_link_clicked (GtkHTML *html, const char *url, gpointer user_data) g_warning ("Can't handle news URLs yet."); else if (!strncasecmp (url, "mailto:", 7)) send_to_url (url); + else if (!strncasecmp (url, "cid:", 4)) + save_data (url + 4, user_data); else gnome_url_show (url); } diff --git a/mail/mail-format.c b/mail/mail-format.c index d10b74612b..6997f96158 100644 --- a/mail/mail-format.c +++ b/mail/mail-format.c @@ -115,6 +115,7 @@ get_cid (CamelMimePart *part, CamelMimeMessage *root) CamelDataWrapper *wrapper = camel_medium_get_content_object (CAMEL_MEDIUM (part)); char *cid; + const char *filename; /* If we have a real Content-ID, use it. If we don't, * make a (syntactically invalid) fake one. @@ -125,6 +126,29 @@ get_cid (CamelMimePart *part, CamelMimeMessage *root) cid = g_strdup_printf ("@@@%p", wrapper); gtk_object_set_data (GTK_OBJECT (root), cid, wrapper); + + /* Record the filename, in case the user wants to save this + * data later. + */ + filename = camel_mime_part_get_filename (part); + if (filename) { + char *safe, *p; + + safe = strrchr (filename, '/'); + if (safe) + safe = g_strdup (safe + 1); + else + safe = g_strdup (filename); + + for (p = safe; *p; p++) { + if (!isascii ((unsigned char)*p) || + strchr (" /'\"`&();|<>${}!", *p)) + *p = '_'; + } + + gtk_object_set_data (GTK_OBJECT (wrapper), "filename", safe); + } + return cid; } @@ -858,7 +882,7 @@ handle_mystery (CamelMimePart *part, CamelMimeMessage *root, GtkBox *box, GMimeContentField *content_type; mail_html_new (&html, &stream, root, TRUE); - mail_html_write (html, stream, "
" + mail_html_write (html, stream, "" "
" "%s
", get_cid (part, root), icon_name, id); -- cgit v1.2.3