From 77baaa791bb6af10ca7530b4fbe327f2de14a62d Mon Sep 17 00:00:00 2001 From: Alexey Berezhok Date: Wed, 3 May 2023 13:10:40 +0300 Subject: [PATCH] Added yandex backend (patch only) --- ...dded-yandex-backend-support-prebuild.patch | 1316 +++++++++++++++++ 1 file changed, 1316 insertions(+) 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..01bdb3f --- /dev/null +++ b/SOURCES/0001-Added-yandex-backend-support-prebuild.patch @@ -0,0 +1,1316 @@ +From 57f0eb558fed22ab09ac9937f264f8d1952fca6d Mon Sep 17 00:00:00 2001 +From: Alexey Berezhok +Date: Wed, 3 May 2023 13:03:16 +0300 +Subject: [PATCH] Added yandex backend support(prebuild) + +--- + .gitignore | 1 + + CMakeLists.txt | 11 + + config.h.in | 6 + + 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/libedataserver/CMakeLists.txt | 2 + + .../e-dataserver-autocleanups.h | 1 + + src/libedataserver/e-oauth2-service-yandex.c | 227 +++++++ + src/libedataserver/e-oauth2-service-yandex.h | 62 ++ + src/libedataserver/e-oauth2-services.c | 2 + + src/libedataserver/libedataserver.h | 1 + + src/modules/CMakeLists.txt | 1 + + .../module-gnome-online-accounts.c | 3 + + src/modules/yandex-backend/CMakeLists.txt | 23 + + .../yandex-backend/module-yandex-backend.c | 594 ++++++++++++++++++ + 21 files changed, 1052 insertions(+), 1 deletion(-) + 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/.gitignore b/.gitignore +index 726890e..575a9f0 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -3,3 +3,4 @@ _build + .build + *.orig + *.rej ++.vscode/ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 2bad65e..d7deb4a 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -435,6 +435,17 @@ if(ENABLE_OAUTH2) + if(WITH_YAHOO_CLIENT_SECRET STREQUAL "") + set(WITH_YAHOO_CLIENT_SECRET "35f49f199dd754ec5e86d3c7cd576a1341c9bc0b") + 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 "8ef866ab7a1f4d3b8fcb58510d422fbc") ++ endif(WITH_YANDEX_CLIENT_ID STREQUAL "") ++ ++ if(WITH_YANDEX_CLIENT_SECRET STREQUAL "") ++ set(WITH_YANDEX_CLIENT_SECRET "aa8be6b692dc4465b1fa40ae6ec7a377") ++ endif(WITH_YANDEX_CLIENT_SECRET STREQUAL "") + endif(ENABLE_OAUTH2) + + # ****************************************** +diff --git a/config.h.in b/config.h.in +index bd2978a..cdd864e 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -51,6 +51,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/po/POTFILES.in b/po/POTFILES.in +index 9a25ab5..10dfcf8 100644 +--- a/po/POTFILES.in ++++ b/po/POTFILES.in +@@ -118,6 +118,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 +@@ -225,6 +227,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 2ba609b..26b2033 100644 +--- a/src/camel/CMakeLists.txt ++++ b/src/camel/CMakeLists.txt +@@ -108,6 +108,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 +@@ -250,6 +251,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 0ff82a2..fb6595a 100644 +--- a/src/camel/camel-autocleanups.h ++++ b/src/camel/camel-autocleanups.h +@@ -111,6 +111,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 0a09c55..82cc3cb 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 0df1baf..9c71ab7 100644 +--- a/src/camel/camel.h ++++ b/src/camel/camel.h +@@ -110,6 +110,7 @@ + #include + #include + #include ++#include + #include + #include + #include +diff --git a/src/libedataserver/CMakeLists.txt b/src/libedataserver/CMakeLists.txt +index b196ae2..49a8471 100644 +--- a/src/libedataserver/CMakeLists.txt ++++ b/src/libedataserver/CMakeLists.txt +@@ -69,6 +69,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-proxy.c +@@ -160,6 +161,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-proxy.h +diff --git a/src/libedataserver/e-dataserver-autocleanups.h b/src/libedataserver/e-dataserver-autocleanups.h +index bc3c81a..93b4e14 100644 +--- a/src/libedataserver/e-dataserver-autocleanups.h ++++ b/src/libedataserver/e-dataserver-autocleanups.h +@@ -39,6 +39,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..19e9453 +--- /dev/null ++++ b/src/libedataserver/e-oauth2-service-yandex.c +@@ -0,0 +1,227 @@ ++/* ++ * 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-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 */ ++ "ogin:email login:info mail:imap_full mail:imap_ro mail:smtp"; ++ ++ 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_title && *page_title) { ++ /* Known response, but no authorization code */ ++ if (g_ascii_strncasecmp (page_title, "Denied ", 7) == 0) ++ return TRUE; ++ ++ if (g_ascii_strncasecmp (page_title, "Success code=", 13) == 0) { ++ *out_authorization_code = g_strdup (page_title + 13); ++ return TRUE; ++ } ++ } ++ ++ if (page_uri && *page_uri) { ++ SoupURI *suri; ++ ++ suri = soup_uri_new (page_uri); ++ if (suri) { ++ const gchar *query = soup_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, "response"); ++ if (response && g_ascii_strncasecmp (response, "code=", 5) == 0) { ++ *out_authorization_code = g_strdup (response + 5); ++ known = TRUE; ++ } else if (response && g_ascii_strncasecmp (response, "error", 5) == 0) { ++ 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 838b007..3679cea 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/libedataserver.h b/src/libedataserver/libedataserver.h +index 34e71cb..e573344 100644 +--- a/src/libedataserver/libedataserver.h ++++ b/src/libedataserver/libedataserver.h +@@ -41,6 +41,7 @@ + #include + #include + #include ++#include + #include + #include + #include +diff --git a/src/modules/CMakeLists.txt b/src/modules/CMakeLists.txt +index d43357c..f4fafce 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) + + if(ENABLE_OAUTH2) + add_subdirectory(oauth2-services) +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 03c4930..9d10d6d 100644 +--- a/src/modules/gnome-online-accounts/module-gnome-online-accounts.c ++++ b/src/modules/gnome-online-accounts/module-gnome-online-accounts.c +@@ -120,6 +120,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..2416fa1 +--- /dev/null ++++ b/src/modules/yandex-backend/CMakeLists.txt +@@ -0,0 +1,23 @@ ++set(extra_deps) ++if(HAVE_LIBGDATA) ++ set(sources ++ module-yandex-backend.c ++ ) ++else(HAVE_LIBGDATA) ++ set(sources ++ module-yandex-backend.c ++ ) ++endif(HAVE_LIBGDATA) ++set(extra_defines) ++set(extra_cflags ${LIBGDATA_CFLAGS}) ++set(extra_incdirs ${LIBGDATA_INCLUDE_DIRS}) ++set(extra_ldflags ${LIBGDATA_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..31e6f2e +--- /dev/null ++++ b/src/modules/yandex-backend/module-yandex-backend.c +@@ -0,0 +1,594 @@ ++/* ++ * 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 ++#include ++ ++#ifdef HAVE_LIBGDATA ++#include ++#endif ++ ++/* 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) ++ ++#define YANDEX_OAUTH2_METHOD "Yandex" ++ ++/* 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) ++ ++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 gboolean ++yandex_backend_can_use_yandex_auth (ESource *source) ++{ ++ ESourceRegistryServer *registry; ++ ESourceAuthentication *auth_extension; ++ gboolean res; ++ ++ g_return_val_if_fail (E_IS_SERVER_SIDE_SOURCE (source), FALSE); ++ ++ registry = e_server_side_source_get_server (E_SERVER_SIDE_SOURCE (source)); ++ if (!e_oauth2_services_is_oauth2_alias (e_source_registry_server_get_oauth2_services (registry), YANDEX_OAUTH2_METHOD)) ++ return FALSE; ++ ++ g_object_ref (source); ++ ++ while (source && e_source_get_parent (source)) { ++ ESource *adept_source; ++ ++ adept_source = e_source_registry_server_ref_source (registry, e_source_get_parent (source)); ++ if (adept_source) { ++ g_object_unref (source); ++ source = adept_source; ++ } else { ++ break; ++ } ++ } ++ ++ auth_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION); ++ res = !e_source_authentication_get_is_external (auth_extension); ++ ++ g_object_unref (source); ++ ++ return res; ++} ++ ++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; ++ gboolean requires_oauth2; ++ gchar *host; ++ ++ g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATION (auth_extension), FALSE); ++ ++ host = e_source_authentication_dup_host (auth_extension); ++ ++ requires_oauth2 = (host != NULL); ++ ++ is_yandex = requires_oauth2 || (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 = requires_oauth2; ++ ++ return is_yandex; ++} ++ ++static gboolean ++yandex_backend_is_oauth2 (const gchar *method) ++{ ++ return g_strcmp0 (method, YANDEX_OAUTH2_METHOD) == 0 || ++ g_strcmp0 (method, "OAuth2") == 0 || ++ g_strcmp0 (method, "XOAUTH2") == 0; ++} ++ ++static gboolean ++yandex_backend_can_change_auth_method (ESourceAuthentication *auth_extension, ++ const gchar *new_method) ++{ ++ gchar *cur_method; ++ gboolean can_change; ++ ++ g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATION (auth_extension), FALSE); ++ ++ if (!new_method) ++ return FALSE; ++ ++ cur_method = e_source_authentication_dup_method (auth_extension); ++ ++ /* Only when turning off OAuth2 */ ++ can_change = yandex_backend_is_oauth2 (cur_method) && !yandex_backend_is_oauth2 (new_method); ++ ++ g_free (cur_method); ++ ++ return can_change; ++} ++ ++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; ++ gboolean can_use_yandex_auth; ++ ++ 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)); ++ ++ can_use_yandex_auth = yandex_backend_can_use_yandex_auth (child_source); ++ if (!can_use_yandex_auth && master_source) ++ can_use_yandex_auth = yandex_backend_can_use_yandex_auth (master_source); ++ ++ if (oauth2_support && !can_use_yandex_auth) { ++ method = "XOAUTH2"; ++ } else if (can_use_yandex_auth) { ++ method = YANDEX_OAUTH2_METHOD; ++ } else { ++ method = NULL; ++ } ++ ++ if (method && (e_collection_backend_is_new_source (collection_backend, child_source) || ++ yandex_backend_can_change_auth_method (auth_extension, method))) ++ 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_remove_unknown_sources_cb (gpointer resource_id, ++ gpointer uid, ++ gpointer user_data) ++{ ++ ESourceRegistryServer *server = user_data; ++ ESource *source; ++ ++ source = e_source_registry_server_ref_source (server, uid); ++ ++ if (source) { ++ e_source_remove_sync (source, NULL, NULL); ++ g_object_unref (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; ++ GHashTable *known_sources; ++ GList *sources; ++ ENamedParameters *credentials_copy = NULL; ++ ++ 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); ++ ++ 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); ++ ++ if (credentials && !e_named_parameters_get (credentials, E_SOURCE_CREDENTIAL_USERNAME)) { ++ credentials_copy = e_named_parameters_new_clone (credentials); ++ e_named_parameters_set (credentials_copy, E_SOURCE_CREDENTIAL_USERNAME, e_source_collection_get_identity (collection_extension)); ++ credentials = credentials_copy; ++ } ++ ++ /* resource-id => source's UID */ ++ known_sources = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); ++ ++ sources = e_collection_backend_list_calendar_sources (collection); ++ g_list_free_full (sources, g_object_unref); ++ ++ /* When the WebDAV extension is created, the auth method can be reset, thus ensure ++ it's there before setting correct authentication method on the master source. */ ++ (void) e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND); ++ ++ result = E_SOURCE_AUTHENTICATION_ACCEPTED; ++ ++ if (result == E_SOURCE_AUTHENTICATION_ACCEPTED) { ++ ESourceRegistryServer *server; ++ ++ server = e_collection_backend_ref_server (collection); ++ ++ if (server) { ++ g_hash_table_foreach (known_sources, yandex_remove_unknown_sources_cb, server); ++ g_object_unref (server); ++ } ++ } ++ ++ g_hash_table_destroy (known_sources); ++ e_named_parameters_free (credentials_copy); ++ ++ e_collection_backend_thaw_populate (collection); ++ ++ return result; ++} ++ ++static void ++yandex_backend_populate (ECollectionBackend *backend) ++{ ++ ESourceAuthentication *authentication_extension; ++ ESource *source; ++ ++ source = e_backend_get_source (E_BACKEND (backend)); ++ 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 ++ it's there before setting correct authentication method on the master source. */ ++ (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, "OAuth2"); ++ ++ /* Chain up to parent's method. */ ++ E_COLLECTION_BACKEND_CLASS (e_yandex_backend_parent_class)->populate (backend); ++ ++} ++ ++static void ++yandex_backend_child_added (ECollectionBackend *backend, ++ ESource *child_source) ++{ ++ ESource *collection_source; ++ const gchar *extension_name; ++ gboolean is_mail = 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); ++ ++ ++ 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); ++ } ++ } ++ ++} ++ ++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; ++ ++ 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->populate = yandex_backend_populate; ++ collection_backend_class->child_added = yandex_backend_child_added; ++ collection_backend_class->child_removed = yandex_backend_child_removed; ++ ++} ++ ++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.1 +