aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mail/ChangeLog11
-rw-r--r--mail/mail-display.c91
-rw-r--r--mail/mail-format.c26
3 files changed, 127 insertions, 1 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog
index 50b7d6c11a..aae11b2708 100644
--- a/mail/ChangeLog
+++ b/mail/ChangeLog
@@ -1,5 +1,16 @@
2000-04-29 Dan Winship <danw@helixcode.com>
+ * 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 <danw@helixcode.com>
+
* mail-format.c (lookup_handler, etc): Improve the builtin vs
bonobo selection code.
(handle_mystery): Include name and Content-Description in the
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 <config.h>
+#include <sys/stat.h>
+#include <fcntl.h>
#include <gnome.h>
+#include "e-util/e-setup.h"
#include "e-util/e-util.h"
#include "mail-display.h"
#include "mail-format.h"
@@ -25,6 +28,92 @@ static GtkObjectClass *mail_display_parent_class;
*----------------------------------------------------------------------*/
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)
{
if (!strncasecmp (url, "news:", 5) ||
@@ -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, "<table><tr><td><a href=\"cid:%p\">"
+ mail_html_write (html, stream, "<table><tr><td><a href=\"cid:%s\">"
"<img src=\"x-gnome-icon:%s\"></a></td>"
"<td>%s<br>", get_cid (part, root), icon_name, id);