1 /*
2 * Copyright (C) 2021 Red Hat (www.redhat.com)
3 *
4 * This library is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU Lesser General Public License as published by
6 * the Free Software Foundation.
7 *
8 * This library is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
10 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
11 * for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this library. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17 #include "evolution-data-server-config.h"
18
19 #include <glib/gi18n-lib.h>
20
21 #include "e-oauth2-service.h"
22 #include "e-oauth2-service-base.h"
23
24 #include "e-oauth2-service-yahoo.h"
25
26 /* https://developer.yahoo.com/oauth2/guide/openid_connect/getting_started.html */
27
28 /* Forward Declarations */
29 static void e_oauth2_service_yahoo_oauth2_service_init (EOAuth2ServiceInterface *iface);
30
G_DEFINE_TYPE_WITH_CODE(EOAuth2ServiceYahoo,e_oauth2_service_yahoo,E_TYPE_OAUTH2_SERVICE_BASE,G_IMPLEMENT_INTERFACE (E_TYPE_OAUTH2_SERVICE,e_oauth2_service_yahoo_oauth2_service_init))31 G_DEFINE_TYPE_WITH_CODE (EOAuth2ServiceYahoo, e_oauth2_service_yahoo, E_TYPE_OAUTH2_SERVICE_BASE,
32 G_IMPLEMENT_INTERFACE (E_TYPE_OAUTH2_SERVICE, e_oauth2_service_yahoo_oauth2_service_init))
33
34 static gboolean
35 eos_yahoo_guess_can_process (EOAuth2Service *service,
36 const gchar *protocol,
37 const gchar *hostname)
38 {
39 return hostname &&
40 e_util_utf8_strstrcase (hostname, ".yahoo.com");
41 }
42
43 static const gchar *
eos_yahoo_get_name(EOAuth2Service * service)44 eos_yahoo_get_name (EOAuth2Service *service)
45 {
46 return "Yahoo";
47 }
48
49 static const gchar *
eos_yahoo_get_display_name(EOAuth2Service * service)50 eos_yahoo_get_display_name (EOAuth2Service *service)
51 {
52 /* Translators: This is a user-visible string, display name of an OAuth2 service. */
53 return C_("OAuth2Service", "Yahoo!");
54 }
55
56 static const gchar *
eos_yahoo_read_settings(EOAuth2Service * service,const gchar * key_name)57 eos_yahoo_read_settings (EOAuth2Service *service,
58 const gchar *key_name)
59 {
60 G_LOCK_DEFINE_STATIC (user_settings);
61 gchar *value;
62
63 G_LOCK (user_settings);
64
65 value = g_object_get_data (G_OBJECT (service), key_name);
66 if (!value) {
67 GSettings *settings;
68
69 settings = g_settings_new ("org.gnome.evolution-data-server");
70 value = g_settings_get_string (settings, key_name);
71 g_object_unref (settings);
72
73 if (value && *value) {
74 g_object_set_data_full (G_OBJECT (service), key_name, value, g_free);
75 } else {
76 g_free (value);
77 value = (gchar *) "";
78
79 g_object_set_data (G_OBJECT (service), key_name, value);
80 }
81 }
82
83 G_UNLOCK (user_settings);
84
85 return value;
86 }
87
88 static const gchar *
eos_yahoo_get_client_id(EOAuth2Service * service,ESource * source)89 eos_yahoo_get_client_id (EOAuth2Service *service,
90 ESource *source)
91 {
92 const gchar *client_id;
93
94 client_id = eos_yahoo_read_settings (service, "oauth2-yahoo-client-id");
95
96 if (client_id && *client_id)
97 return client_id;
98
99 return YAHOO_CLIENT_ID;
100 }
101
102 static const gchar *
eos_yahoo_get_client_secret(EOAuth2Service * service,ESource * source)103 eos_yahoo_get_client_secret (EOAuth2Service *service,
104 ESource *source)
105 {
106 const gchar *client_secret;
107
108 client_secret = eos_yahoo_read_settings (service, "oauth2-yahoo-client-secret");
109
110 if (client_secret && *client_secret)
111 return client_secret;
112
113 return YAHOO_CLIENT_SECRET;
114 }
115
116 static const gchar *
eos_yahoo_get_authentication_uri(EOAuth2Service * service,ESource * source)117 eos_yahoo_get_authentication_uri (EOAuth2Service *service,
118 ESource *source)
119 {
120 return "https://api.login.yahoo.com/oauth2/request_auth";
121 }
122
123 static const gchar *
eos_yahoo_get_refresh_uri(EOAuth2Service * service,ESource * source)124 eos_yahoo_get_refresh_uri (EOAuth2Service *service,
125 ESource *source)
126 {
127 return "https://api.login.yahoo.com/oauth2/get_token";
128 }
129
130 static const gchar *
eos_yahoo_get_redirect_uri(EOAuth2Service * service,ESource * source)131 eos_yahoo_get_redirect_uri (EOAuth2Service *service,
132 ESource *source)
133 {
134 return "https://wiki.gnome.org/Apps/Evolution/YahooOAuth2/";
135 }
136
137 static void
eos_yahoo_prepare_authentication_uri_query(EOAuth2Service * service,ESource * source,GHashTable * uri_query)138 eos_yahoo_prepare_authentication_uri_query (EOAuth2Service *service,
139 ESource *source,
140 GHashTable *uri_query)
141 {
142 const gchar *YAHOO_SCOPE =
143 /* Mail */
144 "mail-w "
145 /* Calendar */
146 "ycal-w "
147 /* Contacts */
148 "sdct-w";
149 gchar *nonce_str;
150 guint64 nonce_val;
151
152 g_return_if_fail (uri_query != NULL);
153
154 nonce_val = getpid () + g_get_real_time () + g_get_monotonic_time() + g_random_int () + g_random_int ();
155 nonce_str = g_strdup_printf ("%" G_GUINT64_FORMAT "d", nonce_val);
156
157 e_oauth2_service_util_set_to_form (uri_query, "scope", YAHOO_SCOPE);
158 e_oauth2_service_util_set_to_form (uri_query, "nonce", nonce_str);
159
160 g_free (nonce_str);
161 }
162
163 static gboolean
eos_yahoo_extract_authorization_code(EOAuth2Service * service,ESource * source,const gchar * page_title,const gchar * page_uri,const gchar * page_content,gchar ** out_authorization_code)164 eos_yahoo_extract_authorization_code (EOAuth2Service *service,
165 ESource *source,
166 const gchar *page_title,
167 const gchar *page_uri,
168 const gchar *page_content,
169 gchar **out_authorization_code)
170 {
171 g_return_val_if_fail (out_authorization_code != NULL, FALSE);
172
173 *out_authorization_code = NULL;
174
175 if (page_uri && *page_uri) {
176 SoupURI *suri;
177
178 suri = soup_uri_new (page_uri);
179 if (suri) {
180 const gchar *query = soup_uri_get_query (suri);
181 gboolean known = FALSE;
182
183 if (query && *query) {
184 GHashTable *params;
185
186 params = soup_form_decode (query);
187 if (params) {
188 const gchar *response;
189
190 response = g_hash_table_lookup (params, "code");
191 if (response) {
192 *out_authorization_code = g_strdup (response);
193 known = TRUE;
194 }
195
196 g_hash_table_destroy (params);
197 }
198 }
199
200 soup_uri_free (suri);
201
202 if (known)
203 return TRUE;
204 }
205 }
206
207 return FALSE;
208 }
209
210 static void
e_oauth2_service_yahoo_oauth2_service_init(EOAuth2ServiceInterface * iface)211 e_oauth2_service_yahoo_oauth2_service_init (EOAuth2ServiceInterface *iface)
212 {
213 iface->guess_can_process = eos_yahoo_guess_can_process;
214 iface->get_name = eos_yahoo_get_name;
215 iface->get_display_name = eos_yahoo_get_display_name;
216 iface->get_client_id = eos_yahoo_get_client_id;
217 iface->get_client_secret = eos_yahoo_get_client_secret;
218 iface->get_authentication_uri = eos_yahoo_get_authentication_uri;
219 iface->get_refresh_uri = eos_yahoo_get_refresh_uri;
220 iface->get_redirect_uri = eos_yahoo_get_redirect_uri;
221 iface->prepare_authentication_uri_query = eos_yahoo_prepare_authentication_uri_query;
222 iface->extract_authorization_code = eos_yahoo_extract_authorization_code;
223 }
224
225 static void
e_oauth2_service_yahoo_class_init(EOAuth2ServiceYahooClass * klass)226 e_oauth2_service_yahoo_class_init (EOAuth2ServiceYahooClass *klass)
227 {
228 }
229
230 static void
e_oauth2_service_yahoo_init(EOAuth2ServiceYahoo * oauth2_yahoo)231 e_oauth2_service_yahoo_init (EOAuth2ServiceYahoo *oauth2_yahoo)
232 {
233 }
234