Added yandex backend(patch only) - mail, calendar support

i9
Alexey Berezhok 2 years ago
parent 77baaa791b
commit 089f2b9af5

@ -1,30 +1,42 @@
From 57f0eb558fed22ab09ac9937f264f8d1952fca6d Mon Sep 17 00:00:00 2001
From ee73290b8ce8d9f3b1b42dc4ddc8a3c8d649778d Mon Sep 17 00:00:00 2001
From: Alexey Berezhok <alexey.berezhok@softline.com>
Date: Wed, 3 May 2023 13:03:16 +0300
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 +
.../backends/google/e-book-backend-google.c | 1 +
.../backends/google/e-book-google-utils.c | 2 +-
src/addressbook/libebook-contacts/e-contact.c | 10 +-
src/addressbook/libebook-contacts/e-contact.h | 7 +
src/addressbook/libebook-contacts/e-vcard.h | 1 +
.../libedata-book/e-book-backend-sexp.c | 11 +
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 | 227 +++++++
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 | 594 ++++++++++++++++++
21 files changed, 1052 insertions(+), 1 deletion(-)
.../yandex-backend/module-yandex-backend.c | 727 ++++++++++++++++++
32 files changed, 1259 insertions(+), 5 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
@ -41,6 +53,20 @@ index 726890e..575a9f0 100644
*.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
@ -80,6 +106,26 @@ index bd2978a..cdd864e 100644
/* 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
@ -108,6 +154,132 @@ index 9a25ab5..10dfcf8 100644
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/addressbook/backends/google/e-book-backend-google.c b/src/addressbook/backends/google/e-book-backend-google.c
index 4597169..043f174 100644
--- a/src/addressbook/backends/google/e-book-backend-google.c
+++ b/src/addressbook/backends/google/e-book-backend-google.c
@@ -1159,6 +1159,7 @@ ebb_google_get_backend_property (EBookBackend *book_backend,
e_contact_field_name (E_CONTACT_IM_AIM),
e_contact_field_name (E_CONTACT_IM_JABBER),
e_contact_field_name (E_CONTACT_IM_YAHOO),
+ e_contact_field_name (E_CONTACT_IM_YANDEX),
e_contact_field_name (E_CONTACT_IM_MSN),
e_contact_field_name (E_CONTACT_IM_ICQ),
e_contact_field_name (E_CONTACT_IM_SKYPE),
diff --git a/src/addressbook/backends/google/e-book-google-utils.c b/src/addressbook/backends/google/e-book-google-utils.c
index 3b14a4e..ed70a4b 100644
--- a/src/addressbook/backends/google/e-book-google-utils.c
+++ b/src/addressbook/backends/google/e-book-google-utils.c
@@ -1095,7 +1095,7 @@ static gboolean
is_known_google_im_protocol (const gchar *protocol)
{
const gchar *known_protocols[] = {
- "AIM", "MSN", "YAHOO", "SKYPE", "QQ",
+ "AIM", "MSN", "YAHOO", "YANDEX", "SKYPE", "QQ",
"GOOGLE-TALK", "ICQ", "JABBER"
};
guint i;
diff --git a/src/addressbook/libebook-contacts/e-contact.c b/src/addressbook/libebook-contacts/e-contact.c
index 54f14fd..b0f1534 100644
--- a/src/addressbook/libebook-contacts/e-contact.c
+++ b/src/addressbook/libebook-contacts/e-contact.c
@@ -75,7 +75,8 @@ static AttrTypeValue glob_attr_type_values[] = {
{ EVC_X_JABBER, "WORK;HOME" },
{ EVC_X_MSN, "WORK;HOME" },
{ EVC_X_SKYPE, "WORK;HOME" },
- { EVC_X_YAHOO, "WORK;HOME" }
+ { EVC_X_YAHOO, "WORK;HOME" },
+ { EVC_X_YANDEX, "WORK;HOME" }
};
#define E_CONTACT_FIELD_TYPE_STRING 0x00000001 /* used for simple single valued attributes */
@@ -249,6 +250,12 @@ static const EContactFieldInfo field_info[] = {
ATTR_TYPE_STR_FIELD (E_CONTACT_IM_YAHOO_WORK_1, EVC_X_YAHOO, "im_yahoo_work_1", N_("Yahoo! Work Screen Name 1"), FALSE, "WORK", 0),
ATTR_TYPE_STR_FIELD (E_CONTACT_IM_YAHOO_WORK_2, EVC_X_YAHOO, "im_yahoo_work_2", N_("Yahoo! Work Screen Name 2"), FALSE, "WORK", 1),
ATTR_TYPE_STR_FIELD (E_CONTACT_IM_YAHOO_WORK_3, EVC_X_YAHOO, "im_yahoo_work_3", N_("Yahoo! Work Screen Name 3"), FALSE, "WORK", 2),
+ ATTR_TYPE_STR_FIELD (E_CONTACT_IM_YANDEX_HOME_1, EVC_X_YANDEX, "im_yandex_home_1", N_("Yandex Home Screen Name 1"), FALSE, "HOME", 0),
+ ATTR_TYPE_STR_FIELD (E_CONTACT_IM_YANDEX_HOME_2, EVC_X_YANDEX, "im_yandex_home_2", N_("Yandex Home Screen Name 2"), FALSE, "HOME", 1),
+ ATTR_TYPE_STR_FIELD (E_CONTACT_IM_YANDEX_HOME_3, EVC_X_YANDEX, "im_yandex_home_3", N_("Yandex Home Screen Name 3"), FALSE, "HOME", 2),
+ ATTR_TYPE_STR_FIELD (E_CONTACT_IM_YANDEX_WORK_1, EVC_X_YANDEX, "im_yandex_work_1", N_("Yandex Work Screen Name 1"), FALSE, "WORK", 0),
+ ATTR_TYPE_STR_FIELD (E_CONTACT_IM_YANDEX_WORK_2, EVC_X_YANDEX, "im_yandex_work_2", N_("Yandex Work Screen Name 2"), FALSE, "WORK", 1),
+ ATTR_TYPE_STR_FIELD (E_CONTACT_IM_YANDEX_WORK_3, EVC_X_YANDEX, "im_yandex_work_3", N_("Yandex Work Screen Name 3"), FALSE, "WORK", 2),
ATTR_TYPE_STR_FIELD (E_CONTACT_IM_MSN_HOME_1, EVC_X_MSN, "im_msn_home_1", N_("MSN Home Screen Name 1"), FALSE, "HOME", 0),
ATTR_TYPE_STR_FIELD (E_CONTACT_IM_MSN_HOME_2, EVC_X_MSN, "im_msn_home_2", N_("MSN Home Screen Name 2"), FALSE, "HOME", 1),
ATTR_TYPE_STR_FIELD (E_CONTACT_IM_MSN_HOME_3, EVC_X_MSN, "im_msn_home_3", N_("MSN Home Screen Name 3"), FALSE, "HOME", 2),
@@ -292,6 +299,7 @@ static const EContactFieldInfo field_info[] = {
MULTI_LIST_FIELD (E_CONTACT_IM_GROUPWISE, EVC_X_GROUPWISE, "im_groupwise", N_("GroupWise ID List"), FALSE),
MULTI_LIST_FIELD (E_CONTACT_IM_JABBER, EVC_X_JABBER, "im_jabber", N_("Jabber ID List"), FALSE),
MULTI_LIST_FIELD (E_CONTACT_IM_YAHOO, EVC_X_YAHOO, "im_yahoo", N_("Yahoo! Screen Name List"), FALSE),
+ MULTI_LIST_FIELD (E_CONTACT_IM_YANDEX, EVC_X_YANDEX, "im_yandex", N_("Yandex Screen Name List"), FALSE),
MULTI_LIST_FIELD (E_CONTACT_IM_MSN, EVC_X_MSN, "im_msn", N_("MSN Screen Name List"), FALSE),
MULTI_LIST_FIELD (E_CONTACT_IM_ICQ, EVC_X_ICQ, "im_icq", N_("ICQ ID List"), FALSE),
diff --git a/src/addressbook/libebook-contacts/e-contact.h b/src/addressbook/libebook-contacts/e-contact.h
index 3f1e084..b5d9ef5 100644
--- a/src/addressbook/libebook-contacts/e-contact.h
+++ b/src/addressbook/libebook-contacts/e-contact.h
@@ -159,6 +159,12 @@ typedef enum {
E_CONTACT_IM_YAHOO_WORK_1, /* Synthetic string field */
E_CONTACT_IM_YAHOO_WORK_2, /* Synthetic string field */
E_CONTACT_IM_YAHOO_WORK_3, /* Synthetic string field */
+ E_CONTACT_IM_YANDEX_HOME_1, /* Synthetic string field */
+ E_CONTACT_IM_YANDEX_HOME_2, /* Synthetic string field */
+ E_CONTACT_IM_YANDEX_HOME_3, /* Synthetic string field */
+ E_CONTACT_IM_YANDEX_WORK_1, /* Synthetic string field */
+ E_CONTACT_IM_YANDEX_WORK_2, /* Synthetic string field */
+ E_CONTACT_IM_YANDEX_WORK_3, /* Synthetic string field */
E_CONTACT_IM_MSN_HOME_1, /* Synthetic string field */
E_CONTACT_IM_MSN_HOME_2, /* Synthetic string field */
E_CONTACT_IM_MSN_HOME_3, /* Synthetic string field */
@@ -198,6 +204,7 @@ typedef enum {
E_CONTACT_IM_GROUPWISE, /* Multi-valued */
E_CONTACT_IM_JABBER, /* Multi-valued */
E_CONTACT_IM_YAHOO, /* Multi-valued */
+ E_CONTACT_IM_YANDEX, /* Multi-valued */
E_CONTACT_IM_MSN, /* Multi-valued */
E_CONTACT_IM_ICQ, /* Multi-valued */
diff --git a/src/addressbook/libebook-contacts/e-vcard.h b/src/addressbook/libebook-contacts/e-vcard.h
index 9efcb3d..9a31ad7 100644
--- a/src/addressbook/libebook-contacts/e-vcard.h
+++ b/src/addressbook/libebook-contacts/e-vcard.h
@@ -135,6 +135,7 @@ G_BEGIN_DECLS
#define EVC_X_VIDEO_URL "X-EVOLUTION-VIDEO-URL"
#define EVC_X_WANTS_HTML "X-MOZILLA-HTML"
#define EVC_X_YAHOO "X-YAHOO"
+#define EVC_X_YANDEX "X-YANDEX"
/**
* EVC_X_BOOK_UID:
diff --git a/src/addressbook/libedata-book/e-book-backend-sexp.c b/src/addressbook/libedata-book/e-book-backend-sexp.c
index 5f971cf..9977311 100644
--- a/src/addressbook/libedata-book/e-book-backend-sexp.c
+++ b/src/addressbook/libedata-book/e-book-backend-sexp.c
@@ -127,6 +127,16 @@ compare_im_yahoo (EContact *contact,
return compare_im (contact, str, region, compare, E_CONTACT_IM_YAHOO);
}
+static gboolean
+compare_im_yandex (EContact *contact,
+ const gchar *str,
+ const gchar *region,
+ CompareFunc compare)
+{
+ return compare_im (contact, str, region, compare, E_CONTACT_IM_YANDEX);
+}
+
+
static gboolean
compare_im_gadugadu (EContact *contact,
const gchar *str,
@@ -384,6 +394,7 @@ static struct prop_info {
LIST_PROP ( "im_icq", compare_im_icq ),
LIST_PROP ( "im_jabber", compare_im_jabber ),
LIST_PROP ( "im_yahoo", compare_im_yahoo ),
+ LIST_PROP ( "im_yandex", compare_im_yandex ),
LIST_PROP ( "im_gadugadu", compare_im_gadugadu ),
LIST_PROP ( "im_groupwise", compare_im_groupwise ),
LIST_PROP ( "email", compare_email ),
diff --git a/src/camel/CMakeLists.txt b/src/camel/CMakeLists.txt
index 2ba609b..26b2033 100644
--- a/src/camel/CMakeLists.txt
@ -291,6 +463,19 @@ index 0df1baf..9c71ab7 100644
#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
@ -325,10 +510,10 @@ index bc3c81a..93b4e14 100644
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
index 0000000..64ac387
--- /dev/null
+++ b/src/libedataserver/e-oauth2-service-yandex.c
@@ -0,0 +1,227 @@
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2018 Red Hat, Inc. (www.redhat.com)
+ *
@ -465,7 +650,7 @@ index 0000000..19e9453
+{
+ const gchar *YANDEX_SCOPE =
+ /* GMail IMAP and SMTP access */
+ "ogin:email login:info mail:imap_full mail:imap_ro mail:smtp";
+ "login:email login:info mail:imap_full mail:imap_ro mail:smtp calendar:all";
+
+ g_return_if_fail (uri_query != NULL);
+
@ -485,17 +670,6 @@ index 0000000..19e9453
+
+ *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;
+
@ -511,11 +685,9 @@ index 0000000..19e9453
+ 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) {
+ response = g_hash_table_lookup (params, "code");
+ if (response) {
+ *out_authorization_code = g_strdup (response);
+ known = TRUE;
+ }
+
@ -644,6 +816,126 @@ index 838b007..3679cea 100644
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
@ -713,10 +1005,10 @@ index 0000000..2416fa1
+)
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
index 0000000..bb6dfc1
--- /dev/null
+++ b/src/modules/yandex-backend/module-yandex-backend.c
@@ -0,0 +1,594 @@
@@ -0,0 +1,727 @@
+/*
+ * module-yandex-backend.c
+ *
@ -739,11 +1031,6 @@ index 0000000..31e6f2e
+#include <glib/gi18n-lib.h>
+
+#include <libebackend/libebackend.h>
+#include <libedataserver/libedataserver.h>
+
+#ifdef HAVE_LIBGDATA
+#include <gdata/gdata.h>
+#endif
+
+/* Standard GObject macros */
+#define E_TYPE_YANDEX_BACKEND \
@ -755,8 +1042,6 @@ index 0000000..31e6f2e
+/* 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"
@ -769,6 +1054,16 @@ index 0000000..31e6f2e
+#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;
+
@ -809,39 +1104,178 @@ index 0000000..31e6f2e
+ e_yandex_backend_factory,
+ E_TYPE_COLLECTION_BACKEND_FACTORY)
+
+static gboolean
+yandex_backend_can_use_yandex_auth (ESource *source)
+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)
+{
+ ESourceRegistryServer *registry;
+ ESourceAuthentication *auth_extension;
+ gboolean res;
+ 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 (E_IS_SERVER_SIDE_SOURCE (source), FALSE);
+ g_return_val_if_fail (collection != NULL, E_SOURCE_AUTHENTICATION_ERROR);
+
+ 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;
+ 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_object_ref (source);
+ 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);
+
+ while (source && e_source_get_parent (source)) {
+ ESource *adept_source;
+ e_collection_backend_freeze_populate (collection);
+
+ adept_source = e_source_registry_server_ref_source (registry, e_source_get_parent (source));
+ if (adept_source) {
+ g_object_unref (source);
+ source = adept_source;
+ (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 {
+ break;
+ 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;
+ }
+
+ auth_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION);
+ res = !e_source_authentication_get_is_external (auth_extension);
+ 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);
+}
+
+ return res;
+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
@ -867,16 +1301,13 @@ index 0000000..31e6f2e
+ 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 && (
+ is_yandex = (host && (
+ host_ends_with (host, "yandex.ru") ||
+ host_ends_with (host, "yandex.com") ||
+ host_ends_with (host, "ya.ru")));
@ -884,41 +1315,11 @@ index 0000000..31e6f2e
+ g_free (host);
+
+ if (out_requires_oauth2)
+ *out_requires_oauth2 = requires_oauth2;
+ *out_requires_oauth2 = TRUE;
+
+ 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,
@ -927,7 +1328,6 @@ index 0000000..31e6f2e
+ 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);
+
@ -938,20 +1338,13 @@ index 0000000..31e6f2e
+ 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) {
+ if (oauth2_support) {
+ 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)))
+ 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);
@ -966,103 +1359,91 @@ index 0000000..31e6f2e
+}
+
+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)
+yandex_backend_calendar_update_auth_method (ECollectionBackend *collection_backend,
+ ESource *child_source,
+ ESource *master_source)
+{
+ 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);
+ EOAuth2Support *oauth2_support;
+ ESourceAuthentication *auth_extension;
+ const gchar *method;
+
+ source = e_backend_get_source (backend);
+ collection_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_COLLECTION);
+ auth_extension = e_source_get_extension (child_source, E_SOURCE_EXTENSION_AUTHENTICATION);
+
+ 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);
+ if (!yandex_backend_is_yandex_host (auth_extension, NULL))
+ return;
+
+ e_collection_backend_freeze_populate (collection);
+ 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 (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;
+ if (oauth2_support) {
+ method = YANDEX_OAUTH2_METHOD_CUSTOM;
+ } else {
+ method = NULL;
+ }
+
+ /* resource-id => source's UID */
+ known_sources = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ if (e_collection_backend_is_new_source (collection_backend, child_source))
+ e_source_authentication_set_method (auth_extension, method);
+
+ sources = e_collection_backend_list_calendar_sources (collection);
+ g_list_free_full (sources, g_object_unref);
+ g_clear_object (&oauth2_support);
+}
+
+ /* 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);
+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));
+}
+
+ result = E_SOURCE_AUTHENTICATION_ACCEPTED;
+static void
+yandex_backend_contacts_update_auth_method (ESource *child_source,
+ ESource *master_source)
+{
+ EOAuth2Support *oauth2_support;
+ ESourceAuthentication *extension;
+ const gchar *method;
+
+ if (result == E_SOURCE_AUTHENTICATION_ACCEPTED) {
+ ESourceRegistryServer *server;
+ extension = e_source_get_extension (child_source, E_SOURCE_EXTENSION_AUTHENTICATION);
+
+ server = e_collection_backend_ref_server (collection);
+ if (!yandex_backend_is_yandex_host (extension, NULL))
+ return;
+
+ if (server) {
+ g_hash_table_foreach (known_sources, yandex_remove_unknown_sources_cb, server);
+ g_object_unref (server);
+ }
+ }
+ 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));
+
+ g_hash_table_destroy (known_sources);
+ e_named_parameters_free (credentials_copy);
+ if (oauth2_support)
+ method = "OAuth2";
+ else
+ method = NULL;
+
+ e_collection_backend_thaw_populate (collection);
+ e_source_authentication_set_method (extension, method);
+
+ return result;
+ g_clear_object (&oauth2_support);
+}
+
+static void
+yandex_backend_populate (ECollectionBackend *backend)
+yandex_backend_contacts_update_auth_method_cb (ESource *child_source,
+ GParamSpec *param,
+ EBackend *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);
+ yandex_backend_contacts_update_auth_method (child_source, e_backend_get_source (backend));
+}
+
+ if (e_source_authentication_get_is_external (authentication_extension))
+ e_source_authentication_set_method (authentication_extension, "OAuth2");
+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);
+
+ /* Chain up to parent's method. */
+ E_COLLECTION_BACKEND_CLASS (e_yandex_backend_parent_class)->populate (backend);
+ if (e_source_has_extension (child_source, E_SOURCE_EXTENSION_ADDRESS_BOOK))
+ return g_strdup (YANDEX_CONTACTS_RESOURCE_ID);
+
+ return NULL;
+}
+
+static void
@ -1072,6 +1453,7 @@ index 0000000..31e6f2e
+ 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)->
@ -1107,7 +1489,8 @@ index 0000000..31e6f2e
+ 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 (
@ -1124,6 +1507,43 @@ index 0000000..31e6f2e
+ }
+ }
+
+ 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
@ -1161,15 +1581,20 @@ index 0000000..31e6f2e
+{
+ 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->populate = yandex_backend_populate;
+ 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

Loading…
Cancel
Save