SHA256
1
0
forked from pool/evolution
evolution/evolution-gnome-autoar.patch

650 lines
21 KiB
Diff

From b5681c51321045e0a509e5b656301e1032d8c4aa Mon Sep 17 00:00:00 2001
From: Razvan Chitu <razvan.ch95@gmail.com>
Date: Fri, 26 Aug 2016 14:55:12 +0300
Subject: Fix archives support in attachments
The API of gnome-autoar was recently modified so compression and extraction
were no longer working. Replace autoar preferences objects with two shell
settings. Save memory file to disk before extracting it. Handle generation of
unique file names internally.
https://bugzilla.gnome.org/show_bug.cgi?id=770380
---
configure.ac | 4 +-
data/org.gnome.evolution.shell.gschema.xml.in | 10 +
e-util/e-attachment-store.c | 78 +++----
e-util/e-attachment.c | 280 +++++++++++++++++++-------
4 files changed, 254 insertions(+), 118 deletions(-)
diff --git a/configure.ac b/configure.ac
index a1ba2c0..a841591 100644
--- a/configure.ac
+++ b/configure.ac
@@ -368,8 +368,8 @@ AC_ARG_ENABLE([autoar],
if test x"$enable_autoar" = xyes; then
PKG_CHECK_MODULES(
[AUTOAR],
- [gnome-autoar >= gnome_autoar_minimum_version
- gnome-autoar-gtk >= gnome_autoar_minimum_version],,
+ [gnome-autoar-0 >= gnome_autoar_minimum_version
+ gnome-autoar-gtk-0 >= gnome_autoar_minimum_version],,
[AC_MSG_ERROR([
gnome-autoar or gnome-autoar-gtk not found
diff --git a/data/org.gnome.evolution.shell.gschema.xml.in b/data/org.gnome.evolution.shell.gschema.xml.in
index 18ece74..02a5a18 100644
--- a/data/org.gnome.evolution.shell.gschema.xml.in
+++ b/data/org.gnome.evolution.shell.gschema.xml.in
@@ -15,6 +15,16 @@
<_summary>Initial file chooser folder</_summary>
<_description>Initial folder for GtkFileChooser dialogs.</_description>
</key>
+ <key name="autoar-format" type="s">
+ <default>''</default>
+ <_summary>Compression format used by autoar</_summary>
+ <_description>Compression format used when compressing attached directories with autoar.</_description>
+ </key>
+ <key name="autoar-filter" type="s">
+ <default>''</default>
+ <_summary>Compression filter used by autoar</_summary>
+ <_description>Compression filter used when compressing attached directories with autoar.</_description>
+ </key>
<key name="start-offline" type="b">
<default>false</default>
<_summary>Start in offline mode</_summary>
diff --git a/e-util/e-attachment-store.c b/e-util/e-attachment-store.c
index 85fa19a..05e4809 100644
--- a/e-util/e-attachment-store.c
+++ b/e-util/e-attachment-store.c
@@ -29,7 +29,7 @@
#include <glib/gi18n.h>
#ifdef HAVE_AUTOAR
-#include <gnome-autoar/autoar.h>
+#include <gnome-autoar/gnome-autoar.h>
#include <gnome-autoar/autoar-gtk.h>
#endif
@@ -648,8 +648,10 @@ e_attachment_store_run_load_dialog (EAttachmentStore *store,
#ifdef HAVE_AUTOAR
GSettings *settings;
- AutoarPref *arpref;
- gint format, filter;
+ char *format_string;
+ char *filter_string;
+ gint format;
+ gint filter;
#endif
g_return_if_fail (E_IS_ATTACHMENT_STORE (store));
@@ -699,14 +701,23 @@ e_attachment_store_run_load_dialog (EAttachmentStore *store,
option_format_box = GTK_BOX (option_format_box_widget);
gtk_box_pack_start (extra_box, option_format_box_widget, FALSE, FALSE, 0);
- settings = e_util_ref_settings (AUTOAR_PREF_DEFAULT_GSCHEMA_ID);
- arpref = autoar_pref_new_with_gsettings (settings);
+ settings = e_util_ref_settings ("org.gnome.evolution.shell");
+
+ format_string = g_settings_get_string (settings, "autoar-format");
+ filter_string = g_settings_get_string (settings, "autoar-filter");
+
+ if (!e_enum_from_string (AUTOAR_TYPE_FORMAT, format_string, &format)) {
+ format = AUTOAR_FORMAT_ZIP;
+ }
+ if (!e_enum_from_string (AUTOAR_TYPE_FILTER, filter_string, &filter)) {
+ filter = AUTOAR_FILTER_NONE;
+ }
option_format_label = gtk_label_new (
_("Archive selected directories using this format:"));
option_format_combo = autoar_gtk_chooser_simple_new (
- autoar_pref_get_default_format (arpref),
- autoar_pref_get_default_filter (arpref));
+ format,
+ filter);
gtk_box_pack_start (option_format_box, option_format_label, FALSE, FALSE, 0);
gtk_box_pack_start (option_format_box, option_format_combo, FALSE, FALSE, 0);
#endif
@@ -729,8 +740,23 @@ e_attachment_store_run_load_dialog (EAttachmentStore *store,
#ifdef HAVE_AUTOAR
autoar_gtk_chooser_simple_get (option_format_combo, &format, &filter);
- autoar_pref_set_default_format (arpref, format);
- autoar_pref_set_default_filter (arpref, filter);
+
+ if (!e_enum_to_string (AUTOAR_TYPE_FORMAT, format)) {
+ format = AUTOAR_FORMAT_ZIP;
+ }
+
+ if (!e_enum_to_string (AUTOAR_TYPE_FORMAT, filter)) {
+ filter = AUTOAR_FILTER_NONE;
+ }
+
+ g_settings_set_string (
+ settings,
+ "autoar-format",
+ e_enum_to_string (AUTOAR_TYPE_FORMAT, format));
+ g_settings_set_string (
+ settings,
+ "autoar-filter",
+ e_enum_to_string (AUTOAR_TYPE_FILTER, filter));
#endif
for (iter = files; iter != NULL; iter = g_slist_next (iter)) {
@@ -742,11 +768,6 @@ e_attachment_store_run_load_dialog (EAttachmentStore *store,
e_attachment_set_disposition (attachment, disposition);
e_attachment_store_add_attachment (store, attachment);
-#ifdef HAVE_AUTOAR
- g_object_set_data_full (G_OBJECT (attachment),
- "autoar-pref", g_object_ref (arpref), g_object_unref);
-#endif
-
e_attachment_load_async (
attachment, (GAsyncReadyCallback)
e_attachment_load_handle_error, parent);
@@ -760,7 +781,8 @@ exit:
gtk_widget_destroy (dialog);
#ifdef HAVE_AUTOAR
g_object_unref (settings);
- g_object_unref (arpref);
+ g_free (format_string);
+ g_free (filter_string);
#endif
}
@@ -848,8 +870,6 @@ e_attachment_store_run_save_dialog (EAttachmentStore *store,
const gchar *name = NULL;
#ifdef HAVE_AUTOAR
- AutoarPref *arpref;
- GSettings *settings;
gchar *mime_type;
#endif
@@ -867,15 +887,10 @@ e_attachment_store_run_save_dialog (EAttachmentStore *store,
#ifdef HAVE_AUTOAR
mime_type = e_attachment_dup_mime_type (attachment);
- settings = e_util_ref_settings (AUTOAR_PREF_DEFAULT_GSCHEMA_ID);
- arpref = autoar_pref_new_with_gsettings (settings);
- if (!autoar_pref_check_file_name (arpref, name) &&
- !autoar_pref_check_mime_type_d (arpref, mime_type)) {
+ if (!autoar_check_mime_type_supported (mime_type)) {
gtk_widget_hide (extra_box_widget);
}
- g_clear_object (&settings);
- g_clear_object (&arpref);
g_free (mime_type);
#endif
@@ -903,27 +918,16 @@ e_attachment_store_run_save_dialog (EAttachmentStore *store,
e_attachment_set_save_self (attachment_list->data, save_self);
e_attachment_set_save_extracted (attachment_list->data, save_extracted);
} else {
- AutoarPref *arpref;
- GSettings *settings;
GList *iter;
- settings = e_util_ref_settings (AUTOAR_PREF_DEFAULT_GSCHEMA_ID);
- arpref = autoar_pref_new_with_gsettings (settings);
-
for (iter = attachment_list; iter != NULL; iter = iter->next) {
EAttachment *attachment;
- GFileInfo *file_info;
- const gchar *name;
gchar *mime_type;
attachment = iter->data;
- file_info = e_attachment_ref_file_info (attachment);
- name = g_file_info_get_display_name (file_info);
mime_type = e_attachment_dup_mime_type (attachment);
- if ((name != NULL &&
- autoar_pref_check_file_name (arpref, name)) ||
- autoar_pref_check_mime_type_d (arpref, mime_type)) {
+ if (autoar_check_mime_type_supported (mime_type)) {
e_attachment_set_save_self (attachment, save_self);
e_attachment_set_save_extracted (attachment, save_extracted);
} else {
@@ -931,12 +935,8 @@ e_attachment_store_run_save_dialog (EAttachmentStore *store,
e_attachment_set_save_extracted (attachment, FALSE);
}
- g_object_unref (file_info);
g_free (mime_type);
}
-
- g_object_unref (settings);
- g_object_unref (arpref);
}
#endif
} else {
diff --git a/e-util/e-attachment.c b/e-util/e-attachment.c
index d451f18..21dec66 100644
--- a/e-util/e-attachment.c
+++ b/e-util/e-attachment.c
@@ -29,8 +29,7 @@
#include <glib/gstdio.h>
#ifdef HAVE_AUTOAR
-#include <gnome-autoar/autoar.h>
-#include <gnome-autoar/autoar-gtk.h>
+#include <gnome-autoar/gnome-autoar.h>
#endif
#include <libedataserver/libedataserver.h>
@@ -2027,7 +2026,7 @@ attachment_load_file_read_cb (GFile *file,
#ifdef HAVE_AUTOAR
static void
-attachment_load_created_decide_dest_cb (AutoarCreate *arcreate,
+attachment_load_created_decide_dest_cb (AutoarCompressor *compressor,
GFile *destination,
EAttachment *attachment)
{
@@ -2035,23 +2034,23 @@ attachment_load_created_decide_dest_cb (AutoarCreate *arcreate,
}
static void
-attachment_load_created_cancelled_cb (AutoarCreate *arcreate,
+attachment_load_created_cancelled_cb (AutoarCompressor *compressor,
LoadContext *load_context)
{
attachment_load_check_for_error (load_context,
g_error_new_literal (
G_IO_ERROR, G_IO_ERROR_CANCELLED, _("Operation was cancelled")));
- g_object_unref (arcreate);
+ g_object_unref (compressor);
}
static void
-attachment_load_created_completed_cb (AutoarCreate *arcreate,
+attachment_load_created_completed_cb (AutoarCompressor *compressor,
LoadContext *load_context)
{
EAttachment *attachment;
GFile *file;
- g_object_unref (arcreate);
+ g_object_unref (compressor);
/* We have set the file to the created temporary archive, so we can
* query info again and use the regular procedure to load the
@@ -2068,12 +2067,12 @@ attachment_load_created_completed_cb (AutoarCreate *arcreate,
}
static void
-attachment_load_created_error_cb (AutoarCreate *arcreate,
+attachment_load_created_error_cb (AutoarCompressor *compressor,
GError *error,
LoadContext *load_context)
{
attachment_load_check_for_error (load_context, g_error_copy (error));
- g_object_unref (arcreate);
+ g_object_unref (compressor);
}
#endif
@@ -2101,25 +2100,49 @@ attachment_load_query_info_cb (GFile *file,
#ifdef HAVE_AUTOAR
if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY) {
- AutoarCreate *arcreate;
- AutoarPref *arpref; /* Do not unref */
+ AutoarCompressor *compressor;
GFile *temporary;
+ GSettings *settings;
+ GList *files = NULL;
+ char *format_string;
+ char *filter_string;
+ gint format;
+ gint filter;
- arpref = g_object_get_data (G_OBJECT (attachment), "autoar-pref");
temporary = attachment_get_temporary (&error);
if (attachment_load_check_for_error (load_context, error))
return;
- arcreate = autoar_create_new_file (arpref, temporary, file, NULL);
- g_signal_connect (arcreate, "decide-dest",
+
+ settings = e_util_ref_settings ("org.gnome.evolution.shell");
+
+ format_string = g_settings_get_string (settings, "autoar-format");
+ filter_string = g_settings_get_string (settings, "autoar-filter");
+
+ if (!e_enum_from_string (AUTOAR_TYPE_FORMAT, format_string, &format)) {
+ format = AUTOAR_FORMAT_ZIP;
+ }
+ if (!e_enum_from_string (AUTOAR_TYPE_FILTER, filter_string, &filter)) {
+ filter = AUTOAR_FILTER_NONE;
+ }
+
+ files = g_list_prepend (files, file);
+
+ compressor = autoar_compressor_new (
+ files, temporary, format, filter, FALSE);
+ g_signal_connect (compressor, "decide-dest",
G_CALLBACK (attachment_load_created_decide_dest_cb), attachment);
- g_signal_connect (arcreate, "cancelled",
+ g_signal_connect (compressor, "cancelled",
G_CALLBACK (attachment_load_created_cancelled_cb), load_context);
- g_signal_connect (arcreate, "completed",
+ g_signal_connect (compressor, "completed",
G_CALLBACK (attachment_load_created_completed_cb), load_context);
- g_signal_connect (arcreate, "error",
+ g_signal_connect (compressor, "error",
G_CALLBACK (attachment_load_created_error_cb), load_context);
- autoar_create_start_async (arcreate, cancellable);
+ autoar_compressor_start_async (compressor, cancellable);
+ g_object_unref (settings);
+ g_free (format_string);
+ g_free (filter_string);
+ g_list_free (files);
g_object_unref (temporary);
} else {
#endif
@@ -2752,6 +2775,7 @@ struct _SaveContext {
GByteArray *input_buffer;
gchar *suggested_destname;
+ GFile *temporary_file;
guint total_tasks : 2;
guint completed_tasks : 2;
@@ -2815,6 +2839,9 @@ attachment_save_context_free (SaveContext *save_context)
if (save_context->suggested_destname != NULL)
g_free (save_context->suggested_destname);
+ if (save_context->temporary_file != NULL)
+ g_clear_object (&save_context->temporary_file);
+
g_mutex_clear (&(save_context->completed_tasks_mutex));
g_mutex_clear (&(save_context->prepared_tasks_mutex));
@@ -2872,6 +2899,33 @@ attachment_save_complete (SaveContext *save_context) {
}
}
+static gchar *
+get_new_name_with_count (const gchar *initial_name,
+ gint count)
+{
+ GString *string;
+ const gchar *ext;
+ gsize length;
+
+ if (count == 0) {
+ return g_strdup (initial_name);
+ }
+
+ string = g_string_sized_new (strlen (initial_name));
+ ext = g_utf8_strchr (initial_name, -1, '.');
+
+ if (ext != NULL)
+ length = ext - initial_name;
+ else
+ length = strlen (initial_name);
+
+ g_string_append_len (string, initial_name, length);
+ g_string_append_printf (string, " (%d)", count);
+ g_string_append (string, (ext != NULL) ? ext : "");
+
+ return g_string_free (string, FALSE);
+}
+
static GFile *
attachment_save_new_candidate (SaveContext *save_context)
{
@@ -2890,27 +2944,7 @@ attachment_save_new_candidate (SaveContext *save_context)
/* Translators: Default attachment filename. */
display_name = _("attachment.dat");
- if (save_context->count == 0)
- basename = g_strdup (display_name);
- else {
- GString *string;
- const gchar *ext;
- gsize length;
-
- string = g_string_sized_new (strlen (display_name));
- ext = g_utf8_strchr (display_name, -1, '.');
-
- if (ext != NULL)
- length = ext - display_name;
- else
- length = strlen (display_name);
-
- g_string_append_len (string, display_name, length);
- g_string_append_printf (string, " (%d)", save_context->count);
- g_string_append (string, (ext != NULL) ? ext : "");
-
- basename = g_string_free (string, FALSE);
- }
+ basename = get_new_name_with_count (display_name, save_context->count);
save_context->count++;
@@ -3009,43 +3043,151 @@ attachment_save_read_cb (GInputStream *input_stream,
}
#ifdef HAVE_AUTOAR
+static GFile*
+attachment_save_extracted_decide_destination_cb (AutoarExtractor *extractor,
+ GFile *destination,
+ GList *files,
+ SaveContext *save_context)
+{
+ gchar *basename;
+ GFile *destination_directory;
+ GFile *new_destination;
+ gint count = 0;
+
+ basename = g_file_get_basename (destination);
+ destination_directory = g_file_get_parent (destination);
+
+ new_destination = g_object_ref (destination);
+
+ while (g_file_query_exists (new_destination, NULL)) {
+ gchar *new_basename;
+
+ new_basename = get_new_name_with_count (basename, ++count);
+
+ g_object_unref (new_destination);
+
+ new_destination = g_file_get_child (
+ destination_directory, new_basename);
+
+ g_free (new_basename);
+ }
+
+ g_object_unref (destination_directory);
+ g_free (basename);
+
+ return new_destination;
+}
+
static void
-attachment_save_extracted_progress_cb (AutoarExtract *arextract,
+attachment_save_extracted_progress_cb (AutoarExtractor *extractor,
guint64 completed_size,
guint completed_files,
SaveContext *save_context)
{
attachment_progress_cb (
- autoar_extract_get_size (arextract),
+ autoar_extractor_get_total_size (extractor),
completed_size, save_context->attachment);
}
static void
-attachment_save_extracted_cancelled_cb (AutoarExtract *arextract,
+attachment_save_extracted_cancelled_cb (AutoarExtractor *extractor,
SaveContext *save_context)
{
attachment_save_check_for_error (save_context,
g_error_new_literal (
G_IO_ERROR, G_IO_ERROR_CANCELLED, _("Operation was cancelled")));
- g_object_unref (arextract);
+ g_object_unref (extractor);
}
static void
-attachment_save_extracted_completed_cb (AutoarExtract *arextract,
+attachment_save_extracted_completed_cb (AutoarExtractor *extractor,
SaveContext *save_context)
{
attachment_save_complete (save_context);
- g_object_unref (arextract);
+ g_object_unref (extractor);
}
static void
-attachment_save_extracted_error_cb (AutoarExtract *arextract,
+attachment_save_extracted_error_cb (AutoarExtractor *extractor,
GError *error,
SaveContext *save_context)
{
attachment_save_check_for_error (save_context, g_error_copy (error));
- g_object_unref (arextract);
+ g_object_unref (extractor);
}
+
+static void
+attachament_save_write_archive_cb (GOutputStream *output_stream,
+ GAsyncResult *result,
+ SaveContext *save_context)
+{
+ AutoarExtractor *extractor;
+ GError *error = NULL;
+ gsize bytes_written;
+
+ g_output_stream_write_all_finish (
+ output_stream, result, &bytes_written, &error);
+
+ g_object_unref (output_stream);
+
+ if (attachment_save_check_for_error (save_context, error)) {
+ return;
+ }
+
+ extractor = autoar_extractor_new (
+ save_context->temporary_file, save_context->directory);
+
+ autoar_extractor_set_delete_after_extraction (extractor, TRUE);
+
+ g_signal_connect (extractor, "decide-destination",
+ G_CALLBACK (attachment_save_extracted_decide_destination_cb),
+ save_context);
+ g_signal_connect (extractor, "progress",
+ G_CALLBACK (attachment_save_extracted_progress_cb),
+ save_context);
+ g_signal_connect (extractor, "cancelled",
+ G_CALLBACK (attachment_save_extracted_cancelled_cb),
+ save_context);
+ g_signal_connect (extractor, "error",
+ G_CALLBACK (attachment_save_extracted_error_cb),
+ save_context);
+ g_signal_connect (extractor, "completed",
+ G_CALLBACK (attachment_save_extracted_completed_cb),
+ save_context);
+
+ autoar_extractor_start_async (
+ extractor, save_context->attachment->priv->cancellable);
+
+ /* We do not g_object_unref (extractor); here because
+ * autoar_extractor_run_start_async () does not increase the
+ * reference count of extractor. We unref the object in
+ * callbacks instead. */
+}
+
+static void
+attachment_save_create_archive_cb (GFile *file,
+ GAsyncResult *result,
+ SaveContext *save_context)
+{
+ GFileOutputStream *output_stream;
+ GError *error = NULL;
+
+ output_stream = g_file_create_finish (file, result, &error);
+
+ if (attachment_save_check_for_error (save_context, error)) {
+ return;
+ }
+
+ g_output_stream_write_all_async (
+ G_OUTPUT_STREAM (output_stream),
+ save_context->input_buffer->data,
+ save_context->input_buffer->len,
+ G_PRIORITY_DEFAULT,
+ save_context->attachment->priv->cancellable,
+ (GAsyncReadyCallback) attachament_save_write_archive_cb,
+ save_context);
+}
+
#endif
static void
@@ -3097,41 +3239,25 @@ attachment_save_got_output_stream (SaveContext *save_context)
#ifdef HAVE_AUTOAR
if (attachment->priv->save_extracted) {
- GSettings *settings;
- AutoarPref *arpref;
- AutoarExtract *arextract;
+ GFile *temporary_directory;
+ GError *error = NULL;
- settings = e_util_ref_settings (AUTOAR_PREF_DEFAULT_GSCHEMA_ID);
- arpref = autoar_pref_new_with_gsettings (settings);
- autoar_pref_set_delete_if_succeed (arpref, FALSE);
+ temporary_directory = attachment_get_temporary (&error);
+ if (attachment_save_check_for_error (save_context, error))
+ return;
- arextract = autoar_extract_new_memory_file (
- buffer->data, buffer->len,
- save_context->suggested_destname,
- save_context->directory, arpref);
+ save_context->temporary_file = g_file_get_child (
+ temporary_directory, save_context->suggested_destname);
- g_signal_connect (arextract, "progress",
- G_CALLBACK (attachment_save_extracted_progress_cb),
- save_context);
- g_signal_connect (arextract, "cancelled",
- G_CALLBACK (attachment_save_extracted_cancelled_cb),
- save_context);
- g_signal_connect (arextract, "error",
- G_CALLBACK (attachment_save_extracted_error_cb),
- save_context);
- g_signal_connect (arextract, "completed",
- G_CALLBACK (attachment_save_extracted_completed_cb),
+ g_file_create_async (
+ save_context->temporary_file,
+ G_FILE_CREATE_NONE,
+ G_PRIORITY_DEFAULT,
+ cancellable,
+ (GAsyncReadyCallback) attachment_save_create_archive_cb,
save_context);
- autoar_extract_start_async (arextract, cancellable);
-
- g_object_unref (settings);
- g_object_unref (arpref);
-
- /* We do not g_object_unref (arextract); here because
- * autoar_extract_run_start_async () do not increase the
- * reference count of arextract. We unref the object in
- * callbacks instead. */
+ g_object_unref (temporary_directory);
}
#endif
--
cgit v0.12