diff options
author | Milan Crha <mcrha@redhat.com> | 2023-04-18 15:07:11 +0200 |
---|---|---|
committer | Milan Crha <mcrha@redhat.com> | 2023-04-18 15:07:11 +0200 |
commit | f939a483d238ca529af4e2cbb03b3513d87b6ea8 (patch) | |
tree | d7359b759cf75c4df17e3f48249e23597774898a | |
parent | 199787af388e744f6d9a5ad1d6f1a29d0c310f82 (diff) | |
download | evolution-f939a483d238ca529af4e2cbb03b3513d87b6ea8.tar.gz |
I#2326 - RSS: Limit re-download on content change, if possible
Closes https://gitlab.gnome.org/GNOME/evolution/-/issues/2326
-rw-r--r-- | src/modules/rss/camel-rss-store-summary.c | 106 | ||||
-rw-r--r-- | src/modules/rss/camel-rss-store-summary.h | 12 | ||||
-rw-r--r-- | src/modules/rss/camel/camel-rss-folder.c | 62 | ||||
-rw-r--r-- | src/modules/rss/e-rss-parser.c | 5 | ||||
-rw-r--r-- | src/modules/rss/evolution/e-rss-shell-view-extension.c | 2 |
5 files changed, 182 insertions, 5 deletions
diff --git a/src/modules/rss/camel-rss-store-summary.c b/src/modules/rss/camel-rss-store-summary.c index ec9a6bf431..f4683d1f4f 100644 --- a/src/modules/rss/camel-rss-store-summary.c +++ b/src/modules/rss/camel-rss-store-summary.c @@ -34,6 +34,8 @@ typedef struct _RssFeed { gchar *href; gchar *display_name; gchar *icon_filename; + gchar *last_etag; + gchar *last_modified; CamelRssContentType content_type; guint32 total_count; guint32 unread_count; @@ -216,6 +218,8 @@ camel_rss_store_summary_load (CamelRssStoreSummary *self, feed->href = g_key_file_get_string (key_file, group, "href", NULL); feed->display_name = g_key_file_get_string (key_file, group, "display-name", NULL); feed->icon_filename = g_key_file_get_string (key_file, group, "icon-filename", NULL); + feed->last_etag = g_key_file_get_string (key_file, group, "last-etag", NULL); + feed->last_modified = g_key_file_get_string (key_file, group, "last-modified", NULL); feed->content_type = g_key_file_get_integer (key_file, group, "content-type", NULL); feed->total_count = (guint32) g_key_file_get_uint64 (key_file, group, "total-count", NULL); feed->unread_count = (guint32) g_key_file_get_uint64 (key_file, group, "unread-count", NULL); @@ -291,6 +295,8 @@ camel_rss_store_summary_save (CamelRssStoreSummary *self, g_key_file_set_string (key_file, group, "href", feed->href); g_key_file_set_string (key_file, group, "display-name", feed->display_name); g_key_file_set_string (key_file, group, "icon-filename", feed->icon_filename ? feed->icon_filename : ""); + g_key_file_set_string (key_file, group, "last-etag", feed->last_etag ? feed->last_etag : ""); + g_key_file_set_string (key_file, group, "last-modified", feed->last_modified ? feed->last_modified : ""); g_key_file_set_integer (key_file, group, "content-type", feed->content_type); g_key_file_set_uint64 (key_file, group, "total-count", feed->total_count); g_key_file_set_uint64 (key_file, group, "unread-count", feed->unread_count); @@ -850,3 +856,103 @@ camel_rss_store_summary_set_last_updated (CamelRssStoreSummary *self, camel_rss_store_summary_unlock (self); } + +const gchar * +camel_rss_store_summary_get_last_etag (CamelRssStoreSummary *self, + const gchar *id) +{ + RssFeed *feed; + const gchar *result = NULL; + + g_return_val_if_fail (CAMEL_IS_RSS_STORE_SUMMARY (self), NULL); + g_return_val_if_fail (id != NULL, NULL); + + camel_rss_store_summary_lock (self); + + feed = g_hash_table_lookup (self->priv->feeds, id); + if (feed) + result = feed->last_etag; + + camel_rss_store_summary_unlock (self); + + return result; +} + +void +camel_rss_store_summary_set_last_etag (CamelRssStoreSummary *self, + const gchar *id, + const gchar *last_etag) +{ + RssFeed *feed; + gboolean changed = FALSE; + + g_return_if_fail (CAMEL_IS_RSS_STORE_SUMMARY (self)); + g_return_if_fail (id != NULL); + + camel_rss_store_summary_lock (self); + + feed = g_hash_table_lookup (self->priv->feeds, id); + if (feed) { + if (g_strcmp0 (feed->last_etag, last_etag) != 0) { + g_free (feed->last_etag); + feed->last_etag = g_strdup (last_etag); + self->priv->dirty = TRUE; + changed = TRUE; + } + } + + camel_rss_store_summary_unlock (self); + + if (changed) + camel_rss_store_summary_schedule_feed_changed (self, id); +} + +const gchar * +camel_rss_store_summary_get_last_modified (CamelRssStoreSummary *self, + const gchar *id) +{ + RssFeed *feed; + const gchar *result = NULL; + + g_return_val_if_fail (CAMEL_IS_RSS_STORE_SUMMARY (self), NULL); + g_return_val_if_fail (id != NULL, NULL); + + camel_rss_store_summary_lock (self); + + feed = g_hash_table_lookup (self->priv->feeds, id); + if (feed) + result = feed->last_modified; + + camel_rss_store_summary_unlock (self); + + return result; +} + +void +camel_rss_store_summary_set_last_modified (CamelRssStoreSummary *self, + const gchar *id, + const gchar *last_modified) +{ + RssFeed *feed; + gboolean changed = FALSE; + + g_return_if_fail (CAMEL_IS_RSS_STORE_SUMMARY (self)); + g_return_if_fail (id != NULL); + + camel_rss_store_summary_lock (self); + + feed = g_hash_table_lookup (self->priv->feeds, id); + if (feed) { + if (g_strcmp0 (feed->last_modified, last_modified) != 0) { + g_free (feed->last_modified); + feed->last_modified = g_strdup (last_modified); + self->priv->dirty = TRUE; + changed = TRUE; + } + } + + camel_rss_store_summary_unlock (self); + + if (changed) + camel_rss_store_summary_schedule_feed_changed (self, id); +} diff --git a/src/modules/rss/camel-rss-store-summary.h b/src/modules/rss/camel-rss-store-summary.h index 9c1b2b36e0..2272a8f429 100644 --- a/src/modules/rss/camel-rss-store-summary.h +++ b/src/modules/rss/camel-rss-store-summary.h @@ -110,6 +110,18 @@ gint64 camel_rss_store_summary_get_last_updated(CamelRssStoreSummary *self, void camel_rss_store_summary_set_last_updated(CamelRssStoreSummary *self, const gchar *id, gint64 last_updated); +const gchar * camel_rss_store_summary_get_last_etag (CamelRssStoreSummary *self, + const gchar *id); +void camel_rss_store_summary_set_last_etag (CamelRssStoreSummary *self, + const gchar *id, + const gchar *last_etag); +const gchar * camel_rss_store_summary_get_last_modified + (CamelRssStoreSummary *self, + const gchar *id); +void camel_rss_store_summary_set_last_modified + (CamelRssStoreSummary *self, + const gchar *id, + const gchar *last_modified); G_END_DECLS diff --git a/src/modules/rss/camel/camel-rss-folder.c b/src/modules/rss/camel/camel-rss-folder.c index 13a783efd7..d6bd517be0 100644 --- a/src/modules/rss/camel/camel-rss-folder.c +++ b/src/modules/rss/camel/camel-rss-folder.c @@ -240,6 +240,8 @@ rss_folder_refresh_info_sync (CamelFolder *folder, CamelFolderChangeInfo *changes = NULL; CamelSession *session; gchar *href; + gchar *last_etag; + gchar *last_modified; gint64 last_updated; gboolean success = TRUE; @@ -260,14 +262,18 @@ rss_folder_refresh_info_sync (CamelFolder *folder, camel_rss_store_summary_lock (rss_store_summary); href = g_strdup (camel_rss_store_summary_get_href (rss_store_summary, self->priv->id)); + last_etag = g_strdup (camel_rss_store_summary_get_last_etag (rss_store_summary, self->priv->id)); + last_modified = g_strdup (camel_rss_store_summary_get_last_modified (rss_store_summary, self->priv->id)); last_updated = camel_rss_store_summary_get_last_updated (rss_store_summary, self->priv->id); camel_rss_store_summary_unlock (rss_store_summary); if (href && *href) { SoupSession *soup_session; + SoupMessageHeaders *request_headers; SoupMessage *message; GBytes *bytes; + GError *local_error = NULL; message = soup_message_new (SOUP_METHOD_GET, href); if (!message) { @@ -290,10 +296,22 @@ rss_folder_refresh_info_sync (CamelFolder *folder, g_object_unref (logger); } - bytes = soup_session_send_and_read (soup_session, message, cancellable, error); + request_headers = soup_message_get_request_headers (message); + + soup_message_headers_append (request_headers, "Connection", "close"); + + if (last_etag && *last_etag) + soup_message_headers_append (request_headers, "If-None-Match", last_etag); + else if (last_modified && *last_modified) + soup_message_headers_append (request_headers, "If-Modified-Since", last_modified); - if (bytes) { + bytes = soup_session_send_and_read (soup_session, message, cancellable, &local_error); + + if (soup_message_get_status (message) == SOUP_STATUS_NOT_MODIFIED) { + g_clear_error (&local_error); + } else if (bytes) { GSList *feeds = NULL; + gboolean save_summary = FALSE; success = SOUP_STATUS_IS_SUCCESSFUL (soup_message_get_status (message)); @@ -392,13 +410,49 @@ rss_folder_refresh_info_sync (CamelFolder *folder, camel_rss_store_summary_set_last_updated (rss_store_summary, self->priv->id, max_last_modified); camel_rss_store_summary_unlock (rss_store_summary); - success = camel_rss_store_summary_save (rss_store_summary, error); + save_summary = TRUE; } } g_slist_free_full (feeds, e_rss_feed_free); + + if (success) { + SoupMessageHeaders *response_headers; + + response_headers = soup_message_get_response_headers (message); + + if (response_headers) { + const gchar *tmp; + + camel_rss_store_summary_lock (rss_store_summary); + + tmp = soup_message_headers_get_one (response_headers, "ETag"); + /* ignore weak ETag-s */ + if (tmp && (g_ascii_strncasecmp (tmp, "W/", 2) == 0 || g_ascii_strncasecmp (tmp, "\"W/", 3) == 0)) + tmp = NULL; + if (tmp && !*tmp) + tmp = NULL; + + camel_rss_store_summary_set_last_etag (rss_store_summary, self->priv->id, tmp); + + tmp = soup_message_headers_get_one (response_headers, "Last-Modified"); + if (tmp && !*tmp) + tmp = NULL; + + camel_rss_store_summary_set_last_modified (rss_store_summary, self->priv->id, tmp); + + camel_rss_store_summary_unlock (rss_store_summary); + + save_summary = TRUE; + } + } + + if (success && save_summary) + success = camel_rss_store_summary_save (rss_store_summary, error); } else { success = FALSE; + if (local_error) + g_propagate_error (error, local_error); } g_clear_pointer (&bytes, g_bytes_unref); @@ -409,6 +463,8 @@ rss_folder_refresh_info_sync (CamelFolder *folder, success = FALSE; } + g_free (last_modified); + g_free (last_etag); g_free (href); if (changes) { diff --git a/src/modules/rss/e-rss-parser.c b/src/modules/rss/e-rss-parser.c index 54b5a9bfc8..3bc0a7c329 100644 --- a/src/modules/rss/e-rss-parser.c +++ b/src/modules/rss/e-rss-parser.c @@ -592,11 +592,12 @@ e_rss_parser_parse (const gchar *xml, xmlDoc *doc; xmlNodePtr root; - g_return_val_if_fail (xml != NULL, FALSE); - if (out_feeds) *out_feeds = NULL; + if (!xml || !xml_len) + return FALSE; + doc = e_xml_parse_data (xml, xml_len); if (!doc) diff --git a/src/modules/rss/evolution/e-rss-shell-view-extension.c b/src/modules/rss/evolution/e-rss-shell-view-extension.c index ecb5ef6cdf..948bd4eb61 100644 --- a/src/modules/rss/evolution/e-rss-shell-view-extension.c +++ b/src/modules/rss/evolution/e-rss-shell-view-extension.c @@ -124,6 +124,8 @@ action_rss_mail_folder_reload_cb (GtkAction *action, g_object_get (store, "summary", &store_summary, NULL); camel_rss_store_summary_set_last_updated (store_summary, folder_path, 0); + camel_rss_store_summary_set_last_etag (store_summary, folder_path, NULL); + camel_rss_store_summary_set_last_modified (store_summary, folder_path, NULL); camel_store_get_folder (store, folder_path, CAMEL_STORE_FOLDER_NONE, G_PRIORITY_DEFAULT, NULL, e_rss_mail_folder_reload_got_folder_cb, shell_view); |