You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
evolution-data-server/SOURCES/0001-Added-yandex-backend-s...

1610 lines
54 KiB

From 1c142459975a8703b6a5771f576a1e3736360954 Mon Sep 17 00:00:00 2001
From: Alexey Berezhok <alexey.berezhok@softline.com>
Date: Mon, 15 May 2023 19:07:27 +0300
Subject: [PATCH] Added yandex backend support(prebuild)
---
.gitignore | 1 +
.vscode/c_cpp_properties.json | 3 +-
CMakeLists.txt | 11 +
config.h.in | 6 +
...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 | 3 +
src/libedataserver/e-soup-session.c | 22 +
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 | 727 ++++++++++++++++++
26 files changed, 1229 insertions(+), 3 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/.gitignore b/.gitignore
index 726890e..575a9f0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@ _build
.build
*.orig
*.rej
+.vscode/
diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json
index a070080..6cc85df 100644
--- a/.vscode/c_cpp_properties.json
+++ b/.vscode/c_cpp_properties.json
@@ -6,7 +6,8 @@
"${workspaceFolder}/**",
"/usr/include/goa-1.0",
"/usr/include/glib-2.0",
- "/usr/lib64/glib-2.0/include/"
+ "/usr/lib64/glib-2.0/include/",
+ "/usr/include/libsoup-2.4"
],
"defines": [],
"compilerPath": "/usr/bin/gcc",
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/data/org.gnome.evolution-data-server.gschema.xml.in b/data/org.gnome.evolution-data-server.gschema.xml.in
index 98defd4..5d5b2bb 100644
--- a/data/org.gnome.evolution-data-server.gschema.xml.in
+++ b/data/org.gnome.evolution-data-server.gschema.xml.in
@@ -81,5 +81,15 @@
<_summary>An OAuth2 client secret to use to connect to Yahoo! servers, instead of the one provided during build time</_summary>
<_description>User-specified OAuth2 client secret for Yahoo! servers. Empty string means to use the one provided during build time. Change of this requires restart.</_description>
</key>
+ <key name="oauth2-yandex-client-id" type="s">
+ <default>''</default>
+ <_summary>An OAuth2 client ID to use to connect to Yandex servers, instead of the one provided during build time</_summary>
+ <_description>User-specified OAuth2 client ID for Yandex servers. Empty string means to use the one provided during build time. Change of this requires restart.</_description>
+ </key>
+ <key name="oauth2-yandex-client-secret" type="s">
+ <default>''</default>
+ <_summary>An OAuth2 client secret to use to connect to Yandex servers, instead of the one provided during build time</_summary>
+ <_description>User-specified OAuth2 client secret for Yandex servers. Empty string means to use the one provided during build time. Change of this requires restart.</_description>
+ </key>
</schema>
</schemalist>
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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "evolution-data-server-config.h"
+
+#include <glib/gi18n-lib.h>
+
+#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 <http://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__CAMEL_H_INSIDE__) && !defined (CAMEL_COMPILATION)
+#error "Only <camel/camel.h> can be included directly."
+#endif
+
+#ifndef CAMEL_SASL_XOAUTH2_YANDEX_H
+#define CAMEL_SASL_XOAUTH2_YANDEX_H
+
+#include <camel/camel-sasl-xoauth2.h>
+
+/* 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 <camel/camel-sasl-popb4smtp.h>
#include <camel/camel-sasl-xoauth2.h>
#include <camel/camel-sasl-xoauth2-google.h>
+#include <camel/camel-sasl-xoauth2-yandex.h>
#include <camel/camel-sasl-xoauth2-outlook.h>
#include <camel/camel-sasl-xoauth2-yahoo.h>
#include <camel/camel-service.h>
diff --git a/src/libebackend/e-webdav-collection-backend.c b/src/libebackend/e-webdav-collection-backend.c
index b99f175..abc3829 100644
--- a/src/libebackend/e-webdav-collection-backend.c
+++ b/src/libebackend/e-webdav-collection-backend.c
@@ -360,7 +360,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 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..64ac387
--- /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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "evolution-data-server-config.h"
+
+#include <glib/gi18n-lib.h>
+
+#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 */
+ "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) {
+ 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, "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 <http://www.gnu.org/licenses/>.
+ */
+
+#if !defined (__LIBEDATASERVER_H_INSIDE__) && !defined (LIBEDATASERVER_COMPILATION)
+#error "Only <libedataserver/libedataserver.h> should be included directly."
+#endif
+
+#ifndef E_OAUTH2_SERVICE_YANDEX_H
+#define E_OAUTH2_SERVICE_YANDEX_H
+
+#include <libedataserver/e-oauth2-service-base.h>
+
+/* 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/e-soup-auth-bearer.c b/src/libedataserver/e-soup-auth-bearer.c
index 78fd131..0d4ee85 100644
--- a/src/libedataserver/e-soup-auth-bearer.c
+++ b/src/libedataserver/e-soup-auth-bearer.c
@@ -39,11 +39,14 @@
#define AUTH_STRENGTH 1
#define EXPIRY_INVALID ((time_t) -1)
+#define DEFAULT_BEARER_AUTH (gchar)0
+#define MAX_CUSTOM_BEARER_ID 16
struct _ESoupAuthBearerPrivate {
GMutex property_lock;
gchar *access_token;
time_t expiry;
+ gchar is_custom_bearer[MAX_CUSTOM_BEARER_ID];
};
G_DEFINE_TYPE_WITH_PRIVATE (
@@ -138,7 +141,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);
g_mutex_unlock (&bearer->priv->property_lock);
@@ -171,6 +177,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);
}
@@ -249,3 +256,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..b08fd37 100644
--- a/src/libedataserver/e-soup-auth-bearer.h
+++ b/src/libedataserver/e-soup-auth-bearer.h
@@ -73,6 +73,9 @@ void e_soup_auth_bearer_set_access_token
const gchar *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
diff --git a/src/libedataserver/e-soup-session.c b/src/libedataserver/e-soup-session.c
index 381b9f8..a633988 100644
--- a/src/libedataserver/e-soup-session.c
+++ b/src/libedataserver/e-soup-session.c
@@ -163,16 +163,32 @@ 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 (soup_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);
@@ -185,6 +201,12 @@ e_soup_session_maybe_prepare_bearer_auth (ESoupSession *session,
E_TYPE_SOUP_AUTH_BEARER,
SOUP_AUTH_HOST, soup_uri->host, 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_mutex_lock (&session->priv->property_lock);
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 <libedataserver/e-oauth2-service.h>
#include <libedataserver/e-oauth2-service-base.h>
#include <libedataserver/e-oauth2-service-google.h>
+#include <libedataserver/e-oauth2-service-yandex.h>
#include <libedataserver/e-oauth2-service-outlook.h>
#include <libedataserver/e-oauth2-service-yahoo.h>
#include <libedataserver/e-oauth2-services.h>
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..bb6dfc1
--- /dev/null
+++ b/src/modules/yandex-backend/module-yandex-backend.c
@@ -0,0 +1,727 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "evolution-data-server-config.h"
+
+#include <glib/gi18n-lib.h>
+
+#include <libebackend/libebackend.h>
+
+/* 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 void
+yandex_backend_add_contacts (ECollectionBackend *backend)
+{
+ ESource *source;
+ ESource *collection_source;
+ ESourceRegistryServer *server;
+ ESourceExtension *extension;
+ ESourceCollection *collection_extension;
+ const gchar *backend_name;
+ const gchar *extension_name;
+ const gchar *resource_id;
+
+ collection_source = e_backend_get_source (E_BACKEND (backend));
+
+ resource_id = YANDEX_CONTACTS_RESOURCE_ID;
+ source = e_collection_backend_new_child (backend, resource_id);
+ e_source_set_display_name (source, _("Contacts"));
+
+ /* Add the address book source to the collection. */
+ collection_extension = e_source_get_extension (
+ collection_source, E_SOURCE_EXTENSION_COLLECTION);
+
+ /* Configure the address book source. */
+
+ backend_name = YANDEX_CONTACTS_BACKEND_NAME;
+
+ extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK;
+ extension = e_source_get_extension (source, extension_name);
+
+ e_source_backend_set_backend_name (
+ E_SOURCE_BACKEND (extension), backend_name);
+
+ extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
+ extension = e_source_get_extension (source, extension_name);
+
+ e_source_authentication_set_host (
+ E_SOURCE_AUTHENTICATION (extension),
+ YANDEX_CONTACTS_HOST);
+
+ e_binding_bind_property (
+ collection_extension, "identity",
+ extension, "user",
+ G_BINDING_SYNC_CREATE);
+
+ server = e_collection_backend_ref_server (backend);
+ e_source_registry_server_add_source (server, source);
+ g_object_unref (server);
+
+ g_object_unref (source);
+}
+
+static gchar *
+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);
+
+ if (e_source_collection_get_contacts_enabled (collection_extension)) {
+ GList *list;
+
+ list = e_collection_backend_list_contacts_sources (backend);
+ if (list == NULL)
+ yandex_backend_add_contacts (backend);
+ g_list_free_full (list, (GDestroyNotify) g_object_unref);
+ }
+}
+
+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 void
+yandex_backend_contacts_update_auth_method (ESource *child_source,
+ ESource *master_source)
+{
+ EOAuth2Support *oauth2_support;
+ ESourceAuthentication *extension;
+ const gchar *method;
+
+ extension = e_source_get_extension (child_source, E_SOURCE_EXTENSION_AUTHENTICATION);
+
+ if (!yandex_backend_is_yandex_host (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 = "OAuth2";
+ else
+ method = NULL;
+
+ e_source_authentication_set_method (extension, method);
+
+ g_clear_object (&oauth2_support);
+}
+
+static void
+yandex_backend_contacts_update_auth_method_cb (ESource *child_source,
+ GParamSpec *param,
+ EBackend *backend)
+{
+ yandex_backend_contacts_update_auth_method (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);
+ }
+
+ extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK;
+ if (e_source_has_extension (child_source, extension_name)) {
+ yandex_backend_contacts_update_auth_method (child_source, collection_source);
+ g_signal_connect (
+ child_source, "notify::oauth2-support",
+ G_CALLBACK (yandex_backend_contacts_update_auth_method_cb),
+ backend);
+
+ if (!has_external_auth) {
+ /* Even the book is part of the collection it can be removed
+ separately, if not configured through GOA or UOA. */
+ e_server_side_source_set_removable (E_SERVER_SIDE_SOURCE (child_source), TRUE);
+ }
+ }
+}
+
+static void
+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.1