1 /*
2 * e-source-ldap.c
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
18 #include "evolution-data-server-config.h"
19
20 #include "e-source-authentication.h"
21 #include "e-source-security.h"
22 #include "e-source-enumtypes.h"
23
24 #include "e-source-ldap.h"
25
26 struct _ESourceLDAPPrivate {
27 gboolean can_browse;
28 gchar *filter;
29 guint limit;
30 gchar *root_dn;
31 ESourceLDAPScope scope;
32
33 /* These are bound to other extensions. */
34 ESourceLDAPAuthentication authentication;
35 ESourceLDAPSecurity security;
36 };
37
38 enum {
39 PROP_0,
40 PROP_AUTHENTICATION,
41 PROP_CAN_BROWSE,
42 PROP_FILTER,
43 PROP_LIMIT,
44 PROP_ROOT_DN,
45 PROP_SCOPE,
46 PROP_SECURITY
47 };
48
49 G_DEFINE_TYPE_WITH_PRIVATE (
50 ESourceLDAP,
51 e_source_ldap,
52 E_TYPE_SOURCE_EXTENSION)
53
54 static struct ELDAPAuthMapping {
55 ESourceLDAPAuthentication value;
56 const gchar *nick;
57 } ldap_auth_mapping[] = {
58 { E_SOURCE_LDAP_AUTHENTICATION_NONE, "none" },
59 { E_SOURCE_LDAP_AUTHENTICATION_EMAIL, "ldap/simple-email" },
60 { E_SOURCE_LDAP_AUTHENTICATION_BINDDN, "ldap/simple-binddn" }
61 };
62
63 static gboolean
source_ldap_transform_auth_enum_nick_to_value(GBinding * binding,const GValue * source_value,GValue * target_value,gpointer not_used)64 source_ldap_transform_auth_enum_nick_to_value (GBinding *binding,
65 const GValue *source_value,
66 GValue *target_value,
67 gpointer not_used)
68 {
69 GEnumClass *enum_class;
70 const gchar *string;
71 gboolean success = FALSE;
72 gint ii;
73
74 enum_class = g_type_class_peek (G_VALUE_TYPE (target_value));
75 g_return_val_if_fail (G_IS_ENUM_CLASS (enum_class), FALSE);
76
77 string = g_value_get_string (source_value);
78
79 for (ii = 0; ii < G_N_ELEMENTS (ldap_auth_mapping); ii++) {
80 if (g_strcmp0 (ldap_auth_mapping[ii].nick, string) == 0) {
81 g_value_set_enum (target_value, ldap_auth_mapping[ii].value);
82 success = TRUE;
83 break;
84 }
85 }
86
87 return success;
88 }
89
90 static gboolean
source_ldap_transform_auth_enum_value_to_nick(GBinding * binding,const GValue * source_value,GValue * target_value,gpointer not_used)91 source_ldap_transform_auth_enum_value_to_nick (GBinding *binding,
92 const GValue *source_value,
93 GValue *target_value,
94 gpointer not_used)
95 {
96 GEnumClass *enum_class;
97 gint value;
98 gboolean success = FALSE;
99 gint ii;
100
101 enum_class = g_type_class_peek (G_VALUE_TYPE (source_value));
102 g_return_val_if_fail (G_IS_ENUM_CLASS (enum_class), FALSE);
103
104 value = g_value_get_enum (source_value);
105
106 for (ii = 0; ii < G_N_ELEMENTS (ldap_auth_mapping); ii++) {
107 if (value == ldap_auth_mapping[ii].value) {
108 g_value_set_string (target_value, ldap_auth_mapping[ii].nick);
109 success = TRUE;
110 break;
111 }
112 }
113
114 return success;
115 }
116
117 static gboolean
source_ldap_transform_enum_nick_to_value(GBinding * binding,const GValue * source_value,GValue * target_value,gpointer not_used)118 source_ldap_transform_enum_nick_to_value (GBinding *binding,
119 const GValue *source_value,
120 GValue *target_value,
121 gpointer not_used)
122 {
123 GEnumClass *enum_class;
124 GEnumValue *enum_value;
125 const gchar *string;
126 gboolean success = FALSE;
127
128 enum_class = g_type_class_peek (G_VALUE_TYPE (target_value));
129 g_return_val_if_fail (G_IS_ENUM_CLASS (enum_class), FALSE);
130
131 string = g_value_get_string (source_value);
132 enum_value = g_enum_get_value_by_nick (enum_class, string);
133 if (enum_value != NULL) {
134 g_value_set_enum (target_value, enum_value->value);
135 success = TRUE;
136 }
137
138 return success;
139 }
140
141 static gboolean
source_ldap_transform_enum_value_to_nick(GBinding * binding,const GValue * source_value,GValue * target_value,gpointer not_used)142 source_ldap_transform_enum_value_to_nick (GBinding *binding,
143 const GValue *source_value,
144 GValue *target_value,
145 gpointer not_used)
146 {
147 GEnumClass *enum_class;
148 GEnumValue *enum_value;
149 gint value;
150 gboolean success = FALSE;
151
152 enum_class = g_type_class_peek (G_VALUE_TYPE (source_value));
153 g_return_val_if_fail (G_IS_ENUM_CLASS (enum_class), FALSE);
154
155 value = g_value_get_enum (source_value);
156 enum_value = g_enum_get_value (enum_class, value);
157 if (enum_value != NULL) {
158 g_value_set_string (target_value, enum_value->value_nick);
159 success = TRUE;
160 }
161
162 return success;
163 }
164
165 static void
source_ldap_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)166 source_ldap_set_property (GObject *object,
167 guint property_id,
168 const GValue *value,
169 GParamSpec *pspec)
170 {
171 switch (property_id) {
172 case PROP_AUTHENTICATION:
173 e_source_ldap_set_authentication (
174 E_SOURCE_LDAP (object),
175 g_value_get_enum (value));
176 return;
177
178 case PROP_CAN_BROWSE:
179 e_source_ldap_set_can_browse (
180 E_SOURCE_LDAP (object),
181 g_value_get_boolean (value));
182 return;
183
184 case PROP_FILTER:
185 e_source_ldap_set_filter (
186 E_SOURCE_LDAP (object),
187 g_value_get_string (value));
188 return;
189
190 case PROP_LIMIT:
191 e_source_ldap_set_limit (
192 E_SOURCE_LDAP (object),
193 g_value_get_uint (value));
194 return;
195
196 case PROP_ROOT_DN:
197 e_source_ldap_set_root_dn (
198 E_SOURCE_LDAP (object),
199 g_value_get_string (value));
200 return;
201
202 case PROP_SCOPE:
203 e_source_ldap_set_scope (
204 E_SOURCE_LDAP (object),
205 g_value_get_enum (value));
206 return;
207
208 case PROP_SECURITY:
209 e_source_ldap_set_security (
210 E_SOURCE_LDAP (object),
211 g_value_get_enum (value));
212 return;
213 }
214
215 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
216 }
217
218 static void
source_ldap_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)219 source_ldap_get_property (GObject *object,
220 guint property_id,
221 GValue *value,
222 GParamSpec *pspec)
223 {
224 switch (property_id) {
225 case PROP_AUTHENTICATION:
226 g_value_set_enum (
227 value,
228 e_source_ldap_get_authentication (
229 E_SOURCE_LDAP (object)));
230 return;
231
232 case PROP_CAN_BROWSE:
233 g_value_set_boolean (
234 value,
235 e_source_ldap_get_can_browse (
236 E_SOURCE_LDAP (object)));
237 return;
238
239 case PROP_FILTER:
240 g_value_take_string (
241 value,
242 e_source_ldap_dup_filter (
243 E_SOURCE_LDAP (object)));
244 return;
245
246 case PROP_LIMIT:
247 g_value_set_uint (
248 value,
249 e_source_ldap_get_limit (
250 E_SOURCE_LDAP (object)));
251 return;
252
253 case PROP_ROOT_DN:
254 g_value_take_string (
255 value,
256 e_source_ldap_dup_root_dn (
257 E_SOURCE_LDAP (object)));
258 return;
259
260 case PROP_SCOPE:
261 g_value_set_enum (
262 value,
263 e_source_ldap_get_scope (
264 E_SOURCE_LDAP (object)));
265 return;
266
267 case PROP_SECURITY:
268 g_value_set_enum (
269 value,
270 e_source_ldap_get_security (
271 E_SOURCE_LDAP (object)));
272 return;
273 }
274
275 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
276 }
277
278 static void
source_ldap_finalize(GObject * object)279 source_ldap_finalize (GObject *object)
280 {
281 ESourceLDAPPrivate *priv;
282
283 priv = E_SOURCE_LDAP (object)->priv;
284
285 g_free (priv->filter);
286 g_free (priv->root_dn);
287
288 /* Chain up to parent's finalize() method. */
289 G_OBJECT_CLASS (e_source_ldap_parent_class)->finalize (object);
290 }
291
292 static void
source_ldap_constructed(GObject * object)293 source_ldap_constructed (GObject *object)
294 {
295 ESource *source;
296 ESourceExtension *this_extension;
297 ESourceExtension *other_extension;
298 const gchar *extension_name;
299
300 /* Chain up to parent's method. */
301 G_OBJECT_CLASS (e_source_ldap_parent_class)->constructed (object);
302
303 this_extension = E_SOURCE_EXTENSION (object);
304 source = e_source_extension_ref_source (this_extension);
305
306 extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
307 other_extension = e_source_get_extension (source, extension_name);
308
309 e_binding_bind_property_full (
310 other_extension, "method",
311 this_extension, "authentication",
312 G_BINDING_BIDIRECTIONAL |
313 G_BINDING_SYNC_CREATE,
314 source_ldap_transform_auth_enum_nick_to_value,
315 source_ldap_transform_auth_enum_value_to_nick,
316 NULL, (GDestroyNotify) NULL);
317
318 extension_name = E_SOURCE_EXTENSION_SECURITY;
319 other_extension = e_source_get_extension (source, extension_name);
320
321 e_binding_bind_property_full (
322 other_extension, "method",
323 this_extension, "security",
324 G_BINDING_BIDIRECTIONAL |
325 G_BINDING_SYNC_CREATE,
326 source_ldap_transform_enum_nick_to_value,
327 source_ldap_transform_enum_value_to_nick,
328 NULL, (GDestroyNotify) NULL);
329
330 g_object_unref (source);
331 }
332
333 static void
e_source_ldap_class_init(ESourceLDAPClass * class)334 e_source_ldap_class_init (ESourceLDAPClass *class)
335 {
336 GObjectClass *object_class;
337 ESourceExtensionClass *extension_class;
338
339 object_class = G_OBJECT_CLASS (class);
340 object_class->set_property = source_ldap_set_property;
341 object_class->get_property = source_ldap_get_property;
342 object_class->finalize = source_ldap_finalize;
343 object_class->constructed = source_ldap_constructed;
344
345 extension_class = E_SOURCE_EXTENSION_CLASS (class);
346 extension_class->name = E_SOURCE_EXTENSION_LDAP_BACKEND;
347
348 /* This is bound to the authentication extension.
349 * Do not use E_SOURCE_PARAM_SETTING here. */
350 g_object_class_install_property (
351 object_class,
352 PROP_AUTHENTICATION,
353 g_param_spec_enum (
354 "authentication",
355 "Authentication",
356 "LDAP authentication method",
357 E_TYPE_SOURCE_LDAP_AUTHENTICATION,
358 E_SOURCE_LDAP_AUTHENTICATION_NONE,
359 G_PARAM_READWRITE |
360 G_PARAM_EXPLICIT_NOTIFY |
361 G_PARAM_STATIC_STRINGS));
362
363 g_object_class_install_property (
364 object_class,
365 PROP_CAN_BROWSE,
366 g_param_spec_boolean (
367 "can-browse",
368 "Can Browse",
369 "Allow browsing contacts",
370 FALSE,
371 G_PARAM_READWRITE |
372 G_PARAM_CONSTRUCT |
373 G_PARAM_EXPLICIT_NOTIFY |
374 G_PARAM_STATIC_STRINGS |
375 E_SOURCE_PARAM_SETTING));
376
377 g_object_class_install_property (
378 object_class,
379 PROP_FILTER,
380 g_param_spec_string (
381 "filter",
382 "Filter",
383 "LDAP search filter",
384 "",
385 G_PARAM_READWRITE |
386 G_PARAM_CONSTRUCT |
387 G_PARAM_EXPLICIT_NOTIFY |
388 G_PARAM_STATIC_STRINGS |
389 E_SOURCE_PARAM_SETTING));
390
391 g_object_class_install_property (
392 object_class,
393 PROP_LIMIT,
394 g_param_spec_uint (
395 "limit",
396 "Limit",
397 "Download limit",
398 0, G_MAXUINT, 100,
399 G_PARAM_READWRITE |
400 G_PARAM_CONSTRUCT |
401 G_PARAM_EXPLICIT_NOTIFY |
402 G_PARAM_STATIC_STRINGS |
403 E_SOURCE_PARAM_SETTING));
404
405 g_object_class_install_property (
406 object_class,
407 PROP_ROOT_DN,
408 g_param_spec_string (
409 "root-dn",
410 "Root DN",
411 "LDAP search base",
412 "",
413 G_PARAM_READWRITE |
414 G_PARAM_CONSTRUCT |
415 G_PARAM_EXPLICIT_NOTIFY |
416 G_PARAM_STATIC_STRINGS |
417 E_SOURCE_PARAM_SETTING));
418
419 g_object_class_install_property (
420 object_class,
421 PROP_SCOPE,
422 g_param_spec_enum (
423 "scope",
424 "Scope",
425 "LDAP search scope",
426 E_TYPE_SOURCE_LDAP_SCOPE,
427 E_SOURCE_LDAP_SCOPE_ONELEVEL,
428 G_PARAM_READWRITE |
429 G_PARAM_CONSTRUCT |
430 G_PARAM_EXPLICIT_NOTIFY |
431 G_PARAM_STATIC_STRINGS |
432 E_SOURCE_PARAM_SETTING));
433
434 /* This is bound to the security extension.
435 * Do not use E_SOURCE_PARAM_SETTING here. */
436 g_object_class_install_property (
437 object_class,
438 PROP_SECURITY,
439 g_param_spec_enum (
440 "security",
441 "Security",
442 "LDAP security method",
443 E_TYPE_SOURCE_LDAP_SECURITY,
444 E_SOURCE_LDAP_SECURITY_NONE,
445 G_PARAM_READWRITE |
446 G_PARAM_EXPLICIT_NOTIFY |
447 G_PARAM_STATIC_STRINGS));
448 }
449
450 static void
e_source_ldap_init(ESourceLDAP * extension)451 e_source_ldap_init (ESourceLDAP *extension)
452 {
453 extension->priv = e_source_ldap_get_instance_private (extension);
454 }
455
456 ESourceLDAPAuthentication
e_source_ldap_get_authentication(ESourceLDAP * extension)457 e_source_ldap_get_authentication (ESourceLDAP *extension)
458 {
459 g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), 0);
460
461 return extension->priv->authentication;
462 }
463
464 void
e_source_ldap_set_authentication(ESourceLDAP * extension,ESourceLDAPAuthentication authentication)465 e_source_ldap_set_authentication (ESourceLDAP *extension,
466 ESourceLDAPAuthentication authentication)
467 {
468 g_return_if_fail (E_IS_SOURCE_LDAP (extension));
469
470 if (extension->priv->authentication == authentication)
471 return;
472
473 extension->priv->authentication = authentication;
474
475 g_object_notify (G_OBJECT (extension), "authentication");
476 }
477
478 gboolean
e_source_ldap_get_can_browse(ESourceLDAP * extension)479 e_source_ldap_get_can_browse (ESourceLDAP *extension)
480 {
481 g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), FALSE);
482
483 return extension->priv->can_browse;
484 }
485
486 void
e_source_ldap_set_can_browse(ESourceLDAP * extension,gboolean can_browse)487 e_source_ldap_set_can_browse (ESourceLDAP *extension,
488 gboolean can_browse)
489 {
490 g_return_if_fail (E_IS_SOURCE_LDAP (extension));
491
492 if (extension->priv->can_browse == can_browse)
493 return;
494
495 extension->priv->can_browse = can_browse;
496
497 g_object_notify (G_OBJECT (extension), "can-browse");
498 }
499
500 const gchar *
e_source_ldap_get_filter(ESourceLDAP * extension)501 e_source_ldap_get_filter (ESourceLDAP *extension)
502 {
503 g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), NULL);
504
505 return extension->priv->filter;
506 }
507
508 gchar *
e_source_ldap_dup_filter(ESourceLDAP * extension)509 e_source_ldap_dup_filter (ESourceLDAP *extension)
510 {
511 const gchar *protected;
512 gchar *duplicate;
513
514 g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), NULL);
515
516 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
517
518 protected = e_source_ldap_get_filter (extension);
519 duplicate = g_strdup (protected);
520
521 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
522
523 return duplicate;
524 }
525
526 void
e_source_ldap_set_filter(ESourceLDAP * extension,const gchar * filter)527 e_source_ldap_set_filter (ESourceLDAP *extension,
528 const gchar *filter)
529 {
530 gboolean needs_parens;
531 gchar *new_filter;
532
533 g_return_if_fail (E_IS_SOURCE_LDAP (extension));
534
535 needs_parens =
536 (filter != NULL) && (*filter != '\0') &&
537 !g_str_has_prefix (filter, "(") &&
538 !g_str_has_suffix (filter, ")");
539
540 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
541
542 if (needs_parens)
543 new_filter = g_strdup_printf ("(%s)", filter);
544 else
545 new_filter = g_strdup (filter);
546
547 if (g_strcmp0 (extension->priv->filter, new_filter) == 0) {
548 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
549 g_free (new_filter);
550 return;
551 }
552
553 g_free (extension->priv->filter);
554 extension->priv->filter = new_filter;
555
556 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
557
558 g_object_notify (G_OBJECT (extension), "filter");
559 }
560
561 guint
e_source_ldap_get_limit(ESourceLDAP * extension)562 e_source_ldap_get_limit (ESourceLDAP *extension)
563 {
564 g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), 0);
565
566 return extension->priv->limit;
567 }
568
569 void
e_source_ldap_set_limit(ESourceLDAP * extension,guint limit)570 e_source_ldap_set_limit (ESourceLDAP *extension,
571 guint limit)
572 {
573 g_return_if_fail (E_IS_SOURCE_LDAP (extension));
574
575 if (extension->priv->limit == limit)
576 return;
577
578 extension->priv->limit = limit;
579
580 g_object_notify (G_OBJECT (extension), "limit");
581 }
582
583 const gchar *
e_source_ldap_get_root_dn(ESourceLDAP * extension)584 e_source_ldap_get_root_dn (ESourceLDAP *extension)
585 {
586 g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), NULL);
587
588 return extension->priv->root_dn;
589 }
590
591 gchar *
e_source_ldap_dup_root_dn(ESourceLDAP * extension)592 e_source_ldap_dup_root_dn (ESourceLDAP *extension)
593 {
594 const gchar *protected;
595 gchar *duplicate;
596
597 g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), NULL);
598
599 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
600
601 protected = e_source_ldap_get_root_dn (extension);
602 duplicate = g_strdup (protected);
603
604 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
605
606 return duplicate;
607 }
608
609 void
e_source_ldap_set_root_dn(ESourceLDAP * extension,const gchar * root_dn)610 e_source_ldap_set_root_dn (ESourceLDAP *extension,
611 const gchar *root_dn)
612 {
613 g_return_if_fail (E_IS_SOURCE_LDAP (extension));
614
615 e_source_extension_property_lock (E_SOURCE_EXTENSION (extension));
616
617 if (e_util_strcmp0 (extension->priv->root_dn, root_dn) == 0) {
618 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
619 return;
620 }
621
622 g_free (extension->priv->root_dn);
623 extension->priv->root_dn = e_util_strdup_strip (root_dn);
624
625 e_source_extension_property_unlock (E_SOURCE_EXTENSION (extension));
626
627 g_object_notify (G_OBJECT (extension), "root-dn");
628 }
629
630 ESourceLDAPScope
e_source_ldap_get_scope(ESourceLDAP * extension)631 e_source_ldap_get_scope (ESourceLDAP *extension)
632 {
633 g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), 0);
634
635 return extension->priv->scope;
636 }
637
638 void
e_source_ldap_set_scope(ESourceLDAP * extension,ESourceLDAPScope scope)639 e_source_ldap_set_scope (ESourceLDAP *extension,
640 ESourceLDAPScope scope)
641 {
642 g_return_if_fail (E_IS_SOURCE_LDAP (extension));
643
644 if (extension->priv->scope == scope)
645 return;
646
647 extension->priv->scope = scope;
648
649 g_object_notify (G_OBJECT (extension), "scope");
650 }
651
652 ESourceLDAPSecurity
e_source_ldap_get_security(ESourceLDAP * extension)653 e_source_ldap_get_security (ESourceLDAP *extension)
654 {
655 g_return_val_if_fail (E_IS_SOURCE_LDAP (extension), 0);
656
657 return extension->priv->security;
658 }
659
660 void
e_source_ldap_set_security(ESourceLDAP * extension,ESourceLDAPSecurity security)661 e_source_ldap_set_security (ESourceLDAP *extension,
662 ESourceLDAPSecurity security)
663 {
664 g_return_if_fail (E_IS_SOURCE_LDAP (extension));
665
666 if (extension->priv->security == security)
667 return;
668
669 extension->priv->security = security;
670
671 g_object_notify (G_OBJECT (extension), "security");
672 }
673