2 Copyright (c) 2008 Instituto Nokia de Tecnologia
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
8 * Redistributions of source code must retain the above copyright notice,
9 this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright notice,
11 this list of conditions and the following disclaimer in the documentation
12 and/or other materials provided with the distribution.
13 * Neither the name of the INdT nor the names of its contributors
14 may be used to endorse or promote products derived from this software
15 without specific prior written permission.
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 POSSIBILITY OF SUCH DAMAGE.
31 * @author Adenilson Cavalcanti da Silva <adenilson.silva@indt.org.br>
32 * @date Thu Jun 26 07:37:03 2008
34 * @brief libgcal google contacts user public API.
36 * Use this functions to handle common tasks when dealing with google contacts.
48 #include "gcal_parser.h"
49 #include "internal_gcal.h"
52 /** Strings associated with phone number types */
53 const char* gcal_phone_type_str
[] = {
54 "assistant", // P_ASSISTANT
55 "callback", // P_CALLBACK
57 "company_main", // P_COMPANY_MAIN
60 "home_fax", // P_HOME_FAX
65 "other_fax", // P_OTHER_FAX
69 "tty_tdd", // P_TTY_TDD
71 "work_fax", // P_WORK_FAX
72 "work_mobile", // P_WORK_MOBILE
73 "work_pager" // P_WORK_PAGER
76 /** Strings associated with email types */
77 const char* gcal_email_type_str
[] = {
83 /** Strings associated with address types */
84 const char* gcal_address_type_str
[] = {
90 gcal_contact_t
gcal_contact_new(char *raw_xml
)
92 gcal_contact_t contact
= NULL
;
96 contact
= (gcal_contact_t
) malloc(sizeof(struct gcal_contact
));
100 gcal_init_contact(contact
);
104 /* Builds a doc, parse and init object */
105 doc
= build_dom_document(raw_xml
);
109 result
= extract_all_contacts(doc
, contact
, 1);
110 clean_dom_document(doc
);
121 void gcal_contact_delete(gcal_contact_t contact
)
126 gcal_destroy_contact(contact
);
131 int gcal_get_contacts(gcal_t gcalobj
, struct gcal_contact_array
*contact_array
)
135 contact_array
->length
= 0;
137 if ((!gcalobj
) || (!contact_array
))
140 result
= gcal_dump(gcalobj
, "GData-Version: 3.0");
142 contact_array
->entries
= NULL
;
143 contact_array
->length
= 0;
147 contact_array
->entries
= gcal_get_all_contacts(gcalobj
,
148 &contact_array
->length
);
149 if (!contact_array
->entries
)
158 void gcal_cleanup_contacts(struct gcal_contact_array
*contacts
)
163 gcal_destroy_contacts(contacts
->entries
, contacts
->length
);
164 contacts
->length
= 0;
165 contacts
->entries
= NULL
;
170 int gcal_add_contact(gcal_t gcalobj
, gcal_contact_t contact
)
173 struct gcal_contact updated
;
174 gcal_init_contact(&updated
);
176 if ((!gcalobj
) || (!contact
))
180 result
= gcal_create_contact(gcalobj
, contact
, &updated
);
184 /* Swap updated fields: id, updated, edit_uri, etag, photo url */
185 if (contact
->common
.id
)
186 free(contact
->common
.id
);
187 contact
->common
.id
= updated
.common
.id
;
188 updated
.common
.id
= NULL
;
190 if (contact
->common
.updated
)
191 free(contact
->common
.updated
);
192 contact
->common
.updated
= updated
.common
.updated
;
193 updated
.common
.updated
= NULL
;
195 if (contact
->common
.edit_uri
)
196 free(contact
->common
.edit_uri
);
197 contact
->common
.edit_uri
= updated
.common
.edit_uri
;
198 updated
.common
.edit_uri
= NULL
;
200 if (contact
->common
.etag
)
201 free(contact
->common
.etag
);
202 contact
->common
.etag
= updated
.common
.etag
;
203 updated
.common
.etag
= NULL
;
206 free(contact
->photo
);
207 contact
->photo
= updated
.photo
;
208 updated
.photo
= NULL
;
210 /* Cleanup updated contact */
211 gcal_destroy_contact(&updated
);
217 int gcal_update_contact(gcal_t gcalobj
, gcal_contact_t contact
)
220 struct gcal_contact updated
;
221 gcal_init_contact(&updated
);
223 if ((!gcalobj
) || (!contact
))
227 result
= gcal_edit_contact(gcalobj
, contact
, &updated
);
231 /* Swap updated fields: updated, edit_uri, etag */
232 if (contact
->common
.updated
)
233 free(contact
->common
.updated
);
234 contact
->common
.updated
= updated
.common
.updated
;
235 updated
.common
.updated
= NULL
;
237 if (contact
->common
.edit_uri
)
238 free(contact
->common
.edit_uri
);
239 contact
->common
.edit_uri
= updated
.common
.edit_uri
;
240 updated
.common
.edit_uri
= NULL
;
242 if (contact
->common
.etag
)
243 free(contact
->common
.etag
);
244 contact
->common
.etag
= updated
.common
.etag
;
245 updated
.common
.etag
= NULL
;
248 free(contact
->photo
);
249 contact
->photo
= updated
.photo
;
250 updated
.photo
= NULL
;
252 /* Cleanup updated contact */
253 gcal_destroy_contact(&updated
);
259 int gcal_erase_contact(gcal_t gcalobj
, gcal_contact_t contact
)
262 if ((!gcalobj
) || (!contact
))
265 result
= gcal_delete_contact(gcalobj
, contact
);
270 int gcal_get_updated_contacts(gcal_t gcal_obj
,
271 struct gcal_contact_array
*contacts
,
276 contacts
->length
= 0;
278 if ((!gcal_obj
) || (!contacts
))
281 result
= gcal_query_updated(gcal_obj
, timestamp
, "GData-Version: 3.0");
283 contacts
->entries
= NULL
;
284 contacts
->length
= 0;
288 contacts
->entries
= gcal_get_all_contacts(gcal_obj
, &contacts
->length
);
289 if (contacts
->entries
)
295 gcal_contact_t
gcal_contact_element(struct gcal_contact_array
*contacts
,
299 struct gcal_contact
*contact
= NULL
;
300 if ((!contacts
) || (_index
> (contacts
->length
- 1)) ||
301 (contacts
->length
== 0))
304 contact
= &contacts
->entries
[_index
];
308 char *gcal_contact_get_xml(gcal_contact_t contact
)
312 return gcal_get_xml(&(contact
->common
));
315 char *gcal_contact_get_id(gcal_contact_t contact
)
319 return gcal_get_id(&(contact
->common
));
322 char *gcal_contact_get_updated(gcal_contact_t contact
)
326 return gcal_get_updated(&(contact
->common
));
329 char *gcal_contact_get_title(gcal_contact_t contact
)
333 return gcal_get_title(&(contact
->common
));
336 char *gcal_contact_get_url(gcal_contact_t contact
)
340 return gcal_get_url(&(contact
->common
));
343 char *gcal_contact_get_etag(gcal_contact_t contact
)
347 return gcal_get_etag(&(contact
->common
));
350 char gcal_contact_is_deleted(gcal_contact_t contact
)
354 return gcal_get_deleted(&(contact
->common
));
358 /* This are the fields unique to contacts */
359 int gcal_contact_get_emails_count(gcal_contact_t contact
)
363 return contact
->emails_nr
;
366 int gcal_contact_get_pref_email(gcal_contact_t contact
)
370 return contact
->pref_email
;
373 char *gcal_contact_get_email_address(gcal_contact_t contact
, int i
)
377 if (!(contact
->emails_field
) || (i
>= contact
->emails_nr
))
379 return contact
->emails_field
[i
];
382 gcal_email_type
gcal_contact_get_email_address_type(gcal_contact_t contact
, int i
)
384 gcal_email_type result
= E_INVALID
;
389 if (!(contact
->emails_type
) || (i
>= contact
->emails_nr
))
391 for (j
= 0; j
< E_ITEMS_COUNT
; j
++)
392 if (!strcmp(contact
->emails_type
[i
], gcal_email_type_str
[j
]))
397 char *gcal_contact_get_content(gcal_contact_t contact
)
401 return contact
->content
;
404 char *gcal_contact_get_nickname(gcal_contact_t contact
)
408 return contact
->nickname
;
411 char *gcal_contact_get_organization(gcal_contact_t contact
)
415 return contact
->org_name
;
418 char *gcal_contact_get_profission(gcal_contact_t contact
)
422 return contact
->org_title
;
425 char *gcal_contact_get_im(gcal_contact_t contact
)
432 char *gcal_contact_get_homepage(gcal_contact_t contact
)
436 return contact
->homepage
;
439 char *gcal_contact_get_blog(gcal_contact_t contact
)
443 return contact
->blog
;
446 int gcal_contact_get_phone_numbers_count(gcal_contact_t contact
)
450 return contact
->phone_numbers_nr
;
453 char *gcal_contact_get_phone_number(gcal_contact_t contact
, int i
)
457 if (!(contact
->phone_numbers_field
) || (i
>= contact
->phone_numbers_nr
))
459 return contact
->phone_numbers_field
[i
];
462 gcal_phone_type
gcal_contact_get_phone_number_type(gcal_contact_t contact
, int i
)
464 gcal_phone_type result
= P_INVALID
;
469 if (!(contact
->phone_numbers_type
) || (i
>= contact
->phone_numbers_nr
))
471 for (j
= 0; j
< P_ITEMS_COUNT
; j
++)
472 if (!strcmp(contact
->phone_numbers_type
[i
], gcal_phone_type_str
[j
]))
477 gcal_structured_subvalues_t
gcal_contact_get_structured_name(gcal_contact_t contact
)
479 if ((!contact
) || (!contact
->structured_name
))
481 return contact
->structured_name
;
484 char *gcal_contact_get_address(gcal_contact_t contact
)
488 return contact
->post_address
;
491 gcal_structured_subvalues_t
gcal_contact_get_structured_address(gcal_contact_t contact
)
493 if ((!contact
) || (!contact
->structured_address
))
495 return contact
->structured_address
;
498 int gcal_contact_get_structured_address_count(gcal_contact_t contact
)
502 return contact
->structured_address_nr
;
505 int *gcal_contact_get_structured_address_count_obj(gcal_contact_t contact
)
509 return &contact
->structured_address_nr
;
512 char *gcal_contact_get_structured_entry(gcal_structured_subvalues_t structured_entry
, int structured_entry_nr
, int structured_entry_count
, const char *field_key
)
514 struct gcal_structured_subvalues
*temp_structured_entry
;
516 if(field_key
== NULL
)
519 if (!structured_entry
|| (structured_entry_nr
>= structured_entry_count
))
522 for (temp_structured_entry
= structured_entry
;
523 temp_structured_entry
!= NULL
;
524 temp_structured_entry
= temp_structured_entry
->next_field
) {
526 if (temp_structured_entry
->next_field
!= NULL
) {
527 if (!strcmp(temp_structured_entry
->field_key
, field_key
)
528 && (temp_structured_entry
->field_typenr
== structured_entry_nr
)) {
529 return temp_structured_entry
->field_value
;
537 char ***gcal_contact_get_structured_address_type_obj(gcal_contact_t contact
)
541 return &contact
->structured_address_type
;
544 gcal_address_type
gcal_contact_get_structured_address_type(gcal_contact_t contact
, int structured_entry_nr
, int structured_entry_count
)
546 gcal_address_type result
= A_INVALID
;
552 if (!(contact
->structured_address_type
) ||
553 (structured_entry_nr
>= structured_entry_count
))
556 for (j
= 0; j
< A_ITEMS_COUNT
; j
++)
557 if (!strcmp(contact
->structured_address_type
[structured_entry_nr
], gcal_address_type_str
[j
]))
563 int gcal_contact_get_groupMembership_count(gcal_contact_t contact
)
567 return contact
->groupMembership_nr
;
570 char *gcal_contact_get_groupMembership(gcal_contact_t contact
, int i
)
574 if (!(contact
->groupMembership
) || (i
>= contact
->groupMembership_nr
))
576 return contact
->groupMembership
[i
];
579 char *gcal_contact_get_photo(gcal_contact_t contact
)
584 return contact
->photo_data
;
587 unsigned int gcal_contact_get_photolength(gcal_contact_t contact
)
592 return contact
->photo_length
;
595 char *gcal_contact_get_birthday(gcal_contact_t contact
)
599 return contact
->birthday
;
602 /* Here starts the gcal_contact setters */
603 int gcal_contact_set_title(gcal_contact_t contact
, const char *field
)
607 if ((!contact
) || (!field
))
610 if (contact
->common
.title
)
611 free(contact
->common
.title
);
613 contact
->common
.title
= strdup(field
);
614 if (contact
->common
.title
)
620 int gcal_contact_delete_email_addresses(gcal_contact_t contact
)
628 if (contact
->emails_nr
> 0) {
629 for (temp
= 0; temp
< contact
->emails_nr
; temp
++) {
630 if (contact
->emails_field
[temp
])
631 free(contact
->emails_field
[temp
]);
632 if (contact
->emails_type
[temp
])
633 free(contact
->emails_type
[temp
]);
636 free(contact
->emails_field
);
637 free(contact
->emails_type
);
640 contact
->emails_nr
= contact
->pref_email
= 0;
641 contact
->emails_field
= contact
->emails_type
= 0;
648 int gcal_contact_add_email_address(gcal_contact_t contact
, const char *field
,
649 gcal_email_type type
, int pref
)
653 if ((!contact
) || (!field
) || (type
<0) || (type
>=E_ITEMS_COUNT
))
656 contact
->emails_field
= (char**) realloc(contact
->emails_field
,
657 (contact
->emails_nr
+1) *
660 contact
->emails_field
[contact
->emails_nr
] = strdup(field
);
662 contact
->emails_type
= (char**) realloc(contact
->emails_type
,
663 (contact
->emails_nr
+1) *
666 contact
->emails_type
[contact
->emails_nr
] = strdup(gcal_email_type_str
[type
]);
669 contact
->pref_email
= contact
->emails_nr
;
671 contact
->emails_nr
++;
678 int gcal_contact_set_url(gcal_contact_t contact
, const char *field
)
682 if ((!contact
) || (!field
))
685 if (contact
->common
.edit_uri
)
686 free(contact
->common
.edit_uri
);
688 contact
->common
.edit_uri
= strdup(field
);
689 if (contact
->common
.edit_uri
)
696 int gcal_contact_set_id(gcal_contact_t contact
, const char *field
)
700 if ((!contact
) || (!field
))
703 if (contact
->common
.id
)
704 free(contact
->common
.id
);
706 contact
->common
.id
= strdup(field
);
707 if (contact
->common
.id
)
714 int gcal_contact_set_etag(gcal_contact_t contact
, const char *field
)
718 if ((!contact
) || (!field
))
721 if (contact
->common
.etag
)
722 free(contact
->common
.etag
);
724 contact
->common
.etag
= strdup(field
);
725 if (contact
->common
.etag
)
731 int gcal_contact_delete_phone_numbers(gcal_contact_t contact
)
739 if (contact
->phone_numbers_nr
> 0) {
740 for (temp
= 0; temp
< contact
->phone_numbers_nr
; temp
++) {
741 if (contact
->phone_numbers_field
[temp
])
742 free(contact
->phone_numbers_field
[temp
]);
743 if (contact
->phone_numbers_type
[temp
])
744 free(contact
->phone_numbers_type
[temp
]);
747 free(contact
->phone_numbers_field
);
748 free(contact
->phone_numbers_type
);
751 contact
->phone_numbers_nr
= 0;
758 int gcal_contact_add_phone_number(gcal_contact_t contact
, const char *field
,
759 gcal_phone_type type
)
763 if ((!contact
) || (!field
) || (type
<0) || (type
>=P_ITEMS_COUNT
))
766 contact
->phone_numbers_field
= (char**) realloc(contact
->phone_numbers_field
, (contact
->phone_numbers_nr
+1) * sizeof(char*));
767 contact
->phone_numbers_field
[contact
->phone_numbers_nr
] = strdup(field
);
769 contact
->phone_numbers_type
= (char**) realloc(contact
->phone_numbers_type
, (contact
->phone_numbers_nr
+1) * sizeof(char*));
770 contact
->phone_numbers_type
[contact
->phone_numbers_nr
] = strdup(gcal_phone_type_str
[type
]);
772 contact
->phone_numbers_nr
++;
779 int gcal_contact_set_address(gcal_contact_t contact
, const char *field
)
783 if ((!contact
) || (!field
))
786 if (contact
->post_address
)
787 free(contact
->post_address
);
789 contact
->post_address
= strdup(field
);
790 if (contact
->post_address
)
796 int gcal_contact_set_structured_address_nr(gcal_contact_t contact
,
797 gcal_address_type type
)
799 int entry_nr
, result
= -1;
801 if (!contact
|| (type
< 0) || (type
>= A_ITEMS_COUNT
))
804 entry_nr
= contact
->structured_address_nr
;
805 contact
->structured_address_type
= (char**) realloc(contact
->structured_address_type
, (entry_nr
+ 1) * sizeof(char*));
806 contact
->structured_address_type
[entry_nr
] = strdup(gcal_address_type_str
[type
]);
807 contact
->structured_address_nr
++;
814 int gcal_contact_set_structured_entry(gcal_structured_subvalues_t structured_entry
,
815 int structured_entry_nr
,
816 int structured_entry_count
,
817 const char *field_key
,
818 const char *field_value
)
820 struct gcal_structured_subvalues
*temp_structured_entry
;
822 if (!structured_entry
|| (!field_value
) || (!field_key
) ||
823 (structured_entry_nr
< 0) ||
824 (structured_entry_nr
>= structured_entry_count
))
827 if (field_value
== NULL
)
830 if (structured_entry
->field_key
== NULL
) {
831 structured_entry
->field_typenr
= structured_entry_nr
;
832 structured_entry
->field_key
= strdup(field_key
);
833 structured_entry
->field_value
= strdup(field_value
);
834 structured_entry
->next_field
= NULL
;
838 //XXX: is this right?
839 for (temp_structured_entry
= structured_entry
; ;
840 temp_structured_entry
= temp_structured_entry
->next_field
) {
841 if (!strcmp(temp_structured_entry
->field_key
,field_key
) &&
842 (temp_structured_entry
->field_typenr
== structured_entry_nr
)) {
843 if (temp_structured_entry
->field_value
!= NULL
) {
844 free(temp_structured_entry
->field_value
);
845 temp_structured_entry
->field_value
= strdup(field_value
);
850 if (temp_structured_entry
->next_field
== NULL
) {
851 temp_structured_entry
->next_field
= (struct gcal_structured_subvalues
*)malloc(sizeof(struct gcal_structured_subvalues
));
852 temp_structured_entry
= temp_structured_entry
->next_field
;
854 temp_structured_entry
->field_typenr
= structured_entry_nr
;
855 temp_structured_entry
->field_key
= strdup(field_key
);
856 temp_structured_entry
->field_value
= strdup(field_value
);
857 temp_structured_entry
->next_field
= NULL
;
865 int gcal_contact_delete_structured_entry(gcal_structured_subvalues_t structured_entry
,
866 int *structured_entry_count
,
867 char ***structured_entry_type
)
870 struct gcal_structured_subvalues
*temp_structured_entry
;
872 if (!structured_entry
)
875 for (temp_structured_entry
= structured_entry
;
876 temp_structured_entry
!= NULL
;
877 temp_structured_entry
= temp_structured_entry
->next_field
) {
879 if (temp_structured_entry
->field_typenr
)
880 temp_structured_entry
->field_typenr
= 0;
881 if (temp_structured_entry
->field_key
)
882 free(temp_structured_entry
->field_key
);
883 if (temp_structured_entry
->field_value
)
884 free(temp_structured_entry
->field_value
);
887 if (structured_entry_count
&& structured_entry_type
) {
888 if ((*structured_entry_count
) > 0) {
889 for (i
= 0; i
< (*structured_entry_count
); i
++)
890 if ((*structured_entry_type
)[i
])
891 free((*structured_entry_type
)[i
]);
892 free((*structured_entry_type
));
895 (*structured_entry_count
) = 0;
902 int gcal_contact_delete_groupMembership(gcal_contact_t contact
)
910 if (contact
->groupMembership_nr
> 0) {
911 for (temp
= 0; temp
< contact
->groupMembership_nr
; temp
++) {
912 if (contact
->groupMembership
[temp
])
913 free(contact
->groupMembership
[temp
]);
916 free(contact
->groupMembership
);
919 contact
->groupMembership_nr
= 0;
924 int gcal_contact_add_groupMembership(gcal_contact_t contact
, char *field
)
928 if ((!contact
) || (!field
))
931 contact
->groupMembership
= (char**) realloc(contact
->groupMembership
, (contact
->groupMembership_nr
+1) * sizeof(char*));
932 contact
->groupMembership
[contact
->groupMembership_nr
] = strdup(field
);
934 contact
->groupMembership_nr
++;
941 int gcal_contact_set_profission(gcal_contact_t contact
, const char *field
)
945 if ((!contact
) || (!field
))
948 if (contact
->org_title
)
949 free(contact
->org_title
);
951 contact
->org_title
= strdup(field
);
952 if (contact
->org_title
)
959 int gcal_contact_set_organization(gcal_contact_t contact
, const char *field
)
963 if ((!contact
) || (!field
))
966 if (contact
->org_name
)
967 free(contact
->org_name
);
969 contact
->org_name
= strdup(field
);
970 if (contact
->org_name
)
976 int gcal_contact_set_content(gcal_contact_t contact
, const char *field
)
980 if ((!contact
) || (!field
))
983 if (contact
->content
)
984 free(contact
->content
);
986 contact
->content
= strdup(field
);
987 if (contact
->content
)
993 int gcal_contact_set_nickname(gcal_contact_t contact
, const char *field
)
997 if ((!contact
) || (!field
))
1000 if (contact
->nickname
)
1001 free(contact
->nickname
);
1003 contact
->nickname
= strdup(field
);
1004 if (contact
->nickname
)
1010 int gcal_contact_set_photo(gcal_contact_t contact
, const char *field
,
1015 if ((!contact
) || (!field
))
1018 if (contact
->photo_data
)
1019 if (contact
->photo_length
> 1)
1020 free(contact
->photo_data
);
1022 if (!(contact
->photo_data
= malloc(length
* sizeof(unsigned char))))
1025 memcpy(contact
->photo_data
, field
, length
);
1026 contact
->photo_length
= length
;
1032 int gcal_contact_set_birthday(gcal_contact_t contact
, const char *field
)
1036 if ((!contact
) || (!field
))
1039 if (contact
->birthday
)
1040 free(contact
->birthday
);
1042 contact
->birthday
= strdup(field
);
1043 if (contact
->birthday
)
1049 int gcal_contact_set_homepage(gcal_contact_t contact
, const char *field
)
1053 if ((!contact
) || (!field
))
1056 if (contact
->homepage
)
1057 free(contact
->homepage
);
1059 contact
->homepage
= strdup(field
);
1060 if (contact
->homepage
)
1066 int gcal_contact_set_blog(gcal_contact_t contact
, const char *field
)
1070 if ((!contact
) || (!field
))
1074 free(contact
->blog
);
1076 contact
->blog
= strdup(field
);