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