diff --git a/SOURCES/Make-DBUS_SERVICES_PREFIX-runtime-configurable.patch b/SOURCES/Make-DBUS_SERVICES_PREFIX-runtime-configurable.patch new file mode 100644 index 0000000..bd83e36 --- /dev/null +++ b/SOURCES/Make-DBUS_SERVICES_PREFIX-runtime-configurable.patch @@ -0,0 +1,659 @@ +From 23c40181b44bc536f3c07aafe966167170856e9f Mon Sep 17 00:00:00 2001 +From: "Owen W. Taylor" +Date: Mon, 20 Nov 2023 12:23:30 -0500 +Subject: [PATCH] Make DBUS_SERVICES_PREFIX runtime-configurable + +Rather than making DBUS_SERVICES_PREFIX a runtime config option, instead +add a config file $sysconfdir/evolution-data-server/dbus-prefix to set +the prefix and read that file both for the library and on the server +side. + +Add a tool in the private libexecdir 'set-dbus-prefix' to write the +config file and edit systemd and D-Bus service files as needed. + +Resolves #502 +--- + CMakeLists.txt | 14 +---- + config.h.in | 3 - + data/org.gnome.EvolutionDataServer.Devel.json | 3 +- + src/addressbook/libebook/e-book-client.c | 3 +- + .../libedata-book/e-data-book-factory.c | 4 +- + ...evolution-addressbook-factory-subprocess.c | 3 +- + src/calendar/libecal/e-cal-client.c | 3 +- + .../libedata-cal/e-data-cal-factory.c | 4 +- + .../evolution-calendar-factory-subprocess.c | 3 +- + src/libebackend/e-source-registry-server.c | 4 +- + src/libebackend/e-user-prompter-server.c | 3 +- + src/libebackend/e-user-prompter.c | 3 +- + src/libedataserver/CMakeLists.txt | 3 + + src/libedataserver/e-dbus-prefix.c | 55 +++++++++++++++++++ + src/libedataserver/e-dbus-prefix.h | 26 +++++++++ + src/libedataserver/e-secret-store.c | 9 +-- + src/libedataserver/e-source-registry.c | 5 +- + .../e-credentials-prompter-impl-oauth2.c | 3 +- + .../secret-monitor/module-secret-monitor.c | 10 +--- + .../evolution-alarm-notify/e-alarm-notify.c | 7 +-- + src/tools/CMakeLists.txt | 7 +++ + src/tools/oauth2-handler/CMakeLists.txt | 1 + + src/tools/oauth2-handler/oauth2-handler.c | 4 +- + src/tools/set-dbus-prefix.in | 37 +++++++++++++ + 24 files changed, 168 insertions(+), 49 deletions(-) + create mode 100644 src/libedataserver/e-dbus-prefix.c + create mode 100644 src/libedataserver/e-dbus-prefix.h + create mode 100644 src/tools/set-dbus-prefix.in + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index e7d376add..7b77d02f5 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -38,7 +38,7 @@ set(PROJECT_DISTCONFIGURE_PARAMS + # ****************************** + # D-Bus versioning + # ****************************** +-# Actual name can be modified with DBUS_SERVICES_PREFIX option ++# If adding new services with service files, they also need to be added to src/tools/set-dbus-prefix.in + set(ADDRESS_BOOK_DBUS_SERVICE_NAME "org.gnome.evolution.dataserver.AddressBook10") + set(CALENDAR_DBUS_SERVICE_NAME "org.gnome.evolution.dataserver.Calendar8") + set(SOURCES_DBUS_SERVICE_NAME "org.gnome.evolution.dataserver.Sources5") +@@ -183,18 +183,6 @@ ensure_default_value(LOCALE_INSTALL_DIR "${SHARE_INSTALL_PREFIX}/locale") + ensure_default_value(SYSCONF_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/etc") + ensure_default_value(EXTENSIONS_DIR "${LIBEXEC_INSTALL_DIR}/evolution/extensions") + +-add_printable_variable(DBUS_SERVICES_PREFIX "Prefix for D-Bus services, usually left empty, without trailing dot" "") +- +-if(NOT ("${DBUS_SERVICES_PREFIX}" STREQUAL "")) +- set(ADDRESS_BOOK_DBUS_SERVICE_NAME "${DBUS_SERVICES_PREFIX}.${ADDRESS_BOOK_DBUS_SERVICE_NAME}") +- set(CALENDAR_DBUS_SERVICE_NAME "${DBUS_SERVICES_PREFIX}.${CALENDAR_DBUS_SERVICE_NAME}") +- set(SOURCES_DBUS_SERVICE_NAME "${DBUS_SERVICES_PREFIX}.${SOURCES_DBUS_SERVICE_NAME}") +- set(USER_PROMPTER_DBUS_SERVICE_NAME "${DBUS_SERVICES_PREFIX}.${USER_PROMPTER_DBUS_SERVICE_NAME}") +- set(OAUTH2_RESPONSE_DBUS_SERVICE_NAME "${DBUS_SERVICES_PREFIX}.${OAUTH2_RESPONSE_DBUS_SERVICE_NAME}") +-else(NOT ("${DBUS_SERVICES_PREFIX}" STREQUAL "")) +- unset(DBUS_SERVICES_PREFIX) +-endif(NOT ("${DBUS_SERVICES_PREFIX}" STREQUAL "")) +- + # ****************************** + # Special directories + # ****************************** +diff --git a/config.h.in b/config.h.in +index 064873e2a..b895655a9 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -21,9 +21,6 @@ + /* Defined to prefix where out-of-tree extensions can be installed */ + #cmakedefine EXTENSIONS_DIR "@EXTENSIONS_DIR@" + +-/* Defined to prefix used by the D-Bus services (usually when run in Flatpak) */ +-#cmakedefine DBUS_SERVICES_PREFIX "@DBUS_SERVICES_PREFIX@" +- + /* D-Bus service name for the address book factory */ + #define ADDRESS_BOOK_DBUS_SERVICE_NAME "@ADDRESS_BOOK_DBUS_SERVICE_NAME@" + +diff --git a/data/org.gnome.EvolutionDataServer.Devel.json b/data/org.gnome.EvolutionDataServer.Devel.json +index c8136ec20..118e25da3 100644 +--- a/data/org.gnome.EvolutionDataServer.Devel.json ++++ b/data/org.gnome.EvolutionDataServer.Devel.json +@@ -277,7 +277,6 @@ + "/share/GConf" + ], + "config-opts": [ +- "-DDBUS_SERVICES_PREFIX=org.gnome.EvolutionDataServer.Devel", + "-DEXTENSIONS_DIR=/app/evolution/extensions", + "-DENABLE_MAINTAINER_MODE=ON", + "-DENABLE_FILE_LOCKING=fcntl", +@@ -304,6 +303,8 @@ + } + ], + "post-install": [ ++ "/app/libexec/evolution-data-server/set-dbus-prefix org.gnome.EvolutionDataServer.Devel", ++ "sed -i s/org.gnome.evolution/org.gnome.EvolutionDataServer.Devel.org.gnome.evolution/ tests/test-server-utils/services/*.service", + "ctest --force-new-ctest-process --output-on-failure" + ] + +diff --git a/src/addressbook/libebook/e-book-client.c b/src/addressbook/libebook/e-book-client.c +index bd479d8f3..3738d37ce 100644 +--- a/src/addressbook/libebook/e-book-client.c ++++ b/src/addressbook/libebook/e-book-client.c +@@ -40,6 +40,7 @@ + + #include + #include ++#include + + #include + #include +@@ -1078,7 +1079,7 @@ book_client_init_in_dbus_thread (GSimpleAsyncResult *simple, + factory_proxy = e_dbus_address_book_factory_proxy_new_sync ( + connection, + G_DBUS_PROXY_FLAGS_NONE, +- ADDRESS_BOOK_DBUS_SERVICE_NAME, ++ e_dbus_prefix (ADDRESS_BOOK_DBUS_SERVICE_NAME), + "/org/gnome/evolution/dataserver/AddressBookFactory", + cancellable, &local_error); + +diff --git a/src/addressbook/libedata-book/e-data-book-factory.c b/src/addressbook/libedata-book/e-data-book-factory.c +index 02adb19b4..a9d89d82e 100644 +--- a/src/addressbook/libedata-book/e-data-book-factory.c ++++ b/src/addressbook/libedata-book/e-data-book-factory.c +@@ -41,6 +41,8 @@ + #include "e-data-book-factory.h" + #include "e-system-locale-watcher.h" + ++#include "libedataserver/e-dbus-prefix.h" ++ + #define d(x) + + struct _EDataBookFactoryPrivate { +@@ -315,7 +317,7 @@ e_data_book_factory_class_init (EDataBookFactoryClass *class) + object_class->dispose = data_book_factory_dispose; + + dbus_server_class = E_DBUS_SERVER_CLASS (class); +- dbus_server_class->bus_name = ADDRESS_BOOK_DBUS_SERVICE_NAME; ++ dbus_server_class->bus_name = e_dbus_prefix (ADDRESS_BOOK_DBUS_SERVICE_NAME); + dbus_server_class->module_directory = modules_directory; + + data_factory_class = E_DATA_FACTORY_CLASS (class); +diff --git a/src/addressbook/libedata-book/evolution-addressbook-factory-subprocess.c b/src/addressbook/libedata-book/evolution-addressbook-factory-subprocess.c +index 3897042e6..ef539573d 100644 +--- a/src/addressbook/libedata-book/evolution-addressbook-factory-subprocess.c ++++ b/src/addressbook/libedata-book/evolution-addressbook-factory-subprocess.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + + typedef struct _SubprocessData SubprocessData; +@@ -198,7 +199,7 @@ main (gint argc, + /* Watch the factory name and close the subprocess if the factory dies/crashes */ + watched_id = g_bus_watch_name ( + G_BUS_TYPE_SESSION, +- ADDRESS_BOOK_DBUS_SERVICE_NAME, ++ e_dbus_prefix (ADDRESS_BOOK_DBUS_SERVICE_NAME), + G_BUS_NAME_WATCHER_FLAGS_NONE, + NULL, + (GBusNameVanishedCallback) vanished_cb, +diff --git a/src/calendar/libecal/e-cal-client.c b/src/calendar/libecal/e-cal-client.c +index d0414e4c7..fd6665db5 100644 +--- a/src/calendar/libecal/e-cal-client.c ++++ b/src/calendar/libecal/e-cal-client.c +@@ -36,6 +36,7 @@ + #include + + #include ++#include + + #include "e-cal-client.h" + #include "e-cal-component.h" +@@ -1211,7 +1212,7 @@ cal_client_init_in_dbus_thread (GSimpleAsyncResult *simple, + factory_proxy = e_dbus_calendar_factory_proxy_new_sync ( + connection, + G_DBUS_PROXY_FLAGS_NONE, +- CALENDAR_DBUS_SERVICE_NAME, ++ e_dbus_prefix (CALENDAR_DBUS_SERVICE_NAME), + "/org/gnome/evolution/dataserver/CalendarFactory", + cancellable, &local_error); + +diff --git a/src/calendar/libedata-cal/e-data-cal-factory.c b/src/calendar/libedata-cal/e-data-cal-factory.c +index e0790e17d..1e4c5e56d 100644 +--- a/src/calendar/libedata-cal/e-data-cal-factory.c ++++ b/src/calendar/libedata-cal/e-data-cal-factory.c +@@ -47,6 +47,8 @@ + #include "e-data-cal.h" + #include "e-data-cal-factory.h" + ++#include "libedataserver/e-dbus-prefix.h" ++ + #include + + #define d(x) +@@ -270,7 +272,7 @@ e_data_cal_factory_class_init (EDataCalFactoryClass *class) + overwrite_subprocess_cal_path = g_strdup (subprocess_cal_path_env); + + dbus_server_class = E_DBUS_SERVER_CLASS (class); +- dbus_server_class->bus_name = CALENDAR_DBUS_SERVICE_NAME; ++ dbus_server_class->bus_name = e_dbus_prefix (CALENDAR_DBUS_SERVICE_NAME); + dbus_server_class->module_directory = modules_directory; + + data_factory_class = E_DATA_FACTORY_CLASS (class); +diff --git a/src/calendar/libedata-cal/evolution-calendar-factory-subprocess.c b/src/calendar/libedata-cal/evolution-calendar-factory-subprocess.c +index 29732fc6e..514d50e2e 100644 +--- a/src/calendar/libedata-cal/evolution-calendar-factory-subprocess.c ++++ b/src/calendar/libedata-cal/evolution-calendar-factory-subprocess.c +@@ -28,6 +28,7 @@ + #include + #include + #include ++#include + #include + + typedef struct _SubprocessData SubprocessData; +@@ -198,7 +199,7 @@ main (gint argc, + /* Watch the factory name and close the subprocess if the factory dies/crashes */ + watched_id = g_bus_watch_name ( + G_BUS_TYPE_SESSION, +- CALENDAR_DBUS_SERVICE_NAME, ++ e_dbus_prefix (CALENDAR_DBUS_SERVICE_NAME), + G_BUS_NAME_WATCHER_FLAGS_NONE, + NULL, + (GBusNameVanishedCallback) vanished_cb, +diff --git a/src/libebackend/e-source-registry-server.c b/src/libebackend/e-source-registry-server.c +index 4fe4759a5..fe34a7921 100644 +--- a/src/libebackend/e-source-registry-server.c ++++ b/src/libebackend/e-source-registry-server.c +@@ -36,6 +36,8 @@ + #include + #include + ++#include ++ + /* Private D-Bus classes. */ + #include "e-dbus-source.h" + #include "e-dbus-source-manager.h" +@@ -1082,7 +1084,7 @@ e_source_registry_server_class_init (ESourceRegistryServerClass *class) + object_class->finalize = source_registry_server_finalize; + + dbus_server_class = E_DBUS_SERVER_CLASS (class); +- dbus_server_class->bus_name = SOURCES_DBUS_SERVICE_NAME; ++ dbus_server_class->bus_name = e_dbus_prefix (SOURCES_DBUS_SERVICE_NAME); + dbus_server_class->module_directory = modules_directory; + dbus_server_class->bus_acquired = source_registry_server_bus_acquired; + dbus_server_class->quit_server = source_registry_server_quit_server; +diff --git a/src/libebackend/e-user-prompter-server.c b/src/libebackend/e-user-prompter-server.c +index f9febd77f..4357ebc90 100644 +--- a/src/libebackend/e-user-prompter-server.c ++++ b/src/libebackend/e-user-prompter-server.c +@@ -29,6 +29,7 @@ + #include + + #include ++#include + + /* Private D-Bus classes. */ + #include "e-dbus-user-prompter.h" +@@ -409,7 +410,7 @@ e_user_prompter_server_class_init (EUserPrompterServerClass *class) + object_class->finalize = user_prompter_server_finalize; + + dbus_server_class = E_DBUS_SERVER_CLASS (class); +- dbus_server_class->bus_name = USER_PROMPTER_DBUS_SERVICE_NAME; ++ dbus_server_class->bus_name = e_dbus_prefix (USER_PROMPTER_DBUS_SERVICE_NAME); + dbus_server_class->module_directory = MODULE_DIRECTORY; + dbus_server_class->bus_acquired = user_prompter_server_bus_acquired; + dbus_server_class->quit_server = user_prompter_server_quit_server; +diff --git a/src/libebackend/e-user-prompter.c b/src/libebackend/e-user-prompter.c +index 054a8b44f..3c3cb5761 100644 +--- a/src/libebackend/e-user-prompter.c ++++ b/src/libebackend/e-user-prompter.c +@@ -26,6 +26,7 @@ + #include "evolution-data-server-config.h" + + #include ++#include + + #include "e-dbus-user-prompter.h" + #include "e-user-prompter.h" +@@ -251,7 +252,7 @@ user_prompter_prompt_thread (GSimpleAsyncResult *simple, + dbus_prompter = e_dbus_user_prompter_proxy_new_for_bus_sync ( + G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, +- USER_PROMPTER_DBUS_SERVICE_NAME, ++ e_dbus_prefix (USER_PROMPTER_DBUS_SERVICE_NAME), + "/org/gnome/evolution/dataserver/UserPrompter", + cancellable, + &local_error); +diff --git a/src/libedataserver/CMakeLists.txt b/src/libedataserver/CMakeLists.txt +index 5ccb29b56..22e9f0c6d 100644 +--- a/src/libedataserver/CMakeLists.txt ++++ b/src/libedataserver/CMakeLists.txt +@@ -53,6 +53,8 @@ set(SOURCES + e-client-private.h + e-collator.c + e-credentials.c ++ e-dbus-prefix.c ++ e-dbus-prefix.h + e-extensible.c + e-extension.c + e-flag.c +@@ -250,6 +252,7 @@ target_compile_definitions(edataserver PRIVATE + -DE_DATA_SERVER_PREFIX=\"${CMAKE_INSTALL_PREFIX}\" + -DE_DATA_SERVER_LOCALEDIR=\"${LOCALE_INSTALL_DIR}\" + -DE_DATA_SERVER_IMAGESDIR=\"${imagesdir}\" ++ -DE_DATA_SERVER_SYSCONFDIR=\"${SYSCONF_INSTALL_DIR}\" + -DE_DATA_SERVER_CREDENTIALMODULEDIR=\"${credentialmoduledir}\" + -DE_DATA_SERVER_UIMODULEDIR=\"${uimoduledir}\" + -DE_DATA_SERVER_PRIVDATADIR=\"${privdatadir}\" +diff --git a/src/libedataserver/e-dbus-prefix.c b/src/libedataserver/e-dbus-prefix.c +new file mode 100644 +index 000000000..7018f2396 +--- /dev/null ++++ b/src/libedataserver/e-dbus-prefix.c +@@ -0,0 +1,55 @@ ++/* Copyright 2023 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 . ++ * ++ */ ++ ++#include "evolution-data-server-config.h" ++ ++#include ++ ++#include "e-dbus-prefix.h" ++ ++static char * ++read_prefix (gpointer data) ++{ ++ char *contents; ++ ++ if (g_file_get_contents (E_DATA_SERVER_SYSCONFDIR "/evolution-data-server/dbus-prefix", ++ &contents, NULL, NULL)) { ++ g_strstrip (contents); ++ return contents; ++ } else { ++ return NULL; ++ } ++} ++ ++const char * ++e_dbus_prefix (const char *base) ++{ ++ static GOnce read_prefix_once = G_ONCE_INIT; ++ const char *prefix; ++ ++ g_once (&read_prefix_once, (GThreadFunc)read_prefix, NULL); ++ prefix = read_prefix_once.retval; ++ ++ if (prefix) { ++ char *prefixed = g_strconcat (prefix, ".", base, NULL); ++ const char *result = g_intern_string (prefixed); ++ g_free (prefixed); ++ ++ return result; ++ } else { ++ return base; ++ } ++} +diff --git a/src/libedataserver/e-dbus-prefix.h b/src/libedataserver/e-dbus-prefix.h +new file mode 100644 +index 000000000..e8298b3fd +--- /dev/null ++++ b/src/libedataserver/e-dbus-prefix.h +@@ -0,0 +1,26 @@ ++/* Copyright 2023 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 . ++ * ++ */ ++ ++#ifndef E_DBUS_PREFIX ++#define E_DBUS_PREFIX ++ ++G_BEGIN_DECLS ++ ++const char *e_dbus_prefix (const char *base); ++ ++G_END_DECLS ++ ++#endif /* E_DBUS_PREFIX */ +diff --git a/src/libedataserver/e-secret-store.c b/src/libedataserver/e-secret-store.c +index e15148227..94c4216e5 100644 +--- a/src/libedataserver/e-secret-store.c ++++ b/src/libedataserver/e-secret-store.c +@@ -35,6 +35,7 @@ + #include + #endif + ++#include "e-dbus-prefix.h" + #include "e-data-server-util.h" + #include "e-secret-store.h" + +@@ -254,12 +255,6 @@ e_win32_secret_delete_secret_sync (const gchar *uid, + #define KEYRING_ITEM_ATTRIBUTE_UID "e-source-uid" + #define KEYRING_ITEM_ATTRIBUTE_ORIGIN "eds-origin" + +-#ifdef DBUS_SERVICES_PREFIX +-#define ORIGIN_KEY DBUS_SERVICES_PREFIX "." PACKAGE +-#else +-#define ORIGIN_KEY PACKAGE +-#endif +- + static SecretSchema password_schema = { + "org.gnome.Evolution.Data.Source", + SECRET_SCHEMA_DONT_MATCH_NAME, +@@ -322,7 +317,7 @@ e_secret_store_store_sync (const gchar *uid, + collection, label, secret, + cancellable, error, + KEYRING_ITEM_ATTRIBUTE_UID, uid, +- KEYRING_ITEM_ATTRIBUTE_ORIGIN, ORIGIN_KEY, ++ KEYRING_ITEM_ATTRIBUTE_ORIGIN, e_dbus_prefix (PACKAGE), + NULL); + #endif + +diff --git a/src/libedataserver/e-source-registry.c b/src/libedataserver/e-source-registry.c +index 4a9b398ca..9d1c98b49 100644 +--- a/src/libedataserver/e-source-registry.c ++++ b/src/libedataserver/e-source-registry.c +@@ -51,6 +51,7 @@ + #include "e-dbus-source-manager.h" + + #include "e-data-server-util.h" ++#include "e-dbus-prefix.h" + #include "e-source-collection.h" + #include "e-source-enumtypes.h" + +@@ -1091,7 +1092,7 @@ source_registry_object_manager_thread (gpointer data) + object_manager = e_dbus_object_manager_client_new_for_bus_sync ( + G_BUS_TYPE_SESSION, + G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, +- SOURCES_DBUS_SERVICE_NAME, ++ e_dbus_prefix (SOURCES_DBUS_SERVICE_NAME), + DBUS_OBJECT_PATH, + NULL, &closure->error); + +@@ -1472,7 +1473,7 @@ source_registry_initable_init (GInitable *initable, + e_dbus_source_manager_proxy_new_for_bus_sync ( + G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, +- SOURCES_DBUS_SERVICE_NAME, ++ e_dbus_prefix (SOURCES_DBUS_SERVICE_NAME), + DBUS_OBJECT_PATH, + cancellable, &local_error); + +diff --git a/src/libedataserverui/e-credentials-prompter-impl-oauth2.c b/src/libedataserverui/e-credentials-prompter-impl-oauth2.c +index b82715917..183b6aa27 100644 +--- a/src/libedataserverui/e-credentials-prompter-impl-oauth2.c ++++ b/src/libedataserverui/e-credentials-prompter-impl-oauth2.c +@@ -23,6 +23,7 @@ + #include + + #include ++#include + + #include "libedataserverui-private.h" + #include "e-dbus-oauth2-response.h" +@@ -893,7 +894,7 @@ cpi_oauth2_maybe_prepare_oauth2_service (ECredentialsPrompterImplOAuth2 *prompte + + prompter_oauth2->priv->bus_owner_id = g_bus_own_name ( + G_BUS_TYPE_SESSION, +- OAUTH2_RESPONSE_DBUS_SERVICE_NAME, ++ e_dbus_prefix (OAUTH2_RESPONSE_DBUS_SERVICE_NAME), + G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE, + cpi_oauth2_bus_acquired_cb, + NULL, +diff --git a/src/modules/secret-monitor/module-secret-monitor.c b/src/modules/secret-monitor/module-secret-monitor.c +index 0eb21669d..5ec7e376c 100644 +--- a/src/modules/secret-monitor/module-secret-monitor.c ++++ b/src/modules/secret-monitor/module-secret-monitor.c +@@ -24,6 +24,8 @@ + + #include + ++#include ++ + /* Standard GObject macros */ + #define E_TYPE_SECRET_MONITOR \ + (e_secret_monitor_get_type ()) +@@ -57,12 +59,6 @@ struct _ESecretMonitorClass { + #define KEYRING_ITEM_ATTRIBUTE_ORIGIN "eds-origin" + #define KEYRING_ITEM_DISPLAY_FORMAT "Evolution Data Source '%s'" + +-#ifdef DBUS_SERVICES_PREFIX +-#define ORIGIN_KEY DBUS_SERVICES_PREFIX "." PACKAGE +-#else +-#define ORIGIN_KEY PACKAGE +-#endif +- + static SecretSchema password_schema = { + "org.gnome.Evolution.Data.Source", + SECRET_SCHEMA_DONT_MATCH_NAME, +@@ -110,7 +106,7 @@ secret_monitor_scan_secrets_thread (gpointer user_data) + server = E_SOURCE_REGISTRY_SERVER (user_data); + + attributes = g_hash_table_new (g_str_hash, g_str_equal); +- g_hash_table_insert (attributes, (gpointer) KEYRING_ITEM_ATTRIBUTE_ORIGIN, (gpointer) ORIGIN_KEY); ++ g_hash_table_insert (attributes, (gpointer) KEYRING_ITEM_ATTRIBUTE_ORIGIN, (gpointer) e_dbus_prefix (PACKAGE)); + + /* List all items under our custom SecretSchema. */ + list = secret_service_search_sync ( +diff --git a/src/services/evolution-alarm-notify/e-alarm-notify.c b/src/services/evolution-alarm-notify/e-alarm-notify.c +index a1116ec9b..1fa205366 100644 +--- a/src/services/evolution-alarm-notify/e-alarm-notify.c ++++ b/src/services/evolution-alarm-notify/e-alarm-notify.c +@@ -31,14 +31,11 @@ + + #include "libecal/libecal.h" + #include "libedataserverui/libedataserverui.h" ++#include "libedataserver/e-dbus-prefix.h" + + #include "e-alarm-notify.h" + +-#ifdef DBUS_SERVICES_PREFIX +-#define APPLICATION_ID DBUS_SERVICES_PREFIX "." "org.gnome.Evolution-alarm-notify" +-#else + #define APPLICATION_ID "org.gnome.Evolution-alarm-notify" +-#endif + + struct _EAlarmNotifyPrivate { + ESourceRegistry *registry; +@@ -1272,7 +1269,7 @@ e_alarm_notify_new (GCancellable *cancellable, + { + return g_initable_new ( + E_TYPE_ALARM_NOTIFY, cancellable, error, +- "application-id", APPLICATION_ID, ++ "application-id", e_dbus_prefix (APPLICATION_ID), + #if GLIB_CHECK_VERSION(2, 60, 0) + "flags", G_APPLICATION_ALLOW_REPLACEMENT, + #endif +diff --git a/src/tools/CMakeLists.txt b/src/tools/CMakeLists.txt +index e8c70b298..cdcd4971d 100644 +--- a/src/tools/CMakeLists.txt ++++ b/src/tools/CMakeLists.txt +@@ -1,3 +1,10 @@ + add_subdirectory(addressbook-export) + add_subdirectory(list-sources) + add_subdirectory(oauth2-handler) ++ ++configure_file(set-dbus-prefix.in set-dbus-prefix @ONLY) ++ ++install(FILES ${CMAKE_CURRENT_BINARY_DIR}/set-dbus-prefix ++ DESTINATION ${privlibexecdir} ++ PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE ++) +diff --git a/src/tools/oauth2-handler/CMakeLists.txt b/src/tools/oauth2-handler/CMakeLists.txt +index 643733d89..0f154c9d0 100644 +--- a/src/tools/oauth2-handler/CMakeLists.txt ++++ b/src/tools/oauth2-handler/CMakeLists.txt +@@ -1,4 +1,5 @@ + set(DEPENDENCIES ++ edataserver + edbus-private + ) + +diff --git a/src/tools/oauth2-handler/oauth2-handler.c b/src/tools/oauth2-handler/oauth2-handler.c +index 952d16fb1..7622293c7 100644 +--- a/src/tools/oauth2-handler/oauth2-handler.c ++++ b/src/tools/oauth2-handler/oauth2-handler.c +@@ -9,6 +9,8 @@ + #include + #include + ++#include ++ + #include "e-dbus-oauth2-response.h" + + static const gchar *glob_uri = NULL; +@@ -73,7 +75,7 @@ got_bus_cb (GObject *source_object, + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS | + G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, +- OAUTH2_RESPONSE_DBUS_SERVICE_NAME, ++ e_dbus_prefix (OAUTH2_RESPONSE_DBUS_SERVICE_NAME), + "/org/gnome/evolution/dataserver/OAuth2Response", + NULL, + proxy_created_cb, +diff --git a/src/tools/set-dbus-prefix.in b/src/tools/set-dbus-prefix.in +new file mode 100644 +index 000000000..2e79e4855 +--- /dev/null ++++ b/src/tools/set-dbus-prefix.in +@@ -0,0 +1,37 @@ ++#!/bin/sh ++ ++set -ex ++ ++dbus_services_prefix="$1" ++ ++mkdir -p "@SYSCONF_INSTALL_DIR@/evolution-data-server" ++echo "$dbus_services_prefix" > "@SYSCONF_INSTALL_DIR@/evolution-data-server/dbus-prefix" ++ ++edit_file() { ++ sed "s/org.gnome.evolution/${dbus_services_prefix}.org.gnome.evolution/" "$1" > "$1.new" && mv "$1.new" "$1" ++} ++ ++SYSTEMD_SERVICE_FILES=" ++evolution-addressbook-factory.service ++evolution-calendar-factory.service ++evolution-source-registry.service ++evolution-user-prompter.service ++" ++ ++if [ "@WITH_SYSTEMD_USER_UNITS@" = ON ] ; then ++ for f in $SYSTEMD_SERVICE_FILES ; do ++ edit_file "@WITH_SYSTEMDUSERUNITDIR@/$f" ++ done ++fi ++ ++DBUS_SERVICE_FILES=" ++@ADDRESS_BOOK_DBUS_SERVICE_NAME@.service ++@CALENDAR_DBUS_SERVICE_NAME@.service ++@SOURCES_DBUS_SERVICE_NAME@.service ++@USER_PROMPTER_DBUS_SERVICE_NAME@.service ++" ++ ++for f in $DBUS_SERVICE_FILES ; do ++ edit_file "@WITH_DBUS_SERVICE_DIR@/$f" ++ mv "@WITH_DBUS_SERVICE_DIR@/$f" "@WITH_DBUS_SERVICE_DIR@/${dbus_services_prefix}.$f" ++done +-- +2.41.0 + diff --git a/SOURCES/evolution-data-server-3.40.4-caldav-crash.patch b/SOURCES/evolution-data-server-3.40.4-caldav-crash.patch deleted file mode 100644 index 7db499b..0000000 --- a/SOURCES/evolution-data-server-3.40.4-caldav-crash.patch +++ /dev/null @@ -1,36 +0,0 @@ -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/SOURCES/evolution-data-server-3.40.4-google-contacts-to-carddav.patch b/SOURCES/evolution-data-server-3.40.4-google-contacts-to-carddav.patch deleted file mode 100644 index 5fc068b..0000000 --- a/SOURCES/evolution-data-server-3.40.4-google-contacts-to-carddav.patch +++ /dev/null @@ -1,4025 +0,0 @@ -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/SOURCES/evolution-data-server-3.40.4-google-oauth2.patch b/SOURCES/evolution-data-server-3.40.4-google-oauth2.patch deleted file mode 100644 index d812318..0000000 --- a/SOURCES/evolution-data-server-3.40.4-google-oauth2.patch +++ /dev/null @@ -1,116 +0,0 @@ -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" - - /* https://developers.google.com/identity/protocols/OAuth2InstalledApp */ -+/* https://developers.google.com/identity/protocols/oauth2/native-app */ - - /* Forward Declarations */ - static void e_oauth2_service_google_oauth2_service_init (EOAuth2ServiceInterface *iface); -@@ -122,14 +123,60 @@ static const gchar * - eos_google_get_authentication_uri (EOAuth2Service *service, - ESource *source) - { -- return "https://accounts.google.com/o/oauth2/auth"; -+ return "https://accounts.google.com/o/oauth2/v2/auth"; - } - - static const gchar * - eos_google_get_refresh_uri (EOAuth2Service *service, - ESource *source) - { -- return "https://www.googleapis.com/oauth2/v3/token"; -+ return "https://oauth2.googleapis.com/token"; -+} -+ -+static const gchar * -+eos_google_get_redirect_uri (EOAuth2Service *service, -+ ESource *source) -+{ -+ G_LOCK_DEFINE_STATIC (redirect_uri); -+ const gchar *key_name = "oauth2-google-redirect-uri"; -+ gchar *value; -+ -+ G_LOCK (redirect_uri); -+ -+ value = g_object_get_data (G_OBJECT (service), key_name); -+ if (!value) { -+ const gchar *client_id = eos_google_get_client_id (service, source); -+ -+ if (client_id) { -+ GPtrArray *array; -+ gchar **strv; -+ gchar *joinstr; -+ guint ii; -+ -+ strv = g_strsplit (client_id, ".", -1); -+ array = g_ptr_array_new (); -+ -+ for (ii = 0; strv[ii]; ii++) { -+ g_ptr_array_insert (array, 0, strv[ii]); -+ } -+ -+ g_ptr_array_add (array, NULL); -+ -+ joinstr = g_strjoinv (".", (gchar **) array->pdata); -+ /* Use reverse-DNS of the client ID with the below path */ -+ value = g_strconcat (joinstr, ":/oauth2redirect", NULL); -+ -+ g_ptr_array_free (array, TRUE); -+ g_strfreev (strv); -+ g_free (joinstr); -+ -+ g_object_set_data_full (G_OBJECT (service), key_name, value, g_free); -+ } -+ } -+ -+ G_UNLOCK (redirect_uri); -+ -+ return value; - } - - static void -@@ -191,13 +238,13 @@ eos_google_extract_authorization_code (EOAuth2Service *service, - - params = soup_form_decode (query); - if (params) { -- const gchar *response; -+ const gchar *code; - -- response = g_hash_table_lookup (params, "response"); -- if (response && g_ascii_strncasecmp (response, "code=", 5) == 0) { -- *out_authorization_code = g_strdup (response + 5); -+ code = g_hash_table_lookup (params, "code"); -+ if (code && *code) { -+ *out_authorization_code = g_strdup (code); - known = TRUE; -- } else if (response && g_ascii_strncasecmp (response, "error", 5) == 0) { -+ } else if (g_hash_table_lookup (params, "error")) { - known = TRUE; - } - -@@ -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; -+ iface->get_redirect_uri = eos_google_get_redirect_uri; - 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/SOURCES/evolution-data-server-3.40.4-icalcompiter.patch b/SOURCES/evolution-data-server-3.40.4-icalcompiter.patch deleted file mode 100644 index e3707b9..0000000 --- a/SOURCES/evolution-data-server-3.40.4-icalcompiter.patch +++ /dev/null @@ -1,49 +0,0 @@ -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/SOURCES/evolution-data-server-3.40.4-secret-monitor-warnings.patch b/SOURCES/evolution-data-server-3.40.4-secret-monitor-warnings.patch deleted file mode 100644 index 4c4b91e..0000000 --- a/SOURCES/evolution-data-server-3.40.4-secret-monitor-warnings.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff -up evolution-data-server-3.28.5/src/modules/secret-monitor/module-secret-monitor.c.secret-monitor-warnings evolution-data-server-3.28.5/src/modules/secret-monitor/module-secret-monitor.c ---- evolution-data-server-3.28.5/src/modules/secret-monitor/module-secret-monitor.c.secret-monitor-warnings 2018-07-30 15:17:06.000000000 +0200 -+++ evolution-data-server-3.28.5/src/modules/secret-monitor/module-secret-monitor.c 2021-11-22 12:52:08.683986536 +0100 -@@ -167,7 +167,7 @@ secret_monitor_scan_secrets_thread (gpoi - g_list_free_full (list, (GDestroyNotify) g_object_unref); - - if (local_error != NULL) { -- g_warning ("%s: %s", G_STRFUNC, local_error->message); -+ e_source_registry_debug_print ("%s: %s", G_STRFUNC, local_error->message); - g_error_free (local_error); - } - -@@ -206,7 +206,7 @@ secret_monitor_scan_secrets_timeout_cb ( - g_thread_unref (thread); - - if (local_error != NULL) { -- g_warning ("%s: %s", G_STRFUNC, local_error->message); -+ e_source_registry_debug_print ("%s: %s", G_STRFUNC, local_error->message); - g_error_free (local_error); - g_object_unref (server); - } diff --git a/SOURCES/evolution-data-server-3.54.2.tar.xz b/SOURCES/evolution-data-server-3.54.2.tar.xz new file mode 100644 index 0000000..a529ff3 Binary files /dev/null and b/SOURCES/evolution-data-server-3.54.2.tar.xz differ diff --git a/SPECS/evolution-data-server.spec b/SPECS/evolution-data-server.spec index 30ebb48..5b7d894 100644 --- a/SPECS/evolution-data-server.spec +++ b/SPECS/evolution-data-server.spec @@ -5,8 +5,13 @@ %define krb5_support 1 %define largefile_support 1 +# disable for i686, because libphonenumber 8.12.57 is not built for it +%ifarch i686 +%global phonenum_support 0 +%else # enabled only for Fedora %global phonenum_support 0%{?fedora} +%endif # Coverity scan can override this to 0, to skip checking in gtk-doc generated code %{!?with_docs: %global with_docs 1} @@ -15,21 +20,23 @@ %global with_docs 0 %endif -%define glib2_version 2.46 -%define gtk3_version 3.16 -%define gcr_version 3.4 +%{!?with_webkitgtk: %global with_webkitgtk (%{undefined rhel} || 0%{?rhel} < 10)} + +%define glib2_version 2.68 +%define gtk3_version 3.20 +%define gtk4_version 4.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.15.1 -%define libgweather_version 3.10 -%define libical_version 3.0.7 -%define libsoup_version 2.58 +%define libgweather_version 4.0 +%define libical_version 3.0.16 +%define libsoup_version 3.1.1 %define nss_version 3.14 %define sqlite_version 3.7.17 -%define webkit2gtk_version 2.28.0 +%define webkit2gtk_version 2.34.0 +%define webkit2gtk4_version 2.36.0 %define json_glib_version 1.0.4 +%define uuid_version 2.0 %define credential_modules_dir %{_libdir}/evolution-data-server/credential-modules %define camel_provider_dir %{_libdir}/evolution-data-server/camel-providers @@ -43,28 +50,21 @@ %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.40.4 -Release: 6%{?dist} +Version: 3.54.2 +Release: 1%{?dist} Summary: Backend data server for Evolution -License: LGPLv2+ -URL: https://wiki.gnome.org/Apps/Evolution -Source: http://download.gnome.org/sources/%{name}/3.40/%{name}-%{version}.tar.xz +License: LGPL-2.0-or-later +URL: https://gitlab.gnome.org/GNOME/evolution/-/wikis/home +Source: http://download.gnome.org/sources/%{name}/3.54/%{name}-%{version}.tar.xz + +# 0-99: General patches -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 +# 100-199: Flatpak-specific patches +# https://gitlab.gnome.org/GNOME/evolution-data-server/-/merge_requests/144 +Patch100: Make-DBUS_SERVICES_PREFIX-runtime-configurable.patch Provides: evolution-webcal = %{version} Obsoletes: evolution-webcal < 2.24.0 @@ -91,29 +91,30 @@ BuildRequires: gperf %if %{with_docs} BuildRequires: gtk-doc >= %{gtk_doc_version} %endif -BuildRequires: intltool >= %{intltool_version} -BuildRequires: make +BuildRequires: ninja-build BuildRequires: vala BuildRequires: systemd -BuildRequires: pkgconfig(gcr-3) >= %{gcr_version} -BuildRequires: pkgconfig(gcr-base-3) >= %{gcr_version} BuildRequires: pkgconfig(gio-2.0) >= %{glib2_version} BuildRequires: pkgconfig(gio-unix-2.0) >= %{glib2_version} BuildRequires: pkgconfig(gmodule-2.0) >= %{glib2_version} BuildRequires: pkgconfig(icu-i18n) BuildRequires: pkgconfig(gtk+-3.0) >= %{gtk3_version} +BuildRequires: pkgconfig(gtk4) >= %{gtk4_version} BuildRequires: pkgconfig(goa-1.0) >= %{goa_version} -BuildRequires: pkgconfig(libgdata) >= %{libgdata_version} -BuildRequires: pkgconfig(gweather-3.0) >= %{libgweather_version} +BuildRequires: pkgconfig(gweather4) >= %{libgweather_version} BuildRequires: pkgconfig(libical-glib) >= %{libical_version} BuildRequires: pkgconfig(libsecret-unstable) >= %{libsecret_version} -BuildRequires: pkgconfig(libsoup-2.4) >= %{libsoup_version} +BuildRequires: pkgconfig(libsoup-3.0) >= %{libsoup_version} BuildRequires: pkgconfig(libxml-2.0) BuildRequires: pkgconfig(nspr) BuildRequires: pkgconfig(nss) >= %{nss_version} BuildRequires: pkgconfig(sqlite3) >= %{sqlite_version} -BuildRequires: pkgconfig(webkit2gtk-4.0) >= %{webkit2gtk_version} +BuildRequires: pkgconfig(uuid) >= %{uuid_version} +%if %{with_webkitgtk} +BuildRequires: pkgconfig(webkit2gtk-4.1) >= %{webkit2gtk_version} +BuildRequires: pkgconfig(webkitgtk-6.0) >= %{webkit2gtk4_version} +%endif BuildRequires: pkgconfig(json-glib-1.0) >= %{json_glib_version} BuildRequires: pkgconfig(libcanberra-gtk3) @@ -132,8 +133,12 @@ BuildRequires: krb5-devel >= 1.11 BuildRequires: libphonenumber-devel BuildRequires: protobuf-devel BuildRequires: boost-devel +BuildRequires: abseil-cpp-devel %endif +# libical 3.0.16 added new API, this ensures to bring it in +Requires: libical-glib >= %{libical_version} + %description The %{name} package provides a unified backend for programs that work with contacts, tasks, and calendar information. @@ -146,13 +151,15 @@ Summary: Development files for building against %{name} 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(gweather4) >= %{libgweather_version} Requires: pkgconfig(libical-glib) >= %{libical_version} Requires: pkgconfig(libsecret-unstable) >= %{libsecret_version} -Requires: pkgconfig(libsoup-2.4) >= %{libsoup_version} +Requires: pkgconfig(libsoup-3.0) >= %{libsoup_version} Requires: pkgconfig(sqlite3) >= %{sqlite_version} -Requires: pkgconfig(webkit2gtk-4.0) >= %{webkit2gtk_version} +%if %{with_webkitgtk} +Requires: pkgconfig(webkit2gtk-4.1) >= %{webkit2gtk_version} +Requires: pkgconfig(webkitgtk-6.0) >= %{webkit2gtk4_version} +%endif Requires: pkgconfig(json-glib-1.0) >= %{json_glib_version} %description devel @@ -195,7 +202,15 @@ The %{name}-tests package contains tests that can be used to verify the functionality of the installed %{name} package. %prep -%autosetup -p1 -S gendiff +%autosetup -p1 -S gendiff -N + +# General patches +%autopatch -p1 -m 0 -M 99 + +# Flatpak-specific patches +%if 0%{?flatpak} +%autopatch -p1 -m 100 -M 199 +%endif %build @@ -251,6 +266,12 @@ fi %define gtkdoc_flags -DENABLE_GTK_DOC=OFF %endif +%if %{with_webkitgtk} +%define webkitgtk_flags -DENABLE_OAUTH2_WEBKITGTK=ON -DENABLE_OAUTH2_WEBKITGTK4=ON +%else +%define webkitgtk_flags -DENABLE_OAUTH2_WEBKITGTK=OFF -DENABLE_OAUTH2_WEBKITGTK4=OFF +%endif + if ! pkg-config --exists nss; then echo "Unable to find suitable version of nss to use!" exit 1 @@ -259,19 +280,16 @@ fi export CPPFLAGS="-I%{_includedir}/et" export CFLAGS="$RPM_OPT_FLAGS -DLDAP_DEPRECATED -fPIC -I%{_includedir}/et -Wno-deprecated-declarations" -%cmake -G "Unix Makefiles" \ +%cmake -G Ninja \ -DENABLE_MAINTAINER_MODE=OFF \ - -DWITH_LIBDB=OFF \ -DENABLE_FILE_LOCKING=fcntl \ -DENABLE_DOT_LOCKING=OFF \ -DENABLE_INTROSPECTION=ON \ -DENABLE_VALA_BINDINGS=ON \ -DENABLE_INSTALLED_TESTS=ON \ + -DWITH_LIBDB=OFF \ -DWITH_SYSTEMDUSERUNITDIR=%{_userunitdir} \ - %if "%{?_eds_dbus_services_prefix}" != "" - -DDBUS_SERVICES_PREFIX=%{?_eds_dbus_services_prefix} \ - %endif - %ldap_flags %krb5_flags %ssl_flags \ + %ldap_flags %krb5_flags %ssl_flags %webkitgtk_flags \ %largefile_flags %gtkdoc_flags %phonenum_flags \ %{nil} @@ -282,6 +300,7 @@ export CFLAGS="$RPM_OPT_FLAGS -DLDAP_DEPRECATED -fPIC -I%{_includedir}/et -Wno-d # make sure the directory exists, because it's owned by eds mkdir $RPM_BUILD_ROOT/%{uimodules_dir} || : +mkdir $RPM_BUILD_ROOT/%{credential_modules_dir} || : # give the libraries some executable bits find $RPM_BUILD_ROOT -name '*.so.*' -exec chmod +x {} \; @@ -291,24 +310,26 @@ find $RPM_BUILD_ROOT -name '*.so.*' -exec chmod +x {} \; %files %license COPYING %doc README ChangeLog NEWS -%{_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}/libcamel-1.2.so.64 +%{_libdir}/libcamel-1.2.so.64.0.0 +%{_libdir}/libebackend-1.2.so.11 +%{_libdir}/libebackend-1.2.so.11.0.0 +%{_libdir}/libebook-1.2.so.21 +%{_libdir}/libebook-1.2.so.21.1.3 +%{_libdir}/libebook-contacts-1.2.so.4 +%{_libdir}/libebook-contacts-1.2.so.4.0.0 +%{_libdir}/libecal-2.0.so.3 +%{_libdir}/libecal-2.0.so.3.0.0 +%{_libdir}/libedata-book-1.2.so.27 +%{_libdir}/libedata-book-1.2.so.27.0.0 +%{_libdir}/libedata-cal-2.0.so.2 +%{_libdir}/libedata-cal-2.0.so.2.0.0 +%{_libdir}/libedataserver-1.2.so.27 +%{_libdir}/libedataserver-1.2.so.27.0.0 +%{_libdir}/libedataserverui-1.2.so.4 +%{_libdir}/libedataserverui-1.2.so.4.0.0 +%{_libdir}/libedataserverui4-1.0.so.0 +%{_libdir}/libedataserverui4-1.0.so.0.0.0 %{_libdir}/girepository-1.0/Camel-1.2.typelib %{_libdir}/girepository-1.0/EBackend-1.2.typelib @@ -319,6 +340,7 @@ find $RPM_BUILD_ROOT -name '*.so.*' -exec chmod +x {} \; %{_libdir}/girepository-1.0/EDataCal-2.0.typelib %{_libdir}/girepository-1.0/EDataServer-1.2.typelib %{_libdir}/girepository-1.0/EDataServerUI-1.2.typelib +%{_libdir}/girepository-1.0/EDataServerUI4-1.0.typelib %{_libexecdir}/camel-gpg-photo-saver %{_libexecdir}/camel-index-control-1.2 @@ -334,10 +356,15 @@ find $RPM_BUILD_ROOT -name '*.so.*' -exec chmod +x {} \; %dir %{_libexecdir}/evolution-data-server %{_libexecdir}/evolution-data-server/addressbook-export %{_libexecdir}/evolution-data-server/evolution-alarm-notify +%{_libexecdir}/evolution-data-server/evolution-oauth2-handler %{_libexecdir}/evolution-data-server/list-sources +%if 0%{?flatpak} +%{_libexecdir}/evolution-data-server/set-dbus-prefix +%endif %{_sysconfdir}/xdg/autostart/org.gnome.Evolution-alarm-notify.desktop %{_datadir}/applications/org.gnome.Evolution-alarm-notify.desktop +%{_datadir}/applications/org.gnome.evolution-data-server.OAuth2-handler.desktop # GSettings schemas: %{_datadir}/GConf/gsettings/evolution-data-server.convert @@ -354,6 +381,7 @@ find $RPM_BUILD_ROOT -name '*.so.*' -exec chmod +x {} \; %{_datadir}/dbus-1/services/%{dbus_service_name_sources}.service %{_datadir}/dbus-1/services/%{dbus_service_name_user_prompter}.service %{_datadir}/pixmaps/evolution-data-server +%{_datadir}/icons/hicolor/scalable/apps/org.gnome.Evolution-alarm-notify.svg %{_userunitdir}/evolution-addressbook-factory.service %{_userunitdir}/evolution-calendar-factory.service @@ -422,6 +450,7 @@ find $RPM_BUILD_ROOT -name '*.so.*' -exec chmod +x {} \; %{_libdir}/libedata-cal-2.0.so %{_libdir}/libedataserver-1.2.so %{_libdir}/libedataserverui-1.2.so +%{_libdir}/libedataserverui4-1.0.so %{_libdir}/pkgconfig/camel-1.2.pc %{_libdir}/pkgconfig/evolution-data-server-1.2.pc %{_libdir}/pkgconfig/libebackend-1.2.pc @@ -432,6 +461,7 @@ find $RPM_BUILD_ROOT -name '*.so.*' -exec chmod +x {} \; %{_libdir}/pkgconfig/libedata-cal-2.0.pc %{_libdir}/pkgconfig/libedataserver-1.2.pc %{_libdir}/pkgconfig/libedataserverui-1.2.pc +%{_libdir}/pkgconfig/libedataserverui4-1.0.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 @@ -441,6 +471,7 @@ find $RPM_BUILD_ROOT -name '*.so.*' -exec chmod +x {} \; %{_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}/gir-1.0/EDataServerUI4-1.0.gir %{_datadir}/vala/vapi/camel-1.2.deps %{_datadir}/vala/vapi/camel-1.2.vapi %{_datadir}/vala/vapi/libebackend-1.2.deps @@ -459,6 +490,8 @@ find $RPM_BUILD_ROOT -name '*.so.*' -exec chmod +x {} \; %{_datadir}/vala/vapi/libedataserver-1.2.vapi %{_datadir}/vala/vapi/libedataserverui-1.2.deps %{_datadir}/vala/vapi/libedataserverui-1.2.vapi +%{_datadir}/vala/vapi/libedataserverui4-1.0.deps +%{_datadir}/vala/vapi/libedataserverui4-1.0.vapi %files langpacks -f %{name}.lang @@ -480,36 +513,225 @@ find $RPM_BUILD_ROOT -name '*.so.*' -exec chmod +x {} \; %{_datadir}/installed-tests %changelog -* Tue May 24 2022 Milan Crha - 3.40.4-6 -- Resolves: #2089902 (CalDAV: Crash on calendar update) +* Wed Dec 25 2024 Eduard Basov - 3.54.2-1 +- Rebuilt for MSVSphere 10 + +* Fri Nov 22 2024 Milan Crha - 3.54.2-1 +- Update to 3.54.2 + +* Fri Oct 18 2024 Milan Crha - 3.54.1-1 +- Update to 3.54.1 + +* Fri Sep 13 2024 Milan Crha - 3.54.0-1 +- Update to 3.54.0 + +* Fri Aug 30 2024 Milan Crha - 3.53.3-1 +- Update to 3.53.3 + +* Fri Aug 02 2024 Milan Crha - 3.53.2-1 +- Update to 3.53.2 + +* Wed Jul 17 2024 Fedora Release Engineering - 3.53.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild + +* Fri Jun 28 2024 Milan Crha - 3.53.1-1 +- Update to 3.53.1 + +* Fri May 24 2024 Milan Crha - 3.52.2-1 +- Update to 3.52.2 + +* Fri Apr 19 2024 Milan Crha - 3.52.1-1 +- Update to 3.52.1 + +* Fri Mar 15 2024 Milan Crha - 3.52.0-1 +- Update to 3.52.0 + +* Fri Mar 01 2024 Milan Crha - 3.51.3-1 +- Update to 3.51.3 + +* Fri Mar 01 2024 Owen Taylor - 3.51.2-2 +- Add patch to allow reconfiguring the dbus-prefix without rebuilding; + this is needed to make EDS work with the new Flatpak infrastructure. +- Remove support _eds_dbus_services_prefix - this was only used by + F38 and earlier Flatpak builds. + +* Fri Feb 09 2024 Milan Crha - 3.51.2-1 +- Update to 3.51.2 + +* Wed Jan 31 2024 Pete Walter - 3.51.1-4 +- Rebuild for ICU 74 + +* Wed Jan 24 2024 Fedora Release Engineering - 3.51.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Fri Jan 19 2024 Fedora Release Engineering - 3.51.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Fri Jan 05 2024 Milan Crha - 3.51.1-1 +- Update to 3.51.1 + +* Tue Dec 19 2023 Florian Weimer - 3.50.2-2 +- Backport upstream patch to fix C issue in CMake probing + +* Fri Dec 01 2023 Milan Crha - 3.50.2-1 +- Update to 3.50.2 + +* Fri Oct 20 2023 Milan Crha - 3.50.1-1 +- Update to 3.50.1 + +* Fri Sep 15 2023 Milan Crha - 3.50.0-1 +- Update to 3.50.0 + +* Fri Sep 01 2023 Milan Crha - 3.49.3-1 +- Update to 3.49.3 -* Wed May 04 2022 Milan Crha - 3.40.4-5 -- Resolves: #2081747 (Backport patch for Google OAuth2 change) +* Fri Aug 04 2023 Milan Crha - 3.49.2-1 +- Update to 3.49.2 -* Tue Apr 05 2022 Milan Crha - 3.40.4-4 -- Resolves: #2071893 (Addressbook: Switch from GData Contacts API to CardDAV API for Google books) +* Wed Jul 19 2023 Fedora Release Engineering - 3.49.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild -* Mon Nov 22 2021 Milan Crha - 3.40.4-3 -- Resolves: #2025480 (secret-monitor: Turn runtime warnings into debug prints) +* Tue Jul 11 2023 František Zatloukal - 3.49.1-2 +- Rebuilt for ICU 73.2 -* Mon Nov 08 2021 Milan Crha - 3.40.4-2 -- Resolves: #2021055 (Add patch to correct ICalCompIter component's usage) +* Fri Jun 30 2023 Milan Crha - 3.49.1-1 +- Update to 3.49.1 -* Fri Aug 13 2021 Milan Crha - 3.40.4-1 -- Related: #1992450 (Update to 3.40.4) +* Fri Jun 02 2023 Milan Crha - 3.48.3-1 +- Update to 3.48.3 -* Mon Aug 09 2021 Mohan Boddu - 3.40.3-2 -- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags - Related: rhbz#1991688 +* Fri May 26 2023 Milan Crha - 3.48.2-1 +- Update to 3.48.2 -* Mon Jul 12 2021 Milan Crha - 3.40.3-1 -- Related: #1981215 (Update to 3.40.3) +* Wed May 17 2023 Sérgio Basto - 3.48.1-2 +- Rebuild for libphonenumber-8.13.x + +* Fri Apr 21 2023 Milan Crha - 3.48.1-1 +- Update to 3.48.1 + +* Fri Mar 17 2023 Milan Crha - 3.48.0-1 +- Update to 3.48.0 + +* Thu Mar 09 2023 Michael Catanzaro - 3.47.3-2 +- Build against WebKitGTK 2.39.91 + +* Fri Mar 03 2023 Milan Crha - 3.47.3-1 +- Update to 3.47.3 + +* Wed Feb 22 2023 Michael Catanzaro - 3.47.2-2 +- Build against WebKitGTK 2.39.90 + +* Fri Feb 10 2023 Milan Crha - 3.47.2-1 +- Update to 3.47.2 + +* Wed Feb 01 2023 Michael Catanzaro - 3.47.1-4 +- Build against WebKitGTK 2.39.6 + +* Fri Jan 20 2023 Michael Catanzaro - 3.47.1-3 +- Build against WebKitGTK 2.39.5 + +* Thu Jan 19 2023 Fedora Release Engineering - 3.47.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + +* Fri Jan 06 2023 Milan Crha - 3.47.1-1 +- Update to 3.47.1 +- Require libical 3.0.16 for added new API + +* Sat Dec 31 2022 Pete Walter - 3.46.2-3 +- Rebuild for ICU 72 + +* Mon Dec 05 2022 Michael Catanzaro - 3.46.2-2 +- Build against webkitgtk-6.0 + +* Fri Dec 02 2022 Milan Crha - 3.46.2-1 +- Update to 3.46.2 + +* Fri Oct 21 2022 Milan Crha - 3.46.1-1 +- Update to 3.46.1 + +* Fri Sep 16 2022 Milan Crha - 3.46.0-1 +- Update to 3.46.0 + +* Fri Sep 02 2022 Milan Crha - 3.45.3-1 +- Update to 3.45.3 + +* Fri Aug 05 2022 Milan Crha - 3.45.2-1 +- Update to 3.45.2 + +* Mon Aug 01 2022 Frantisek Zatloukal - 3.45.1-3 +- Rebuilt for ICU 71.1 + +* Thu Jul 21 2022 Fedora Release Engineering - 3.45.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Tue Jul 19 2022 Milan Crha - 3.45.1-1 +- Update to 3.45.1 + +* Mon Jul 18 2022 Milan Crha - 3.44.3-2 +- Add patch for RH bug #2107751 (glib2's G_TLS_CERTIFICATE_FLAGS_NONE causes infinite loop) + +* Fri Jul 01 2022 Milan Crha - 3.44.3-1 +- Update to 3.44.3 + +* Fri May 27 2022 Milan Crha - 3.44.2-1 +- Update to 3.44.2 + +* Fri Apr 22 2022 Milan Crha - 3.44.1-1 +- Update to 3.44.1 + +* Fri Mar 18 2022 Milan Crha - 3.44.0-1 +- Update to 3.44.0 + +* Fri Mar 04 2022 Milan Crha - 3.43.3-1 +- Update to 3.43.3 + +* Fri Feb 11 2022 Milan Crha - 3.43.2-1 +- Update to 3.43.2 + +* Thu Jan 20 2022 Fedora Release Engineering - 3.43.1.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + +* Fri Jan 07 2022 Milan Crha - 3.43.1.1-1 +- Update to 3.43.1.1 + +* Fri Dec 03 2021 Milan Crha - 3.42.2-1 +- Update to 3.42.2 + +* Sat Nov 06 2021 Adrian Reber - 3.42.1-3 +- Rebuilt for protobuf 3.19.0 + +* Fri Nov 05 2021 Milan Crha - 3.42.1-2 +- Add patch to correct ICalCompIter component's usage + +* Fri Oct 29 2021 Milan Crha - 3.42.1-1 +- Update to 3.42.1 + +* Thu Oct 28 2021 Adam Williamson - 3.42.0-2 +- Rebuild with newer protobuf and libphonenumber + +* Fri Sep 17 2021 Milan Crha - 3.42.0-1 +- Update to 3.42.0 + +* Fri Sep 03 2021 Milan Crha - 3.41.3-1 +- Update to 3.41.3 + +* Fri Aug 13 2021 Milan Crha - 3.41.2-1 +- Update to 3.41.2 + +* Wed Jul 21 2021 Fedora Release Engineering - 3.41.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Fri Jul 09 2021 Milan Crha - 3.41.1-1 +- Update to 3.41.1 * Fri Jun 04 2021 Milan Crha - 3.40.2-1 -- Related: #1967855 (Update to 3.40.2) +- Update to 3.40.2 + +* Wed May 19 2021 Pete Walter - 3.40.1-2 +- Rebuild for ICU 69 -* Thu Apr 15 2021 Mohan Boddu - 3.40.0-4 -- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937 +* Fri Apr 30 2021 Milan Crha - 3.40.1-1 +- Update to 3.40.1 * Mon Mar 29 2021 Milan Crha - 3.40.0-3 - Resolves: #1943818 (ESourceWebDAV: Fallback to SHA1 on SSL trust verification if needed)