add user specified stylesheet option
[claws.git] / src / ldapupdate.c
blobb13f2429c91fc7ba4aa308f9b71f5e0f15d911e3
1 /*
2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 2003-2012 Michael Rasmussen and the Claws Mail team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 * Functions necessary to access LDAP servers.
25 * Outstanding bugs
26 * 1) When adding a contact to an empty addressbook from the pop-up menu
27 * when right-clicking on an email address causes claws-mail to crash in
28 * addritem.c line 965. Severity: Show stopper. Solved in 2.9.2cvs17
29 * 2) Updating a contact gets lost if the user makes a new search on the
30 * same LdapServer. Severity: Medium. Solved in 2.9.2cvs17 (patch added to solve 1) also solved this bug)
31 * 3) After adding a new contact the displayName for the contact is empty
32 * until the user makes a reread from the LdapServer. Severity: minor.
33 * Solved in 2.9.2cvs24
36 #ifdef HAVE_CONFIG_H
37 # include "config.h"
38 #include "claws-features.h"
39 #endif
41 #ifdef USE_LDAP
43 #include <glib.h>
44 #include <glib/gi18n.h>
45 #include <sys/time.h>
46 #include <string.h>
48 #include "ldapupdate.h"
49 #include "mgutils.h"
50 #include "addritem.h"
51 #include "addrcache.h"
52 #include "ldapctrl.h"
53 #include "ldapquery.h"
54 #include "ldapserver.h"
55 #include "ldaputil.h"
56 #include "utils.h"
57 #include "adbookbase.h"
58 #include "editaddress_other_attributes_ldap.h"
60 /**
61 * Structure to hold user defined attributes
62 * from contacts
64 typedef struct _AttrKeyValue AttrKeyValue;
65 struct _AttrKeyValue {
66 gchar *key;
67 gchar *value;
70 /**
71 * Structure to hold contact information.
72 * Each addressbook will have 0..N contacts.
74 typedef struct _EmailKeyValue EmailKeyValue;
75 struct _EmailKeyValue {
76 gchar *mail;
77 gchar *alias;
78 gchar *remarks;
81 /**
82 * Structure to hold information about RDN.
84 typedef struct _Rdn Rdn;
85 struct _Rdn {
86 gchar *attribute;
87 gchar *value;
88 gchar *new_dn;
91 /**
92 * Retrieve address group item for update.
93 * \param group Group to print.
94 * \param array GHashTAble of item_group, or <i>NULL</i> if none created.
96 void ldapsvr_retrieve_item_group(ItemGroup *group, GHashTable *array) {
97 /* Not implemented in this release */
98 cm_return_if_fail(group != NULL);
102 * Create an initial EmailKeyValue structure
103 * \return empty structure
105 EmailKeyValue *emailkeyvalue_create() {
106 EmailKeyValue *buf;
108 buf = g_new0(EmailKeyValue, 1);
109 buf->alias = NULL;
110 buf->mail = NULL;
111 buf->remarks = NULL;
112 return buf;
116 * Create an initial AttrKeyValue structure
117 * \return empty structure
119 AttrKeyValue *attrkeyvalue_create() {
120 AttrKeyValue *buf;
122 buf = g_new0(AttrKeyValue, 1);
123 buf->key = NULL;
124 buf->value = NULL;
125 return buf;
129 * Free created AttrKeyValue structure
130 * \param akv AttrKeyValue structure to free
132 void attrkeyvalue_free(AttrKeyValue *akv) {
133 if (akv->key) {
134 g_free(akv->key);
135 akv->key = NULL;
137 if (akv->value) {
138 g_free(akv->value);
139 akv->value = NULL;
141 g_free(akv);
142 akv = NULL;
146 * Retrieve E-Mail address object for update.
147 * \param item ItemEmail to update.
148 * \return object, or <i>NULL</i> if none created.
150 EmailKeyValue *ldapsvr_retrieve_item_email(ItemEMail *item) {
151 EmailKeyValue *newItem;
152 cm_return_val_if_fail(item != NULL, NULL);
153 newItem = emailkeyvalue_create();
154 newItem->alias = g_strdup(ADDRITEM_NAME(item));
155 newItem->mail = g_strdup(item->address);
156 newItem->remarks = g_strdup(item->remarks);
157 return newItem;
161 * Retrieve user attribute object for update.
162 * \param item UserAttribute to update.
163 * \return object, or <i>NULL</i> if none created.
165 AttrKeyValue *ldapsvr_retrieve_attribute(UserAttribute *item) {
166 AttrKeyValue *newItem;
167 cm_return_val_if_fail(item != NULL, NULL);
168 newItem = attrkeyvalue_create();
169 newItem->key = g_strdup(item->name);
170 newItem->value = g_strdup(item->value);
171 return newItem;
175 * Retrieve person object for update.
176 * \param person ItemPerson to update.
177 * \param array GHashTable with user input.
178 * \return false if update is not needed, or true if update is needed.
180 gboolean ldapsvr_retrieve_item_person(ItemPerson *person, GHashTable *array) {
181 GList *node, *attr;
183 cm_return_val_if_fail(person != NULL, FALSE);
184 switch (person->status) {
185 case NONE: return FALSE;
186 case ADD_ENTRY: g_hash_table_insert(array, "status", "new"); break;
187 case UPDATE_ENTRY: g_hash_table_insert(array, "status", "update"); break;
188 case DELETE_ENTRY: g_hash_table_insert(array, "status", "delete"); break;
189 default: g_critical("ldapsvr_retrieve_item_person->Unknown status: %d", person->status);
191 g_hash_table_insert(array, "uid", ADDRITEM_ID(person));
192 g_hash_table_insert(array, "cn", ADDRITEM_NAME(person));
193 g_hash_table_insert(array, "givenName", person->firstName);
194 g_hash_table_insert(array, "sn", person->lastName);
195 g_hash_table_insert(array, "nickName", person->nickName);
196 g_hash_table_insert(array, "dn", person->externalID);
197 g_hash_table_insert(array, "person", person);
198 node = person->listEMail;
199 attr = NULL;
200 while (node) {
201 EmailKeyValue *newEmail = ldapsvr_retrieve_item_email(node->data);
202 if (newEmail)
203 attr = g_list_append(attr, newEmail);
204 node = g_list_next(node);
206 g_hash_table_insert(array, "mail", attr);
207 node = person->listAttrib;
208 attr = NULL;
209 while (node) {
210 AttrKeyValue *newAttr = ldapsvr_retrieve_attribute(node->data);
211 if (newAttr)
212 attr = g_list_append(attr, newAttr);
213 node = g_list_next(node);
215 g_hash_table_insert(array, "attribute", attr);
216 return TRUE;
220 * Print contents of contacts hashtable for debug.
221 * This function must be called with g_hash_table_foreach.
222 * \param key Key to process.
223 * \param data Data to process.
224 * \param fd Output stream.
226 void ldapsvr_print_contacts_hashtable(gpointer key, gpointer data, gpointer fd) {
227 gchar *keyName = (gchar *) key;
228 GList *node;
230 if (g_ascii_strcasecmp("mail", keyName) == 0) {
231 node = (GList *) data;
232 while (node) {
233 EmailKeyValue *item = node->data;
234 if (debug_get_mode()) {
235 debug_print("\t\talias = %s\n", item->alias?item->alias:"null");
236 debug_print("\t\tmail = %s\n", item->mail?item->mail:"null");
237 debug_print("\t\tremarks = %s\n", item->remarks?item->remarks:"null");
239 else if (fd) {
240 FILE *stream = (FILE *) fd;
241 fprintf(stream, "\t\talias = %s\n", item->alias?item->alias:"null");
242 fprintf(stream, "\t\tmail = %s\n", item->mail?item->mail:"null");
243 fprintf(stream, "\t\tremarks = %s\n", item->remarks?item->remarks:"null");
245 node = g_list_next(node);
248 else if (g_ascii_strcasecmp("attribute", keyName) == 0) {
249 node = (GList *) data;
250 while (node) {
251 AttrKeyValue *item = node->data;
252 if (debug_get_mode()) {
253 debug_print("\t\t%s = %s\n", item->key?item->key:"null",
254 item->value?item->value:"null");
256 else if (fd) {
257 FILE *stream = (FILE *) fd;
258 fprintf(stream, "\t\t%s = %s\n", item->key?item->key:"null",
259 item->value?item->value:"null");
261 node = g_list_next(node);
264 else {
265 if (debug_get_mode())
266 debug_print("\t\t%s = %s\n", keyName?keyName:"null", data?(gchar *)data:"null");
267 else if (fd) {
268 FILE *stream = (FILE *) fd;
269 fprintf(stream, "\t\t%s = %s\n", keyName?keyName:"null", data?(gchar *)data:"null");
275 * Free list of changed contacts
277 * \param list List of GHashTable
279 void ldapsvr_free_hashtable(GList *list) {
280 GList *tmp = list;
281 while (tmp) {
282 g_hash_table_destroy(tmp->data);
283 tmp->data = NULL;
284 tmp = g_list_next(tmp);
286 g_list_free(list);
287 list = NULL;
291 * Get person object from cache
293 * \param server Resource to LDAP
294 * \param uid PersonID in cache
295 * \return person object, or <i>NULL</i> if fail
297 ItemPerson *ldapsvr_get_contact(LdapServer *server, gchar *uid) {
298 AddrItemObject *aio;
299 cm_return_val_if_fail(server != NULL || uid != NULL, NULL);
300 aio = addrcache_get_object(server->addressCache, uid);
301 if (aio) {
302 if(aio->type == ITEMTYPE_PERSON) {
303 return (ItemPerson *) aio;
306 return NULL;
310 * Create an initial Rdn structure
312 * \return empty structure
314 Rdn *rdn_create() {
315 Rdn *buf;
317 buf = g_new0(Rdn, 1);
318 buf->attribute = NULL;
319 buf->value = NULL;
320 buf->new_dn = NULL;
321 return buf;
325 * Free a created Rdn structure
326 * \param rdn Structure to free
328 void rdn_free(Rdn *rdn) {
329 if (rdn->attribute) {
330 g_free(rdn->attribute);
331 rdn->attribute = NULL;
333 if (rdn->value) {
334 g_free(rdn->value);
335 rdn->value = NULL;
337 if (rdn->new_dn) {
338 g_free(rdn->new_dn);
339 rdn->new_dn = NULL;
341 g_free(rdn);
342 rdn = NULL;
346 * update Rdn structure
348 * \param rdn Rdn structure to update
349 * \param head Uniq part of dn
350 * \param tail Common part of dn
352 void update_rdn(Rdn *rdn, gchar *head, gchar *tail) {
353 rdn->value = g_strdup(head);
354 rdn->new_dn = g_strdup_printf("%s=%s%s", rdn->attribute, head, tail);
358 * Deside if dn needs to be changed
360 * \param hash GHashTable with user input.
361 * \param dn dn for current object
362 * \return Rdn structure
364 Rdn *ldapsvr_modify_dn(GHashTable *hash, gchar *dn) {
365 Rdn *rdn;
366 gchar *pos, *compare;
367 gchar *rest;
368 gchar *val;
369 cm_return_val_if_fail(hash != NULL || dn != NULL, NULL);
371 pos = g_strstr_len(dn, strlen(dn), "=");
372 if (!pos)
373 return NULL;
375 compare = g_strndup(dn, pos - dn);
377 pos++;
378 rest = g_strstr_len(pos, strlen(pos), ",");
379 val = g_strndup(pos, rest - pos);
380 if (val == NULL) {
381 if (compare)
382 g_free(compare);
383 return NULL;
385 rdn = rdn_create();
386 rdn->value = val;
387 rdn->attribute = compare;
389 if (strcmp("mail", rdn->attribute) == 0) {
390 GList *list = g_hash_table_lookup(hash, rdn->attribute);
391 while (list) {
392 EmailKeyValue *item = list->data;
393 compare = (gchar *) item->mail;
394 if (strcmp(compare, rdn->value) == 0) {
395 update_rdn(rdn, compare, rest);
396 return rdn;
398 list = g_list_next(list);
400 /* if compare and rdn->attribute are equal then last email removed/empty */
401 if (strcmp(compare, rdn->attribute) != 0) {
402 /* RDN changed. Find new */
403 update_rdn(rdn, compare, rest);
404 return rdn;
407 else {
408 compare = g_hash_table_lookup(hash, rdn->attribute);
409 /* if compare and rdn->attribute are equal then dn removed/empty */
410 if (strcmp(compare, rdn->attribute) != 0) {
411 update_rdn(rdn, compare, rest);
412 return rdn;
415 rdn_free(rdn);
416 return NULL;
420 * This macro is borrowed from the Balsa project
421 * Creates a LDAPMod structure
423 * \param mods Empty LDAPMod structure
424 * \param modarr Array with values to insert
425 * \param op Operation to perform on LDAP
426 * \param attr Attribute to insert
427 * \param strv Empty array which is NULL terminated
428 * \param val Value for attribute
430 #define SETMOD(mods,modarr,op,attr,strv,val) \
431 do { (mods) = &(modarr); (modarr).mod_type=attr; (modarr).mod_op=op;\
432 (strv)[0]=(val); (modarr).mod_values=strv; \
433 } while(0)
436 * Creates a LDAPMod structure
438 * \param mods Empty LDAPMod structure
439 * \param modarr Array with values to insert
440 * \param op Operation to perform on LDAP
441 * \param attr Attribute to insert
442 * \param strv Array with values to insert. Must be NULL terminated
444 #define SETMODS(mods,modarr,op,attr,strv) \
445 do { (mods) = &(modarr); (modarr).mod_type=attr; \
446 (modarr).mod_op=op; (modarr).mod_values=strv; \
447 } while(0)
448 #define MODSIZE 10
451 * Clean up, close LDAP connection, and refresh cache
453 * \param ld Resource to LDAP
454 * \param server AddressBook resource
455 * \param contact GHashTable with current changed object
457 void clean_up(LDAP *ld, LdapServer *server, GHashTable *contact) {
458 ItemPerson *person =
459 ldapsvr_get_contact(server, g_hash_table_lookup(contact , "uid"));
460 if (person) {
461 gchar *displayName;
462 person->status = NONE;
463 displayName = g_hash_table_lookup(contact, "displayName");
464 if (displayName)
465 person->nickName = g_strdup(displayName);
467 if (server->retVal != LDAPRC_SUCCESS) {
468 if (person) {
469 ItemPerson *res =
470 addrcache_remove_person(server->addressCache, person);
471 if (!res)
472 g_critical("ldapsvr_update_book: Could not clean cache\n");
473 else
474 addritem_free_item_person(res);
477 if (ld)
478 ldapsvr_disconnect(ld);
482 * Get cn attribute from dn
484 * \param dn Distinguesh Name for current object
485 * \return AttrKeyValue, or <i>NULL</i> if none created
487 AttrKeyValue *get_cn(gchar *dn) {
488 AttrKeyValue *cn;
489 gchar *start;
490 gchar *end;
491 gchar *item;
492 gchar **key_value;
493 cm_return_val_if_fail(dn != NULL, NULL);
495 cn = attrkeyvalue_create();
496 start = g_strstr_len(dn, strlen(dn), "cn");
497 if (start == NULL) {
498 attrkeyvalue_free(cn);
499 return NULL;
501 end = g_strstr_len(start, strlen(start), ",");
502 item = g_strndup(start, end - start);
503 if (item == NULL) {
504 attrkeyvalue_free(cn);
505 return NULL;
507 key_value = g_strsplit(item, "=", 2);
508 cn->key = g_strdup(key_value[0]);
509 cn->value = g_strdup(key_value[1]);
510 g_strfreev(key_value);
511 g_free(item);
512 return cn;
516 * Get mail attribute from dn
518 * \param dn Distinguesh Name for current object
519 * \return AttrKeyValue, or <i>NULL</i> if none created
521 AttrKeyValue *get_mail(gchar *dn) {
522 AttrKeyValue *mail;
523 gchar *start;
524 gchar *end;
525 gchar *item;
526 gchar **key_value;
527 cm_return_val_if_fail(dn != NULL, NULL);
529 mail = attrkeyvalue_create();
530 start = g_strstr_len(dn, strlen(dn), "mail");
531 if (start == NULL) {
532 attrkeyvalue_free(mail);
533 return NULL;
535 end = g_strstr_len(start, strlen(start), ",");
536 item = g_strndup(start, end - start);
537 if (item == NULL) {
538 attrkeyvalue_free(mail);
539 return NULL;
541 key_value = g_strsplit(item, "=", 2);
542 mail->key = g_strdup(key_value[0]);
543 mail->value = g_strdup(key_value[1]);
544 g_strfreev(key_value);
545 g_free(item);
546 return mail;
550 * Get ou or o attribute from dn
552 * \param dn Distinguesh Name for current object
553 * \return AttrKeyValue, or <i>NULL</i> if none created
555 AttrKeyValue *get_ou(gchar *dn) {
556 AttrKeyValue *ou;
557 gchar *start;
558 gchar *end;
559 gchar *item;
560 gchar **key_value;
562 cm_return_val_if_fail(dn != NULL, NULL);
563 ou = attrkeyvalue_create();
564 start = g_strstr_len(dn, strlen(dn), ",o=");
565 if (start == NULL)
566 start = g_strstr_len(dn, strlen(dn), ",ou=");
567 if (start == NULL) {
568 attrkeyvalue_free(ou);
569 return NULL;
571 start++;
572 end = g_strstr_len(start, strlen(start), ",");
573 item = g_strndup(start, end - start);
574 if (item == NULL) {
575 attrkeyvalue_free(ou);
576 return NULL;
578 key_value = g_strsplit(item, "=", 2);
579 ou->key = g_strdup(key_value[0]);
580 ou->value = g_strdup(key_value[1]);
581 g_strfreev(key_value);
582 g_free(item);
583 return ou;
587 * Print the contents of a LDAPMod structure for debuging purposes
589 * \param mods LDAPMod structure
591 void ldapsvr_print_ldapmod(LDAPMod *mods[]) {
592 gchar *mod_op;
593 int i;
595 cm_return_if_fail(mods != NULL);
596 g_printerr( "Type\n");
597 for (i = 0; NULL != mods[i]; i++) {
598 LDAPMod *mod = (LDAPMod *) mods[i];
599 gchar **vals;
600 switch (mod->mod_op) {
601 case LDAP_MOD_ADD: mod_op = g_strdup("ADD"); break;
602 case LDAP_MOD_REPLACE: mod_op = g_strdup("MODIFY"); break;
603 case LDAP_MOD_DELETE: mod_op = g_strdup("DELETE"); break;
604 default: mod_op = g_strdup("UNKNOWN");
606 g_printerr( "Operation: %s\tType:%s\nValues:\n", mod_op, mod->mod_type);
607 vals = mod->mod_vals.modv_strvals;
608 while (*vals) {
609 g_printerr( "\t%s\n", *vals++);
615 * Make a compare for every new value we want to store in the
616 * directory with the current values. Great tool for debugging
617 * against invalid syntax in attributes
619 * \param ld AddressBook resource
620 * \param dn dn for the entry
621 * \param cnt Number of attributes to compare
622 * \param mods LDAPMod structure
624 void ldapsvr_compare_attr(LDAP *ld, gchar *dn, gint cnt, LDAPMod *mods[]) {
625 int i, rc;
627 #ifdef OPEN_LDAP_API_AT_LEAST_3000
629 struct berval val;
631 #endif
633 cm_return_if_fail(ld != NULL || dn != NULL || cnt >= 0 || mods != NULL);
634 for (i = 0; i < cnt; i++) {
635 gchar *value = g_strdup(mods[i]->mod_vals.modv_strvals[0]);
636 if (!value || strcmp(value, "") == 0)
637 value = g_strdup("thisisonlyadummy");
639 #ifdef OPEN_LDAP_API_AT_LEAST_3000
641 val.bv_val = value;
642 val.bv_len = strlen(value);
644 rc = ldap_compare_ext_s(ld, dn, mods[i]->mod_type, &val, NULL, NULL);
646 #else
648 /* This is deprecated as of OpenLDAP-2.3.0 */
649 rc = ldap_compare_s(ld, dn, mods[i]->mod_type, value);
651 #endif
653 g_printerr("ldap_compare for (%s:%s)\" failed[0x%x]: %s\n",
654 mods[i]->mod_type, value, rc, ldaputil_get_error(ld));
655 g_free(value);
660 * compare attribute to LDAP in case of LDAP_INAPPROPRIATE_MATCHING
662 * \param ld AddressBook resource
663 * \param server Reference to server
664 * \param dn dn for the entry
665 * \param attr Attribute
666 * \param value New value
667 * \return int, return will be LDAP_MOD_ADD, LDAP_MOD_REPLACE, or LDAP_MOD_DELETE
669 int ldapsvr_compare_manual_attr(LDAP *ld, LdapServer *server, gchar *dn, char *attr, char *value) {
670 LDAPMessage *res, *e = NULL;
671 BerElement *ber;
672 struct berval **vals;
673 int rc;
674 LdapControl *ctl;
675 gchar *filter;
676 gchar *attribute;
677 int retVal = -2, i;
678 AttrKeyValue *mail;
680 cm_return_val_if_fail(ld != NULL || server != NULL || attr != NULL, -1);
681 ctl = server->control;
682 mail = get_mail(dn);
683 if (! mail)
684 return -2;
685 filter = g_strdup_printf("(&(mail=%s)(%s=*))", mail->value, attr);
686 attrkeyvalue_free(mail);
687 if (ctl) {
689 rc = ldap_search_ext_s(ld, ctl->baseDN, LDAP_SCOPE_ONELEVEL, filter, NULL, 0, NULL, NULL, NULL, 0, &res);
691 if (rc) {
692 g_printerr("ldap_search for attr=%s\" failed[0x%x]: %s\n",attr, rc, ldaputil_get_error(ld));
693 retVal = -2;
695 else {
696 e = ldap_first_entry(ld, res);
697 /* entry has this attribute */
698 if (e) {
699 attribute = ldap_first_attribute( ld, e, &ber );
700 if (attribute) {
701 if (value) {
702 if( ( vals = ldap_get_values_len( ld, e, attr ) ) != NULL ) {
703 for( i = 0; vals[i] != NULL; i++ ) {
704 debug_print("Compare: %s=%s\n", attr, vals[i]->bv_val);
705 /* attribute has same value */
706 if (strcmp(vals[i]->bv_val, value) == 0)
707 retVal = -1;
708 /* attribute has new value */
709 else
710 retVal = LDAP_MOD_REPLACE;
713 ldap_value_free_len(vals);
715 else
716 retVal = LDAP_MOD_DELETE;
718 if( ber != NULL ) {
719 ber_free( ber, 0 );
721 ldap_memfree(attribute);
723 /* entry does not have this attribute */
724 else {
725 /* Only add if this is a real attribute */
726 if (value)
727 retVal = LDAP_MOD_ADD;
728 /* This is dummy value used to avoid ldap_compare error */
729 else
730 retVal = -1;
734 else
735 retVal = -2;
736 g_free(filter);
737 return retVal;
741 * Deside which kind of operation is required to handle
742 * updating the specified attribute
744 * \param ld AddressBook resource
745 * \param server Reference to server
746 * \param dn dn for the entry
747 * \param attr Attribute
748 * \param value New value
749 * \return int, return will be LDAP_MOD_ADD, LDAP_MOD_REPLACE, or LDAP_MOD_DELETE
751 int ldapsvr_deside_operation(LDAP *ld, LdapServer *server, char *dn, char *attr, char *value) {
752 int rc;
753 gboolean dummy = FALSE;
755 #ifdef OPEN_LDAP_API_AT_LEAST_3000
757 struct berval val;
759 #endif
761 cm_return_val_if_fail(ld != NULL || server != NULL || dn != NULL || attr != NULL, -1);
762 if (value == NULL)
763 return -1;
764 /* value containing empty string cause invalid syntax. A bug in
765 * the LDAP library? Therefore we add a dummy value
767 if (strcmp(value,"") == 0) {
768 value = g_strdup("thisisonlyadummy");
769 dummy = TRUE;
772 #ifdef OPEN_LDAP_API_AT_LEAST_3000
774 val.bv_val = value;
775 val.bv_len = strlen(value);
777 rc = ldap_compare_ext_s(ld, dn, attr, &val, NULL, NULL);
779 #else
781 /* This is deprecated as of OpenLDAP-2.3.0 */
782 rc = ldap_compare_s(ld, dn, attr, value);
784 #endif
786 debug_print("ldap_compare for (%s:%s)\" error_code[0x%x]: %s\n",
787 attr, value, rc, ldaputil_get_error(ld));
788 switch (rc) {
789 case LDAP_COMPARE_FALSE:
790 if (dummy)
791 return LDAP_MOD_DELETE;
792 else
793 return LDAP_MOD_REPLACE;
794 case LDAP_COMPARE_TRUE: return -1;
795 case LDAP_NO_SUCH_ATTRIBUTE: return LDAP_MOD_ADD;
796 /* LDAP_INAPPROPRIATE_MATCHING needs extensive testing because I
797 * am not aware off the condition causing this return value!
799 case LDAP_INAPPROPRIATE_MATCHING:
800 if (dummy)
801 value = NULL;
802 return ldapsvr_compare_manual_attr(ld, server, dn, attr, value);
803 case LDAP_UNDEFINED_TYPE: return -2;
804 case LDAP_INVALID_SYNTAX: return -2;
805 default: return -2;
810 * Check if attribute is part of the current search criteria
812 * \param list Array containing attributes in the current search criteria
813 * \param attr Attribute to check
814 * \result <i>TRUE</i> if attribute is found in the current search criteria
816 gboolean ldapsvr_check_search_attributes(char **list, char *attr) {
817 while (*list) {
818 if (strcmp(*list++, attr) == 0)
819 return TRUE;
821 return FALSE;
825 * Deside which other attributes needs updating
827 * \param ld LDAP resource
828 * \param server AddressBook resource
829 * \param dn dn for the entry
830 * \param contact GHashTable with information for the current contact
832 void ldapsvr_handle_other_attributes(LDAP *ld, LdapServer *server, char *dn, GHashTable *contact) {
833 GList *node;
834 gboolean CHECKED_ATTRIBUTE[ATTRIBUTE_SIZE + 1];
835 LDAPMod *mods[ATTRIBUTE_SIZE + 1];
836 LDAPMod modarr[ATTRIBUTE_SIZE];
837 gint cnt = 0;
838 char *attr[ATTRIBUTE_SIZE + 1][2];
839 int mod_op, rc, i;
841 cm_return_if_fail(server != NULL || dn != NULL || contact != NULL);
842 for (i = 0; i <= ATTRIBUTE_SIZE; i++) {
843 CHECKED_ATTRIBUTE[i] = FALSE;
844 attr[i][0] = attr[i][1] = NULL;
846 node = g_hash_table_lookup(contact , "attribute");
847 while (node) {
848 AttrKeyValue *item = node->data;
849 if (item) {
850 int index = get_attribute_index(item->key);
851 if (index >= 0) {
852 debug_print("Found other attribute: %s = %s\n",
853 item->key?item->key:"null", item->value?item->value:"null");
854 mod_op = ldapsvr_deside_operation(ld, server, dn, item->key, item->value);
855 /* Only consider attributes which we no how to handle.
856 * Set to TRUE in CHECKED_ATTRIBUTE array to indicate no further action
858 if (mod_op < 0) {
859 CHECKED_ATTRIBUTE[index] = TRUE;
860 node = g_list_next(node);
861 continue;
863 if (mod_op == LDAP_MOD_DELETE) {
864 /* Setting param to NULL instructs OpenLDAP to remove any
865 * value stored for this attribute and remove the attribute
866 * completely. Should multiple instances of an attribute be
867 * allowed in the future param is required to have the value
868 * store for the attribute which is going to be deleted
870 item->value = NULL;
872 if (mod_op == LDAP_MOD_REPLACE && strcmp(item->value, "") == 0) {
873 /* Having an empty string is considered a syntax error in
874 * ldap. E.g attributes with empty strings are not allowed
875 * in which case we treate this as a request for deleting
876 * the attribute.
878 mod_op = LDAP_MOD_DELETE;
879 item->value = NULL;
881 if (mod_op == LDAP_MOD_ADD && strcmp(item->value, "") == 0) {
882 /* Adding an empty string is considered a syntax error in
883 * ldap. E.g attributes with empty strings are not allowed
884 * in which case we silently refuse to add this entry
887 else {
888 SETMOD(mods[cnt], modarr[cnt], mod_op, g_strdup(item->key), attr[cnt], g_strdup(item->value));
889 cnt++;
890 CHECKED_ATTRIBUTE[index] = TRUE;
894 node = g_list_next(node);
896 char **attribs = ldapctl_full_attribute_array(server->control);
897 for (i = 0; i < ATTRIBUTE_SIZE; i++) {
898 /* Attributes which holds no information are to be removed */
899 if (CHECKED_ATTRIBUTE[i] == FALSE) {
900 /* Only consider those attributes which is currently part of the search criteria.
901 * If attributes are not part of the search criteria they would seem to hold
902 * no information since their values will not be populated in the GUI
904 if (!strcmp(ATTRIBUTE[i], "jpegPhoto")) {
905 debug_print("not updating jpegPhoto\n");
906 continue;
908 if (ldapsvr_check_search_attributes(attribs, (char *) ATTRIBUTE[i])) {
909 mod_op = ldapsvr_deside_operation(ld, server, dn, (char *) ATTRIBUTE[i], "");
910 if (mod_op == LDAP_MOD_DELETE) {
911 SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_DELETE, g_strdup((char *) ATTRIBUTE[i]), attr[cnt], NULL);
912 cnt++;
917 ldapctl_free_attribute_array(attribs);
918 mods[cnt] = NULL;
919 if (debug_get_mode())
920 ldapsvr_print_ldapmod(mods);
921 server->retVal = LDAPRC_SUCCESS;
922 rc = ldap_modify_ext_s(ld, dn, mods, NULL, NULL);
923 if (rc) {
924 switch (rc) {
925 case LDAP_ALREADY_EXISTS:
926 server->retVal = LDAPRC_ALREADY_EXIST;
927 break;
928 default:
929 g_printerr("ldap_modify for dn=%s\" failed[0x%x]: %s\n", dn, rc, ldaputil_get_error(ld));
930 if (rc == 0x8)
931 server->retVal = LDAPRC_STRONG_AUTH;
932 else
933 server->retVal = LDAPRC_NAMING_VIOLATION;
936 else {
937 char **attribs = ldapctl_full_attribute_array(server->control);
938 for (i = 0; i < ATTRIBUTE_SIZE; i++) {
939 if (!strcmp(ATTRIBUTE[i], "jpegPhoto")) {
940 debug_print("not updating jpegPhoto\n");
941 continue;
943 if (ldapsvr_check_search_attributes(attribs, (char *) ATTRIBUTE[i])) {
944 if (CHECKED_ATTRIBUTE[i] == FALSE) {
945 AddrItemObject *aio = addrcache_get_object(server->addressCache, g_hash_table_lookup(contact , "uid"));
946 ItemPerson *person = (ItemPerson *) aio;
947 addritem_person_remove_attribute(person, (const gchar *) ATTRIBUTE[i]);
951 ldapctl_free_attribute_array(attribs);
956 * Add new contact to LDAP
958 * \param server AddressBook resource
959 * \param contact GHashTable with object to add
961 void ldapsvr_add_contact(LdapServer *server, GHashTable *contact) {
962 gchar *email = NULL, *param = NULL;
963 LDAP *ld = NULL;
964 LDAPMod *mods[MODSIZE];
965 LDAPMod modarr[7];
966 gint cnt = 0;
967 char *cn[] = {NULL, NULL};
968 char *displayName[] = {NULL, NULL};
969 char *givenName[] = {NULL, NULL};
970 char **mail = NULL;
971 char *sn[] = {NULL, NULL};
972 char *org[] = {NULL, NULL};
973 char *obj[] = {/*"top",*/ "person", "organizationalPerson", "inetOrgPerson", NULL};
974 int rc=0;
975 GList *node;
976 AttrKeyValue *ou, *commonName;
977 ItemPerson *person;
978 gchar *base_dn;
979 GList *mailList;
981 cm_return_if_fail(server != NULL || contact != NULL);
982 node = g_hash_table_lookup(contact , "mail");
983 if (node) {
984 EmailKeyValue *newEmail = node->data;
985 email = g_strdup(newEmail->mail);
987 if (email == NULL) {
988 server->retVal = LDAPRC_NODN;
989 clean_up(ld, server, contact);
990 return;
992 base_dn = g_strdup_printf("mail=%s,%s",
993 email, server->control->baseDN?server->control->baseDN:"null");
994 g_free(email);
995 person =
996 ldapsvr_get_contact(server, g_hash_table_lookup(contact , "uid"));
997 person->externalID = g_strdup(base_dn);
998 debug_print("dn: %s\n", base_dn);
999 ld = ldapsvr_connect(server->control);
1000 if (ld == NULL) {
1001 clean_up(ld, server, contact);
1002 debug_print("no ldap found\n");
1003 return;
1005 SETMODS(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "objectClass", obj);
1006 cnt++;
1007 ou = get_ou(base_dn);
1008 if (ou != NULL) {
1009 SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, g_strdup(ou->key), org, g_strdup(ou->value));
1010 cnt++;
1011 attrkeyvalue_free(ou);
1014 commonName = get_cn(base_dn);
1015 if (commonName == NULL) {
1016 param = g_hash_table_lookup(contact , "cn");
1017 if (param) {
1018 SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "cn", cn, param);
1020 else {
1021 clean_up(ld, server, contact);
1022 debug_print("no CN found\n");
1023 return;
1026 else {
1027 SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, g_strdup(commonName->key), cn, g_strdup(commonName->value));
1028 cnt++;
1029 param = g_hash_table_lookup(contact , "cn");
1030 SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "displayName", displayName, param);
1031 g_hash_table_insert(contact, "displayName", param);
1032 attrkeyvalue_free(commonName);
1034 cnt++;
1035 param = g_hash_table_lookup(contact , "givenName");
1036 if (param) {
1037 SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "givenName", givenName, param);
1038 cnt++;
1040 mailList = g_hash_table_lookup(contact , "mail");
1041 if (mailList) {
1042 char **tmp;
1043 tmp = g_malloc(sizeof(*tmp) * (g_list_length(mailList)+1));
1044 mail = tmp;
1045 while (mailList) {
1046 EmailKeyValue *item = mailList->data;
1047 *tmp++ = g_strdup((gchar *) item->mail);
1048 mailList = g_list_next(mailList);
1050 *tmp = NULL;
1051 SETMODS(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "mail", mail);
1052 cnt++;
1054 param = g_hash_table_lookup(contact, "sn");
1055 if (param == NULL)
1056 param = g_strdup(N_("Some SN"));
1057 SETMOD(mods[cnt], modarr[cnt], LDAP_MOD_ADD, "sn", sn, param);
1058 cnt++;
1059 mods[cnt] = NULL;
1060 if (debug_get_mode()) {
1061 ldapsvr_print_ldapmod(mods);
1063 server->retVal = LDAPRC_SUCCESS;
1064 rc = ldap_add_ext_s(ld, base_dn, mods, NULL, NULL);
1065 if (rc) {
1066 switch (rc) {
1067 case LDAP_ALREADY_EXISTS:
1068 server->retVal = LDAPRC_ALREADY_EXIST;
1069 break;
1070 default:
1071 g_printerr("ldap_modify for dn=%s\" failed[0x%x]: %s\n",
1072 base_dn, rc, ldaputil_get_error(ld));
1073 if (rc == 0x8)
1074 server->retVal = LDAPRC_STRONG_AUTH;
1075 else
1076 server->retVal = LDAPRC_NAMING_VIOLATION;
1079 ldapsvr_handle_other_attributes(ld, server, base_dn, contact);
1080 g_free(base_dn);
1081 clean_up(ld, server, contact);
1085 * Update contact to LDAP
1087 * \param server AddressBook resource
1088 * \param contact GHashTable with object to update
1090 void ldapsvr_update_contact(LdapServer *server, GHashTable *contact) {
1091 LDAP *ld = NULL;
1092 LDAPMod *mods[MODSIZE];
1093 LDAPMod modarr[4];
1094 gint cnt = 0;
1095 gchar *param, *dn;
1096 Rdn *NoRemove = NULL;
1097 char *cn[] = {NULL, NULL};
1098 char *givenName[] = {NULL, NULL};
1099 char **mail = NULL;
1100 char *sn[] = {NULL, NULL};
1101 GList *mailList;
1102 int mod_op;
1104 cm_return_if_fail(server != NULL || contact != NULL);
1105 ld = ldapsvr_connect(server->control);
1106 if (ld == NULL) {
1107 clean_up(ld, server, contact);
1108 return;
1110 dn = g_hash_table_lookup(contact, "dn");
1112 if (dn == NULL) {
1113 clean_up(ld, server, contact);
1114 return;
1116 NoRemove = ldapsvr_modify_dn(contact, dn);
1117 if (NoRemove) {
1118 /* We are trying to change RDN */
1119 gchar *newRdn = g_strdup_printf("%s=%s", NoRemove->attribute, NoRemove->value);
1121 #ifdef OPEN_LDAP_API_AT_LEAST_3000
1123 int rc = ldap_rename_s(ld, dn, newRdn, NULL, 1, NULL, NULL);
1125 #else
1127 /* This is deprecated as of OpenLDAP-2.3.0 */
1128 int rc = ldap_modrdn2_s(ld, dn, newRdn, 1);
1130 #endif
1132 if(rc != LDAP_SUCCESS) {
1133 if (rc == LDAP_ALREADY_EXISTS) {
1134 /* We are messing with a contact with more than one listed email
1135 * address and the email we are changing is not the one used for dn
1137 /* It needs to be able to handle renaming errors to an already defined
1138 * dn. For now we just refuse the update. It will be caught later on as
1139 * a LDAPRC_NAMING_VIOLATION error.
1142 else {
1143 g_printerr("Current dn: %s\n", dn);
1144 g_printerr("new dn: %s\n", newRdn);
1145 g_printerr("LDAP Error(ldap_modrdn2_s) failed[0x%x]: %s\n", rc, ldaputil_get_error(ld));
1146 g_free(newRdn);
1147 clean_up(ld, server, contact);
1148 return;
1151 else {
1152 ItemPerson *person = g_hash_table_lookup(contact, "person");
1153 g_free(newRdn);
1154 dn = g_strdup(NoRemove->new_dn);
1155 g_hash_table_replace(contact, "dn", dn);
1156 if (person) {
1157 g_free(person->externalID);
1158 person->externalID = dn;
1162 else {
1163 server->retVal = LDAPRC_NODN;
1164 clean_up(ld, server, contact);
1165 return;
1167 param = g_hash_table_lookup(contact , "cn");
1168 mod_op = ldapsvr_deside_operation(ld, server, dn, "displayName", param);
1169 if (mod_op >= 0 && (strcmp(param, NoRemove->value) != 0 && strcmp("cn", NoRemove->attribute) != 0)) {
1170 if (mod_op == LDAP_MOD_DELETE) {
1171 /* Setting param to NULL instructs OpenLDAP to remove any
1172 * value stored for this attribute and remove the attribute
1173 * completely. Should multiple instances of an attribute be
1174 * allowed in the future param is required to have the value
1175 * store for the attribute which is going to be deleted
1177 param = NULL;
1179 if (mod_op == LDAP_MOD_REPLACE && strcmp(param, "") == 0) {
1180 /* Having an empty string is considered a syntax error in
1181 * ldap. E.g attributes with empty strings are not allowed
1182 * in which case we treate this as a request for deleting
1183 * the attribute.
1185 mod_op = LDAP_MOD_DELETE;
1186 param = NULL;
1188 if (mod_op == LDAP_MOD_ADD && strcmp(param, "") == 0) {
1189 /* Adding an empty string is considered a syntax error in
1190 * ldap. E.g attributes with empty strings are not allowed
1191 * in which case we silently refuse to add this entry
1194 else {
1195 SETMOD(mods[cnt], modarr[cnt], mod_op, "displayName", cn, param);
1196 cnt++;
1197 g_hash_table_insert(contact, "displayName", param);
1200 param = g_hash_table_lookup(contact , "givenName");
1201 mod_op = ldapsvr_deside_operation(ld, server, dn, "givenName", param);
1202 if (mod_op >= 0 && (strcmp(param, NoRemove->value) != 0 && strcmp("givenName", NoRemove->attribute) != 0)) {
1203 if (mod_op == LDAP_MOD_DELETE) {
1204 /* Setting param to NULL instructs OpenLDAP to remove any
1205 * value stored for this attribute and remove the attribute
1206 * completely. Should multiple instances of an attribute be
1207 * allowed in the future param is required to have the value
1208 * store for the attribute which is going to be deleted
1210 param = NULL;
1212 if (mod_op == LDAP_MOD_REPLACE && strcmp(param, "") == 0) {
1213 /* Having an empty string is considered a syntax error in
1214 * ldap. E.g attributes with empty strings are not allowed
1215 * in which case we treate this as a request for deleting
1216 * the attribute.
1218 mod_op = LDAP_MOD_DELETE;
1219 param = NULL;
1221 if (mod_op == LDAP_MOD_ADD && strcmp(param, "") == 0) {
1222 /* Adding an empty string is considered a syntax error in
1223 * ldap. E.g attributes with empty strings are not allowed
1224 * in which case we silently refuse to add this entry
1227 else {
1228 SETMOD(mods[cnt], modarr[cnt], mod_op, "givenName", givenName, param);
1229 cnt++;
1232 mailList = g_hash_table_lookup(contact , "mail");
1233 if (mailList) {
1234 debug_print("# of mail: %d\n", g_list_length(mailList));
1235 if (!(strcmp("mail", NoRemove->attribute) == 0 && g_list_length(mailList) == 1)) {
1236 char **tmp;
1237 tmp = g_malloc(sizeof(*tmp) * (g_list_length(mailList)+1));
1238 mail = tmp;
1239 while (mailList) {
1240 EmailKeyValue *item = mailList->data;
1241 *tmp++ = g_strdup((gchar *) item->mail);
1242 mailList = g_list_next(mailList);
1244 *tmp = NULL;
1246 * At least one email address is required
1247 * in which case it will always be a replace
1249 SETMODS(mods[cnt], modarr[cnt], LDAP_MOD_REPLACE, "mail", mail);
1250 cnt++;
1253 else {
1255 * an error condition since at least one email adress
1256 * is required. Should never occur though.
1259 param = g_hash_table_lookup(contact , "sn");
1260 mod_op = ldapsvr_deside_operation(ld, server, dn, "sn", param);
1261 if (mod_op >= 0 && (strcmp(param, NoRemove->value) != 0 && strcmp("sn", NoRemove->attribute) != 0)) {
1262 if (mod_op == LDAP_MOD_DELETE) {
1263 /* Setting param to NULL instructs OpenLDAP to remove any
1264 * value stored for this attribute and remove the attribute
1265 * completely. Should multiple instances of an attribute be
1266 * allowed in the future param is required to have the value
1267 * store for the attribute which is going to be deleted
1269 param = NULL;
1271 if (mod_op == LDAP_MOD_REPLACE && strcmp(param, "") == 0) {
1272 /* Having an empty string is considered a syntax error in
1273 * ldap. E.g attributes with empty strings are not allowed
1274 * in which case we treate this as a request for deleting
1275 * the attribute.
1277 mod_op = LDAP_MOD_DELETE;
1278 param = NULL;
1280 if (mod_op == LDAP_MOD_ADD && strcmp(param, "") == 0) {
1281 /* Adding an empty string is considered a syntax error in
1282 * ldap. E.g attributes with empty strings are not allowed
1283 * in which case we silently refuse to add this entry
1286 else {
1287 SETMOD(mods[cnt], modarr[cnt], mod_op, "sn", sn, param);
1288 cnt++;
1291 debug_print("newDN: %s\n", dn);
1292 if (NoRemove)
1293 rdn_free(NoRemove);
1294 server->retVal = LDAPRC_SUCCESS;
1295 if (cnt > 0) {
1296 int rc;
1297 mods[cnt] = NULL;
1298 rc = ldap_modify_ext_s(ld, dn, mods, NULL, NULL);
1299 if (rc) {
1300 g_printerr("ldap_modify for dn=%s\" failed[0x%x]: %s\n",
1301 dn, rc, ldaputil_get_error(ld));
1302 server->retVal = LDAPRC_NAMING_VIOLATION;
1304 if (mail)
1305 g_free(mail);
1307 ldapsvr_handle_other_attributes(ld, server, dn, contact);
1308 /* If we do not make changes persistent at this point then changes
1309 * will be lost if the user makes new search on the same server since
1310 * changes are only present in Claws' internal cache. This issue has to
1311 * be solved in addressbook.c since this involves access to structures
1312 * which are only accessible in addressbook.c */
1313 clean_up(ld, server, contact);
1317 * Delete contact from LDAP
1319 * \param server AddressBook resource
1320 * \param contact GHashTable with object to delete
1322 void ldapsvr_delete_contact(LdapServer *server, GHashTable *contact) {
1323 LDAP *ld = NULL;
1324 gchar *dn;
1325 int rc;
1327 cm_return_if_fail(server != NULL || contact != NULL);
1328 ld = ldapsvr_connect(server->control);
1329 if (ld == NULL) {
1330 clean_up(ld, server, contact);
1331 return;
1333 dn = g_hash_table_lookup(contact, "dn");
1334 if (dn == NULL) {
1335 clean_up(ld, server, contact);
1336 return;
1338 server->retVal = LDAPRC_SUCCESS;
1339 rc = ldap_delete_ext_s(ld, dn, NULL, NULL);
1340 if (rc) {
1341 g_printerr("ldap_modify for dn=%s\" failed[0x%x]: %s\n",
1342 dn, rc, ldaputil_get_error(ld));
1343 server->retVal = LDAPRC_NODN;
1345 clean_up(ld, server, contact);
1349 * Update any changes to the server.
1351 * \param server AddressBook resource.
1352 * \param person ItemPerson holding user input.
1354 void ldapsvr_update_book(LdapServer *server, ItemPerson *item) {
1355 GList *node = NULL;
1356 GHashTable *contact = NULL;
1357 GList *contacts = NULL, *head = NULL;
1359 cm_return_if_fail(server != NULL);
1360 debug_print("updating ldap addressbook\n");
1362 contact = g_hash_table_new(g_str_hash, g_str_equal);
1363 if (item) {
1364 gboolean result = ldapsvr_retrieve_item_person(item, contact);
1365 debug_print("Found contact to update: %s\n", result? "Yes" : "No");
1366 if (result) {
1367 if (debug_get_mode()) {
1368 addritem_print_item_person(item, stdout);
1370 contacts = g_list_append(contacts, contact);
1373 else {
1374 ItemFolder *folder = server->addressCache->rootFolder;
1375 node = folder->listFolder;
1376 if (node) {
1377 while (node) {
1378 AddrItemObject *aio = node->data;
1379 if (aio) {
1380 if (aio->type == ITEMTYPE_FOLDER) {
1381 ItemFolder *folder = (ItemFolder *) aio;
1382 GList *persons = folder->listPerson;
1383 while (persons) {
1384 AddrItemObject *aio = persons->data;
1385 if (aio) {
1386 if (aio->type == ITEMTYPE_PERSON) {
1387 ItemPerson *item = (ItemPerson *) aio;
1388 gboolean result = ldapsvr_retrieve_item_person(item, contact);
1389 debug_print("Found contact to update: %s\n", result? "Yes" : "No");
1390 if (result) {
1391 if (debug_get_mode()) {
1392 gchar *uid = g_hash_table_lookup(contact, "uid");
1393 item = ldapsvr_get_contact(server, uid);
1394 addritem_print_item_person(item, stdout);
1396 contacts = g_list_append(contacts, contact);
1400 persons = g_list_next(persons);
1404 else {
1405 g_printerr("\t\tpid : ???\n");
1407 node = g_list_next(node);
1411 head = contacts;
1412 if (debug_get_mode()) {
1413 if (contacts)
1414 debug_print("Contacts which must be updated in LDAP:\n");
1415 while (contacts) {
1416 debug_print("\tContact:\n");
1417 g_hash_table_foreach(contacts->data,
1418 ldapsvr_print_contacts_hashtable, stderr);
1419 contacts = g_list_next(contacts);
1422 if (contacts == NULL)
1423 contacts = head;
1424 while (contacts) {
1425 gchar *status;
1426 contact = (GHashTable *) contacts->data;
1427 status = (gchar *) g_hash_table_lookup(contact, "status");
1428 if (status == NULL)
1429 status = g_strdup("NULL");
1430 if (g_ascii_strcasecmp(status, "new") == 0) {
1431 ldapsvr_add_contact(server, contact);
1433 else if (g_ascii_strcasecmp(status, "update") == 0) {
1434 ldapsvr_update_contact(server, contact);
1436 else if (g_ascii_strcasecmp(status, "delete") == 0) {
1437 ldapsvr_delete_contact(server, contact);
1439 else
1440 g_critical("ldapsvr_update_book->Unknown status: %s\n", status);
1441 contacts = g_list_next(contacts);
1443 ldapsvr_free_hashtable(head);
1446 #endif /* USE_LDAP */
1449 * End of Source.