diff --git a/download b/download deleted file mode 100644 index cec53fe50a32774dec449068de660c0afe7e5ac6..0000000000000000000000000000000000000000 --- a/download +++ /dev/null @@ -1 +0,0 @@ -998d5b280372357346d2bc7afe45b36d evolution-data-server-3.28.5.tar.xz diff --git a/evolution-data-server-3.28.5-CVE-2020-14928.patch b/evolution-data-server-3.28.5-CVE-2020-14928.patch deleted file mode 100644 index a587ba3dabe994d04fa32b8aba3a7f73b12360ce..0000000000000000000000000000000000000000 --- a/evolution-data-server-3.28.5-CVE-2020-14928.patch +++ /dev/null @@ -1,91 +0,0 @@ -diff -up evolution-data-server-3.28.5/src/camel/camel-stream-buffer.c.CVE-2020-14928 evolution-data-server-3.28.5/src/camel/camel-stream-buffer.c ---- evolution-data-server-3.28.5/src/camel/camel-stream-buffer.c.CVE-2020-14928 2018-07-30 15:17:06.000000000 +0200 -+++ evolution-data-server-3.28.5/src/camel/camel-stream-buffer.c 2020-07-23 10:26:57.962555350 +0200 -@@ -524,3 +524,22 @@ camel_stream_buffer_read_line (CamelStre - - return g_strdup ((gchar *) sbf->priv->linebuf); - } -+ -+/* -+ * camel_stream_buffer_discard_cache: -+ * @sbf: a #CamelStreamBuffer -+ * -+ * Discards any cached data in the @sbf. The next read reads -+ * from the stream. -+ * -+ * Since: 3.28.5-14 -+ */ -+void -+camel_stream_buffer_discard_cache (CamelStreamBuffer *sbf) -+{ -+ g_return_if_fail (CAMEL_IS_STREAM_BUFFER (sbf)); -+ -+ sbf->priv->ptr = sbf->priv->buf; -+ sbf->priv->end = sbf->priv->buf; -+ sbf->priv->ptr[0] = '\0'; -+} -diff -up evolution-data-server-3.28.5/src/camel/camel-stream-buffer.h.CVE-2020-14928 evolution-data-server-3.28.5/src/camel/camel-stream-buffer.h ---- evolution-data-server-3.28.5/src/camel/camel-stream-buffer.h.CVE-2020-14928 2018-07-30 15:17:06.000000000 +0200 -+++ evolution-data-server-3.28.5/src/camel/camel-stream-buffer.h 2020-07-23 10:26:57.963555348 +0200 -@@ -93,6 +93,8 @@ gint camel_stream_buffer_gets (CamelStr - gchar * camel_stream_buffer_read_line (CamelStreamBuffer *sbf, - GCancellable *cancellable, - GError **error); -+void camel_stream_buffer_discard_cache -+ (CamelStreamBuffer *sbf); - - G_END_DECLS - -diff -up evolution-data-server-3.28.5/src/camel/providers/pop3/camel-pop3-store.c.CVE-2020-14928 evolution-data-server-3.28.5/src/camel/providers/pop3/camel-pop3-store.c ---- evolution-data-server-3.28.5/src/camel/providers/pop3/camel-pop3-store.c.CVE-2020-14928 2018-07-30 15:17:06.000000000 +0200 -+++ evolution-data-server-3.28.5/src/camel/providers/pop3/camel-pop3-store.c 2020-07-23 10:26:57.963555348 +0200 -@@ -208,6 +208,8 @@ connect_to_server (CamelService *service - - if (tls_stream != NULL) { - camel_stream_set_base_stream (stream, tls_stream); -+ /* Truncate any left cached input from the insecure part of the session */ -+ camel_pop3_stream_discard_cache (pop3_engine->stream); - g_object_unref (tls_stream); - } else { - g_prefix_error ( -diff -up evolution-data-server-3.28.5/src/camel/providers/pop3/camel-pop3-stream.c.CVE-2020-14928 evolution-data-server-3.28.5/src/camel/providers/pop3/camel-pop3-stream.c ---- evolution-data-server-3.28.5/src/camel/providers/pop3/camel-pop3-stream.c.CVE-2020-14928 2018-07-30 15:17:06.000000000 +0200 -+++ evolution-data-server-3.28.5/src/camel/providers/pop3/camel-pop3-stream.c 2020-07-23 10:26:57.963555348 +0200 -@@ -457,3 +457,14 @@ camel_pop3_stream_getd (CamelPOP3Stream - - return 1; - } -+ -+void -+camel_pop3_stream_discard_cache (CamelPOP3Stream *is) -+{ -+ if (is) { -+ is->ptr = is->end = is->buf; -+ is->lineptr = is->linebuf; -+ is->lineend = is->linebuf + CAMEL_POP3_STREAM_LINE_SIZE; -+ is->ptr[0] = '\n'; -+ } -+} -diff -up evolution-data-server-3.28.5/src/camel/providers/pop3/camel-pop3-stream.h.CVE-2020-14928 evolution-data-server-3.28.5/src/camel/providers/pop3/camel-pop3-stream.h ---- evolution-data-server-3.28.5/src/camel/providers/pop3/camel-pop3-stream.h.CVE-2020-14928 2018-07-30 15:17:06.000000000 +0200 -+++ evolution-data-server-3.28.5/src/camel/providers/pop3/camel-pop3-stream.h 2020-07-23 10:26:57.963555348 +0200 -@@ -87,6 +87,7 @@ gint camel_pop3_stream_getd (CamelPOP3 - guint *len, - GCancellable *cancellable, - GError **error); -+void camel_pop3_stream_discard_cache (CamelPOP3Stream *is); - - G_END_DECLS - -diff -up evolution-data-server-3.28.5/src/camel/providers/smtp/camel-smtp-transport.c.CVE-2020-14928 evolution-data-server-3.28.5/src/camel/providers/smtp/camel-smtp-transport.c ---- evolution-data-server-3.28.5/src/camel/providers/smtp/camel-smtp-transport.c.CVE-2020-14928 2018-07-30 15:17:06.000000000 +0200 -+++ evolution-data-server-3.28.5/src/camel/providers/smtp/camel-smtp-transport.c 2020-07-23 10:26:57.963555348 +0200 -@@ -319,6 +319,8 @@ connect_to_server (CamelService *service - - if (tls_stream != NULL) { - camel_stream_set_base_stream (stream, tls_stream); -+ /* Truncate any left cached input from the insecure part of the session */ -+ camel_stream_buffer_discard_cache (transport->istream); - g_object_unref (tls_stream); - } else { - g_prefix_error ( diff --git a/evolution-data-server-3.28.5-CVE-2020-16117.patch b/evolution-data-server-3.28.5-CVE-2020-16117.patch deleted file mode 100644 index 6b656f866858c07f2ed923234724d773f0b1181a..0000000000000000000000000000000000000000 --- a/evolution-data-server-3.28.5-CVE-2020-16117.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff -up evolution-data-server-3.28.5/src/camel/providers/imapx/camel-imapx-server.c.CVE-2020-16117 evolution-data-server-3.28.5/src/camel/providers/imapx/camel-imapx-server.c ---- evolution-data-server-3.28.5/src/camel/providers/imapx/camel-imapx-server.c.CVE-2020-16117 2018-07-30 15:17:06.000000000 +0200 -+++ evolution-data-server-3.28.5/src/camel/providers/imapx/camel-imapx-server.c 2020-09-30 09:10:32.240788043 +0200 -@@ -2979,7 +2979,8 @@ connected: - - /* See if we got new capabilities - * in the STARTTLS response. */ -- imapx_free_capability (is->priv->cinfo); -+ if (is->priv->cinfo) -+ imapx_free_capability (is->priv->cinfo); - is->priv->cinfo = NULL; - if (ic->status->condition == IMAPX_CAPABILITY) { - is->priv->cinfo = ic->status->u.cinfo; diff --git a/evolution-data-server-3.28.5-calbackendfile-interval-tree-destroy.patch b/evolution-data-server-3.28.5-calbackendfile-interval-tree-destroy.patch deleted file mode 100644 index 5188f380b2007f8a8585ddd8558e90517f7da87e..0000000000000000000000000000000000000000 --- a/evolution-data-server-3.28.5-calbackendfile-interval-tree-destroy.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff -up evolution-data-server-3.28.5/src/calendar/backends/file/e-cal-backend-file.c.calbackendfile-interval-tree-destroy evolution-data-server-3.28.5/src/calendar/backends/file/e-cal-backend-file.c ---- evolution-data-server-3.28.5/src/calendar/backends/file/e-cal-backend-file.c.calbackendfile-interval-tree-destroy 2021-06-16 16:09:19.863360296 +0200 -+++ evolution-data-server-3.28.5/src/calendar/backends/file/e-cal-backend-file.c 2021-06-16 16:10:14.225398710 +0200 -@@ -298,7 +298,8 @@ free_calendar_data (ECalBackendFile *cbf - - g_rec_mutex_lock (&priv->idle_save_rmutex); - -- e_intervaltree_destroy (priv->interval_tree); -+ if (priv->interval_tree) -+ e_intervaltree_destroy (priv->interval_tree); - priv->interval_tree = NULL; - - free_calendar_components (priv->comp_uid_hash, priv->icalcomp); diff --git a/evolution-data-server-3.28.5-cmake-variable-name-comparison.patch b/evolution-data-server-3.28.5-cmake-variable-name-comparison.patch deleted file mode 100644 index 88b9a112e0cbfa45f4b0af044a74932821fce7a0..0000000000000000000000000000000000000000 --- a/evolution-data-server-3.28.5-cmake-variable-name-comparison.patch +++ /dev/null @@ -1,44 +0,0 @@ -diff -up evolution-data-server-3.28.5/cmake/modules/PrintableOptions.cmake.cmake-variable-name-comparison evolution-data-server-3.28.5/cmake/modules/PrintableOptions.cmake ---- evolution-data-server-3.28.5/cmake/modules/PrintableOptions.cmake.cmake-variable-name-comparison 2021-06-16 16:45:58.554763738 +0200 -+++ evolution-data-server-3.28.5/cmake/modules/PrintableOptions.cmake 2021-06-16 16:47:13.343021509 +0200 -@@ -19,32 +19,32 @@ - # prints all the build options previously added with the above functions - - macro(add_printable_variable_bare _name) -- if(_name STREQUAL "") -+ if("${_name}" STREQUAL "") - message(FATAL_ERROR "variable name cannot be empty") -- endif(_name STREQUAL "") -+ endif("${_name}" STREQUAL "") - list(APPEND _printable_options ${_name}) - endmacro() - - macro(add_printable_option _name _description _default_value) -- if(_name STREQUAL "") -+ if("${_name}" STREQUAL "") - message(FATAL_ERROR "option name cannot be empty") -- endif(_name STREQUAL "") -+ endif("${_name}" STREQUAL "") - option(${_name} ${_description} ${_default_value}) - add_printable_variable_bare(${_name}) - endmacro() - - macro(add_printable_variable _name _description _default_value) -- if(_name STREQUAL "") -+ if("${_name}" STREQUAL "") - message(FATAL_ERROR "variable name cannot be empty") -- endif(_name STREQUAL "") -+ endif("${_name}" STREQUAL "") - set(${_name} ${_default_value} CACHE STRING ${_description}) - add_printable_variable_bare(${_name}) - endmacro() - - macro(add_printable_variable_path _name _description _default_value) -- if(_name STREQUAL "") -+ if("${_name}" STREQUAL "") - message(FATAL_ERROR "path variable name cannot be empty") -- endif(_name STREQUAL "") -+ endif("${_name}" STREQUAL "") - set(${_name} ${_default_value} CACHE PATH ${_description}) - add_printable_variable_bare(${_name}) - endmacro() diff --git a/evolution-data-server-3.28.5-cve-2019-3890.patch b/evolution-data-server-3.28.5-cve-2019-3890.patch deleted file mode 100644 index 5a197598d649488e8330b667ef8f9f491522dbee..0000000000000000000000000000000000000000 --- a/evolution-data-server-3.28.5-cve-2019-3890.patch +++ /dev/null @@ -1,18 +0,0 @@ -diff -up evolution-data-server-3.28.5/src/libedataserver/e-data-server-util.c.cve-2019-3890 evolution-data-server-3.28.5/src/libedataserver/e-data-server-util.c ---- evolution-data-server-3.28.5/src/libedataserver/e-data-server-util.c.cve-2019-3890 2019-04-15 09:25:49.273786456 +0200 -+++ evolution-data-server-3.28.5/src/libedataserver/e-data-server-util.c 2019-04-15 09:35:00.784778830 +0200 -@@ -3147,11 +3147,13 @@ e_util_can_use_collection_as_credential_ - if (can_use_collection) { - gchar *method_source, *method_collection; - -- /* Also check the method; if different, then rather not use the collection */ -+ /* Also check the method; if different, then rather not use the collection. -+ Consider 'none' method on the child as the same as the collection method. */ - method_source = e_source_authentication_dup_method (auth_source); - method_collection = e_source_authentication_dup_method (auth_collection); - - can_use_collection = !method_source || !method_collection || -+ g_ascii_strcasecmp (method_source, "none") == 0 || - g_ascii_strcasecmp (method_source, method_collection) == 0; - - g_free (method_source); diff --git a/evolution-data-server-3.28.5-dav-online-load-href.patch b/evolution-data-server-3.28.5-dav-online-load-href.patch deleted file mode 100644 index 91923c539266f022f75bc0b63cd9dfa52b9c913e..0000000000000000000000000000000000000000 --- a/evolution-data-server-3.28.5-dav-online-load-href.patch +++ /dev/null @@ -1,24 +0,0 @@ -diff -up evolution-data-server-3.28.5/src/addressbook/backends/webdav/e-book-backend-webdav.c.dav-online-load-href evolution-data-server-3.28.5/src/addressbook/backends/webdav/e-book-backend-webdav.c ---- evolution-data-server-3.28.5/src/addressbook/backends/webdav/e-book-backend-webdav.c.dav-online-load-href 2018-11-26 12:18:57.874823757 +0100 -+++ evolution-data-server-3.28.5/src/addressbook/backends/webdav/e-book-backend-webdav.c 2018-11-26 12:20:27.967822511 +0100 -@@ -993,6 +993,8 @@ ebb_webdav_load_contact_sync (EBookMetaB - if (!*out_contact) { - success = FALSE; - g_propagate_error (&local_error, EDB_ERROR_EX (E_DATA_BOOK_STATUS_OTHER_ERROR, _("Received object is not a valid vCard"))); -+ } else if (out_extra) { -+ *out_extra = g_strdup (href); - } - } - -diff -up evolution-data-server-3.28.5/src/calendar/backends/caldav/e-cal-backend-caldav.c.dav-online-load-href evolution-data-server-3.28.5/src/calendar/backends/caldav/e-cal-backend-caldav.c ---- evolution-data-server-3.28.5/src/calendar/backends/caldav/e-cal-backend-caldav.c.dav-online-load-href 2018-11-26 12:19:15.809823509 +0100 -+++ evolution-data-server-3.28.5/src/calendar/backends/caldav/e-cal-backend-caldav.c 2018-11-26 12:20:03.976822843 +0100 -@@ -1135,6 +1135,8 @@ ecb_caldav_load_component_sync (ECalMeta - if (!*out_component) { - success = FALSE; - g_propagate_error (&local_error, EDC_ERROR (InvalidObject)); -+ } else if (out_extra) { -+ *out_extra = g_strdup (href); - } - } - diff --git a/evolution-data-server-3.28.5-dav-remove-ignores-not-found.patch b/evolution-data-server-3.28.5-dav-remove-ignores-not-found.patch deleted file mode 100644 index 7caad3e51cae4789086868f571528f3b7f926453..0000000000000000000000000000000000000000 --- a/evolution-data-server-3.28.5-dav-remove-ignores-not-found.patch +++ /dev/null @@ -1,34 +0,0 @@ -diff -up evolution-data-server-3.28.5/src/addressbook/backends/webdav/e-book-backend-webdav.c.dav-remove-ignores-not-found evolution-data-server-3.28.5/src/addressbook/backends/webdav/e-book-backend-webdav.c ---- evolution-data-server-3.28.5/src/addressbook/backends/webdav/e-book-backend-webdav.c.dav-remove-ignores-not-found 2018-11-28 14:31:11.278711852 +0100 -+++ evolution-data-server-3.28.5/src/addressbook/backends/webdav/e-book-backend-webdav.c 2018-11-28 14:32:38.231710649 +0100 -@@ -1160,6 +1160,13 @@ ebb_webdav_remove_contact_sync (EBookMet - g_object_unref (contact); - g_free (etag); - -+ /* Ignore not found errors, this was a delete and the resource is gone. -+ It can be that it had been deleted on the server by other application. */ -+ if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_NOT_FOUND)) { -+ g_clear_error (&local_error); -+ success = TRUE; -+ } -+ - if (local_error) { - ebb_webdav_check_credentials_error (bbdav, webdav, local_error); - g_propagate_error (error, local_error); -diff -up evolution-data-server-3.28.5/src/calendar/backends/caldav/e-cal-backend-caldav.c.dav-remove-ignores-not-found evolution-data-server-3.28.5/src/calendar/backends/caldav/e-cal-backend-caldav.c ---- evolution-data-server-3.28.5/src/calendar/backends/caldav/e-cal-backend-caldav.c.dav-remove-ignores-not-found 2018-11-28 14:30:52.299712114 +0100 -+++ evolution-data-server-3.28.5/src/calendar/backends/caldav/e-cal-backend-caldav.c 2018-11-28 14:31:11.279711852 +0100 -@@ -1320,6 +1320,13 @@ ecb_caldav_remove_component_sync (ECalMe - icalcomponent_free (icalcomp); - g_free (etag); - -+ /* Ignore not found errors, this was a delete and the resource is gone. -+ It can be that it had been deleted on the server by other application. */ -+ if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_NOT_FOUND)) { -+ g_clear_error (&local_error); -+ success = TRUE; -+ } -+ - if (local_error) { - ecb_caldav_check_credentials_error (cbdav, webdav, local_error); - g_propagate_error (error, local_error); diff --git a/evolution-data-server-3.28.5-delay-new-module-load.patch b/evolution-data-server-3.28.5-delay-new-module-load.patch deleted file mode 100644 index ce085064d6ea4330d217a879428c2954dfaeabc3..0000000000000000000000000000000000000000 --- a/evolution-data-server-3.28.5-delay-new-module-load.patch +++ /dev/null @@ -1,125 +0,0 @@ -diff -up evolution-data-server-3.28.5/src/libebackend/e-dbus-server.c.delay-new-module-load evolution-data-server-3.28.5/src/libebackend/e-dbus-server.c ---- evolution-data-server-3.28.5/src/libebackend/e-dbus-server.c.delay-new-module-load 2018-07-30 15:17:06.000000000 +0200 -+++ evolution-data-server-3.28.5/src/libebackend/e-dbus-server.c 2020-01-15 13:29:46.090644022 +0100 -@@ -75,6 +75,78 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE ( - EDBusServer, e_dbus_server, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (E_TYPE_EXTENSIBLE, NULL)) - -+typedef struct _ModuleLoadData { -+ GWeakRef server_wr; -+ gchar *filename; -+} ModuleLoadData; -+ -+static ModuleLoadData * -+module_load_data_new (EDBusServer *server, -+ const gchar *filename) -+{ -+ ModuleLoadData *mld; -+ -+ mld = g_slice_new0 (ModuleLoadData); -+ g_weak_ref_init (&mld->server_wr, server); -+ mld->filename = g_strdup (filename); -+ -+ return mld; -+} -+ -+static void -+module_load_data_free (gpointer ptr) -+{ -+ ModuleLoadData *mld = ptr; -+ -+ if (mld) { -+ g_weak_ref_clear (&mld->server_wr); -+ g_free (mld->filename); -+ g_slice_free (ModuleLoadData, mld); -+ } -+} -+ -+static gboolean -+e_dbus_server_load_module_timeout_cb (gpointer user_data) -+{ -+ ModuleLoadData *mld = user_data; -+ EDBusServer *server; -+ -+ g_return_val_if_fail (mld != NULL, FALSE); -+ -+ server = g_weak_ref_get (&mld->server_wr); -+ if (server) { -+ EModule *module; -+ -+ e_source_registry_debug_print ("Loading module '%s'\n", mld->filename); -+ -+ module = e_module_load_file (mld->filename); -+ if (module) { -+ g_type_module_unuse ((GTypeModule *) module); -+ -+ e_dbus_server_quit (server, E_DBUS_SERVER_EXIT_RELOAD); -+ } -+ -+ g_object_unref (server); -+ } -+ -+ return FALSE; -+} -+ -+static void -+e_dbus_server_schedule_module_load (EDBusServer *server, -+ const gchar *filename) -+{ -+ g_return_if_fail (E_IS_DBUS_SERVER (server)); -+ g_return_if_fail (filename != NULL); -+ -+ e_source_registry_debug_print ("Schedule load of module '%s'\n", filename); -+ -+ /* Delay the load by 10 seconds, in case the module doesn't have placed -+ all its libraries in the expected directories. */ -+ g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, 10, e_dbus_server_load_module_timeout_cb, -+ module_load_data_new (server, filename), module_load_data_free); -+} -+ - static void - dbus_server_bus_acquired_cb (GDBusConnection *connection, - const gchar *bus_name, -@@ -552,38 +624,27 @@ dbus_server_module_directory_changed_cb - if (event_type == G_FILE_MONITOR_EVENT_RENAMED && other_file) { - G_LOCK (loaded_modules); - if (!g_hash_table_contains (loaded_modules, filename)) { -+ gchar *other_filename = g_file_get_path (other_file); -+ e_source_registry_debug_print ("Module file '%s' renamed to '%s'\n", filename, other_filename); - g_free (filename); -- filename = g_file_get_path (other_file); -+ filename = other_filename; - event_type = G_FILE_MONITOR_EVENT_CREATED; - } - G_UNLOCK (loaded_modules); - } - - if (filename && g_str_has_suffix (filename, "." G_MODULE_SUFFIX)) { -- gboolean any_loaded = FALSE; -- - if (event_type == G_FILE_MONITOR_EVENT_CREATED || - event_type == G_FILE_MONITOR_EVENT_MOVED_IN) { - G_LOCK (loaded_modules); - - if (!g_hash_table_contains (loaded_modules, filename)) { -- EModule *module; -- - g_hash_table_add (loaded_modules, g_strdup (filename)); -- -- module = e_module_load_file (filename); -- if (module) { -- any_loaded = TRUE; -- -- g_type_module_unuse ((GTypeModule *) module); -- } -+ e_dbus_server_schedule_module_load (server, filename); - } - - G_UNLOCK (loaded_modules); - } -- -- if (any_loaded) -- e_dbus_server_quit (server, E_DBUS_SERVER_EXIT_RELOAD); - } - - g_free (filename); diff --git a/evolution-data-server-3.28.5-imapx-icloud-mail.patch b/evolution-data-server-3.28.5-imapx-icloud-mail.patch deleted file mode 100644 index 32694a3ed40cd5c7f2941d4acdc96c5ddfe38289..0000000000000000000000000000000000000000 --- a/evolution-data-server-3.28.5-imapx-icloud-mail.patch +++ /dev/null @@ -1,42 +0,0 @@ -diff -up evolution-data-server-3.28.5/src/camel/providers/imapx/camel-imapx-server.c.imapx-icloud-mail evolution-data-server-3.28.5/src/camel/providers/imapx/camel-imapx-server.c ---- evolution-data-server-3.28.5/src/camel/providers/imapx/camel-imapx-server.c.imapx-icloud-mail 2021-04-23 09:30:07.734875376 +0200 -+++ evolution-data-server-3.28.5/src/camel/providers/imapx/camel-imapx-server.c 2021-04-23 09:31:45.321718451 +0200 -@@ -629,6 +629,12 @@ imapx_server_stash_command_arguments (Ca - if (CAMEL_IMAPX_HAVE_CAPABILITY (is->priv->cinfo, SPECIAL_USE) || CAMEL_IMAPX_HAVE_CAPABILITY (is->priv->cinfo, X_GM_EXT_1)) - g_string_append_printf (buffer, " SPECIAL-USE"); - is->priv->list_return_opts = g_string_free (buffer, FALSE); -+ } else if (!is->priv->is_broken_cyrus && CAMEL_IMAPX_HAVE_CAPABILITY (is->priv->cinfo, LIST_STATUS)) { -+ buffer = g_string_new (""); -+ g_string_append_printf ( -+ buffer, "STATUS (%s)", -+ is->priv->status_data_items); -+ is->priv->list_return_opts = g_string_free (buffer, FALSE); - } else { - is->priv->list_return_opts = NULL; - } -@@ -6208,7 +6214,7 @@ camel_imapx_server_list_sync (CamelIMAPX - - camel_imapx_command_unref (ic); - -- if (success && !is->priv->list_return_opts) { -+ if (success && (!is->priv->list_return_opts || CAMEL_IMAPX_LACK_CAPABILITY (is->priv->cinfo, LIST_EXTENDED))) { - ic = camel_imapx_command_new (is, CAMEL_IMAPX_JOB_LSUB, "LSUB \"\" %s", - pattern); - -diff -up evolution-data-server-3.28.5/src/camel/providers/imapx/camel-imapx-utils.c.imapx-icloud-mail evolution-data-server-3.28.5/src/camel/providers/imapx/camel-imapx-utils.c ---- evolution-data-server-3.28.5/src/camel/providers/imapx/camel-imapx-utils.c.imapx-icloud-mail 2018-07-30 15:17:06.000000000 +0200 -+++ evolution-data-server-3.28.5/src/camel/providers/imapx/camel-imapx-utils.c 2021-04-23 09:30:07.736875373 +0200 -@@ -580,13 +580,6 @@ imapx_parse_capability (CamelIMAPXInputS - stream, &token, &len, cancellable, &local_error); - } - -- /* Some capabilities are extensions of other capabilities. -- * Make sure all prerequisite capability flags are present. */ -- -- /* LIST-STATUS is an extension of LIST-EXTENDED. */ -- if (CAMEL_IMAPX_HAVE_CAPABILITY (cinfo, LIST_STATUS)) -- cinfo->capa |= imapx_lookup_capability ("LIST-EXTENDED"); -- - if (local_error != NULL) { - g_propagate_error (error, local_error); - imapx_free_capability (cinfo); diff --git a/evolution-data-server-3.28.5-mangled-deeper-html-quotes.patch b/evolution-data-server-3.28.5-mangled-deeper-html-quotes.patch deleted file mode 100644 index bba30002d17bacece608c86cab71e206f0f4abd3..0000000000000000000000000000000000000000 --- a/evolution-data-server-3.28.5-mangled-deeper-html-quotes.patch +++ /dev/null @@ -1,55 +0,0 @@ -From 6022b2b7816fea84919eef5993363f636bf734dc Mon Sep 17 00:00:00 2001 -From: Milan Crha -Date: Mon, 3 Sep 2018 09:43:50 +0200 -Subject: evo-I#86 - Quoting of plain text mail into HTML mode mangles deeper - levels - -Related to https://gitlab.gnome.org/GNOME/evolution/issues/86 - -diff --git a/src/camel/camel-mime-filter-tohtml.c b/src/camel/camel-mime-filter-tohtml.c -index 07024aa1a..df6283655 100644 ---- a/src/camel/camel-mime-filter-tohtml.c -+++ b/src/camel/camel-mime-filter-tohtml.c -@@ -303,6 +303,7 @@ html_convert (CamelMimeFilter *mime_filter, - outend = mime_filter->outbuf + mime_filter->outsize; - - if (priv->flags & CAMEL_MIME_FILTER_TOHTML_PRE && !priv->pre_open) { -+ outptr = check_size (mime_filter, outptr, &outend, 6); - outptr = g_stpcpy (outptr, "
");
- 		priv->pre_open = TRUE;
- 	}
-@@ -339,13 +340,13 @@ html_convert (CamelMimeFilter *mime_filter,
- 
- 			depth = citation_depth (start, inend, &skip);
- 			while (priv->blockquote_depth < depth) {
--				outptr = check_size (mime_filter, outptr, &outend, 30);
--				outptr = g_stpcpy (outptr, "
\n"); -+ outptr = check_size (mime_filter, outptr, &outend, 25); -+ outptr = g_stpcpy (outptr, "
"); - priv->blockquote_depth++; - } - while (priv->blockquote_depth > depth) { -- outptr = check_size (mime_filter, outptr, &outend, 15); -- outptr = g_stpcpy (outptr, "
\n"); -+ outptr = check_size (mime_filter, outptr, &outend, 14); -+ outptr = g_stpcpy (outptr, "
"); - priv->blockquote_depth--; - } - #if FOOLISHLY_UNMUNGE_FROM -@@ -463,14 +464,14 @@ html_convert (CamelMimeFilter *mime_filter, - outptr, &outend); - - while (priv->blockquote_depth > 0) { -- outptr = check_size (mime_filter, outptr, &outend, 15); -+ outptr = check_size (mime_filter, outptr, &outend, 14); - outptr = g_stpcpy (outptr, ""); - priv->blockquote_depth--; - } - - if (priv->pre_open) { - /* close the pre-tag */ -- outptr = check_size (mime_filter, outptr, &outend, 10); -+ outptr = check_size (mime_filter, outptr, &outend, 7); - outptr = g_stpcpy (outptr, "
"); - priv->pre_open = FALSE; - } diff --git a/evolution-data-server-3.28.5-nonstandard-uuencode-encoding.patch b/evolution-data-server-3.28.5-nonstandard-uuencode-encoding.patch deleted file mode 100644 index 53420b6f46d5332b9971dafaa2b736a7df3f673d..0000000000000000000000000000000000000000 --- a/evolution-data-server-3.28.5-nonstandard-uuencode-encoding.patch +++ /dev/null @@ -1,26 +0,0 @@ -diff -up evolution-data-server-3.28.5/src/camel/camel-folder-summary.c.nonstandard-uuencode-encoding evolution-data-server-3.28.5/src/camel/camel-folder-summary.c ---- evolution-data-server-3.28.5/src/camel/camel-folder-summary.c.nonstandard-uuencode-encoding 2018-07-30 15:17:06.000000000 +0200 -+++ evolution-data-server-3.28.5/src/camel/camel-folder-summary.c 2021-09-30 17:30:47.674951472 +0200 -@@ -3153,7 +3153,8 @@ summary_traverse_content_with_parser (Ca - else - camel_mime_filter_reset (summary->priv->filter_qp); - enc_id = camel_mime_parser_filter_add (mp, summary->priv->filter_qp); -- } else if (!g_ascii_strcasecmp (encoding, "x-uuencode")) { -+ } else if (!g_ascii_strcasecmp (encoding, "x-uuencode") || -+ !g_ascii_strcasecmp (encoding, "uuencode")) { - d (printf (" decoding x-uuencode\n")); - if (summary->priv->filter_uu == NULL) - summary->priv->filter_uu = camel_mime_filter_basic_new (CAMEL_MIME_FILTER_BASIC_UU_DEC); -diff -up evolution-data-server-3.28.5/src/camel/camel-mime-utils.c.nonstandard-uuencode-encoding evolution-data-server-3.28.5/src/camel/camel-mime-utils.c ---- evolution-data-server-3.28.5/src/camel/camel-mime-utils.c.nonstandard-uuencode-encoding 2018-07-30 15:17:06.000000000 +0200 -+++ evolution-data-server-3.28.5/src/camel/camel-mime-utils.c 2021-09-30 17:30:47.674951472 +0200 -@@ -3268,6 +3268,9 @@ camel_transfer_encoding_from_string (con - for (i = 0; i < G_N_ELEMENTS (encodings); i++) - if (!g_ascii_strcasecmp (string, encodings[i])) - return i; -+ -+ if (!g_ascii_strcasecmp (string, "uuencode")) -+ return CAMEL_TRANSFER_ENCODING_UUENCODE; - } - - return CAMEL_TRANSFER_ENCODING_DEFAULT; diff --git a/evolution-data-server-3.28.5-test-cal-meta-backend-without-evolution.patch b/evolution-data-server-3.28.5-test-cal-meta-backend-without-evolution.patch deleted file mode 100644 index d1edbc4ba77b29f19fcbfed4c70ea5f1a1d1923e..0000000000000000000000000000000000000000 --- a/evolution-data-server-3.28.5-test-cal-meta-backend-without-evolution.patch +++ /dev/null @@ -1,117 +0,0 @@ -diff -up evolution-data-server-3.28.5/tests/libedata-cal/components/event-7.ics.test-cal-meta-backend-without-evolution evolution-data-server-3.28.5/tests/libedata-cal/components/event-7.ics ---- evolution-data-server-3.28.5/tests/libedata-cal/components/event-7.ics.test-cal-meta-backend-without-evolution 2020-01-16 08:28:52.842204524 +0100 -+++ evolution-data-server-3.28.5/tests/libedata-cal/components/event-7.ics 2020-01-16 08:30:30.726203170 +0100 -@@ -6,7 +6,7 @@ DTEND;TZID=/freeassociation.sourceforge. - SEQUENCE:1 - SUMMARY:With attachment - TRANSP:OPAQUE --ATTACH:file:///usr/share/icons/hicolor/48x48/apps/evolution.png -+ATTACH:$EVENT1URI$ - CLASS:PUBLIC - CREATED:20170221T125054Z - LAST-MODIFIED:20170221T125054Z -diff -up evolution-data-server-3.28.5/tests/libedata-cal/test-cal-cache-utils.c.test-cal-meta-backend-without-evolution evolution-data-server-3.28.5/tests/libedata-cal/test-cal-cache-utils.c ---- evolution-data-server-3.28.5/tests/libedata-cal/test-cal-cache-utils.c.test-cal-meta-backend-without-evolution 2018-07-30 15:17:06.000000000 +0200 -+++ evolution-data-server-3.28.5/tests/libedata-cal/test-cal-cache-utils.c 2020-01-16 08:28:52.842204524 +0100 -@@ -114,13 +114,10 @@ tcu_fixture_teardown (TCUFixture *fixtur - } - - gchar * --tcu_new_icalstring_from_test_case (const gchar *case_name) -+tcu_get_test_case_filename (const gchar *case_name) - { - gchar *filename; - gchar *case_filename; -- GFile * file; -- GError *error = NULL; -- gchar *icalstring = NULL; - - case_filename = g_strdup_printf ("%s.ics", case_name); - -@@ -132,16 +129,48 @@ tcu_new_icalstring_from_test_case (const - else - filename = g_build_filename (SRCDIR, "..", "libedata-cal", "components", case_filename, NULL); - -+ g_free (case_filename); -+ -+ return filename; -+} -+ -+gchar * -+tcu_new_icalstring_from_test_case (const gchar *case_name) -+{ -+ gchar *filename; -+ GFile * file; -+ GError *error = NULL; -+ gchar *icalstring = NULL, *uripart; -+ -+ filename = tcu_get_test_case_filename (case_name); -+ - file = g_file_new_for_path (filename); - if (!g_file_load_contents (file, NULL, &icalstring, NULL, NULL, &error)) - g_error ( - "Failed to read test iCal string file '%s': %s", - filename, error->message); - -- g_free (case_filename); - g_free (filename); - g_object_unref (file); - -+ uripart = strstr (icalstring, "$EVENT1URI$"); -+ if (uripart) { -+ gchar *uri; -+ GString *str; -+ -+ filename = tcu_get_test_case_filename ("event-1"); -+ uri = g_filename_to_uri (filename, NULL, NULL); -+ g_free (filename); -+ -+ str = g_string_new_len (icalstring, uripart - icalstring); -+ g_string_append (str, uri); -+ g_string_append (str, uripart + 11); -+ g_free (icalstring); -+ g_free (uri); -+ -+ icalstring = g_string_free (str, FALSE); -+ } -+ - return icalstring; - } - -diff -up evolution-data-server-3.28.5/tests/libedata-cal/test-cal-cache-utils.h.test-cal-meta-backend-without-evolution evolution-data-server-3.28.5/tests/libedata-cal/test-cal-cache-utils.h ---- evolution-data-server-3.28.5/tests/libedata-cal/test-cal-cache-utils.h.test-cal-meta-backend-without-evolution 2018-07-30 15:17:06.000000000 +0200 -+++ evolution-data-server-3.28.5/tests/libedata-cal/test-cal-cache-utils.h 2020-01-16 08:28:52.842204524 +0100 -@@ -46,6 +46,7 @@ ECalComponent * tcu_new_component_from_t - void tcu_add_component_from_test_case (TCUFixture *fixture, - const gchar *case_name, - ECalComponent **out_component); -+gchar * tcu_get_test_case_filename (const gchar *case_name); - - G_END_DECLS - -diff -up evolution-data-server-3.28.5/tests/libedata-cal/test-cal-meta-backend.c.test-cal-meta-backend-without-evolution evolution-data-server-3.28.5/tests/libedata-cal/test-cal-meta-backend.c ---- evolution-data-server-3.28.5/tests/libedata-cal/test-cal-meta-backend.c.test-cal-meta-backend-without-evolution 2018-07-30 15:17:06.000000000 +0200 -+++ evolution-data-server-3.28.5/tests/libedata-cal/test-cal-meta-backend.c 2020-01-16 08:28:52.842204524 +0100 -@@ -1274,6 +1274,7 @@ static void - test_get_attachment_uris (ECalMetaBackend *meta_backend) - { - ECalBackendSyncClass *backend_class; -+ gchar *expected_uri, *filename; - GSList *uris = NULL; - GError *error = NULL; - -@@ -1306,7 +1307,13 @@ test_get_attachment_uris (ECalMetaBacken - g_assert_no_error (error); - g_assert_nonnull (uris); - g_assert_cmpint (g_slist_length (uris), ==, 1); -- g_assert_cmpstr (uris->data, ==, "file:///usr/share/icons/hicolor/48x48/apps/evolution.png"); -+ -+ filename = tcu_get_test_case_filename ("event-1"); -+ expected_uri = g_filename_to_uri (filename, NULL, NULL); -+ g_free (filename); -+ -+ g_assert_cmpstr (uris->data, ==, expected_uri); -+ g_free (expected_uri); - - g_slist_free_full (uris, g_free); - } diff --git a/evolution-data-server-3.28.5-tests-cal-client-get-revision.patch b/evolution-data-server-3.28.5-tests-cal-client-get-revision.patch deleted file mode 100644 index 2c776fcd42a048058238551ef96d9234a2def89f..0000000000000000000000000000000000000000 --- a/evolution-data-server-3.28.5-tests-cal-client-get-revision.patch +++ /dev/null @@ -1,100 +0,0 @@ -diff -up evolution-data-server-3.28.5/src/addressbook/libedata-book/e-data-book.c.test-cal-client-get-revision evolution-data-server-3.28.5/src/addressbook/libedata-book/e-data-book.c ---- evolution-data-server-3.28.5/src/addressbook/libedata-book/e-data-book.c.test-cal-client-get-revision 2018-07-30 15:17:06.000000000 +0200 -+++ evolution-data-server-3.28.5/src/addressbook/libedata-book/e-data-book.c 2019-05-23 19:31:07.484064234 +0200 -@@ -1856,6 +1856,12 @@ e_data_book_report_backend_property_chan - g_strfreev (strv); - } - -+ /* Ensure the property change signal on the D-Bus is invoked immediately, not on idle */ -+ g_dbus_interface_skeleton_flush (G_DBUS_INTERFACE_SKELETON (dbus_interface)); -+ -+ if (book->priv->connection && !g_dbus_connection_is_closed (book->priv->connection)) -+ g_dbus_connection_flush_sync (book->priv->connection, NULL, NULL); -+ - /* Disregard anything else. */ - } - -diff -up evolution-data-server-3.28.5/src/calendar/libedata-cal/e-data-cal.c.test-cal-client-get-revision evolution-data-server-3.28.5/src/calendar/libedata-cal/e-data-cal.c ---- evolution-data-server-3.28.5/src/calendar/libedata-cal/e-data-cal.c.test-cal-client-get-revision 2018-07-30 15:17:06.000000000 +0200 -+++ evolution-data-server-3.28.5/src/calendar/libedata-cal/e-data-cal.c 2019-05-23 19:31:07.485064234 +0200 -@@ -2470,6 +2470,12 @@ e_data_cal_report_backend_property_chang - if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) - e_dbus_calendar_set_default_object (dbus_interface, prop_value); - -+ /* Ensure the property change signal on the D-Bus is invoked immediately, not on idle */ -+ g_dbus_interface_skeleton_flush (G_DBUS_INTERFACE_SKELETON (dbus_interface)); -+ -+ if (cal->priv->connection && !g_dbus_connection_is_closed (cal->priv->connection)) -+ g_dbus_connection_flush_sync (cal->priv->connection, NULL, NULL); -+ - /* Disregard anything else. */ - } - -diff -up evolution-data-server-3.28.5/tests/libebook/client/test-book-client-get-revision.c.test-cal-client-get-revision evolution-data-server-3.28.5/tests/libebook/client/test-book-client-get-revision.c ---- evolution-data-server-3.28.5/tests/libebook/client/test-book-client-get-revision.c.test-cal-client-get-revision 2018-07-30 15:17:06.000000000 +0200 -+++ evolution-data-server-3.28.5/tests/libebook/client/test-book-client-get-revision.c 2019-05-23 19:31:07.485064234 +0200 -@@ -48,9 +48,22 @@ get_revision_compare_cycle (EBookClient - if (!e_client_get_backend_property_sync (E_CLIENT (client), CLIENT_BACKEND_PROPERTY_REVISION, &revision_after, NULL, &error)) - g_error ("Error getting book revision: %s", error->message); - -+ /* Sometimes, kind of rarely, the D-Bus property change is not delivered on time, -+ thus give it some time to be received and processed. */ -+ if (g_strcmp0 (revision_before, revision_after) == 0) { -+ g_message (" D-Bus property 'revision' change not received yet, trying to wait a bit"); -+ -+ g_usleep (G_USEC_PER_SEC / 2); -+ -+ g_clear_pointer (&revision_after, g_free); -+ -+ if (!e_client_get_backend_property_sync (E_CLIENT (client), CLIENT_BACKEND_PROPERTY_REVISION, &revision_after, NULL, &error)) -+ g_error ("Error getting book revision: %s", error->message); -+ } -+ - g_assert (revision_before); - g_assert (revision_after); -- g_assert (strcmp (revision_before, revision_after) != 0); -+ g_assert_cmpstr (revision_before, !=, revision_after); - - g_message ( - "Passed cycle, revision before '%s' revision after '%s'", -diff -up evolution-data-server-3.28.5/tests/libecal/client/test-cal-client-get-revision.c.test-cal-client-get-revision evolution-data-server-3.28.5/tests/libecal/client/test-cal-client-get-revision.c ---- evolution-data-server-3.28.5/tests/libecal/client/test-cal-client-get-revision.c.test-cal-client-get-revision 2018-07-30 15:17:06.000000000 +0200 -+++ evolution-data-server-3.28.5/tests/libecal/client/test-cal-client-get-revision.c 2019-05-23 19:31:07.485064234 +0200 -@@ -42,18 +42,34 @@ get_revision_compare_cycle (ECalClient * - - if (!e_client_get_backend_property_sync (E_CLIENT (client), CLIENT_BACKEND_PROPERTY_REVISION, - &revision_before, NULL, &error)) -- g_error ("Error getting book revision: %s", error->message); -+ g_error ("Error getting calendar revision: %s", error->message); - - if (!e_cal_client_create_object_sync (client, icalcomp, &uid, NULL, &error)) - g_error ("Error creating object: %s", error->message); - -+ if (!e_cal_client_remove_object_sync (client, uid, NULL, E_CAL_OBJ_MOD_ALL, NULL, &error)) -+ g_error ("Error removing created object: %s", error->message); -+ - if (!e_client_get_backend_property_sync (E_CLIENT (client), CLIENT_BACKEND_PROPERTY_REVISION, - &revision_after, NULL, &error)) -- g_error ("Error getting book revision: %s", error->message); -+ g_error ("Error getting calendar revision: %s", error->message); -+ -+ /* Sometimes, kind of rarely, the D-Bus property change is not delivered on time, -+ thus give it some time to be received and processed. */ -+ if (g_strcmp0 (revision_before, revision_after) == 0) { -+ g_message (" D-Bus property 'revision' change not received yet, trying to wait a bit"); -+ -+ g_usleep (G_USEC_PER_SEC / 2); -+ -+ g_clear_pointer (&revision_after, g_free); -+ -+ if (!e_client_get_backend_property_sync (E_CLIENT (client), CLIENT_BACKEND_PROPERTY_REVISION, &revision_after, NULL, &error)) -+ g_error ("Error getting book revision: %s", error->message); -+ } - - g_assert (revision_before); - g_assert (revision_after); -- g_assert (strcmp (revision_before, revision_after) != 0); -+ g_assert_cmpstr (revision_before, !=, revision_after); - - g_message ( - "Passed cycle, revision before '%s' revision after '%s'", diff --git a/evolution-data-server-3.28.5-tests-retry-client-open.patch b/evolution-data-server-3.28.5-tests-retry-client-open.patch deleted file mode 100644 index 0d12bff061b5de07efb8754231ca19e883ace650..0000000000000000000000000000000000000000 --- a/evolution-data-server-3.28.5-tests-retry-client-open.patch +++ /dev/null @@ -1,341 +0,0 @@ -diff -up evolution-data-server-3.28.5/src/libebackend/e-data-factory.c.tests-retry-client-open evolution-data-server-3.28.5/src/libebackend/e-data-factory.c ---- evolution-data-server-3.28.5/src/libebackend/e-data-factory.c.tests-retry-client-open 2018-07-30 15:17:06.000000000 +0200 -+++ evolution-data-server-3.28.5/src/libebackend/e-data-factory.c 2018-12-04 10:42:29.837599599 +0100 -@@ -1278,6 +1278,13 @@ data_factory_spawn_subprocess_backend (E - priv = data_factory->priv; - - source = e_source_registry_ref_source (priv->registry, uid); -+ -+ if (!source) { -+ g_set_error ( -+ &error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, -+ _("No such source for UID “%s”"), uid); -+ } -+ - if (source && e_source_has_extension (source, extension_name)) { - ESourceBackend *extension; - -@@ -1372,7 +1379,7 @@ data_factory_spawn_subprocess_backend (E - NULL); - - g_object_unref (subprocess); -- } else { -+ } else if (!error) { - error = g_error_new (G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, - _("Backend factory for source “%s” and extension “%s” cannot be found."), - uid, extension_name); -diff -up evolution-data-server-3.28.5/tests/libecal/client/test-cal-client-get-free-busy.c.tests-retry-client-open evolution-data-server-3.28.5/tests/libecal/client/test-cal-client-get-free-busy.c ---- evolution-data-server-3.28.5/tests/libecal/client/test-cal-client-get-free-busy.c.tests-retry-client-open 2018-12-04 10:43:10.449599037 +0100 -+++ evolution-data-server-3.28.5/tests/libecal/client/test-cal-client-get-free-busy.c 2018-12-04 10:43:19.837598907 +0100 -@@ -94,6 +94,49 @@ teardown_fixture (ETestServerFixture *fi - } - - static void -+add_component_sync (ECalClient *cal_client) -+{ -+ const gchar *comp_str = -+ "BEGIN:VEVENT\r\n" -+ "UID:test-fb-event-1\r\n" -+ "DTSTAMP:20040212T000000Z\r\n" -+ "DTSTART:20040213T060000Z\r\n" -+ "DTEND:20040213T080000Z\r\n" -+ "SUMMARY:Test event\r\n" -+ "TRANSP:OPAQUE\r\n" -+ "CLASS:PUBLIC\r\n" -+ "CREATED:20040211T080000Z\r\n" -+ "LAST-MODIFIED:20040211T080000Z\r\n" -+ "END:VEVENT\r\n"; -+ icalcomponent *icalcomp; -+ GError *error = NULL; -+ -+ icalcomp = icalcomponent_new_from_string (comp_str); -+ g_assert_nonnull (icalcomp); -+ -+ if (!e_cal_client_create_object_sync (cal_client, icalcomp, NULL, NULL, &error)) -+ g_error ("Failed to add component: %s", error ? error->message : "Unknown error"); -+ -+ icalcomponent_free (icalcomp); -+ g_clear_error (&error); -+} -+ -+static void -+wait_for_dbus_signal (GMainLoop *loop) -+{ -+ GMainContext *main_context; -+ gint retries = 0; -+ -+ main_context = g_main_loop_get_context (loop); -+ -+ while (!received_free_busy_data && retries < 5) { -+ retries++; -+ -+ g_main_context_iteration (main_context, TRUE); -+ } -+} -+ -+static void - free_busy_data_cb (ECalClient *client, - const GSList *free_busy, - const gchar *func_name) -@@ -114,9 +157,13 @@ test_get_free_busy_sync (ETestServerFixt - - cal_client = E_TEST_SERVER_UTILS_SERVICE (fixture, ECalClient); - -+ add_component_sync (cal_client); -+ - /* This is set by the free-busy-data callback */ - received_free_busy_data = FALSE; - -+ g_signal_connect (cal_client, "free-busy-data", G_CALLBACK (free_busy_data_cb), (gpointer) G_STRFUNC); -+ - utc = icaltimezone_get_utc_timezone (); - start = time_from_isodate ("20040212T000000Z"); - end = time_add_day_with_zone (start, 2, utc); -@@ -127,6 +174,9 @@ test_get_free_busy_sync (ETestServerFixt - - g_slist_free (users); - -+ wait_for_dbus_signal (fixture->loop); -+ -+ g_assert (received_free_busy_data); - g_assert (freebusy_data); - - g_slist_free_full (freebusy_data, g_object_unref); -@@ -147,6 +197,8 @@ async_get_free_busy_result_ready (GObjec - if (!e_cal_client_get_free_busy_finish (cal_client, result, &freebusy_data, &error)) - g_error ("create object finish: %s", error->message); - -+ wait_for_dbus_signal (loop); -+ - g_assert (received_free_busy_data); - g_assert (freebusy_data); - -@@ -166,6 +218,8 @@ test_get_free_busy_async (ETestServerFix - - cal_client = E_TEST_SERVER_UTILS_SERVICE (fixture, ECalClient); - -+ add_component_sync (cal_client); -+ - /* This is set by the free-busy-data callback */ - received_free_busy_data = FALSE; - -diff -up evolution-data-server-3.28.5/tests/test-server-utils/e-test-server-utils.c.tests-retry-client-open evolution-data-server-3.28.5/tests/test-server-utils/e-test-server-utils.c ---- evolution-data-server-3.28.5/tests/test-server-utils/e-test-server-utils.c.tests-retry-client-open 2018-07-30 15:17:06.000000000 +0200 -+++ evolution-data-server-3.28.5/tests/test-server-utils/e-test-server-utils.c 2018-12-04 10:43:19.838598907 +0100 -@@ -199,6 +199,7 @@ assert_object_finalized (ETestServerFixt - typedef struct { - ETestServerFixture *fixture; - ETestServerClosure *closure; -+ guint retries; - } FixturePair; - - static gboolean -@@ -332,12 +333,15 @@ e_test_server_utils_bootstrap_timeout (F - return FALSE; - } - -+static gboolean e_test_server_utils_retry_open_client_cb (gpointer user_data); -+ - static void - e_test_server_utils_client_ready (GObject *source_object, - GAsyncResult *res, - gpointer user_data) - { - FixturePair *pair = (FixturePair *) user_data; -+ gboolean need_retry = FALSE; - GError *error = NULL; - - switch (pair->closure->type) { -@@ -345,7 +349,10 @@ e_test_server_utils_client_ready (GObjec - pair->fixture->service.book_client = (EBookClient *) - e_book_client_connect_finish (res, &error); - -- if (!pair->fixture->service.book_client) -+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) && -+ pair->retries < 3) -+ need_retry = TRUE; -+ else if (!pair->fixture->service.book_client) - g_error ("Unable to create the test book: %s", error->message); - - break; -@@ -353,7 +360,10 @@ e_test_server_utils_client_ready (GObjec - pair->fixture->service.book_client = (EBookClient *) - e_book_client_connect_direct_finish (res, &error); - -- if (!pair->fixture->service.book_client) -+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) && -+ pair->retries < 3) -+ need_retry = TRUE; -+ else if (!pair->fixture->service.book_client) - g_error ("Unable to create the test book: %s", error->message); - - break; -@@ -361,7 +371,10 @@ e_test_server_utils_client_ready (GObjec - pair->fixture->service.calendar_client = (ECalClient *) - e_cal_client_connect_finish (res, &error); - -- if (!pair->fixture->service.calendar_client) -+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) && -+ pair->retries < 3) -+ need_retry = TRUE; -+ else if (!pair->fixture->service.calendar_client) - g_error ("Unable to create the test calendar: %s", error->message); - - break; -@@ -371,6 +384,14 @@ e_test_server_utils_client_ready (GObjec - g_assert_not_reached (); - } - -+ g_clear_error (&error); -+ -+ if (need_retry) { -+ pair->retries++; -+ g_timeout_add_seconds (1, e_test_server_utils_retry_open_client_cb, pair); -+ return; -+ } -+ - /* Track ref counts now that we have a client */ - add_weak_ref (pair->fixture, pair->closure->type); - -@@ -382,6 +403,7 @@ e_test_server_utils_source_added (ESourc - ESource *source, - FixturePair *pair) - { -+ gboolean need_retry = FALSE; - GError *error = NULL; - - if (g_strcmp0 (e_source_get_uid (source), pair->fixture->source_name) != 0) -@@ -409,8 +431,13 @@ e_test_server_utils_source_added (ESourc - } - - if (!pair->closure->use_async_connect && -- !pair->fixture->service.book_client) -- g_error ("Unable to create the test book: %s", error ? error->message : "Unknown error"); -+ !pair->fixture->service.book_client) { -+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) && -+ pair->retries < 3) -+ need_retry = TRUE; -+ else -+ g_error ("Unable to create the test book: %s", error ? error->message : "Unknown error"); -+ } - - break; - -@@ -418,11 +445,23 @@ e_test_server_utils_source_added (ESourc - - /* Dont bother testing the Async apis for deprecated APIs */ - pair->fixture->service.book = e_book_new (source, &error); -- if (!pair->fixture->service.book) -- g_error ("Unable to create the test book: %s", error->message); -+ if (!pair->fixture->service.book) { -+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) && -+ pair->retries < 3) -+ need_retry = TRUE; -+ else -+ g_error ("Unable to create the test book: %s", error->message); -+ -+ break; -+ } - -- if (!e_book_open (pair->fixture->service.book, FALSE, &error)) -- g_error ("Unable to open book: %s", error->message); -+ if (!e_book_open (pair->fixture->service.book, FALSE, &error)) { -+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) && -+ pair->retries < 3) -+ need_retry = TRUE; -+ else -+ g_error ("Unable to open book: %s", error->message); -+ } - - break; - -@@ -439,8 +478,13 @@ e_test_server_utils_source_added (ESourc - e_cal_client_connect_sync ( - source, - pair->closure->calendar_source_type, (guint32) -1, NULL, &error); -- if (!pair->fixture->service.calendar_client) -- g_error ("Unable to create the test calendar: %s", error->message); -+ if (!pair->fixture->service.calendar_client) { -+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) && -+ pair->retries < 3) -+ need_retry = TRUE; -+ else -+ g_error ("Unable to create the test calendar: %s", error->message); -+ } - } - - break; -@@ -449,11 +493,22 @@ e_test_server_utils_source_added (ESourc - - /* Dont bother testing the Async apis for deprecated APIs */ - pair->fixture->service.calendar = e_cal_new (source, pair->closure->calendar_source_type); -- if (!pair->fixture->service.calendar) -- g_error ("Unable to create the test calendar"); -+ if (!pair->fixture->service.calendar) { -+ if (pair->retries < 3) -+ need_retry = TRUE; -+ else -+ g_error ("Unable to create the test calendar"); - -- if (!e_cal_open (pair->fixture->service.calendar, FALSE, &error)) -- g_error ("Unable to open calendar: %s", error->message); -+ break; -+ } -+ -+ if (!e_cal_open (pair->fixture->service.calendar, FALSE, &error)) { -+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND) && -+ pair->retries < 3) -+ need_retry = TRUE; -+ else -+ g_error ("Unable to open calendar: %s", error->message); -+ } - - break; - -@@ -461,6 +516,14 @@ e_test_server_utils_source_added (ESourc - return; - } - -+ g_clear_error (&error); -+ -+ if (need_retry) { -+ pair->retries++; -+ g_timeout_add_seconds (1, e_test_server_utils_retry_open_client_cb, pair); -+ return; -+ } -+ - /* Add the weak ref now if we just created it */ - if (pair->closure->type != E_TEST_SERVER_NONE && - pair->closure->use_async_connect == FALSE) -@@ -471,6 +534,22 @@ e_test_server_utils_source_added (ESourc - } - - static gboolean -+e_test_server_utils_retry_open_client_cb (gpointer user_data) -+{ -+ FixturePair *pair = user_data; -+ ESource *source; -+ -+ source = e_source_registry_ref_source (pair->fixture->registry, pair->fixture->source_name); -+ -+ g_assert (E_IS_SOURCE (source)); -+ -+ e_test_server_utils_source_added (pair->fixture->registry, source, pair); -+ g_object_unref (source); -+ -+ return FALSE; -+} -+ -+static gboolean - e_test_server_utils_bootstrap_idle (FixturePair *pair) - { - ESourceBackend *backend = NULL; -@@ -578,7 +657,7 @@ e_test_server_utils_setup (ETestServerFi - gconstpointer user_data) - { - ETestServerClosure *closure = (ETestServerClosure *) user_data; -- FixturePair pair = { fixture, closure }; -+ FixturePair pair = { fixture, closure, 0 }; - - /* Create work directory */ - if (!test_installed_services ()) diff --git a/evolution-data-server-3.28.5-vcard-attr-param-struct-reff.patch b/evolution-data-server-3.28.5-vcard-attr-param-struct-reff.patch deleted file mode 100644 index 35b49409be5e4ad814faa70fc5b43ffb2ab9bc8b..0000000000000000000000000000000000000000 --- a/evolution-data-server-3.28.5-vcard-attr-param-struct-reff.patch +++ /dev/null @@ -1,179 +0,0 @@ -diff --git a/src/addressbook/libebook-contacts/e-vcard.c b/src/addressbook/libebook-contacts/e-vcard.c -index e44b7fdcf..680cf85af 100644 ---- a/src/addressbook/libebook-contacts/e-vcard.c -+++ b/src/addressbook/libebook-contacts/e-vcard.c -@@ -120,6 +120,14 @@ - - G_DEFINE_TYPE (EVCard, e_vcard, G_TYPE_OBJECT) - -+static EVCardAttribute *e_vcard_attribute_ref (EVCardAttribute *attr); -+static void e_vcard_attribute_unref (EVCardAttribute *attr); -+static EVCardAttributeParam *e_vcard_attribute_param_ref (EVCardAttributeParam *param); -+static void e_vcard_attribute_param_unref (EVCardAttributeParam *param); -+ -+G_DEFINE_BOXED_TYPE (EVCardAttribute, e_vcard_attribute, e_vcard_attribute_ref, e_vcard_attribute_unref) -+G_DEFINE_BOXED_TYPE (EVCardAttributeParam, e_vcard_attribute_param, e_vcard_attribute_param_ref, e_vcard_attribute_param_unref) -+ - /* Encoding used in v-card - * Note: v-card spec defines additional 7BIT 8BIT and X- encoding - */ -@@ -135,6 +143,7 @@ struct _EVCardPrivate { - }; - - struct _EVCardAttribute { -+ gint ref_count; - gchar *group; - gchar *name; - GList *params; /* EVCardParam */ -@@ -145,6 +154,7 @@ struct _EVCardAttribute { - }; - - struct _EVCardAttributeParam { -+ gint ref_count; - gchar *name; - GList *values; /* GList of gchar *'s */ - }; -@@ -1555,6 +1565,7 @@ e_vcard_attribute_new (const gchar *attr_group, - if (attr_group != NULL && *attr_group == '\0') - attr_group = NULL; - -+ attr->ref_count = 1; - attr->group = g_strdup (attr_group); - attr->name = g_strdup (attr_name); - -@@ -1572,14 +1583,34 @@ e_vcard_attribute_free (EVCardAttribute *attr) - { - g_return_if_fail (attr != NULL); - -- g_free (attr->group); -- g_free (attr->name); -+ e_vcard_attribute_unref (attr); -+} - -- e_vcard_attribute_remove_values (attr); -+static EVCardAttribute * -+e_vcard_attribute_ref (EVCardAttribute *attr) -+{ -+ g_return_val_if_fail (attr != NULL, NULL); - -- e_vcard_attribute_remove_params (attr); -+ g_atomic_int_inc (&attr->ref_count); - -- g_slice_free (EVCardAttribute, attr); -+ return attr; -+} -+ -+static void -+e_vcard_attribute_unref (EVCardAttribute *attr) -+{ -+ g_return_if_fail (attr != NULL); -+ -+ if (g_atomic_int_dec_and_test (&attr->ref_count)) { -+ g_free (attr->group); -+ g_free (attr->name); -+ -+ e_vcard_attribute_remove_values (attr); -+ -+ e_vcard_attribute_remove_params (attr); -+ -+ g_slice_free (EVCardAttribute, attr); -+ } - } - - /** -@@ -1609,25 +1640,6 @@ e_vcard_attribute_copy (EVCardAttribute *attr) - return a; - } - --GType --e_vcard_attribute_get_type (void) --{ -- static volatile gsize type_id__volatile = 0; -- -- if (g_once_init_enter (&type_id__volatile)) { -- GType type_id; -- -- type_id = g_boxed_type_register_static ( -- "EVCardAttribute", -- (GBoxedCopyFunc) e_vcard_attribute_copy, -- (GBoxedFreeFunc) e_vcard_attribute_free); -- -- g_once_init_leave (&type_id__volatile, type_id); -- } -- -- return type_id__volatile; --} -- - /** - * e_vcard_remove_attributes: - * @evc: vcard object -@@ -2068,25 +2080,6 @@ e_vcard_attribute_remove_params (EVCardAttribute *attr) - attr->encoding = EVC_ENCODING_RAW; - } - --GType --e_vcard_attribute_param_get_type (void) --{ -- static volatile gsize type_id__volatile = 0; -- -- if (g_once_init_enter (&type_id__volatile)) { -- GType type_id; -- -- type_id = g_boxed_type_register_static ( -- "EVCardAttributeParam", -- (GBoxedCopyFunc) e_vcard_attribute_param_copy, -- (GBoxedFreeFunc) e_vcard_attribute_param_free); -- -- g_once_init_leave (&type_id__volatile, type_id); -- } -- -- return type_id__volatile; --} -- - /** - * e_vcard_attribute_param_new: - * @name: the name of the new parameter -@@ -2099,6 +2092,8 @@ EVCardAttributeParam * - e_vcard_attribute_param_new (const gchar *name) - { - EVCardAttributeParam *param = g_slice_new (EVCardAttributeParam); -+ -+ param->ref_count = 1; - param->values = NULL; - param->name = g_strdup (name); - -@@ -2116,11 +2111,31 @@ e_vcard_attribute_param_free (EVCardAttributeParam *param) - { - g_return_if_fail (param != NULL); - -- g_free (param->name); -+ e_vcard_attribute_param_unref (param); -+} -+ -+static EVCardAttributeParam * -+e_vcard_attribute_param_ref (EVCardAttributeParam *param) -+{ -+ g_return_val_if_fail (param != NULL, NULL); -+ -+ g_atomic_int_inc (¶m->ref_count); -+ -+ return param; -+} -+ -+static void -+e_vcard_attribute_param_unref (EVCardAttributeParam *param) -+{ -+ g_return_if_fail (param != NULL); -+ -+ if (g_atomic_int_dec_and_test (¶m->ref_count)) { -+ g_free (param->name); - -- e_vcard_attribute_param_remove_values (param); -+ e_vcard_attribute_param_remove_values (param); - -- g_slice_free (EVCardAttributeParam, param); -+ g_slice_free (EVCardAttributeParam, param); -+ } - } - - /** diff --git a/evolution-data-server-3.28.5-vcard-remove-param-value.patch b/evolution-data-server-3.28.5-vcard-remove-param-value.patch deleted file mode 100644 index 3471410f3e017a8fcf02ee3c65ef51a575493ffb..0000000000000000000000000000000000000000 --- a/evolution-data-server-3.28.5-vcard-remove-param-value.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff --git a/src/addressbook/libebook-contacts/e-vcard.c b/src/addressbook/libebook-contacts/e-vcard.c -index f11a17d77..e44b7fdcf 100644 ---- a/src/addressbook/libebook-contacts/e-vcard.c -+++ b/src/addressbook/libebook-contacts/e-vcard.c -@@ -2395,8 +2395,8 @@ e_vcard_attribute_remove_param_value (EVCardAttribute *attr, - return; - } - -- param->values = g_list_delete_link (param->values, l); - g_free (l->data); -+ param->values = g_list_delete_link (param->values, l); - - if (param->values == NULL) { - e_vcard_attribute_param_free (param); diff --git a/evolution-data-server-3.40.4-caldav-crash.patch b/evolution-data-server-3.40.4-caldav-crash.patch new file mode 100644 index 0000000000000000000000000000000000000000..7db499bc9e97bacdf5cb98cc4fe10586b8f5ddb9 --- /dev/null +++ b/evolution-data-server-3.40.4-caldav-crash.patch @@ -0,0 +1,36 @@ +From ad616bafcf7df22d265f7254c82ec285252bf1e7 Mon Sep 17 00:00:00 2001 +From: Milan Crha +Date: Tue, 24 May 2022 18:27:09 +0200 +Subject: [PATCH] I#359 - CalDAV: Crash on calendar update + +Closes https://gitlab.gnome.org/GNOME/evolution-data-server/-/issues/359 +--- + src/calendar/backends/caldav/e-cal-backend-caldav.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/src/calendar/backends/caldav/e-cal-backend-caldav.c b/src/calendar/backends/caldav/e-cal-backend-caldav.c +index c8aeb8205..2aeed3c91 100644 +--- a/src/calendar/backends/caldav/e-cal-backend-caldav.c ++++ b/src/calendar/backends/caldav/e-cal-backend-caldav.c +@@ -545,7 +545,8 @@ ecb_caldav_multiget_from_sets_sync (ECalBackendCalDAV *cbdav, + link = *in_link; + + while (link && left_to_go > 0) { +- ECalMetaBackendInfo *nfo = link->data; ++ GSList *nfo_link = link; ++ ECalMetaBackendInfo *nfo = nfo_link->data; + + link = g_slist_next (link); + if (!link) { +@@ -635,7 +636,7 @@ ecb_caldav_multiget_from_sets_sync (ECalBackendCalDAV *cbdav, + else + e_cal_meta_backend_info_free (nfo); + +- link->data = NULL; ++ nfo_link->data = NULL; + g_clear_error (&local_error); + continue; + } else if (local_error) { +-- +2.35.1 + diff --git a/evolution-data-server-3.40.4-google-contacts-to-carddav.patch b/evolution-data-server-3.40.4-google-contacts-to-carddav.patch new file mode 100644 index 0000000000000000000000000000000000000000..5fc068b2a0e1039fade8c17bf4ed22c7531cfa11 --- /dev/null +++ b/evolution-data-server-3.40.4-google-contacts-to-carddav.patch @@ -0,0 +1,4025 @@ +From d63a1ce3921a6a6c573a6a70dbf2e152adf74c3f Mon Sep 17 00:00:00 2001 +From: Milan Crha +Date: Thu, 3 Jun 2021 17:43:27 +0200 +Subject: [PATCH] Addressbook: Switch from GData Contacts API to CardDAV API + for Google books + +The GData Contacts API is going to be shut down [1], thus move to +the CardDAV API, which the Google server supports too. + +[1] https://developers.google.com/contacts/v3/announcement + +Related to https://gitlab.gnome.org/GNOME/libgdata/-/issues/42 +--- + po/POTFILES.in | 2 - + src/addressbook/backends/CMakeLists.txt | 4 - + .../backends/carddav/e-book-backend-carddav.c | 3 +- + .../backends/google/CMakeLists.txt | 100 - + .../google/e-book-backend-google-factory.c | 78 - + .../backends/google/e-book-backend-google.c | 1371 ------------- + .../backends/google/e-book-backend-google.h | 63 - + .../backends/google/e-book-google-utils.c | 1747 ----------------- + .../backends/google/e-book-google-utils.h | 69 - + .../backends/google/tests/CMakeLists.txt | 38 - + .../backends/google/tests/phone-numbers.c | 125 -- + .../google-backend/module-google-backend.c | 141 +- + ...evolution-source-registry-migrate-tweaks.c | 51 + + 13 files changed, 65 insertions(+), 3727 deletions(-) + delete mode 100644 src/addressbook/backends/google/CMakeLists.txt + delete mode 100644 src/addressbook/backends/google/e-book-backend-google-factory.c + delete mode 100644 src/addressbook/backends/google/e-book-backend-google.c + delete mode 100644 src/addressbook/backends/google/e-book-backend-google.h + delete mode 100644 src/addressbook/backends/google/e-book-google-utils.c + delete mode 100644 src/addressbook/backends/google/e-book-google-utils.h + delete mode 100644 src/addressbook/backends/google/tests/CMakeLists.txt + delete mode 100644 src/addressbook/backends/google/tests/phone-numbers.c + +diff --git a/po/POTFILES.in b/po/POTFILES.in +index 9a25ab509..111edaa5d 100644 +--- a/po/POTFILES.in ++++ b/po/POTFILES.in +@@ -4,8 +4,6 @@ + src/addressbook/backends/carddav/e-book-backend-carddav.c + src/addressbook/backends/file/e-book-backend-file.c + src/addressbook/backends/file/e-book-backend-file-migrate-bdb.c +-src/addressbook/backends/google/e-book-backend-google.c +-src/addressbook/backends/google/e-book-google-utils.c + src/addressbook/backends/ldap/e-book-backend-ldap.c + src/addressbook/libebook-contacts/e-book-contacts-utils.c + src/addressbook/libebook-contacts/e-contact.c +diff --git a/src/addressbook/backends/CMakeLists.txt b/src/addressbook/backends/CMakeLists.txt +index dced9968e..f38ad6ac1 100644 +--- a/src/addressbook/backends/CMakeLists.txt ++++ b/src/addressbook/backends/CMakeLists.txt +@@ -1,10 +1,6 @@ + add_subdirectory(carddav) + add_subdirectory(file) + +-if(ENABLE_GOOGLE) +- add_subdirectory(google) +-endif(ENABLE_GOOGLE) +- + if(HAVE_LDAP) + add_subdirectory(ldap) + endif(HAVE_LDAP) +diff --git a/src/addressbook/backends/carddav/e-book-backend-carddav.c b/src/addressbook/backends/carddav/e-book-backend-carddav.c +index 0f587eaef..faf90b127 100644 +--- a/src/addressbook/backends/carddav/e-book-backend-carddav.c ++++ b/src/addressbook/backends/carddav/e-book-backend-carddav.c +@@ -165,7 +165,8 @@ ebb_carddav_connect_sync (EBookMetaBackend *meta_backend, + } + + g_free (path); +- } else if (soup_uri->host && e_util_utf8_strstrcase (soup_uri->host, ".googleusercontent.com")) { ++ } else if (soup_uri->host && (e_util_utf8_strstrcase (soup_uri->host, ".googleusercontent.com") || ++ e_util_utf8_strstrcase (soup_uri->host, ".googleapis.com"))) { + g_clear_error (&local_error); + success = TRUE; + +diff --git a/src/addressbook/backends/google/CMakeLists.txt b/src/addressbook/backends/google/CMakeLists.txt +deleted file mode 100644 +index 09e2beeae..000000000 +--- a/src/addressbook/backends/google/CMakeLists.txt ++++ /dev/null +@@ -1,100 +0,0 @@ +-set(DEPENDENCIES +- ebackend +- ebook +- ebook-contacts +- edataserver +- edata-book +-) +- +-add_library(ebookbackendgoogle MODULE +- e-book-backend-google-factory.c +- e-book-backend-google.c +- e-book-backend-google.h +- e-book-google-utils.c +- e-book-google-utils.h +-) +- +-add_dependencies(ebookbackendgoogle +- ${DEPENDENCIES} +-) +- +-target_compile_definitions(ebookbackendgoogle PRIVATE +- -DG_LOG_DOMAIN=\"e-book-backend-google\" +- -DBACKENDDIR=\"${ebook_backenddir}\" +-) +- +-target_compile_options(ebookbackendgoogle PUBLIC +- ${ADDRESSBOOK_CFLAGS} +- ${LIBGDATA_CFLAGS} +-) +- +-target_include_directories(ebookbackendgoogle PUBLIC +- ${CMAKE_BINARY_DIR} +- ${CMAKE_BINARY_DIR}/src +- ${CMAKE_SOURCE_DIR}/src +- ${CMAKE_BINARY_DIR}/src/addressbook +- ${CMAKE_SOURCE_DIR}/src/addressbook +- ${ADDRESSBOOK_INCLUDE_DIRS} +- ${LIBGDATA_INCLUDE_DIRS} +-) +- +-target_link_libraries(ebookbackendgoogle +- ${DEPENDENCIES} +- ${ADDRESSBOOK_LDFLAGS} +- ${LIBGDATA_LDFLAGS} +-) +- +-install(TARGETS ebookbackendgoogle +- DESTINATION ${ebook_backenddir} +-) +- +-# Private utility library. +-# This is split out to allow it to be unit tested. +- +-set(SOURCES +- e-book-google-utils.c +- e-book-google-utils.h +-) +- +-add_library(ebook-google-utils STATIC +- ${SOURCES} +-) +- +-add_dependencies(ebook-google-utils +- ebackend +- ebook +- ebook-contacts +- edataserver +- edata-book +-) +- +-target_compile_definitions(ebook-google-utils PRIVATE +- -DG_LOG_DOMAIN=\"e-book-google-utils\" +-) +- +-target_compile_options(ebook-google-utils PUBLIC +- ${ADDRESSBOOK_CFLAGS} +- ${LIBGDATA_CFLAGS} +-) +- +-target_include_directories(ebook-google-utils PUBLIC +- ${CMAKE_BINARY_DIR} +- ${CMAKE_BINARY_DIR}/src +- ${CMAKE_SOURCE_DIR}/src +- ${CMAKE_BINARY_DIR}/src/addressbook +- ${CMAKE_SOURCE_DIR}/src/addressbook +- ${ADDRESSBOOK_INCLUDE_DIRS} +- ${LIBGDATA_INCLUDE_DIRS} +-) +- +-target_link_libraries(ebook-google-utils +- ebackend +- ebook +- ebook-contacts +- edataserver +- edata-book +- ${ADDRESSBOOK_LDFLAGS} +- ${LIBGDATA_LDFLAGS} +-) +- +-add_subdirectory(tests) +diff --git a/src/addressbook/backends/google/e-book-backend-google-factory.c b/src/addressbook/backends/google/e-book-backend-google-factory.c +deleted file mode 100644 +index 68b4d5189..000000000 +--- a/src/addressbook/backends/google/e-book-backend-google-factory.c ++++ /dev/null +@@ -1,78 +0,0 @@ +-/* e-book-backend-google-factory.c - Google contact backend factory. +- * +- * Copyright (C) 2008 Joergen Scheibengruber +- * +- * This library is free software: you can redistribute it and/or modify it +- * under the terms of the GNU Lesser General Public License as published by +- * the Free Software Foundation. +- * +- * This library is distributed in the hope that it will be useful, but +- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License +- * for more details. +- * +- * You should have received a copy of the GNU Lesser General Public License +- * along with this library. If not, see . +- * +- * Authors: Joergen Scheibengruber +- */ +- +-#include "evolution-data-server-config.h" +- +-#include "e-book-backend-google.h" +- +-#define FACTORY_NAME "google" +- +-typedef EBookBackendFactory EBookBackendGoogleFactory; +-typedef EBookBackendFactoryClass EBookBackendGoogleFactoryClass; +- +-static EModule *e_module; +- +-/* Module Entry Points */ +-void e_module_load (GTypeModule *type_module); +-void e_module_unload (GTypeModule *type_module); +- +-/* Forward Declarations */ +-GType e_book_backend_google_factory_get_type (void); +- +-G_DEFINE_DYNAMIC_TYPE ( +- EBookBackendGoogleFactory, +- e_book_backend_google_factory, +- E_TYPE_BOOK_BACKEND_FACTORY) +- +-static void +-e_book_backend_google_factory_class_init (EBookBackendFactoryClass *class) +-{ +- EBackendFactoryClass *backend_factory_class; +- +- backend_factory_class = E_BACKEND_FACTORY_CLASS (class); +- backend_factory_class->e_module = e_module; +- backend_factory_class->share_subprocess = TRUE; +- +- class->factory_name = FACTORY_NAME; +- class->backend_type = E_TYPE_BOOK_BACKEND_GOOGLE; +-} +- +-static void +-e_book_backend_google_factory_class_finalize (EBookBackendFactoryClass *class) +-{ +-} +- +-static void +-e_book_backend_google_factory_init (EBookBackendFactory *factory) +-{ +-} +- +-G_MODULE_EXPORT void +-e_module_load (GTypeModule *type_module) +-{ +- e_module = E_MODULE (type_module); +- +- e_book_backend_google_factory_register_type (type_module); +-} +- +-G_MODULE_EXPORT void +-e_module_unload (GTypeModule *type_module) +-{ +- e_module = NULL; +-} +diff --git a/src/addressbook/backends/google/e-book-backend-google.c b/src/addressbook/backends/google/e-book-backend-google.c +deleted file mode 100644 +index 4597169eb..000000000 +--- a/src/addressbook/backends/google/e-book-backend-google.c ++++ /dev/null +@@ -1,1371 +0,0 @@ +-/* e-book-backend-google.c - Google contact backendy. +- * +- * Copyright (C) 2008 Joergen Scheibengruber +- * Copyright (C) 2010, 2011 Philip Withnall +- * Copyright (C) 2017 Red Hat, Inc. (www.redhat.com) +- * +- * This library is free software: you can redistribute it and/or modify it +- * under the terms of the GNU Lesser General Public License as published by +- * the Free Software Foundation. +- * +- * This library is distributed in the hope that it will be useful, but +- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License +- * for more details. +- * +- * You should have received a copy of the GNU Lesser General Public License +- * along with this library. If not, see . +- * +- * Authors: Joergen Scheibengruber +- * Philip Withnall +- */ +- +-#include "evolution-data-server-config.h" +- +-#include +-#include +- +-#include +-#include +- +-#include "libedataserver/libedataserver.h" +- +-#include "e-book-backend-google.h" +-#include "e-book-google-utils.h" +- +-#ifdef G_OS_WIN32 +-#ifdef gmtime_r +-#undef gmtime_r +-#endif +- +-/* The gmtime() in Microsoft's C library is MT-safe */ +-#define gmtime_r(tp,tmp) (gmtime(tp)?(*(tmp)=*gmtime(tp),(tmp)):0) +-#endif +- +-#define URI_GET_CONTACTS "https://www.google.com/m8/feeds/contacts/default/full" +- +-/* Local cache data version. Change it to re-download whole book content */ +-#define EBB_GOOGLE_DATA_VERSION 2 +- +-struct _EBookBackendGooglePrivate { +- /* For all the group-related members */ +- GRecMutex groups_lock; +- /* Mapping from group ID to (human readable) group name */ +- GHashTable *groups_by_id; +- /* Mapping from (human readable) group name to group ID */ +- GHashTable *groups_by_name; +- /* Mapping system_group_id to entry ID */ +- GHashTable *system_groups_by_id; +- /* Mapping entry ID to system_group_id */ +- GHashTable *system_groups_by_entry_id; +- /* Time when the groups were last queried */ +- GTimeVal groups_last_update; +- /* Did the server-side groups change? If so, re-download the book */ +- gboolean groups_changed; +- +- GRecMutex conn_lock; +- GDataAuthorizer *authorizer; +- GDataService *service; +- GHashTable *preloaded; /* gchar *uid ~> EContact * */ +-}; +- +-G_DEFINE_TYPE_WITH_PRIVATE (EBookBackendGoogle, e_book_backend_google, E_TYPE_BOOK_META_BACKEND) +- +-static void +-ebb_google_data_book_error_from_gdata_error (GError **error, +- const GError *gdata_error) +-{ +- gboolean use_fallback = FALSE; +- +- g_return_if_fail (gdata_error != NULL); +- +- if (!error) +- return; +- +- /* Authentication errors */ +- if (gdata_error->domain == GDATA_SERVICE_ERROR) { +- switch (gdata_error->code) { +- case GDATA_SERVICE_ERROR_UNAVAILABLE: +- g_propagate_error (error, +- e_client_error_create (E_CLIENT_ERROR_REPOSITORY_OFFLINE, NULL)); +- break; +- case GDATA_SERVICE_ERROR_PROTOCOL_ERROR: +- g_propagate_error (error, +- e_client_error_create (E_CLIENT_ERROR_INVALID_QUERY, gdata_error->message)); +- break; +- case GDATA_SERVICE_ERROR_ENTRY_ALREADY_INSERTED: +- g_propagate_error (error, +- e_book_client_error_create (E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS, NULL)); +- break; +- case GDATA_SERVICE_ERROR_AUTHENTICATION_REQUIRED: +- g_propagate_error (error, +- e_client_error_create (E_CLIENT_ERROR_AUTHENTICATION_REQUIRED, NULL)); +- break; +- case GDATA_SERVICE_ERROR_NOT_FOUND: +- g_propagate_error (error, +- e_book_client_error_create (E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND, NULL)); +- break; +- case GDATA_SERVICE_ERROR_CONFLICT: +- g_propagate_error (error, +- e_book_client_error_create (E_BOOK_CLIENT_ERROR_CONTACT_ID_ALREADY_EXISTS, NULL)); +- break; +- case GDATA_SERVICE_ERROR_FORBIDDEN: +- g_propagate_error (error, +- e_client_error_create (E_CLIENT_ERROR_QUERY_REFUSED, NULL)); +- break; +- case GDATA_SERVICE_ERROR_BAD_QUERY_PARAMETER: +- g_propagate_error (error, +- e_client_error_create (E_CLIENT_ERROR_INVALID_QUERY, gdata_error->message)); +- break; +- default: +- use_fallback = TRUE; +- break; +- } +- +- } else { +- use_fallback = TRUE; +- } +- +- /* Generic fallback */ +- if (use_fallback) { +- g_propagate_error (error, +- e_client_error_create (E_CLIENT_ERROR_OTHER_ERROR, gdata_error->message)); +- } +-} +- +-static gboolean +-ebb_google_is_authorized_locked (EBookBackendGoogle *bbgoogle) +-{ +- g_return_val_if_fail (E_IS_BOOK_BACKEND_GOOGLE (bbgoogle), FALSE); +- +- if (!bbgoogle->priv->service) +- return FALSE; +- +- return gdata_service_is_authorized (GDATA_SERVICE (bbgoogle->priv->service)); +-} +- +-static gboolean +-ebb_google_request_authorization_locked (EBookBackendGoogle *bbgoogle, +- const ENamedParameters *credentials, +- GCancellable *cancellable, +- GError **error) +-{ +- /* Make sure we have the GDataService configured +- * before requesting authorization. */ +- +- if (!bbgoogle->priv->authorizer) { +- ESource *source; +- EGDataOAuth2Authorizer *authorizer; +- +- source = e_backend_get_source (E_BACKEND (bbgoogle)); +- +- authorizer = e_gdata_oauth2_authorizer_new (source, GDATA_TYPE_CONTACTS_SERVICE); +- bbgoogle->priv->authorizer = GDATA_AUTHORIZER (authorizer); +- } +- +- if (E_IS_GDATA_OAUTH2_AUTHORIZER (bbgoogle->priv->authorizer)) { +- e_gdata_oauth2_authorizer_set_credentials (E_GDATA_OAUTH2_AUTHORIZER (bbgoogle->priv->authorizer), credentials); +- } +- +- if (!bbgoogle->priv->service) { +- GDataContactsService *contacts_service; +- +- contacts_service = gdata_contacts_service_new (bbgoogle->priv->authorizer); +- bbgoogle->priv->service = GDATA_SERVICE (contacts_service); +- +- e_binding_bind_property ( +- bbgoogle, "proxy-resolver", +- bbgoogle->priv->service, "proxy-resolver", +- G_BINDING_SYNC_CREATE); +- } +- +- /* If we're using OAuth tokens, then as far as the backend +- * is concerned it's always authorized. The GDataAuthorizer +- * will take care of everything in the background. */ +- if (!GDATA_IS_CLIENT_LOGIN_AUTHORIZER (bbgoogle->priv->authorizer)) +- return TRUE; +- +- /* Otherwise it's up to us to obtain a login secret, but +- there is currently no way to do it, thus simply fail. */ +- return FALSE; +-} +- +-/* returns whether group changed from the one stored in the cache; +- * returns FALSE, if the group was not in the cache yet; +- * also adds the group into the cache; +- * use group_name = NULL to remove it from the cache. +- */ +-static gboolean +-ebb_google_cache_update_group (EBookBackendGoogle *bbgoogle, +- const gchar *group_id, +- const gchar *group_name) +-{ +- EBookCache *book_cache; +- gboolean changed; +- gchar *key, *old_value; +- +- g_return_val_if_fail (E_IS_BOOK_BACKEND_GOOGLE (bbgoogle), FALSE); +- g_return_val_if_fail (group_id != NULL, FALSE); +- +- book_cache = e_book_meta_backend_ref_cache (E_BOOK_META_BACKEND (bbgoogle)); +- g_return_val_if_fail (book_cache != NULL, FALSE); +- +- key = g_strconcat ("google-group", ":", group_id, NULL); +- old_value = e_cache_dup_key (E_CACHE (book_cache), key, NULL); +- +- if (group_name) { +- changed = old_value && g_strcmp0 (old_value, group_name) != 0; +- +- e_cache_set_key (E_CACHE (book_cache), key, group_name, NULL); +- +- /* Add the category to Evolution’s category list. */ +- e_categories_add (group_name, NULL, NULL, TRUE); +- } else { +- changed = old_value != NULL; +- +- e_cache_set_key (E_CACHE (book_cache), key, NULL, NULL); +- +- /* Remove the category from Evolution’s category list. */ +- if (changed) +- e_categories_remove (old_value); +- } +- +- g_object_unref (book_cache); +- g_free (old_value); +- g_free (key); +- +- return changed; +-} +- +-static void +-ebb_google_process_group (EBookBackendGoogle *bbgoogle, +- GDataEntry *entry) +-{ +- const gchar *uid, *system_group_id; +- gchar *name; +- gboolean is_deleted; +- +- uid = gdata_entry_get_id (entry); +- name = e_contact_sanitise_google_group_name (entry); +- +- system_group_id = gdata_contacts_group_get_system_group_id (GDATA_CONTACTS_GROUP (entry)); +- is_deleted = gdata_contacts_group_is_deleted (GDATA_CONTACTS_GROUP (entry)); +- +- g_rec_mutex_lock (&bbgoogle->priv->groups_lock); +- +- if (system_group_id) { +- if (is_deleted) { +- gchar *entry_id = g_hash_table_lookup (bbgoogle->priv->system_groups_by_id, system_group_id); +- g_hash_table_remove (bbgoogle->priv->system_groups_by_entry_id, entry_id); +- g_hash_table_remove (bbgoogle->priv->system_groups_by_id, system_group_id); +- } else { +- gchar *entry_id, *system_group_id_dup; +- +- entry_id = e_contact_sanitise_google_group_id (uid); +- system_group_id_dup = g_strdup (system_group_id); +- +- g_hash_table_replace (bbgoogle->priv->system_groups_by_entry_id, entry_id, system_group_id_dup); +- g_hash_table_replace (bbgoogle->priv->system_groups_by_id, system_group_id_dup, entry_id); +- } +- +- g_free (name); +- +- /* use evolution's names for google's system groups */ +- name = g_strdup (e_contact_map_google_with_evo_group (system_group_id, TRUE)); +- +- g_warn_if_fail (name != NULL); +- if (!name) +- name = g_strdup (system_group_id); +- } +- +- if (is_deleted) { +- g_hash_table_remove (bbgoogle->priv->groups_by_id, uid); +- g_hash_table_remove (bbgoogle->priv->groups_by_name, name); +- +- bbgoogle->priv->groups_changed = ebb_google_cache_update_group (bbgoogle, uid, NULL) || bbgoogle->priv->groups_changed; +- } else { +- g_hash_table_replace (bbgoogle->priv->groups_by_id, e_contact_sanitise_google_group_id (uid), g_strdup (name)); +- g_hash_table_replace (bbgoogle->priv->groups_by_name, g_strdup (name), e_contact_sanitise_google_group_id (uid)); +- +- bbgoogle->priv->groups_changed = ebb_google_cache_update_group (bbgoogle, uid, name) || bbgoogle->priv->groups_changed; +- } +- +- g_rec_mutex_unlock (&bbgoogle->priv->groups_lock); +- +- g_free (name); +-} +- +-static gboolean +-ebb_google_get_groups_locked_sync (EBookBackendGoogle *bbgoogle, +- gboolean with_time_constraint, +- GCancellable *cancellable, +- GError **error) +-{ +- GDataQuery *query; +- GDataFeed *feed; +- gboolean success; +- GError *local_error = NULL; +- +- g_return_val_if_fail (E_IS_BOOK_BACKEND_GOOGLE (bbgoogle), FALSE); +- g_return_val_if_fail (ebb_google_is_authorized_locked (bbgoogle), FALSE); +- +- g_rec_mutex_lock (&bbgoogle->priv->groups_lock); +- +- /* Build our query, always fetch all of them */ +- query = GDATA_QUERY (gdata_contacts_query_new_with_limits (NULL, 0, G_MAXINT)); +- if (with_time_constraint && bbgoogle->priv->groups_last_update.tv_sec != 0) { +- gdata_query_set_updated_min (query, bbgoogle->priv->groups_last_update.tv_sec); +- gdata_contacts_query_set_show_deleted (GDATA_CONTACTS_QUERY (query), TRUE); +- } +- +- bbgoogle->priv->groups_changed = FALSE; +- +- /* Run the query synchronously */ +- feed = gdata_contacts_service_query_groups ( +- GDATA_CONTACTS_SERVICE (bbgoogle->priv->service), +- query, cancellable, NULL, NULL, &local_error); +- +- if (with_time_constraint && bbgoogle->priv->groups_last_update.tv_sec != 0 && ( +- g_error_matches (local_error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_BAD_QUERY_PARAMETER) || +- g_error_matches (local_error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR))) { +- g_clear_error (&local_error); +- +- gdata_query_set_updated_min (query, -1); +- +- feed = gdata_contacts_service_query_groups ( +- GDATA_CONTACTS_SERVICE (bbgoogle->priv->service), +- query, cancellable, NULL, NULL, error); +- } else if (local_error) { +- g_propagate_error (error, local_error); +- } +- +- success = feed != NULL; +- +- if (success) { +- GList *link; +- +- for (link = gdata_feed_get_entries (feed); link; link = g_list_next (link)) { +- ebb_google_process_group (bbgoogle, link->data); +- } +- +- g_get_current_time (&bbgoogle->priv->groups_last_update); +- } +- +- g_rec_mutex_unlock (&bbgoogle->priv->groups_lock); +- +- g_clear_object (&feed); +- g_object_unref (query); +- +- return success; +-} +- +-static gboolean +-ebb_google_connect_sync (EBookMetaBackend *meta_backend, +- const ENamedParameters *credentials, +- ESourceAuthenticationResult *out_auth_result, +- gchar **out_certificate_pem, +- GTlsCertificateFlags *out_certificate_errors, +- GCancellable *cancellable, +- GError **error) +-{ +- EBookBackendGoogle *bbgoogle; +- gboolean success; +- GError *local_error = NULL; +- +- g_return_val_if_fail (E_IS_BOOK_BACKEND_GOOGLE (meta_backend), FALSE); +- g_return_val_if_fail (out_auth_result != NULL, FALSE); +- +- bbgoogle = E_BOOK_BACKEND_GOOGLE (meta_backend); +- +- *out_auth_result = E_SOURCE_AUTHENTICATION_ACCEPTED; +- +- g_rec_mutex_lock (&bbgoogle->priv->conn_lock); +- +- if (ebb_google_is_authorized_locked (bbgoogle)) { +- g_rec_mutex_unlock (&bbgoogle->priv->conn_lock); +- return TRUE; +- } +- +- success = ebb_google_request_authorization_locked (bbgoogle, credentials, cancellable, &local_error); +- if (success) +- success = gdata_authorizer_refresh_authorization (bbgoogle->priv->authorizer, cancellable, &local_error); +- +- if (success) +- success = ebb_google_get_groups_locked_sync (bbgoogle, FALSE, cancellable, &local_error); +- +- g_rec_mutex_unlock (&bbgoogle->priv->conn_lock); +- +- if (!success) { +- if (g_error_matches (local_error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_AUTHENTICATION_REQUIRED)) { +- *out_auth_result = E_SOURCE_AUTHENTICATION_REJECTED; +- } else if (g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_CONNECTION_REFUSED) || +- g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) { +- *out_auth_result = E_SOURCE_AUTHENTICATION_REJECTED; +- g_propagate_error (error, local_error); +- local_error = NULL; +- } else { +- *out_auth_result = E_SOURCE_AUTHENTICATION_ERROR; +- ebb_google_data_book_error_from_gdata_error (error, local_error); +- } +- +- g_clear_error (&local_error); +- } +- +- return success; +-} +- +-static gboolean +-ebb_google_disconnect_sync (EBookMetaBackend *meta_backend, +- GCancellable *cancellable, +- GError **error) +-{ +- EBookBackendGoogle *bbgoogle; +- +- g_return_val_if_fail (E_IS_BOOK_BACKEND_GOOGLE (meta_backend), FALSE); +- +- bbgoogle = E_BOOK_BACKEND_GOOGLE (meta_backend); +- +- g_rec_mutex_lock (&bbgoogle->priv->conn_lock); +- +- g_clear_object (&bbgoogle->priv->service); +- g_clear_object (&bbgoogle->priv->authorizer); +- +- g_rec_mutex_unlock (&bbgoogle->priv->conn_lock); +- +- return TRUE; +-} +- +-static gboolean +-ebb_google_get_changes_sync (EBookMetaBackend *meta_backend, +- const gchar *last_sync_tag, +- gboolean is_repeat, +- gchar **out_new_sync_tag, +- gboolean *out_repeat, +- GSList **out_created_objects, /* EBookMetaBackendInfo * */ +- GSList **out_modified_objects, /* EBookMetaBackendInfo * */ +- GSList **out_removed_objects, /* EBookMetaBackendInfo * */ +- GCancellable *cancellable, +- GError **error) +-{ +- EBookBackendGoogle *bbgoogle; +- EBookCache *book_cache; +- gint64 updated_time = 0; +- GTimeVal last_updated; +- GDataFeed *feed; +- GDataContactsQuery *contacts_query; +- GHashTable *known_uids = NULL; +- GError *local_error = NULL; +- +- g_return_val_if_fail (E_IS_BOOK_BACKEND_GOOGLE (meta_backend), FALSE); +- g_return_val_if_fail (out_new_sync_tag != NULL, FALSE); +- g_return_val_if_fail (out_created_objects != NULL, FALSE); +- g_return_val_if_fail (out_modified_objects != NULL, FALSE); +- g_return_val_if_fail (out_removed_objects != NULL, FALSE); +- +- bbgoogle = E_BOOK_BACKEND_GOOGLE (meta_backend); +- +- *out_created_objects = NULL; +- *out_modified_objects = NULL; +- *out_removed_objects = NULL; +- +- g_rec_mutex_lock (&bbgoogle->priv->conn_lock); +- +- if (!ebb_google_get_groups_locked_sync (bbgoogle, TRUE, cancellable, error)) { +- g_rec_mutex_unlock (&bbgoogle->priv->conn_lock); +- return FALSE; +- } +- +- book_cache = e_book_meta_backend_ref_cache (meta_backend); +- +- /* Download everything when the local data version mismatches */ +- if (e_cache_get_key_int (E_CACHE (book_cache), "google-data-version", NULL) != EBB_GOOGLE_DATA_VERSION) +- last_sync_tag = NULL; +- +- if (!last_sync_tag || +- !g_time_val_from_iso8601 (last_sync_tag, &last_updated)) { +- last_updated.tv_sec = 0; +- } +- +- contacts_query = gdata_contacts_query_new_with_limits (NULL, 0, G_MAXINT); +- if (last_updated.tv_sec > 0 && !bbgoogle->priv->groups_changed) { +- gdata_query_set_updated_min (GDATA_QUERY (contacts_query), last_updated.tv_sec); +- gdata_contacts_query_set_show_deleted (contacts_query, TRUE); +- } +- +- feed = gdata_contacts_service_query_contacts (GDATA_CONTACTS_SERVICE (bbgoogle->priv->service), GDATA_QUERY (contacts_query), cancellable, NULL, NULL, &local_error); +- +- if (last_updated.tv_sec > 0 && !bbgoogle->priv->groups_changed && ( +- g_error_matches (local_error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_BAD_QUERY_PARAMETER) || +- g_error_matches (local_error, GDATA_SERVICE_ERROR, GDATA_SERVICE_ERROR_PROTOCOL_ERROR))) { +- g_clear_error (&local_error); +- +- gdata_query_set_updated_min (GDATA_QUERY (contacts_query), -1); +- +- feed = gdata_contacts_service_query_contacts (GDATA_CONTACTS_SERVICE (bbgoogle->priv->service), GDATA_QUERY (contacts_query), cancellable, NULL, NULL, &local_error); +- } +- +- if (feed && !g_cancellable_is_cancelled (cancellable) && !local_error) { +- GList *link; +- +- if (!last_sync_tag) { +- GSList *uids = NULL, *slink; +- +- if (e_cache_get_uids (E_CACHE (book_cache), E_CACHE_EXCLUDE_DELETED, &uids, NULL, cancellable, NULL)) { +- known_uids = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); +- +- for (slink = uids; slink; slink = g_slist_next (slink)) { +- gchar *uid = slink->data; +- +- if (uid) { +- g_hash_table_insert (known_uids, uid, NULL); +- /* Steal the data */ +- slink->data = NULL; +- } +- } +- +- g_slist_free_full (uids, g_free); +- } +- } +- +- if (gdata_feed_get_updated (feed) > updated_time) +- updated_time = gdata_feed_get_updated (feed); +- +- for (link = gdata_feed_get_entries (feed); link && !g_cancellable_is_cancelled (cancellable); link = g_list_next (link)) { +- GDataContactsContact *gdata_contact = link->data; +- EContact *cached_contact = NULL; +- gchar *uid; +- +- if (!GDATA_IS_CONTACTS_CONTACT (gdata_contact)) +- continue; +- +- uid = g_strdup (e_book_google_utils_uid_from_entry (GDATA_ENTRY (gdata_contact))); +- if (!uid || !*uid) { +- g_free (uid); +- continue; +- } +- +- if (known_uids) +- g_hash_table_remove (known_uids, uid); +- +- if (!e_book_cache_get_contact (book_cache, uid, FALSE, &cached_contact, cancellable, NULL)) +- cached_contact = NULL; +- +- if (gdata_contacts_contact_is_deleted (gdata_contact)) { +- *out_removed_objects = g_slist_prepend (*out_removed_objects, +- e_book_meta_backend_info_new (uid, NULL, NULL, NULL)); +- } else { +- EContact *new_contact; +- +- if (cached_contact) { +- gchar *old_etag; +- +- old_etag = e_vcard_util_dup_x_attribute (E_VCARD (cached_contact), E_GOOGLE_X_ETAG); +- if (!old_etag) +- old_etag = e_contact_get (cached_contact, E_CONTACT_REV); +- +- if (g_strcmp0 (gdata_entry_get_etag (GDATA_ENTRY (gdata_contact)), old_etag) == 0) { +- g_object_unref (cached_contact); +- g_free (old_etag); +- g_free (uid); +- continue; +- } +- +- g_free (old_etag); +- } +- +- g_rec_mutex_lock (&bbgoogle->priv->groups_lock); +- new_contact = e_contact_new_from_gdata_entry (GDATA_ENTRY (gdata_contact), +- bbgoogle->priv->groups_by_id, bbgoogle->priv->system_groups_by_entry_id); +- g_rec_mutex_unlock (&bbgoogle->priv->groups_lock); +- +- if (new_contact) { +- const gchar *etag, *photo_etag; +- gchar *object, *revision, *extra; +- +- photo_etag = gdata_contacts_contact_get_photo_etag (gdata_contact); +- if (photo_etag && cached_contact) { +- gchar *old_photo_etag; +- +- old_photo_etag = e_vcard_util_dup_x_attribute (E_VCARD (cached_contact), E_GOOGLE_X_PHOTO_ETAG); +- if (g_strcmp0 (photo_etag, old_photo_etag) == 0) { +- EContactPhoto *photo; +- +- /* To not download it again, when it's already available locally */ +- photo_etag = NULL; +- +- /* Copy the photo attribute to the changed contact */ +- photo = e_contact_get (cached_contact, E_CONTACT_PHOTO); +- e_contact_set (new_contact, E_CONTACT_PHOTO, photo); +- +- e_contact_photo_free (photo); +- } +- +- g_free (old_photo_etag); +- } +- +- if (photo_etag) { +- guint8 *photo_data; +- gsize photo_length = 0; +- gchar *photo_content_type = NULL; +- GError *local_error2 = NULL; +- +- photo_data = gdata_contacts_contact_get_photo (gdata_contact, GDATA_CONTACTS_SERVICE (bbgoogle->priv->service), +- &photo_length, &photo_content_type, cancellable, &local_error2); +- +- if (!local_error2) { +- EContactPhoto *photo; +- +- photo = e_contact_photo_new (); +- photo->type = E_CONTACT_PHOTO_TYPE_INLINED; +- photo->data.inlined.data = (guchar *) photo_data; +- photo->data.inlined.length = photo_length; +- photo->data.inlined.mime_type = photo_content_type; +- +- e_contact_set (E_CONTACT (new_contact), E_CONTACT_PHOTO, photo); +- +- e_contact_photo_free (photo); +- +- /* Read of the photo frees previously obtained photo_etag */ +- photo_etag = gdata_contacts_contact_get_photo_etag (gdata_contact); +- +- e_vcard_util_set_x_attribute (E_VCARD (new_contact), E_GOOGLE_X_PHOTO_ETAG, photo_etag); +- } else { +- g_debug ("%s: Downloading contact photo for '%s' failed: %s", G_STRFUNC, +- gdata_entry_get_id (GDATA_ENTRY (gdata_contact)), local_error2->message); +- +- g_clear_error (&local_error2); +- } +- } +- +- etag = gdata_entry_get_etag (GDATA_ENTRY (gdata_contact)); +- e_vcard_util_set_x_attribute (E_VCARD (new_contact), E_GOOGLE_X_ETAG, etag); +- revision = e_book_google_utils_time_to_revision (gdata_entry_get_updated (GDATA_ENTRY (gdata_contact))); +- e_contact_set (new_contact, E_CONTACT_REV, revision); +- object = e_vcard_to_string (E_VCARD (new_contact), EVC_FORMAT_VCARD_30); +- extra = gdata_parsable_get_xml (GDATA_PARSABLE (gdata_contact)); +- +- if (cached_contact) { +- *out_modified_objects = g_slist_prepend (*out_modified_objects, +- e_book_meta_backend_info_new (uid, revision, object, extra)); +- } else { +- *out_created_objects = g_slist_prepend (*out_created_objects, +- e_book_meta_backend_info_new (uid, revision, object, extra)); +- } +- +- g_free (revision); +- g_free (object); +- g_free (extra); +- } +- +- g_clear_object (&new_contact); +- } +- +- g_clear_object (&cached_contact); +- g_free (uid); +- } +- } +- +- g_rec_mutex_unlock (&bbgoogle->priv->conn_lock); +- g_clear_object (&contacts_query); +- g_clear_object (&feed); +- +- if (!g_cancellable_is_cancelled (cancellable) && !local_error) { +- last_updated.tv_sec = updated_time; +- last_updated.tv_usec = 0; +- +- *out_new_sync_tag = g_time_val_to_iso8601 (&last_updated); +- +- if (!last_sync_tag) +- e_cache_set_key_int (E_CACHE (book_cache), "google-data-version", EBB_GOOGLE_DATA_VERSION, NULL); +- +- if (known_uids) { +- GHashTableIter iter; +- gpointer key; +- +- g_hash_table_iter_init (&iter, known_uids); +- while (g_hash_table_iter_next (&iter, &key, NULL)) { +- const gchar *uid = key; +- +- if (uid) { +- *out_removed_objects = g_slist_prepend (*out_removed_objects, +- e_book_meta_backend_info_new (uid, NULL, NULL, NULL)); +- } +- } +- } +- } +- +- if (known_uids) +- g_hash_table_destroy (known_uids); +- +- g_clear_object (&book_cache); +- +- if (local_error) { +- g_propagate_error (error, local_error); +- return FALSE; +- } +- +- return TRUE; +-} +- +-static gboolean +-ebb_google_load_contact_sync (EBookMetaBackend *meta_backend, +- const gchar *uid, +- const gchar *extra, +- EContact **out_contact, +- gchar **out_extra, +- GCancellable *cancellable, +- GError **error) +-{ +- EBookBackendGoogle *bbgoogle; +- +- g_return_val_if_fail (E_IS_BOOK_BACKEND_GOOGLE (meta_backend), FALSE); +- g_return_val_if_fail (uid != NULL, FALSE); +- g_return_val_if_fail (out_contact != NULL, FALSE); +- g_return_val_if_fail (out_extra != NULL, FALSE); +- +- bbgoogle = E_BOOK_BACKEND_GOOGLE (meta_backend); +- +- /* Only "load" preloaded during save, otherwise fail with an error, +- because the backend provides objects within get_changes_sync() */ +- +- if (bbgoogle->priv->preloaded) { +- EContact *contact; +- +- contact = g_hash_table_lookup (bbgoogle->priv->preloaded, uid); +- if (contact) { +- *out_contact = e_contact_duplicate (contact); +- +- g_hash_table_remove (bbgoogle->priv->preloaded, uid); +- +- return TRUE; +- } +- } +- +- g_set_error_literal (error, E_BOOK_CLIENT_ERROR, E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND, +- e_book_client_error_to_string (E_BOOK_CLIENT_ERROR_CONTACT_NOT_FOUND)); +- +- return FALSE; +-} +- +-static gchar * +-ebb_google_create_group_sync (EBookBackendGoogle *bbgoogle, +- const gchar *category_name, +- GCancellable *cancellable, +- GError **error) +-{ +- GDataEntry *group, *new_group; +- const gchar *system_group_id; +- gchar *uid; +- +- system_group_id = e_contact_map_google_with_evo_group (category_name, FALSE); +- if (system_group_id) { +- gchar *group_entry_id; +- +- g_rec_mutex_lock (&bbgoogle->priv->groups_lock); +- group_entry_id = g_strdup (g_hash_table_lookup (bbgoogle->priv->system_groups_by_id, system_group_id)); +- g_rec_mutex_unlock (&bbgoogle->priv->groups_lock); +- +- g_return_val_if_fail (group_entry_id != NULL, NULL); +- +- return group_entry_id; +- } +- +- group = GDATA_ENTRY (gdata_contacts_group_new (NULL)); +- +- gdata_entry_set_title (group, category_name); +- +- /* Insert the new group */ +- g_rec_mutex_lock (&bbgoogle->priv->conn_lock); +- new_group = GDATA_ENTRY (gdata_contacts_service_insert_group ( +- GDATA_CONTACTS_SERVICE (bbgoogle->priv->service), +- GDATA_CONTACTS_GROUP (group), +- cancellable, error)); +- g_rec_mutex_unlock (&bbgoogle->priv->conn_lock); +- g_object_unref (group); +- +- if (new_group == NULL) +- return NULL; +- +- /* Add the new group to the group mappings */ +- uid = g_strdup (gdata_entry_get_id (new_group)); +- +- g_rec_mutex_lock (&bbgoogle->priv->groups_lock); +- g_hash_table_replace (bbgoogle->priv->groups_by_id, e_contact_sanitise_google_group_id (uid), g_strdup (category_name)); +- g_hash_table_replace (bbgoogle->priv->groups_by_name, g_strdup (category_name), e_contact_sanitise_google_group_id (uid)); +- g_rec_mutex_unlock (&bbgoogle->priv->groups_lock); +- +- g_object_unref (new_group); +- +- /* Update the cache. */ +- ebb_google_cache_update_group (bbgoogle, uid, category_name); +- +- return uid; +-} +- +-static gboolean +-ebb_google_photo_changed (EBookMetaBackend *meta_backend, +- EContact *old_contact, +- EContact *new_contact, +- GCancellable *cancellable) +-{ +- EContact *old_contact_copy = NULL; +- EContactPhoto *old_photo; +- EContactPhoto *new_photo; +- gboolean changed = FALSE; +- +- old_photo = e_contact_get (old_contact, E_CONTACT_PHOTO); +- new_photo = e_contact_get (new_contact, E_CONTACT_PHOTO); +- +- if (!old_photo && new_photo) +- changed = TRUE; +- +- if (old_photo && !new_photo) +- changed = TRUE; +- +- /* old_photo comes from cache, thus it's always URI (to local file or elsewhere), +- while the new_photo is to be saved, which is always inlined. */ +- if (!changed && old_photo && new_photo && +- old_photo->type == E_CONTACT_PHOTO_TYPE_URI && +- new_photo->type == E_CONTACT_PHOTO_TYPE_INLINED) { +- e_contact_photo_free (old_photo); +- old_photo = NULL; +- +- old_contact_copy = e_contact_duplicate (old_contact); +- +- if (e_book_meta_backend_inline_local_photos_sync (meta_backend, old_contact_copy, cancellable, NULL)) +- old_photo = e_contact_get (old_contact_copy, E_CONTACT_PHOTO); +- } +- +- if (old_photo && new_photo && +- old_photo->type == E_CONTACT_PHOTO_TYPE_INLINED && +- new_photo->type == E_CONTACT_PHOTO_TYPE_INLINED) { +- guchar *old_data; +- guchar *new_data; +- gsize old_length; +- gsize new_length; +- +- old_data = old_photo->data.inlined.data; +- new_data = new_photo->data.inlined.data; +- +- old_length = old_photo->data.inlined.length; +- new_length = new_photo->data.inlined.length; +- +- changed = +- (old_length != new_length) || +- (memcmp (old_data, new_data, old_length) != 0); +- } +- +- e_contact_photo_free (old_photo); +- e_contact_photo_free (new_photo); +- g_clear_object (&old_contact_copy); +- +- return changed; +-} +- +-static GDataEntry * +-ebb_google_update_contact_photo_sync (GDataContactsContact *contact, +- GDataContactsService *service, +- EContactPhoto *photo, +- GCancellable *cancellable, +- GError **error) +-{ +- GDataAuthorizationDomain *authorization_domain; +- GDataEntry *gdata_contact = NULL; +- const gchar *content_type; +- const guint8 *photo_data; +- gsize photo_length; +- gboolean success; +- +- authorization_domain = gdata_contacts_service_get_primary_authorization_domain (); +- +- if (photo != NULL) { +- photo_data = (guint8 *) photo->data.inlined.data; +- photo_length = photo->data.inlined.length; +- content_type = photo->data.inlined.mime_type; +- } else { +- photo_data = NULL; +- photo_length = 0; +- content_type = NULL; +- } +- +- success = gdata_contacts_contact_set_photo ( +- contact, service, +- photo_data, photo_length, +- content_type, +- cancellable, error); +- +- if (success) { +- /* Setting the photo changes the contact's ETag, +- * so query for the contact to obtain its new ETag. */ +- gdata_contact = gdata_service_query_single_entry ( +- GDATA_SERVICE (service), +- authorization_domain, +- gdata_entry_get_id (GDATA_ENTRY (contact)), +- NULL, GDATA_TYPE_CONTACTS_CONTACT, +- cancellable, error); +- } +- +- return gdata_contact; +-} +- +-static gboolean +-ebb_google_save_contact_sync (EBookMetaBackend *meta_backend, +- gboolean overwrite_existing, +- EConflictResolution conflict_resolution, +- /* const */ EContact *contact, +- const gchar *extra, +- guint32 opflags, +- gchar **out_new_uid, +- gchar **out_new_extra, +- GCancellable *cancellable, +- GError **error) +-{ +- EBookBackendGoogle *bbgoogle; +- EBookCache *book_cache; +- GDataEntry *entry = NULL; +- GDataContactsContact *gdata_contact; +- EContact *cached_contact = NULL; +- EContact *new_contact; +- const gchar *uid; +- EContactPhoto *photo; +- gboolean photo_changed; +- GError *local_error = NULL; +- +- g_return_val_if_fail (E_IS_BOOK_BACKEND_GOOGLE (meta_backend), FALSE); +- g_return_val_if_fail (E_IS_CONTACT (contact), FALSE); +- g_return_val_if_fail (out_new_uid != NULL, FALSE); +- g_return_val_if_fail (out_new_extra != NULL, FALSE); +- +- book_cache = e_book_meta_backend_ref_cache (meta_backend); +- g_return_val_if_fail (book_cache != NULL, FALSE); +- +- bbgoogle = E_BOOK_BACKEND_GOOGLE (meta_backend); +- +- if (!overwrite_existing || !e_book_cache_get_contact (book_cache, e_contact_get_const (contact, E_CONTACT_UID), +- FALSE, &cached_contact, cancellable, NULL)) { +- cached_contact = NULL; +- } +- +- if (extra && *extra) +- entry = GDATA_ENTRY (gdata_parsable_new_from_xml (GDATA_TYPE_CONTACTS_CONTACT, extra, -1, NULL)); +- +- g_rec_mutex_lock (&bbgoogle->priv->conn_lock); +- g_rec_mutex_lock (&bbgoogle->priv->groups_lock); +- +- /* Ensure the system groups have been fetched. */ +- if (g_hash_table_size (bbgoogle->priv->system_groups_by_id) == 0) +- ebb_google_get_groups_locked_sync (bbgoogle, FALSE, cancellable, NULL); +- +- if (overwrite_existing || entry) { +- if (gdata_entry_update_from_e_contact (entry, contact, FALSE, +- bbgoogle->priv->groups_by_name, +- bbgoogle->priv->system_groups_by_id, +- ebb_google_create_group_sync, +- bbgoogle, +- cancellable)) { +- overwrite_existing = TRUE; +- } else { +- g_clear_object (&entry); +- } +- } else { +- /* Build the GDataEntry from the vCard */ +- entry = gdata_entry_new_from_e_contact ( +- contact, +- bbgoogle->priv->groups_by_name, +- bbgoogle->priv->system_groups_by_id, +- ebb_google_create_group_sync, +- bbgoogle, +- cancellable); +- } +- +- g_rec_mutex_unlock (&bbgoogle->priv->groups_lock); +- +- photo_changed = cached_contact && ebb_google_photo_changed (meta_backend, cached_contact, contact, cancellable); +- +- g_clear_object (&cached_contact); +- g_clear_object (&book_cache); +- +- if (!entry) { +- g_rec_mutex_unlock (&bbgoogle->priv->conn_lock); +- g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_OTHER_ERROR, _("Object to save is not a valid vCard"))); +- return FALSE; +- } +- +- if (overwrite_existing) { +- gdata_contact = GDATA_CONTACTS_CONTACT (gdata_service_update_entry ( +- bbgoogle->priv->service, +- gdata_contacts_service_get_primary_authorization_domain (), +- entry, cancellable, &local_error)); +- } else { +- gdata_contact = gdata_contacts_service_insert_contact ( +- GDATA_CONTACTS_SERVICE (bbgoogle->priv->service), +- GDATA_CONTACTS_CONTACT (entry), +- cancellable, &local_error); +- } +- +- photo = g_object_steal_data (G_OBJECT (entry), "photo"); +- +- g_object_unref (entry); +- +- if (!gdata_contact) { +- g_rec_mutex_unlock (&bbgoogle->priv->conn_lock); +- ebb_google_data_book_error_from_gdata_error (error, local_error); +- g_clear_error (&local_error); +- e_contact_photo_free (photo); +- +- return FALSE; +- } +- +- if (photo_changed) { +- entry = ebb_google_update_contact_photo_sync (gdata_contact, GDATA_CONTACTS_SERVICE (bbgoogle->priv->service), photo, cancellable, &local_error); +- if (!entry) { +- g_rec_mutex_unlock (&bbgoogle->priv->conn_lock); +- ebb_google_data_book_error_from_gdata_error (error, local_error); +- g_clear_error (&local_error); +- e_contact_photo_free (photo); +- g_clear_object (&gdata_contact); +- +- return FALSE; +- } +- +- g_object_unref (gdata_contact); +- gdata_contact = GDATA_CONTACTS_CONTACT (entry); +- } +- +- g_rec_mutex_unlock (&bbgoogle->priv->conn_lock); +- +- g_rec_mutex_lock (&bbgoogle->priv->groups_lock); +- new_contact = e_contact_new_from_gdata_entry (GDATA_ENTRY (gdata_contact), +- bbgoogle->priv->groups_by_id, +- bbgoogle->priv->system_groups_by_entry_id); +- g_rec_mutex_unlock (&bbgoogle->priv->groups_lock); +- +- if (!new_contact) { +- g_object_unref (gdata_contact); +- e_contact_photo_free (photo); +- g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_OTHER_ERROR, _("Failed to create contact from returned server data"))); +- return FALSE; +- } +- +- e_contact_set (new_contact, E_CONTACT_PHOTO, photo); +- e_vcard_util_set_x_attribute (E_VCARD (new_contact), E_GOOGLE_X_PHOTO_ETAG, gdata_contacts_contact_get_photo_etag (gdata_contact)); +- +- *out_new_extra = gdata_parsable_get_xml (GDATA_PARSABLE (gdata_contact)); +- +- g_object_unref (gdata_contact); +- +- e_contact_photo_free (photo); +- +- uid = e_contact_get_const (new_contact, E_CONTACT_UID); +- +- if (!uid) { +- g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_OTHER_ERROR, _("Server returned contact without UID"))); +- +- g_object_unref (new_contact); +- g_free (*out_new_extra); +- *out_new_extra = NULL; +- +- return FALSE; +- } +- +- if (bbgoogle->priv->preloaded) { +- *out_new_uid = g_strdup (uid); +- g_hash_table_insert (bbgoogle->priv->preloaded, g_strdup (uid), new_contact); +- } else { +- g_object_unref (new_contact); +- } +- +- return TRUE; +-} +- +-static gboolean +-ebb_google_remove_contact_sync (EBookMetaBackend *meta_backend, +- EConflictResolution conflict_resolution, +- const gchar *uid, +- const gchar *extra, +- const gchar *object, +- guint32 opflags, +- GCancellable *cancellable, +- GError **error) +-{ +- EBookBackendGoogle *bbgoogle; +- GDataEntry *entry; +- GError *local_error = NULL; +- +- g_return_val_if_fail (E_IS_BOOK_BACKEND_GOOGLE (meta_backend), FALSE); +- g_return_val_if_fail (uid != NULL, FALSE); +- g_return_val_if_fail (extra != NULL, FALSE); +- +- entry = GDATA_ENTRY (gdata_parsable_new_from_xml (GDATA_TYPE_CONTACTS_CONTACT, extra, -1, NULL)); +- if (!entry) { +- g_propagate_error (error, e_client_error_create (E_CLIENT_ERROR_INVALID_ARG, NULL)); +- return FALSE; +- } +- +- bbgoogle = E_BOOK_BACKEND_GOOGLE (meta_backend); +- +- g_rec_mutex_lock (&bbgoogle->priv->conn_lock); +- +- if (!gdata_service_delete_entry (bbgoogle->priv->service, +- gdata_contacts_service_get_primary_authorization_domain (), entry, +- cancellable, &local_error)) { +- g_rec_mutex_unlock (&bbgoogle->priv->conn_lock); +- ebb_google_data_book_error_from_gdata_error (error, local_error); +- g_error_free (local_error); +- g_object_unref (entry); +- +- return FALSE; +- } +- +- g_rec_mutex_unlock (&bbgoogle->priv->conn_lock); +- g_object_unref (entry); +- +- return TRUE; +-} +- +-static gchar * +-ebb_google_get_backend_property (EBookBackend *book_backend, +- const gchar *prop_name) +-{ +- g_return_val_if_fail (prop_name != NULL, NULL); +- +- if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) { +- return g_strjoin (",", +- "net", +- "do-initial-query", +- "contact-lists", +- e_book_meta_backend_get_capabilities (E_BOOK_META_BACKEND (book_backend)), +- NULL); +- +- } else if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_REQUIRED_FIELDS)) { +- return g_strdup (""); +- +- } else if (g_str_equal (prop_name, E_BOOK_BACKEND_PROPERTY_SUPPORTED_FIELDS)) { +- return g_strjoin (",", +- e_contact_field_name (E_CONTACT_UID), +- e_contact_field_name (E_CONTACT_REV), +- e_contact_field_name (E_CONTACT_FULL_NAME), +- +- e_contact_field_name (E_CONTACT_EMAIL_1), +- e_contact_field_name (E_CONTACT_EMAIL_2), +- e_contact_field_name (E_CONTACT_EMAIL_3), +- e_contact_field_name (E_CONTACT_EMAIL_4), +- e_contact_field_name (E_CONTACT_EMAIL), +- +- e_contact_field_name (E_CONTACT_ADDRESS_LABEL_HOME), +- e_contact_field_name (E_CONTACT_ADDRESS_LABEL_WORK), +- e_contact_field_name (E_CONTACT_ADDRESS_LABEL_OTHER), +- +- e_contact_field_name (E_CONTACT_IM_AIM), +- e_contact_field_name (E_CONTACT_IM_JABBER), +- e_contact_field_name (E_CONTACT_IM_YAHOO), +- e_contact_field_name (E_CONTACT_IM_MSN), +- e_contact_field_name (E_CONTACT_IM_ICQ), +- e_contact_field_name (E_CONTACT_IM_SKYPE), +- e_contact_field_name (E_CONTACT_IM_GOOGLE_TALK), +- /* current implementation uses http://schemas.google.com/g/2005# namespace +- * see google-utils:gdata_gd_im_address_from_attribute +- * +- * google namespace does not support: +- * e_contact_field_name (E_CONTACT_IM_TWITTER), +- * e_contact_field_name (E_CONTACT_IM_GADUGADU), +- * e_contact_field_name (E_CONTACT_IM_GROUPWISE), +- * see https://developers.google.com/gdata/docs/2.0/elements#gdIm +- * see google-utils:is_known_google_im_protocol +- */ +- +- e_contact_field_name (E_CONTACT_ADDRESS), +- e_contact_field_name (E_CONTACT_ADDRESS_HOME), +- e_contact_field_name (E_CONTACT_ADDRESS_WORK), +- e_contact_field_name (E_CONTACT_ADDRESS_OTHER), +- e_contact_field_name (E_CONTACT_NAME), +- e_contact_field_name (E_CONTACT_GIVEN_NAME), +- e_contact_field_name (E_CONTACT_FAMILY_NAME), +- e_contact_field_name (E_CONTACT_PHONE_HOME), +- e_contact_field_name (E_CONTACT_PHONE_HOME_FAX), +- e_contact_field_name (E_CONTACT_PHONE_BUSINESS), +- e_contact_field_name (E_CONTACT_PHONE_BUSINESS_FAX), +- e_contact_field_name (E_CONTACT_PHONE_MOBILE), +- e_contact_field_name (E_CONTACT_PHONE_PAGER), +- e_contact_field_name (E_CONTACT_PHONE_ASSISTANT), +- e_contact_field_name (E_CONTACT_PHONE_BUSINESS_2), +- e_contact_field_name (E_CONTACT_PHONE_CALLBACK), +- e_contact_field_name (E_CONTACT_PHONE_CAR), +- e_contact_field_name (E_CONTACT_PHONE_COMPANY), +- e_contact_field_name (E_CONTACT_PHONE_HOME_2), +- e_contact_field_name (E_CONTACT_PHONE_ISDN), +- e_contact_field_name (E_CONTACT_PHONE_OTHER), +- e_contact_field_name (E_CONTACT_PHONE_OTHER_FAX), +- e_contact_field_name (E_CONTACT_PHONE_PRIMARY), +- e_contact_field_name (E_CONTACT_PHONE_RADIO), +- e_contact_field_name (E_CONTACT_PHONE_TELEX), +- e_contact_field_name (E_CONTACT_PHONE_TTYTDD), +- e_contact_field_name (E_CONTACT_TEL), +- +- e_contact_field_name (E_CONTACT_IM_AIM_HOME_1), +- e_contact_field_name (E_CONTACT_IM_AIM_HOME_2), +- e_contact_field_name (E_CONTACT_IM_AIM_HOME_3), +- e_contact_field_name (E_CONTACT_IM_AIM_WORK_1), +- e_contact_field_name (E_CONTACT_IM_AIM_WORK_2), +- e_contact_field_name (E_CONTACT_IM_AIM_WORK_3), +- e_contact_field_name (E_CONTACT_IM_GROUPWISE_HOME_1), +- e_contact_field_name (E_CONTACT_IM_GROUPWISE_HOME_2), +- e_contact_field_name (E_CONTACT_IM_GROUPWISE_HOME_3), +- e_contact_field_name (E_CONTACT_IM_GROUPWISE_WORK_1), +- e_contact_field_name (E_CONTACT_IM_GROUPWISE_WORK_2), +- e_contact_field_name (E_CONTACT_IM_GROUPWISE_WORK_3), +- e_contact_field_name (E_CONTACT_IM_JABBER_HOME_1), +- e_contact_field_name (E_CONTACT_IM_JABBER_HOME_2), +- e_contact_field_name (E_CONTACT_IM_JABBER_HOME_3), +- e_contact_field_name (E_CONTACT_IM_JABBER_WORK_1), +- e_contact_field_name (E_CONTACT_IM_JABBER_WORK_2), +- e_contact_field_name (E_CONTACT_IM_JABBER_WORK_3), +- e_contact_field_name (E_CONTACT_IM_YAHOO_HOME_1), +- e_contact_field_name (E_CONTACT_IM_YAHOO_HOME_2), +- e_contact_field_name (E_CONTACT_IM_YAHOO_HOME_3), +- e_contact_field_name (E_CONTACT_IM_YAHOO_WORK_1), +- e_contact_field_name (E_CONTACT_IM_YAHOO_WORK_2), +- e_contact_field_name (E_CONTACT_IM_YAHOO_WORK_3), +- e_contact_field_name (E_CONTACT_IM_MSN_HOME_1), +- e_contact_field_name (E_CONTACT_IM_MSN_HOME_2), +- e_contact_field_name (E_CONTACT_IM_MSN_HOME_3), +- e_contact_field_name (E_CONTACT_IM_MSN_WORK_1), +- e_contact_field_name (E_CONTACT_IM_MSN_WORK_2), +- e_contact_field_name (E_CONTACT_IM_MSN_WORK_3), +- e_contact_field_name (E_CONTACT_IM_ICQ_HOME_1), +- e_contact_field_name (E_CONTACT_IM_ICQ_HOME_2), +- e_contact_field_name (E_CONTACT_IM_ICQ_HOME_3), +- e_contact_field_name (E_CONTACT_IM_ICQ_WORK_1), +- e_contact_field_name (E_CONTACT_IM_ICQ_WORK_2), +- e_contact_field_name (E_CONTACT_IM_ICQ_WORK_3), +- e_contact_field_name (E_CONTACT_IM_GADUGADU_HOME_1), +- e_contact_field_name (E_CONTACT_IM_GADUGADU_HOME_2), +- e_contact_field_name (E_CONTACT_IM_GADUGADU_HOME_3), +- e_contact_field_name (E_CONTACT_IM_GADUGADU_WORK_1), +- e_contact_field_name (E_CONTACT_IM_GADUGADU_WORK_2), +- e_contact_field_name (E_CONTACT_IM_GADUGADU_WORK_3), +- e_contact_field_name (E_CONTACT_IM_SKYPE_HOME_1), +- e_contact_field_name (E_CONTACT_IM_SKYPE_HOME_2), +- e_contact_field_name (E_CONTACT_IM_SKYPE_HOME_3), +- e_contact_field_name (E_CONTACT_IM_SKYPE_WORK_1), +- e_contact_field_name (E_CONTACT_IM_SKYPE_WORK_2), +- e_contact_field_name (E_CONTACT_IM_SKYPE_WORK_3), +- e_contact_field_name (E_CONTACT_IM_GOOGLE_TALK_HOME_1), +- e_contact_field_name (E_CONTACT_IM_GOOGLE_TALK_HOME_2), +- e_contact_field_name (E_CONTACT_IM_GOOGLE_TALK_HOME_3), +- e_contact_field_name (E_CONTACT_IM_GOOGLE_TALK_WORK_1), +- e_contact_field_name (E_CONTACT_IM_GOOGLE_TALK_WORK_2), +- e_contact_field_name (E_CONTACT_IM_GOOGLE_TALK_WORK_3), +- +- e_contact_field_name (E_CONTACT_SIP), +- e_contact_field_name (E_CONTACT_ORG), +- e_contact_field_name (E_CONTACT_ORG_UNIT), +- e_contact_field_name (E_CONTACT_TITLE), +- e_contact_field_name (E_CONTACT_ROLE), +- e_contact_field_name (E_CONTACT_HOMEPAGE_URL), +- e_contact_field_name (E_CONTACT_BLOG_URL), +- e_contact_field_name (E_CONTACT_BIRTH_DATE), +- e_contact_field_name (E_CONTACT_ANNIVERSARY), +- e_contact_field_name (E_CONTACT_NOTE), +- e_contact_field_name (E_CONTACT_PHOTO), +- e_contact_field_name (E_CONTACT_CATEGORIES), +- e_contact_field_name (E_CONTACT_CATEGORY_LIST), +- e_contact_field_name (E_CONTACT_FILE_AS), +- e_contact_field_name (E_CONTACT_NICKNAME), +- NULL); +- } +- +- /* Chain up to parent's method. */ +- return E_BOOK_BACKEND_CLASS (e_book_backend_google_parent_class)->impl_get_backend_property (book_backend, prop_name); +-} +- +-static void +-ebb_google_constructed (GObject *object) +-{ +- EBookBackendGoogle *bbgoogle = E_BOOK_BACKEND_GOOGLE (object); +- +- /* Chain up to parent's method. */ +- G_OBJECT_CLASS (e_book_backend_google_parent_class)->constructed (object); +- +- /* Set it as always writable, regardless online/offline state */ +- e_book_backend_set_writable (E_BOOK_BACKEND (bbgoogle), TRUE); +-} +- +-static void +-ebb_google_dispose (GObject *object) +-{ +- EBookBackendGoogle *bbgoogle = E_BOOK_BACKEND_GOOGLE (object); +- +- g_rec_mutex_lock (&bbgoogle->priv->conn_lock); +- +- g_clear_object (&bbgoogle->priv->service); +- g_clear_object (&bbgoogle->priv->authorizer); +- +- g_rec_mutex_unlock (&bbgoogle->priv->conn_lock); +- +- g_hash_table_destroy (bbgoogle->priv->preloaded); +- bbgoogle->priv->preloaded = NULL; +- +- /* Chain up to parent's method. */ +- G_OBJECT_CLASS (e_book_backend_google_parent_class)->dispose (object); +-} +- +-static void +-ebb_google_finalize (GObject *object) +-{ +- EBookBackendGoogle *bbgoogle = E_BOOK_BACKEND_GOOGLE (object); +- +- g_clear_pointer (&bbgoogle->priv->groups_by_id, (GDestroyNotify) g_hash_table_destroy); +- g_clear_pointer (&bbgoogle->priv->groups_by_id, (GDestroyNotify) g_hash_table_destroy); +- g_clear_pointer (&bbgoogle->priv->groups_by_name, (GDestroyNotify) g_hash_table_destroy); +- g_clear_pointer (&bbgoogle->priv->system_groups_by_entry_id, (GDestroyNotify) g_hash_table_destroy); +- g_clear_pointer (&bbgoogle->priv->system_groups_by_id, (GDestroyNotify) g_hash_table_destroy); +- +- g_rec_mutex_clear (&bbgoogle->priv->groups_lock); +- g_rec_mutex_clear (&bbgoogle->priv->conn_lock); +- +- /* Chain up to parent's method. */ +- G_OBJECT_CLASS (e_book_backend_google_parent_class)->finalize (object); +-} +- +-static void +-e_book_backend_google_init (EBookBackendGoogle *bbgoogle) +-{ +- bbgoogle->priv = e_book_backend_google_get_instance_private (bbgoogle); +- bbgoogle->priv->preloaded = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); +- +- g_rec_mutex_init (&bbgoogle->priv->groups_lock); +- g_rec_mutex_init (&bbgoogle->priv->conn_lock); +- +- bbgoogle->priv->groups_by_id = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); +- bbgoogle->priv->groups_by_name = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); +- bbgoogle->priv->system_groups_by_id = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); +- /* shares keys and values with system_groups_by_id */ +- bbgoogle->priv->system_groups_by_entry_id = g_hash_table_new (g_str_hash, g_str_equal); +-} +- +-static void +-e_book_backend_google_class_init (EBookBackendGoogleClass *klass) +-{ +- GObjectClass *object_class; +- EBookBackendClass *book_backend_class; +- EBookMetaBackendClass *book_meta_backend_class; +- +- book_meta_backend_class = E_BOOK_META_BACKEND_CLASS (klass); +- book_meta_backend_class->backend_module_filename = "libebookbackendgoogle.so"; +- book_meta_backend_class->backend_factory_type_name = "EBookBackendGoogleFactory"; +- book_meta_backend_class->connect_sync = ebb_google_connect_sync; +- book_meta_backend_class->disconnect_sync = ebb_google_disconnect_sync; +- book_meta_backend_class->get_changes_sync = ebb_google_get_changes_sync; +- book_meta_backend_class->load_contact_sync = ebb_google_load_contact_sync; +- book_meta_backend_class->save_contact_sync = ebb_google_save_contact_sync; +- book_meta_backend_class->remove_contact_sync = ebb_google_remove_contact_sync; +- +- book_backend_class = E_BOOK_BACKEND_CLASS (klass); +- book_backend_class->impl_get_backend_property = ebb_google_get_backend_property; +- +- object_class = G_OBJECT_CLASS (klass); +- object_class->constructed = ebb_google_constructed; +- object_class->dispose = ebb_google_dispose; +- object_class->finalize = ebb_google_finalize; +-} +diff --git a/src/addressbook/backends/google/e-book-backend-google.h b/src/addressbook/backends/google/e-book-backend-google.h +deleted file mode 100644 +index fcbf1dec1..000000000 +--- a/src/addressbook/backends/google/e-book-backend-google.h ++++ /dev/null +@@ -1,63 +0,0 @@ +-/* e-book-backend-google.h - Google contact backendy. +- * +- * Copyright (C) 2008 Joergen Scheibengruber +- * +- * This library is free software: you can redistribute it and/or modify it +- * under the terms of the GNU Lesser General Public License as published by +- * the Free Software Foundation. +- * +- * This library is distributed in the hope that it will be useful, but +- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License +- * for more details. +- * +- * You should have received a copy of the GNU Lesser General Public License +- * along with this library. If not, see . +- * +- * Authors: Joergen Scheibengruber +- */ +- +-#ifndef E_BOOK_BACKEND_GOOGLE_H +-#define E_BOOK_BACKEND_GOOGLE_H +- +-#include +- +-/* Standard GObject macros */ +-#define E_TYPE_BOOK_BACKEND_GOOGLE \ +- (e_book_backend_google_get_type ()) +-#define E_BOOK_BACKEND_GOOGLE(obj) \ +- (G_TYPE_CHECK_INSTANCE_CAST \ +- ((obj), E_TYPE_BOOK_BACKEND_GOOGLE, EBookBackendGoogle)) +-#define E_BOOK_BACKEND_GOOGLE_CLASS(cls) \ +- (G_TYPE_CHECK_CLASS_CAST \ +- ((cls), E_TYPE_BOOK_BACKEND_GOOGLE, EBookBackendGoogleClass)) +-#define E_IS_BOOK_BACKEND_GOOGLE(obj) \ +- (G_TYPE_CHECK_INSTANCE_TYPE \ +- ((obj), E_TYPE_BOOK_BACKEND_GOOGLE)) +-#define E_IS_BOOK_BACKEND_GOOGLE_CLASS(cls) \ +- (G_TYPE_CHECK_CLASS_TYPE \ +- ((cls), E_TYPE_BOOK_BACKEND_GOOGLE)) +-#define E_BOOK_BACKEND_GOOGLE_GET_CLASS(obj) \ +- (G_TYPE_INSTANCE_GET_CLASS \ +- ((obj), E_TYPE_BOOK_BACKEND_GOOGLE, EBookBackendGoogleClass)) +- +-G_BEGIN_DECLS +- +-typedef struct _EBookBackendGoogle EBookBackendGoogle; +-typedef struct _EBookBackendGoogleClass EBookBackendGoogleClass; +-typedef struct _EBookBackendGooglePrivate EBookBackendGooglePrivate; +- +-struct _EBookBackendGoogle { +- EBookMetaBackend parent_object; +- EBookBackendGooglePrivate *priv; +-}; +- +-struct _EBookBackendGoogleClass { +- EBookMetaBackendClass parent_class; +-}; +- +-GType e_book_backend_google_get_type (void); +- +-G_END_DECLS +- +-#endif /* E_BOOK_BACKEND_GOOGLE_H */ +diff --git a/src/addressbook/backends/google/e-book-google-utils.c b/src/addressbook/backends/google/e-book-google-utils.c +deleted file mode 100644 +index 3b14a4e9d..000000000 +--- a/src/addressbook/backends/google/e-book-google-utils.c ++++ /dev/null +@@ -1,1747 +0,0 @@ +-/* e-book-google-utils.c - Google contact conversion utilities. +- * +- * Copyright (C) 2008 Joergen Scheibengruber +- * Copyright (C) 2010, 2011, 2012 Philip Withnall +- * +- * This library is free software: you can redistribute it and/or modify it +- * under the terms of the GNU Lesser General Public License as published by +- * the Free Software Foundation. +- * +- * This library is distributed in the hope that it will be useful, but +- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License +- * for more details. +- * +- * You should have received a copy of the GNU Lesser General Public License +- * along with this library. If not, see . +- * +- * Authors: Joergen Scheibengruber +- * Philip Withnall +- */ +- +-#include "evolution-data-server-config.h" +- +-#include +-#include +- +-#include +-#include +-#include +- +-#include "e-book-google-utils.h" +- +-/* Definitions for our custom X-URIS vCard attribute for storing URIs. +- * See: bgo#659079. It would be nice to move this into EVCard sometime. */ +-#define GDATA_URIS_ATTR "X-URIS" +-#define GDATA_URIS_TYPE_HOME_PAGE "X-HOME-PAGE" +-#define GDATA_URIS_TYPE_BLOG "X-BLOG" +-#define GDATA_URIS_TYPE_PROFILE "X-PROFILE" +-#define GDATA_URIS_TYPE_FTP "X-FTP" +- +-#define GOOGLE_SYSTEM_GROUP_ATTR "X-GOOGLE-SYSTEM-GROUP-IDS" +- +-#define MULTIVALUE_ATTRIBUTE_SUFFIX "-MULTIVALUE" +- +-gboolean __e_book_google_utils_debug__; +-#define __debug__(...) (__e_book_google_utils_debug__ ? g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, __VA_ARGS__) : (void) 0) +- +-#define GOOGLE_PRIMARY_PARAM "X-EVOLUTION-UI-SLOT" +-#define GOOGLE_LABEL_PARAM "X-GOOGLE-LABEL" +-#define GDATA_ENTRY_XML_ATTR "X-GDATA-ENTRY-XML" +-#define GDATA_ENTRY_LINK_ATTR "X-GDATA-ENTRY-LINK" +- +-static void add_attribute_from_gdata_gd_email_address (EVCard *vcard, GDataGDEmailAddress *email); +-static void add_attribute_from_gdata_gd_im_address (EVCard *vcard, GDataGDIMAddress *im); +-static void add_attribute_from_gdata_gd_phone_number (EVCard *vcard, GDataGDPhoneNumber *number); +-static void add_attribute_from_gdata_gd_postal_address (EVCard *vcard, GDataGDPostalAddress *address); +-static void add_attribute_from_gdata_gd_organization (EVCard *vcard, GDataGDOrganization *org); +-static void add_attribute_from_gc_contact_website (EVCard *vcard, GDataGContactWebsite *website); +- +-static GDataGDEmailAddress *gdata_gd_email_address_from_attribute (EVCardAttribute *attr, gboolean *primary); +-static GDataGDIMAddress *gdata_gd_im_address_from_attribute (EVCardAttribute *attr, gboolean *primary); +-static GDataGDPhoneNumber *gdata_gd_phone_number_from_attribute (EVCardAttribute *attr, gboolean *primary); +-static GDataGDPostalAddress *gdata_gd_postal_address_from_attribute (EVCardAttribute *attr, gboolean *primary); +-static GDataGDOrganization *gdata_gd_organization_from_attribute (EVCardAttribute *attr, gboolean *primary); +-static GDataGContactWebsite *gdata_gc_contact_website_from_attribute (EVCardAttribute *attr, gboolean *primary); +- +-static gboolean is_known_google_im_protocol (const gchar *protocol); +- +-GDataEntry * +-gdata_entry_new_from_e_contact (EContact *contact, +- GHashTable *groups_by_name, +- GHashTable *system_groups_by_id, +- EContactGoogleCreateGroupFunc create_group, +- EBookBackendGoogle *bbgoogle, +- GCancellable *cancellable) +-{ +- GDataEntry *entry; +- +- g_return_val_if_fail (E_IS_CONTACT (contact), NULL); +- g_return_val_if_fail (groups_by_name != NULL, NULL); +- g_return_val_if_fail (system_groups_by_id != NULL, NULL); +- g_return_val_if_fail (g_hash_table_size (system_groups_by_id) > 0, FALSE); +- g_return_val_if_fail (create_group != NULL, NULL); +- +- entry = GDATA_ENTRY (gdata_contacts_contact_new (NULL)); +- +- if (gdata_entry_update_from_e_contact (entry, contact, TRUE, groups_by_name, system_groups_by_id, create_group, bbgoogle, cancellable)) +- return entry; +- +- g_object_unref (entry); +- +- return NULL; +-} +- +-static void +-remove_anniversary (GDataContactsContact *contact) +-{ +- GList *events, *itr; +- +- events = gdata_contacts_contact_get_events (contact); +- if (!events) +- return; +- +- events = g_list_copy (events); +- g_list_foreach (events, (GFunc) g_object_ref, NULL); +- +- gdata_contacts_contact_remove_all_events (contact); +- for (itr = events; itr; itr = itr->next) { +- GDataGContactEvent *event = itr->data; +- +- if (g_strcmp0 (gdata_gcontact_event_get_relation_type (event), GDATA_GCONTACT_EVENT_ANNIVERSARY) != 0) +- gdata_contacts_contact_add_event (contact, event); +- } +- +- g_list_foreach (events, (GFunc) g_object_unref, NULL); +- g_list_free (events); +-} +- +-gboolean +-gdata_entry_update_from_e_contact (GDataEntry *entry, +- EContact *contact, +- gboolean ensure_personal_group, +- GHashTable *groups_by_name, +- GHashTable *system_groups_by_id, +- EContactGoogleCreateGroupFunc create_group, +- EBookBackendGoogle *bbgoogle, +- GCancellable *cancellable) +-{ +- GList *attributes, *iter, *category_names, *extended_property_names; +- EContactName *name_struct = NULL; +- EContactPhoto *photo; +- gboolean have_email_primary = FALSE; +- gboolean have_im_primary = FALSE; +- gboolean have_phone_primary = FALSE; +- gboolean have_postal_primary = FALSE; +- gboolean have_org_primary = FALSE; +- gboolean have_uri_primary = FALSE; +- gchar *title, *role, *note, *nickname; +- EContactDate *bdate; +- const gchar *url; +- +-#if defined(GDATA_CHECK_VERSION) +-#if GDATA_CHECK_VERSION(0, 11, 0) +- const gchar *file_as; +-#endif +-#endif +- +- g_return_val_if_fail (GDATA_IS_ENTRY (entry), FALSE); +- g_return_val_if_fail (E_IS_CONTACT (contact), FALSE); +- g_return_val_if_fail (groups_by_name != NULL, FALSE); +- g_return_val_if_fail (system_groups_by_id != NULL, FALSE); +- g_return_val_if_fail (g_hash_table_size (system_groups_by_id) > 0, FALSE); +- g_return_val_if_fail (create_group != NULL, FALSE); +- +- attributes = e_vcard_get_attributes (E_VCARD (contact)); +- +- /* N and FN */ +- name_struct = e_contact_get (contact, E_CONTACT_NAME); +- if (name_struct) { +- GDataGDName *name; +- const gchar *given = NULL, *family = NULL; +- +- if (name_struct->given && *(name_struct->given) != '\0') +- given = name_struct->given; +- if (name_struct->family && *(name_struct->family) != '\0') +- family = name_struct->family; +- +- name = gdata_gd_name_new (given, family); +- if (name_struct->additional && *(name_struct->additional) != '\0') +- gdata_gd_name_set_additional_name (name, name_struct->additional); +- if (name_struct->prefixes && *(name_struct->prefixes) != '\0') +- gdata_gd_name_set_prefix (name, name_struct->prefixes); +- if (name_struct->suffixes && *(name_struct->suffixes) != '\0') +- gdata_gd_name_set_suffix (name, name_struct->suffixes); +- gdata_gd_name_set_full_name (name, e_contact_get (contact, E_CONTACT_FULL_NAME)); +- +- gdata_contacts_contact_set_name (GDATA_CONTACTS_CONTACT (entry), name); +- g_object_unref (name); +- } +- +-#if defined(GDATA_CHECK_VERSION) +-#if GDATA_CHECK_VERSION(0, 11, 0) +- /* File as */ +- file_as = e_contact_get (contact, E_CONTACT_FILE_AS); +- if (file_as && *file_as) +- gdata_contacts_contact_set_file_as (GDATA_CONTACTS_CONTACT (entry), file_as); +- else +- gdata_contacts_contact_set_file_as (GDATA_CONTACTS_CONTACT (entry), NULL); +-#endif +-#endif +- +- /* NOTE */ +- note = e_contact_get (contact, E_CONTACT_NOTE); +- if (note) +- gdata_entry_set_content (entry, note); +- else +- gdata_entry_set_content (entry, NULL); +- g_free (note); +- +- /* Nickname */ +- nickname = e_contact_get (contact, E_CONTACT_NICKNAME); +- gdata_contacts_contact_set_nickname (GDATA_CONTACTS_CONTACT (entry), nickname && *nickname ? nickname : NULL); +- g_free (nickname); +- +- /* Clear out all the old attributes */ +- gdata_contacts_contact_remove_all_email_addresses (GDATA_CONTACTS_CONTACT (entry)); +- gdata_contacts_contact_remove_all_phone_numbers (GDATA_CONTACTS_CONTACT (entry)); +- gdata_contacts_contact_remove_all_postal_addresses (GDATA_CONTACTS_CONTACT (entry)); +- gdata_contacts_contact_remove_all_im_addresses (GDATA_CONTACTS_CONTACT (entry)); +- gdata_contacts_contact_remove_all_organizations (GDATA_CONTACTS_CONTACT (entry)); +- gdata_contacts_contact_remove_all_websites (GDATA_CONTACTS_CONTACT (entry)); +- +- category_names = gdata_contacts_contact_get_groups (GDATA_CONTACTS_CONTACT (entry)); +- for (iter = category_names; iter != NULL; iter = g_list_delete_link (iter, iter)) +- gdata_contacts_contact_remove_group (GDATA_CONTACTS_CONTACT (entry), iter->data); +- +- extended_property_names = g_hash_table_get_keys (gdata_contacts_contact_get_extended_properties (GDATA_CONTACTS_CONTACT (entry))); +- for (iter = extended_property_names; iter != NULL; iter = g_list_delete_link (iter, iter)) { +- gdata_contacts_contact_set_extended_property (GDATA_CONTACTS_CONTACT (entry), iter->data, NULL); +- } +- +- /* We walk them in reverse order, so we can find +- * the correct primaries */ +- iter = g_list_last (attributes); +- for (; iter; iter = iter->prev) { +- EVCardAttribute *attr; +- const gchar *name; +- +- attr = iter->data; +- name = e_vcard_attribute_get_name (attr); +- +- if (0 == g_ascii_strcasecmp (name, EVC_UID) || +- 0 == g_ascii_strcasecmp (name, EVC_REV) || +- 0 == g_ascii_strcasecmp (name, EVC_N) || +- 0 == g_ascii_strcasecmp (name, EVC_FN) || +- 0 == g_ascii_strcasecmp (name, EVC_LABEL) || +- 0 == g_ascii_strcasecmp (name, EVC_VERSION) || +- 0 == g_ascii_strcasecmp (name, EVC_X_FILE_AS) || +- 0 == g_ascii_strcasecmp (name, EVC_TITLE) || +- 0 == g_ascii_strcasecmp (name, EVC_ROLE) || +- 0 == g_ascii_strcasecmp (name, EVC_NOTE) || +- 0 == g_ascii_strcasecmp (name, EVC_CATEGORIES) || +- 0 == g_ascii_strcasecmp (name, EVC_PHOTO) || +- 0 == g_ascii_strcasecmp (name, GOOGLE_SYSTEM_GROUP_ATTR) || +- 0 == g_ascii_strcasecmp (name, e_contact_field_name (E_CONTACT_NICKNAME)) || +- 0 == g_ascii_strcasecmp (name, E_GOOGLE_X_PHOTO_ETAG)) { +- /* Ignore attributes which are treated separately */ +- } else if (0 == g_ascii_strcasecmp (name, EVC_EMAIL)) { +- /* EMAIL */ +- GDataGDEmailAddress *email; +- +- email = gdata_gd_email_address_from_attribute (attr, &have_email_primary); +- if (email) { +- gdata_contacts_contact_add_email_address (GDATA_CONTACTS_CONTACT (entry), email); +- g_object_unref (email); +- } +- } else if (0 == g_ascii_strcasecmp (name, EVC_TEL)) { +- /* TEL */ +- GDataGDPhoneNumber *number; +- +- number = gdata_gd_phone_number_from_attribute (attr, &have_phone_primary); +- if (number) { +- gdata_contacts_contact_add_phone_number (GDATA_CONTACTS_CONTACT (entry), number); +- g_object_unref (number); +- } +- } else if (0 == g_ascii_strcasecmp (name, EVC_ADR)) { +- /* ADR (we ignore LABEL, since it should be the same as ADR, and ADR is more structured) */ +- GDataGDPostalAddress *address; +- +- address = gdata_gd_postal_address_from_attribute (attr, &have_postal_primary); +- if (address) { +- gdata_contacts_contact_add_postal_address (GDATA_CONTACTS_CONTACT (entry), address); +- g_object_unref (address); +- } +- } else if (0 == g_ascii_strcasecmp (name, EVC_ORG)) { +- /* ORG */ +- GDataGDOrganization *org; +- +- org = gdata_gd_organization_from_attribute (attr, &have_org_primary); +- if (org) { +- gdata_contacts_contact_add_organization (GDATA_CONTACTS_CONTACT (entry), org); +- g_object_unref (org); +- } +- } else if (0 == g_ascii_strncasecmp (name, "X-", 2) && is_known_google_im_protocol (name + 2)) { +- /* X-IM */ +- GDataGDIMAddress *im; +- +- im = gdata_gd_im_address_from_attribute (attr, &have_im_primary); +- if (im) { +- gdata_contacts_contact_add_im_address (GDATA_CONTACTS_CONTACT (entry), im); +- g_object_unref (im); +- } +- } else if (0 == g_ascii_strcasecmp (name, GDATA_URIS_ATTR)) { +- /* X-URIS */ +- GDataGContactWebsite *website; +- +- website =gdata_gc_contact_website_from_attribute (attr, &have_uri_primary); +- if (website) { +- gdata_contacts_contact_add_website (GDATA_CONTACTS_CONTACT (entry), website); +- g_object_unref (website); +- } +- } else if (e_vcard_attribute_is_single_valued (attr)) { +- gchar *value; +- +- /* Add the attribute as an extended property */ +- value = e_vcard_attribute_get_value (attr); +- gdata_contacts_contact_set_extended_property (GDATA_CONTACTS_CONTACT (entry), name, value); +- g_free (value); +- } else { +- gchar *multi_name; +- GList *values, *l; +- GString *value; +- +- value = g_string_new (""); +- values = e_vcard_attribute_get_values (attr); +- +- for (l = values; l != NULL; l = l->next) { +- gchar *escaped = e_vcard_escape_string (l->data); +- g_string_append (value, escaped); +- if (l->next != NULL) +- g_string_append_c (value, ','); +- g_free (escaped); +- } +- multi_name = g_strconcat (name, MULTIVALUE_ATTRIBUTE_SUFFIX, NULL); +- gdata_contacts_contact_set_extended_property (GDATA_CONTACTS_CONTACT (entry), multi_name, value->str); +- g_free (multi_name); +- g_string_free (value, TRUE); +- } +- } +- +- /* TITLE and ROLE */ +- title = e_contact_get (contact, E_CONTACT_TITLE); +- role = e_contact_get (contact, E_CONTACT_ROLE); +- if (title || role) { +- GDataGDOrganization *org = NULL; +- +- /* Find an appropriate org: try to add them to the primary organization, but fall back to the first listed organization if none +- * are marked as primary. */ +- if (have_org_primary) { +- org = gdata_contacts_contact_get_primary_organization (GDATA_CONTACTS_CONTACT (entry)); +- } else { +- GList *orgs = gdata_contacts_contact_get_organizations (GDATA_CONTACTS_CONTACT (entry)); +- if (orgs) +- org = orgs->data; +- } +- +- /* Set the title and role */ +- if (org != NULL && title != NULL && *title != '\0') +- gdata_gd_organization_set_title (org, title); +- if (org != NULL && role != NULL && *role != '\0') +- gdata_gd_organization_set_job_description (org, role); +- } +- +- g_free (title); +- g_free (role); +- +- url = e_contact_get_const (contact, E_CONTACT_HOMEPAGE_URL); +- if (url && *url) { +- GDataGContactWebsite *website = gdata_gcontact_website_new (url, GDATA_GCONTACT_WEBSITE_HOME_PAGE, NULL, FALSE); +- if (website) { +- gdata_contacts_contact_add_website (GDATA_CONTACTS_CONTACT (entry), website); +- g_object_unref (website); +- } +- } +- +- url = e_contact_get_const (contact, E_CONTACT_BLOG_URL); +- if (url && *url) { +- GDataGContactWebsite *website = gdata_gcontact_website_new (url, GDATA_GCONTACT_WEBSITE_BLOG, NULL, FALSE); +- if (website) { +- gdata_contacts_contact_add_website (GDATA_CONTACTS_CONTACT (entry), website); +- g_object_unref (website); +- } +- } +- +- gdata_contacts_contact_set_birthday (GDATA_CONTACTS_CONTACT (entry), NULL, TRUE); +- bdate = e_contact_get (contact, E_CONTACT_BIRTH_DATE); +- if (bdate) { +- GDate *gdate = g_date_new_dmy (bdate->day, bdate->month, bdate->year); +- +- if (gdate) { +- gdata_contacts_contact_set_birthday (GDATA_CONTACTS_CONTACT (entry), gdate, TRUE); +- g_date_free (gdate); +- } +- e_contact_date_free (bdate); +- } +- +- remove_anniversary (GDATA_CONTACTS_CONTACT (entry)); +- bdate = e_contact_get (contact, E_CONTACT_ANNIVERSARY); +- if (bdate) { +- GDate *gdate = g_date_new_dmy (bdate->day, bdate->month, bdate->year); +- +- if (gdate) { +- GDataGContactEvent *anni = gdata_gcontact_event_new (gdate, GDATA_GCONTACT_EVENT_ANNIVERSARY, NULL); +- +- if (anni) { +- gdata_contacts_contact_add_event (GDATA_CONTACTS_CONTACT (entry), anni); +- g_object_unref (anni); +- } +- +- g_date_free (gdate); +- } +- e_contact_date_free (bdate); +- } +- +- /* Map X-GOOGLE-SYSTEM-GROUP-IDS from outside to CATEGORIES. +- * They will be mapped again to system group ids below; this is done +- * so e-d-s / evolution (which use CATEGORIES), folks / gnome-contacts +- * (which use X-GOOGLE-SYSTEM-GROUP-IDS) and google contacts (which +- * uses the GData group IDs) all stay in sync */ +- { +- EVCardAttribute *system_group_attr; +- EVCardAttribute *categories_attr; +- +- system_group_attr = e_vcard_get_attribute (E_VCARD (contact), GOOGLE_SYSTEM_GROUP_ATTR); +- categories_attr = e_vcard_get_attribute (E_VCARD (contact), EVC_CATEGORIES); +- +- if (system_group_attr) { +- GList *system_groups = e_vcard_attribute_get_values (system_group_attr); +- GList *sys_group; +- +- for (sys_group = system_groups; sys_group; sys_group = sys_group->next) { +- const gchar *category_name; +- +- category_name = e_contact_map_google_with_evo_group (sys_group->data, TRUE); +- +- if (!categories_attr) { +- categories_attr = e_vcard_attribute_new (NULL, EVC_CATEGORIES); +- e_vcard_append_attribute (E_VCARD (contact), categories_attr); +- } +- +- e_vcard_attribute_add_value (categories_attr, category_name); +- } +- } +- } +- +- /* CATEGORIES */ +- for (category_names = e_contact_get (contact, E_CONTACT_CATEGORY_LIST); category_names != NULL; category_names = category_names->next) { +- gchar *category_id = NULL; +- const gchar *category_name = category_names->data; +- const gchar *system_group_id; +- +- if (category_name == NULL || *category_name == '\0') +- continue; +- +- system_group_id = e_contact_map_google_with_evo_group (category_name, FALSE); +- if (system_group_id) { +- const gchar *group_entry_id = g_hash_table_lookup (system_groups_by_id, system_group_id); +- +- g_warn_if_fail (group_entry_id != NULL); +- +- category_id = g_strdup (group_entry_id); +- } +- +- if (category_id == NULL) +- category_id = g_strdup (g_hash_table_lookup (groups_by_name, category_name)); +- if (category_id == NULL) { +- GError *local_error = NULL; +- +- category_id = create_group (bbgoogle, category_name, cancellable, &local_error); +- if (category_id == NULL) { +- g_warning ("Error creating group '%s': %s", category_name, local_error ? local_error->message : "Unknown error"); +- g_clear_error (&local_error); +- continue; +- } +- } +- +- /* Add the category to Evolution’s category list. */ +- e_categories_add (category_name, NULL, NULL, TRUE); +- +- gdata_contacts_contact_add_group (GDATA_CONTACTS_CONTACT (entry), category_id); +- if (g_strcmp0 (system_group_id, GDATA_CONTACTS_GROUP_CONTACTS) == 0) +- ensure_personal_group = FALSE; +- g_free (category_id); +- } +- +- /* to have contacts shown in My Contacts by default, +- * see https://bugzilla.gnome.org/show_bug.cgi?id=663324 +- * for more details */ +- if (ensure_personal_group) { +- const gchar *group_entry_id = g_hash_table_lookup (system_groups_by_id, GDATA_CONTACTS_GROUP_CONTACTS); +- +- g_warn_if_fail (group_entry_id != NULL); +- +- if (group_entry_id) +- gdata_contacts_contact_add_group (GDATA_CONTACTS_CONTACT (entry), group_entry_id); +- } +- +- /* PHOTO */ +- photo = e_contact_get (contact, E_CONTACT_PHOTO); +- +- if (photo != NULL && photo->type == E_CONTACT_PHOTO_TYPE_INLINED) { +- g_object_set_data_full (G_OBJECT (entry), "photo", photo, (GDestroyNotify) e_contact_photo_free); +- } else { +- g_object_set_data (G_OBJECT (entry), "photo", NULL); +- +- if (photo != NULL) { +- e_contact_photo_free (photo); +- } +- } +- +- return TRUE; +-} +- +-static void +-foreach_extended_props_cb (const gchar *name, +- const gchar *value, +- EVCard *vcard) +-{ +- EVCardAttribute *attr; +- gchar *multi_name; +- GString *str; +- const gchar *p; +- +- if (g_str_has_suffix (name, MULTIVALUE_ATTRIBUTE_SUFFIX)) { +- multi_name = g_strndup (name, strlen (name) - strlen (MULTIVALUE_ATTRIBUTE_SUFFIX)); +- +- attr = e_vcard_attribute_new (NULL, multi_name); +- g_free (multi_name); +- str = g_string_new (""); +- +- /* Unescape a string as described in RFC2426, section 5, breaking at unescaped commas */ +- for (p = value ? value : ""; *p; p++) { +- if (*p == '\\') { +- p++; +- if (*p == '\0') { +- g_string_append_c (str, '\\'); +- break; +- } +- switch (*p) { +- case 'n': g_string_append_c (str, '\n'); break; +- case 'r': g_string_append_c (str, '\r'); break; +- case ';': g_string_append_c (str, ';'); break; +- case ',': g_string_append_c (str, ','); break; +- case '\\': g_string_append_c (str, '\\'); break; +- default: +- g_warning ("invalid escape, passing it through"); +- g_string_append_c (str, '\\'); +- g_string_append_c (str, *p); +- break; +- } +- } else if (*p == ',') { +- if (str->len > 0) { +- e_vcard_attribute_add_value (attr, str->str); +- g_string_set_size (str, 0); +- } +- } else { +- g_string_append_c (str, *p); +- } +- } +- +- if (str->len > 0) { +- e_vcard_attribute_add_value (attr, str->str); +- g_string_set_size (str, 0); +- } +- g_string_free (str, TRUE); +- +- e_vcard_add_attribute (vcard, attr); +- +- } else { +- attr = e_vcard_attribute_new (NULL, name); +- e_vcard_add_attribute_with_value (vcard, attr, value); +- } +-} +- +-EContact * +-e_contact_new_from_gdata_entry (GDataEntry *entry, +- GHashTable *groups_by_id, +- GHashTable *system_groups_by_entry_id) +-{ +- EVCard *vcard; +- EVCardAttribute *attr, *system_group_ids_attr; +- GList *email_addresses, *im_addresses, *phone_numbers, *postal_addresses, *orgs, *category_names, *category_ids; +- const gchar *uid, *note, *nickname; +- GList *itr; +- GDataGDName *name; +- GDataGDEmailAddress *email; +- GDataGDIMAddress *im; +- GDataGDPhoneNumber *phone_number; +- GDataGDPostalAddress *postal_address; +- GDataGDOrganization *org; +- GHashTable *extended_props; +- GList *websites, *events; +- GDate bdate; +- GDateTime *dt; +- gchar *rev = NULL; +- gboolean bdate_has_year; +- gboolean have_uri_home = FALSE, have_uri_blog = FALSE; +- +-#if defined(GDATA_CHECK_VERSION) +-#if GDATA_CHECK_VERSION(0, 11, 0) +- const gchar *file_as; +-#endif +-#endif +- +- g_return_val_if_fail (system_groups_by_entry_id != NULL, NULL); +- g_return_val_if_fail (g_hash_table_size (system_groups_by_entry_id) > 0, FALSE); +- +- uid = e_book_google_utils_uid_from_entry (entry); +- if (NULL == uid) +- return NULL; +- +- vcard = E_VCARD (e_contact_new ()); +- +- /* UID */ +- attr = e_vcard_attribute_new (NULL, EVC_UID); +- e_vcard_add_attribute_with_value (vcard, attr, uid); +- +- if (gdata_entry_get_etag (entry)) +- e_vcard_util_set_x_attribute (vcard, E_GOOGLE_X_ETAG, gdata_entry_get_etag (entry)); +- +- /* REV */ +- attr = e_vcard_attribute_new (NULL, EVC_REV); +- dt = g_date_time_new_from_unix_utc (gdata_entry_get_updated (entry)); +- if (dt) { +- rev = g_date_time_format (dt, "%Y-%m-%dT%H:%M:%SZ"); +- g_date_time_unref (dt); +- } +- +- if (!rev) +- rev = g_strdup_printf ("%" G_GINT64_FORMAT, gdata_entry_get_updated (entry)); +- +- e_vcard_add_attribute_with_value (vcard, attr, rev); +- +- g_free (rev); +- +- /* FN, N */ +- name = gdata_contacts_contact_get_name (GDATA_CONTACTS_CONTACT (entry)); +- if (name) { +- EContactName name_struct; +- +- /* Set the full name */ +- e_contact_set (E_CONTACT (vcard), E_CONTACT_FULL_NAME, gdata_gd_name_get_full_name (name)); +- +- /* We just need to set the E_CONTACT_NAME field, and all the other name attribute values +- * in the EContact will be populated automatically from that */ +- name_struct.family = (gchar *) gdata_gd_name_get_family_name (name); +- name_struct.given = (gchar *) gdata_gd_name_get_given_name (name); +- name_struct.additional = (gchar *) gdata_gd_name_get_additional_name (name); +- name_struct.prefixes = (gchar *) gdata_gd_name_get_prefix (name); +- name_struct.suffixes = (gchar *) gdata_gd_name_get_suffix (name); +- +- e_contact_set (E_CONTACT (vcard), E_CONTACT_NAME, &name_struct); +- } +- +-#if defined(GDATA_CHECK_VERSION) +-#if GDATA_CHECK_VERSION(0, 11, 0) +- /* File as */ +- file_as = gdata_contacts_contact_get_file_as (GDATA_CONTACTS_CONTACT (entry)); +- if (file_as && *file_as) +- e_contact_set (E_CONTACT (vcard), E_CONTACT_FILE_AS, file_as); +-#endif +-#endif +- +- /* NOTE */ +- note = gdata_entry_get_content (entry); +- if (note) +- e_contact_set (E_CONTACT (vcard), E_CONTACT_NOTE, note); +- +- /* Nickname */ +- nickname = gdata_contacts_contact_get_nickname (GDATA_CONTACTS_CONTACT (entry)); +- if (nickname) +- e_contact_set (E_CONTACT (vcard), E_CONTACT_NICKNAME, nickname); +- +- /* EMAIL - primary first */ +- email = gdata_contacts_contact_get_primary_email_address (GDATA_CONTACTS_CONTACT (entry)); +- add_attribute_from_gdata_gd_email_address (vcard, email); +- +- email_addresses = gdata_contacts_contact_get_email_addresses (GDATA_CONTACTS_CONTACT (entry)); +- for (itr = email_addresses; itr; itr = itr->next) { +- email = itr->data; +- if (gdata_gd_email_address_is_primary (email) == TRUE) +- continue; +- add_attribute_from_gdata_gd_email_address (vcard, email); +- } +- +- /* X-IM - primary first */ +- im = gdata_contacts_contact_get_primary_im_address (GDATA_CONTACTS_CONTACT (entry)); +- add_attribute_from_gdata_gd_im_address (vcard, im); +- +- im_addresses = gdata_contacts_contact_get_im_addresses (GDATA_CONTACTS_CONTACT (entry)); +- for (itr = im_addresses; itr; itr = itr->next) { +- im = itr->data; +- if (gdata_gd_im_address_is_primary (im) == TRUE) +- continue; +- add_attribute_from_gdata_gd_im_address (vcard, im); +- } +- +- /* TEL - primary first */ +- phone_number = gdata_contacts_contact_get_primary_phone_number (GDATA_CONTACTS_CONTACT (entry)); +- add_attribute_from_gdata_gd_phone_number (vcard, phone_number); +- +- phone_numbers = gdata_contacts_contact_get_phone_numbers (GDATA_CONTACTS_CONTACT (entry)); +- for (itr = phone_numbers; itr; itr = itr->next) { +- phone_number = itr->data; +- if (gdata_gd_phone_number_is_primary (phone_number) == TRUE) +- continue; +- add_attribute_from_gdata_gd_phone_number (vcard, phone_number); +- } +- +- /* LABEL and ADR - primary first */ +- postal_address = gdata_contacts_contact_get_primary_postal_address (GDATA_CONTACTS_CONTACT (entry)); +- add_attribute_from_gdata_gd_postal_address (vcard, postal_address); +- +- postal_addresses = gdata_contacts_contact_get_postal_addresses (GDATA_CONTACTS_CONTACT (entry)); +- for (itr = postal_addresses; itr; itr = itr->next) { +- postal_address = itr->data; +- if (gdata_gd_postal_address_is_primary (postal_address) == TRUE) +- continue; +- add_attribute_from_gdata_gd_postal_address (vcard, postal_address); +- } +- +- /* TITLE, ROLE and ORG - primary first */ +- org = gdata_contacts_contact_get_primary_organization (GDATA_CONTACTS_CONTACT (entry)); +- orgs = gdata_contacts_contact_get_organizations (GDATA_CONTACTS_CONTACT (entry)); +- add_attribute_from_gdata_gd_organization (vcard, org); +- +- if (org || orgs) { +- if (!org) +- org = orgs->data; +- +- /* EVC_TITLE and EVC_ROLE from the primary organization (or the first organization in the list if there isn't a primary org) */ +- attr = e_vcard_attribute_new (NULL, EVC_TITLE); +- e_vcard_add_attribute_with_value (vcard, attr, gdata_gd_organization_get_title (org)); +- +- attr = e_vcard_attribute_new (NULL, EVC_ROLE); +- e_vcard_add_attribute_with_value (vcard, attr, gdata_gd_organization_get_job_description (org)); +- } +- +- for (itr = orgs; itr; itr = itr->next) { +- org = itr->data; +- add_attribute_from_gdata_gd_organization (vcard, org); +- } +- +- /* CATEGORIES */ +- category_ids = gdata_contacts_contact_get_groups (GDATA_CONTACTS_CONTACT (entry)); +- category_names = NULL; +- system_group_ids_attr = e_vcard_attribute_new ("", GOOGLE_SYSTEM_GROUP_ATTR); +- +- for (itr = category_ids; itr != NULL; itr = g_list_delete_link (itr, itr)) { +- gchar *category_id, *category_name; +- const gchar *system_group_id; +- +- category_id = e_contact_sanitise_google_group_id (itr->data); +- category_name = g_hash_table_lookup (groups_by_id, category_id); +- +- if (category_name != NULL) { +- if (g_list_find_custom (category_names, category_name, (GCompareFunc) g_strcmp0) == NULL) { +- category_names = g_list_prepend (category_names, category_name); +- +- /* Add the category to Evolution’s category list. */ +- e_categories_add (category_name, NULL, NULL, TRUE); +- } +- } else +- g_warning ("Couldn't find name for category with ID '%s'.", category_id); +- +- /* Maintain a list of the IDs of the system groups the contact is in. */ +- system_group_id = g_hash_table_lookup (system_groups_by_entry_id, category_id); +- if (system_group_id != NULL) { +- e_vcard_attribute_add_value (system_group_ids_attr, system_group_id); +- } +- +- g_free (category_id); +- } +- +- e_contact_set (E_CONTACT (vcard), E_CONTACT_CATEGORY_LIST, category_names); +- g_list_free (category_names); +- +- /* Expose the IDs of the system groups the contact is in so that libfolks (and other clients) can use the information +- * without having to reverse-engineer it from the (localised) category names on the contact. */ +- if (e_vcard_attribute_get_values (system_group_ids_attr) != NULL) { +- e_vcard_add_attribute (vcard, system_group_ids_attr); +- } else { +- e_vcard_attribute_free (system_group_ids_attr); +- } +- +- /* Extended properties */ +- extended_props = gdata_contacts_contact_get_extended_properties (GDATA_CONTACTS_CONTACT (entry)); +- g_hash_table_foreach (extended_props, (GHFunc) foreach_extended_props_cb, vcard); +- +- websites = gdata_contacts_contact_get_websites (GDATA_CONTACTS_CONTACT (entry)); +- for (itr = websites; itr != NULL; itr = itr->next) { +- GDataGContactWebsite *website = itr->data; +- const gchar *uri, *reltype; +- +- if (!website) +- continue; +- +- uri = gdata_gcontact_website_get_uri (website); +- reltype = gdata_gcontact_website_get_relation_type (website); +- +- if (!uri || !*uri || !reltype) +- continue; +- +- if (!have_uri_home && g_str_equal (reltype, GDATA_GCONTACT_WEBSITE_HOME_PAGE)) { +- e_contact_set (E_CONTACT (vcard), E_CONTACT_HOMEPAGE_URL, uri); +- have_uri_home = TRUE; +- } else if (!have_uri_blog && g_str_equal (reltype, GDATA_GCONTACT_WEBSITE_BLOG)) { +- e_contact_set (E_CONTACT (vcard), E_CONTACT_BLOG_URL, uri); +- have_uri_blog = TRUE; +- } else { +- add_attribute_from_gc_contact_website (vcard, website); +- } +- } +- +- g_date_clear (&bdate, 1); +- bdate_has_year = gdata_contacts_contact_get_birthday (GDATA_CONTACTS_CONTACT (entry), &bdate); +- if (!bdate_has_year) { +- GTimeVal curr_time = { 0 }; +- GDate tmp_date; +- +- g_get_current_time (&curr_time); +- g_date_clear (&tmp_date, 1); +- g_date_set_time_val (&tmp_date, &curr_time); +- +- g_date_set_year (&bdate, g_date_get_year (&tmp_date)); +- } +- +- if (g_date_valid (&bdate)) { +- EContactDate *date = e_contact_date_new (); +- +- if (date) { +- date->day = g_date_get_day (&bdate); +- date->month = g_date_get_month (&bdate); +- date->year = g_date_get_year (&bdate); +- +- e_contact_set (E_CONTACT (vcard), E_CONTACT_BIRTH_DATE, date); +- e_contact_date_free (date); +- } +- } +- +- events = gdata_contacts_contact_get_events (GDATA_CONTACTS_CONTACT (entry)); +- for (itr = events; itr; itr = itr->next) { +- GDataGContactEvent *event = itr->data; +- +- if (!event) +- continue; +- +- if (!gdata_gcontact_event_get_relation_type (event) || +- !g_str_equal (gdata_gcontact_event_get_relation_type (event), GDATA_GCONTACT_EVENT_ANNIVERSARY)) +- continue; +- +- g_date_clear (&bdate, 1); +- gdata_gcontact_event_get_date (event, &bdate); +- +- if (g_date_valid (&bdate)) { +- EContactDate *date = e_contact_date_new (); +- +- if (date) { +- date->day = g_date_get_day (&bdate); +- date->month = g_date_get_month (&bdate); +- date->year = g_date_get_year (&bdate); +- +- e_contact_set (E_CONTACT (vcard), E_CONTACT_ANNIVERSARY, date); +- e_contact_date_free (date); +- } +- } +- +- break; +- } +- +- return E_CONTACT (vcard); +-} +- +-void +-e_contact_add_gdata_entry_xml (EContact *contact, +- GDataEntry *entry) +-{ +- EVCardAttribute *attr; +- gchar *entry_xml; +- GDataLink *edit_link; +- +- /* Cache the XML representing the entry */ +- entry_xml = gdata_parsable_get_xml (GDATA_PARSABLE (entry)); +- attr = e_vcard_attribute_new ("", GDATA_ENTRY_XML_ATTR); +- e_vcard_attribute_add_value (attr, entry_xml); +- e_vcard_add_attribute (E_VCARD (contact), attr); +- g_free (entry_xml); +- +- /* Also add the update URI for the entry, since that's not serialised by gdata_parsable_get_xml */ +- edit_link = gdata_entry_look_up_link (entry, GDATA_LINK_EDIT); +- if (edit_link != NULL) { +- attr = e_vcard_attribute_new ("", GDATA_ENTRY_LINK_ATTR); +- e_vcard_attribute_add_value (attr, gdata_link_get_uri (edit_link)); +- e_vcard_add_attribute (E_VCARD (contact), attr); +- } +-} +- +-void +-e_contact_remove_gdata_entry_xml (EContact *contact) +-{ +- e_vcard_remove_attributes (E_VCARD (contact), NULL, GDATA_ENTRY_XML_ATTR); +- e_vcard_remove_attributes (E_VCARD (contact), NULL, GDATA_ENTRY_LINK_ATTR); +-} +- +-const gchar * +-e_contact_get_gdata_entry_xml (EContact *contact, +- const gchar **edit_uri) +-{ +- EVCardAttribute *attr; +- GList *values = NULL; +- +- /* Return the edit URI if asked */ +- if (edit_uri != NULL) { +- attr = e_vcard_get_attribute (E_VCARD (contact), GDATA_ENTRY_LINK_ATTR); +- if (attr != NULL) +- values = e_vcard_attribute_get_values (attr); +- if (values != NULL) +- *edit_uri = values->data; +- } +- +- /* Return the entry's XML */ +- attr = e_vcard_get_attribute (E_VCARD (contact), GDATA_ENTRY_XML_ATTR); +- values = e_vcard_attribute_get_values (attr); +- +- return values ? values->data : NULL; +-} +- +-struct RelTypeMap { +- const gchar *rel; +- const gchar *types[2]; +-}; +- +-/* NOTE: These maps must be kept ordered with the one-to-many types first */ +-static const struct RelTypeMap rel_type_map_phone[] = { +- { "home", { "HOME", "VOICE" }}, +- { "home_fax", { "HOME", "FAX" }}, +- { "work", { "WORK", "VOICE" }}, +- { "work_fax", { "WORK", "FAX" }}, +- { "work_mobile", { "WORK", "CELL" }}, +- { "work_pager", { "WORK", "PAGER" }}, +- { "assistant", { EVC_X_ASSISTANT, NULL }}, +- { "callback", { EVC_X_CALLBACK, NULL }}, +- { "car", { "CAR", NULL }}, +- { "company_main", {EVC_X_COMPANY, NULL }}, +- { "isdn", { "ISDN", NULL }}, +- { "main", { "PREF", NULL }}, +- { "mobile", { "CELL", NULL }}, +- { "other", { "VOICE", NULL }}, +- { "other_fax", { "FAX", NULL }}, +- { "pager", { "PAGER", NULL }}, +- { "radio", { EVC_X_RADIO, NULL }}, +- { "telex", { EVC_X_TELEX, NULL }}, +- { "tty_tdd", { EVC_X_TTYTDD, NULL }}, +- +- /* XXX This has no clear mapping to an EContact field. +- * It's listed here for completeness, but ordered +- * last so that "other_fax" is preferred. */ +- { "fax", { "FAX", NULL }} +-}; +- +-static const struct RelTypeMap rel_type_map_im[] = { +- { "home", { "HOME", NULL }}, +- { "netmeeting", { "NETMEETING", NULL }}, +- { "other", { "OTHER", NULL }}, +- { "work", { "WORK", NULL }}, +-}; +- +-static const struct RelTypeMap rel_type_map_uris[] = { +- { GDATA_GCONTACT_WEBSITE_HOME_PAGE, { GDATA_URIS_TYPE_HOME_PAGE, NULL }}, +- { GDATA_GCONTACT_WEBSITE_BLOG, { GDATA_URIS_TYPE_BLOG, NULL }}, +- { GDATA_GCONTACT_WEBSITE_PROFILE, { GDATA_URIS_TYPE_PROFILE, NULL }}, +- { GDATA_GCONTACT_WEBSITE_FTP, { GDATA_URIS_TYPE_FTP, NULL }}, +- { GDATA_GCONTACT_WEBSITE_HOME, { "HOME", NULL }}, +- { GDATA_GCONTACT_WEBSITE_OTHER, { "OTHER", NULL }}, +- { GDATA_GCONTACT_WEBSITE_WORK, { "WORK", NULL }}, +-}; +- +-static const struct RelTypeMap rel_type_map_others[] = { +- { "home", { "HOME", NULL }}, +- { "other", { "OTHER", NULL }}, +- { "work", { "WORK", NULL }}, +-}; +- +-static gboolean +-_add_type_param_from_google_rel (EVCardAttribute *attr, +- const struct RelTypeMap rel_type_map[], +- guint map_len, +- const gchar *rel) +-{ +- const gchar * field; +- guint i; +- +- field = strstr (rel ? rel : "", "#"); +- if (NULL == field) +- return FALSE; +- +- field++; +- for (i = 0; i < map_len; i++) { +- if (0 == g_ascii_strcasecmp (rel_type_map[i].rel, field)) { +- EVCardAttributeParam *param; +- param = e_vcard_attribute_param_new ("TYPE"); +- e_vcard_attribute_param_add_value (param, rel_type_map[i].types[0]); +- if (rel_type_map[i].types[1]) +- e_vcard_attribute_param_add_value (param, rel_type_map[i].types[1]); +- e_vcard_attribute_add_param (attr, param); +- return TRUE; +- } +- } +- g_warning ("Unknown relationship '%s'", rel); +- +- return TRUE; +-} +- +-static gboolean +-add_type_param_from_google_rel_phone (EVCardAttribute *attr, +- const gchar *rel) +-{ +- return _add_type_param_from_google_rel (attr, rel_type_map_phone, G_N_ELEMENTS (rel_type_map_phone), rel); +-} +- +-static gboolean +-add_type_param_from_google_rel_im (EVCardAttribute *attr, +- const gchar *rel) +-{ +- return _add_type_param_from_google_rel (attr, rel_type_map_im, G_N_ELEMENTS (rel_type_map_im), rel); +-} +- +-static gboolean +-add_type_param_from_google_rel_uris (EVCardAttribute *attr, +- const gchar *rel) +-{ +- return _add_type_param_from_google_rel (attr, rel_type_map_uris, G_N_ELEMENTS (rel_type_map_uris), rel); +-} +- +-static gboolean +-add_type_param_from_google_rel (EVCardAttribute *attr, +- const gchar *rel) +-{ +- return _add_type_param_from_google_rel (attr, rel_type_map_others, G_N_ELEMENTS (rel_type_map_others), rel); +-} +- +-static void +-add_label_param (EVCardAttribute *attr, +- const gchar *label) +-{ +- if (label && label[0] != '\0') { +- EVCardAttributeParam *param; +- param = e_vcard_attribute_param_new (GOOGLE_LABEL_PARAM); +- e_vcard_attribute_add_param_with_value (attr, param, label); +- } +-} +- +-static gchar * +-_google_rel_from_types (GList *types, +- const struct RelTypeMap rel_type_map[], +- guint map_len, +- gboolean use_prefix) +-{ +- const gchar *format = "http://schemas.google.com/g/2005#%s"; +- guint i; +- if (!use_prefix) +- format = "%s"; +- +- /* For each of the entries in the map... */ +- for (i = 0; i < map_len; i++) { +- GList *cur; +- gboolean first_matched = FALSE, second_matched = rel_type_map[i].types[1] ? FALSE : TRUE; +- +- /* ...iterate through all the vCard's types and see if two of them match the types in the current map entry. */ +- for (cur = types; cur != NULL; cur = cur->next) { +- if (0 == g_ascii_strcasecmp (rel_type_map[i].types[0], cur->data)) +- first_matched = TRUE; +- else if (!rel_type_map[i].types[1] || 0 == g_ascii_strcasecmp (rel_type_map[i].types[1], cur->data)) +- second_matched = TRUE; +- +- /* If they do, return the rel value from that entry... */ +- if (first_matched && second_matched) +- return g_strdup_printf (format, rel_type_map[i].rel); +- } +- } +- +- /* ...otherwise return an "other" result. */ +- return g_strdup_printf (format, "other"); +-} +- +-static gchar * +-google_rel_from_types (GList *types) +-{ +- return _google_rel_from_types (types, rel_type_map_others, G_N_ELEMENTS (rel_type_map_others), TRUE); +-} +- +-static gchar * +-google_rel_from_types_phone (GList *types) +-{ +- return _google_rel_from_types (types, rel_type_map_phone, G_N_ELEMENTS (rel_type_map_phone), TRUE); +-} +- +-static gchar * +-google_rel_from_types_uris (GList *types) +-{ +- return _google_rel_from_types (types, rel_type_map_uris, G_N_ELEMENTS (rel_type_map_uris), FALSE); +-} +- +-static gboolean +-is_known_google_im_protocol (const gchar *protocol) +-{ +- const gchar *known_protocols[] = { +- "AIM", "MSN", "YAHOO", "SKYPE", "QQ", +- "GOOGLE-TALK", "ICQ", "JABBER" +- }; +- guint i; +- +- if (NULL == protocol) +- return FALSE; +- +- for (i = 0; i < G_N_ELEMENTS (known_protocols); i++) { +- if (0 == g_ascii_strcasecmp (known_protocols[i], protocol)) +- return TRUE; +- } +- +- return FALSE; +-} +- +-static gchar * +-field_name_from_google_im_protocol (const gchar *google_protocol) +-{ +- gchar *protocol; +- if (!google_protocol) +- return NULL; +- +- protocol = g_strrstr (google_protocol, "#"); +- if (!protocol) +- return NULL; +- +- if (strcmp ("#GOOGLE_TALK", protocol) == 0) +- return g_strdup (EVC_X_GOOGLE_TALK); +- else +- return g_strdup_printf ("X-%s", protocol + 1); +-} +- +-static gchar * +-google_im_protocol_from_field_name (const gchar *field_name) +-{ +- const gchar format[] = "http://schemas.google.com/g/2005#%s"; +- +- if (!field_name || strlen (field_name) < 3) +- return NULL; +- +- if (strcmp (field_name, EVC_X_GOOGLE_TALK) == 0) +- return g_strdup_printf (format, "GOOGLE_TALK"); +- else +- return g_strdup_printf (format, field_name + 2); +-} +- +-static void +-add_primary_param (EVCardAttribute *attr, +- gboolean has_type) +-{ +- EVCardAttributeParam *param = e_vcard_attribute_param_new (GOOGLE_PRIMARY_PARAM); +- e_vcard_attribute_add_param_with_value (attr, param, "1"); +- +- if (!has_type) { +- param = e_vcard_attribute_param_new ("TYPE"); +- e_vcard_attribute_add_param_with_value (attr, param, "PREF"); +- } +-} +- +-static GList * +-get_google_primary_type_label (EVCardAttribute *attr, +- gboolean *primary, +- const gchar **label) +-{ +- GList *params; +- GList *types = NULL; +- +- *primary = FALSE; +- *label = NULL; +- params = e_vcard_attribute_get_params (attr); +- +- while (params) { +- const gchar *name; +- +- name = e_vcard_attribute_param_get_name (params->data); +- if (g_ascii_strcasecmp (name, GOOGLE_PRIMARY_PARAM) == 0) { +- GList *values; +- +- values = e_vcard_attribute_param_get_values (params->data); +- if (values && values->data && +- (((const gchar *) values->data)[0] == '1' || +- 0 == g_ascii_strcasecmp (values->data, "yes"))) { +- *primary = TRUE; +- } +- } +- +- if (g_ascii_strcasecmp (name, GOOGLE_LABEL_PARAM) == 0) { +- GList *values; +- +- values = e_vcard_attribute_param_get_values (params->data); +- *label = values ? values->data : NULL; +- } +- +- if (g_ascii_strcasecmp (name, "TYPE") == 0) +- types = e_vcard_attribute_param_get_values (params->data); +- params = params->next; +- } +- +- return types; +-} +- +-static void +-add_attribute_from_gdata_gd_email_address (EVCard *vcard, +- GDataGDEmailAddress *email) +-{ +- EVCardAttribute *attr; +- gboolean has_type; +- +- if (!email || !gdata_gd_email_address_get_address (email)) +- return; +- +- attr = e_vcard_attribute_new (NULL, EVC_EMAIL); +- has_type = add_type_param_from_google_rel (attr, gdata_gd_email_address_get_relation_type (email)); +- if (gdata_gd_email_address_is_primary (email)) +- add_primary_param (attr, has_type); +- add_label_param (attr, gdata_gd_email_address_get_label (email)); +- +- e_vcard_attribute_add_value (attr, gdata_gd_email_address_get_address (email)); +- +- if (attr) +- e_vcard_add_attribute (vcard, attr); +-} +- +-static void +-add_attribute_from_gdata_gd_im_address (EVCard *vcard, +- GDataGDIMAddress *im) +-{ +- EVCardAttribute *attr; +- gboolean has_type; +- gchar *field_name; +- +- if (!im || !gdata_gd_im_address_get_address (im)) +- return; +- +- field_name = field_name_from_google_im_protocol (gdata_gd_im_address_get_protocol (im)); +- if (!field_name) +- return; +- +- attr = e_vcard_attribute_new (NULL, field_name); +- has_type = add_type_param_from_google_rel_im (attr, gdata_gd_im_address_get_relation_type (im)); +- if (gdata_gd_im_address_is_primary (im)) +- add_primary_param (attr, has_type); +- add_label_param (attr, gdata_gd_im_address_get_label (im)); +- +- e_vcard_attribute_add_value (attr, gdata_gd_im_address_get_address (im)); +- +- if (attr) +- e_vcard_add_attribute (vcard, attr); +-} +- +-static void +-add_attribute_from_gdata_gd_phone_number (EVCard *vcard, +- GDataGDPhoneNumber *number) +-{ +- EVCardAttribute *attr; +- gboolean has_type; +- +- if (!number || !gdata_gd_phone_number_get_number (number)) +- return; +- +- attr = e_vcard_attribute_new (NULL, EVC_TEL); +- has_type = add_type_param_from_google_rel_phone (attr, gdata_gd_phone_number_get_relation_type (number)); +- if (gdata_gd_phone_number_is_primary (number)) +- add_primary_param (attr, has_type); +- add_label_param (attr, gdata_gd_phone_number_get_label (number)); +- +- e_vcard_attribute_add_value (attr, gdata_gd_phone_number_get_number (number)); +- +- if (attr) +- e_vcard_add_attribute (vcard, attr); +-} +- +-static void +-add_attribute_from_gdata_gd_postal_address (EVCard *vcard, +- GDataGDPostalAddress *address) +-{ +- EVCardAttribute *attr; +- gboolean has_type; +- +- if (!address || !gdata_gd_postal_address_get_address (address)) +- return; +- +- /* Add the LABEL */ +- attr = e_vcard_attribute_new (NULL, EVC_LABEL); +- has_type = add_type_param_from_google_rel (attr, gdata_gd_postal_address_get_relation_type (address)); +- if (gdata_gd_postal_address_is_primary (address)) +- add_primary_param (attr, has_type); +- add_label_param (attr, gdata_gd_postal_address_get_label (address)); +- +- e_vcard_attribute_add_value (attr, gdata_gd_postal_address_get_address (address)); +- +- if (attr) +- e_vcard_add_attribute (vcard, attr); +- +- /* Add the ADR */ +- attr = e_vcard_attribute_new (NULL, EVC_ADR); +- has_type = add_type_param_from_google_rel (attr, gdata_gd_postal_address_get_relation_type (address)); +- if (gdata_gd_postal_address_is_primary (address)) +- add_primary_param (attr, has_type); +- add_label_param (attr, gdata_gd_postal_address_get_label (address)); +- +- e_vcard_attribute_add_value (attr, gdata_gd_postal_address_get_po_box (address)); +- e_vcard_attribute_add_value (attr, gdata_gd_postal_address_get_house_name (address)); +- e_vcard_attribute_add_value (attr, gdata_gd_postal_address_get_street (address)); +- e_vcard_attribute_add_value (attr, gdata_gd_postal_address_get_city (address)); +- e_vcard_attribute_add_value (attr, gdata_gd_postal_address_get_region (address)); +- e_vcard_attribute_add_value (attr, gdata_gd_postal_address_get_postcode (address)); +- e_vcard_attribute_add_value (attr, gdata_gd_postal_address_get_country (address)); +- +- /* The following bits of data provided by the Google Contacts API can't be fitted into the vCard format: +- * gdata_gd_postal_address_get_mail_class +- * gdata_gd_postal_address_get_usage +- * gdata_gd_postal_address_get_agent +- * gdata_gd_postal_address_get_neighborhood +- * gdata_gd_postal_address_get_subregion +- * gdata_gd_postal_address_get_country_code */ +- +- if (attr) +- e_vcard_add_attribute (vcard, attr); +-} +- +-static void +-add_attribute_from_gdata_gd_organization (EVCard *vcard, +- GDataGDOrganization *org) +-{ +- EVCardAttribute *attr; +- gboolean has_type; +- +- if (!org) +- return; +- +- /* Add the LABEL */ +- attr = e_vcard_attribute_new (NULL, EVC_ORG); +- has_type = add_type_param_from_google_rel (attr, gdata_gd_organization_get_relation_type (org)); +- if (gdata_gd_organization_is_primary (org)) +- add_primary_param (attr, has_type); +- add_label_param (attr, gdata_gd_organization_get_label (org)); +- +- e_vcard_attribute_add_value (attr, gdata_gd_organization_get_name (org)); +- e_vcard_attribute_add_value (attr, gdata_gd_organization_get_department (org)); +- +- /* The following bits of data provided by the Google Contacts API can't be fitted into the vCard format: +- * gdata_gd_organization_get_title (handled by TITLE) +- * gdata_gd_organization_get_job_description (handled by ROLE) +- * gdata_gd_organization_get_symbol +- * gdata_gd_organization_get_location */ +- +- if (attr) +- e_vcard_add_attribute (vcard, attr); +-} +- +-static void +-add_attribute_from_gc_contact_website (EVCard *vcard, +- GDataGContactWebsite *website) +-{ +- EVCardAttribute *attr; +- gboolean has_type; +- +- if (!website || !gdata_gcontact_website_get_uri (website)) +- return; +- +- attr = e_vcard_attribute_new (NULL, GDATA_URIS_ATTR); +- has_type = add_type_param_from_google_rel_uris (attr, gdata_gcontact_website_get_relation_type (website)); +- if (gdata_gcontact_website_is_primary (website)) +- add_primary_param (attr, has_type); +- add_label_param (attr, gdata_gcontact_website_get_label (website)); +- +- e_vcard_attribute_add_value (attr, gdata_gcontact_website_get_uri (website)); +- +- e_vcard_add_attribute (vcard, attr); +-} +-static GDataGDEmailAddress * +-gdata_gd_email_address_from_attribute (EVCardAttribute *attr, +- gboolean *have_primary) +-{ +- GDataGDEmailAddress *email = NULL; +- GList *values; +- +- values = e_vcard_attribute_get_values (attr); +- if (values) { +- GList *types; +- gchar *rel = NULL; +- const gchar *label; +- gboolean primary; +- +- types = get_google_primary_type_label (attr, &primary, &label); +- if (!*have_primary) +- *have_primary = primary; +- else +- primary = FALSE; +- +- if (label == NULL) /* rel and label are mutually exclusive (bgo#675712) */ +- rel = google_rel_from_types (types); +- email = gdata_gd_email_address_new (values->data, rel, label, primary); +- g_free (rel); +- +- __debug__ ( +- "New %semail entry %s (%s/%s)", +- gdata_gd_email_address_is_primary (email) ? "primary " : "", +- gdata_gd_email_address_get_address (email), +- gdata_gd_email_address_get_relation_type (email), +- gdata_gd_email_address_get_label (email)); +- } +- +- return email; +-} +- +-static GDataGDIMAddress * +-gdata_gd_im_address_from_attribute (EVCardAttribute *attr, +- gboolean *have_primary) +-{ +- GDataGDIMAddress *im = NULL; +- GList *values; +- const gchar *name; +- +- name = e_vcard_attribute_get_name (attr); +- +- values = e_vcard_attribute_get_values (attr); +- if (values) { +- GList *types; +- gchar *protocol, *rel; +- const gchar *label; +- gboolean primary; +- +- types = get_google_primary_type_label (attr, &primary, &label); +- if (!*have_primary) +- *have_primary = primary; +- else +- primary = FALSE; +- +- rel = google_rel_from_types (types); +- protocol = google_im_protocol_from_field_name (name); +- im = gdata_gd_im_address_new (values->data, protocol, rel, label, primary); +- g_free (rel); +- g_free (protocol); +- +- __debug__ ( +- "New %s%s entry %s (%s/%s)", +- gdata_gd_im_address_is_primary (im) ? "primary " : "", +- gdata_gd_im_address_get_protocol (im), +- gdata_gd_im_address_get_address (im), +- gdata_gd_im_address_get_relation_type (im), +- gdata_gd_im_address_get_label (im)); +- } +- +- return im; +-} +- +-static GDataGDPhoneNumber * +-gdata_gd_phone_number_from_attribute (EVCardAttribute *attr, +- gboolean *have_primary) +-{ +- GDataGDPhoneNumber *number = NULL; +- GList *values; +- +- values = e_vcard_attribute_get_values (attr); +- if (values) { +- GList *types; +- gboolean primary; +- gchar *rel = NULL; +- const gchar *label; +- +- types = get_google_primary_type_label (attr, &primary, &label); +- if (!*have_primary) +- *have_primary = primary; +- else +- primary = FALSE; +- +- if (label == NULL) /* rel and label are mutually exclusive (bgo#675712) */ +- rel = google_rel_from_types_phone (types); +- number = gdata_gd_phone_number_new (values->data, rel, label, NULL, primary); +- g_free (rel); +- +- __debug__ ( +- "New %sphone-number entry %s (%s/%s)", +- gdata_gd_phone_number_is_primary (number) ? "primary " : "", +- gdata_gd_phone_number_get_number (number), +- gdata_gd_phone_number_get_relation_type (number), +- gdata_gd_phone_number_get_label (number)); +- } +- +- return number; +-} +- +-static GDataGDPostalAddress * +-gdata_gd_postal_address_from_attribute (EVCardAttribute *attr, +- gboolean *have_primary) +-{ +- GDataGDPostalAddress *address = NULL; +- GList *values; +- +- values = e_vcard_attribute_get_values (attr); +- if (values && values->data) { +- GList *types, *value; +- gchar *rel = NULL; +- const gchar *label; +- gboolean primary; +- +- types = get_google_primary_type_label (attr, &primary, &label); +- if (!*have_primary) +- *have_primary = primary; +- else +- primary = FALSE; +- +- if (label == NULL) /* rel and label are mutually exclusive (bgo#675712) */ +- rel = google_rel_from_types (types); +- address = gdata_gd_postal_address_new (rel, label, primary); +- g_free (rel); +- +- /* Set the components of the address from the vCard's attribute values */ +- value = values; +- gdata_gd_postal_address_set_po_box (address, (*((gchar *) value->data) != '\0') ? value->data : NULL); +- value = value->next; +- if (!value) +- return address; +- label = (*((gchar *) value->data) != '\0') ? value->data : NULL; +- value = value->next; +- if (!value) { +- gdata_gd_postal_address_set_street (address, label); +- return address; +- } +- if (label) { +- const gchar *value_str = (*((gchar *) value->data) != '\0') ? value->data : NULL; +- +- if (value_str) { +- gchar *tmp; +- +- tmp = g_strconcat (value_str, "\n", label, NULL); +- gdata_gd_postal_address_set_street (address, tmp); +- g_free (tmp); +- } else { +- gdata_gd_postal_address_set_street (address, label); +- } +- } else { +- gdata_gd_postal_address_set_street (address, (*((gchar *) value->data) != '\0') ? value->data : NULL); +- } +- value = value->next; +- if (!value) +- return address; +- gdata_gd_postal_address_set_city (address, (*((gchar *) value->data) != '\0') ? value->data : NULL); +- value = value->next; +- if (!value) +- return address; +- gdata_gd_postal_address_set_region (address, (*((gchar *) value->data) != '\0') ? value->data : NULL); +- value = value->next; +- if (!value) +- return address; +- gdata_gd_postal_address_set_postcode (address, (*((gchar *) value->data) != '\0') ? value->data : NULL); +- value = value->next; +- if (!value) +- return address; +- gdata_gd_postal_address_set_country (address, (*((gchar *) value->data) != '\0') ? value->data : NULL, NULL); +- +- /* Throw it away if nothing was set */ +- if (gdata_gd_postal_address_get_po_box (address) == NULL && gdata_gd_postal_address_get_house_name (address) == NULL && +- gdata_gd_postal_address_get_street (address) == NULL && gdata_gd_postal_address_get_city (address) == NULL && +- gdata_gd_postal_address_get_region (address) == NULL && gdata_gd_postal_address_get_postcode (address) == NULL && +- gdata_gd_postal_address_get_country (address) == NULL) { +- g_object_unref (address); +- return NULL; +- } +- +- __debug__ ( +- "New %spostal address entry %s (%s/%s)", +- gdata_gd_postal_address_is_primary (address) ? "primary " : "", +- gdata_gd_postal_address_get_address (address), +- gdata_gd_postal_address_get_relation_type (address), +- gdata_gd_postal_address_get_label (address)); +- } +- +- return address; +-} +- +-static GDataGDOrganization * +-gdata_gd_organization_from_attribute (EVCardAttribute *attr, +- gboolean *have_primary) +-{ +- GDataGDOrganization *org = NULL; +- GList *values; +- +- values = e_vcard_attribute_get_values (attr); +- if (values) { +- GList *types; +- gboolean primary; +- gchar *rel = NULL; +- const gchar *label; +- +- types = get_google_primary_type_label (attr, &primary, &label); +- if (!*have_primary) +- *have_primary = primary; +- else +- primary = FALSE; +- +- if (label == NULL) /* rel and label are mutually exclusive (bgo#675712) */ +- rel = google_rel_from_types (types); +- org = gdata_gd_organization_new (values->data, NULL, rel, label, primary); +- if (values->next != NULL && values->next->data != NULL && *((gchar *) values->next->data) != '\0') +- gdata_gd_organization_set_department (org, values->next->data); +- g_free (rel); +- +- /* TITLE and ROLE are dealt with separately in gdata_entry_update_from_e_contact() */ +- +- __debug__ ( +- "New %sorganization entry %s (%s/%s)", +- gdata_gd_organization_is_primary (org) ? "primary " : "", +- gdata_gd_organization_get_name (org), +- gdata_gd_organization_get_relation_type (org), +- gdata_gd_organization_get_label (org)); +- } +- +- return org; +-} +- +-static GDataGContactWebsite * +-gdata_gc_contact_website_from_attribute (EVCardAttribute *attr, +- gboolean *have_primary) +-{ +- GDataGContactWebsite *website = NULL; +- GList *values; +- +- values = e_vcard_attribute_get_values (attr); +- if (values) { +- GList *types; +- gchar *rel; +- const gchar *label; +- gboolean primary; +- +- types = get_google_primary_type_label (attr, &primary, &label); +- if (!*have_primary) +- *have_primary = primary; +- else +- primary = FALSE; +- +- rel = google_rel_from_types_uris (types); +- website = gdata_gcontact_website_new (values->data, rel, label, primary); +- g_free (rel); +- +- __debug__ ( +- "New %suri entry %s (%s/%s)", +- gdata_gcontact_website_is_primary (website) ? "primary " : "", +- gdata_gcontact_website_get_uri (website), +- gdata_gcontact_website_get_relation_type (website), +- gdata_gcontact_website_get_label (website)); +- } +- +- return website; +-} +- +-const gchar * +-e_contact_map_google_with_evo_group (const gchar *group_name, +- gboolean google_to_evo) +-{ +- struct _GroupsMap { +- const gchar *google_id; +- const gchar *evo_name; +- } groups_map[] = { +- /* System Group: My Contacts */ +- { GDATA_CONTACTS_GROUP_CONTACTS, N_("Personal") }, +- /* System Group: Friends */ +- { GDATA_CONTACTS_GROUP_FRIENDS, N_("Friends") }, +- /* System Group: Family */ +- { GDATA_CONTACTS_GROUP_FAMILY, N_("Family") }, +- /* System Group: Coworkers */ +- { GDATA_CONTACTS_GROUP_COWORKERS, N_("Coworkers") } +- }; +- guint ii; +- +- if (!group_name) +- return NULL; +- +- for (ii = 0; ii < G_N_ELEMENTS (groups_map); ii++) { +- if (google_to_evo) { +- if (g_str_equal (group_name, groups_map[ii].google_id)) +- return _(groups_map[ii].evo_name); +- } else { +- if (g_str_equal (group_name, _(groups_map[ii].evo_name))) +- return groups_map[ii].google_id; +- } +- } +- +- return NULL; +-} +- +-gchar * +-e_contact_sanitise_google_group_id (const gchar *group_id) +-{ +- gchar *id, *base; +- +- id = g_strdup (group_id); +- +- /* Fix the ID to refer to the full projection, rather than the base projection, because Google think that returning different IDs for the +- * same object is somehow a good idea. */ +- if (id != NULL) { +- base = strstr (id, "/base/"); +- if (base != NULL) +- memcpy (base, "/full/", 6); +- } +- +- return id; +-} +- +-gchar * +-e_contact_sanitise_google_group_name (GDataEntry *group) +-{ +- const gchar *system_group_id = gdata_contacts_group_get_system_group_id (GDATA_CONTACTS_GROUP (group)); +- const gchar *evo_name; +- +- evo_name = e_contact_map_google_with_evo_group (system_group_id, TRUE); +- +- if (system_group_id == NULL) { +- return g_strdup (gdata_entry_get_title (group)); /* Non-system group */ +- } else if (evo_name) { +- return g_strdup (evo_name); +- } else { +- g_warning ("Unknown system group '%s' for group with ID '%s'.", system_group_id, gdata_entry_get_id (group)); +- return g_strdup (gdata_entry_get_title (group)); +- } +-} +- +-/* Makes a non-URL UID from a URL ID; the returned string is owned by @entry */ +-const gchar * +-e_book_google_utils_uid_from_entry (GDataEntry *entry) +-{ +- const gchar *id, *slash; +- +- id = gdata_entry_get_id (entry); +- if (!id) +- return NULL; +- +- slash = strrchr (id, '/'); +- +- if (slash && slash[1]) +- return slash + 1; +- +- return id; +-} +- +-gchar * +-e_book_google_utils_time_to_revision (gint64 unix_time) +-{ +- struct tm stm; +- time_t tt = (time_t) unix_time; +- gchar time_string[100] = { 0 }; +- +- gmtime_r (&tt, &stm); +- strftime (time_string, 100, "%Y-%m-%dT%H:%M:%SZ", &stm); +- +- return g_strdup (time_string); +-} +diff --git a/src/addressbook/backends/google/e-book-google-utils.h b/src/addressbook/backends/google/e-book-google-utils.h +deleted file mode 100644 +index 302731ba5..000000000 +--- a/src/addressbook/backends/google/e-book-google-utils.h ++++ /dev/null +@@ -1,69 +0,0 @@ +-/* e-book-google-utils.h - Google contact conversion utilities. +- * +- * Copyright (C) 2012 Philip Withnall +- * +- * This library is free software: you can redistribute it and/or modify it +- * under the terms of the GNU Lesser General Public License as published by +- * the Free Software Foundation. +- * +- * This library is distributed in the hope that it will be useful, but +- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License +- * for more details. +- * +- * You should have received a copy of the GNU Lesser General Public License +- * along with this library. If not, see . +- * +- * Authors: Philip Withnall +- */ +- +-#ifndef E_BOOK_GOOGLE_UTILS_H +-#define E_BOOK_GOOGLE_UTILS_H +- +-#include +- +-#include "e-book-backend-google.h" +- +-#define E_GOOGLE_X_ETAG "X-EVOLUTION-GOOGLE-ETAG" +-#define E_GOOGLE_X_PHOTO_ETAG "X-EVOLUTION-GOOGLE-PHOTO-ETAG" +- +-G_BEGIN_DECLS +- +-typedef gchar *(*EContactGoogleCreateGroupFunc) (EBookBackendGoogle *bbgoogle, +- const gchar *category_name, +- GCancellable *cancellable, +- GError **error); +- +-GDataEntry * gdata_entry_new_from_e_contact (EContact *contact, +- GHashTable *groups_by_name, +- GHashTable *system_groups_by_id, +- EContactGoogleCreateGroupFunc create_group, +- EBookBackendGoogle *bbgoogle, +- GCancellable *cancellable) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +-gboolean gdata_entry_update_from_e_contact +- (GDataEntry *entry, +- EContact *contact, +- gboolean ensure_personal_group, +- GHashTable *groups_by_name, +- GHashTable *system_groups_by_id, +- EContactGoogleCreateGroupFunc create_group, +- EBookBackendGoogle *bbgoogle, +- GCancellable *cancellable); +- +-EContact *e_contact_new_from_gdata_entry (GDataEntry *entry, GHashTable *groups_by_id, +- GHashTable *system_groups_by_entry_id) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +-void e_contact_add_gdata_entry_xml (EContact *contact, GDataEntry *entry); +-void e_contact_remove_gdata_entry_xml (EContact *contact); +-const gchar *e_contact_get_gdata_entry_xml (EContact *contact, const gchar **edit_uri); +- +-const gchar *e_contact_map_google_with_evo_group (const gchar *group_name, gboolean google_to_evo); +- +-gchar *e_contact_sanitise_google_group_id (const gchar *group_id) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +-gchar *e_contact_sanitise_google_group_name (GDataEntry *group) G_GNUC_MALLOC G_GNUC_WARN_UNUSED_RESULT; +- +-const gchar * e_book_google_utils_uid_from_entry (GDataEntry *entry); +-gchar * e_book_google_utils_time_to_revision (gint64 unix_time); +- +-G_END_DECLS +- +-#endif /* E_BOOK_GOOGLE_UTILS_H */ +diff --git a/src/addressbook/backends/google/tests/CMakeLists.txt b/src/addressbook/backends/google/tests/CMakeLists.txt +deleted file mode 100644 +index dd8280587..000000000 +--- a/src/addressbook/backends/google/tests/CMakeLists.txt ++++ /dev/null +@@ -1,38 +0,0 @@ +-set(DEPENDENCIES +- ebook-google-utils +-) +- +-add_executable(ebookbackendgoogle-phonenumber +- phone-numbers.c +-) +- +-add_dependencies(ebookbackendgoogle-phonenumber +- ${DEPENDENCIES} +-) +- +-target_compile_definitions(ebookbackendgoogle-phonenumber PRIVATE +- -DG_LOG_DOMAIN=\"ebookbackendgoogle-phonenumber\" +-) +- +-target_compile_options(ebookbackendgoogle-phonenumber PUBLIC +- ${ADDRESSBOOK_CFLAGS} +- ${LIBGDATA_CFLAGS} +-) +- +-target_include_directories(ebookbackendgoogle-phonenumber PUBLIC +- ${CMAKE_BINARY_DIR} +- ${CMAKE_BINARY_DIR}/src +- ${CMAKE_SOURCE_DIR}/src +- ${CMAKE_SOURCE_DIR}/src/addressbook/backends/google +- ${CMAKE_CURRENT_SOURCE_DIR} +- ${ADDRESSBOOK_INCLUDE_DIRS} +- ${LIBGDATA_INCLUDE_DIRS} +-) +- +-target_link_libraries(ebookbackendgoogle-phonenumber +- ${DEPENDENCIES} +- ${ADDRESSBOOK_LDFLAGS} +- ${LIBGDATA_LDFLAGS} +-) +- +-add_check_test(ebookbackendgoogle-phonenumber) +diff --git a/src/addressbook/backends/google/tests/phone-numbers.c b/src/addressbook/backends/google/tests/phone-numbers.c +deleted file mode 100644 +index f2ca12ffd..000000000 +--- a/src/addressbook/backends/google/tests/phone-numbers.c ++++ /dev/null +@@ -1,125 +0,0 @@ +-/* phone-numbers.c - Phone number tests +- * +- * Copyright (C) 2012 Philip Withnall +- * +- * This program is free software: you can redistribute it and/or modify it +- * under the terms of the GNU Lesser General Public License as published by +- * the Free Software Foundation. +- * +- * This program is distributed in the hope that it will be useful, but +- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License +- * for more details. +- * +- * You should have received a copy of the GNU Lesser General Public License +- * along with this program. If not, see . +- * +- * Authors: Philip Withnall +- */ +- +-#include +-#include +- +-#include "e-book-google-utils.h" +- +-static GHashTable/**/ * +-build_groups_by_name (void) +-{ +- return g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); +-} +- +-static GHashTable/**/ * +-build_system_groups_by_id (void) +-{ +- GHashTable *table = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); +- g_hash_table_insert (table, g_strdup (GDATA_CONTACTS_GROUP_CONTACTS), g_strdup ("contacts-group-id")); +- return table; +-} +- +-static gchar * +-create_group_null (EBookBackendGoogle *bbgoogle, +- const gchar *category_name, +- GCancellable *cancellable, +- GError **error) +-{ +- /* Must never be reached. */ +- g_assert_not_reached (); +-} +- +-#define ENTRY_FROM_VCARD(entry, VCARD_PROPS) G_STMT_START { \ +- EContact *contact; \ +- GHashTable *groups_by_name, *system_groups_by_id; \ +-\ +- groups_by_name = build_groups_by_name (); \ +- system_groups_by_id = build_system_groups_by_id (); \ +-\ +- contact = e_contact_new_from_vcard ( \ +- "BEGIN:VCARD" "\n" \ +- "VERSION:3.0" "\n" \ +- "UID:foobar-baz" "\n" \ +- "FN:Foobar Baz" "\n" \ +- VCARD_PROPS \ +- "END:VCARD" \ +- ); \ +-\ +- entry = gdata_entry_new_from_e_contact (contact, groups_by_name, system_groups_by_id, create_group_null, NULL, NULL); \ +- g_assert (entry != NULL); \ +-\ +- g_hash_table_unref (system_groups_by_id); \ +- g_hash_table_unref (groups_by_name); \ +-\ +- g_object_unref (contact); \ +-} G_STMT_END +- +-/* Include both an X-GOOGLE_LABEL and a TYPE attribute in the vCard and test that exactly one of them is copied to the entry. */ +-static void +-test_label_and_type (void) +-{ +- GDataEntry *entry; +- GDataGDPhoneNumber *phone_number; +- +- g_test_bug ("675712"); +- +- ENTRY_FROM_VCARD (entry, "TEL;X-GOOGLE-LABEL=VOICE;TYPE=PREF;X-EVOLUTION-UI-SLOT=1:+0123456789" "\n"); +- +- /* Check that the entry has exactly one phone number, and that it contains exactly one of the rel and label properties. */ +- phone_number = gdata_contacts_contact_get_primary_phone_number (GDATA_CONTACTS_CONTACT (entry)); +- +- g_assert_cmpstr (gdata_gd_phone_number_get_relation_type (phone_number), ==, NULL); +- g_assert_cmpstr (gdata_gd_phone_number_get_label (phone_number), ==, "VOICE"); +- +- g_object_unref (entry); +-} +- +-/* Include neither an X-GOOGLE_LABEL nor a TYPE attribute in the vCard and test that a suitable default appears in the entry. */ +-static void +-test_label_nor_type (void) +-{ +- GDataEntry *entry; +- GDataGDPhoneNumber *phone_number; +- +- g_test_bug ("675712"); +- +- ENTRY_FROM_VCARD (entry, "TEL;X-EVOLUTION-UI-SLOT=1:+0123456789" "\n"); +- +- /* Check that the entry has exactly one phone number, and that it contains exactly one of the rel and label properties. */ +- phone_number = gdata_contacts_contact_get_primary_phone_number (GDATA_CONTACTS_CONTACT (entry)); +- +- g_assert_cmpstr (gdata_gd_phone_number_get_relation_type (phone_number), ==, GDATA_GD_PHONE_NUMBER_OTHER); +- g_assert_cmpstr (gdata_gd_phone_number_get_label (phone_number), ==, NULL); +- +- g_object_unref (entry); +-} +- +-gint +-main (gint argc, +- gchar **argv) +-{ +- g_test_init (&argc, &argv, NULL); +- g_test_bug_base ("https://bugzilla.gnome.org/"); +- +- g_test_add_func ("/phone-numbers/label-and-type", test_label_and_type); +- g_test_add_func ("/phone-numbers/label-nor-type", test_label_nor_type); +- +- return g_test_run (); +-} +diff --git a/src/modules/google-backend/module-google-backend.c b/src/modules/google-backend/module-google-backend.c +index 2b1fcf473..01fc05b9b 100644 +--- a/src/modules/google-backend/module-google-backend.c ++++ b/src/modules/google-backend/module-google-backend.c +@@ -50,11 +50,6 @@ + #define GOOGLE_SMTP_PORT 465 + #define GOOGLE_SMTP_SECURITY_METHOD METHOD (SSL_ON_ALTERNATE_PORT) + +-/* Contacts Configuration Details */ +-#define GOOGLE_CONTACTS_BACKEND_NAME "google" +-#define GOOGLE_CONTACTS_HOST "www.google.com" +-#define GOOGLE_CONTACTS_RESOURCE_ID "Contacts" +- + /* Tasks Configuration Details */ + #define GOOGLE_TASKS_BACKEND_NAME "gtasks" + +@@ -489,6 +484,7 @@ google_backend_authenticate_sync (EBackend *backend, + GList *sources; + ENamedParameters *credentials_copy = NULL; + const gchar *calendar_url; ++ const gchar *contacts_url = NULL; + + g_return_val_if_fail (collection != NULL, E_SOURCE_AUTHENTICATION_ERROR); + +@@ -538,8 +534,14 @@ google_backend_authenticate_sync (EBackend *backend, + } + } + +- if (e_source_collection_get_calendar_enabled (collection_extension) && calendar_url) { +- result = e_webdav_collection_backend_discover_sync (E_WEBDAV_COLLECTION_BACKEND (backend), calendar_url, NULL, ++ if (!e_source_collection_get_calendar_enabled (collection_extension)) ++ calendar_url = NULL; ++ ++ if (e_source_collection_get_contacts_enabled (collection_extension)) ++ contacts_url = "https://www.googleapis.com/.well-known/carddav"; ++ ++ if (calendar_url || contacts_url) { ++ result = e_webdav_collection_backend_discover_sync (E_WEBDAV_COLLECTION_BACKEND (backend), calendar_url, contacts_url, + credentials, out_certificate_pem, out_certificate_errors, cancellable, error); + } else { + result = E_SOURCE_AUTHENTICATION_ACCEPTED; +@@ -616,78 +618,13 @@ google_backend_authenticate_sync (EBackend *backend, + return result; + } + +-static void +-google_backend_add_contacts (ECollectionBackend *backend) +-{ +- ESource *source; +- ESource *collection_source; +- ESourceRegistryServer *server; +- ESourceExtension *extension; +- ESourceCollection *collection_extension; +- const gchar *backend_name; +- const gchar *extension_name; +- const gchar *resource_id; +- +- collection_source = e_backend_get_source (E_BACKEND (backend)); +- +- resource_id = GOOGLE_CONTACTS_RESOURCE_ID; +- source = e_collection_backend_new_child (backend, resource_id); +- e_source_set_display_name (source, _("Contacts")); +- +- /* Add the address book source to the collection. */ +- collection_extension = e_source_get_extension ( +- collection_source, E_SOURCE_EXTENSION_COLLECTION); +- +- /* Configure the address book source. */ +- +- backend_name = GOOGLE_CONTACTS_BACKEND_NAME; +- +- extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK; +- extension = e_source_get_extension (source, extension_name); +- +- e_source_backend_set_backend_name ( +- E_SOURCE_BACKEND (extension), backend_name); +- +- extension_name = E_SOURCE_EXTENSION_AUTHENTICATION; +- extension = e_source_get_extension (source, extension_name); +- +- e_source_authentication_set_host ( +- E_SOURCE_AUTHENTICATION (extension), +- GOOGLE_CONTACTS_HOST); +- +- e_binding_bind_property ( +- collection_extension, "identity", +- extension, "user", +- G_BINDING_SYNC_CREATE); +- +- server = e_collection_backend_ref_server (backend); +- e_source_registry_server_add_source (server, source); +- g_object_unref (server); +- +- g_object_unref (source); +-} +- +-static gchar * +-google_backend_get_resource_id (EWebDAVCollectionBackend *webdav_backend, +- ESource *source) +-{ +- g_return_val_if_fail (E_IS_SOURCE (source), NULL); +- +- if (e_source_has_extension (source, E_SOURCE_EXTENSION_ADDRESS_BOOK)) +- return g_strdup (GOOGLE_CONTACTS_RESOURCE_ID); +- +- /* Chain up to parent's method. */ +- return E_WEBDAV_COLLECTION_BACKEND_CLASS (e_google_backend_parent_class)->get_resource_id (webdav_backend, source); +-} +- + static gboolean + google_backend_is_custom_source (EWebDAVCollectionBackend *webdav_backend, + ESource *source) + { + g_return_val_if_fail (E_IS_SOURCE (source), FALSE); + +- if (e_source_has_extension (source, E_SOURCE_EXTENSION_ADDRESS_BOOK) || +- e_source_has_extension (source, E_SOURCE_EXTENSION_TASK_LIST)) ++ if (e_source_has_extension (source, E_SOURCE_EXTENSION_TASK_LIST)) + return TRUE; + + /* Chain up to parent's method. */ +@@ -697,12 +634,10 @@ google_backend_is_custom_source (EWebDAVCollectionBackend *webdav_backend, + static void + google_backend_populate (ECollectionBackend *backend) + { +- ESourceCollection *collection_extension; + ESourceAuthentication *authentication_extension; + ESource *source; + + source = e_backend_get_source (E_BACKEND (backend)); +- collection_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_COLLECTION); + authentication_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION); + + /* When the WebDAV extension is created, the auth method can be reset, thus ensure +@@ -716,15 +651,6 @@ google_backend_populate (ECollectionBackend *backend) + + /* Chain up to parent's method. */ + E_COLLECTION_BACKEND_CLASS (e_google_backend_parent_class)->populate (backend); +- +- if (e_source_collection_get_contacts_enabled (collection_extension)) { +- GList *list; +- +- list = e_collection_backend_list_contacts_sources (backend); +- if (list == NULL) +- google_backend_add_contacts (backend); +- g_list_free_full (list, (GDestroyNotify) g_object_unref); +- } + } + + static gchar * +@@ -733,12 +659,10 @@ google_backend_dup_resource_id (ECollectionBackend *backend, + { + if (e_source_has_extension (child_source, E_SOURCE_EXTENSION_CALENDAR) || + e_source_has_extension (child_source, E_SOURCE_EXTENSION_MEMO_LIST) || +- e_source_has_extension (child_source, E_SOURCE_EXTENSION_TASK_LIST)) ++ e_source_has_extension (child_source, E_SOURCE_EXTENSION_TASK_LIST) || ++ e_source_has_extension (child_source, E_SOURCE_EXTENSION_ADDRESS_BOOK)) + return E_COLLECTION_BACKEND_CLASS (e_google_backend_parent_class)->dup_resource_id (backend, child_source); + +- if (e_source_has_extension (child_source, E_SOURCE_EXTENSION_ADDRESS_BOOK)) +- return g_strdup (GOOGLE_CONTACTS_RESOURCE_ID); +- + return NULL; + } + +@@ -749,7 +673,6 @@ google_backend_child_added (ECollectionBackend *backend, + ESource *collection_source; + const gchar *extension_name; + gboolean is_mail = FALSE; +- gboolean has_external_auth = FALSE; + + /* Chain up to parent's child_added() method. */ + E_COLLECTION_BACKEND_CLASS (e_google_backend_parent_class)-> +@@ -785,8 +708,6 @@ google_backend_child_added (ECollectionBackend *backend, + child_source, extension_name); + auth_child_user = e_source_authentication_get_user ( + auth_child_extension); +- has_external_auth = e_source_authentication_get_is_external ( +- auth_child_extension); + + /* XXX Do not override an existing user name setting. + * The IMAP or (especially) SMTP configuration may +@@ -846,42 +767,6 @@ google_backend_child_added (ECollectionBackend *backend, + child_source, "notify::oauth2-support", + G_CALLBACK (google_backend_contacts_update_auth_method_cb), + backend); +- +- if (!has_external_auth) { +- /* Even the book is part of the collection it can be removed +- separately, if not configured through GOA or UOA. */ +- e_server_side_source_set_removable (E_SERVER_SIDE_SOURCE (child_source), TRUE); +- } +- } +-} +- +-static void +-google_backend_child_removed (ECollectionBackend *backend, +- ESource *child_source) +-{ +- ESource *collection_source; +- gboolean has_external_auth = FALSE; +- +- /* Chain up to parent's method. */ +- E_COLLECTION_BACKEND_CLASS (e_google_backend_parent_class)->child_removed (backend, child_source); +- +- collection_source = e_backend_get_source (E_BACKEND (backend)); +- +- if (e_source_has_extension (child_source, E_SOURCE_EXTENSION_AUTHENTICATION)) { +- ESourceAuthentication *auth_child_extension; +- +- auth_child_extension = e_source_get_extension (child_source, E_SOURCE_EXTENSION_AUTHENTICATION); +- has_external_auth = e_source_authentication_get_is_external (auth_child_extension); +- } +- +- if (e_source_has_extension (child_source, E_SOURCE_EXTENSION_ADDRESS_BOOK) && +- e_source_has_extension (collection_source, E_SOURCE_EXTENSION_COLLECTION) && +- !has_external_auth) { +- ESourceCollection *collection_extension; +- +- collection_extension = e_source_get_extension (collection_source, E_SOURCE_EXTENSION_COLLECTION); +- +- e_source_collection_set_contacts_enabled (collection_extension, FALSE); + } + } + +@@ -914,10 +799,8 @@ e_google_backend_class_init (EGoogleBackendClass *class) + collection_backend_class->populate = google_backend_populate; + collection_backend_class->dup_resource_id = google_backend_dup_resource_id; + collection_backend_class->child_added = google_backend_child_added; +- collection_backend_class->child_removed = google_backend_child_removed; + + webdav_collection_backend_class = E_WEBDAV_COLLECTION_BACKEND_CLASS (class); +- webdav_collection_backend_class->get_resource_id = google_backend_get_resource_id; + webdav_collection_backend_class->is_custom_source = google_backend_is_custom_source; + } + +diff --git a/src/services/evolution-source-registry/evolution-source-registry-migrate-tweaks.c b/src/services/evolution-source-registry/evolution-source-registry-migrate-tweaks.c +index 82d113d98..6c7b221f5 100644 +--- a/src/services/evolution-source-registry/evolution-source-registry-migrate-tweaks.c ++++ b/src/services/evolution-source-registry/evolution-source-registry-migrate-tweaks.c +@@ -208,6 +208,56 @@ evolution_source_registry_migrate_webdav_book_to_carddav (ESourceRegistryServer + return modified; + } + ++ ++static gboolean ++evolution_source_registry_migrate_google_book_to_carddav (ESourceRegistryServer *server, ++ GKeyFile *key_file, ++ const gchar *uid) ++{ ++ gboolean modified = FALSE; ++ ++ g_return_val_if_fail (key_file != NULL, FALSE); ++ ++ if (g_key_file_has_group (key_file, E_SOURCE_EXTENSION_ADDRESS_BOOK) && ++ g_key_file_has_key (key_file, E_SOURCE_EXTENSION_ADDRESS_BOOK, "BackendName", NULL)) { ++ gchar *backend_name; ++ ++ backend_name = g_key_file_get_string (key_file, E_SOURCE_EXTENSION_ADDRESS_BOOK, "BackendName", NULL); ++ if (g_strcmp0 (backend_name, "google") == 0) { ++ g_key_file_set_string (key_file, E_SOURCE_EXTENSION_ADDRESS_BOOK, "BackendName", "carddav"); ++ modified = TRUE; ++ } ++ ++ g_free (backend_name); ++ } ++ ++ if (modified && g_key_file_has_group (key_file, E_SOURCE_EXTENSION_AUTHENTICATION)) { ++ gchar *user; ++ ++ user = g_key_file_get_string (key_file, E_SOURCE_EXTENSION_AUTHENTICATION, "User", NULL); ++ ++ if (user && *user) { ++ gchar *path; ++ ++ /* Unfortunately no mapping with the default book, thus either drop it or hard code the URL */ ++ path = g_strdup_printf ("/carddav/v1/principals/%s/lists/default/", user); ++ ++ g_key_file_set_string (key_file, E_SOURCE_EXTENSION_WEBDAV_BACKEND, "ResourcePath", path); ++ g_key_file_set_string (key_file, E_SOURCE_EXTENSION_AUTHENTICATION, "Host", "www.googleapis.com"); ++ g_key_file_set_string (key_file, E_SOURCE_EXTENSION_AUTHENTICATION, "Method", "Google"); ++ g_key_file_set_integer (key_file, E_SOURCE_EXTENSION_AUTHENTICATION, "Port", 443); ++ g_key_file_set_string (key_file, E_SOURCE_EXTENSION_AUTHENTICATION, "User", user); ++ g_key_file_set_string (key_file, E_SOURCE_EXTENSION_SECURITY, "Method", "tls"); ++ ++ g_free (path); ++ } ++ ++ g_free (user); ++ } ++ ++ return modified; ++} ++ + gboolean + evolution_source_registry_migrate_tweak_key_file (ESourceRegistryServer *server, + GKeyFile *key_file, +@@ -218,6 +268,7 @@ evolution_source_registry_migrate_tweak_key_file (ESourceRegistryServer *server, + modified = evolution_source_registry_migrate_imap_to_imapx (server, key_file, uid); + modified = evolution_source_registry_migrate_owncloud_to_webdav (server, key_file, uid) || modified; + modified = evolution_source_registry_migrate_webdav_book_to_carddav (server, key_file, uid) || modified; ++ modified = evolution_source_registry_migrate_google_book_to_carddav (server, key_file, uid) || modified; + + return modified; + } +-- +GitLab + diff --git a/evolution-data-server-3.28.5-google-oauth2.patch b/evolution-data-server-3.40.4-google-oauth2.patch similarity index 76% rename from evolution-data-server-3.28.5-google-oauth2.patch rename to evolution-data-server-3.40.4-google-oauth2.patch index 71ab3a7936031b23c083db9d4783d5bf7c930c4f..d812318fa27e74a2f8dafd22b2473e65f7b8a469 100644 --- a/evolution-data-server-3.28.5-google-oauth2.patch +++ b/evolution-data-server-3.40.4-google-oauth2.patch @@ -1,6 +1,18 @@ -diff -up evolution-data-server-3.28.5/src/libedataserver/e-oauth2-service-google.c.google-oauth2 evolution-data-server-3.28.5/src/libedataserver/e-oauth2-service-google.c ---- evolution-data-server-3.28.5/src/libedataserver/e-oauth2-service-google.c.google-oauth2 2018-07-30 15:17:06.000000000 +0200 -+++ evolution-data-server-3.28.5/src/libedataserver/e-oauth2-service-google.c 2022-05-04 18:57:08.059385307 +0200 +From 08ec37272bb945625daed7e6ae7ed2bd663cdabd Mon Sep 17 00:00:00 2001 +From: Milan Crha +Date: Wed, 4 May 2022 15:30:49 +0200 +Subject: [PATCH] I#388 - Google OAuth out-of-band (oob) flow will be + deprecated + +Closes https://gitlab.gnome.org/GNOME/evolution-data-server/-/issues/388 +--- + src/libedataserver/e-oauth2-service-google.c | 62 +++++++++++++++++--- + 1 file changed, 55 insertions(+), 7 deletions(-) + +diff --git a/src/libedataserver/e-oauth2-service-google.c b/src/libedataserver/e-oauth2-service-google.c +index 4d262d32f..93af1cb0b 100644 +--- a/src/libedataserver/e-oauth2-service-google.c ++++ b/src/libedataserver/e-oauth2-service-google.c @@ -24,6 +24,7 @@ #include "e-oauth2-service-google.h" @@ -9,7 +21,7 @@ diff -up evolution-data-server-3.28.5/src/libedataserver/e-oauth2-service-google /* Forward Declarations */ static void e_oauth2_service_google_oauth2_service_init (EOAuth2ServiceInterface *iface); -@@ -74,14 +75,60 @@ static const gchar * +@@ -122,14 +123,60 @@ static const gchar * eos_google_get_authentication_uri (EOAuth2Service *service, ESource *source) { @@ -72,7 +84,7 @@ diff -up evolution-data-server-3.28.5/src/libedataserver/e-oauth2-service-google } static void -@@ -143,13 +190,13 @@ eos_google_extract_authorization_code (E +@@ -191,13 +238,13 @@ eos_google_extract_authorization_code (EOAuth2Service *service, params = soup_form_decode (query); if (params) { @@ -91,7 +103,7 @@ diff -up evolution-data-server-3.28.5/src/libedataserver/e-oauth2-service-google known = TRUE; } -@@ -177,6 +224,7 @@ e_oauth2_service_google_oauth2_service_i +@@ -225,6 +272,7 @@ e_oauth2_service_google_oauth2_service_init (EOAuth2ServiceInterface *iface) iface->get_client_secret = eos_google_get_client_secret; iface->get_authentication_uri = eos_google_get_authentication_uri; iface->get_refresh_uri = eos_google_get_refresh_uri; @@ -99,3 +111,6 @@ diff -up evolution-data-server-3.28.5/src/libedataserver/e-oauth2-service-google iface->prepare_authentication_uri_query = eos_google_prepare_authentication_uri_query; iface->extract_authorization_code = eos_google_extract_authorization_code; } +-- +2.35.1 + diff --git a/evolution-data-server-3.40.4-icalcompiter.patch b/evolution-data-server-3.40.4-icalcompiter.patch new file mode 100644 index 0000000000000000000000000000000000000000..e3707b9fd57784925a1ff94000d98a9e6e3c3225 --- /dev/null +++ b/evolution-data-server-3.40.4-icalcompiter.patch @@ -0,0 +1,49 @@ +diff --git a/src/calendar/backends/file/e-cal-backend-file.c b/src/calendar/backends/file/e-cal-backend-file.c +index f40bf807c..79ae53632 100644 +--- a/src/calendar/backends/file/e-cal-backend-file.c ++++ b/src/calendar/backends/file/e-cal-backend-file.c +@@ -904,6 +904,7 @@ scan_vcalendar (ECalBackendFile *cbfile) + if (e_cal_component_set_icalcomponent (comp, icomp)) { + /* Thus it's not freed while being used in the 'comp' */ + g_object_ref (icomp); ++ i_cal_object_set_owner (I_CAL_OBJECT (icomp), G_OBJECT (priv->vcalendar)); + + check_dup_uid (cbfile, comp); + +diff --git a/src/calendar/backends/http/e-cal-backend-http.c b/src/calendar/backends/http/e-cal-backend-http.c +index a7e930ca0..bfe9b4554 100644 +--- a/src/calendar/backends/http/e-cal-backend-http.c ++++ b/src/calendar/backends/http/e-cal-backend-http.c +@@ -477,13 +477,18 @@ ecb_http_get_changes_sync (ECalMetaBackend *meta_backend, + } else { + iter = i_cal_component_begin_component (maincomp, I_CAL_VCALENDAR_COMPONENT); + subcomp = i_cal_comp_iter_deref (iter); ++ if (subcomp) ++ i_cal_object_set_owner (I_CAL_OBJECT (subcomp), G_OBJECT (maincomp)); + } + + while (subcomp && success) { + ICalComponent *next_subcomp = NULL; + +- if (iter) ++ if (iter) { + next_subcomp = i_cal_comp_iter_next (iter); ++ if (next_subcomp) ++ i_cal_object_set_owner (I_CAL_OBJECT (next_subcomp), G_OBJECT (maincomp)); ++ } + + if (i_cal_component_isa (subcomp) == I_CAL_VCALENDAR_COMPONENT) { + success = e_cal_meta_backend_gather_timezones_sync (meta_backend, subcomp, TRUE, cancellable, error); +diff --git a/src/calendar/libecal/e-cal-component.c b/src/calendar/libecal/e-cal-component.c +index a3dddcc8f..c7629813a 100644 +--- a/src/calendar/libecal/e-cal-component.c ++++ b/src/calendar/libecal/e-cal-component.c +@@ -95,6 +95,8 @@ foreach_subcomponent (ICalComponent *icalcomp, + while (subcomp) { + ICalComponent *next_subcomp; + ++ i_cal_object_set_owner (I_CAL_OBJECT (subcomp), G_OBJECT (icalcomp)); ++ + next_subcomp = i_cal_comp_iter_next (iter); + + if (!func (icalcomp, subcomp, user_data)) { diff --git a/evolution-data-server-3.28.5-secret-monitor-warnings.patch b/evolution-data-server-3.40.4-secret-monitor-warnings.patch similarity index 100% rename from evolution-data-server-3.28.5-secret-monitor-warnings.patch rename to evolution-data-server-3.40.4-secret-monitor-warnings.patch diff --git a/evolution-data-server-3.40.4.tar.xz b/evolution-data-server-3.40.4.tar.xz new file mode 100644 index 0000000000000000000000000000000000000000..46a291bd26e18005e409499acc4b06d071158ee5 Binary files /dev/null and b/evolution-data-server-3.40.4.tar.xz differ diff --git a/evolution-data-server.spec b/evolution-data-server.spec index bf9867f7f170a82530928c37db8fd538e186e2ca..f11c729692f313fc0de47732d48b805bdb628b24 100644 --- a/evolution-data-server.spec +++ b/evolution-data-server.spec @@ -1,25 +1,35 @@ +%define anolis_release .0.1 +%undefine __cmake_in_source_build + %define ldap_support 1 %define static_ldap 0 %define krb5_support 1 %define largefile_support 1 +# enabled only for Fedora +%global phonenum_support 0%{?fedora} + # Coverity scan can override this to 0, to skip checking in gtk-doc generated code %{!?with_docs: %global with_docs 1} -%define glib2_version 2.46.0 -%define gtk3_version 3.10.0 +%if 0%{?flatpak} +%global with_docs 0 +%endif + +%define glib2_version 2.46 +%define gtk3_version 3.16 %define gcr_version 3.4 %define gtk_doc_version 1.9 %define goa_version 3.8 %define intltool_version 0.35.5 %define libsecret_version 0.5 -%define libgdata_version 0.10.0 -%define libgweather_version 3.5.0 -%define libical_version 2.0 -%define libsoup_version 2.42 +%define libgdata_version 0.15.1 +%define libgweather_version 3.10 +%define libical_version 3.0.7 +%define libsoup_version 2.58 %define nss_version 3.14 -%define sqlite_version 3.5 -%define webkit2gtk_version 2.11.91 +%define sqlite_version 3.7.17 +%define webkit2gtk_version 2.28.0 %define json_glib_version 1.0.4 %define credential_modules_dir %{_libdir}/evolution-data-server/credential-modules @@ -27,88 +37,49 @@ %define ebook_backends_dir %{_libdir}/evolution-data-server/addressbook-backends %define ecal_backends_dir %{_libdir}/evolution-data-server/calendar-backends %define modules_dir %{_libdir}/evolution-data-server/registry-modules +%define uimodules_dir %{_libdir}/evolution-data-server/ui-modules + +%global dbus_service_name_address_book org.gnome.evolution.dataserver.AddressBook10 +%global dbus_service_name_calendar org.gnome.evolution.dataserver.Calendar8 +%global dbus_service_name_sources org.gnome.evolution.dataserver.Sources5 +%global dbus_service_name_user_prompter org.gnome.evolution.dataserver.UserPrompter0 + +%if "%{?_eds_dbus_services_prefix}" != "" +%global dbus_service_name_address_book %{?_eds_dbus_services_prefix}.%{dbus_service_name_address_book} +%global dbus_service_name_calendar %{?_eds_dbus_services_prefix}.%{dbus_service_name_calendar} +%global dbus_service_name_sources %{?_eds_dbus_services_prefix}.%{dbus_service_name_sources} +%global dbus_service_name_user_prompter %{?_eds_dbus_services_prefix}.%{dbus_service_name_user_prompter} +%endif ### Abstract ### Name: evolution-data-server -Version: 3.28.5 -Release: 19%{?dist}.1 -Group: System Environment/Libraries +Version: 3.40.4 +Release: 6%{anolis_release}%{?dist} Summary: Backend data server for Evolution License: LGPLv2+ URL: https://wiki.gnome.org/Apps/Evolution -Source: http://download.gnome.org/sources/%{name}/3.28/%{name}-%{version}.tar.xz +Source: http://download.gnome.org/sources/%{name}/3.40/%{name}-%{version}.tar.xz + +Patch01: evolution-data-server-3.40.4-icalcompiter.patch +Patch02: evolution-data-server-3.40.4-secret-monitor-warnings.patch +Patch03: evolution-data-server-3.40.4-google-contacts-to-carddav.patch +Patch04: evolution-data-server-3.40.4-google-oauth2.patch +Patch05: evolution-data-server-3.40.4-caldav-crash.patch Provides: evolution-webcal = %{version} Obsoletes: evolution-webcal < 2.24.0 # RH-bug #1362477 -Recommends: pinentry-gtk +Recommends: pinentry-gui %if 0%{?fedora} # From rhughes-f20-gnome-3-12 copr Obsoletes: compat-evolution-data-server310-libcamel < 3.12 %endif -### Patches ### - -# RH bug #1624835 -Patch01: evolution-data-server-3.28.5-mangled-deeper-html-quotes.patch - -# RH bug #1653232 -Patch02: evolution-data-server-3.28.5-dav-online-load-href.patch - -# RH bug #1654203 -Patch03: evolution-data-server-3.28.5-tests-retry-client-open.patch - -# RH bug #1654310 -Patch04: evolution-data-server-3.28.5-dav-remove-ignores-not-found.patch - -# RH bug #1654720 -Patch05: evolution-data-server-3.28.5-vcard-remove-param-value.patch - -# RH bug #1654783 -Patch06: evolution-data-server-3.28.5-tests-cal-client-get-revision.patch - -# RH bug #1655030 -Patch07: evolution-data-server-3.28.5-vcard-attr-param-struct-reff.patch - -# RH bug #1696763 -Patch08: evolution-data-server-3.28.5-cve-2019-3890.patch - -# RH bug #1788478 -Patch09: evolution-data-server-3.28.5-delay-new-module-load.patch - -# RH bug #1791547 -Patch10: evolution-data-server-3.28.5-test-cal-meta-backend-without-evolution.patch - -# RH bug #1859141 -Patch11: evolution-data-server-3.28.5-CVE-2020-14928.patch - -# RH bug #1862403 -Patch12: evolution-data-server-3.28.5-CVE-2020-16117.patch - -# RH bug #1952792 -Patch13: evolution-data-server-3.28.5-imapx-icloud-mail.patch - -# RH bug #1972749 -Patch14: evolution-data-server-3.28.5-cmake-variable-name-comparison.patch - -# RH bug #1971676 -Patch15: evolution-data-server-3.28.5-calbackendfile-interval-tree-destroy.patch - -# RH bug #2008217 -Patch16: evolution-data-server-3.28.5-nonstandard-uuencode-encoding.patch - -# RH bug #1938533 -Patch17: evolution-data-server-3.28.5-secret-monitor-warnings.patch - -# RH bug #2081986 -Patch18: evolution-data-server-3.28.5-google-oauth2.patch - ### Dependencies ### -Requires: dconf Requires: %{name}-langpacks = %{version}-%{release} ### Build Dependencies ### @@ -118,14 +89,12 @@ BuildRequires: gcc BuildRequires: gcc-c++ BuildRequires: gettext BuildRequires: gperf +%if %{with_docs} BuildRequires: gtk-doc >= %{gtk_doc_version} +%endif BuildRequires: intltool >= %{intltool_version} -BuildRequires: libdb-devel -BuildRequires: perl-generators -BuildRequires: %{_bindir}/python3 +BuildRequires: make BuildRequires: vala -BuildRequires: vala-tools -BuildRequires: sendmail BuildRequires: systemd BuildRequires: pkgconfig(gcr-3) >= %{gcr_version} @@ -138,7 +107,7 @@ BuildRequires: pkgconfig(gtk+-3.0) >= %{gtk3_version} BuildRequires: pkgconfig(goa-1.0) >= %{goa_version} BuildRequires: pkgconfig(libgdata) >= %{libgdata_version} BuildRequires: pkgconfig(gweather-3.0) >= %{libgweather_version} -BuildRequires: pkgconfig(libical) >= %{libical_version} +BuildRequires: pkgconfig(libical-glib) >= %{libical_version} BuildRequires: pkgconfig(libsecret-unstable) >= %{libsecret_version} BuildRequires: pkgconfig(libsoup-2.4) >= %{libsoup_version} BuildRequires: pkgconfig(libxml-2.0) @@ -147,6 +116,7 @@ BuildRequires: pkgconfig(nss) >= %{nss_version} BuildRequires: pkgconfig(sqlite3) >= %{sqlite_version} BuildRequires: pkgconfig(webkit2gtk-4.0) >= %{webkit2gtk_version} BuildRequires: pkgconfig(json-glib-1.0) >= %{json_glib_version} +BuildRequires: pkgconfig(libcanberra-gtk3) %if %{ldap_support} BuildRequires: openldap-devel >= 2.0.11 @@ -159,6 +129,12 @@ BuildRequires: pkgconfig(openssl) BuildRequires: krb5-devel >= 1.11 %endif +%if %{phonenum_support} +BuildRequires: libphonenumber-devel +BuildRequires: protobuf-devel +BuildRequires: boost-devel +%endif + %description The %{name} package provides a unified backend for programs that work with contacts, tasks, and calendar information. @@ -168,13 +144,12 @@ by other packages. %package devel Summary: Development files for building against %{name} -Group: Development/Libraries Requires: %{name}%{?_isa} = %{version}-%{release} Requires: pkgconfig(goa-1.0) >= %{goa_version} Requires: pkgconfig(libgdata) >= %{libgdata_version} Requires: pkgconfig(gweather-3.0) >= %{libgweather_version} -Requires: pkgconfig(libical) >= %{libical_version} +Requires: pkgconfig(libical-glib) >= %{libical_version} Requires: pkgconfig(libsecret-unstable) >= %{libsecret_version} Requires: pkgconfig(libsoup-2.4) >= %{libsoup_version} Requires: pkgconfig(sqlite3) >= %{sqlite_version} @@ -196,7 +171,6 @@ This package contains translations for %{name}. %package doc Summary: Documentation files for %{name} -Group: Development/Libraries BuildArch: noarch %description doc @@ -206,16 +180,15 @@ This package contains developer documentation for %{name}. %endif %package perl -Group: Applications/Productivity Summary: Supplemental utilities that require Perl Requires: %{name}%{?_isa} = %{version}-%{release} +Requires: perl-interpreter %description perl This package contains supplemental utilities for %{name} that require Perl. %package tests Summary: Tests for the %{name} package -Group: Development/Libraries Requires: %{name}%{?_isa} = %{version}-%{release} %description tests @@ -223,32 +196,10 @@ The %{name}-tests package contains tests that can be used to verify the functionality of the installed %{name} package. %prep -%setup -q - -%patch01 -p1 -b .mangled-deeper-html-quotes -%patch02 -p1 -b .dav-online-load-href -%patch03 -p1 -b .tests-retry-client-open -%patch04 -p1 -b .dav-remove-ignores-not-found -%patch05 -p1 -b .vcard-remove-param-value -%patch06 -p1 -b .tests-cal-client-get-revision -%patch07 -p1 -b .vcard-attr-param-struct-reff -%patch08 -p1 -b .cve-2019-3890 -%patch09 -p1 -b .delay-new-module-load -%patch10 -p1 -b .test-cal-meta-backend-without-evolution -%patch11 -p1 -b .CVE-2020-14928 -%patch12 -p1 -b .CVE-2020-16117 -%patch13 -p1 -b .imapx-icloud-mail -%patch14 -p1 -b .cmake-variable-name-comparison -%patch15 -p1 -b .calbackendfile-interval-tree-destroy -%patch16 -p1 -b .nonstandard-uuencode-encoding -%patch17 -p1 -b .secret-monitor-warnings -%patch18 -p1 -b .google-oauth2 +%autosetup -p1 -S gendiff %build -mkdir -p _build -cd _build - %if %{ldap_support} %if %{static_ldap} @@ -287,6 +238,12 @@ fi %define largefile_flags -DENABLE_LARGEFILE=OFF %endif +%if %{phonenum_support} +%define phonenum_flags -DWITH_PHONENUMBER=ON +%else +%define phonenum_flags -DWITH_PHONENUMBER=OFF +%endif + %define ssl_flags -DENABLE_SMIME=ON %if %{with_docs} @@ -303,62 +260,63 @@ fi export CPPFLAGS="-I%{_includedir}/et" export CFLAGS="$RPM_OPT_FLAGS -DLDAP_DEPRECATED -fPIC -I%{_includedir}/et -Wno-deprecated-declarations" -# See Ross Burton's blog entry for why we want --with-libdb. -# http://www.burtonini.com/blog//computers/eds-libdb-2006-07-18-10-40 - %cmake -G "Unix Makefiles" \ -DENABLE_MAINTAINER_MODE=OFF \ - -DENABLE_UOA=OFF \ - -DWITH_LIBDB=/usr \ + -DWITH_LIBDB=OFF \ -DENABLE_FILE_LOCKING=fcntl \ -DENABLE_DOT_LOCKING=OFF \ -DENABLE_INTROSPECTION=ON \ -DENABLE_VALA_BINDINGS=ON \ -DENABLE_INSTALLED_TESTS=ON \ + -DWITH_SYSTEMDUSERUNITDIR=%{_userunitdir} \ + %if "%{?_eds_dbus_services_prefix}" != "" + -DDBUS_SERVICES_PREFIX=%{?_eds_dbus_services_prefix} \ + %endif %ldap_flags %krb5_flags %ssl_flags \ - %largefile_flags %gtkdoc_flags \ - .. + %largefile_flags %gtkdoc_flags %phonenum_flags \ + %{nil} -make %{?_smp_mflags} +%cmake_build %install -cd _build -rm -rf $RPM_BUILD_ROOT +%cmake_install -make DESTDIR=$RPM_BUILD_ROOT install +# make sure the directory exists, because it's owned by eds +mkdir $RPM_BUILD_ROOT/%{uimodules_dir} || : # give the libraries some executable bits find $RPM_BUILD_ROOT -name '*.so.*' -exec chmod +x {} \; %find_lang %{name} -%post -p /sbin/ldconfig - -%postun -/sbin/ldconfig -if [ $1 -eq 0 ] ; then - glib-compile-schemas %{_datadir}/glib-2.0/schemas &>/dev/null || : -fi - -%posttrans -glib-compile-schemas %{_datadir}/glib-2.0/schemas &>/dev/null || : - %files %license COPYING -%doc README ChangeLog NEWS -%{_libdir}/libcamel-1.2.so.* -%{_libdir}/libebackend-1.2.so.* -%{_libdir}/libebook-1.2.so.* -%{_libdir}/libebook-contacts-1.2.so.* -%{_libdir}/libecal-1.2.so.* -%{_libdir}/libedata-book-1.2.so.* -%{_libdir}/libedata-cal-1.2.so.* -%{_libdir}/libedataserver-1.2.so.* -%{_libdir}/libedataserverui-1.2.so.* +%{_libdir}/libcamel-1.2.so.62 +%{_libdir}/libcamel-1.2.so.62.0.0 +%{_libdir}/libebackend-1.2.so.10 +%{_libdir}/libebackend-1.2.so.10.0.0 +%{_libdir}/libebook-1.2.so.20 +%{_libdir}/libebook-1.2.so.20.1.3 +%{_libdir}/libebook-contacts-1.2.so.3 +%{_libdir}/libebook-contacts-1.2.so.3.0.0 +%{_libdir}/libecal-2.0.so.1 +%{_libdir}/libecal-2.0.so.1.0.0 +%{_libdir}/libedata-book-1.2.so.26 +%{_libdir}/libedata-book-1.2.so.26.0.0 +%{_libdir}/libedata-cal-2.0.so.1 +%{_libdir}/libedata-cal-2.0.so.1.0.0 +%{_libdir}/libedataserver-1.2.so.26 +%{_libdir}/libedataserver-1.2.so.26.0.0 +%{_libdir}/libedataserverui-1.2.so.3 +%{_libdir}/libedataserverui-1.2.so.3.0.0 %{_libdir}/girepository-1.0/Camel-1.2.typelib +%{_libdir}/girepository-1.0/EBackend-1.2.typelib %{_libdir}/girepository-1.0/EBook-1.2.typelib %{_libdir}/girepository-1.0/EBookContacts-1.2.typelib +%{_libdir}/girepository-1.0/ECal-2.0.typelib +%{_libdir}/girepository-1.0/EDataBook-1.2.typelib +%{_libdir}/girepository-1.0/EDataCal-2.0.typelib %{_libdir}/girepository-1.0/EDataServer-1.2.typelib %{_libdir}/girepository-1.0/EDataServerUI-1.2.typelib @@ -375,8 +333,12 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &>/dev/null || : %dir %{_libexecdir}/evolution-data-server %{_libexecdir}/evolution-data-server/addressbook-export +%{_libexecdir}/evolution-data-server/evolution-alarm-notify %{_libexecdir}/evolution-data-server/list-sources +%{_sysconfdir}/xdg/autostart/org.gnome.Evolution-alarm-notify.desktop +%{_datadir}/applications/org.gnome.Evolution-alarm-notify.desktop + # GSettings schemas: %{_datadir}/GConf/gsettings/evolution-data-server.convert %{_datadir}/glib-2.0/schemas/org.gnome.Evolution.DefaultSources.gschema.xml @@ -387,10 +349,10 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &>/dev/null || : %{_datadir}/glib-2.0/schemas/org.gnome.evolution.shell.network-config.gschema.xml %{_datadir}/evolution-data-server -%{_datadir}/dbus-1/services/org.gnome.evolution.dataserver.AddressBook.service -%{_datadir}/dbus-1/services/org.gnome.evolution.dataserver.Calendar.service -%{_datadir}/dbus-1/services/org.gnome.evolution.dataserver.Sources.service -%{_datadir}/dbus-1/services/org.gnome.evolution.dataserver.UserPrompter.service +%{_datadir}/dbus-1/services/%{dbus_service_name_address_book}.service +%{_datadir}/dbus-1/services/%{dbus_service_name_calendar}.service +%{_datadir}/dbus-1/services/%{dbus_service_name_sources}.service +%{_datadir}/dbus-1/services/%{dbus_service_name_user_prompter}.service %{_datadir}/pixmaps/evolution-data-server %{_userunitdir}/evolution-addressbook-factory.service @@ -404,6 +366,7 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &>/dev/null || : %dir %{ebook_backends_dir} %dir %{ecal_backends_dir} %dir %{modules_dir} +%dir %{uimodules_dir} %{_libdir}/evolution-data-server/libedbus-private.so @@ -428,16 +391,16 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &>/dev/null || : # e-d-s extensions: %{credential_modules_dir}/module-credentials-goa.so +%{ebook_backends_dir}/libebookbackendcarddav.so %{ebook_backends_dir}/libebookbackendfile.so -%{ebook_backends_dir}/libebookbackendgoogle.so %{ebook_backends_dir}/libebookbackendldap.so -%{ebook_backends_dir}/libebookbackendwebdav.so %{ecal_backends_dir}/libecalbackendcaldav.so %{ecal_backends_dir}/libecalbackendcontacts.so %{ecal_backends_dir}/libecalbackendfile.so %{ecal_backends_dir}/libecalbackendgtasks.so %{ecal_backends_dir}/libecalbackendhttp.so %{ecal_backends_dir}/libecalbackendweather.so +%{ecal_backends_dir}/libecalbackendwebdavnotes.so %{modules_dir}/module-cache-reaper.so %{modules_dir}/module-google-backend.so %{modules_dir}/module-gnome-online-accounts.so @@ -454,9 +417,9 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &>/dev/null || : %{_libdir}/libebackend-1.2.so %{_libdir}/libebook-1.2.so %{_libdir}/libebook-contacts-1.2.so -%{_libdir}/libecal-1.2.so +%{_libdir}/libecal-2.0.so %{_libdir}/libedata-book-1.2.so -%{_libdir}/libedata-cal-1.2.so +%{_libdir}/libedata-cal-2.0.so %{_libdir}/libedataserver-1.2.so %{_libdir}/libedataserverui-1.2.so %{_libdir}/pkgconfig/camel-1.2.pc @@ -464,33 +427,46 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &>/dev/null || : %{_libdir}/pkgconfig/libebackend-1.2.pc %{_libdir}/pkgconfig/libebook-1.2.pc %{_libdir}/pkgconfig/libebook-contacts-1.2.pc -%{_libdir}/pkgconfig/libecal-1.2.pc +%{_libdir}/pkgconfig/libecal-2.0.pc %{_libdir}/pkgconfig/libedata-book-1.2.pc -%{_libdir}/pkgconfig/libedata-cal-1.2.pc +%{_libdir}/pkgconfig/libedata-cal-2.0.pc %{_libdir}/pkgconfig/libedataserver-1.2.pc %{_libdir}/pkgconfig/libedataserverui-1.2.pc %{_datadir}/gir-1.0/Camel-1.2.gir +%{_datadir}/gir-1.0/EBackend-1.2.gir %{_datadir}/gir-1.0/EBook-1.2.gir %{_datadir}/gir-1.0/EBookContacts-1.2.gir +%{_datadir}/gir-1.0/ECal-2.0.gir +%{_datadir}/gir-1.0/EDataBook-1.2.gir +%{_datadir}/gir-1.0/EDataCal-2.0.gir %{_datadir}/gir-1.0/EDataServer-1.2.gir %{_datadir}/gir-1.0/EDataServerUI-1.2.gir %{_datadir}/vala/vapi/camel-1.2.deps %{_datadir}/vala/vapi/camel-1.2.vapi +%{_datadir}/vala/vapi/libebackend-1.2.deps +%{_datadir}/vala/vapi/libebackend-1.2.vapi %{_datadir}/vala/vapi/libebook-1.2.deps %{_datadir}/vala/vapi/libebook-1.2.vapi %{_datadir}/vala/vapi/libebook-contacts-1.2.deps %{_datadir}/vala/vapi/libebook-contacts-1.2.vapi +%{_datadir}/vala/vapi/libecal-2.0.deps +%{_datadir}/vala/vapi/libecal-2.0.vapi +%{_datadir}/vala/vapi/libedata-book-1.2.deps +%{_datadir}/vala/vapi/libedata-book-1.2.vapi +%{_datadir}/vala/vapi/libedata-cal-2.0.deps +%{_datadir}/vala/vapi/libedata-cal-2.0.vapi %{_datadir}/vala/vapi/libedataserver-1.2.deps %{_datadir}/vala/vapi/libedataserver-1.2.vapi %{_datadir}/vala/vapi/libedataserverui-1.2.deps %{_datadir}/vala/vapi/libedataserverui-1.2.vapi -%files langpacks -f _build/%{name}.lang +%files langpacks -f %{name}.lang %if %{with_docs} %files doc %{_datadir}/gtk-doc/html/* +%doc README ChangeLog NEWS %endif @@ -499,80 +475,273 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &>/dev/null || : %files tests %{_libdir}/libetestserverutils.so -%{_libdir}/libetestserverutils.so.* +%{_libdir}/libetestserverutils.so.0 +%{_libdir}/libetestserverutils.so.0.0.0 %{_libexecdir}/%{name}/installed-tests %{_datadir}/installed-tests %changelog -* Thu May 05 2022 Milan Crha - 3.28.5-19.1 -- Resolves: #2081986 (Backport patch for Google OAuth2 change) +* Tue May 16 2023 Chang Gao - 3.40.4-6.0.1 +- move docs to doc subpack + +* Tue May 24 2022 Milan Crha - 3.40.4-6 +- Resolves: #2089902 (CalDAV: Crash on calendar update) + +* Wed May 04 2022 Milan Crha - 3.40.4-5 +- Resolves: #2081747 (Backport patch for Google OAuth2 change) + +* Tue Apr 05 2022 Milan Crha - 3.40.4-4 +- Resolves: #2071893 (Addressbook: Switch from GData Contacts API to CardDAV API for Google books) + +* Mon Nov 22 2021 Milan Crha - 3.40.4-3 +- Resolves: #2025480 (secret-monitor: Turn runtime warnings into debug prints) + +* Mon Nov 08 2021 Milan Crha - 3.40.4-2 +- Resolves: #2021055 (Add patch to correct ICalCompIter component's usage) + +* Fri Aug 13 2021 Milan Crha - 3.40.4-1 +- Related: #1992450 (Update to 3.40.4) + +* Mon Aug 09 2021 Mohan Boddu - 3.40.3-2 +- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags + Related: rhbz#1991688 + +* Mon Jul 12 2021 Milan Crha - 3.40.3-1 +- Related: #1981215 (Update to 3.40.3) + +* Fri Jun 04 2021 Milan Crha - 3.40.2-1 +- Related: #1967855 (Update to 3.40.2) + +* Thu Apr 15 2021 Mohan Boddu - 3.40.0-4 +- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937 + +* Mon Mar 29 2021 Milan Crha - 3.40.0-3 +- Resolves: #1943818 (ESourceWebDAV: Fallback to SHA1 on SSL trust verification if needed) + +* Fri Mar 26 2021 Kalev Lember - 3.40.0-2 +- Drop unnecessary requires on dconf + +* Fri Mar 19 2021 Milan Crha - 3.40.0-1 +- Update to 3.40.0 + +* Fri Mar 12 2021 Milan Crha - 3.39.3-1 +- Update to 3.39.3 + +* Sat Feb 13 2021 Kalev Lember - 3.39.2-3 +- Drop temporary ABI compat + +* Fri Feb 12 2021 Kalev Lember - 3.39.2-2 +- Keep temporary ABI compat with previous soname + +* Fri Feb 12 2021 Milan Crha - 3.39.2-1 +- Update to 3.39.2 + +* Fri Feb 05 2021 Kalev Lember - 3.39.1-3 +- Recommend pinentry-gui virtual provide, rather than pinentry-gtk + +* Tue Jan 26 2021 Fedora Release Engineering - 3.39.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Fri Jan 08 2021 Milan Crha - 3.39.1-1 +- Update to 3.39.1 + +* Fri Nov 20 2020 Milan Crha - 3.38.2-1 +- Update to 3.38.2 + +* Mon Oct 05 2020 Milan Crha - 3.38.1-2 +- Correct D-Bus service file name - it can change when _eds_dbus_services_prefix is defined +- Replace perl-generators build time dependency with perl-interpreter install time dependency + +* Fri Oct 02 2020 Milan Crha - 3.38.1-1 +- Update to 3.38.1 + +* Sat Sep 26 2020 Adrian Reber - 3.38.0-2 +- Rebuilt for protobuf 3.13 + +* Fri Sep 11 2020 Milan Crha - 3.38.0-1 +- Update to 3.38.0 + +* Fri Sep 04 2020 Milan Crha - 3.37.92-1 +- Update to 3.37.92 + +* Fri Aug 07 2020 Milan Crha - 3.37.90-1 +- Update to 3.37.90 + +* Mon Jul 27 2020 Fedora Release Engineering - 3.37.3-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Tue Jul 14 2020 Milan Crha - 3.37.3-3 +- Rebuild in a side tag for bodhi, to be able to create an update + +* Fri Jul 03 2020 Milan Crha - 3.37.3-2 +- Add a patch for missing G_BEGIN_DECLS in e-soup-logger.h + +* Fri Jul 03 2020 Milan Crha - 3.37.3-1 +- Update to 3.37.3 + +* Tue Jun 23 2020 Adam Williamson - 3.37.2-2 +- Rebuild with newer protobuf and libphonenumber +- Backport several fixes for annoying bugs from mainline + +* Fri May 29 2020 Milan Crha - 3.37.2-1 +- Update to 3.37.2 + +* Sun May 17 2020 Pete Walter - 3.37.1-2 +- Rebuild for ICU 67 + +* Fri Apr 24 2020 Milan Crha - 3.37.1-1 +- Update to 3.37.1 + +* Wed Apr 01 2020 Nikhil Jha - 3.36.1-3 +- Build with phonenumber support + +* Mon Mar 30 2020 Milan Crha - 3.36.1-2 +- Remove libdb dependency + +* Fri Mar 27 2020 Milan Crha - 3.36.1-1 +- Update to 3.36.1 + +* Fri Mar 06 2020 Milan Crha - 3.36.0-1 +- Update to 3.36.0 + +* Fri Feb 28 2020 Milan Crha - 3.35.92-1 +- Update to 3.35.92 + +* Fri Feb 14 2020 Milan Crha - 3.35.91-1 +- Update to 3.35.91 + +* Fri Jan 31 2020 Milan Crha - 3.35.90-1 +- Update to 3.35.90 + +* Tue Jan 28 2020 Fedora Release Engineering - 3.35.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Tue Jan 07 2020 Milan Crha - 3.35.3-2 +- Add patch for RH bug #1754321 (alarm-notify: Double-free with certain types of the reminder) + +* Fri Jan 03 2020 Milan Crha - 3.35.3-1 +- Update to 3.35.3 + +* Fri Nov 22 2019 Milan Crha - 3.35.2-1 +- Update to 3.35.2 + +* Fri Nov 01 2019 Pete Walter - 3.35.1-2 +- Rebuild for ICU 65 + +* Fri Oct 11 2019 Milan Crha - 3.35.1-1 +- Update to 3.35.1 + +* Mon Oct 07 2019 Milan Crha - 3.34.1-1 +- Update to 3.34.1 + +* Mon Sep 09 2019 Milan Crha - 3.34.0-1 +- Update to 3.34.0 + +* Mon Sep 02 2019 Milan Crha - 3.33.92-1 +- Update to 3.33.92 + +* Mon Aug 19 2019 Milan Crha - 3.33.91-1 +- Update to 3.33.91 + +* Mon Aug 05 2019 Milan Crha - 3.33.90-1 +- Update to 3.33.90 + +* Thu Jul 25 2019 Fedora Release Engineering - 3.33.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Mon Jul 15 2019 Milan Crha - 3.33.4-1 +- Update to 3.33.4 + +* Mon Jul 08 2019 Kalev Lember - 3.33.3-2 +- Rebuilt for libgweather soname bump + +* Mon Jun 17 2019 Milan Crha - 3.33.3-1 +- Update to 3.33.3 + +* Mon May 20 2019 Milan Crha - 3.33.2-1 +- Update to 3.33.2 + +* Mon Apr 22 2019 Milan Crha - 3.33.1-1 +- Update to 3.33.1 + +* Mon Apr 08 2019 Milan Crha - 3.32.1-1 +- Update to 3.32.1 + +* Mon Mar 11 2019 Milan Crha - 3.32.0-1 +- Update to 3.32.0 + +* Mon Mar 04 2019 Milan Crha - 3.31.92-1 +- Update to 3.31.92 + +* Mon Feb 18 2019 Milan Crha - 3.31.91-1 +- Update to 3.31.91 -* Mon Nov 22 2021 Milan Crha - 3.28.5-19 -- Resolves: #1938533 (secret-monitor: Turn runtime warnings into debug prints) +* Mon Feb 04 2019 Kalev Lember - 3.31.90-2 +- Update BRs for vala packaging changes -* Thu Sep 30 2021 Milan Crha - 3.28.5-18 -- Resolves: #2008217 (Camel: Understand non-standard "Content-Transfer-Encoding: uuencode") +* Mon Feb 04 2019 Milan Crha - 3.31.90-1 +- Update to 3.31.90 -* Wed Jun 16 2021 Milan Crha - 3.28.5-17 -- Resolves: #1972749 (PrintableOptions.cmake: Correct variable name comparison) -- Resolves: #1971676 (ECalBackendFile: Free interval tree only when being allocated) +* Thu Jan 31 2019 Fedora Release Engineering - 3.31.4-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild -* Fri Apr 23 2021 Milan Crha - 3.28.5-16 -- Resolves: #1952792 (IMAPx: Fix connect to iCloud mail server) +* Wed Jan 23 2019 Pete Walter - 3.31.4-3 +- Rebuild for ICU 63 -* Wed Sep 30 2020 Milan Crha - 3.28.5-15 -- Resolves: #1862403 (CVE-2020-16117: Crash on malformed server response with minimal capabilities) +* Mon Jan 07 2019 Milan Crha - 3.31.4-2 +- Fix typo in the latest Igor Gnatenko's commit (Remove obsolete scriptlets) -* Thu Jul 23 2020 Milan Crha - 3.28.5-14 -- Resolves: #1859141 (CVE-2020-14928: Response Injection via STARTTLS in SMTP and POP3) +* Mon Jan 07 2019 Milan Crha - 3.31.4-1 +- Update to 3.31.4 -* Thu Jan 16 2020 Milan Crha - 3.28.5-13 -- Resolves: #1791547 (test-cal-meta-backend cannot run without installed Evolution) +* Mon Dec 10 2018 Milan Crha - 3.31.3-1 +- Update to 3.31.3 -* Wed Jan 15 2020 Milan Crha - 3.28.5-12 -- Add patch for RH bug #1788478 (EDBusServer: Delay new module load) +* Mon Nov 12 2018 Milan Crha - 3.31.2-1 +- Update to 3.31.2 -* Mon May 27 2019 Milan Crha - 3.28.5-11 -- Update patch for RH bug #1713619 (test-cal-client-get-revision could fail due to delayed D-Bus property change notification) +* Mon Oct 08 2018 Milan Crha - 3.31.1-1 +- Update to 3.31.1 -* Mon Apr 15 2019 Milan Crha - 3.28.5-10 -- Add patch related to evolution-ews' CVE-2019-3890 (RH bug #1696763) +* Mon Sep 24 2018 Milan Crha - 3.30.1-1 +- Update to 3.30.1 +- Remove patch for GNOME Evolution issue #86 (fixed upstream) -* Tue Dec 04 2018 Milan Crha - 3.28.5-9 -- Update patch for RH bug #1654203 (Make tests retry when factory doesn't know about added ESource yet) +* Mon Sep 03 2018 Milan Crha - 3.30.0-1 +- Update to 3.30.0 +- Add patch for GNOME Evolution issue #86 (Quoting of plain text mail into HTML mode mangles deeper levels) -* Fri Nov 30 2018 Milan Crha - 3.28.5-8 -- Add patch for RH bug #1655030 (Make EVCardAttribute/EVCardAttributeParam structures ref-counted internally) +* Mon Aug 27 2018 Milan Crha - 3.29.92-1 +- Update to 3.29.92 -* Thu Nov 29 2018 Milan Crha - 3.28.5-7 -- Add patch for RH bug #1654720 (Correct use-after-free in e_vcard_attribute_remove_param_value()) -- Add patch for RH bug #1654783 (test-cal-client-get-revision could fail due to delayed D-Bus property change notification) +* Mon Aug 13 2018 Milan Crha - 3.29.91-1 +- Update to 3.29.91 -* Wed Nov 28 2018 Milan Crha - 3.28.5-6 -- Add patch for RH bug #1654310 ([CalDAV/CardDAV] Ignore Not Found error on resource delete) +* Mon Jul 30 2018 Milan Crha - 3.29.90-1 +- Update to 3.29.90 -* Wed Nov 28 2018 Milan Crha - 3.28.5-5 -- Add patch for RH bug #1654203 (Make tests retry when factory doesn't know about added ESource yet) +* Mon Jul 16 2018 Milan Crha - 3.29.4-1 +- Update to 3.29.4 -* Mon Nov 26 2018 Milan Crha - 3.28.5-4 -- Add patch for RH bug #1653232 ([CalDAV/CardDAV] Can add component to local cache with incomplete info) +* Fri Jul 13 2018 Fedora Release Engineering - 3.29.3-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild -* Mon Sep 03 2018 Milan Crha - 3.28.5-3 -- Add patch for RH bug #1624835 (Quoting of plain text mail into HTML mode mangles deeper levels) +* Tue Jul 10 2018 Pete Walter - 3.29.3-2 +- Rebuild for ICU 62 -* Tue Aug 14 2018 Petr Viktorin - 3.28.5-2 -- Fix BuildRequires for /usr/bin/python3 -- Resolves: #1615515 +* Mon Jun 18 2018 Milan Crha - 3.29.3-1 +- Update to 3.29.3 -* Mon Jul 30 2018 Milan Crha - 3.28.5-1 -- Update to 3.28.5 +* Mon May 21 2018 Milan Crha - 3.29.2-1 +- Update to 3.29.2 -* Mon Jul 16 2018 Milan Crha - 3.28.4-1 -- Update to 3.28.4 +* Mon Apr 30 2018 Pete Walter - 3.29.1-2 +- Rebuild for ICU 61.1 -* Mon Jun 18 2018 Milan Crha - 3.28.3-1 -- Update to 3.28.3 -- Remove fix to strip closing > from URLs when linkifying (fixed upstream) +* Mon Apr 16 2018 Milan Crha - 3.29.1-1 +- Update to 3.29.1 +- Remove fix to strip closing > from URLs when linkifying (BGO#795108) (Fixed upstream) +- Drop build dependency on python * Tue Apr 10 2018 Adam Williamson - 3.28.1-2 - Backport fix to strip closing > from URLs when linkifying (BGO#795108)