diff options
Diffstat (limited to 'mail')
-rw-r--r-- | mail/ChangeLog | 14 | ||||
-rw-r--r-- | mail/mail-display.c | 215 | ||||
-rw-r--r-- | mail/mail-format.c | 81 |
3 files changed, 206 insertions, 104 deletions
diff --git a/mail/ChangeLog b/mail/ChangeLog index 1f90e5416f..a79e1145ff 100644 --- a/mail/ChangeLog +++ b/mail/ChangeLog @@ -1,3 +1,17 @@ +2000-07-26 Dan Winship <danw@helixcode.com> + + * mail-format.c (lookup_handler): Update for OAF and for external + apps as well as components. + (handle_via_external): Handler to set up for data that can be + displayed by an external application. + + * mail-display.c (on_link_clicked, etc): Refactor the save_data() + code and add launch_external() as a handler for + x-evolution-external URLs. + (embeddable_destroy_cb): Remove this, since it seems like it's all + wrong. + (on_object_requested): Update for OAF, and fix some bugs. + 2000-07-25 Jeffrey Stedfast <fejj@helixcode.com> * mail-config.c (get_service_url): Always prepend a leading "/" to diff --git a/mail/mail-display.c b/mail/mail-display.c index c324b7cbc1..a0f6acbbe0 100644 --- a/mail/mail-display.c +++ b/mail/mail-display.c @@ -23,6 +23,7 @@ #include <libgnorba/gnorba.h> #include <bonobo/bonobo-stream-memory.h> #include <libgnomevfs/gnome-vfs-mime-info.h> +#include <libgnomevfs/gnome-vfs-mime-handlers.h> #define PARENT_TYPE (gtk_vbox_get_type ()) @@ -42,28 +43,26 @@ save_data_eexist_cb (int reply, gpointer user_data) gtk_main_quit (); } -static void -save_data_cb (GtkWidget *widget, gpointer user_data) +static gboolean +write_data_to_file (CamelMimePart *part, const char *name, gboolean unique) { - CamelDataWrapper *data = user_data; + CamelDataWrapper *data; CamelStream *stream_fs; - GtkFileSelection *file_select = (GtkFileSelection *) - gtk_widget_get_ancestor (widget, GTK_TYPE_FILE_SELECTION); - char *name; int fd; - name = gtk_file_selection_get_filename (file_select); + g_return_val_if_fail (CAMEL_IS_MIME_PART (part), FALSE); + data = camel_medium_get_content_object (CAMEL_MEDIUM (part)); fd = open (name, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); - if (fd == -1 && errno == EEXIST) { + if (fd == -1 && errno == EEXIST && !unique) { gboolean ok = FALSE; - gnome_ok_cancel_dialog_modal_parented ( + gnome_ok_cancel_dialog_modal ( "A file by that name already exists.\nOverwrite it?", - save_data_eexist_cb, &ok, GTK_WINDOW (file_select)); + save_data_eexist_cb, &ok); gtk_main (); if (!ok) - return; + return FALSE; fd = open (name, O_WRONLY | O_TRUNC); } @@ -72,8 +71,9 @@ save_data_cb (GtkWidget *widget, gpointer user_data) 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; + gnome_error_dialog (msg); + g_free (msg); + return FALSE; } stream_fs = camel_stream_fs_new_with_fd (fd); @@ -81,55 +81,129 @@ save_data_cb (GtkWidget *widget, gpointer user_data) || camel_stream_flush (stream_fs) == -1) { char *msg; - msg = g_strdup_printf ("Could not write data: %s", strerror(errno)); - gnome_error_dialog_parented (msg, GTK_WINDOW (file_select)); + msg = g_strdup_printf ("Could not write data: %s", + strerror (errno)); + gnome_error_dialog (msg); + g_free (msg); + gtk_object_unref (GTK_OBJECT (stream_fs)); + return FALSE; } gtk_object_unref (GTK_OBJECT (stream_fs)); + return TRUE; +} + +static char * +make_safe_filename (const char *prefix, CamelMimePart *part) +{ + GMimeContentField *type; + const char *name; + char *safe, *p; + + type = camel_mime_part_get_content_type (part); + if (type) + name = gmime_content_field_get_parameter (type, "name"); + if (!name) + name = camel_mime_part_get_filename (part); + if (!name) + name = "attachment"; + + p = strrchr (name, '/'); + if (p) + safe = g_strdup_printf ("%s%s", prefix, p); + else + safe = g_strdup_printf ("%s/%s", prefix, name); + + for (p = strrchr (safe, '/') + 1; *p; p++) { + if (!isascii ((unsigned char)*p) || + strchr (" /'\"`&();|<>${}!", *p)) + *p = '_'; + } + + return safe; +} + +CamelMimePart * +part_for_url (const char *url, CamelMimeMessage *message) +{ + GHashTable *urls; + + urls = gtk_object_get_data (GTK_OBJECT (message), "urls"); + g_return_val_if_fail (urls != NULL, NULL); + return g_hash_table_lookup (urls, url); +} + +static void +launch_external (const char *url, CamelMimeMessage *message) +{ + const char *command = url + 21; + char *tmpl, *tmpdir, *filename, *argv[2]; + CamelMimePart *part = part_for_url (url, message); + + tmpl = g_strdup ("/tmp/evolution.XXXXXX"); +#ifdef HAVE_MKDTEMP + tmpdir = mkdtemp (tmpl); +#else + tmpdir = mktemp (tmpl); + if (tmpdir) { + if (mkdir (tmpdir, S_IRWXU) == -1) + tmpdir = NULL; + } +#endif + if (!tmpdir) { + char *msg = g_strdup_printf ("Could not create temporary " + "directory: %s", + g_strerror (errno)); + gnome_error_dialog (msg); + g_free (msg); + return; + } + + filename = make_safe_filename (tmpdir, part); + + if (!write_data_to_file (part, filename, TRUE)) { + g_free (tmpl); + g_free (filename); + return; + } + + argv[0] = (char *)command; + argv[1] = filename; + + gnome_execute_async (tmpdir, 2, argv); + g_free (tmpdir); + g_free (filename); +} + +static void +save_data_cb (GtkWidget *widget, gpointer user_data) +{ + GtkFileSelection *file_select = (GtkFileSelection *) + gtk_widget_get_ancestor (widget, GTK_TYPE_FILE_SELECTION); + + write_data_to_file (user_data, + gtk_file_selection_get_filename (file_select), + FALSE); gtk_widget_destroy (GTK_WIDGET (file_select)); } static void save_data (const char *cid, CamelMimeMessage *message) { - GHashTable *urls; - CamelMimePart *part; - CamelDataWrapper *data; GtkFileSelection *file_select; char *filename; + CamelMimePart *part; - g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message)); - urls = gtk_object_get_data (GTK_OBJECT (message), "urls"); - part = g_hash_table_lookup (urls, cid); - g_return_if_fail (CAMEL_IS_MIME_PART (part)); - data = camel_medium_get_content_object (CAMEL_MEDIUM (part)); - - filename = (char *)camel_mime_part_get_filename (part); - if (filename) { - char *p; - - p = strrchr (filename, '/'); - if (p) - filename = g_strdup_printf ("%s%s", g_get_home_dir(), p); - else { - filename = g_strdup_printf ("%s/%s", g_get_home_dir(), - filename); - } - - for (p = strrchr (filename, '/') + 1; *p; p++) { - if (!isascii ((unsigned char)*p) || - strchr (" /'\"`&();|<>${}!", *p)) - *p = '_'; - } - } else - filename = g_strdup_printf ("%s/attachment", g_get_home_dir()); + part = part_for_url (cid, message); + g_return_if_fail (part != NULL); + filename = make_safe_filename (g_get_home_dir (), part); file_select = GTK_FILE_SELECTION (gtk_file_selection_new ("Save Attachment")); 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), data); + GTK_SIGNAL_FUNC (save_data_cb), part); gtk_signal_connect_object (GTK_OBJECT (file_select->cancel_button), "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), @@ -152,38 +226,12 @@ on_link_clicked (GtkHTML *html, const char *url, gpointer user_data) send_to_url (url); else if (!strncasecmp (url, "cid:", 4)) save_data (url, message); + else if (!strncasecmp (url, "x-evolution-external:", 21)) + launch_external (url, message); else gnome_url_show (url); } -static void -embeddable_destroy_cb (GtkObject *obj, gpointer user_data) -{ - BonoboWidget *be; /* bonobo embeddable */ - BonoboViewFrame *vf; /* the embeddable view frame */ - BonoboObjectClient* server; - CORBA_Environment ev; - - be = BONOBO_WIDGET (obj); - server = bonobo_widget_get_server (be); - - vf = bonobo_widget_get_view_frame (be); - bonobo_control_frame_control_deactivate ( - BONOBO_CONTROL_FRAME (vf)); - /* w = bonobo_control_frame_get_widget (BONOBO_CONTROL_FRAME (vf)); */ - - /* gtk_widget_destroy (w); */ - - CORBA_exception_init (&ev); - Bonobo_Unknown_unref ( - bonobo_object_corba_objref (BONOBO_OBJECT(server)), &ev); - CORBA_Object_release ( - bonobo_object_corba_objref (BONOBO_OBJECT(server)), &ev); - - CORBA_exception_free (&ev); - bonobo_object_unref (BONOBO_OBJECT (vf)); -} - static gboolean on_object_requested (GtkHTML *html, GtkHTMLEmbedded *eb, gpointer data) { @@ -191,7 +239,7 @@ on_object_requested (GtkHTML *html, GtkHTMLEmbedded *eb, gpointer data) GHashTable *urls; CamelMedium *medium; CamelDataWrapper *wrapper; - const char *goad_id; + OAF_ServerInfo *component; GtkWidget *embedded; BonoboObjectClient *server; Bonobo_PersistStream persist; @@ -208,29 +256,20 @@ on_object_requested (GtkHTML *html, GtkHTMLEmbedded *eb, gpointer data) g_return_val_if_fail (CAMEL_IS_MEDIUM (medium), FALSE); wrapper = camel_medium_get_content_object (medium); - goad_id = gnome_vfs_mime_get_value (eb->type, "bonobo-goad-id"); - if (!goad_id) { - char *main_type = - g_strndup (eb->type, strcspn (eb->type, "/")); - - goad_id = gnome_vfs_mime_get_value (main_type, - "bonobo-goad-id"); - g_free (main_type); - } - if (!goad_id) + component = gnome_vfs_mime_get_default_component (eb->type); + if (!component) return FALSE; - embedded = bonobo_widget_new_subdoc (goad_id, NULL); + embedded = bonobo_widget_new_subdoc (component->iid, NULL); + CORBA_free (component); if (!embedded) return FALSE; - gtk_signal_connect (GTK_OBJECT (embedded), "destroy", - embeddable_destroy_cb, NULL); server = bonobo_widget_get_server (BONOBO_WIDGET (embedded)); persist = (Bonobo_PersistStream) bonobo_object_client_query_interface ( server, "IDL:Bonobo/PersistStream:1.0", NULL); if (persist == CORBA_OBJECT_NIL) { - bonobo_object_unref (BONOBO_OBJECT (embedded)); + gtk_object_sink (GTK_OBJECT (embedded)); return FALSE; } @@ -254,7 +293,7 @@ on_object_requested (GtkHTML *html, GtkHTMLEmbedded *eb, gpointer data) CORBA_Object_release (persist, &ev); if (ev._major != CORBA_NO_EXCEPTION) { - bonobo_object_unref (BONOBO_OBJECT (embedded)); + gtk_object_sink (GTK_OBJECT (embedded)); CORBA_exception_free (&ev); return FALSE; } diff --git a/mail/mail-format.c b/mail/mail-format.c index 93049a7aa0..582068042c 100644 --- a/mail/mail-format.c +++ b/mail/mail-format.c @@ -30,6 +30,7 @@ #include "e-util/e-setup.h" /*for evolution_dir*/ #include <libgnome/libgnome.h> #include <libgnomevfs/gnome-vfs-mime-info.h> +#include <libgnomevfs/gnome-vfs-mime-handlers.h> #include <ctype.h> /* for isprint */ #include <string.h> /* for strstr */ @@ -84,6 +85,9 @@ static gboolean handle_unknown_type (CamelMimePart *part, static gboolean handle_via_bonobo (CamelMimePart *part, const char *mime_type, struct mail_format_data *mfd); +static gboolean handle_via_external (CamelMimePart *part, + const char *mime_type, + struct mail_format_data *mfd); /* writes the header info for a mime message into an html stream */ static void write_headers (CamelMimeMessage *message, @@ -229,8 +233,8 @@ static mime_handler_fn lookup_handler (const char *mime_type, gboolean *generic) { mime_handler_fn handler_function; - const char *whole_goad_id, *generic_goad_id; char *mime_type_main; + GnomeVFSMimeAction *action; if (mime_function_table == NULL) setup_function_table (); @@ -242,10 +246,10 @@ lookup_handler (const char *mime_type, gboolean *generic) /* OK. There are 6 possibilities, which we try in this order: * 1) full match in the main table * 2) partial match in the main table - * 3) full match in bonobo + * 3) full match in gnome_vfs_mime_* * 4) full match in the fallback table * 5) partial match in the fallback table - * 6) partial match in bonobo + * 6) partial match in gnome_vfs_mime_* * * Of these, 1-4 are considered exact matches, and 5 and 6 are * considered generic. @@ -271,20 +275,24 @@ lookup_handler (const char *mime_type, gboolean *generic) return handler_function; } - whole_goad_id = gnome_vfs_mime_get_value (mime_type, "bonobo-goad-id"); - generic_goad_id = gnome_vfs_mime_get_value (mime_type_main, - "bonobo-goad-id"); +/* FIXME: Remove this #ifdef after gnome-vfs 0.3 is released */ +#ifdef HAVE_GNOME_VFS_MIME_GET_DEFAULT_ACTION_WITHOUT_FALLBACK + action = gnome_vfs_mime_get_default_action_without_fallback (mime_type); + if (action) { + if (action->action_type == GNOME_VFS_MIME_ACTION_TYPE_COMPONENT) + handler_function = handle_via_bonobo; + else + handler_function = handle_via_external; - if (whole_goad_id && (!generic_goad_id || - strcmp (whole_goad_id, generic_goad_id) != 0)) { /* Optimize this for the next time through. */ g_hash_table_insert (mime_function_table, - g_strdup (mime_type), - handle_via_bonobo); + g_strdup (mime_type), handler_function); g_free (mime_type_main); + gnome_vfs_mime_action_free (action); *generic = FALSE; - return handle_via_bonobo; + return handler_function; } +#endif handler_function = g_hash_table_lookup (mime_fallback_table, mime_type); @@ -293,8 +301,17 @@ lookup_handler (const char *mime_type, gboolean *generic) else { handler_function = g_hash_table_lookup (mime_fallback_table, mime_type_main); - if (!handler_function && generic_goad_id) - handler_function = handle_via_bonobo; + if (!handler_function) { + action = gnome_vfs_mime_get_default_action (mime_type_main); + if (action) { + if (action->action_type == + GNOME_VFS_MIME_ACTION_TYPE_COMPONENT) + handler_function = handle_via_bonobo; + else + handler_function = handle_via_external; + gnome_vfs_mime_action_free (action); + } + } *generic = TRUE; } @@ -902,14 +919,19 @@ static const char * get_url_for_icon (const char *icon_name, struct mail_format_data *mfd) { static GHashTable *icons; - char *icon_path = gnome_pixmap_file (icon_name), buf[1024], *url; + char *icon_path, buf[1024], *url; GByteArray *ba; if (!icons) icons = g_hash_table_new (g_str_hash, g_str_equal); - if (!icon_path) - return "file:///dev/null"; + if (*icon_name == '/') + icon_path = g_strdup (icon_name); + else { + icon_path = gnome_pixmap_file (icon_name); + if (!icon_path) + return "file:///dev/null"; + } ba = g_hash_table_lookup (icons, icon_path); if (!ba) { @@ -1215,6 +1237,33 @@ handle_via_bonobo (CamelMimePart *part, const char *mime_type, return TRUE; } +static gboolean +handle_via_external (CamelMimePart *part, const char *mime_type, + struct mail_format_data *mfd) +{ + GnomeVFSMimeApplication *app; + const char *desc, *icon; + char *action, *url; + + app = gnome_vfs_mime_get_default_application (mime_type); + g_return_val_if_fail (app != NULL, FALSE); + + desc = gnome_vfs_mime_get_value (mime_type, "description"); + icon = gnome_vfs_mime_get_value (mime_type, "icon-filename"); + if (!icon) + icon = "gnome-unknown.png"; + action = g_strdup_printf ("open the file in %s", app->name); + url = g_strdup_printf ("x-evolution-external:%s", app->command); + g_hash_table_insert (mfd->urls, url, part); + + handle_mystery (part, mfd, url, icon, desc, action); + + g_free (action); + + return TRUE; +} + + static char * reply_body (CamelDataWrapper *data, gboolean want_plain, gboolean *is_html) { |