[evolution-data-server/wip/offline-cache] [ECalMetaBackend] Locally stored attachments (beside cache file) never removed



commit 2e0d6e9bdb3c60697332114653d4ae75b6fad90f
Author: Milan Crha <mcrha redhat com>
Date:   Tue May 16 10:02:16 2017 +0200

    [ECalMetaBackend] Locally stored attachments (beside cache file) never removed

 src/calendar/libedata-cal/e-cal-cache.c        |  115 +++++++++++++++++++++++-
 src/calendar/libedata-cal/e-cal-cache.h        |    4 +
 src/calendar/libedata-cal/e-cal-meta-backend.c |   20 ++++-
 3 files changed, 135 insertions(+), 4 deletions(-)
---
diff --git a/src/calendar/libedata-cal/e-cal-cache.c b/src/calendar/libedata-cal/e-cal-cache.c
index bf845ee..8a186ed 100644
--- a/src/calendar/libedata-cal/e-cal-cache.c
+++ b/src/calendar/libedata-cal/e-cal-cache.c
@@ -32,6 +32,7 @@
 #include "evolution-data-server-config.h"
 
 #include <glib/gi18n-lib.h>
+#include <glib/gstdio.h>
 #include <sqlite3.h>
 
 #include <libebackend/libebackend.h>
@@ -2803,6 +2804,78 @@ e_cal_cache_get_offline_changes  (ECalCache *cal_cache,
 }
 
 /**
+ * e_cal_cache_delete_attachments:
+ * @cal_cache: an #ECalCache
+ * @component: an icalcomponent
+ * @cancellable: optional #GCancellable object, or %NULL
+ * @error: return location for a #GError, or %NULL
+ *
+ * Deletes all locally stored attachments beside the cache file from the disk.
+ * This doesn't modify the @component. It's usually called before the @component
+ * is being removed from the @cal_cache.
+ *
+ * Returns: Whether succeeded.
+ *
+ * Since: 3.26
+ **/
+gboolean
+e_cal_cache_delete_attachments (ECalCache *cal_cache,
+                               icalcomponent *component,
+                               GCancellable *cancellable,
+                               GError **error)
+{
+       icalproperty *prop;
+       gchar *cache_dirname = NULL;
+
+       g_return_val_if_fail (E_IS_CAL_CACHE (cal_cache), FALSE);
+       g_return_val_if_fail (component != NULL, FALSE);
+
+       for (prop = icalcomponent_get_first_property (component, ICAL_ATTACH_PROPERTY);
+            prop;
+            prop = icalcomponent_get_next_property (component, ICAL_ATTACH_PROPERTY)) {
+               icalattach *attach = icalproperty_get_attach (prop);
+
+               if (attach && icalattach_get_is_url (attach)) {
+                       const gchar *url;
+
+                       url = icalattach_get_url (attach);
+                       if (url) {
+                               gsize buf_size;
+                               gchar *buf;
+
+                               buf_size = strlen (url);
+                               buf = g_malloc0 (buf_size + 1);
+
+                               icalvalue_decode_ical_string (url, buf, buf_size);
+
+                               if (g_str_has_prefix (buf, "file://")) {
+                                       gchar *filename;
+
+                                       filename = g_filename_from_uri (buf, NULL, NULL);
+                                       if (filename) {
+                                               if (!cache_dirname)
+                                                       cache_dirname = g_path_get_dirname 
(e_cache_get_filename (E_CACHE (cal_cache)));
+
+                                               if (g_str_has_prefix (filename, cache_dirname) &&
+                                                   g_unlink (filename) == -1) {
+                                                       /* Ignore these errors */
+                                               }
+
+                                               g_free (filename);
+                                       }
+                               }
+
+                               g_free (buf);
+                       }
+               }
+       }
+
+       g_free (cache_dirname);
+
+       return TRUE;
+}
+
+/**
  * e_cal_cache_put_timezone:
  * @cal_cache: an #ECalCache
  * @zone: an icaltimezone to put
@@ -3213,6 +3286,41 @@ e_cal_cache_resolve_timezone_simple_cb (const gchar *tzid,
 }
 
 static gboolean
+ecc_search_delete_attachment_cb (ECalCache *cal_cache,
+                                const gchar *uid,
+                                const gchar *rid,
+                                const gchar *revision,
+                                const gchar *object,
+                                const gchar *extra,
+                                EOfflineState offline_state,
+                                gpointer user_data)
+{
+       icalcomponent *icalcomp;
+       GCancellable *cancellable = user_data;
+       GError *local_error = NULL;
+
+       g_return_val_if_fail (E_IS_CAL_CACHE (cal_cache), FALSE);
+       g_return_val_if_fail (object != NULL, FALSE);
+
+       icalcomp = icalcomponent_new_from_string (object);
+       if (!icalcomp)
+               return TRUE;
+
+       if (!e_cal_cache_delete_attachments (cal_cache, icalcomp, cancellable, &local_error)) {
+               if (rid && !*rid)
+                       rid = NULL;
+
+               g_debug ("%s: Failed to remove attachments for '%s%s%s': %s", G_STRFUNC,
+                       uid, rid ? "|" : "", rid ? rid : "", local_error ? local_error->message : "Unknown 
error");
+               g_clear_error (&local_error);
+       }
+
+       icalcomponent_free (icalcomp);
+
+       return !g_cancellable_is_cancelled (cancellable);
+}
+
+static gboolean
 ecc_empty_aux_tables (ECache *cache,
                      GCancellable *cancellable,
                      GError **error)
@@ -3323,8 +3431,11 @@ e_cal_cache_remove_all_locked (ECache *cache,
        g_return_val_if_fail (E_IS_CAL_CACHE (cache), FALSE);
        g_return_val_if_fail (E_CACHE_CLASS (e_cal_cache_parent_class)->remove_all_locked != NULL, FALSE);
 
-       /* Cannot free content of priv->loaded_timezones and priv->modified_timezones, because those can be 
used anywhere */
-       success = ecc_empty_aux_tables (cache, cancellable, error);
+       /* Cannot free content of priv->loaded_timezones and priv->modified_timezones,
+          because those can be used anywhere */
+       success = ecc_empty_aux_tables (cache, cancellable, error) &&
+               e_cal_cache_search_with_callback (E_CAL_CACHE (cache), NULL,
+               ecc_search_delete_attachment_cb, cancellable, cancellable, error);
 
        success = success && E_CACHE_CLASS (e_cal_cache_parent_class)->remove_all_locked (cache, uids, 
cancellable, error);
 
diff --git a/src/calendar/libedata-cal/e-cal-cache.h b/src/calendar/libedata-cal/e-cal-cache.h
index 305fbb3..ede88a7 100644
--- a/src/calendar/libedata-cal/e-cal-cache.h
+++ b/src/calendar/libedata-cal/e-cal-cache.h
@@ -295,6 +295,10 @@ gboolean   e_cal_cache_search_with_callback
 GSList *       e_cal_cache_get_offline_changes (ECalCache *cal_cache,
                                                 GCancellable *cancellable,
                                                 GError **error);
+gboolean       e_cal_cache_delete_attachments  (ECalCache *cal_cache,
+                                                icalcomponent *component,
+                                                GCancellable *cancellable,
+                                                GError **error);
 
 gboolean       e_cal_cache_put_timezone        (ECalCache *cal_cache,
                                                 const icaltimezone *zone,
diff --git a/src/calendar/libedata-cal/e-cal-meta-backend.c b/src/calendar/libedata-cal/e-cal-meta-backend.c
index 9f37bbb..47e58de 100644
--- a/src/calendar/libedata-cal/e-cal-meta-backend.c
+++ b/src/calendar/libedata-cal/e-cal-meta-backend.c
@@ -759,7 +759,8 @@ ecmb_maybe_remove_from_cache (ECalMetaBackend *meta_backend,
 
                id = e_cal_component_get_id (comp);
                if (id) {
-                       if (!e_cal_cache_remove_component (cal_cache, id->uid, id->rid, offline_flag, 
cancellable, error)) {
+                       if (!e_cal_cache_delete_attachments (cal_cache, e_cal_component_get_icalcomponent 
(comp), cancellable, error) ||
+                           !e_cal_cache_remove_component (cal_cache, id->uid, id->rid, offline_flag, 
cancellable, error)) {
                                e_cal_component_free_id (id);
                                g_slist_free_full (comps, g_object_unref);
 
@@ -1158,6 +1159,10 @@ ecmb_put_instances (ECalMetaBackend *meta_backend,
                        if (!id)
                                continue;
 
+                       success = e_cal_cache_delete_attachments (cal_cache, 
e_cal_component_get_icalcomponent (comp), cancellable, error);
+                       if (!success)
+                               break;
+
                        success = e_cal_cache_remove_component (cal_cache, id->uid, id->rid, offline_flag, 
cancellable, error);
 
                        e_cal_backend_notify_component_removed (cal_backend, id, comp, NULL);
@@ -3739,11 +3744,14 @@ e_cal_meta_backend_inline_local_attachments_sync (ECalMetaBackend *meta_backend,
                                                  GError **error)
 {
        icalproperty *prop;
+       const gchar *uid;
        gboolean success = TRUE;
 
        g_return_val_if_fail (E_IS_CAL_META_BACKEND (meta_backend), FALSE);
        g_return_val_if_fail (component != NULL, FALSE);
 
+       uid = icalcomponent_get_uid (component);
+
        for (prop = icalcomponent_get_first_property (component, ICAL_ATTACH_PROPERTY);
             prop && success;
             prop = icalcomponent_get_next_property (component, ICAL_ATTACH_PROPERTY)) {
@@ -3785,7 +3793,15 @@ e_cal_meta_backend_inline_local_attachments_sync (ECalMetaBackend *meta_backend,
 
                                        /* Preserve existing FILENAME parameter */
                                        if (!icalproperty_get_first_parameter (prop, 
ICAL_FILENAME_PARAMETER)) {
-                                               param = icalparameter_new_filename (basename);
+                                               const gchar *use_filename = basename;
+
+                                               /* generated filename by Evolution */
+                                               if (uid && g_str_has_prefix (use_filename, uid) &&
+                                                   use_filename[strlen (uid)] == '-') {
+                                                       use_filename += strlen (uid) + 1;
+                                               }
+
+                                               param = icalparameter_new_filename (use_filename);
                                                icalproperty_add_parameter (prop, param);
                                        }
                                } else {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]