1 /*
2  * nmcontact.c
3  *
4  * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; version 2 of the License.
9  *
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.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA	02111-1301	USA
18  *
19  */
20 
21 #include <glib.h>
22 #include <string.h>
23 #include "nmcontact.h"
24 #include "nmfield.h"
25 #include "nmuser.h"
26 #include "util.h"
27 
28 struct _NMContact
29 {
30 	int id;
31 	int parent_id;
32 	int seq;
33 	char *dn;
34 	char *display_name;
35 	NMUserRecord *user_record;
36 	gpointer data;
37 	int ref_count;
38 };
39 
40 struct _NMFolder
41 {
42 	int id;
43 	int seq;
44 	char *name;
45 	GSList *folders;
46 	GSList *contacts;
47 	int ref_count;
48 };
49 
50 static int count = 0;
51 
52 static void _release_folder_contacts(NMFolder * folder);
53 static void _release_folder_folders(NMFolder * folder);
54 static void _add_contacts(NMUser * user, NMFolder * folder, NMField * fields);
55 static void _add_folders(NMFolder * root, NMField * fields);
56 
57 /*********************************************************************
58  * Contact API
59  *********************************************************************/
60 
61 NMContact *
nm_create_contact()62 nm_create_contact()
63 {
64 	NMContact *contact = g_new0(NMContact, 1);
65 
66 	contact->ref_count = 1;
67 
68 	purple_debug(PURPLE_DEBUG_INFO, "novell", "Creating contact, total=%d\n",
69 			   count++);
70 
71 	return contact;
72 }
73 
74 /*
75  * This creates a contact for the contact list. The
76  * field array that is passed in should be a
77  * NM_A_FA_CONTACT array.
78  *
79  */
80 NMContact *
nm_create_contact_from_fields(NMField * fields)81 nm_create_contact_from_fields(NMField * fields)
82 {
83 	NMContact *contact;
84 	NMField *field;
85 
86 	if ( fields == NULL || fields->tag == NULL || fields->ptr_value == 0 ||
87 		 !purple_strequal(fields->tag, NM_A_FA_CONTACT) )
88 	{
89 		return NULL;
90 	}
91 
92 	contact = nm_create_contact();
93 
94 	if ((field = nm_locate_field(NM_A_SZ_OBJECT_ID, (NMField *) fields->ptr_value))) {
95 
96 		if (field->ptr_value)
97 			contact->id = atoi((char *) field->ptr_value);
98 
99 	}
100 
101 	if ((field = nm_locate_field(NM_A_SZ_PARENT_ID, (NMField *) fields->ptr_value))) {
102 
103 		if (field->ptr_value)
104 			contact->parent_id = atoi((char *) field->ptr_value);
105 
106 	}
107 
108 	if ((field =
109 		 nm_locate_field(NM_A_SZ_SEQUENCE_NUMBER, (NMField *) fields->ptr_value))) {
110 
111 		if (field->ptr_value)
112 			contact->seq = atoi((char *) field->ptr_value);
113 
114 	}
115 
116 	if ((field =
117 		 nm_locate_field(NM_A_SZ_DISPLAY_NAME, (NMField *) fields->ptr_value))) {
118 
119 		if (field->ptr_value)
120 			contact->display_name = g_strdup((char *) field->ptr_value);
121 
122 	}
123 
124 	if ((field = nm_locate_field(NM_A_SZ_DN, (NMField *) fields->ptr_value))) {
125 
126 		if (field->ptr_value)
127 			contact->dn = g_strdup((char *) field->ptr_value);
128 
129 	}
130 
131 	return contact;
132 }
133 
134 void
nm_contact_update_list_properties(NMContact * contact,NMField * fields)135 nm_contact_update_list_properties(NMContact * contact, NMField * fields)
136 {
137 	NMField *field;
138 
139 	if (contact == NULL || fields == NULL || fields->ptr_value == 0)
140 		return;
141 
142 	if ((field = nm_locate_field(NM_A_SZ_OBJECT_ID, (NMField *) fields->ptr_value))) {
143 
144 		if (field->ptr_value)
145 			contact->id = atoi((char *)field->ptr_value);
146 
147 	}
148 
149 	if ((field = nm_locate_field(NM_A_SZ_PARENT_ID, (NMField *) fields->ptr_value))) {
150 
151 		if (field->ptr_value)
152 			contact->parent_id = atoi((char *) field->ptr_value);
153 
154 	}
155 
156 	if ((field =
157 		 nm_locate_field(NM_A_SZ_SEQUENCE_NUMBER, (NMField *) fields->ptr_value))) {
158 
159 		if (field->ptr_value)
160 			contact->seq = atoi((char *) field->ptr_value);
161 
162 	}
163 
164 	if ((field =
165 		 nm_locate_field(NM_A_SZ_DISPLAY_NAME, (NMField *) fields->ptr_value))) {
166 
167 		if (field->ptr_value) {
168 			if (contact->display_name)
169 				g_free(contact->display_name);
170 
171 			contact->display_name = g_strdup((char *) field->ptr_value);
172 		}
173 
174 	}
175 
176 	if ((field = nm_locate_field(NM_A_SZ_DN, (NMField *) fields->ptr_value))) {
177 
178 		if (field->ptr_value) {
179 			if (contact->dn)
180 				g_free(contact->dn);
181 
182 			contact->dn = g_strdup((char *) field->ptr_value);
183 		}
184 
185 	}
186 }
187 
188 NMField *
nm_contact_to_fields(NMContact * contact)189 nm_contact_to_fields(NMContact * contact)
190 {
191 	NMField *fields = NULL;
192 
193 	if (contact == NULL)
194 		return NULL;
195 
196 	fields = nm_field_add_pointer(fields, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
197 								  g_strdup_printf("%d", contact->id), NMFIELD_TYPE_UTF8);
198 
199 	fields = nm_field_add_pointer(fields, NM_A_SZ_PARENT_ID, 0, NMFIELD_METHOD_VALID, 0,
200 								  g_strdup_printf("%d", contact->parent_id), NMFIELD_TYPE_UTF8);
201 
202 	fields = nm_field_add_pointer(fields, NM_A_SZ_SEQUENCE_NUMBER, 0, NMFIELD_METHOD_VALID, 0,
203 								  g_strdup_printf("%d", contact->seq), NMFIELD_TYPE_UTF8);
204 
205 	if (contact->display_name != NULL) {
206 		fields = nm_field_add_pointer(fields, NM_A_SZ_DISPLAY_NAME, 0, NMFIELD_METHOD_VALID, 0,
207 									  g_strdup(contact->display_name), NMFIELD_TYPE_UTF8);
208 	}
209 
210 	if (contact->dn != NULL) {
211 		fields = nm_field_add_pointer(fields, NM_A_SZ_DN, 0, NMFIELD_METHOD_VALID, 0,
212 									  g_strdup(contact->dn), NMFIELD_TYPE_UTF8);
213 	}
214 
215 	return fields;
216 }
217 
218 void
nm_contact_add_ref(NMContact * contact)219 nm_contact_add_ref(NMContact * contact)
220 {
221 	if (contact)
222 		contact->ref_count++;
223 }
224 
225 void
nm_release_contact(NMContact * contact)226 nm_release_contact(NMContact * contact)
227 {
228 	if (contact == NULL)
229 		return;
230 
231 	if (--(contact->ref_count) == 0) {
232 
233 		purple_debug(PURPLE_DEBUG_INFO, "novell",
234 				   "Releasing contact, total=%d\n", --count);
235 
236 		if (contact->display_name) {
237 			g_free(contact->display_name);
238 		}
239 
240 		if (contact->dn) {
241 			g_free(contact->dn);
242 		}
243 
244 		if (contact->user_record) {
245 			nm_release_user_record(contact->user_record);
246 		}
247 
248 		g_free(contact);
249 	}
250 
251 }
252 
253 const char *
nm_contact_get_display_name(NMContact * contact)254 nm_contact_get_display_name(NMContact * contact)
255 {
256 	if (contact == NULL)
257 		return NULL;
258 
259 	if (contact->user_record != NULL && contact->display_name == NULL) {
260 		const char *full_name, *lname, *fname, *cn, *display_id;
261 
262 		full_name = nm_user_record_get_full_name(contact->user_record);
263 		fname = nm_user_record_get_first_name(contact->user_record);
264 		lname = nm_user_record_get_last_name(contact->user_record);
265 		cn = nm_user_record_get_userid(contact->user_record);
266 		display_id = nm_user_record_get_display_id(contact->user_record);
267 
268 		/* Try to build a display name. */
269 		if (full_name) {
270 
271 			contact->display_name = g_strdup(full_name);
272 
273 		} else if (fname && lname) {
274 
275 			contact->display_name = g_strdup_printf("%s %s", fname, lname);
276 
277 		} else {
278 
279 			/* If auth attribute is set use it */
280 			if (nm_user_record_get_auth_attr(contact->user_record) &&
281 				display_id != NULL)	{
282 
283 				contact->display_name = g_strdup(display_id);
284 
285 			} else {
286 
287 				/* Use CN or display id */
288 				if (cn) {
289 
290 					contact->display_name = g_strdup(cn);
291 
292 				} else if (display_id) {
293 
294 					contact->display_name = g_strdup(display_id);
295 
296 				}
297 
298 			}
299 
300 		}
301 	}
302 
303 	return contact->display_name;
304 }
305 
306 void
nm_contact_set_display_name(NMContact * contact,const char * display_name)307 nm_contact_set_display_name(NMContact * contact, const char *display_name)
308 {
309 	if (contact == NULL)
310 		return;
311 
312 	if (contact->display_name) {
313 		g_free(contact->display_name);
314 		contact->display_name = NULL;
315 	}
316 
317 	if (display_name)
318 		contact->display_name = g_strdup(display_name);
319 }
320 
321 void
nm_contact_set_dn(NMContact * contact,const char * dn)322 nm_contact_set_dn(NMContact * contact, const char *dn)
323 {
324 	if (contact == NULL)
325 		return;
326 
327 	if (contact->dn) {
328 		g_free(contact->dn);
329 		contact->dn = NULL;
330 	}
331 
332 	if (dn)
333 		contact->dn = g_strdup(dn);
334 }
335 
336 const char *
nm_contact_get_dn(NMContact * contact)337 nm_contact_get_dn(NMContact * contact)
338 {
339 	if (contact == NULL)
340 		return NULL;
341 
342 	return contact->dn;
343 }
344 
345 gpointer
nm_contact_get_data(NMContact * contact)346 nm_contact_get_data(NMContact * contact)
347 {
348 	if (contact == NULL)
349 		return NULL;
350 
351 	return contact->data;
352 }
353 
354 int
nm_contact_get_id(NMContact * contact)355 nm_contact_get_id(NMContact * contact)
356 {
357 	if (contact == NULL)
358 		return -1;
359 
360 	return contact->id;
361 }
362 
363 int
nm_contact_get_parent_id(NMContact * contact)364 nm_contact_get_parent_id(NMContact * contact)
365 {
366 	if (contact == NULL)
367 		return -1;
368 
369 	return contact->parent_id;
370 }
371 
372 void
nm_contact_set_data(NMContact * contact,gpointer data)373 nm_contact_set_data(NMContact * contact, gpointer data)
374 {
375 	if (contact == NULL)
376 		return;
377 
378 	contact->data = data;
379 }
380 
381 void
nm_contact_set_user_record(NMContact * contact,NMUserRecord * user_record)382 nm_contact_set_user_record(NMContact * contact, NMUserRecord * user_record)
383 {
384 	if (contact == NULL)
385 		return;
386 
387 	if (contact->user_record) {
388 		nm_release_user_record(contact->user_record);
389 	}
390 
391 	nm_user_record_add_ref(user_record);
392 	contact->user_record = user_record;
393 }
394 
395 NMUserRecord *
nm_contact_get_user_record(NMContact * contact)396 nm_contact_get_user_record(NMContact * contact)
397 {
398 	if (contact == NULL)
399 		return NULL;
400 
401 	return contact->user_record;
402 }
403 
404 const char *
nm_contact_get_userid(NMContact * contact)405 nm_contact_get_userid(NMContact * contact)
406 {
407 	NMUserRecord *user_record;
408 	const char *userid = NULL;
409 
410 	if (contact == NULL)
411 		return NULL;
412 
413 	user_record = nm_contact_get_user_record(contact);
414 	if (user_record) {
415 		userid = nm_user_record_get_userid(user_record);
416 	}
417 
418 	return userid;
419 }
420 
421 const char *
nm_contact_get_display_id(NMContact * contact)422 nm_contact_get_display_id(NMContact * contact)
423 {
424 	NMUserRecord *user_record;
425 	const char *id = NULL;
426 
427 	if (contact == NULL)
428 		return NULL;
429 
430 	user_record = nm_contact_get_user_record(contact);
431 	if (user_record) {
432 		id = nm_user_record_get_display_id(user_record);
433 	}
434 
435 	return id;
436 }
437 
438 
439 /*********************************************************************
440  * Folder API
441  *********************************************************************/
442 
443 NMFolder *
nm_create_folder(const char * name)444 nm_create_folder(const char *name)
445 {
446 	NMFolder *folder = g_new0(NMFolder, 1);
447 
448 	if (name)
449 		folder->name = g_strdup(name);
450 
451 	folder->ref_count = 1;
452 
453 	return folder;
454 }
455 
456 NMFolder *
nm_create_folder_from_fields(NMField * fields)457 nm_create_folder_from_fields(NMField * fields)
458 {
459 	NMField *field;
460 	NMFolder *folder;
461 
462 	if (fields == NULL || fields->ptr_value == 0)
463 		return NULL;
464 
465 	folder = g_new0(NMFolder, 1);
466 
467 	if ((field = nm_locate_field(NM_A_SZ_OBJECT_ID, (NMField *) fields->ptr_value))) {
468 
469 		if (field->ptr_value)
470 			folder->id = atoi((char *) field->ptr_value);
471 	}
472 
473 	if ((field =
474 		 nm_locate_field(NM_A_SZ_SEQUENCE_NUMBER, (NMField *) fields->ptr_value))) {
475 
476 		if (field->ptr_value)
477 			folder->seq = atoi((char *) field->ptr_value);
478 	}
479 
480 	if ((field =
481 		 nm_locate_field(NM_A_SZ_DISPLAY_NAME, (NMField *) fields->ptr_value))) {
482 
483 		if (field->ptr_value)
484 			folder->name = g_strdup((char *) field->ptr_value);
485 	}
486 
487 	folder->ref_count = 1;
488 	return folder;
489 }
490 
491 NMField *
nm_folder_to_fields(NMFolder * folder)492 nm_folder_to_fields(NMFolder * folder)
493 {
494 	NMField *fields = NULL;
495 
496 	if (folder == NULL)
497 		return NULL;
498 
499 	fields = nm_field_add_pointer(fields, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
500 								  g_strdup_printf("%d", folder->id), NMFIELD_TYPE_UTF8);
501 
502 	fields = nm_field_add_pointer(fields, NM_A_SZ_PARENT_ID, 0, NMFIELD_METHOD_VALID, 0,
503 								  g_strdup("0"), NMFIELD_TYPE_UTF8);
504 
505 	fields = nm_field_add_pointer(fields, NM_A_SZ_TYPE, 0, NMFIELD_METHOD_VALID, 0,
506 								  g_strdup("1"), NMFIELD_TYPE_UTF8);
507 
508 	fields = nm_field_add_pointer(fields, NM_A_SZ_SEQUENCE_NUMBER, 0, NMFIELD_METHOD_VALID, 0,
509 								  g_strdup_printf("%d", folder->seq), NMFIELD_TYPE_UTF8);
510 
511 	if (folder->name != NULL) {
512 		fields = nm_field_add_pointer(fields, NM_A_SZ_DISPLAY_NAME, 0, NMFIELD_METHOD_VALID, 0,
513 									  g_strdup(folder->name), NMFIELD_TYPE_UTF8);
514 	}
515 
516 
517 	return fields;
518 }
519 
520 void
nm_folder_update_list_properties(NMFolder * folder,NMField * fields)521 nm_folder_update_list_properties(NMFolder * folder, NMField * fields)
522 {
523 	NMField *field;
524 
525 	if (folder == NULL || fields == NULL || fields->ptr_value == 0)
526 		return;
527 
528 	if ((field = nm_locate_field(NM_A_SZ_OBJECT_ID, (NMField *) fields->ptr_value))) {
529 
530 		if (field->ptr_value)
531 			folder->id = atoi((char *) field->ptr_value);
532 
533 	}
534 
535 	if ((field =
536 		 nm_locate_field(NM_A_SZ_SEQUENCE_NUMBER, (NMField *) fields->ptr_value))) {
537 
538 		if (field->ptr_value)
539 			folder->seq = atoi((char *) field->ptr_value);
540 
541 	}
542 
543 	if ((field =
544 		 nm_locate_field(NM_A_SZ_DISPLAY_NAME, (NMField *) fields->ptr_value))) {
545 
546 		if (field->ptr_value) {
547 			if (folder->name)
548 				g_free(folder->name);
549 
550 			folder->name = g_strdup((char *) field->ptr_value);
551 		}
552 
553 	}
554 
555 }
556 
557 void
nm_release_folder(NMFolder * folder)558 nm_release_folder(NMFolder * folder)
559 {
560 	if (folder == NULL)
561 		return;
562 
563 	if (--(folder->ref_count) == 0) {
564 		if (folder->name) {
565 			g_free(folder->name);
566 		}
567 
568 		if (folder->folders) {
569 			_release_folder_folders(folder);
570 		}
571 
572 		if (folder->contacts) {
573 			_release_folder_contacts(folder);
574 		}
575 
576 		g_free(folder);
577 	}
578 }
579 
580 
581 void
nm_folder_add_ref(NMFolder * folder)582 nm_folder_add_ref(NMFolder * folder)
583 {
584 	if (folder)
585 		folder->ref_count++;
586 }
587 
588 int
nm_folder_get_subfolder_count(NMFolder * folder)589 nm_folder_get_subfolder_count(NMFolder * folder)
590 {
591 	if (folder == NULL)
592 		return 0;
593 
594 	if (folder->folders)
595 		return g_slist_length(folder->folders);
596 	else
597 		return 0;
598 }
599 
600 NMFolder *
nm_folder_get_subfolder(NMFolder * folder,int index)601 nm_folder_get_subfolder(NMFolder * folder, int index)
602 {
603 	if (folder == NULL)
604 		return NULL;
605 
606 	if (folder->folders)
607 		return (NMFolder *) g_slist_nth_data(folder->folders, index);
608 	else
609 		return NULL;
610 }
611 
612 int
nm_folder_get_contact_count(NMFolder * folder)613 nm_folder_get_contact_count(NMFolder * folder)
614 {
615 	if (folder == NULL)
616 		return 0;
617 
618 	if (folder->contacts != NULL)
619 		return g_slist_length(folder->contacts);
620 	else
621 		return 0;
622 }
623 
624 NMContact *
nm_folder_get_contact(NMFolder * folder,int index)625 nm_folder_get_contact(NMFolder * folder, int index)
626 {
627 	if (folder == NULL)
628 		return NULL;
629 
630 	if (folder->contacts)
631 		return (NMContact *) g_slist_nth_data(folder->contacts, index);
632 	else
633 		return NULL;
634 }
635 
636 const char *
nm_folder_get_name(NMFolder * folder)637 nm_folder_get_name(NMFolder * folder)
638 {
639 	if (folder == NULL)
640 		return NULL;
641 
642 	return folder->name;
643 }
644 
645 void
nm_folder_set_name(NMFolder * folder,const char * name)646 nm_folder_set_name(NMFolder * folder, const char *name)
647 {
648 	if (folder == NULL || name == NULL)
649 		return;
650 
651 	if (folder->name)
652 		g_free(folder->name);
653 
654 	folder->name = g_strdup(name);
655 }
656 
657 int
nm_folder_get_id(NMFolder * folder)658 nm_folder_get_id(NMFolder * folder)
659 {
660 	if (folder == NULL) {
661 		return  -1;
662 	}
663 
664 	return folder->id;
665 }
666 
667 void
nm_folder_add_folder_to_list(NMFolder * root,NMFolder * folder)668 nm_folder_add_folder_to_list(NMFolder * root, NMFolder * folder)
669 {
670 	GSList *node;
671 
672 	if (root == NULL || folder == NULL)
673 		return;
674 
675 	node = root->folders;
676 	while (node) {
677 		if (folder->seq <= ((NMFolder *) node->data)->seq) {
678 			nm_folder_add_ref(folder);
679 			root->folders = g_slist_insert_before(root->folders, node, folder);
680 			break;
681 		}
682 		node = g_slist_next(node);
683 	}
684 	if (node == NULL) {
685 		nm_folder_add_ref(folder);
686 		root->folders = g_slist_append(root->folders, folder);
687 	}
688 }
689 
690 void
nm_folder_remove_contact(NMFolder * folder,NMContact * contact)691 nm_folder_remove_contact(NMFolder * folder, NMContact * contact)
692 {
693 	GSList *node;
694 
695 	if (folder == NULL || contact == NULL)
696 		return;
697 
698 	node = folder->contacts;
699 	while (node) {
700 		if (contact->id == ((NMContact *) (node->data))->id) {
701 			folder->contacts = g_slist_remove(folder->contacts, node->data);
702 			nm_release_contact(contact);
703 			break;
704 		}
705 		node = g_slist_next(node);
706 	}
707 }
708 
709 void
nm_folder_add_contact_to_list(NMFolder * root_folder,NMContact * contact)710 nm_folder_add_contact_to_list(NMFolder * root_folder, NMContact * contact)
711 {
712 	GSList *node = NULL;
713 	NMFolder *folder = root_folder;
714 
715 	if (folder == NULL || contact == NULL)
716 		return;
717 
718 	/* Find folder to add contact to */
719 	if (contact->parent_id != 0) {
720 		node = folder->folders;
721 		while (node) {
722 			folder = (NMFolder *) node->data;
723 			if (contact->parent_id == folder->id) {
724 				break;
725 			}
726 			folder = NULL;
727 			node = g_slist_next(node);
728 		}
729 	}
730 
731 	/* Add contact to list */
732 	if (folder) {
733 		node = folder->contacts;
734 		while (node) {
735 			if (contact->seq <= ((NMContact *) (node->data))->seq) {
736 				nm_contact_add_ref(contact);
737 				folder->contacts =
738 					g_slist_insert_before(folder->contacts, node, contact);
739 				break;
740 			}
741 			node = g_slist_next(node);
742 		}
743 
744 		if (node == NULL) {
745 			nm_contact_add_ref(contact);
746 			folder->contacts = g_slist_append(folder->contacts, contact);
747 		}
748 	}
749 }
750 
751 void
nm_folder_add_contacts_and_folders(NMUser * user,NMFolder * root,NMField * fields)752 nm_folder_add_contacts_and_folders(NMUser * user, NMFolder * root,
753 								   NMField * fields)
754 {
755 	/* Add the contacts and folders from the field array */
756 	if (user && root && fields) {
757 		_add_folders(root, fields);
758 		_add_contacts(user, root, fields);
759 	}
760 }
761 
762 gpointer
nm_folder_find_item_by_object_id(NMFolder * root_folder,int object_id)763 nm_folder_find_item_by_object_id(NMFolder * root_folder, int object_id)
764 {
765 	int cnt, cnt2, i, j;
766 	gpointer item = NULL;
767 	NMFolder *folder;
768 	NMContact *contact;
769 
770 	if (root_folder == NULL)
771 		return NULL;
772 
773 	/* Check all contacts for the top level folder */
774 	cnt = nm_folder_get_contact_count(root_folder);
775 	for (i = 0; i < cnt; i++) {
776 		contact = nm_folder_get_contact(root_folder, i);
777 		if (contact && (contact->id == object_id)) {
778 			item = contact;
779 			break;
780 		}
781 	}
782 
783 	/* If we haven't found the item yet, check the subfolders */
784 	if (item == NULL) {
785 		cnt = nm_folder_get_subfolder_count(root_folder);
786 		for (i = 0; (i < cnt) && (item == NULL); i++) {
787 			folder = nm_folder_get_subfolder(root_folder, i);
788 
789 			/* Check the id of this folder */
790 			if (folder && (folder->id == object_id)) {
791 				item = folder;
792 				break;
793 			}
794 
795 			/* Check all contacts for this folder */
796 			cnt2 = nm_folder_get_contact_count(folder);
797 			for (j = 0; j < cnt2; j++) {
798 				contact = nm_folder_get_contact(folder, j);
799 				if (contact && (contact->id == object_id)) {
800 					item = contact;
801 					break;
802 				}
803 			}
804 		}
805 	}
806 
807 	return item;
808 }
809 
810 NMContact *
nm_folder_find_contact_by_userid(NMFolder * folder,const char * userid)811 nm_folder_find_contact_by_userid(NMFolder * folder, const char *userid)
812 {
813 	int cnt, i;
814 	NMContact *tmp, *contact = NULL;
815 
816 	if (folder == NULL || userid == NULL)
817 		return NULL;
818 
819 	cnt = nm_folder_get_contact_count(folder);
820 	for (i = 0; i < cnt; i++) {
821 		tmp = nm_folder_get_contact(folder, i);
822 		if (tmp && nm_utf8_str_equal(nm_contact_get_userid(tmp), userid)) {
823 			contact = tmp;
824 			break;
825 		}
826 	}
827 
828 	return contact;
829 }
830 
831 NMContact *
nm_folder_find_contact_by_display_id(NMFolder * folder,const char * display_id)832 nm_folder_find_contact_by_display_id(NMFolder * folder, const char *display_id)
833 {
834 	int cnt, i;
835 	NMContact *tmp, *contact = NULL;
836 
837 	if (folder == NULL || display_id == NULL)
838 		return NULL;
839 
840 	cnt = nm_folder_get_contact_count(folder);
841 	for (i = 0; i < cnt; i++) {
842 		tmp = nm_folder_get_contact(folder, i);
843 		if (tmp && nm_utf8_str_equal(nm_contact_get_display_id(tmp), display_id)) {
844 			contact = tmp;
845 			break;
846 		}
847 	}
848 
849 	return contact;
850 }
851 
852 NMContact *
nm_folder_find_contact(NMFolder * folder,const char * dn)853 nm_folder_find_contact(NMFolder * folder, const char *dn)
854 {
855 	int cnt, i;
856 	NMContact *tmp, *contact = NULL;
857 
858 	if (folder == NULL || dn == NULL)
859 		return NULL;
860 
861 	cnt = nm_folder_get_contact_count(folder);
862 	for (i = 0; i < cnt; i++) {
863 		tmp = nm_folder_get_contact(folder, i);
864 		if (tmp && nm_utf8_str_equal(nm_contact_get_dn(tmp), dn)) {
865 			contact = tmp;
866 			break;
867 		}
868 	}
869 
870 	return contact;
871 }
872 
873 
874 /*********************************************************************
875  * Utility functions
876  *********************************************************************/
877 
878 static void
_release_folder_contacts(NMFolder * folder)879 _release_folder_contacts(NMFolder * folder)
880 {
881 	GSList *cnode;
882 	NMContact *contact;
883 
884 	for (cnode = folder->contacts; cnode; cnode = cnode->next) {
885 		contact = cnode->data;
886 		cnode->data = NULL;
887 		nm_release_contact(contact);
888 	}
889 
890 	g_slist_free(folder->contacts);
891 	folder->contacts = NULL;
892 }
893 
894 static void
_release_folder_folders(NMFolder * folder)895 _release_folder_folders(NMFolder * folder)
896 {
897 	GSList *fnode;
898 	NMFolder *subfolder;
899 
900 	if (folder == NULL)
901 		return;
902 
903 	for (fnode = folder->folders; fnode; fnode = fnode->next) {
904 		subfolder = fnode->data;
905 		fnode->data = NULL;
906 		nm_release_folder(subfolder);
907 	}
908 
909 	g_slist_free(folder->folders);
910 	folder->folders = NULL;
911 }
912 
913 static void
_add_folders(NMFolder * root,NMField * fields)914 _add_folders(NMFolder * root, NMField * fields)
915 {
916 	NMFolder *folder = NULL;
917 	NMField *locate = NULL;
918 
919 	locate = nm_locate_field(NM_A_FA_FOLDER, fields);
920 	while (locate != NULL) {
921 
922 		/* Create a new folder */
923 		folder = nm_create_folder_from_fields(locate);
924 
925 		/* Add subfolder to roots folder list */
926 		nm_folder_add_folder_to_list(root, folder);
927 
928 		/* Decrement the ref count */
929 		nm_release_folder(folder);
930 
931 		/* Find the next folder */
932 		locate = nm_locate_field(NM_A_FA_FOLDER, locate+1);
933 
934 	}
935 }
936 
937 static void
_add_contacts(NMUser * user,NMFolder * folder,NMField * fields)938 _add_contacts(NMUser * user, NMFolder * folder, NMField * fields)
939 {
940 	NMContact *contact = NULL;
941 	NMField *locate = NULL,  *details;
942 	NMUserRecord *user_record = NULL;
943 
944 	locate = nm_locate_field(NM_A_FA_CONTACT, fields);
945 	while (locate != NULL) {
946 
947 		/* Create a new contact from the fields */
948 		contact = nm_create_contact_from_fields(locate);
949 
950 		/* Add it to our contact list */
951 		nm_folder_add_contact_to_list(folder, contact);
952 
953 		/* Update the contact cache */
954 		nm_user_add_contact(user, contact);
955 
956 		/* Update the user record cache */
957 		if ((details = nm_locate_field(NM_A_FA_USER_DETAILS,
958 									   (NMField *) locate->ptr_value))) {
959 			user_record = nm_find_user_record(user, nm_contact_get_dn(contact));
960 			if (user_record == NULL) {
961 				user_record = nm_create_user_record_from_fields(details);
962 				nm_user_record_set_dn(user_record, nm_contact_get_dn(contact));
963 				nm_user_add_user_record(user, user_record);
964 				nm_release_user_record(user_record);
965 			}
966 			nm_contact_set_user_record(contact, user_record);
967 		}
968 
969 		nm_release_contact(contact);
970 
971 		locate = nm_locate_field(NM_A_FA_CONTACT, locate+1);
972 	}
973 }
974