goa: Add missing linker flag (for real).
[platform/upstream/evolution-data-server.git] / libedataserver / e-source-authentication.c
1 /*
2  * e-source-authentication.c
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) version 3.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with the program; if not, see <http://www.gnu.org/licenses/>
16  *
17  */
18
19 /**
20  * SECTION: e-source-authentication
21  * @include: libedataserver/libedataserver.h
22  * @short_description: #ESource extension for authentication settings
23  *
24  * The #ESourceAuthentication extension tracks authentication settings
25  * for a user account on a remote server.
26  *
27  * Access the extension as follows:
28  *
29  * |[
30  *   #include <libedataserver/libedataserver.h>
31  *
32  *   ESourceAuthentication *extension;
33  *
34  *   extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION);
35  * ]|
36  **/
37
38 #include "e-source-authentication.h"
39
40 #include <libedataserver/e-data-server-util.h>
41
42 #define E_SOURCE_AUTHENTICATION_GET_PRIVATE(obj) \
43         (G_TYPE_INSTANCE_GET_PRIVATE \
44         ((obj), E_TYPE_SOURCE_AUTHENTICATION, ESourceAuthenticationPrivate))
45
46 struct _ESourceAuthenticationPrivate {
47         GMutex property_lock;
48         gchar *host;
49         gchar *method;
50         guint16 port;
51         gchar *user;
52
53         /* GNetworkAddress caches data internally, so we maintain the
54          * instance to preserve the cache as opposed to just creating
55          * a new GNetworkAddress instance each time it's requested. */
56         GSocketConnectable *connectable;
57 };
58
59 enum {
60         PROP_0,
61         PROP_CONNECTABLE,
62         PROP_HOST,
63         PROP_METHOD,
64         PROP_PORT,
65         PROP_USER
66 };
67
68 G_DEFINE_TYPE (
69         ESourceAuthentication,
70         e_source_authentication,
71         E_TYPE_SOURCE_EXTENSION)
72
73 static void
74 source_authentication_update_connectable (ESourceAuthentication *extension)
75 {
76         const gchar *host;
77         guint16 port;
78
79         /* This MUST be called with the property_lock acquired. */
80
81         g_clear_object (&extension->priv->connectable);
82
83         host = e_source_authentication_get_host (extension);
84         port = e_source_authentication_get_port (extension);
85
86         if (host != NULL) {
87                 GSocketConnectable *connectable;
88                 connectable = g_network_address_new (host, port);
89                 extension->priv->connectable = connectable;
90         }
91 }
92
93 static void
94 source_authentication_set_property (GObject *object,
95                                     guint property_id,
96                                     const GValue *value,
97                                     GParamSpec *pspec)
98 {
99         switch (property_id) {
100                 case PROP_HOST:
101                         e_source_authentication_set_host (
102                                 E_SOURCE_AUTHENTICATION (object),
103                                 g_value_get_string (value));
104                         return;
105
106                 case PROP_METHOD:
107                         e_source_authentication_set_method (
108                                 E_SOURCE_AUTHENTICATION (object),
109                                 g_value_get_string (value));
110                         return;
111
112                 case PROP_PORT:
113                         e_source_authentication_set_port (
114                                 E_SOURCE_AUTHENTICATION (object),
115                                 g_value_get_uint (value));
116                         return;
117
118                 case PROP_USER:
119                         e_source_authentication_set_user (
120                                 E_SOURCE_AUTHENTICATION (object),
121                                 g_value_get_string (value));
122                         return;
123         }
124
125         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
126 }
127
128 static void
129 source_authentication_get_property (GObject *object,
130                                     guint property_id,
131                                     GValue *value,
132                                     GParamSpec *pspec)
133 {
134         switch (property_id) {
135                 case PROP_CONNECTABLE:
136                         g_value_take_object (
137                                 value,
138                                 e_source_authentication_ref_connectable (
139                                 E_SOURCE_AUTHENTICATION (object)));
140                         return;
141
142                 case PROP_HOST:
143                         g_value_take_string (
144                                 value,
145                                 e_source_authentication_dup_host (
146                                 E_SOURCE_AUTHENTICATION (object)));
147                         return;
148
149                 case PROP_METHOD:
150                         g_value_take_string (
151                                 value,
152                                 e_source_authentication_dup_method (
153                                 E_SOURCE_AUTHENTICATION (object)));
154                         return;
155
156                 case PROP_PORT:
157                         g_value_set_uint (
158                                 value,
159                                 e_source_authentication_get_port (
160                                 E_SOURCE_AUTHENTICATION (object)));
161                         return;
162
163                 case PROP_USER:
164                         g_value_take_string (
165                                 value,
166                                 e_source_authentication_dup_user (
167                                 E_SOURCE_AUTHENTICATION (object)));
168                         return;
169         }
170
171         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
172 }
173
174 static void
175 source_authentication_dispose (GObject *object)
176 {
177         ESourceAuthenticationPrivate *priv;
178
179         priv = E_SOURCE_AUTHENTICATION_GET_PRIVATE (object);
180
181         g_clear_object (&priv->connectable);
182
183         /* Chain up to parent's dispose() method. */
184         G_OBJECT_CLASS (e_source_authentication_parent_class)->dispose (object);
185 }
186
187 static void
188 source_authentication_finalize (GObject *object)
189 {
190         ESourceAuthenticationPrivate *priv;
191
192         priv = E_SOURCE_AUTHENTICATION_GET_PRIVATE (object);
193
194         g_mutex_clear (&priv->property_lock);
195
196         g_free (priv->host);
197         g_free (priv->method);
198         g_free (priv->user);
199
200         /* Chain up to parent's finalize() method. */
201         G_OBJECT_CLASS (e_source_authentication_parent_class)->finalize (object);
202 }
203
204 static void
205 e_source_authentication_class_init (ESourceAuthenticationClass *class)
206 {
207         GObjectClass *object_class;
208         ESourceExtensionClass *extension_class;
209
210         g_type_class_add_private (class, sizeof (ESourceAuthenticationPrivate));
211
212         object_class = G_OBJECT_CLASS (class);
213         object_class->set_property = source_authentication_set_property;
214         object_class->get_property = source_authentication_get_property;
215         object_class->dispose = source_authentication_dispose;
216         object_class->finalize = source_authentication_finalize;
217
218         extension_class = E_SOURCE_EXTENSION_CLASS (class);
219         extension_class->name = E_SOURCE_EXTENSION_AUTHENTICATION;
220
221         g_object_class_install_property (
222                 object_class,
223                 PROP_CONNECTABLE,
224                 g_param_spec_object (
225                         "connectable",
226                         "Connectable",
227                         "A GSocketConnectable constructed "
228                         "from the host and port properties",
229                         G_TYPE_SOCKET_CONNECTABLE,
230                         G_PARAM_READABLE |
231                         G_PARAM_STATIC_STRINGS));
232
233         g_object_class_install_property (
234                 object_class,
235                 PROP_HOST,
236                 g_param_spec_string (
237                         "host",
238                         "Host",
239                         "Host name for the remote account",
240                         "",
241                         G_PARAM_READWRITE |
242                         G_PARAM_CONSTRUCT |
243                         G_PARAM_STATIC_STRINGS |
244                         E_SOURCE_PARAM_SETTING));
245
246         g_object_class_install_property (
247                 object_class,
248                 PROP_METHOD,
249                 g_param_spec_string (
250                         "method",
251                         "Method",
252                         "Authentication method",
253                         "none",
254                         G_PARAM_READWRITE |
255                         G_PARAM_CONSTRUCT |
256                         G_PARAM_STATIC_STRINGS |
257                         E_SOURCE_PARAM_SETTING));
258
259         g_object_class_install_property (
260                 object_class,
261                 PROP_PORT,
262                 g_param_spec_uint (
263                         "port",
264                         "Port",
265                         "Port number for the remote account",
266                         0, G_MAXUINT16, 0,
267                         G_PARAM_READWRITE |
268                         G_PARAM_CONSTRUCT |
269                         G_PARAM_STATIC_STRINGS |
270                         E_SOURCE_PARAM_SETTING));
271
272         g_object_class_install_property (
273                 object_class,
274                 PROP_USER,
275                 g_param_spec_string (
276                         "user",
277                         "User",
278                         "User name for the remote account",
279                         NULL,
280                         G_PARAM_READWRITE |
281                         G_PARAM_CONSTRUCT |
282                         G_PARAM_STATIC_STRINGS |
283                         E_SOURCE_PARAM_SETTING));
284 }
285
286 static void
287 e_source_authentication_init (ESourceAuthentication *extension)
288 {
289         extension->priv = E_SOURCE_AUTHENTICATION_GET_PRIVATE (extension);
290         g_mutex_init (&extension->priv->property_lock);
291 }
292
293 /**
294  * e_source_authentication_required:
295  * @extension: an #ESourceAuthentication
296  *
297  * This is a convenience function which returns whether authentication
298  * is required at all, regardless of the method used.  This relies on
299  * the convention of setting #ESourceAuthentication:method to "none"
300  * when authentication is <emphasis>not</emphasis> required.
301  *
302  * Returns: whether authentication is required at all
303  *
304  * Since: 3.6
305  **/
306 gboolean
307 e_source_authentication_required (ESourceAuthentication *extension)
308 {
309         const gchar *method;
310
311         g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATION (extension), FALSE);
312
313         method = e_source_authentication_get_method (extension);
314         g_return_val_if_fail (method != NULL && *method != '\0', FALSE);
315
316         return (g_strcmp0 (method, "none") != 0);
317 }
318
319 /**
320  * e_source_authentication_ref_connectable:
321  * @extension: an #ESourceAuthentication
322  *
323  * Returns a #GSocketConnectable instance constructed from @extension's
324  * #ESourceAuthentication:host and #ESourceAuthentication:port properties,
325  * or %NULL if the #ESourceAuthentication:host is not set.
326  *
327  * The returned #GSocketConnectable is referenced for thread-safety and must
328  * be unreferenced with g_object_unref() when finished with it.
329  *
330  * Returns: (transfer full): a #GSocketConnectable, or %NULL
331  *
332  * Since: 3.8
333  **/
334 GSocketConnectable *
335 e_source_authentication_ref_connectable (ESourceAuthentication *extension)
336 {
337         GSocketConnectable *connectable = NULL;
338
339         g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATION (extension), NULL);
340
341         g_mutex_lock (&extension->priv->property_lock);
342
343         if (extension->priv->connectable != NULL)
344                 connectable = g_object_ref (extension->priv->connectable);
345
346         g_mutex_unlock (&extension->priv->property_lock);
347
348         return connectable;
349 }
350
351 /**
352  * e_source_authentication_get_host:
353  * @extension: an #ESourceAuthentication
354  *
355  * Returns the host name used to authenticate to a remote account.
356  *
357  * Returns: the host name of a remote account
358  *
359  * Since: 3.6
360  **/
361 const gchar *
362 e_source_authentication_get_host (ESourceAuthentication *extension)
363 {
364         g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATION (extension), NULL);
365
366         return extension->priv->host;
367 }
368
369 /**
370  * e_source_authentication_dup_host:
371  * @extension: an #ESourceAuthentication
372  *
373  * Thread-safe variation of e_source_authentication_get_host().
374  * Use this function when accessing @extension from multiple threads.
375  *
376  * The returned string should be freed with g_free() when no longer needed.
377  *
378  * Returns: a newly-allocated copy of #ESourceAuthentication:host
379  *
380  * Since: 3.6
381  **/
382 gchar *
383 e_source_authentication_dup_host (ESourceAuthentication *extension)
384 {
385         const gchar *protected;
386         gchar *duplicate;
387
388         g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATION (extension), NULL);
389
390         g_mutex_lock (&extension->priv->property_lock);
391
392         protected = e_source_authentication_get_host (extension);
393         duplicate = g_strdup (protected);
394
395         g_mutex_unlock (&extension->priv->property_lock);
396
397         return duplicate;
398 }
399
400 /**
401  * e_source_authentication_set_host:
402  * @extension: an #ESourceAuthentication
403  * @host: (allow-none): a host name, or %NULL
404  *
405  * Sets the host name used to authenticate to a remote account.
406  *
407  * The internal copy of @host is automatically stripped of leading and
408  * trailing whitespace.  If the resulting string is empty, %NULL is set
409  * instead.
410  *
411  * Since: 3.6
412  **/
413 void
414 e_source_authentication_set_host (ESourceAuthentication *extension,
415                                   const gchar *host)
416 {
417         g_return_if_fail (E_IS_SOURCE_AUTHENTICATION (extension));
418
419         g_mutex_lock (&extension->priv->property_lock);
420
421         if (g_strcmp0 (extension->priv->host, host) == 0) {
422                 g_mutex_unlock (&extension->priv->property_lock);
423                 return;
424         }
425
426         g_free (extension->priv->host);
427         extension->priv->host = e_util_strdup_strip (host);
428
429         source_authentication_update_connectable (extension);
430
431         g_mutex_unlock (&extension->priv->property_lock);
432
433         g_object_notify (G_OBJECT (extension), "host");
434
435         /* Changing the host also changes the connectable. */
436         g_object_notify (G_OBJECT (extension), "connectable");
437 }
438
439 /**
440  * e_source_authentication_get_method:
441  * @extension: an #ESourceAuthentication
442  *
443  * Returns the authentication method for a remote account.  There are
444  * no pre-defined method names; backends are free to set this however
445  * they wish.  If authentication is not required for a remote account,
446  * the convention is to set #ESourceAuthentication:method to "none".
447  *
448  * Returns: the authentication method for a remote account
449  *
450  * Since: 3.6
451  **/
452 const gchar *
453 e_source_authentication_get_method (ESourceAuthentication *extension)
454 {
455         g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATION (extension), NULL);
456
457         return extension->priv->method;
458 }
459
460 /**
461  * e_source_authentication_dup_method:
462  * @extension: an #ESourceAuthentication
463  *
464  * Thread-safe variation of e_source_authentication_get_method().
465  * Use this function when accessing @extension from multiple threads.
466  *
467  * The returned string should be freed with g_free() when no longer needed.
468  *
469  * Returns: a newly-allocated copy of #ESourceAuthentication:method
470  *
471  * Since: 3.6
472  **/
473 gchar *
474 e_source_authentication_dup_method (ESourceAuthentication *extension)
475 {
476         const gchar *protected;
477         gchar *duplicate;
478
479         g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATION (extension), NULL);
480
481         g_mutex_lock (&extension->priv->property_lock);
482
483         protected = e_source_authentication_get_method (extension);
484         duplicate = g_strdup (protected);
485
486         g_mutex_unlock (&extension->priv->property_lock);
487
488         return duplicate;
489 }
490
491 /**
492  * e_source_authentication_set_method:
493  * @extension: an #ESourceAuthentication
494  * @method: (allow-none): authentication method, or %NULL
495  *
496  * Sets the authentication method for a remote account.  There are no
497  * pre-defined method names; backends are free to set this however they
498  * wish.  If authentication is not required for a remote account, the
499  * convention is to set the method to "none".  In keeping with that
500  * convention, #ESourceAuthentication:method will be set to "none" if
501  * @method is %NULL or an empty string.
502  *
503  * Since: 3.6
504  **/
505 void
506 e_source_authentication_set_method (ESourceAuthentication *extension,
507                                     const gchar *method)
508 {
509         g_return_if_fail (E_IS_SOURCE_AUTHENTICATION (extension));
510
511         g_mutex_lock (&extension->priv->property_lock);
512
513         if (g_strcmp0 (extension->priv->method, method) == 0) {
514                 g_mutex_unlock (&extension->priv->property_lock);
515                 return;
516         }
517
518         g_free (extension->priv->method);
519         extension->priv->method = e_util_strdup_strip (method);
520
521         if (extension->priv->method == NULL)
522                 extension->priv->method = g_strdup ("none");
523
524         g_mutex_unlock (&extension->priv->property_lock);
525
526         g_object_notify (G_OBJECT (extension), "method");
527 }
528
529 /**
530  * e_source_authentication_get_port:
531  * @extension: an #ESourceAuthentication
532  *
533  * Returns the port number used to authenticate to a remote account.
534  *
535  * Returns: the port number of a remote account
536  *
537  * Since: 3.6
538  **/
539 guint16
540 e_source_authentication_get_port (ESourceAuthentication *extension)
541 {
542         g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATION (extension), 0);
543
544         return extension->priv->port;
545 }
546
547 /**
548  * e_source_authentication_set_port:
549  * @extension: an #ESourceAuthentication
550  * @port: a port number
551  *
552  * Sets the port number used to authenticate to a remote account.
553  *
554  * Since: 3.6
555  **/
556 void
557 e_source_authentication_set_port (ESourceAuthentication *extension,
558                                   guint16 port)
559 {
560         g_return_if_fail (E_SOURCE_AUTHENTICATION (extension));
561
562         g_mutex_lock (&extension->priv->property_lock);
563
564         if (extension->priv->port == port) {
565                 g_mutex_unlock (&extension->priv->property_lock);
566                 return;
567         }
568
569         extension->priv->port = port;
570
571         source_authentication_update_connectable (extension);
572
573         g_mutex_unlock (&extension->priv->property_lock);
574
575         g_object_notify (G_OBJECT (extension), "port");
576
577         /* Changing the port also changes the connectable. */
578         g_object_notify (G_OBJECT (extension), "connectable");
579 }
580
581 /**
582  * e_source_authentication_get_user:
583  * @extension: an #ESourceAuthentication
584  *
585  * Returns the user name used to authenticate to a remote account.
586  *
587  * Returns: the user name of a remote account
588  *
589  * Since: 3.6
590  **/
591 const gchar *
592 e_source_authentication_get_user (ESourceAuthentication *extension)
593 {
594         g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATION (extension), NULL);
595
596         return extension->priv->user;
597 }
598
599 /**
600  * e_source_authentication_dup_user:
601  * @extension: an #ESourceAuthentication
602  *
603  * Thread-safe variation of e_source_authentication_get_user().
604  * Use this function when accessing @extension from multiple threads.
605  *
606  * The returned string should be freed with g_free() when no longer needed.
607  *
608  * Returns: a newly-allocated copy of #ESourceAuthentication:user
609  *
610  * Since: 3.6
611  **/
612 gchar *
613 e_source_authentication_dup_user (ESourceAuthentication *extension)
614 {
615         const gchar *protected;
616         gchar *duplicate;
617
618         g_return_val_if_fail (E_IS_SOURCE_AUTHENTICATION (extension), NULL);
619
620         g_mutex_lock (&extension->priv->property_lock);
621
622         protected = e_source_authentication_get_user (extension);
623         duplicate = g_strdup (protected);
624
625         g_mutex_unlock (&extension->priv->property_lock);
626
627         return duplicate;
628 }
629
630 /**
631  * e_source_authentication_set_user:
632  * @extension: an #ESourceAuthentication
633  * @user: (allow-none): a user name, or %NULL
634  *
635  * Sets the user name used to authenticate to a remote account.
636  *
637  * The internal copy of @user is automatically stripped of leading and
638  * trailing whitespace.  If the resulting string is empty, %NULL is set
639  * instead.
640  *
641  * Since: 3.6
642  **/
643 void
644 e_source_authentication_set_user (ESourceAuthentication *extension,
645                                   const gchar *user)
646 {
647         g_return_if_fail (E_IS_SOURCE_AUTHENTICATION (extension));
648
649         g_mutex_lock (&extension->priv->property_lock);
650
651         if (g_strcmp0 (extension->priv->user, user) == 0) {
652                 g_mutex_unlock (&extension->priv->property_lock);
653                 return;
654         }
655
656         g_free (extension->priv->user);
657         extension->priv->user = e_util_strdup_strip (user);
658
659         g_mutex_unlock (&extension->priv->property_lock);
660
661         g_object_notify (G_OBJECT (extension), "user");
662 }