aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mail/em-utils.c239
-rw-r--r--mail/em-utils.h3
-rw-r--r--plugins/itip-formatter/itip-formatter.c42
-rw-r--r--plugins/mail-to-task/mail-to-task.c161
4 files changed, 147 insertions, 298 deletions
diff --git a/mail/em-utils.c b/mail/em-utils.c
index 0e9742d8ab..0eab5f6fac 100644
--- a/mail/em-utils.c
+++ b/mail/em-utils.c
@@ -345,245 +345,6 @@ em_filename_make_safe (gchar *string)
/* Saving messages... */
-static const gchar *
-emu_save_get_filename_for_part (CamelMimePart *part)
-{
- const gchar *filename;
-
- filename = camel_mime_part_get_filename (part);
- if (filename == NULL) {
- if (CAMEL_IS_MIME_MESSAGE (part)) {
- filename = camel_mime_message_get_subject (
- CAMEL_MIME_MESSAGE (part));
- if (filename == NULL)
- filename = _("message");
- } else
- filename = _("attachment");
- }
-
- return filename;
-}
-
-/**
- * em_utils_save_part:
- * @parent: parent window
- * @prompt: prompt string
- * @part: part to save
- *
- * Saves a mime part to disk (prompting the user for filename).
- **/
-void
-em_utils_save_part (GtkWindow *parent, const gchar *prompt, CamelMimePart *part)
-{
- GtkWidget *file_chooser;
- const gchar *utf8_filename;
- gchar *uri = NULL, *filename;
-
- g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
-
- utf8_filename = emu_save_get_filename_for_part (part);
- filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
- em_filename_make_safe (filename);
-
- file_chooser = e_file_get_save_filesel (
- parent, prompt, filename, GTK_FILE_CHOOSER_ACTION_SAVE);
-
- if (gtk_dialog_run (GTK_DIALOG (file_chooser)) != GTK_RESPONSE_OK)
- goto exit;
-
- uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (file_chooser));
-
- /* XXX Would be nice to mention _why_ we can't save. */
- if (!e_file_can_save (GTK_WINDOW (file_chooser), uri)) {
- g_warning ("Unable to save %s", uri);
- goto exit;
- }
-
- e_file_update_save_path (
- gtk_file_chooser_get_current_folder_uri (
- GTK_FILE_CHOOSER (file_chooser)), TRUE);
-
- mail_save_part (part, uri, NULL, NULL, FALSE);
-
-exit:
- gtk_widget_destroy (file_chooser);
- g_free (uri);
- g_free (filename);
-}
-
-/* It "assigns" to each part its unique file name, based on the appearance.
- parts contains CamelMimePart, returned value contains gchar *, in same
- order as parts; resulting list should free data and GSList itself as well.
-*/
-static GSList *
-get_unique_file_names (GSList *parts)
-{
- GSList *iter;
- GSList *file_names = NULL;
-
- if (!parts)
- return NULL;
-
- for (iter = parts; iter != NULL; iter = iter->next) {
- CamelMimePart *part = iter->data;
- const gchar *utf8_filename;
- gchar *filename;
-
- utf8_filename = emu_save_get_filename_for_part (part);
- filename = g_filename_from_utf8 (utf8_filename, -1, NULL, NULL, NULL);
- em_filename_make_safe (filename);
-
- file_names = g_slist_prepend (file_names, filename);
- }
-
- if (file_names) {
- GSList *sorted_file_names;
- gint counter = 1;
- const gchar *last;
- GCompareFunc cmp_func = (GCompareFunc) strcmp;
-
- #ifdef G_OS_WIN32
- cmp_func = (GCompareFunc) g_ascii_strcasecmp;
- #endif
-
- /* we prepended, so reverse to make right order */
- file_names = g_slist_reverse (file_names);
-
- sorted_file_names = g_slist_sort (g_slist_copy (file_names), cmp_func);
- last = sorted_file_names->data;
- for (iter = sorted_file_names->next; iter; iter = iter->next) {
- gchar *name = iter->data;
-
- if (name && last && cmp_func (name, last) == 0) {
- gchar *new_name;
- gchar *p = strrchr (name, '.');
- GSList *i2;
-
- /* if we have an extension, then place number before it (at p is ".ext"),
- otherwise just append number in brackets */
- if (p)
- new_name = g_strdup_printf ("%.*s(%d)%s", (gint) (p - name), name, counter, p);
- else
- new_name = g_strdup_printf ("%s(%d)", name, counter);
-
- /* we need to find the proper item in unsorted list and replace with new name;
- we should always find that item, so no check for leaks */
- for (i2 = file_names; i2; i2 = i2->next) {
- if (i2->data == name) {
- g_free (name);
- i2->data = new_name;
- break;
- }
- }
-
- counter++;
- } else {
- last = name;
- counter = 1;
- }
- }
-
- g_slist_free (sorted_file_names);
- }
-
- return file_names;
-}
-
-void
-em_utils_save_parts (GtkWindow *parent, const gchar *prompt, GSList *parts)
-{
- GtkWidget *file_chooser;
- gchar *path_uri;
- GSList *iter, *file_names, *iter_file;
-
- g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent));
-
- file_chooser = e_file_get_save_filesel (
- parent, prompt, NULL, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
-
- if (gtk_dialog_run (GTK_DIALOG (file_chooser)) != GTK_RESPONSE_OK)
- goto exit;
-
- path_uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (file_chooser));
-
- e_file_update_save_path (path_uri, FALSE);
-
- file_names = get_unique_file_names (parts);
-
- for (iter = parts, iter_file = file_names; iter && iter_file; iter = iter->next, iter_file = iter_file->next) {
- CamelMimePart *part = iter->data;
- gchar *uri, *filename;
-
- filename = iter_file->data;
- uri = g_build_path ("/", path_uri, filename, NULL);
- g_free (filename);
- iter_file->data = NULL;
-
- /* XXX Would be nice to mention _why_ we can't save. */
- if (e_file_can_save (GTK_WINDOW (file_chooser), uri))
- mail_save_part (part, uri, NULL, NULL, FALSE);
- else
- g_warning ("Unable to save %s", uri);
-
- g_free (uri);
- }
-
- g_slist_free (file_names);
- g_free (path_uri);
-
-exit:
- gtk_widget_destroy (file_chooser);
-}
-
-/**
- * em_utils_save_part_to_file:
- * @parent: parent window
- * @filename: filename to save to
- * @part: part to save
- *
- * Save a part's content to a specific file
- * Creates all needed directories and overwrites without prompting
- *
- * Returns %TRUE if saving succeeded, %FALSE otherwise
- **/
-gboolean
-em_utils_save_part_to_file(GtkWindow *parent, const gchar *filename, CamelMimePart *part)
-{
- gint done;
- gchar *dirname;
- struct stat st;
-
- if (filename[0] == 0)
- return FALSE;
-
- dirname = g_path_get_dirname(filename);
- if (g_mkdir_with_parents(dirname, 0777) == -1) {
- GtkWidget *w = e_error_new(parent, "mail:no-create-path", filename, g_strerror(errno), NULL);
- g_free(dirname);
- em_utils_show_error_silent (w);
- return FALSE;
- }
- g_free(dirname);
-
- if (g_access(filename, F_OK) == 0) {
- if (g_access(filename, W_OK) != 0) {
- e_error_run(parent, E_ERROR_ASK_FILE_EXISTS_OVERWRITE, filename, NULL);
- return FALSE;
- }
- }
-
- if (g_stat(filename, &st) != -1 && !S_ISREG(st.st_mode)) {
- GtkWidget *w = e_error_new(parent, "mail:no-write-path-notfile", filename, NULL);
- em_utils_show_error_silent (w);
- return FALSE;
- }
-
- /* FIXME: This doesn't handle default charsets */
- mail_msg_wait(mail_save_part(part, filename, emu_save_part_done, &done, FALSE));
-
- return done;
-}
-
struct _save_messages_data {
CamelFolder *folder;
GPtrArray *uids;
diff --git a/mail/em-utils.h b/mail/em-utils.h
index 79caba050e..9bb35b1dc2 100644
--- a/mail/em-utils.h
+++ b/mail/em-utils.h
@@ -52,8 +52,6 @@ void em_utils_edit_filters (GtkWidget *parent);
void em_filename_make_safe (gchar *string);
void em_utils_edit_vfolders (GtkWidget *parent);
-void em_utils_save_part(GtkWindow *parent, const gchar *prompt, CamelMimePart *part);
-gboolean em_utils_save_part_to_file(GtkWindow *parent, const gchar *filename, CamelMimePart *part);
void em_utils_save_messages (GtkWindow *parent, CamelFolder *folder, GPtrArray *uids);
void em_utils_flag_for_followup (EMailReader *reader, CamelFolder *folder, GPtrArray *uids);
@@ -72,7 +70,6 @@ void em_utils_selection_set_urilist(GtkSelectionData *data, CamelFolder *folder,
void em_utils_selection_get_urilist(GtkSelectionData *data, CamelFolder *folder);
gchar *em_utils_temp_save_part(GtkWidget *parent, CamelMimePart *part, gboolean mode);
-void em_utils_save_parts (GtkWindow *parent, const gchar *prompt, GSList * parts);
gboolean em_utils_folder_is_drafts(CamelFolder *folder, const gchar *uri);
gboolean em_utils_folder_is_templates(CamelFolder *folder, const gchar *uri);
diff --git a/plugins/itip-formatter/itip-formatter.c b/plugins/itip-formatter/itip-formatter.c
index 8ed7a51b37..658acc07dc 100644
--- a/plugins/itip-formatter/itip-formatter.c
+++ b/plugins/itip-formatter/itip-formatter.c
@@ -57,7 +57,9 @@
#include <calendar/gui/itip-utils.h>
#include <calendar/common/authentication.h>
#include <shell/e-shell.h>
+#include <shell/e-shell-utils.h>
#include "itip-view.h"
+#include <misc/e-attachment.h>
#define CLASSID "itip://"
#define GCONF_KEY_DELETE "/apps/evolution/itip/delete_processed"
@@ -1474,18 +1476,54 @@ get_next (icalcompiter *iter)
}
static void
+attachment_load_finish (EAttachment *attachment,
+ GAsyncResult *result,
+ GFile *file)
+{
+ EShell *shell;
+ GtkWindow *parent;
+
+ /* XXX Theoretically, this should never fail. */
+ e_attachment_load_finish (attachment, result, NULL);
+
+ shell = e_shell_get_default ();
+ parent = e_shell_get_active_window (shell);
+
+ e_attachment_save_async (
+ attachment, file, (GAsyncReadyCallback)
+ e_attachment_save_handle_error, parent);
+
+ g_object_unref (file);
+}
+
+static void
save_vcalendar_cb (GtkWidget *button, struct _itip_puri *pitip)
{
+ EAttachment *attachment;
+ EShell *shell;
+ GFile *file;
+
g_return_if_fail (pitip != NULL);
g_return_if_fail (pitip->vcalendar != NULL);
g_return_if_fail (pitip->part != NULL);
+ shell = e_shell_get_default ();
+ file = e_shell_run_save_dialog (
+ shell, _("Save Calendar"), NULL, NULL);
+ if (file == NULL)
+ return;
+
if (!camel_mime_part_get_filename (pitip->part)) {
- /* To Translators: This is a default file name when saving calendar part */
+ /* Translators: This is a default filename for a calendar. */
camel_mime_part_set_filename (pitip->part, _("calendar.ics"));
}
- em_utils_save_part (GTK_WINDOW (gtk_widget_get_toplevel (button)), _("Save calendar"), pitip->part);
+ attachment = e_attachment_new ();
+ e_attachment_set_mime_part (attachment, pitip->part);
+
+ e_attachment_load_async (
+ attachment, (GAsyncReadyCallback)
+ attachment_load_finish, file);
}
static GtkWidget *
diff --git a/plugins/mail-to-task/mail-to-task.c b/plugins/mail-to-task/mail-to-task.c
index 1c8be4538a..5c373d86c1 100644
--- a/plugins/mail-to-task/mail-to-task.c
+++ b/plugins/mail-to-task/mail-to-task.c
@@ -57,6 +57,7 @@
#include <shell/e-shell-view.h>
#include <shell/e-shell-window-actions.h>
#include <calendar/gui/cal-editor-utils.h>
+#include <misc/e-attachment-store.h>
#define E_SHELL_WINDOW_ACTION_CONVERT_TO_EVENT(window) \
E_SHELL_WINDOW_ACTION ((window), "mail-convert-to-event")
@@ -72,26 +73,6 @@ gboolean mail_browser_init (GtkUIManager *ui_manager,
gboolean mail_shell_view_init (GtkUIManager *ui_manager,
EShellView *shell_view);
-static gchar *
-clean_name(const guchar *s)
-{
- GString *out = g_string_new("");
- guint32 c;
- gchar *r;
-
- while ((c = camel_utf8_getc ((const guchar **)&s)))
- {
- if (!g_unichar_isprint (c) || ( c < 0x7f && strchr (" /'\"`&();|<>$%{}!", c )))
- c = '_';
- g_string_append_u (out, c);
- }
-
- r = g_strdup (out->str);
- g_string_free (out, TRUE);
-
- return r;
-}
-
static void
set_attendees (ECalComponent *comp, CamelMimeMessage *message, const gchar *organizer)
{
@@ -281,61 +262,133 @@ set_organizer (ECalComponent *comp)
}
static void
+attachment_load_finished (EAttachment *attachment,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ struct {
+ gchar **uris;
+ gboolean done;
+ } *status = user_data;
+
+ /* XXX Should be no need to check for error here.
+ * This is just to reset state in the EAttachment. */
+ e_attachment_load_finish (attachment, result, NULL);
+
+ status->done = TRUE;
+}
+
+static void
+attachment_save_finished (EAttachmentStore *store,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ gchar **uris;
+
+ struct {
+ gchar **uris;
+ gboolean done;
+ } *status = user_data;
+
+ /* XXX Add some error handling here! */
+ uris = e_attachment_store_save_finish (store, result, NULL);
+
+ status->uris = uris;
+ status->done = TRUE;
+}
+
+static void
set_attachments (ECal *client, ECalComponent *comp, CamelMimeMessage *message)
{
- gint parts, i;
- GSList *list = NULL;
- const gchar *uid;
- const gchar *store_uri;
- gchar *store_dir;
+ /* XXX Much of this is copied from CompEditor::get_attachment_list().
+ * Perhaps it should be split off as a separate utility? */
+
+ EAttachmentStore *store;
CamelDataWrapper *content;
+ CamelMultipart *multipart;
+ GFile *destination;
+ GSList *list = NULL;
+ const gchar *comp_uid = NULL;
+ const gchar *local_store;
+ gint ii, n_parts;
+ gchar *uri;
+
+ struct {
+ gchar **uris;
+ gboolean done;
+ } status;
content = camel_medium_get_content_object ((CamelMedium *) message);
if (!content || !CAMEL_IS_MULTIPART (content))
return;
- parts = camel_multipart_get_number (CAMEL_MULTIPART (content));
- if (parts < 1)
+ n_parts = camel_multipart_get_number (CAMEL_MULTIPART (content));
+ if (n_parts < 1)
return;
- e_cal_component_get_uid (comp, &uid);
- store_uri = e_cal_get_local_attachment_store (client);
- if (!store_uri)
- return;
- store_dir = g_filename_from_uri (store_uri, NULL, NULL);
+ e_cal_component_get_uid (comp, &comp_uid);
+ local_store = e_cal_get_local_attachment_store (client);
+ uri = g_build_path ("/", local_store, comp_uid, NULL);
+ destination = g_file_new_for_uri (uri);
+ g_free (uri);
+
+ /* Create EAttachments from the MIME parts and add them to the
+ * attachment store. */
- for (i = 1; i < parts; i++)
- {
- gchar *filename, *path, *tmp;
- const gchar *orig_filename;
+ multipart = CAMEL_MULTIPART (content);
+ store = E_ATTACHMENT_STORE (e_attachment_store_new ());
+
+ for (ii = 1; ii < n_parts; ii++) {
CamelMimePart *mime_part;
+ EAttachment *attachment;
- mime_part = camel_multipart_get_part (CAMEL_MULTIPART (content), i);
+ status.done = FALSE;
- orig_filename = camel_mime_part_get_filename (mime_part);
- if (!orig_filename)
- continue;
+ attachment = e_attachment_new ();
+ mime_part = camel_multipart_get_part (multipart, ii);
+ e_attachment_set_mime_part (attachment, mime_part);
- tmp = clean_name ((const guchar *)orig_filename);
- filename = g_strdup_printf ("%s-%s", uid, tmp);
- path = g_build_filename (store_dir, filename, NULL);
+ e_attachment_load_async (
+ attachment, (GAsyncReadyCallback)
+ attachment_load_finished, &status);
- if (em_utils_save_part_to_file (NULL, path, mime_part))
- {
- gchar *uri;
- uri = g_filename_to_uri (path, NULL, NULL);
- list = g_slist_append (list, g_strdup (uri));
- g_free (uri);
- }
+ /* Loading should be instantaneous since we already have
+ * the full content, but we still have to crank the main
+ * loop until the callback gets triggered. */
+ while (!status.done)
+ gtk_main_iteration ();
- g_free (tmp);
- g_free (filename);
- g_free (path);
+ e_attachment_store_add_attachment (store, attachment);
+ g_object_unref (attachment);
}
- g_free (store_dir);
+ status.uris = NULL;
+ status.done = FALSE;
+
+ e_attachment_store_save_async (
+ store, destination, (GAsyncReadyCallback)
+ attachment_save_finished, &status);
+
+ /* We can't return until we have results, so crank
+ * the main loop until the callback gets triggered. */
+ while (!status.done)
+ gtk_main_iteration ();
+
+ g_return_if_fail (status.uris != NULL);
+ /* Transfer the URI strings to the GSList. */
+ for (ii = 0; status.uris[ii] != NULL; ii++) {
+ list = g_slist_prepend (list, status.uris[ii]);
+ status.uris[ii] = NULL;
+ }
+
+ g_free (status.uris);
+
+ /* XXX Does this take ownership of the list? */
e_cal_component_set_attachment_list (comp, list);
+
+ g_object_unref (destination);
+ g_object_unref (store);
}
static void