From 7b6342fdc7cb7a3dbe8c84447da3656b76c5c41a Mon Sep 17 00:00:00 2001 From: Dmitry Samoylik Date: Wed, 12 Feb 2025 19:01:48 +0300 Subject: [PATCH] Added yandex backend support prebuild --- ...dded-yandex-backend-support-prebuild.patch | 1511 +++++++++++++++++ SPECS/evolution-data-server.spec | 12 +- 2 files changed, 1522 insertions(+), 1 deletion(-) create mode 100644 SOURCES/0001-Added-yandex-backend-support-prebuild.patch diff --git a/SOURCES/0001-Added-yandex-backend-support-prebuild.patch b/SOURCES/0001-Added-yandex-backend-support-prebuild.patch new file mode 100644 index 0000000..5707a59 --- /dev/null +++ b/SOURCES/0001-Added-yandex-backend-support-prebuild.patch @@ -0,0 +1,1511 @@ +From c3ac28fb1425d455f0638157a1e397284fbac782 Mon Sep 17 00:00:00 2001 +From: Dmitry Samoylik +Date: Tue, 11 Feb 2025 11:39:55 +0300 +Subject: [PATCH] Added yandex backend support prebuild + +--- + CMakeLists.txt | 11 + + config.h.in | 6 + + data/CMakeLists.txt | 26 + + ...gnome.evolution-data-server.gschema.xml.in | 10 + + po/POTFILES.in | 3 + + src/camel/CMakeLists.txt | 2 + + src/camel/camel-autocleanups.h | 1 + + src/camel/camel-sasl-xoauth2-yandex.c | 44 ++ + src/camel/camel-sasl-xoauth2-yandex.h | 63 ++ + src/camel/camel-sasl.c | 2 + + src/camel/camel.h | 1 + + src/libebackend/e-webdav-collection-backend.c | 2 +- + src/libedataserver/CMakeLists.txt | 2 + + .../e-dataserver-autocleanups.h | 1 + + src/libedataserver/e-oauth2-service-yandex.c | 214 ++++++ + src/libedataserver/e-oauth2-service-yandex.h | 62 ++ + src/libedataserver/e-oauth2-services.c | 2 + + src/libedataserver/e-soup-auth-bearer.c | 22 +- + src/libedataserver/e-soup-auth-bearer.h | 4 + + src/libedataserver/e-soup-session.c | 21 + + src/libedataserver/libedataserver.h | 1 + + src/modules/CMakeLists.txt | 1 + + .../module-gnome-online-accounts.c | 3 + + src/modules/yandex-backend/CMakeLists.txt | 17 + + .../yandex-backend/module-yandex-backend.c | 619 ++++++++++++++++++ + 25 files changed, 1138 insertions(+), 2 deletions(-) + create mode 100644 src/camel/camel-sasl-xoauth2-yandex.c + create mode 100644 src/camel/camel-sasl-xoauth2-yandex.h + create mode 100644 src/libedataserver/e-oauth2-service-yandex.c + create mode 100644 src/libedataserver/e-oauth2-service-yandex.h + create mode 100644 src/modules/yandex-backend/CMakeLists.txt + create mode 100644 src/modules/yandex-backend/module-yandex-backend.c + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 31c4584..6303e34 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -477,6 +477,17 @@ if(WITH_YAHOO_CLIENT_SECRET STREQUAL "") + set(WITH_YAHOO_CLIENT_SECRET "|c3UmdHkmcXl5JCR3dXQlI3UleHYkcyN3IyR1d3YhcXN0cSN5IiNwIkA=|") + endif(WITH_YAHOO_CLIENT_SECRET STREQUAL "") + ++add_printable_variable(WITH_YANDEX_CLIENT_ID "Yandex OAuth 2.0 client id" "") ++add_printable_variable(WITH_YANDEX_CLIENT_SECRET "Yandex OAuth 2.0 client secret" "") ++ ++if(WITH_YANDEX_CLIENT_ID STREQUAL "") ++ set(WITH_YANDEX_CLIENT_ID "aab3f89a0d504003bfa3bb5326f68575") ++endif(WITH_YANDEX_CLIENT_ID STREQUAL "") ++ ++if(WITH_YANDEX_CLIENT_SECRET STREQUAL "") ++ set(WITH_YANDEX_CLIENT_SECRET "4e6f4755f2ec457e9a80f0f43683fc32") ++endif(WITH_YANDEX_CLIENT_SECRET STREQUAL "") ++ + # ****************************************** + # Check whether to build examples/demos + # ****************************************** +diff --git a/config.h.in b/config.h.in +index 4a295dc..ce721ad 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -57,6 +57,12 @@ + /* Define Yahoo! OAuth 2.0 Client Secret to use */ + #define YAHOO_CLIENT_SECRET "@WITH_YAHOO_CLIENT_SECRET@" + ++/* Define Yandex OAuth 2.0 Client ID to use */ ++#define YANDEX_CLIENT_ID "@WITH_YANDEX_CLIENT_ID@" ++ ++/* Define Yandex OAuth 2.0 Client Secret to use */ ++#define YANDEX_CLIENT_SECRET "@WITH_YANDEX_CLIENT_SECRET@" ++ + /* Path to a sendmail binary, or equivalent */ + #define SENDMAIL_PATH "@SENDMAIL_PATH@" + +diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt +index 8fa6429..548c3a8 100644 +--- a/data/CMakeLists.txt ++++ b/data/CMakeLists.txt +@@ -52,6 +52,32 @@ if(NOT WITH_GOOGLE_CLIENT_ID STREQUAL "") + unset(_google_oauth2_scheme) + endif(NOT WITH_GOOGLE_CLIENT_ID STREQUAL "") + ++ ++# if(NOT WITH_YANDEX_CLIENT_ID STREQUAL "") ++# set(CMAKE_REQUIRED_DEFINITIONS ${DATA_SERVER_CFLAGS}) ++# set(CMAKE_REQUIRED_INCLUDES ${CMAKE_BINARY_DIR} ${DATA_SERVER_INCLUDE_DIRS}) ++# set(CMAKE_REQUIRED_LIBRARIES ${DATA_SERVER_LDFLAGS}) ++# list(APPEND CMAKE_REQUIRED_DEFINITIONS -DG_LOG_DOMAIN=\"oauth2-value-helper\" -DBUILDING_VALUE_HELPER=1) ++# file(TO_NATIVE_PATH "${CMAKE_BINARY_DIR}/oauth2-yandex-client-id" _binary_dir_to_file) ++# CHECK_C_SOURCE_RUNS("#define DECODE_KEY \"${WITH_YANDEX_CLIENT_ID}\" ++# #define DECODE_TO_FILE \"${_binary_dir_to_file}\" ++# #define DECODE_REVERSED 1 ++# #include \"${CMAKE_SOURCE_DIR}/src/libedataserver/e-oauth2-service.c\"" _decoded) ++# file(READ ${_binary_dir_to_file} _yandex_oauth2_scheme) ++# unset(_binary_dir_to_file) ++# unset(_decoded) ++# unset(CMAKE_REQUIRED_LIBRARIES) ++# unset(CMAKE_REQUIRED_INCLUDES) ++# unset(CMAKE_REQUIRED_DEFINITIONS) ++# ++# if(NOT _yandex_oauth2_scheme STREQUAL "") ++# set(OAUTH2_SCHEMES "x-scheme-handler/${_yandex_oauth2_scheme};${OAUTH2_SCHEMES}") ++# endif(NOT _yandex_oauth2_scheme STREQUAL "") ++# unset(_yandex_oauth2_scheme) ++# endif(NOT WITH_YANDEX_CLIENT_ID STREQUAL "") ++ ++set(OAUTH2_SCHEMES "x-scheme-handler/eds-oauth2;") ++ + configure_file(org.gnome.evolution-data-server.OAuth2-handler.desktop.in + org.gnome.evolution-data-server.OAuth2-handler.desktop.in + @ONLY +diff --git a/data/org.gnome.evolution-data-server.gschema.xml.in b/data/org.gnome.evolution-data-server.gschema.xml.in +index b66c019..d171255 100644 +--- a/data/org.gnome.evolution-data-server.gschema.xml.in ++++ b/data/org.gnome.evolution-data-server.gschema.xml.in +@@ -86,6 +86,16 @@ + An OAuth2 client secret to use to connect to Yahoo! servers, instead of the one provided during build time + User-specified OAuth2 client secret for Yahoo! servers. Empty string means to use the one provided during build time. Change of this requires restart. + ++ ++ '' ++ An OAuth2 client ID to use to connect to Yandex servers, instead of the one provided during build time ++ User-specified OAuth2 client ID for Yandex servers. Empty string means to use the one provided during build time. Change of this requires restart. ++ ++ ++ '' ++ An OAuth2 client secret to use to connect to Yandex servers, instead of the one provided during build time ++ User-specified OAuth2 client secret for Yandex servers. Empty string means to use the one provided during build time. Change of this requires restart. ++ + + false + Whether to limit operations in Power Saver mode +diff --git a/po/POTFILES.in b/po/POTFILES.in +index 135996e..c6ab15e 100644 +--- a/po/POTFILES.in ++++ b/po/POTFILES.in +@@ -115,6 +115,7 @@ src/camel/camel-sasl-xoauth2.c + src/camel/camel-sasl-xoauth2-google.c + src/camel/camel-sasl-xoauth2-outlook.c + src/camel/camel-sasl-xoauth2-yahoo.c ++src/camel/camel-sasl-xoauth2-yandex.c + src/camel/camel-search-private.c + src/camel/camel-service.c + src/camel/camel-session.c +@@ -200,6 +201,7 @@ src/libedataserver/e-oauth2-service.c + src/libedataserver/e-oauth2-service-google.c + src/libedataserver/e-oauth2-service-outlook.c + src/libedataserver/e-oauth2-service-yahoo.c ++src/libedataserver/e-oauth2-service-yandex.c + src/libedataserver/e-soup-session.c + src/libedataserver/e-source.c + src/libedataserver/e-source-credentials-provider-impl.c +@@ -226,6 +228,7 @@ src/modules/google-backend/module-google-backend.c + src/modules/trust-prompt/module-trust-prompt.c + src/modules/trust-prompt/trust-prompt-gtk.c + src/modules/yahoo-backend/module-yahoo-backend.c ++src/modules/yandex-backend/module-yandex-backend.c + src/services/evolution-addressbook-factory/evolution-addressbook-factory.c + src/services/evolution-alarm-notify/e-alarm-notify.c + src/services/evolution-calendar-factory/evolution-calendar-factory.c +diff --git a/src/camel/CMakeLists.txt b/src/camel/CMakeLists.txt +index 59bc77a..a18a4d7 100644 +--- a/src/camel/CMakeLists.txt ++++ b/src/camel/CMakeLists.txt +@@ -113,6 +113,7 @@ set(SOURCES + camel-sasl-xoauth2-google.c + camel-sasl-xoauth2-outlook.c + camel-sasl-xoauth2-yahoo.c ++ camel-sasl-xoauth2-yandex.c + camel-sasl.c + camel-search-private.c + camel-search-sql-sexp.c +@@ -257,6 +258,7 @@ set(HEADERS + camel-sasl-xoauth2-google.h + camel-sasl-xoauth2-outlook.h + camel-sasl-xoauth2-yahoo.h ++ camel-sasl-xoauth2-yandex.h + camel-sasl.h + camel-search-private.h + camel-search-sql-sexp.h +diff --git a/src/camel/camel-autocleanups.h b/src/camel/camel-autocleanups.h +index ab36772..a653b58 100644 +--- a/src/camel/camel-autocleanups.h ++++ b/src/camel/camel-autocleanups.h +@@ -112,6 +112,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(CamelSaslPlain, g_object_unref) + G_DEFINE_AUTOPTR_CLEANUP_FUNC(CamelSaslPOPB4SMTP, g_object_unref) + G_DEFINE_AUTOPTR_CLEANUP_FUNC(CamelSaslXOAuth2, g_object_unref) + G_DEFINE_AUTOPTR_CLEANUP_FUNC(CamelSaslXOAuth2Google, g_object_unref) ++G_DEFINE_AUTOPTR_CLEANUP_FUNC(CamelSaslXOAuth2Yandex, g_object_unref) + G_DEFINE_AUTOPTR_CLEANUP_FUNC(CamelSaslXOAuth2Outlook, g_object_unref) + G_DEFINE_AUTOPTR_CLEANUP_FUNC(CamelService, g_object_unref) + G_DEFINE_AUTOPTR_CLEANUP_FUNC(CamelServiceAuthType, camel_service_auth_type_free) +diff --git a/src/camel/camel-sasl-xoauth2-yandex.c b/src/camel/camel-sasl-xoauth2-yandex.c +new file mode 100644 +index 0000000..234839a +--- /dev/null ++++ b/src/camel/camel-sasl-xoauth2-yandex.c +@@ -0,0 +1,44 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ ++/* ++ * 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 "camel-sasl-xoauth2-yandex.h" ++ ++static CamelServiceAuthType sasl_xoauth2_yandex_auth_type = { ++ N_("OAuth2 (Yandex)"), ++ N_("This option will use an OAuth 2.0 " ++ "access token to connect to the yandex server"), ++ "Yandex", ++ FALSE ++}; ++ ++G_DEFINE_TYPE (CamelSaslXOAuth2Yandex, camel_sasl_xoauth2_yandex, CAMEL_TYPE_SASL_XOAUTH2) ++ ++static void ++camel_sasl_xoauth2_yandex_class_init (CamelSaslXOAuth2YandexClass *klass) ++{ ++ CamelSaslClass *sasl_class; ++ ++ sasl_class = CAMEL_SASL_CLASS (klass); ++ sasl_class->auth_type = &sasl_xoauth2_yandex_auth_type; ++} ++ ++static void ++camel_sasl_xoauth2_yandex_init (CamelSaslXOAuth2Yandex *sasl) ++{ ++} +diff --git a/src/camel/camel-sasl-xoauth2-yandex.h b/src/camel/camel-sasl-xoauth2-yandex.h +new file mode 100644 +index 0000000..0141ef9 +--- /dev/null ++++ b/src/camel/camel-sasl-xoauth2-yandex.h +@@ -0,0 +1,63 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ ++/* ++ * 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 . ++ */ ++ ++#if !defined (__CAMEL_H_INSIDE__) && !defined (CAMEL_COMPILATION) ++#error "Only can be included directly." ++#endif ++ ++#ifndef CAMEL_SASL_XOAUTH2_YANDEX_H ++#define CAMEL_SASL_XOAUTH2_YANDEX_H ++ ++#include ++ ++/* Standard GObject macros */ ++#define CAMEL_TYPE_SASL_XOAUTH2_YANDEX \ ++ (camel_sasl_xoauth2_yandex_get_type ()) ++#define CAMEL_SASL_XOAUTH2_YANDEX(obj) \ ++ (G_TYPE_CHECK_INSTANCE_CAST \ ++ ((obj), CAMEL_TYPE_SASL_XOAUTH2_YANDEX, CamelSaslXOAuth2Yandex)) ++#define CAMEL_SASL_XOAUTH2_YANDEX_CLASS(cls) \ ++ (G_TYPE_CHECK_CLASS_CAST \ ++ ((cls), CAMEL_TYPE_SASL_XOAUTH2_YANDEX, CamelSaslXOAuth2YandexClass)) ++#define CAMEL_IS_SASL_XOAUTH2_YANDEX(obj) \ ++ (G_TYPE_CHECK_INSTANCE_TYPE \ ++ ((obj), CAMEL_TYPE_SASL_XOAUTH2_YANDEX)) ++#define CAMEL_IS_SASL_XOAUTH2_YANDEX_CLASS(cls) \ ++ (G_TYPE_CHECK_CLASS_TYPE \ ++ ((cls), CAMEL_TYPE_SASL_XOAUTH2_YANDEX)) ++#define CAMEL_SASL_XOAUTH2_YANDEX_GET_CLASS(obj) \ ++ (G_TYPE_INSTANCE_GET_CLASS \ ++ ((obj), CAMEL_TYPE_SASL_XOAUTH2_YANDEX, CamelSaslXOAuth2YandexClass)) ++ ++G_BEGIN_DECLS ++ ++typedef struct _CamelSaslXOAuth2Yandex CamelSaslXOAuth2Yandex; ++typedef struct _CamelSaslXOAuth2YandexClass CamelSaslXOAuth2YandexClass; ++typedef struct _CamelSaslXOAuth2YandexPrivate CamelSaslXOAuth2YandexPrivate; ++ ++struct _CamelSaslXOAuth2Yandex { ++ CamelSaslXOAuth2 parent; ++ CamelSaslXOAuth2YandexPrivate *priv; ++}; ++ ++struct _CamelSaslXOAuth2YandexClass { ++ CamelSaslXOAuth2Class parent_class; ++}; ++ ++GType camel_sasl_xoauth2_yandex_get_type (void) G_GNUC_CONST; ++ ++G_END_DECLS ++ ++#endif /* CAMEL_SASL_XOAUTH2_YANDEX_H */ +diff --git a/src/camel/camel-sasl.c b/src/camel/camel-sasl.c +index 8882693..c36bec5 100644 +--- a/src/camel/camel-sasl.c ++++ b/src/camel/camel-sasl.c +@@ -35,6 +35,7 @@ + #include "camel-sasl-xoauth2-google.h" + #include "camel-sasl-xoauth2-outlook.h" + #include "camel-sasl-xoauth2-yahoo.h" ++#include "camel-sasl-xoauth2-yandex.h" + #include "camel-sasl.h" + #include "camel-service.h" + +@@ -133,6 +134,7 @@ sasl_build_class_table (void) + g_type_ensure (CAMEL_TYPE_SASL_XOAUTH2_GOOGLE); + g_type_ensure (CAMEL_TYPE_SASL_XOAUTH2_OUTLOOK); + g_type_ensure (CAMEL_TYPE_SASL_XOAUTH2_YAHOO); ++ g_type_ensure (CAMEL_TYPE_SASL_XOAUTH2_YANDEX); + + class_table = g_hash_table_new_full ( + (GHashFunc) g_str_hash, +diff --git a/src/camel/camel.h b/src/camel/camel.h +index 99504c2..c6c4bbe 100644 +--- a/src/camel/camel.h ++++ b/src/camel/camel.h +@@ -114,6 +114,7 @@ + #include + #include + #include ++#include + #include + #include + #include +diff --git a/src/libebackend/e-webdav-collection-backend.c b/src/libebackend/e-webdav-collection-backend.c +index ed5a4f6..4c321f4 100644 +--- a/src/libebackend/e-webdav-collection-backend.c ++++ b/src/libebackend/e-webdav-collection-backend.c +@@ -379,7 +379,7 @@ webdav_collection_backend_populate (ECollectionBackend *collection) + auth_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION); + method = e_source_authentication_dup_method (auth_extension); + user = e_source_authentication_dup_user (auth_extension); +- needs_credentials = user && *user && g_strcmp0 (method, "OAuth2") != 0 && ++ needs_credentials = user && *user && (g_strcmp0 (method, "OAuth2") != 0 || g_strcmp0 (method, "Yandex") != 0) && + !e_oauth2_services_is_oauth2_alias (e_source_registry_server_get_oauth2_services (server), method); + g_free (method); + g_free (user); +diff --git a/src/libedataserver/CMakeLists.txt b/src/libedataserver/CMakeLists.txt +index 3806914..997b36d 100644 +--- a/src/libedataserver/CMakeLists.txt ++++ b/src/libedataserver/CMakeLists.txt +@@ -73,6 +73,7 @@ set(SOURCES + e-oauth2-service-google.c + e-oauth2-service-outlook.c + e-oauth2-service-yahoo.c ++ e-oauth2-service-yandex.c + e-oauth2-services.c + e-operation-pool.c + e-secret-store.c +@@ -167,6 +168,7 @@ set(HEADERS + e-oauth2-service-google.h + e-oauth2-service-outlook.h + e-oauth2-service-yahoo.h ++ e-oauth2-service-yandex.h + e-oauth2-services.h + e-operation-pool.h + e-secret-store.h +diff --git a/src/libedataserver/e-dataserver-autocleanups.h b/src/libedataserver/e-dataserver-autocleanups.h +index f432984..f66dd5a 100644 +--- a/src/libedataserver/e-dataserver-autocleanups.h ++++ b/src/libedataserver/e-dataserver-autocleanups.h +@@ -40,6 +40,7 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(ENetworkMonitor, g_object_unref) + G_DEFINE_AUTOPTR_CLEANUP_FUNC(EOAuth2Service, g_object_unref) + G_DEFINE_AUTOPTR_CLEANUP_FUNC(EOAuth2ServiceBase, g_object_unref) + G_DEFINE_AUTOPTR_CLEANUP_FUNC(EOAuth2ServiceGoogle, g_object_unref) ++G_DEFINE_AUTOPTR_CLEANUP_FUNC(EOAuth2ServiceYandex, g_object_unref) + G_DEFINE_AUTOPTR_CLEANUP_FUNC(EOAuth2ServiceOutlook, g_object_unref) + G_DEFINE_AUTOPTR_CLEANUP_FUNC(EOAuth2Services, g_object_unref) + G_DEFINE_AUTOPTR_CLEANUP_FUNC(EOperationPool, e_operation_pool_free) +diff --git a/src/libedataserver/e-oauth2-service-yandex.c b/src/libedataserver/e-oauth2-service-yandex.c +new file mode 100644 +index 0000000..008e416 +--- /dev/null ++++ b/src/libedataserver/e-oauth2-service-yandex.c +@@ -0,0 +1,214 @@ ++/* ++ * Copyright (C) 2018 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-oauth2-service.h" ++#include "e-oauth2-service-base.h" ++#include "e-data-server-util.h" ++#include "e-oauth2-service-yandex.h" ++ ++/* Forward Declarations */ ++static void e_oauth2_service_yandex_oauth2_service_init (EOAuth2ServiceInterface *iface); ++ ++G_DEFINE_TYPE_WITH_CODE (EOAuth2ServiceYandex, e_oauth2_service_yandex, E_TYPE_OAUTH2_SERVICE_BASE, ++ G_IMPLEMENT_INTERFACE (E_TYPE_OAUTH2_SERVICE, e_oauth2_service_yandex_oauth2_service_init)) ++ ++static gboolean ++eos_yandex_guess_can_process (EOAuth2Service *service, ++ const gchar *protocol, ++ const gchar *hostname) ++{ ++ return hostname && ( ++ e_util_utf8_strstrcase (hostname, ".yandex.ru") || ++ e_util_utf8_strstrcase (hostname, ".ya.ru") || ++ e_util_utf8_strstrcase (hostname, ".yandex.com")); ++} ++ ++static const gchar * ++eos_yandex_get_name (EOAuth2Service *service) ++{ ++ return "Yandex"; ++} ++ ++static const gchar * ++eos_yandex_get_display_name (EOAuth2Service *service) ++{ ++ /* Translators: This is a user-visible string, display name of an OAuth2 service. */ ++ return C_("OAuth2Service", "yandex"); ++} ++ ++static const gchar * ++eos_yandex_read_settings (EOAuth2Service *service, ++ const gchar *key_name) ++{ ++ G_LOCK_DEFINE_STATIC (user_settings); ++ gchar *value; ++ ++ G_LOCK (user_settings); ++ ++ value = g_object_get_data (G_OBJECT (service), key_name); ++ if (!value) { ++ GSettings *settings; ++ ++ settings = g_settings_new ("org.gnome.evolution-data-server"); ++ value = g_settings_get_string (settings, key_name); ++ g_object_unref (settings); ++ ++ if (value && *value) { ++ g_object_set_data_full (G_OBJECT (service), key_name, value, g_free); ++ } else { ++ g_free (value); ++ value = (gchar *) ""; ++ ++ g_object_set_data (G_OBJECT (service), key_name, value); ++ } ++ } ++ ++ G_UNLOCK (user_settings); ++ ++ return value; ++} ++ ++static const gchar * ++eos_yandex_get_client_id (EOAuth2Service *service, ++ ESource *source) ++{ ++ const gchar *client_id; ++ ++ client_id = eos_yandex_read_settings (service, "oauth2-yandex-client-id"); ++ ++ if (client_id && *client_id) ++ return client_id; ++ ++ return YANDEX_CLIENT_ID; ++} ++ ++static const gchar * ++eos_yandex_get_client_secret (EOAuth2Service *service, ++ ESource *source) ++{ ++ const gchar *client_secret; ++ ++ client_secret = eos_yandex_read_settings (service, "oauth2-yandex-client-secret"); ++ ++ if (client_secret && *client_secret) ++ return client_secret; ++ ++ return YANDEX_CLIENT_SECRET; ++} ++ ++static const gchar * ++eos_yandex_get_authentication_uri (EOAuth2Service *service, ++ ESource *source) ++{ ++ return "https://oauth.yandex.ru/authorize"; ++} ++ ++static const gchar * ++eos_yandex_get_refresh_uri (EOAuth2Service *service, ++ ESource *source) ++{ ++ return "https://oauth.yandex.ru/token"; ++} ++ ++static void ++eos_yandex_prepare_authentication_uri_query (EOAuth2Service *service, ++ ESource *source, ++ GHashTable *uri_query) ++{ ++ const gchar *YANDEX_SCOPE = ++ /* GMail IMAP and SMTP access */ ++ "login:email login:info mail:imap_full mail:imap_ro mail:smtp calendar:all"; ++ ++ g_return_if_fail (uri_query != NULL); ++ ++ e_oauth2_service_util_set_to_form (uri_query, "scope", YANDEX_SCOPE); ++ e_oauth2_service_util_set_to_form (uri_query, "include_granted_scopes", "false"); ++} ++ ++static gboolean ++eos_yandex_extract_authorization_code (EOAuth2Service *service, ++ ESource *source, ++ const gchar *page_title, ++ const gchar *page_uri, ++ const gchar *page_content, ++ gchar **out_authorization_code) ++{ ++ g_return_val_if_fail (out_authorization_code != NULL, FALSE); ++ ++ *out_authorization_code = NULL; ++ ++ if (page_uri && *page_uri) { ++ GUri *suri; ++ ++ suri = g_uri_parse (page_uri, SOUP_HTTP_URI_FLAGS, NULL); ++ if (suri) { ++ const gchar *query = g_uri_get_query (suri); ++ gboolean known = FALSE; ++ ++ if (query && *query) { ++ GHashTable *params; ++ ++ params = soup_form_decode (query); ++ if (params) { ++ const gchar *response; ++ ++ response = g_hash_table_lookup (params, "code"); ++ if (response) { ++ *out_authorization_code = g_strdup (response); ++ known = TRUE; ++ } ++ ++ g_hash_table_destroy (params); ++ } ++ } ++ ++// soup_uri_free (suri); ++ ++ if (known) ++ return TRUE; ++ } ++ } ++ ++ return FALSE; ++} ++ ++static void ++e_oauth2_service_yandex_oauth2_service_init (EOAuth2ServiceInterface *iface) ++{ ++ iface->guess_can_process = eos_yandex_guess_can_process; ++ iface->get_name = eos_yandex_get_name; ++ iface->get_display_name = eos_yandex_get_display_name; ++ iface->get_client_id = eos_yandex_get_client_id; ++ iface->get_client_secret = eos_yandex_get_client_secret; ++ iface->get_authentication_uri = eos_yandex_get_authentication_uri; ++ iface->get_refresh_uri = eos_yandex_get_refresh_uri; ++ iface->prepare_authentication_uri_query = eos_yandex_prepare_authentication_uri_query; ++ iface->extract_authorization_code = eos_yandex_extract_authorization_code; ++} ++ ++static void ++e_oauth2_service_yandex_class_init (EOAuth2ServiceYandexClass *klass) ++{ ++} ++ ++static void ++e_oauth2_service_yandex_init (EOAuth2ServiceYandex *oauth2_google) ++{ ++} +diff --git a/src/libedataserver/e-oauth2-service-yandex.h b/src/libedataserver/e-oauth2-service-yandex.h +new file mode 100644 +index 0000000..0011fd9 +--- /dev/null ++++ b/src/libedataserver/e-oauth2-service-yandex.h +@@ -0,0 +1,62 @@ ++/* ++ * Copyright (C) 2018 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 . ++ */ ++ ++#if !defined (__LIBEDATASERVER_H_INSIDE__) && !defined (LIBEDATASERVER_COMPILATION) ++#error "Only should be included directly." ++#endif ++ ++#ifndef E_OAUTH2_SERVICE_YANDEX_H ++#define E_OAUTH2_SERVICE_YANDEX_H ++ ++#include ++ ++/* Standard GObject macros */ ++#define E_TYPE_OAUTH2_SERVICE_YANDEX \ ++ (e_oauth2_service_yandex_get_type ()) ++#define E_OAUTH2_SERVICE_YANDEX(obj) \ ++ (G_TYPE_CHECK_INSTANCE_CAST \ ++ ((obj), E_TYPE_OAUTH2_SERVICE_YANDEX, EOAuth2ServiceYandex)) ++#define E_OAUTH2_SERVICE_YANDEX_CLASS(cls) \ ++ (G_TYPE_CHECK_CLASS_CAST \ ++ ((cls), E_TYPE_OAUTH2_SERVICE_YANDEX, EOAuth2ServiceYandexClass)) ++#define E_IS_OAUTH2_SERVICE_YANDEX(obj) \ ++ (G_TYPE_CHECK_INSTANCE_TYPE \ ++ ((obj), E_TYPE_OAUTH2_SERVICE_YANDEX)) ++#define E_IS_OAUTH2_SERVICE_YANDEX_CLASS(cls) \ ++ (G_TYPE_CHECK_CLASS_TYPE \ ++ ((cls), E_TYPE_OAUTH2_SERVICE_YANDEX)) ++#define E_OAUTH2_SERVICE_YANDEX_GET_CLASS(obj) \ ++ (G_TYPE_INSTANCE_GET_CLASS \ ++ ((obj), E_TYPE_OAUTH2_SERVICE_YANDEX, EOAuth2ServiceYandexClass)) ++ ++G_BEGIN_DECLS ++ ++typedef struct _EOAuth2ServiceYandex EOAuth2ServiceYandex; ++typedef struct _EOAuth2ServiceYandexClass EOAuth2ServiceYandexClass; ++ ++struct _EOAuth2ServiceYandex { ++ EOAuth2ServiceBase parent; ++}; ++ ++struct _EOAuth2ServiceYandexClass { ++ EOAuth2ServiceBaseClass parent_class; ++}; ++ ++GType e_oauth2_service_yandex_get_type (void) G_GNUC_CONST; ++ ++G_END_DECLS ++ ++#endif /* E_OAUTH2_SERVICE_YANDEX_H */ +diff --git a/src/libedataserver/e-oauth2-services.c b/src/libedataserver/e-oauth2-services.c +index 22cb20e..a5977bd 100644 +--- a/src/libedataserver/e-oauth2-services.c ++++ b/src/libedataserver/e-oauth2-services.c +@@ -36,6 +36,7 @@ + + /* Known built-in implementations */ + #include "e-oauth2-service-google.h" ++#include "e-oauth2-service-yandex.h" + #include "e-oauth2-service-outlook.h" + #include "e-oauth2-service-yahoo.h" + +@@ -136,6 +137,7 @@ e_oauth2_services_class_init (EOAuth2ServicesClass *klass) + + /* Ensure built-in service types are registered */ + g_type_ensure (E_TYPE_OAUTH2_SERVICE_GOOGLE); ++ g_type_ensure (E_TYPE_OAUTH2_SERVICE_YANDEX); + g_type_ensure (E_TYPE_OAUTH2_SERVICE_OUTLOOK); + g_type_ensure (E_TYPE_OAUTH2_SERVICE_YAHOO); + } +diff --git a/src/libedataserver/e-soup-auth-bearer.c b/src/libedataserver/e-soup-auth-bearer.c +index ccf0136..310c781 100644 +--- a/src/libedataserver/e-soup-auth-bearer.c ++++ b/src/libedataserver/e-soup-auth-bearer.c +@@ -41,6 +41,8 @@ + #define AUTH_STRENGTH 1 + + #define EXPIRY_INVALID ((time_t) -1) ++#define DEFAULT_BEARER_AUTH (gchar)0 ++#define MAX_CUSTOM_BEARER_ID 16 + + /* How many seconds earlier than reported by the server is the token considered expired. */ + #define TOKEN_VALIDITY_GAP_SECS 5 +@@ -49,6 +51,7 @@ struct _ESoupAuthBearerPrivate { + GMutex property_lock; + gchar *access_token; + time_t expiry; ++ gchar is_custom_bearer[MAX_CUSTOM_BEARER_ID]; + }; + + G_DEFINE_TYPE_WITH_PRIVATE ( +@@ -194,7 +197,10 @@ e_soup_auth_bearer_get_authorization (SoupAuth *auth, + + g_mutex_lock (&bearer->priv->property_lock); + +- res = g_strdup_printf ("Bearer %s", bearer->priv->access_token); ++ if (!bearer->priv->is_custom_bearer[0]) ++ res = g_strdup_printf ("Bearer %s", bearer->priv->access_token); ++ else ++ res = g_strdup_printf ("%s %s", bearer->priv->is_custom_bearer, bearer->priv->access_token); + + e_soup_auth_bearer_debug_print ("%s: bearer:%p message:%p; status:%u token:%p expired:%d\n", + G_STRFUNC, bearer, message, soup_message_get_status (message), +@@ -249,6 +255,7 @@ e_soup_auth_bearer_init (ESoupAuthBearer *bearer) + { + bearer->priv = e_soup_auth_bearer_get_instance_private (bearer); + bearer->priv->expiry = EXPIRY_INVALID; ++ bearer->priv->is_custom_bearer[0] = DEFAULT_BEARER_AUTH; + + g_mutex_init (&bearer->priv->property_lock); + } +@@ -343,3 +350,16 @@ e_soup_auth_bearer_is_expired (ESoupAuthBearer *bearer) + + return expired; + } ++ ++gboolean ++e_soup_auth_bearer_set_custom_bearer_name (ESoupAuthBearer *bearer, const gchar *bearer_name) ++{ ++ if (!bearer) return TRUE; ++ g_return_val_if_fail (E_IS_SOUP_AUTH_BEARER (bearer), TRUE); ++ ++ g_mutex_lock (&bearer->priv->property_lock); ++ g_utf8_strncpy(bearer->priv->is_custom_bearer, bearer_name, MAX_CUSTOM_BEARER_ID-1); ++ g_mutex_unlock (&bearer->priv->property_lock); ++ ++ return TRUE; ++} +diff --git a/src/libedataserver/e-soup-auth-bearer.h b/src/libedataserver/e-soup-auth-bearer.h +index 545bf02..a6cb576 100644 +--- a/src/libedataserver/e-soup-auth-bearer.h ++++ b/src/libedataserver/e-soup-auth-bearer.h +@@ -74,6 +74,10 @@ void e_soup_auth_bearer_set_access_token + gint expires_in_seconds); + gboolean e_soup_auth_bearer_is_expired (ESoupAuthBearer *bearer); + ++gboolean ++e_soup_auth_bearer_set_custom_bearer_name (ESoupAuthBearer *bearer, ++const gchar *bearer_name); ++ + G_END_DECLS + + #endif /* E_SOUP_AUTH_BEARER_H */ +diff --git a/src/libedataserver/e-soup-session.c b/src/libedataserver/e-soup-session.c +index 19e9d07..7ff729e 100644 +--- a/src/libedataserver/e-soup-session.c ++++ b/src/libedataserver/e-soup-session.c +@@ -236,16 +236,31 @@ e_soup_session_maybe_prepare_bearer_auth (ESoupSession *session, + GError **error) + { + gboolean success; ++ gchar *auth_method = NULL; ++ ESource *source; + + g_return_val_if_fail (E_IS_SOUP_SESSION (session), FALSE); + g_return_val_if_fail (g_uri != NULL, FALSE); + + g_mutex_lock (&session->priv->property_lock); ++ source = e_soup_session_get_source (session); ++ if (source && e_source_has_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION)) { ++ ESourceAuthentication *extension; ++ ++ extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION); ++ auth_method = e_source_authentication_dup_method (extension); ++ } + if (session->priv->using_bearer_auth) { + ESoupAuthBearer *using_bearer_auth = g_object_ref (session->priv->using_bearer_auth); + + g_mutex_unlock (&session->priv->property_lock); + ++ if (auth_method){ ++ if (!g_strcmp0(auth_method, "Yandex")){ ++ e_soup_auth_bearer_set_custom_bearer_name (using_bearer_auth, "OAuth"); ++ } ++ } ++ + success = e_soup_session_setup_bearer_auth (session, message, FALSE, using_bearer_auth, cancellable, error); + + g_clear_object (&using_bearer_auth); +@@ -256,6 +271,12 @@ e_soup_session_maybe_prepare_bearer_auth (ESoupSession *session, + E_TYPE_SOUP_AUTH_BEARER, + "authority", g_uri_get_host (g_uri), NULL); + ++ if (auth_method){ ++ if (!g_strcmp0(auth_method, "Yandex")){ ++ e_soup_auth_bearer_set_custom_bearer_name (E_SOUP_AUTH_BEARER(soup_auth), "OAuth"); ++ } ++ } ++ + success = e_soup_session_setup_bearer_auth (session, message, FALSE, E_SOUP_AUTH_BEARER (soup_auth), cancellable, error); + if (success) { + g_clear_object (&session->priv->using_bearer_auth); +diff --git a/src/libedataserver/libedataserver.h b/src/libedataserver/libedataserver.h +index 9acf33f..508f27d 100644 +--- a/src/libedataserver/libedataserver.h ++++ b/src/libedataserver/libedataserver.h +@@ -45,6 +45,7 @@ + #include + #include + #include ++#include + #include + #include + #include +diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt +index 0046e7a..ff80114 100644 +--- a/src/modules/CMakeLists.txt ++++ b/src/modules/CMakeLists.txt +@@ -67,6 +67,7 @@ add_subdirectory(google-backend) + add_subdirectory(outlook-backend) + add_subdirectory(webdav-backend) + add_subdirectory(yahoo-backend) ++add_subdirectory(yandex-backend) + add_subdirectory(oauth2-services) + + if(HAVE_GTK) +diff --git a/src/modules/gnome-online-accounts/module-gnome-online-accounts.c b/src/modules/gnome-online-accounts/module-gnome-online-accounts.c +index 626971b..5b047d0 100644 +--- a/src/modules/gnome-online-accounts/module-gnome-online-accounts.c ++++ b/src/modules/gnome-online-accounts/module-gnome-online-accounts.c +@@ -124,6 +124,9 @@ gnome_online_accounts_get_backend_name (const gchar *goa_provider_type) + if (g_str_equal (goa_provider_type, "google")) + eds_backend_name = "google"; + ++ if (g_str_equal (goa_provider_type, "yandex")) ++ eds_backend_name = "yandex"; ++ + if (g_str_equal (goa_provider_type, "imap_smtp")) + eds_backend_name = "none"; + +diff --git a/src/modules/yandex-backend/CMakeLists.txt b/src/modules/yandex-backend/CMakeLists.txt +new file mode 100644 +index 0000000..960c882 +--- /dev/null ++++ b/src/modules/yandex-backend/CMakeLists.txt +@@ -0,0 +1,17 @@ ++set(extra_deps) ++set(sources ++ module-yandex-backend.c ++ ) ++set(extra_defines) ++set(extra_cflags) ++set(extra_incdirs) ++set(extra_ldflags) ++ ++add_source_registry_module(module-yandex-backend ++ sources ++ extra_deps ++ extra_defines ++ extra_cflags ++ extra_incdirs ++ extra_ldflags ++) +diff --git a/src/modules/yandex-backend/module-yandex-backend.c b/src/modules/yandex-backend/module-yandex-backend.c +new file mode 100644 +index 0000000..a99d35c +--- /dev/null ++++ b/src/modules/yandex-backend/module-yandex-backend.c +@@ -0,0 +1,619 @@ ++/* ++ * module-yandex-backend.c ++ * ++ * 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 ++ ++/* Standard GObject macros */ ++#define E_TYPE_YANDEX_BACKEND \ ++ (e_yandex_backend_get_type ()) ++#define E_YANDEX_BACKEND(obj) \ ++ (G_TYPE_CHECK_INSTANCE_CAST \ ++ ((obj), E_TYPE_YANDEX_BACKEND, EYandexBackend)) ++ ++/* Just for readability... */ ++#define METHOD(x) (CAMEL_NETWORK_SECURITY_METHOD_##x) ++ ++/* IMAP Configuration Details */ ++#define YANDEX_IMAP_BACKEND_NAME "imapx" ++#define YANDEX_IMAP_HOST "imap.yandex.ru" ++#define YANDEX_IMAP_PORT 993 ++#define YANDEX_IMAP_SECURITY_METHOD METHOD (SSL_ON_ALTERNATE_PORT) ++ ++/* SMTP Configuration Details */ ++#define YANDEX_SMTP_BACKEND_NAME "smtp" ++#define YANDEX_SMTP_HOST "smtp.yandex.ru" ++#define YANDEX_SMTP_PORT 465 ++#define YANDEX_SMTP_SECURITY_METHOD METHOD (SSL_ON_ALTERNATE_PORT) ++ ++/* WebDAV Configuration Details */ ++#define YANDEX_CALDAV_URL "https://caldav.yandex.ru/" ++#define YANDEX_CARDDAV_URL "https://carddav.yandex.ru/" ++ ++#define YANDEX_CONTACTS_RESOURCE_ID "Contacts" ++#define YANDEX_CONTACTS_BACKEND_NAME "yandex" ++#define YANDEX_CONTACTS_HOST "carddav.yandex.ru" ++ ++#define YANDEX_OAUTH2_METHOD_CUSTOM "Yandex" ++ ++typedef struct _EYandexBackend EYandexBackend; ++typedef struct _EYandexBackendClass EYandexBackendClass; ++ ++typedef struct _EYandexBackendFactory EYandexBackendFactory; ++typedef struct _EYandexBackendFactoryClass EYandexBackendFactoryClass; ++ ++struct _EYandexBackend { ++ EWebDAVCollectionBackend parent; ++}; ++ ++struct _EYandexBackendClass { ++ EWebDAVCollectionBackendClass parent_class; ++}; ++ ++struct _EYandexBackendFactory { ++ ECollectionBackendFactory parent; ++}; ++ ++struct _EYandexBackendFactoryClass { ++ ECollectionBackendFactoryClass parent_class; ++}; ++ ++/* Module Entry Points */ ++void e_module_load (GTypeModule *type_module); ++void e_module_unload (GTypeModule *type_module); ++ ++/* Forward Declarations */ ++GType e_yandex_backend_get_type (void); ++GType e_yandex_backend_factory_get_type (void); ++ ++G_DEFINE_DYNAMIC_TYPE ( ++ EYandexBackend, ++ e_yandex_backend, ++ E_TYPE_WEBDAV_COLLECTION_BACKEND) ++ ++G_DEFINE_DYNAMIC_TYPE ( ++ EYandexBackendFactory, ++ e_yandex_backend_factory, ++ E_TYPE_COLLECTION_BACKEND_FACTORY) ++ ++static void ++yandex_backend_calendar_update_auth_method (ECollectionBackend *collection_backend, ++ ESource *child_source, ++ ESource *master_source); ++ ++static ESourceAuthenticationResult ++yandex_backend_authenticate_sync (EBackend *backend, ++ const ENamedParameters *credentials, ++ gchar **out_certificate_pem, ++ GTlsCertificateFlags *out_certificate_errors, ++ GCancellable *cancellable, ++ GError **error) ++{ ++ ECollectionBackend *collection = E_COLLECTION_BACKEND (backend); ++ ESourceCollection *collection_extension; ++ ESource *source; ++ ESourceAuthenticationResult result = E_SOURCE_AUTHENTICATION_ERROR; ++ ESourceGoa *goa_extension = NULL; ++ const gchar *calendar_url; ++ const gchar *carddav_url; ++ ++ g_return_val_if_fail (collection != NULL, E_SOURCE_AUTHENTICATION_ERROR); ++ ++ source = e_backend_get_source (backend); ++ collection_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_COLLECTION); ++ if (e_source_has_extension (source, E_SOURCE_EXTENSION_GOA)) ++ goa_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_GOA); ++ ++ g_return_val_if_fail (e_source_collection_get_calendar_enabled (collection_extension) || ++ e_source_collection_get_contacts_enabled (collection_extension), E_SOURCE_AUTHENTICATION_ERROR); ++ ++ e_collection_backend_freeze_populate (collection); ++ ++ (void) e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND); ++ yandex_backend_calendar_update_auth_method (collection, source, NULL); ++ ++ if (goa_extension) { ++ calendar_url = e_source_goa_get_calendar_url (goa_extension); ++ carddav_url = e_source_goa_get_contacts_url (goa_extension); ++ } else { ++ calendar_url = "https://caldav.yandex.ru/"; ++ carddav_url = "https://carddav.yandex.ru"; ++ } ++ ++ if (e_source_collection_get_calendar_enabled (collection_extension) && (calendar_url || carddav_url)) { ++ result = e_webdav_collection_backend_discover_sync (E_WEBDAV_COLLECTION_BACKEND (backend), ++ calendar_url, carddav_url, credentials, ++ out_certificate_pem, out_certificate_errors, cancellable, error); ++ } else { ++ result = E_SOURCE_AUTHENTICATION_ACCEPTED; ++ } ++ ++ if (result == E_SOURCE_AUTHENTICATION_ACCEPTED) { ++ ESourceRegistryServer *server; ++ ++ server = e_collection_backend_ref_server (collection); ++ ++ if (server) { ++ g_object_unref (server); ++ } ++ } ++ ++ e_collection_backend_thaw_populate (collection); ++ ++ return result; ++} ++ ++static gchar * ++yandex_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 (YANDEX_CONTACTS_RESOURCE_ID); ++ ++ /* Chain up to parent's method. */ ++ return E_WEBDAV_COLLECTION_BACKEND_CLASS (e_yandex_backend_parent_class)->get_resource_id (webdav_backend, source); ++} ++ ++static gboolean ++yandex_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)) ++ return TRUE; ++ ++ /* Chain up to parent's method. */ ++ return E_WEBDAV_COLLECTION_BACKEND_CLASS (e_yandex_backend_parent_class)->is_custom_source (webdav_backend, source); ++} ++ ++static void ++yandex_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); ++ ++ (void) e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND); ++ ++ if (e_source_authentication_get_is_external (authentication_extension)) ++ e_source_authentication_set_method (authentication_extension, YANDEX_OAUTH2_METHOD_CUSTOM); ++ ++ /* Chain up to parent's method. */ ++ E_COLLECTION_BACKEND_CLASS (e_yandex_backend_parent_class)->populate (backend); ++ ++} ++ ++static gboolean ++host_ends_with (const gchar *host, ++ const gchar *ends_with) ++{ ++ gint host_len, ends_with_len; ++ ++ if (!host || !ends_with) ++ return FALSE; ++ ++ host_len = strlen (host); ++ ends_with_len = strlen (ends_with); ++ ++ if (host_len <= ends_with_len) ++ return FALSE; ++ ++ return g_ascii_strcasecmp (host + host_len - ends_with_len, ends_with) == 0; ++} ++ ++static gboolean ++yandex_backend_is_yandex_host (ESourceAuthentication *auth_extension, ++ gboolean *out_requires_oauth2) ++{ ++ gboolean is_yandex; ++ gchar *host; ++ ++ g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATION (auth_extension), FALSE); ++ ++ host = e_source_authentication_dup_host (auth_extension); ++ ++ is_yandex = (host && ( ++ host_ends_with (host, "yandex.ru") || ++ host_ends_with (host, "yandex.com") || ++ host_ends_with (host, "ya.ru"))); ++ ++ g_free (host); ++ ++ if (out_requires_oauth2) ++ *out_requires_oauth2 = TRUE; ++ ++ return is_yandex; ++} ++ ++static void ++yandex_backend_mail_update_auth_method (ECollectionBackend *collection_backend, ++ ESource *child_source, ++ ESource *master_source) ++{ ++ ESourceAuthentication *auth_extension; ++ EOAuth2Support *oauth2_support; ++ const gchar *method; ++ ++ auth_extension = e_source_get_extension (child_source, E_SOURCE_EXTENSION_AUTHENTICATION); ++ ++ if (!yandex_backend_is_yandex_host (auth_extension, NULL)) ++ return; ++ ++ oauth2_support = e_server_side_source_ref_oauth2_support (E_SERVER_SIDE_SOURCE (child_source)); ++ if (!oauth2_support && master_source) ++ oauth2_support = e_server_side_source_ref_oauth2_support (E_SERVER_SIDE_SOURCE (master_source)); ++ ++ if (oauth2_support) { ++ method = "XOAUTH2"; ++ } else { ++ method = NULL; ++ } ++ ++ if (method && e_collection_backend_is_new_source (collection_backend, child_source)) ++ e_source_authentication_set_method (auth_extension, method); ++ ++ g_clear_object (&oauth2_support); ++} ++ ++static void ++yandex_backend_mail_update_auth_method_cb (ESource *child_source, ++ GParamSpec *param, ++ EBackend *backend) ++{ ++ yandex_backend_mail_update_auth_method (E_COLLECTION_BACKEND (backend), child_source, e_backend_get_source (backend)); ++} ++ ++static void ++yandex_backend_calendar_update_auth_method (ECollectionBackend *collection_backend, ++ ESource *child_source, ++ ESource *master_source) ++{ ++ EOAuth2Support *oauth2_support; ++ ESourceAuthentication *auth_extension; ++ const gchar *method; ++ ++ auth_extension = e_source_get_extension (child_source, E_SOURCE_EXTENSION_AUTHENTICATION); ++ ++ if (!yandex_backend_is_yandex_host (auth_extension, NULL)) ++ return; ++ ++ oauth2_support = e_server_side_source_ref_oauth2_support (E_SERVER_SIDE_SOURCE (child_source)); ++ if (!oauth2_support && master_source) ++ oauth2_support = e_server_side_source_ref_oauth2_support (E_SERVER_SIDE_SOURCE (master_source)); ++ ++ if (oauth2_support) { ++ method = YANDEX_OAUTH2_METHOD_CUSTOM; ++ } else { ++ method = NULL; ++ } ++ ++ if (e_collection_backend_is_new_source (collection_backend, child_source)) ++ e_source_authentication_set_method (auth_extension, method); ++ ++ g_clear_object (&oauth2_support); ++} ++ ++static void ++yandex_backend_calendar_update_auth_method_cb (ESource *child_source, ++ GParamSpec *param, ++ EBackend *backend) ++{ ++ yandex_backend_calendar_update_auth_method (E_COLLECTION_BACKEND (backend), child_source, e_backend_get_source (backend)); ++} ++ ++static gchar * ++yandex_backend_dup_resource_id (ECollectionBackend *backend, ++ ESource *child_source) ++{ ++ 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)) ++ return E_COLLECTION_BACKEND_CLASS (e_yandex_backend_parent_class)->dup_resource_id (backend, child_source); ++ ++ if (e_source_has_extension (child_source, E_SOURCE_EXTENSION_ADDRESS_BOOK)) ++ return g_strdup (YANDEX_CONTACTS_RESOURCE_ID); ++ ++ return NULL; ++} ++ ++static void ++yandex_backend_child_added (ECollectionBackend *backend, ++ ESource *child_source) ++{ ++ 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_yandex_backend_parent_class)-> ++ child_added (backend, child_source); ++ ++ collection_source = e_backend_get_source (E_BACKEND (backend)); ++ ++ extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; ++ is_mail |= e_source_has_extension (child_source, extension_name); ++ ++ extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY; ++ is_mail |= e_source_has_extension (child_source, extension_name); ++ ++ extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT; ++ is_mail |= e_source_has_extension (child_source, extension_name); ++ ++ /* Synchronize mail-related user with the collection identity. */ ++ extension_name = E_SOURCE_EXTENSION_AUTHENTICATION; ++ if (is_mail && e_source_has_extension (child_source, extension_name)) { ++ ESourceAuthentication *auth_child_extension; ++ ESourceCollection *collection_extension; ++ const gchar *collection_identity; ++ const gchar *auth_child_user; ++ ++ extension_name = E_SOURCE_EXTENSION_COLLECTION; ++ collection_extension = e_source_get_extension ( ++ collection_source, extension_name); ++ collection_identity = e_source_collection_get_identity ( ++ collection_extension); ++ ++ extension_name = E_SOURCE_EXTENSION_AUTHENTICATION; ++ auth_child_extension = e_source_get_extension ( ++ 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); ++ ++ if (auth_child_user == NULL) ++ e_source_authentication_set_user ( ++ auth_child_extension, ++ collection_identity); ++ ++ if (e_source_has_extension (child_source, E_SOURCE_EXTENSION_MAIL_ACCOUNT) || ++ e_source_has_extension (child_source, E_SOURCE_EXTENSION_MAIL_TRANSPORT)) { ++ yandex_backend_mail_update_auth_method (backend, child_source, collection_source); ++ g_signal_connect ( ++ child_source, "notify::oauth2-support", ++ G_CALLBACK (yandex_backend_mail_update_auth_method_cb), ++ backend); ++ } ++ } ++ ++ extension_name = E_SOURCE_EXTENSION_CALENDAR; ++ if (e_source_has_extension (child_source, extension_name)) { ++ ESourceAlarms *alarms_extension; ++ ++ /* To not notify about past reminders. */ ++ alarms_extension = e_source_get_extension (child_source, E_SOURCE_EXTENSION_ALARMS); ++ if (!e_source_alarms_get_last_notified (alarms_extension)) { ++ GTimeVal today_tv; ++ gchar *today; ++ ++ g_get_current_time (&today_tv); ++ today = g_time_val_to_iso8601 (&today_tv); ++ e_source_alarms_set_last_notified (alarms_extension, today); ++ g_free (today); ++ } ++ ++ yandex_backend_calendar_update_auth_method (backend, child_source, collection_source); ++ g_signal_connect ( ++ child_source, "notify::oauth2-support", ++ G_CALLBACK (yandex_backend_calendar_update_auth_method_cb), ++ backend); ++ } ++ ++} ++ ++static void ++yandex_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_yandex_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); ++ } ++} ++ ++static void ++e_yandex_backend_class_init (EYandexBackendClass *class) ++{ ++ EBackendClass *backend_class; ++ ECollectionBackendClass *collection_backend_class; ++ EWebDAVCollectionBackendClass *webdav_collection_backend_class; ++ ++ backend_class = E_BACKEND_CLASS (class); ++ backend_class->authenticate_sync = yandex_backend_authenticate_sync; ++ ++ collection_backend_class = E_COLLECTION_BACKEND_CLASS (class); ++ collection_backend_class->child_added = yandex_backend_child_added; ++ collection_backend_class->populate = yandex_backend_populate; ++ collection_backend_class->dup_resource_id = yandex_backend_dup_resource_id; ++ collection_backend_class->child_removed = yandex_backend_child_removed; ++ ++ webdav_collection_backend_class = E_WEBDAV_COLLECTION_BACKEND_CLASS (class); ++ webdav_collection_backend_class->get_resource_id = yandex_backend_get_resource_id; ++ webdav_collection_backend_class->is_custom_source = yandex_backend_is_custom_source; ++} ++ ++static void ++e_yandex_backend_class_finalize (EYandexBackendClass *class) ++{ ++} ++ ++static void ++e_yandex_backend_init (EYandexBackend *backend) ++{ ++} ++ ++static void ++yandex_backend_prepare_mail_account_source (ESource *source) ++{ ++ ESourceCamel *camel_extension; ++ ESourceExtension *extension; ++ CamelSettings *settings; ++ const gchar *backend_name; ++ const gchar *extension_name; ++ ++ backend_name = YANDEX_IMAP_BACKEND_NAME; ++ ++ extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; ++ extension = e_source_get_extension (source, extension_name); ++ ++ e_source_backend_set_backend_name ( ++ E_SOURCE_BACKEND (extension), backend_name); ++ ++ extension_name = e_source_camel_get_extension_name (backend_name); ++ camel_extension = e_source_get_extension (source, extension_name); ++ settings = e_source_camel_get_settings (camel_extension); ++ ++ /* The "auth-mechanism" should be determined elsewhere. */ ++ ++ camel_network_settings_set_host ( ++ CAMEL_NETWORK_SETTINGS (settings), ++ YANDEX_IMAP_HOST); ++ ++ camel_network_settings_set_port ( ++ CAMEL_NETWORK_SETTINGS (settings), ++ YANDEX_IMAP_PORT); ++ ++ camel_network_settings_set_security_method ( ++ CAMEL_NETWORK_SETTINGS (settings), ++ YANDEX_IMAP_SECURITY_METHOD); ++} ++ ++static void ++yandex_backend_prepare_mail_transport_source (ESource *source) ++{ ++ ESourceCamel *camel_extension; ++ ESourceExtension *extension; ++ CamelSettings *settings; ++ const gchar *backend_name; ++ const gchar *extension_name; ++ ++ /* Configure the mail transport source. */ ++ ++ backend_name = YANDEX_SMTP_BACKEND_NAME; ++ ++ extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT; ++ extension = e_source_get_extension (source, extension_name); ++ ++ e_source_backend_set_backend_name ( ++ E_SOURCE_BACKEND (extension), backend_name); ++ ++ extension_name = e_source_camel_get_extension_name (backend_name); ++ camel_extension = e_source_get_extension (source, extension_name); ++ settings = e_source_camel_get_settings (camel_extension); ++ ++ /* The "auth-mechanism" should be determined elsewhere. */ ++ ++ camel_network_settings_set_host ( ++ CAMEL_NETWORK_SETTINGS (settings), ++ YANDEX_SMTP_HOST); ++ ++ camel_network_settings_set_port ( ++ CAMEL_NETWORK_SETTINGS (settings), ++ YANDEX_SMTP_PORT); ++ ++ camel_network_settings_set_security_method ( ++ CAMEL_NETWORK_SETTINGS (settings), ++ YANDEX_SMTP_SECURITY_METHOD); ++} ++ ++static void ++yandex_backend_factory_prepare_mail (ECollectionBackendFactory *factory, ++ ESource *mail_account_source, ++ ESource *mail_identity_source, ++ ESource *mail_transport_source) ++{ ++ ECollectionBackendFactoryClass *parent_class; ++ ++ /* Chain up to parent's prepare_mail() method. */ ++ parent_class = ++ E_COLLECTION_BACKEND_FACTORY_CLASS ( ++ e_yandex_backend_factory_parent_class); ++ parent_class->prepare_mail ( ++ factory, ++ mail_account_source, ++ mail_identity_source, ++ mail_transport_source); ++ ++ yandex_backend_prepare_mail_account_source (mail_account_source); ++ yandex_backend_prepare_mail_transport_source (mail_transport_source); ++} ++ ++static void ++e_yandex_backend_factory_class_init (EYandexBackendFactoryClass *class) ++{ ++ ECollectionBackendFactoryClass *factory_class; ++ ++ factory_class = E_COLLECTION_BACKEND_FACTORY_CLASS (class); ++ factory_class->factory_name = "yandex"; ++ factory_class->backend_type = E_TYPE_YANDEX_BACKEND; ++ factory_class->prepare_mail = yandex_backend_factory_prepare_mail; ++} ++ ++static void ++e_yandex_backend_factory_class_finalize (EYandexBackendFactoryClass *class) ++{ ++} ++ ++static void ++e_yandex_backend_factory_init (EYandexBackendFactory *factory) ++{ ++} ++ ++G_MODULE_EXPORT void ++e_module_load (GTypeModule *type_module) ++{ ++ e_yandex_backend_register_type (type_module); ++ e_yandex_backend_factory_register_type (type_module); ++} ++ ++G_MODULE_EXPORT void ++e_module_unload (GTypeModule *type_module) ++{ ++} ++ +-- +2.39.5 + diff --git a/SPECS/evolution-data-server.spec b/SPECS/evolution-data-server.spec index 5b7d894..1916516 100644 --- a/SPECS/evolution-data-server.spec +++ b/SPECS/evolution-data-server.spec @@ -54,7 +54,7 @@ Name: evolution-data-server Version: 3.54.2 -Release: 1%{?dist} +Release: 1%{?dist}.inferit Summary: Backend data server for Evolution License: LGPL-2.0-or-later URL: https://gitlab.gnome.org/GNOME/evolution/-/wikis/home @@ -66,6 +66,9 @@ Source: http://download.gnome.org/sources/%{name}/3.54/%{name}-%{version}.tar.xz # https://gitlab.gnome.org/GNOME/evolution-data-server/-/merge_requests/144 Patch100: Make-DBUS_SERVICES_PREFIX-runtime-configurable.patch +# MSVSphere +Patch1: 0001-Added-yandex-backend-support-prebuild.patch + Provides: evolution-webcal = %{version} Obsoletes: evolution-webcal < 2.24.0 @@ -136,6 +139,9 @@ BuildRequires: boost-devel BuildRequires: abseil-cpp-devel %endif +%global debug_package %{nil} +%define _build_id_links none + # libical 3.0.16 added new API, this ensures to bring it in Requires: libical-glib >= %{libical_version} @@ -431,6 +437,7 @@ find $RPM_BUILD_ROOT -name '*.so.*' -exec chmod +x {} \; %{ecal_backends_dir}/libecalbackendwebdavnotes.so %{modules_dir}/module-cache-reaper.so %{modules_dir}/module-google-backend.so +%{modules_dir}/module-yandex-backend.so %{modules_dir}/module-gnome-online-accounts.so %{modules_dir}/module-oauth2-services.so %{modules_dir}/module-outlook-backend.so @@ -513,6 +520,9 @@ find $RPM_BUILD_ROOT -name '*.so.*' -exec chmod +x {} \; %{_datadir}/installed-tests %changelog +* Wed Feb 12 2025 Dmitriy Samoylik - 3.54.2-1.inferit +- Added yandex backend support prebuild + * Wed Dec 25 2024 Eduard Basov - 3.54.2-1 - Rebuilt for MSVSphere 10