1 /*
2 * libvc - vCard library
3 * Copyright (C) 2003 Andrew Hsu
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later
9 * version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
19 * MA 02111-1307 USA
20 *
21 * $Id: vc.c,v 1.5 2003/06/14 00:03:39 ahsu Rel $
22 */
23
24
25 #include "vc.h"
26 #include <stdlib.h>
27 #include <string.h>
28 #include <stdio.h>
29
30 #define BUF_LEN 80
31
32 /*** STRUCTS ***/
33
34 struct vc_component_tag
35 {
36 char *group;
37 char *name;
38 vc_component_param *param;
39 char *value;
40 vc_component *next;
41 };
42
43 struct vc_component_param_tag
44 {
45 char *name;
46 char *value;
47 vc_component_param *next;
48 };
49
50 /*** FUNCTION DEFINITIONS ***/
51
52 /***************************************************************************
53 Returns a new vc_component with everything set to NULL. The
54 user of the new vc_component will be responsible for freeing
55 it in the future with a call to vc_delete or vc_delete_deep.
56 */
57
58 vc_component *
vc_new()59 vc_new ()
60 {
61 vc_component *new_vc = NULL;
62
63 new_vc = (vc_component *) malloc (sizeof (vc_component));
64
65 if (NULL == new_vc)
66 {
67 fprintf (stderr, "unable to malloc a new vc_component\n");
68 exit (1);
69 }
70 else
71 {
72 new_vc->group = NULL;
73 new_vc->name = NULL;
74 new_vc->param = NULL;
75 new_vc->value = NULL;
76 new_vc->next = NULL;
77 }
78
79 return new_vc;
80 }
81
82 /***************************************************************************
83 Sets the group of a vc_component by making a copy of the
84 given group. Does nothing if the given vc_component is NULL.
85 Returns the given vc_component.
86 */
87
88 vc_component *
vc_set_group(vc_component * vc,const char * group)89 vc_set_group (vc_component * vc, const char *group)
90 {
91 if (NULL != vc)
92 {
93 free (vc->group);
94 vc->group = strdup (group);
95 }
96
97 return vc;
98 }
99
100 /***************************************************************************
101 Sets the name of a vc_component by making a copy of the given
102 name. Does nothing if the given vc_component is NULL.
103 Returns the given vc_component.
104 */
105
106 vc_component *
vc_set_name(vc_component * vc,char * name)107 vc_set_name (vc_component * vc, char *name)
108 {
109 if (NULL != vc)
110 {
111 free (vc->name);
112 vc->name = strdup (name);
113 }
114
115 return vc;
116 }
117
118 /***************************************************************************
119 Appends to the linked-list of parameters in the given
120 vc_component. Does nothing if the given vc_component is
121 NULL. Returns the given vc_component.
122 */
123
124 vc_component *
vc_add_param(vc_component * vc,vc_component_param * vc_param)125 vc_add_param (vc_component * vc, vc_component_param * vc_param)
126 {
127 if (NULL != vc)
128 {
129 vc_component_param *p = NULL;
130 p = vc->param;
131
132 if (NULL == p)
133 {
134 vc->param = vc_param;
135 }
136 else
137 {
138 while (NULL != p->next)
139 {
140 p = p->next;
141 }
142
143 p->next = vc_param;
144 }
145 }
146
147 return vc;
148 }
149
150 /***************************************************************************
151 Sets the value of a vc_component by making a copy of the
152 given value. Does nothing if the given vc_component is NULL.
153 Returns the given vc_component.
154 */
155
156 vc_component *
vc_set_value(vc_component * vc,const char * value)157 vc_set_value (vc_component * vc, const char *value)
158 {
159 if (NULL != vc)
160 {
161 free (vc->value);
162 vc->value = strdup (value);
163 }
164
165 return vc;
166 }
167
168 /***************************************************************************
169 Traverses to the end of the list of head and then appends tail
170 as the next node. If head is null, does nothing. Returns head.
171 */
172
173 vc_component *
vc_link(vc_component * head,vc_component * tail)174 vc_link (vc_component * head, vc_component * tail)
175 {
176 if (NULL != head)
177 {
178 vc_component *vc = NULL;
179 vc = head;
180
181 while (NULL != vc->next)
182 {
183 vc = vc->next;
184 }
185
186 vc->next = tail;
187 }
188
189 return head;
190 }
191
192 /***************************************************************************
193 This is a convenience function for appending a new vc_component
194 to the end of the list pointed to by the given vc_component.
195 Returns a pointer to the newly created vc_component if
196 successful, NULL otherwise.
197 */
198
199 vc_component *
vc_append_with_name(vc_component * vc,char * name)200 vc_append_with_name (vc_component * vc, char *name)
201 {
202 vc_component *new_vc = NULL;
203 if (NULL != vc)
204 {
205 new_vc = vc_new ();
206 vc_set_name (new_vc, name);
207 vc_link (vc, new_vc);
208 }
209
210 return new_vc;
211 }
212
213 /***************************************************************************
214 Checks the parameters of the given vc_component to see if
215 there exists a parameter name `TYPE' with a value of `pref'.
216 Returns a value of 1 if found, else 0.
217 */
218
219 int
vc_is_preferred(vc_component * vc)220 vc_is_preferred (vc_component * vc)
221 {
222 int ret_val = 0;
223
224 if (NULL != vc)
225 {
226 vc_component_param *vc_param = NULL;
227 char *value = NULL;
228 int done = 0;
229
230 for (vc_param = vc_param_get_by_name (vc->param, "TYPE");
231 (NULL != vc_param) && (!done);
232 vc_param = vc_param_get_next_by_name (vc_param, "TYPE"))
233 {
234 value = vc_param_get_value (vc_param);
235
236 if (NULL != value)
237 {
238 if (0 == strcasecmp (value, "pref"))
239 {
240 ret_val = 1;
241 done = 1;
242 }
243 }
244 }
245 }
246
247 return ret_val;
248 }
249
250 /***************************************************************************
251 Returns the pointer to the name of the preferred telephone
252 number of the given vc. This is done by checking for `TYPE'
253 parameters with a value of `pref'. If no such parameter is
254 found, then the first vc_component with the name `TEL' will be
255 returned. Returns NULL if none found. Users of this function
256 must not modify the contents to which the returned pointer
257 points to.
258
259 TODO: Fix the duplicate code with vc_get_preferred_email.
260 */
261
262 char *
vc_get_preferred_tel(vc_component * v)263 vc_get_preferred_tel (vc_component * v)
264 {
265 char *tel = NULL;
266 int done = 0;
267 vc_component *vc = NULL;
268
269 vc = vc_get_next_by_name (v, VC_TELEPHONE);
270 tel = vc_get_value (vc);
271
272 if (!vc_is_preferred (vc))
273 {
274 while ((NULL != vc) && (!done))
275 {
276 vc = vc_get_next_by_name (vc, VC_TELEPHONE);
277 if (vc_is_preferred (vc))
278 {
279 tel = vc_get_value (vc);
280 done = 1;
281 }
282 }
283 }
284
285 return tel;
286 }
287
288 /***************************************************************************
289 Returns the pointer to the name of the preferred email number
290 of the given vc. This is done by checking for `TYPE'
291 parameters with a value of `pref'. If no such parameter is
292 found, then the first vc_component with the name `EMAIL'
293 will be returned. Returns NULL if none found. Users of this
294 function must not modify the contents to which the returned
295 pointer points to.
296
297 FIXME: lots of duplicate code with vc_get_preferred_tel
298 */
299
300 char *
vc_get_preferred_email(vc_component * v)301 vc_get_preferred_email (vc_component * v)
302 {
303 char *email = NULL;
304 int done = 0;
305 vc_component *vc = NULL;
306
307 vc = vc_get_next_by_name (v, VC_EMAIL);
308 email = vc_get_value (vc);
309
310 if (!vc_is_preferred (vc))
311 {
312 while ((NULL != vc) && (!done))
313 {
314 vc = vc_get_next_by_name (vc, VC_EMAIL);
315 if (vc_is_preferred (vc))
316 {
317 email = vc_get_value (vc);
318 done = 1;
319 }
320 }
321 }
322
323 return email;
324 }
325
326 /***************************************************************************
327 Returns the pointer to the group of the given vc_component.
328 Users of this function must not modify the contents to which
329 the pointer points to (use vc_set_group function for modifying
330 the group). Returns NULL if no group found.
331 */
332
333 char *
vc_get_group(const vc_component * vc)334 vc_get_group (const vc_component * vc)
335 {
336 char *ret_val = NULL;
337 if (NULL != vc)
338 {
339 ret_val = vc->group;
340 }
341
342 return ret_val;
343 }
344
345 /***************************************************************************
346 Returns the pointer to the name of the given vc_component.
347 Users of this function must not modify the contents to which
348 the pointer points to (use vc_set_name function for modifying
349 the name). Returns NULL if no name found.
350 */
351
352 char *
vc_get_name(const vc_component * vc)353 vc_get_name (const vc_component * vc)
354 {
355 char *ret_val = NULL;
356 if (NULL != vc)
357 {
358 ret_val = vc->name;
359 }
360
361 return ret_val;
362 }
363
364 /***************************************************************************
365 Returns the pointer to the first parameter of the given
366 vc_component. Users of this function may use the modify
367 functions for vc_component_param to change the contents of
368 the returned parameter. Returns NULL if no parameter found.
369 */
370
371 vc_component_param *
vc_get_param(const vc_component * vc)372 vc_get_param (const vc_component * vc)
373 {
374 vc_component_param *ret_val = NULL;
375 if (NULL != vc)
376 {
377 ret_val = vc->param;
378 }
379
380 return ret_val;
381 }
382
383 /***************************************************************************
384 Returns the pointer to the value of the given vc_component.
385 Users of this function must not modify the contents to which
386 the pointer points to (use vc_set_value function for modifying
387 the value). Returns NULL if no value found.
388 */
389
390 char *
vc_get_value(const vc_component * vc)391 vc_get_value (const vc_component * vc)
392 {
393 char *ret_val = NULL;
394 if (NULL != vc)
395 {
396 ret_val = vc->value;
397 }
398
399 return ret_val;
400 }
401
402 /***************************************************************************
403 Returns a new vc_component_param with everything set to NULL.
404 The user of the new vc_component_param will be responsible
405 for freeing it in the future with a call to vc_param_delete or
406 vc_param_delete_deep.
407 */
408
409 vc_component_param *
vc_param_new()410 vc_param_new ()
411 {
412 vc_component_param *new_vc_param = NULL;
413
414 new_vc_param = (vc_component_param *) malloc (sizeof (vc_component_param));
415
416 if (NULL == new_vc_param)
417 {
418 fprintf (stderr, "unable to malloc a new vc_component_param\n");
419 exit (1);
420 }
421 else
422 {
423 new_vc_param->name = NULL;
424 new_vc_param->value = NULL;
425 new_vc_param->next = NULL;
426 }
427
428 return new_vc_param;
429 }
430
431 /***************************************************************************
432 Sets the name of a vc_component_param by making a copy of
433 the given name. Does nothing if the given vc_component_param
434 is NULL. Returns the given vc_component_param.
435 */
436
437 vc_component_param *
vc_param_set_name(vc_component_param * vc_param,const char * name)438 vc_param_set_name (vc_component_param * vc_param, const char *name)
439 {
440 if (NULL != vc_param)
441 {
442 free (vc_param->name);
443 vc_param->name = strdup (name);
444 }
445
446 return vc_param;
447 }
448
449 /***************************************************************************
450 Sets the value of a vc_component_param by making a copy of
451 the given value. Does nothing if the given vc_component_param
452 is NULL. Returns the given vc_component_param.
453 */
454
455 vc_component_param *
vc_param_set_value(vc_component_param * vc_param,const char * value)456 vc_param_set_value (vc_component_param * vc_param, const char *value)
457 {
458 if (NULL != vc_param)
459 {
460 free (vc_param->value);
461 vc_param->value = strdup (value);
462 }
463
464 return vc_param;
465 }
466
467 /***************************************************************************
468 Traverses to the end of the list of head and then appends tail
469 as the next node. If head is null, does nothing. Returns head.
470 */
471
472 vc_component_param *
vc_param_link(vc_component_param * head,vc_component_param * tail)473 vc_param_link (vc_component_param * head, vc_component_param * tail)
474 {
475 if (NULL != head)
476 {
477 vc_component_param *vc_param = NULL;
478 vc_param = head;
479
480 while (NULL != vc_param->next)
481 {
482 vc_param = vc_param->next;
483 }
484
485 vc_param->next = tail;
486 }
487
488 return head;
489 }
490
491 /***************************************************************************
492 Returns the pointer to the name of the given vc_component_param.
493 Users of this function must not modify the contents to which
494 the pointer points to (use vc_param_set_name function for
495 modifying the name). Returns NULL if no name found.
496 */
497
498 char *
vc_param_get_name(const vc_component_param * vc_param)499 vc_param_get_name (const vc_component_param * vc_param)
500 {
501 char *ret_val = NULL;
502 if (NULL != vc_param)
503 {
504 ret_val = vc_param->name;
505 }
506
507 return ret_val;
508 }
509
510 /***************************************************************************
511 Returns the pointer to the value of the given vc_component_param.
512 Users of this function must not modify the contents to which
513 the pointer points to (use vc_param_set_value function for
514 modifying the value). Returns NULL if no name found.
515 */
516
517 char *
vc_param_get_value(const vc_component_param * vc_param)518 vc_param_get_value (const vc_component_param * vc_param)
519 {
520 char *ret_val = NULL;
521 if (NULL != vc_param)
522 {
523 ret_val = vc_param->value;
524 }
525
526 return ret_val;
527 }
528
529 /***************************************************************************
530 Returns the next vc_component linked to the given one.
531 Returns NULL if none left.
532 */
533
534 vc_component *
vc_get_next(const vc_component * vc)535 vc_get_next (const vc_component * vc)
536 {
537 vc_component *ret_val = NULL;
538
539 if (NULL != vc)
540 {
541 ret_val = vc->next;
542 }
543
544 return ret_val;
545 }
546
547 /***************************************************************************
548 Searches for a vc_component that matches the given name,
549 starting with the one after the given vc_component. Returns
550 NULL if none is found.
551 */
552
553 vc_component *
vc_get_next_by_name(vc_component * vc,const char * name)554 vc_get_next_by_name (vc_component * vc, const char *name)
555 {
556 vc_component *result_vc = NULL;
557 vc_component *tmp_vc = NULL;
558 int done = 0;
559
560 if ((NULL != name) && (NULL != vc))
561 {
562 tmp_vc = vc->next;
563 while ((0 == done) && (NULL != tmp_vc))
564 {
565 if (NULL != tmp_vc->name)
566 {
567 if (0 == strcasecmp (name, tmp_vc->name))
568 {
569 result_vc = tmp_vc;
570 done = 1;
571 }
572 }
573 tmp_vc = tmp_vc->next;
574 }
575 }
576
577 return result_vc;
578 }
579
580 /***************************************************************************
581 Returns the next vc_component_param linked to the given one.
582 Returns NULL if none left.
583 */
584
585 vc_component_param *
vc_param_get_next(const vc_component_param * vc_param)586 vc_param_get_next (const vc_component_param * vc_param)
587 {
588 vc_component_param *ret_val = NULL;
589
590 if (NULL != vc_param)
591 {
592 ret_val = vc_param->next;
593 }
594
595 return ret_val;
596 }
597
598 /***************************************************************************
599 Searches for a vc_component_param that matches the given
600 name, starting with the given vc_component_param. Returns
601 NULL if none is found.
602
603 FIXME: lots of code duplicated from vc_param_get_next_by_name
604 */
605
606 vc_component_param *
vc_param_get_by_name(vc_component_param * vc_param,const char * name)607 vc_param_get_by_name (vc_component_param * vc_param, const char *name)
608 {
609 vc_component_param *result_vc_param = NULL;
610 vc_component_param *tmp_vc_param = NULL;
611 int done = 0;
612
613 if ((NULL != name) && (NULL != vc_param))
614 {
615 tmp_vc_param = vc_param;
616 while ((0 == done) && (NULL != tmp_vc_param))
617 {
618 if (NULL != tmp_vc_param->name)
619 {
620 if (0 == strcasecmp (name, tmp_vc_param->name))
621 {
622 result_vc_param = tmp_vc_param;
623 done = 1;
624 }
625 }
626 tmp_vc_param = tmp_vc_param->next;
627 }
628 }
629
630 return result_vc_param;
631 }
632
633 /***************************************************************************
634 Searches for a vc_component_param that matches the given
635 name, starting with the one after the given vc_component_param.
636 Returns NULL if none is found.
637
638 FIXME: lots of code duplicated from vc_param_get_by_name
639 */
640
641 vc_component_param *
vc_param_get_next_by_name(vc_component_param * vc_param,const char * name)642 vc_param_get_next_by_name (vc_component_param * vc_param, const char *name)
643 {
644 vc_component_param *result_vc_param = NULL;
645 vc_component_param *tmp_vc_param = NULL;
646 int done = 0;
647
648 if ((NULL != name) && (NULL != vc_param))
649 {
650 tmp_vc_param = vc_param->next;
651 while ((0 == done) && (NULL != tmp_vc_param))
652 {
653 if (NULL != tmp_vc_param->name)
654 {
655 if (0 == strcasecmp (name, tmp_vc_param->name))
656 {
657 result_vc_param = tmp_vc_param;
658 done = 1;
659 }
660 }
661 tmp_vc_param = tmp_vc_param->next;
662 }
663 }
664
665 return result_vc_param;
666 }
667
668 /***************************************************************************
669 Performs a "shallow" delete of the given vc_component. This
670 means that only the given vc_component will be freed. As a
671 side-effect, a "deep" delete of all the associated parameters
672 will be performed. A responsible user of this function would
673 also remember to set the given vc_component pointer variable
674 to NULL when this function returns.
675 */
676
677 void
vc_delete(vc_component * vc)678 vc_delete (vc_component * vc)
679 {
680 if (NULL != vc)
681 {
682 free (vc->group);
683 free (vc->name);
684 vc_param_delete_deep (vc->param);
685 free (vc->value);
686 free (vc);
687 }
688 }
689
690 /***************************************************************************
691 Performs a "deep" delete of the given vc_component. This
692 means that all the vc_components linked to the given one
693 will also be deleted. A responsible user of this function would
694 also remember to set the given vc_component pointer variable
695 to NULL when this function returns.
696 */
697
698 void
vc_delete_deep(vc_component * vc)699 vc_delete_deep (vc_component * vc)
700 {
701 vc_component *tmp_vc = NULL;
702 vc_component *vc_to_free = NULL;
703
704 tmp_vc = vc;
705 while (NULL != tmp_vc)
706 {
707 vc_to_free = tmp_vc;
708 tmp_vc = tmp_vc->next;
709
710 vc_delete (vc_to_free);
711 }
712 }
713
714 /***************************************************************************
715 Performs a "shallow" delete of the given vc_component_param.
716 This means that only the given vc_component_param will be
717 freed. A responsible user of this function would also remember
718 to set the given vc_component_param pointer variable to NULL
719 when this function returns.
720 */
721
722 void
vc_param_delete(vc_component_param * vc_param)723 vc_param_delete (vc_component_param * vc_param)
724 {
725 if (NULL != vc_param)
726 {
727 free (vc_param->name);
728 free (vc_param->value);
729 free (vc_param);
730 }
731 }
732
733 /***************************************************************************
734 Performs a "deep" delete of the given vc_component_param.
735 This means that all the vc_component_params linked to the
736 given one will also be deleted. A responsible user of this
737 function would also remember to set the given vc_component_param
738 pointer variable to NULL when this function returns.
739 */
740
741 void
vc_param_delete_deep(vc_component_param * vc_param)742 vc_param_delete_deep (vc_component_param * vc_param)
743 {
744 vc_component_param *tmp_vc_param = NULL;
745 vc_component_param *vc_param_to_free = NULL;
746
747 tmp_vc_param = vc_param;
748 while (NULL != tmp_vc_param)
749 {
750 vc_param_to_free = tmp_vc_param;
751 tmp_vc_param = tmp_vc_param->next;
752
753 vc_param_delete (vc_param_to_free);
754 }
755 }
756
757 /***************************************************************************
758 Prints the linked-list of vc_component_param to the given
759 FILE pointer.
760 */
761
762 void
fprintf_vc_component_param(FILE * fp,vc_component_param * vc_param)763 fprintf_vc_component_param (FILE * fp, vc_component_param * vc_param)
764 {
765 vc_component_param *tmp_vc_param = NULL;
766
767 tmp_vc_param = vc_param;
768
769 for (tmp_vc_param = vc_param; NULL != tmp_vc_param;
770 tmp_vc_param = vc_param_get_next (tmp_vc_param))
771 {
772 fprintf (fp, ";%s=%s", tmp_vc_param->name, tmp_vc_param->value);
773 }
774 }
775
776 /***************************************************************************
777 Prints a single vc_component to the given FILE pointer.
778 */
779
780 void
fprintf_vc_component(FILE * fp,vc_component * vc)781 fprintf_vc_component (FILE * fp, vc_component * vc)
782 {
783 if (NULL != vc)
784 {
785 if (NULL != vc->group)
786 {
787 fprintf (fp, "%s.", vc->group);
788 }
789
790 /* the name is expected to exist */
791 fprintf (fp, "%s", vc->name);
792
793 fprintf_vc_component_param (fp, vc->param);
794 fprintf (fp, ":");
795
796 if (NULL != vc->value)
797 {
798 fprintf (fp, "%s", vc->value);
799 }
800
801 fprintf (fp, "\n");
802 }
803 }
804
805 /***************************************************************************
806 Prints the entire vCard to the given FILE pointer.
807 */
808
809 void
fprintf_vcard(FILE * fp,vc_component * vcard)810 fprintf_vcard (FILE * fp, vc_component * vcard)
811 {
812 vc_component *vc = NULL;
813
814 vc = vcard;
815 if (NULL != vc)
816 {
817 fprintf (fp, "BEGIN:VCARD\n");
818
819 for (vc = vc->next; NULL != vc; vc = vc->next)
820 {
821 fprintf_vc_component (fp, vc);
822 }
823
824 fprintf (fp, "END:VCARD\n");
825 }
826 }
827
828 /***************************************************************************
829 Returns the number of vCards found in the given FILE pointer.
830 */
831
832 int
count_vcards(FILE * fp)833 count_vcards (FILE * fp)
834 {
835 char buf[256];
836 int counter = 0;
837
838 while (EOF != fscanf (fp, "%s\n", buf))
839 {
840 if (0 == strcasecmp (buf, "BEGIN:VCARD"))
841 counter++;
842 }
843
844 return counter;
845 }
846
847 /***************************************************************************
848 Returns a new string of the contents of the section of the given
849 string denoted by the part_index.
850 */
851
852 char *
get_val_struct_part(const char * str,int part_index)853 get_val_struct_part (const char *str, int part_index)
854 {
855 char buf[BUF_LEN];
856 int i = 0;
857 int j = 0;
858 int part_counter = 0;
859 int done = 0;
860 char *result = NULL;
861
862 if (NULL != str)
863 {
864 buf[0] = '\0';
865
866 while ('\0' != str[i] && 1 != done)
867 {
868 if (part_index == part_counter)
869 {
870 while (str[i] != ';' && i < BUF_LEN - 1)
871 {
872 buf[j] = str[i];
873 j++;
874 i++;
875 }
876
877 buf[j] = '\0';
878 done = 1;
879 }
880 else
881 {
882 if (';' == str[i])
883 {
884 part_counter++;
885 }
886 i++;
887 }
888 }
889
890 if ('\0' != buf[0])
891 {
892 result = strdup (buf);
893 }
894 }
895
896 return result;
897 }
898