4 * Copyright (c) 2010 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
25 #include <unicode/ucnv.h>
26 #include <unicode/ustring.h>
27 #include <tzplatform_config.h>
30 #ifdef _CONTACTS_IPC_CLIENT
31 #include "ctsvc_client_ipc.h"
35 #include "ctsvc_internal.h"
36 #include "ctsvc_record.h"
37 #include "ctsvc_list.h"
38 #include "ctsvc_localize_utils.h"
39 #include "ctsvc_notify.h"
40 #include "ctsvc_image_util.h"
42 #define DEFAULT_ADDRESS_BOOK_ID 0
44 #define SMART_STRDUP(src) (src && *src) ? strdup(src) : NULL
45 #define CTSVC_VCARD_PHOTO_MAX_SIZE 1024*1024
47 #define CTSVC_VCARD_APPEND_STR(buf, buf_size, len, str) do { \
48 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, str, false)) < 0) { \
49 ERR("__ctsvc_vcard_append_str() Fail"); \
50 return CONTACTS_ERROR_OUT_OF_MEMORY; \
54 #define CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, content) do { \
55 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, content, true)) < 0) { \
56 ERR("__ctsvc_vcard_append_str() Fail"); \
57 return CONTACTS_ERROR_OUT_OF_MEMORY; \
62 #define CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, content) do { \
63 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";CHARSET=UTF-8"); \
64 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ":"); \
65 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, content); \
66 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, CTSVC_CRLF); \
77 CTSVC_VCARD_VALUE_NONE,
80 CTSVC_VCARD_VALUE_PHONETIC_FIRST_NAME,
81 CTSVC_VCARD_VALUE_PHONETIC_MIDDLE_NAME,
82 CTSVC_VCARD_VALUE_PHONETIC_LAST_NAME,
83 CTSVC_VCARD_VALUE_NICKNAME,
84 CTSVC_VCARD_VALUE_PHOTO,
85 CTSVC_VCARD_VALUE_BDAY,
86 CTSVC_VCARD_VALUE_X_ANNIVERSARY,
87 CTSVC_VCARD_VALUE_X_TIZEN_EVENT,
88 CTSVC_VCARD_VALUE_ADR,
89 CTSVC_VCARD_VALUE_TEL,
90 CTSVC_VCARD_VALUE_EMAIL,
91 CTSVC_VCARD_VALUE_TITLE,
92 CTSVC_VCARD_VALUE_ROLE,
93 CTSVC_VCARD_VALUE_LOGO,
94 CTSVC_VCARD_VALUE_ORG,
95 CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_LOCATION,
96 CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_DESCRIPTION,
97 CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_PHONETIC_NAME,
98 CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_ASSISTANT_NAME,
99 CTSVC_VCARD_VALUE_NOTE,
100 CTSVC_VCARD_VALUE_REV,
101 CTSVC_VCARD_VALUE_UID,
102 CTSVC_VCARD_VALUE_URL,
103 CTSVC_VCARD_VALUE_X_MSN,
104 CTSVC_VCARD_VALUE_X_YAHOO,
105 CTSVC_VCARD_VALUE_X_ICQ,
106 CTSVC_VCARD_VALUE_X_AIM,
107 CTSVC_VCARD_VALUE_X_JABBER,
108 CTSVC_VCARD_VALUE_X_SKYPE_USERNAME,
109 CTSVC_VCARD_VALUE_X_SKYPE,
110 CTSVC_VCARD_VALUE_X_QQ,
111 CTSVC_VCARD_VALUE_X_GOOGLE_TALK,
112 CTSVC_VCARD_VALUE_X_TIZEN_MESSENGER,
113 CTSVC_VCARD_VALUE_X_TIZEN_RELATIONSHIP,
114 CTSVC_VCARD_VALUE_END,
115 CTSVC_VCARD_VALUE_MAX
119 CTSVC_VCARD_IMG_NONE,
120 CTSVC_VCARD_IMG_PNG, /* Portable Network Graphics */
122 CTSVC_VCARD_IMG_JPEG, /* ISO JPEG format */
123 CTSVC_VCARD_IMG_GIF, /* Graphics Interchange Format */
124 CTSVC_VCARD_IMG_TIFF, /* Tagged Image File Format */
125 CTSVC_VCARD_IMG_CGM, /* ISO Computer Graphics Metafile */
126 CTSVC_VCARD_IMG_WMF, /* MS Windows Metafile */
127 CTSVC_VCARD_IMG_BMP, /* MS Windows Bitmap */
128 CTSVC_VCARD_IMG_MET, /* IBM PM Metafile */
129 CTSVC_VCARD_IMG_PMB, /* IBM PM Bitmap */
130 CTSVC_VCARD_IMG_DIB, /* MS Windows DIB */
131 CTSVC_VCARD_IMG_PICT, /* Apple Picture format */
132 CTSVC_VCARD_IMG_PDF, /* Adobe Page Description Format */
133 CTSVC_VCARD_IMG_PS, /* Adobe PostScript format */
134 CTSVC_VCARD_IMG_QTIME, /* Apple QuickTime format */
135 CTSVC_VCARD_IMG_MPEG, /* ISO MPEG format */
136 CTSVC_VCARD_IMG_MPEG2, /* ISO MPEG version 2 format */
137 CTSVC_VCARD_IMG_AVI, /* Intel AVI format */
140 static const char *content_name[CTSVC_VCARD_VALUE_MAX] = {0};
141 const char *CTSVC_CRLF = "\r\n";
143 static int limit_size_of_photo = CTSVC_IMAGE_MAX_SIZE;
145 static void __ctsvc_vcard_initial(void)
147 if (NULL == *content_name) {
148 /* content_name[CTSVC_VCARD_VALUE_NAME] = "NAME"; // not supported */
149 /* content_name[CTSVC_VCARD_VALUE_PROFILE] = "PROFILE"; // not supported */
150 /* content_name[CTSVC_VCARD_VALUE_SOURCE] = "SOURCE"; // not supported */
151 content_name[CTSVC_VCARD_VALUE_FN] = "FN";
152 content_name[CTSVC_VCARD_VALUE_N] = "N";
153 content_name[CTSVC_VCARD_VALUE_PHONETIC_FIRST_NAME] = "X-PHONETIC-FIRST-NAME";
154 content_name[CTSVC_VCARD_VALUE_PHONETIC_MIDDLE_NAME] = "X-PHONETIC-MIDDLE-NAME";
155 content_name[CTSVC_VCARD_VALUE_PHONETIC_LAST_NAME] = "X-PHONETIC-LAST-NAME";
156 content_name[CTSVC_VCARD_VALUE_NICKNAME] = "NICKNAME";
157 content_name[CTSVC_VCARD_VALUE_PHOTO] = "PHOTO";
158 content_name[CTSVC_VCARD_VALUE_BDAY] = "BDAY";
159 content_name[CTSVC_VCARD_VALUE_X_ANNIVERSARY] = "ANNIVERSARY";
160 content_name[CTSVC_VCARD_VALUE_X_TIZEN_EVENT] = "X-TIZEN-EVENT";
161 content_name[CTSVC_VCARD_VALUE_ADR] = "ADR";
162 /* content_name[CTSVC_VCARD_VALUE_LABEL] = "LABEL"; // not supported */
163 content_name[CTSVC_VCARD_VALUE_TEL] = "TEL";
164 content_name[CTSVC_VCARD_VALUE_EMAIL] = "EMAIL";
165 /* content_name[CTSVC_VCARD_VALUE_MAILER] = "MAILER"; // not supported */
166 /* content_name[CTSVC_VCARD_VALUE_TZ] = "TZ"; // not supported */
167 /* content_name[CTSVC_VCARD_VALUE_GEO] = "GEO"; // not supported */
168 content_name[CTSVC_VCARD_VALUE_TITLE] = "TITLE";
169 content_name[CTSVC_VCARD_VALUE_ROLE] = "ROLE";
170 content_name[CTSVC_VCARD_VALUE_LOGO] = "LOGO";
171 /* content_name[CTSVC_VCARD_VALUE_AGENT] = "AGENT"; // not supported */
172 content_name[CTSVC_VCARD_VALUE_ORG] = "ORG";
173 content_name[CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_LOCATION] = "X-TIZEN-COMPANY-LOCATION";
174 content_name[CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_DESCRIPTION] = "X-TIZEN-COMPANY-DESCRIPTION";
175 content_name[CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_PHONETIC_NAME] = "X-TIZEN-COMPANY-PHONETIC-NAME";
176 content_name[CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_ASSISTANT_NAME] = "X-TIZEN-COMPANY-ASSISTANT-NAME";
177 /* content_name[CTSVC_VCARD_VALUE_CATEGORIES] = "CATEGORIES"; // not supported */
178 content_name[CTSVC_VCARD_VALUE_NOTE] = "NOTE";
179 /* content_name[CTSVC_VCARD_VALUE_PRODID] = "PRODID"; // not supported */
180 content_name[CTSVC_VCARD_VALUE_REV] = "REV";
181 /* content_name[CTSVC_VCARD_VALUE_SORT-STRING] = "SORT-STRING"; // not supported */
182 content_name[CTSVC_VCARD_VALUE_UID] = "UID";
183 content_name[CTSVC_VCARD_VALUE_URL] = "URL";
184 /* content_name[CTSVC_VCARD_VALUE_VERSION] = "VERSION"; // not supported */
185 /* content_name[CTSVC_VCARD_VALUE_CLASS] = "CLASS"; // not supported */
186 /* content_name[CTSVC_VCARD_VALUE_KEY] = "KEY"; // not supported */
187 content_name[CTSVC_VCARD_VALUE_X_MSN] = "X-MSN";
188 content_name[CTSVC_VCARD_VALUE_X_YAHOO] = "X-YAHOO";
189 content_name[CTSVC_VCARD_VALUE_X_ICQ] = "X-ICQ";
190 content_name[CTSVC_VCARD_VALUE_X_AIM] = "X-AIM";
191 content_name[CTSVC_VCARD_VALUE_X_JABBER] = "X-JABBER";
192 content_name[CTSVC_VCARD_VALUE_X_SKYPE_USERNAME] = "X-SKYPE-USERNAME";
193 content_name[CTSVC_VCARD_VALUE_X_SKYPE] = "X-SKYPE";
194 content_name[CTSVC_VCARD_VALUE_X_QQ] = "X-QQ";
195 content_name[CTSVC_VCARD_VALUE_X_GOOGLE_TALK] = "X-GOOGLE-TALK";
196 content_name[CTSVC_VCARD_VALUE_X_TIZEN_MESSENGER] = "X-TIZEN-MESSENGER";
197 content_name[CTSVC_VCARD_VALUE_X_TIZEN_RELATIONSHIP] = "X-TIZEN-RELATIONSHIP";
198 /* content_name[CTSVC_VCARD_VALUE_X_CHILDREN] = "X-CHILDREN"; */
199 content_name[CTSVC_VCARD_VALUE_END] = "END";
203 static int __ctsvc_vcard_append_str(char **buf, int *buf_size, int len, const char *str, bool need_conversion)
207 const char *safe_str = SAFE_STR(str);
209 bool need_realloc = false;
211 str_len = strlen(safe_str);
212 while ((*buf_size-len) < (str_len+1)) {
213 *buf_size = *buf_size * 2;
218 if (NULL == (tmp = realloc(*buf, *buf_size)))
224 if (need_conversion) {
225 const char *s = safe_str;
226 char *r = (char *)(*buf+len);
231 if (*(s+1) && '\n' == *(s+1)) {
244 if (*buf_size < str_len+len+1) {
245 *buf_size = *buf_size * 2;
246 if (NULL == (tmp = realloc(*buf, *buf_size))) {
250 r = (char *)(*buf+len+str_len);
264 if (*buf_size < str_len+len+1) {
265 *buf_size = *buf_size * 2;
266 if (NULL == (tmp = realloc(*buf, *buf_size))) {
270 r = (char *)(*buf+len+str_len);
276 if (*(s+1) && 0xAC == *(s+1)) { /* en/em backslash */
280 if (*buf_size < str_len+len+1) {
281 *buf_size = *buf_size * 2;
282 if (NULL == (tmp = realloc(*buf, *buf_size))) {
286 r = (char *)(*buf+len+str_len);
293 if (*buf_size < str_len+len+1) {
294 *buf_size = *buf_size * 2;
295 if (NULL == (tmp = realloc(*buf, *buf_size))) {
299 r = (char *)(*buf+len+str_len);
308 if (*(s+1) && 0x5F == *(s+1)) { /* en/em backslash */
312 if (*buf_size < str_len+len+1) {
313 *buf_size = *buf_size * 2;
314 if (NULL == (tmp = realloc(*buf, *buf_size))) {
318 r = (char *)(*buf+len+str_len);
325 if (*buf_size < str_len+len+1) {
326 *buf_size = *buf_size * 2;
327 if (NULL == (tmp = realloc(*buf, *buf_size))) {
331 r = (char *)(*buf+len+str_len);
348 len_temp = snprintf(*buf+len, *buf_size-len+1, "%s", safe_str);
354 #define CTS_VCARD_FOLDING_LIMIT 75
356 static inline int __ctsvc_vcard_add_folding(char **buf, int *buf_size, int buf_len)
359 char *buf_copy = NULL;
360 int len, result_len = 0;
363 bool content_start = false;
364 bool encode_64 = false;
366 buf_copy = calloc(1, *buf_size);
367 if (NULL == buf_copy) {
368 ERR("calloc() Fail");
377 if (*buf_size < result_len + 5) {
379 *buf_size = *buf_size + 1000;
380 if (NULL == (tmp = realloc(buf_copy, *buf_size))) {
385 r = (buf_copy + result_len);
389 if (false == content_start) {
391 content_start = true;
392 else if (STRING_EQUAL == strncmp(s, "ENCODING=BASE64", strlen("ENCODING=BASE64")))
398 } else if ('\n' == *s) {
401 content_start = false;
406 if (false == encode_64)
407 char_len = ctsvc_check_utf8(*s);
409 if (CTS_VCARD_FOLDING_LIMIT <= len + char_len) {
436 static inline int __ctsvc_vcard_append_name(ctsvc_list_s *names, char **buf, int *buf_size, int len)
438 char display[1024] = {0};
439 GList *cursor = names->records;
442 RETV_IF(NULL == cursor, len);
446 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_N]);
448 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";CHARSET=UTF-8");
449 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ":");
450 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, name->last);
451 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
452 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, name->first);
453 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
454 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, name->addition);
455 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
456 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, name->prefix);
457 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
458 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, name->suffix);
460 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, CTSVC_CRLF);
462 if (name->first && name->last) {
463 contacts_name_display_order_e order = CONTACTS_NAME_DISPLAY_ORDER_FIRSTLAST;
464 #ifdef _CONTACTS_IPC_CLIENT
465 contacts_setting_get_name_display_order(&order);
467 if (CONTACTS_NAME_DISPLAY_ORDER_FIRSTLAST == order) {
468 snprintf(display, sizeof(display), "%s %s", name->first, name->last);
470 /* CONTACTS_NAME_DISPLAY_ORDER_LASTFIRST */
471 snprintf(display, sizeof(display), "%s, %s", name->last, name->first);
474 snprintf(display, sizeof(display), "%s%s", SAFE_STR(name->first), SAFE_STR(name->last));
477 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_FN]);
478 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, display);
480 if (name->phonetic_first) {
481 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_PHONETIC_FIRST_NAME]);
482 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, name->phonetic_first);
485 if (name->phonetic_middle) {
486 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_PHONETIC_MIDDLE_NAME]);
487 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, name->phonetic_middle);
491 if (name->phonetic_last) {
492 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_PHONETIC_LAST_NAME]);
493 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, name->phonetic_last);
499 static inline const char* __ctsvc_get_img_suffix(int type)
502 case CTSVC_VCARD_IMG_TIFF:
504 case CTSVC_VCARD_IMG_GIF:
506 case CTSVC_VCARD_IMG_PNG:
508 case CTSVC_VCARD_IMG_CGM:
510 case CTSVC_VCARD_IMG_WMF:
512 case CTSVC_VCARD_IMG_BMP:
514 case CTSVC_VCARD_IMG_MET:
516 case CTSVC_VCARD_IMG_PMB:
518 case CTSVC_VCARD_IMG_DIB:
520 case CTSVC_VCARD_IMG_PICT:
522 case CTSVC_VCARD_IMG_PDF:
524 case CTSVC_VCARD_IMG_PS:
526 case CTSVC_VCARD_IMG_QTIME:
528 case CTSVC_VCARD_IMG_MPEG:
530 case CTSVC_VCARD_IMG_MPEG2:
532 case CTSVC_VCARD_IMG_AVI:
534 case CTSVC_VCARD_IMG_JPEG:
537 ERR("Wrong Image type is: CTSVC_VCARD_IMG_NONE");
542 static inline int __ctsvc_vcard_get_image_type(char *val)
545 RETV_IF(NULL == val, CTSVC_VCARD_IMG_NONE);
549 *temp = tolower(*temp);
553 result = strstr(val, "jpeg");
554 if (result) return CTSVC_VCARD_IMG_JPEG;
556 result = strstr(val, "jpg");
557 if (result) return CTSVC_VCARD_IMG_JPEG;
559 result = strstr(val, "png");
560 if (result) return CTSVC_VCARD_IMG_PNG;
562 result = strstr(val, "gif");
563 if (result) return CTSVC_VCARD_IMG_GIF;
565 result = strstr(val, "tiff");
566 if (result) return CTSVC_VCARD_IMG_TIFF;
568 result = strstr(val, "cgm");
569 if (result) return CTSVC_VCARD_IMG_CGM;
571 result = strstr(val, "wmf");
572 if (result) return CTSVC_VCARD_IMG_WMF;
574 result = strstr(val, "bmp");
575 if (result) return CTSVC_VCARD_IMG_BMP;
577 result = strstr(val, "met");
578 if (result) return CTSVC_VCARD_IMG_MET;
580 result = strstr(val, "pmb");
581 if (result) return CTSVC_VCARD_IMG_PMB;
583 result = strstr(val, "dib");
584 if (result) return CTSVC_VCARD_IMG_DIB;
586 result = strstr(val, "pict");
587 if (result) return CTSVC_VCARD_IMG_PICT;
589 result = strstr(val, "pdf");
590 if (result) return CTSVC_VCARD_IMG_PDF;
592 result = strstr(val, "ps");
593 if (result) return CTSVC_VCARD_IMG_PS;
595 result = strstr(val, "qtime");
596 if (result) return CTSVC_VCARD_IMG_QTIME;
598 result = strstr(val, "mpeg");
599 if (result) return CTSVC_VCARD_IMG_MPEG;
601 result = strstr(val, "mpeg2");
602 if (result) return CTSVC_VCARD_IMG_MPEG2;
604 result = strstr(val, "avi");
605 if (result) return CTSVC_VCARD_IMG_AVI;
607 return CTSVC_VCARD_IMG_NONE;
610 static inline const char* __ctsvc_get_image_type_str(int type)
613 case CTSVC_VCARD_IMG_TIFF:
615 case CTSVC_VCARD_IMG_GIF:
617 case CTSVC_VCARD_IMG_PNG:
619 case CTSVC_VCARD_IMG_CGM:
621 case CTSVC_VCARD_IMG_WMF:
623 case CTSVC_VCARD_IMG_BMP:
625 case CTSVC_VCARD_IMG_MET:
627 case CTSVC_VCARD_IMG_PMB:
629 case CTSVC_VCARD_IMG_DIB:
631 case CTSVC_VCARD_IMG_PICT:
633 case CTSVC_VCARD_IMG_PDF:
635 case CTSVC_VCARD_IMG_PS:
637 case CTSVC_VCARD_IMG_QTIME:
639 case CTSVC_VCARD_IMG_MPEG:
641 case CTSVC_VCARD_IMG_MPEG2:
643 case CTSVC_VCARD_IMG_AVI:
645 case CTSVC_VCARD_IMG_JPEG:
651 static inline int __ctsvc_vcard_put_company_logo(const char *path, char **buf, int *buf_size, int len)
657 guchar image[CTSVC_VCARD_PHOTO_MAX_SIZE] = {0};
659 suffix = strrchr(path, '.');
660 type = __ctsvc_vcard_get_image_type(suffix);
662 fd = open(path, O_RDONLY);
663 RETVM_IF(fd < 0, CONTACTS_ERROR_SYSTEM, "System : Open Fail(%d)", errno);
666 while ((ret = read(fd, image+read_len, sizeof(image)-read_len))) {
676 RETVM_IF(ret < 0, CONTACTS_ERROR_SYSTEM, "System : read() Fail(%d)", errno);
678 buf_image = g_base64_encode(image, read_len);
681 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_LOGO], false)) < 0)
683 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, ";ENCODING=BASE64;TYPE=", false)) < 0)
685 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, __ctsvc_get_image_type_str(type), false)) < 0)
687 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, ":", false)) < 0)
689 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, buf_image, false)) < 0)
691 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, CTSVC_CRLF, false)) < 0)
693 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, CTSVC_CRLF, false)) < 0)
699 /* LCOV_EXCL_START */
700 ERR("__ctsvc_vcard_append_str() Fail");
701 return CONTACTS_ERROR_OUT_OF_MEMORY;
708 static bool __ctsvc_vcard_is_valid_custom_label(char *label)
711 RETV_IF(NULL == label || '\0' == *label, false);
715 RETV_IF(1 != ctsvc_check_utf8(c), false);
716 if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') ||
717 ('0' <= c && c <= '9') || c == '-') {
726 static inline int __ctsvc_vcard_put_company_type(int type, char *label, char **buf, int *buf_size, int len)
728 if (type == CONTACTS_COMPANY_TYPE_WORK) {
729 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=WORK");
730 } else if (type == CONTACTS_COMPANY_TYPE_CUSTOM) {
731 if (__ctsvc_vcard_is_valid_custom_label(label)) {
732 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-");
733 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, label);
739 static inline int __ctsvc_vcard_append_company(ctsvc_list_s *company_list, char **buf, int *buf_size, int len)
742 ctsvc_company_s *company;
744 for (cursor = company_list->records; cursor; cursor = cursor->next) {
746 company = cursor->data;
748 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_ORG]);
750 len = __ctsvc_vcard_put_company_type(company->type, SAFE_STR(company->label), buf, buf_size, len);
751 RETV_IF(len < 0, CONTACTS_ERROR_OUT_OF_MEMORY);
753 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";CHARSET=UTF-8");
754 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ":");
755 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, company->name);
756 if (company->department) {
757 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
758 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, company->department);
761 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, CTSVC_CRLF);
763 if (company->job_title) {
764 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_TITLE]);
765 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, company->job_title);
769 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_ROLE]);
770 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, company->role);
773 if (company->location) {
774 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_LOCATION]);
775 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, company->location);
778 if (company->description) {
779 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_DESCRIPTION]);
780 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, company->description);
783 if (company->phonetic_name) {
784 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_PHONETIC_NAME]);
785 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, company->phonetic_name);
788 if (company->assistant_name) {
789 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_ASSISTANT_NAME]);
790 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, company->assistant_name);
794 len = __ctsvc_vcard_put_company_logo(company->logo, buf, buf_size, len);
795 RETV_IF(len < 0, CONTACTS_ERROR_OUT_OF_MEMORY);
802 static inline int __ctsvc_vcard_append_note(ctsvc_list_s *note_list, char **buf, int *buf_size, int len)
807 for (cursor = note_list->records; cursor; cursor = cursor->next) {
810 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_NOTE]);
811 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, note->note);
818 static inline int __ctsvc_vcard_2_put_postal_type(int type, char *dest, int dest_size)
822 if (type & CONTACTS_ADDRESS_TYPE_DOM)
823 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "DOM");
824 if (type & CONTACTS_ADDRESS_TYPE_INTL)
825 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "INTL");
826 if (type & CONTACTS_ADDRESS_TYPE_HOME)
827 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "HOME");
828 if (type & CONTACTS_ADDRESS_TYPE_WORK)
829 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "WORK");
830 if (type & CONTACTS_ADDRESS_TYPE_POSTAL)
831 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "POSTAL");
832 if (type & CONTACTS_ADDRESS_TYPE_PARCEL)
833 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "PARCEL");
838 static inline int __ctsvc_vcard_put_postal_type(int type, char *label, char **buf, int *buf_size, int len)
840 char *type_str = NULL;
841 if (type == CONTACTS_ADDRESS_TYPE_DOM)
843 else if (type == CONTACTS_ADDRESS_TYPE_INTL)
845 else if (type == CONTACTS_ADDRESS_TYPE_HOME)
847 else if (type == CONTACTS_ADDRESS_TYPE_WORK)
849 else if (type == CONTACTS_ADDRESS_TYPE_POSTAL)
851 else if (type == CONTACTS_ADDRESS_TYPE_PARCEL)
854 if (type == CONTACTS_ADDRESS_TYPE_CUSTOM) {
855 if (__ctsvc_vcard_is_valid_custom_label(label)) {
856 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-");
857 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, label);
863 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=");
864 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, type_str);
869 static inline int __ctsvc_vcard_append_postals(ctsvc_list_s *address_list, char **buf, int *buf_size, int len)
872 ctsvc_address_s *address;
874 for (cursor = address_list->records; cursor; cursor = cursor->next) {
875 address = cursor->data;
877 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_ADR]);
879 len = __ctsvc_vcard_put_postal_type(address->type, SAFE_STR(address->label), buf, buf_size, len);
880 RETV_IF(len < 0, CONTACTS_ERROR_OUT_OF_MEMORY);
882 if (address->is_default)
883 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";PREF");
885 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";CHARSET=UTF-8");
886 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ":");
887 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, address->pobox);
888 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
889 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, address->extended);
890 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
891 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, address->street);
892 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
893 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, address->locality);
894 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
895 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, address->region);
896 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
897 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, address->postalcode);
898 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
899 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, address->country);
901 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, CTSVC_CRLF);
908 static inline int __ctsvc_vcard_append_nicknames(ctsvc_list_s *nickname_list, char **buf, int *buf_size, int len)
912 ctsvc_nickname_s *nickname;
915 for (cursor = nickname_list->records; cursor; cursor = cursor->next) {
916 nickname = cursor->data;
917 if (nickname->nickname && *nickname->nickname) {
919 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_NICKNAME]);
920 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";CHARSET=UTF-8");
921 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ":");
922 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, nickname->nickname);
925 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ",");
926 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, nickname->nickname);
931 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, CTSVC_CRLF);
936 static inline int __ctsvc_vcard_2_put_number_type(int type, char *dest, int dest_size)
939 if (type & CONTACTS_NUMBER_TYPE_HOME)
940 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "HOME");
941 if (type & CONTACTS_NUMBER_TYPE_MSG)
942 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "MSG");
943 if (type & CONTACTS_NUMBER_TYPE_WORK)
944 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "WORK");
945 if (type & CONTACTS_NUMBER_TYPE_VOICE)
946 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "VOICE");
947 if (type & CONTACTS_NUMBER_TYPE_FAX)
948 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "FAX");
949 if (type & CONTACTS_NUMBER_TYPE_VOICE)
950 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "VOICE");
951 if (type & CONTACTS_NUMBER_TYPE_CELL)
952 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "CELL");
953 if (type & CONTACTS_NUMBER_TYPE_VIDEO)
954 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "VIDEO");
955 if (type & CONTACTS_NUMBER_TYPE_PAGER)
956 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "PAGER");
957 if (type & CONTACTS_NUMBER_TYPE_BBS)
958 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "BBS");
959 if (type & CONTACTS_NUMBER_TYPE_MODEM)
960 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "MODEM");
961 if (type & CONTACTS_NUMBER_TYPE_CAR)
962 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "CAR");
963 if (type & CONTACTS_NUMBER_TYPE_ISDN)
964 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "ISDN");
965 if (type & CONTACTS_NUMBER_TYPE_PCS)
966 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "PCS");
971 static inline int __ctsvc_vcard_put_number_type(int type, char *label, char **buf, int *buf_size, int len)
973 if (type & CONTACTS_NUMBER_TYPE_HOME)
974 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=HOME");
975 if (type & CONTACTS_NUMBER_TYPE_MSG)
976 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=MSG");
977 if (type & CONTACTS_NUMBER_TYPE_WORK)
978 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=WORK");
979 if (type & CONTACTS_NUMBER_TYPE_VOICE)
980 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=VOICE");
981 if (type & CONTACTS_NUMBER_TYPE_FAX)
982 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=FAX");
983 if (type & CONTACTS_NUMBER_TYPE_CELL)
984 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=CELL");
985 if (type & CONTACTS_NUMBER_TYPE_VIDEO)
986 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=VIDEO");
987 if (type & CONTACTS_NUMBER_TYPE_PAGER)
988 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=PAGER");
989 if (type & CONTACTS_NUMBER_TYPE_BBS)
990 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=BBS");
991 if (type & CONTACTS_NUMBER_TYPE_MODEM)
992 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=MODEM");
993 if (type & CONTACTS_NUMBER_TYPE_CAR)
994 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=CAR");
995 if (type & CONTACTS_NUMBER_TYPE_ISDN)
996 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=ISDN");
997 if (type & CONTACTS_NUMBER_TYPE_PCS)
998 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=PCS");
999 if (type & CONTACTS_NUMBER_TYPE_ASSISTANT)
1000 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-ASSISTANT");
1001 if (type & CONTACTS_NUMBER_TYPE_RADIO)
1002 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-RADIO");
1003 if (type & CONTACTS_NUMBER_TYPE_COMPANY_MAIN)
1004 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-COMPANY-MAIN");
1005 if (type & CONTACTS_NUMBER_TYPE_MAIN)
1006 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-MAIN");
1007 if (type == CONTACTS_NUMBER_TYPE_CUSTOM) {
1008 if (__ctsvc_vcard_is_valid_custom_label(label)) {
1009 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-");
1010 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, label);
1017 static int __ctsvc_vcard_check_utf8(char c)
1019 if ((c & 0xff) < (128 & 0xff))
1021 else if ((c & (char)0xe0) == (char)0xc0)
1023 else if ((c & (char)0xf0) == (char)0xe0)
1025 else if ((c & (char)0xf8) == (char)0xf0)
1027 else if ((c & (char)0xfc) == (char)0xf8)
1029 else if ((c & (char)0xfe) == (char)0xfc)
1032 return CONTACTS_ERROR_INVALID_PARAMETER;
1035 static void __ctsvc_vcard_get_clean_number_for_export(char *str, char *dest)
1038 char *s = SAFE_STR(str);
1044 char_len = __ctsvc_vcard_check_utf8(*s);
1045 if (3 == char_len) {
1047 if (*(s+1) == 0xbc) {
1048 if (0x90 <= *(s+2) && *(s+2) <= 0x99) {
1049 /* ef bc 90 : '0' ~ ef bc 99 : '9' */
1050 *r = '0' + (*(s+2) - 0x90);
1053 } else if (0x8b == *(s+2)) {
1054 /* ef bc 8b : '+' */
1058 } else if (0x8a == *(s+2)) {
1059 /* ef bc 8a : '*' */
1063 } else if (0x83 == *(s+2)) {
1064 /* ef bc 83 : '#' */
1068 } else if (0x8c == *(s+2)) {
1069 /* ef bc 8c : ',' */
1073 } else if (0x9b == *(s+2)) {
1074 /* ef bc 9b : ';' */
1087 } else if (1 == char_len) {
1141 static inline int __ctsvc_vcard_append_numbers(ctsvc_list_s *number_list, char **buf, int *buf_size, int len)
1144 ctsvc_number_s *number;
1146 for (cursor = number_list->records; cursor; cursor = cursor->next) {
1147 number = cursor->data;
1148 if (number->number) {
1149 char clean_number[strlen(number->number)+1];
1150 clean_number[0] = '\0';
1151 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_TEL]);
1153 len = __ctsvc_vcard_put_number_type(number->type, SAFE_STR(number->label), buf, buf_size, len);
1154 RETV_IF(len < 0, CONTACTS_ERROR_OUT_OF_MEMORY);
1156 if (number->is_default)
1157 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";PREF");
1159 __ctsvc_vcard_get_clean_number_for_export(number->number, clean_number);
1161 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, clean_number);
1167 static inline int __ctsvc_vcard_2_put_email_type(int type, char *dest, int dest_size)
1171 if (CONTACTS_EMAIL_TYPE_HOME & type)
1172 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "HOME");
1173 if (CONTACTS_EMAIL_TYPE_WORK & type)
1174 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "WORK");
1179 static inline int __ctsvc_vcard_put_email_type(int type, char *label, char **buf, int *buf_size, int len)
1181 char *type_str = NULL;
1182 if (CONTACTS_EMAIL_TYPE_HOME == type) {
1184 } else if (CONTACTS_EMAIL_TYPE_WORK == type) {
1186 } else if (CONTACTS_EMAIL_TYPE_MOBILE == type) {
1188 } else if (CONTACTS_EMAIL_TYPE_CUSTOM == type) {
1189 if (__ctsvc_vcard_is_valid_custom_label(label)) {
1190 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-");
1191 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, label);
1197 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=");
1198 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, type_str);
1203 static inline int __ctsvc_vcard_append_emails(ctsvc_list_s *email_list, char **buf, int *buf_size, int len)
1206 ctsvc_email_s *email;
1208 for (cursor = email_list->records; cursor; cursor = cursor->next) {
1209 email = cursor->data;
1210 if (email->email_addr) {
1211 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_EMAIL]);
1213 len = __ctsvc_vcard_put_email_type(email->type, SAFE_STR(email->label), buf, buf_size, len);
1214 RETV_IF(len < 0, CONTACTS_ERROR_OUT_OF_MEMORY);
1216 if (email->is_default)
1217 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";PREF");
1219 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, email->email_addr);
1225 static inline int __ctsvc_vcard_put_url_type(int type, char *label, char **buf, int *buf_size, int len)
1227 char *type_str = NULL;
1229 if (CONTACTS_URL_TYPE_HOME == type) {
1231 } else if (CONTACTS_URL_TYPE_WORK == type) {
1233 } else if (CONTACTS_URL_TYPE_CUSTOM == type) {
1234 if (__ctsvc_vcard_is_valid_custom_label(label)) {
1235 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-");
1236 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, label);
1241 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=");
1242 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, type_str);
1247 static inline int __ctsvc_vcard_append_webs(ctsvc_list_s *url_list, char **buf, int *buf_size, int len)
1252 for (cursor = url_list->records; cursor; cursor = cursor->next) {
1255 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_URL]);
1257 len = __ctsvc_vcard_put_url_type(url->type, SAFE_STR(url->label), buf, buf_size, len);
1258 RETV_IF(len < 0, CONTACTS_ERROR_OUT_OF_MEMORY);
1260 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, url->url);
1266 #define VCARD_INIT_LENGTH 1024
1267 #define VCARD_ITEM_LENGTH 1024
1269 static inline int __ctsvc_vcard_append_events(ctsvc_list_s *event_list, char **buf, int *buf_size, int len)
1272 ctsvc_event_s *data;
1273 char event[VCARD_ITEM_LENGTH] = {0};
1275 for (cursor = event_list->records; cursor; cursor = cursor->next) {
1276 data = cursor->data;
1277 if (0 == data->date) continue;
1280 if (CONTACTS_EVENT_TYPE_BIRTH == data->type) {
1281 snprintf(event, sizeof(event), "%s:%d-%02d-%02d%s",
1282 content_name[CTSVC_VCARD_VALUE_BDAY],
1283 data->date/10000, (data->date%10000)/100, data->date%100,
1285 } else if (CONTACTS_EVENT_TYPE_ANNIVERSARY == data->type) {
1286 snprintf(event, sizeof(event), "%s;TYPE=ANNIVERSARY:%d-%02d-%02d%s",
1287 content_name[CTSVC_VCARD_VALUE_X_TIZEN_EVENT],
1288 data->date/10000, (data->date%10000)/100, data->date%100,
1290 } else if (CONTACTS_EVENT_TYPE_CUSTOM == data->type) {
1291 if (__ctsvc_vcard_is_valid_custom_label(data->label)) {
1292 snprintf(event, sizeof(event), "%s;TYPE=X-%s:%d-%02d-%02d%s",
1293 content_name[CTSVC_VCARD_VALUE_X_TIZEN_EVENT],
1294 SAFE_STR(data->label),
1295 data->date/10000, (data->date%10000)/100, data->date%100,
1298 snprintf(event, sizeof(event), "%s:%d-%02d-%02d%s",
1299 content_name[CTSVC_VCARD_VALUE_X_TIZEN_EVENT],
1300 data->date/10000, (data->date%10000)/100, data->date%100,
1304 snprintf(event, sizeof(event), "%s:%d-%02d-%02d%s",
1305 content_name[CTSVC_VCARD_VALUE_X_TIZEN_EVENT],
1306 data->date/10000, (data->date%10000)/100, data->date%100,
1309 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, event);
1315 static inline int __ctsvc_vcard_append_messengers(ctsvc_list_s *messenger_list, char **buf, int *buf_size, int len)
1318 ctsvc_messenger_s *messenger;
1319 const char *content_name_messenger = NULL;
1320 const char *content_name_x_type = NULL;
1322 for (cursor = messenger_list->records; cursor; cursor = cursor->next) {
1323 messenger = cursor->data;
1325 content_name_messenger = NULL;
1326 content_name_x_type = NULL;
1328 if (messenger->im_id && *messenger->im_id) {
1329 switch (messenger->type) {
1330 case CONTACTS_MESSENGER_TYPE_WLM:
1331 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_MSN];
1333 case CONTACTS_MESSENGER_TYPE_YAHOO:
1334 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_YAHOO];
1336 case CONTACTS_MESSENGER_TYPE_ICQ:
1337 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_ICQ];
1339 case CONTACTS_MESSENGER_TYPE_AIM:
1340 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_AIM];
1342 case CONTACTS_MESSENGER_TYPE_JABBER:
1343 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_JABBER];
1345 case CONTACTS_MESSENGER_TYPE_SKYPE:
1346 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_SKYPE_USERNAME];
1348 case CONTACTS_MESSENGER_TYPE_QQ:
1349 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_QQ];
1351 case CONTACTS_MESSENGER_TYPE_GOOGLE:
1352 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_GOOGLE_TALK];
1354 case CONTACTS_MESSENGER_TYPE_FACEBOOK:
1355 content_name_x_type = "FACEBOOK";
1357 case CONTACTS_MESSENGER_TYPE_IRC:
1358 content_name_x_type = "IRC";
1360 case CONTACTS_MESSENGER_TYPE_CUSTOM:
1361 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_X_TIZEN_MESSENGER]);
1362 if (__ctsvc_vcard_is_valid_custom_label(messenger->label)) {
1363 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-");
1364 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, messenger->label);
1366 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, messenger->im_id);
1369 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_X_TIZEN_MESSENGER]);
1370 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, messenger->im_id);
1374 if (content_name_messenger) {
1375 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name_messenger);
1376 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, messenger->im_id);
1377 } else if (content_name_x_type) {
1378 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_X_TIZEN_MESSENGER]);
1379 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=");
1380 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name_x_type);
1381 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, messenger->im_id);
1388 static inline int __ctsvc_vcard_put_relationship_type(int type, char *label, char **buf, int *buf_size, int len)
1390 const char *type_str = NULL;
1393 case CONTACTS_RELATIONSHIP_TYPE_ASSISTANT:
1394 type_str = "ASSISTANT";
1396 case CONTACTS_RELATIONSHIP_TYPE_BROTHER:
1397 type_str = "BROTHER";
1399 case CONTACTS_RELATIONSHIP_TYPE_CHILD:
1402 case CONTACTS_RELATIONSHIP_TYPE_DOMESTIC_PARTNER:
1403 type_str = "DOMESTIC_PARTNER";
1405 case CONTACTS_RELATIONSHIP_TYPE_FATHER:
1406 type_str = "FATHER";
1408 case CONTACTS_RELATIONSHIP_TYPE_FRIEND:
1409 type_str = "FRIEND";
1411 case CONTACTS_RELATIONSHIP_TYPE_MANAGER:
1412 type_str = "MANAGER";
1414 case CONTACTS_RELATIONSHIP_TYPE_MOTHER:
1415 type_str = "MOTHER";
1417 case CONTACTS_RELATIONSHIP_TYPE_PARENT:
1418 type_str = "PARENT";
1420 case CONTACTS_RELATIONSHIP_TYPE_PARTNER:
1421 type_str = "PARTNER";
1423 case CONTACTS_RELATIONSHIP_TYPE_REFERRED_BY:
1424 type_str = "REFERRED_BY";
1426 case CONTACTS_RELATIONSHIP_TYPE_RELATIVE:
1427 type_str = "RELATIVE";
1429 case CONTACTS_RELATIONSHIP_TYPE_SISTER:
1430 type_str = "SISTER";
1432 case CONTACTS_RELATIONSHIP_TYPE_SPOUSE:
1433 type_str = "SPOUSE";
1435 case CONTACTS_RELATIONSHIP_TYPE_CUSTOM:
1436 if (__ctsvc_vcard_is_valid_custom_label(label)) {
1437 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-");
1438 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, label);
1444 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=");
1445 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, type_str);
1451 static inline int __ctsvc_vcard_append_relationships(ctsvc_list_s *relationship_list, char **buf, int *buf_size, int len)
1454 ctsvc_relationship_s *relationship;
1456 for (cursor = relationship_list->records; cursor; cursor = cursor->next) {
1457 relationship = cursor->data;
1459 if (relationship->name) {
1460 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, "X-TIZEN-RELATIONSHIP");
1462 len = __ctsvc_vcard_put_relationship_type(relationship->type, SAFE_STR(relationship->label), buf, buf_size, len);
1463 RETV_IF(len < 0, CONTACTS_ERROR_OUT_OF_MEMORY);
1464 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, relationship->name);
1473 unsigned char **image;
1474 unsigned int *image_size;
1478 static bool _ctsvc_vcard_image_util_supported_jpeg_colorspace_cb(
1479 image_util_colorspace_e colorspace, void *user_data)
1485 unsigned int size_decode = 0;
1486 void *buffer = NULL;
1487 void *buffer_temp = NULL;
1489 vcard_image_info *info = user_data;
1491 ret = ctsvc_image_util_get_mimetype(colorspace, &mimetype);
1492 if (CONTACTS_ERROR_NONE != ret) {
1493 /* LCOV_EXCL_START */
1494 info->ret = CONTACTS_ERROR_SYSTEM;
1496 /* LCOV_EXCL_STOP */
1499 image_util_decode_h dh = NULL;
1501 unsigned long l_width = 0;
1502 unsigned long l_height = 0;
1503 unsigned long long ll_size_decode = 0;
1505 ret = image_util_decode_create(&dh);
1506 if (IMAGE_UTIL_ERROR_NONE != ret)
1508 ret = image_util_decode_set_input_path(dh, info->src);
1509 if (IMAGE_UTIL_ERROR_NONE != ret)
1511 ret = image_util_decode_set_colorspace(dh, colorspace);
1512 if (IMAGE_UTIL_ERROR_NONE != ret)
1514 ret = image_util_decode_set_output_buffer(dh, (unsigned char **)&buffer);
1515 if (IMAGE_UTIL_ERROR_NONE != ret)
1517 ret = image_util_decode_run(dh, &l_width, &l_height, &ll_size_decode);
1518 if (IMAGE_UTIL_ERROR_NONE != ret)
1521 width = (int)l_width;
1522 height = (int)l_height;
1523 size_decode = (unsigned int)ll_size_decode;
1526 ret = image_util_decode_destroy(dh);
1527 if (IMAGE_UTIL_ERROR_NONE != ret || 0 == width || 0 == height) {
1528 /* LCOV_EXCL_START */
1529 info->ret = CONTACTS_ERROR_SYSTEM;
1531 /* LCOV_EXCL_STOP */
1533 size = (uint64_t)size_decode;
1535 if (limit_size_of_photo < width || limit_size_of_photo < height) { /* need resize */
1539 media_packet_h packet;
1542 if (width > height) {
1543 resized_width = limit_size_of_photo;
1544 resized_height = height * limit_size_of_photo / width;
1546 resized_height = limit_size_of_photo;
1547 resized_width = width * limit_size_of_photo / height;
1550 if (resized_height % 8)
1551 resized_height -= (resized_height % 8);
1553 if (resized_width % 8)
1554 resized_width -= (resized_width % 8);
1556 fmt = ctsvc_image_util_create_media_format(mimetype, width, height);
1558 /* LCOV_EXCL_START */
1559 ERR("_ctsvc_image_create_media_format() Fail");
1560 info->ret = CONTACTS_ERROR_SYSTEM;
1563 /* LCOV_EXCL_STOP */
1566 packet = ctsvc_image_util_create_media_packet(fmt, buffer, (unsigned int)size);
1567 if (NULL == packet) {
1568 /* LCOV_EXCL_START */
1569 ERR("_ctsvc_image_create_media_packet() Fail");
1570 media_format_unref(fmt);
1571 info->ret = CONTACTS_ERROR_SYSTEM;
1574 /* LCOV_EXCL_STOP */
1577 ret = ctsvc_image_util_resize(packet, resized_width, resized_height, &buffer_temp,
1580 media_packet_destroy(packet);
1581 media_format_unref(fmt);
1583 if (CONTACTS_ERROR_NONE != ret) {
1585 info->ret = CONTACTS_ERROR_SYSTEM;
1589 buffer = buffer_temp;
1591 width = resized_width;
1592 height = resized_height;
1595 image_util_encode_h eh = NULL;
1597 unsigned long long ll_size_encode = 0;
1599 ret = image_util_encode_create(IMAGE_UTIL_JPEG, &eh);
1600 if (IMAGE_UTIL_ERROR_NONE != ret)
1602 ret = image_util_encode_set_input_buffer(eh, buffer);
1603 if (IMAGE_UTIL_ERROR_NONE != ret)
1605 ret = image_util_encode_set_resolution(eh, width, height);
1606 if (IMAGE_UTIL_ERROR_NONE != ret)
1608 ret = image_util_encode_set_colorspace(eh, colorspace);
1609 if (IMAGE_UTIL_ERROR_NONE != ret)
1611 ret = image_util_encode_set_quality(eh, CTSVC_IMAGE_ENCODE_QUALITY);
1612 if (IMAGE_UTIL_ERROR_NONE != ret)
1614 ret = image_util_encode_set_output_buffer(eh, info->image);
1615 if (IMAGE_UTIL_ERROR_NONE != ret)
1617 ret = image_util_encode_run(eh, &ll_size_encode);
1618 *(info->image_size) = (unsigned int)ll_size_encode;
1621 ret = image_util_encode_destroy(eh);
1623 if (IMAGE_UTIL_ERROR_NONE != ret) {
1624 /* LCOV_EXCL_START */
1625 ERR("image_util_encode_jpeg_to_memory", ret);
1626 info->ret = CONTACTS_ERROR_SYSTEM;
1628 /* LCOV_EXCL_STOP */
1631 info->ret = CONTACTS_ERROR_NONE;
1635 static inline int __ctsvc_vcard_encode_photo(const char *src,
1636 unsigned char **image, unsigned int *image_size)
1639 vcard_image_info info = {src, image, image_size, CONTACTS_ERROR_SYSTEM};
1641 ret = image_util_foreach_supported_colorspace(IMAGE_UTIL_JPEG,
1642 _ctsvc_vcard_image_util_supported_jpeg_colorspace_cb, &info);
1644 if (IMAGE_UTIL_ERROR_NONE != ret)
1645 return CONTACTS_ERROR_SYSTEM;
1650 static inline int __ctsvc_vcard_put_photo(ctsvc_list_s *image_list, char **buf, int *buf_size, int len)
1652 int ret = CONTACTS_ERROR_NONE, fd, type;
1653 unsigned int read_len;
1656 unsigned char *image = NULL;
1657 unsigned int img_buf_size = 0;
1659 ctsvc_image_s *data;
1661 for (cursor = image_list->records; cursor; cursor = cursor->next) {
1662 data = cursor->data;
1663 if (NULL == data->path) continue;
1665 ret = __ctsvc_vcard_encode_photo(data->path, &image, &read_len);
1667 if (CONTACTS_ERROR_NONE != ret) {
1668 INFO("__ctsvc_vcard_encode_photo() Fail(%d)", ret);
1670 img_buf_size = CTSVC_VCARD_PHOTO_MAX_SIZE * sizeof(unsigned char);
1671 image = calloc(1, img_buf_size);
1672 if (NULL == image) {
1673 /* LCOV_EXCL_START */
1674 ERR("calloc() Fail");
1675 return CONTACTS_ERROR_OUT_OF_MEMORY;
1676 /* LCOV_EXCL_STOP */
1679 fd = open(data->path, O_RDONLY);
1681 /* LCOV_EXCL_START */
1682 ERR("System : Open Fail(%d)", errno);
1684 return CONTACTS_ERROR_SYSTEM;
1685 /* LCOV_EXCL_STOP */
1689 while ((ret = read(fd, image+read_len, img_buf_size-read_len))) {
1700 /* LCOV_EXCL_START */
1701 ERR("System : read() Fail(%d)", errno);
1703 return CONTACTS_ERROR_SYSTEM;
1704 /* LCOV_EXCL_STOP */
1708 suffix = strrchr(data->path, '.');
1709 type = __ctsvc_vcard_get_image_type(suffix);
1711 buf_image = g_base64_encode(image, read_len);
1716 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_PHOTO], false)) < 0)
1718 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, ";ENCODING=BASE64;TYPE=", false)) < 0)
1720 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, __ctsvc_get_image_type_str(type), false)) < 0)
1722 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, ":", false)) < 0)
1724 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, buf_image, false)) < 0)
1726 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, CTSVC_CRLF, false)) < 0)
1728 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, CTSVC_CRLF, false)) < 0)
1734 /* LCOV_EXCL_START */
1735 ERR("__ctsvc_vcard_append_str() Fail");
1736 return CONTACTS_ERROR_OUT_OF_MEMORY;
1737 /* LCOV_EXCL_STOP */
1745 static inline int __ctsvc_vcard_append_contact(ctsvc_contact_s *contact, char **buf, int *buf_size, int len)
1747 if (contact->name) {
1748 len = __ctsvc_vcard_append_name(contact->name, buf, buf_size, len);
1749 RETV_IF(len < 0, len);
1751 if (contact->company) {
1752 len = __ctsvc_vcard_append_company(contact->company, buf, buf_size, len);
1753 RETV_IF(len < 0, len);
1755 if (contact->note) {
1756 len = __ctsvc_vcard_append_note(contact->note, buf, buf_size, len);
1757 RETV_IF(len < 0, len);
1759 if (contact->postal_addrs) {
1760 len = __ctsvc_vcard_append_postals(contact->postal_addrs, buf, buf_size, len);
1761 RETV_IF(len < 0, len);
1763 if (contact->numbers) {
1764 len = __ctsvc_vcard_append_numbers(contact->numbers, buf, buf_size, len);
1765 RETV_IF(len < 0, len);
1767 if (contact->emails) {
1768 len = __ctsvc_vcard_append_emails(contact->emails, buf, buf_size, len);
1769 RETV_IF(len < 0, len);
1771 if (contact->nicknames) {
1772 len = __ctsvc_vcard_append_nicknames(contact->nicknames, buf, buf_size, len);
1773 RETV_IF(len < 0, len);
1775 if (contact->urls) {
1776 len = __ctsvc_vcard_append_webs(contact->urls, buf, buf_size, len);
1777 RETV_IF(len < 0, len);
1779 if (contact->events) {
1780 len = __ctsvc_vcard_append_events(contact->events, buf, buf_size, len);
1781 RETV_IF(len < 0, len);
1783 if (contact->images) {
1784 len = __ctsvc_vcard_put_photo(contact->images, buf, buf_size, len);
1785 RETV_IF(len < 0, len);
1787 if (contact->messengers) {
1788 len = __ctsvc_vcard_append_messengers(contact->messengers, buf, buf_size, len);
1789 RETV_IF(len < 0, len);
1791 if (contact->relationships) {
1792 len = __ctsvc_vcard_append_relationships(contact->relationships, buf, buf_size, len);
1793 RETV_IF(len < 0, len);
1796 if (contact->uid && DEFAULT_ADDRESS_BOOK_ID == contact->addressbook_id) {
1797 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_UID]);
1798 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, contact->uid);
1801 if (contact->changed_time) {
1803 gmtime_r((time_t *)&contact->changed_time, &ts);
1804 char temp[VCARD_ITEM_LENGTH] = {0};
1805 snprintf(temp, sizeof(temp), "%s:%04d-%02d-%02dT%02d:%02d:%02dZ%s",
1806 content_name[CTSVC_VCARD_VALUE_REV],
1807 1900+ts.tm_year, 1+ts.tm_mon, ts.tm_mday,
1808 ts.tm_hour, ts.tm_min, ts.tm_sec,
1811 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, temp);
1814 ctsvc_list_s *profile;
1819 static inline int __ctsvc_vcard_append_my_profile(ctsvc_my_profile_s *my_profile, char **buf, int *buf_size, int len)
1821 if (my_profile->name) {
1822 len = __ctsvc_vcard_append_name(my_profile->name, buf, buf_size, len);
1823 RETV_IF(len < 0, len);
1825 if (my_profile->company) {
1826 len = __ctsvc_vcard_append_company(my_profile->company, buf, buf_size, len);
1827 RETV_IF(len < 0, len);
1829 if (my_profile->note) {
1830 len = __ctsvc_vcard_append_note(my_profile->note, buf, buf_size, len);
1831 RETV_IF(len < 0, len);
1833 if (my_profile->postal_addrs) {
1834 len = __ctsvc_vcard_append_postals(my_profile->postal_addrs, buf, buf_size, len);
1835 RETV_IF(len < 0, len);
1837 if (my_profile->numbers) {
1838 len = __ctsvc_vcard_append_numbers(my_profile->numbers, buf, buf_size, len);
1839 RETV_IF(len < 0, len);
1841 if (my_profile->emails) {
1842 len = __ctsvc_vcard_append_emails(my_profile->emails, buf, buf_size, len);
1843 RETV_IF(len < 0, len);
1845 if (my_profile->nicknames) {
1846 len = __ctsvc_vcard_append_nicknames(my_profile->nicknames, buf, buf_size, len);
1847 RETV_IF(len < 0, len);
1849 if (my_profile->urls) {
1850 len = __ctsvc_vcard_append_webs(my_profile->urls, buf, buf_size, len);
1851 RETV_IF(len < 0, len);
1853 if (my_profile->events) {
1854 len = __ctsvc_vcard_append_events(my_profile->events, buf, buf_size, len);
1855 RETV_IF(len < 0, len);
1857 if (my_profile->images) {
1858 len = __ctsvc_vcard_put_photo(my_profile->images, buf, buf_size, len);
1859 RETV_IF(len < 0, len);
1861 if (my_profile->messengers) {
1862 len = __ctsvc_vcard_append_messengers(my_profile->messengers, buf, buf_size, len);
1863 RETV_IF(len < 0, len);
1865 if (my_profile->relationships) {
1866 len = __ctsvc_vcard_append_relationships(my_profile->relationships, buf, buf_size, len);
1867 RETV_IF(len < 0, len);
1870 if (my_profile->uid && DEFAULT_ADDRESS_BOOK_ID == my_profile->addressbook_id) {
1871 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_UID]);
1872 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, my_profile->uid);
1875 if (my_profile->changed_time) {
1877 gmtime_r((time_t *)&my_profile->changed_time, &ts);
1878 char temp[VCARD_ITEM_LENGTH] = {0};
1879 snprintf(temp, sizeof(temp), "%s:%04d-%02d-%02dT%02d:%02d:%02dZ%s",
1880 content_name[CTSVC_VCARD_VALUE_REV],
1881 1900+ts.tm_year, 1+ts.tm_mon, ts.tm_mday,
1882 ts.tm_hour, ts.tm_min, ts.tm_sec,
1885 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, temp);
1889 ctsvc_list_s *profile;
1894 static inline int __ctsvc_vcard_append_start_vcard_3_0(char **buf, int *buf_size, int len)
1896 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, "BEGIN:VCARD");
1897 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, CTSVC_CRLF);
1898 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, "VERSION:3.0");
1899 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, CTSVC_CRLF);
1903 static inline int __ctsvc_vcard_append_end_vcard(char **buf, int *buf_size, int len)
1905 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, "END:VCARD");
1906 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, CTSVC_CRLF);
1910 static int __ctsvc_vcard_make(ctsvc_contact_s *contact, char **vcard_stream)
1913 int buf_size = VCARD_INIT_LENGTH;
1916 __ctsvc_vcard_initial();
1918 buf = calloc(1, buf_size);
1920 /* LCOV_EXCL_START */
1921 ERR("calloc() Fail");
1922 return CONTACTS_ERROR_OUT_OF_MEMORY;
1923 /* LCOV_EXCL_STOP */
1926 len = __ctsvc_vcard_append_start_vcard_3_0(&buf, &buf_size, len);
1928 /* LCOV_EXCL_START */
1930 return CONTACTS_ERROR_OUT_OF_MEMORY;
1931 /* LCOV_EXCL_STOP */
1934 len = __ctsvc_vcard_append_contact(contact, &buf, &buf_size, len);
1936 /* LCOV_EXCL_START */
1938 return CONTACTS_ERROR_OUT_OF_MEMORY;
1939 /* LCOV_EXCL_STOP */
1942 len = __ctsvc_vcard_append_end_vcard(&buf, &buf_size, len);
1944 /* LCOV_EXCL_START */
1946 return CONTACTS_ERROR_OUT_OF_MEMORY;
1947 /* LCOV_EXCL_STOP */
1950 len = __ctsvc_vcard_add_folding(&buf, &buf_size, len);
1952 /* LCOV_EXCL_START */
1954 return CONTACTS_ERROR_OUT_OF_MEMORY;
1955 /* LCOV_EXCL_STOP */
1957 *vcard_stream = buf;
1959 return CONTACTS_ERROR_NONE;
1962 static int __ctsvc_vcard_make_from_my_profile(ctsvc_my_profile_s *my_profile, char **vcard_stream)
1965 int buf_size = VCARD_INIT_LENGTH;
1968 __ctsvc_vcard_initial();
1970 buf = calloc(1, buf_size);
1972 /* LCOV_EXCL_START */
1973 ERR("calloc() Fail");
1974 return CONTACTS_ERROR_OUT_OF_MEMORY;
1975 /* LCOV_EXCL_STOP */
1978 len = __ctsvc_vcard_append_start_vcard_3_0(&buf, &buf_size, len);
1980 /* LCOV_EXCL_START */
1982 return CONTACTS_ERROR_OUT_OF_MEMORY;
1983 /* LCOV_EXCL_STOP */
1986 len = __ctsvc_vcard_append_my_profile(my_profile, &buf, &buf_size, len);
1988 /* LCOV_EXCL_START */
1990 return CONTACTS_ERROR_OUT_OF_MEMORY;
1991 /* LCOV_EXCL_STOP */
1994 len = __ctsvc_vcard_append_end_vcard(&buf, &buf_size, len);
1996 /* LCOV_EXCL_START */
1998 return CONTACTS_ERROR_OUT_OF_MEMORY;
1999 /* LCOV_EXCL_STOP */
2002 len = __ctsvc_vcard_add_folding(&buf, &buf_size, len);
2004 /* LCOV_EXCL_START */
2006 return CONTACTS_ERROR_OUT_OF_MEMORY;
2007 /* LCOV_EXCL_STOP */
2010 *vcard_stream = buf;
2012 return CONTACTS_ERROR_NONE;
2015 EXPORT_API int contacts_vcard_make_from_contact(contacts_record_h record, char **vcard_stream)
2017 CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
2018 ctsvc_contact_s *contact;
2019 RETV_IF(NULL == vcard_stream, CONTACTS_ERROR_INVALID_PARAMETER);
2020 *vcard_stream = NULL;
2022 RETVM_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER,
2023 "contact(%p), vcard_stream(%p)", record, vcard_stream);
2025 contact = (ctsvc_contact_s*)record;
2026 RETVM_IF(CTSVC_RECORD_CONTACT != contact->base.r_type, CONTACTS_ERROR_INVALID_PARAMETER,
2027 "The record is not conatct record (type : %d)", contact->base.r_type);
2029 return __ctsvc_vcard_make(contact, vcard_stream);
2032 EXPORT_API int contacts_vcard_make_from_my_profile(contacts_record_h record, char **vcard_stream)
2034 CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
2035 ctsvc_my_profile_s *my_profile;
2036 RETV_IF(NULL == vcard_stream, CONTACTS_ERROR_INVALID_PARAMETER);
2037 *vcard_stream = NULL;
2039 RETVM_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER,
2040 "my_profile(%p), vcard_stream(%p)", record, vcard_stream);
2042 my_profile = (ctsvc_my_profile_s*)record;
2043 RETVM_IF(CTSVC_RECORD_MY_PROFILE != my_profile->base.r_type, CONTACTS_ERROR_INVALID_PARAMETER,
2044 "The record is not conatct record (type : %d)", my_profile->base.r_type);
2046 return __ctsvc_vcard_make_from_my_profile(my_profile, vcard_stream);
2049 #ifdef _CONTACTS_IPC_CLIENT
2050 static int __ctsvc_vcard_append_person(ctsvc_person_s *person, ctsvc_list_s *list_contacts, char **buf, int *buf_size, int len)
2052 int changed_time = 0;
2053 ctsvc_contact_s *contact;
2054 GList *cursor = NULL;
2056 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2057 contact = cursor->data;
2058 if (contact && contact->id == person->name_contact_id && contact->name) {
2059 len = __ctsvc_vcard_append_name(contact->name, buf, buf_size, len);
2060 RETV_IF(len < 0, len);
2064 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2065 contact = cursor->data;
2066 if (contact && contact->company && contact->company->cursor) {
2067 len = __ctsvc_vcard_append_company(contact->company, buf, buf_size, len);
2068 RETV_IF(len < 0, len);
2072 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2073 contact = cursor->data;
2074 if (contact && contact->note && contact->note->cursor) {
2075 len = __ctsvc_vcard_append_note(contact->note, buf, buf_size, len);
2076 RETV_IF(len < 0, len);
2079 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2080 contact = cursor->data;
2081 if (contact && contact->postal_addrs && contact->postal_addrs->cursor) {
2082 len = __ctsvc_vcard_append_postals(contact->postal_addrs, buf, buf_size, len);
2083 RETV_IF(len < 0, len);
2086 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2087 contact = cursor->data;
2088 if (contact && contact->numbers && contact->numbers->cursor) {
2089 len = __ctsvc_vcard_append_numbers(contact->numbers, buf, buf_size, len);
2090 RETV_IF(len < 0, len);
2094 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2095 contact = cursor->data;
2096 if (contact && contact->emails && contact->emails->cursor) {
2097 len = __ctsvc_vcard_append_emails(contact->emails, buf, buf_size, len);
2098 RETV_IF(len < 0, len);
2102 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2103 contact = cursor->data;
2104 if (contact && contact->nicknames && contact->nicknames->cursor) {
2105 len = __ctsvc_vcard_append_nicknames(contact->nicknames, buf, buf_size, len);
2106 RETV_IF(len < 0, len);
2109 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2110 contact = cursor->data;
2111 if (contact && contact->urls && contact->urls->cursor) {
2112 len = __ctsvc_vcard_append_webs(contact->urls, buf, buf_size, len);
2113 RETV_IF(len < 0, len);
2117 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2118 contact = cursor->data;
2119 if (contact && contact->events && contact->events->cursor) {
2120 len = __ctsvc_vcard_append_events(contact->events, buf, buf_size, len);
2121 RETV_IF(len < 0, len);
2124 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2125 contact = cursor->data;
2126 if (contact && contact->images && contact->images->cursor) {
2127 len = __ctsvc_vcard_put_photo(contact->images, buf, buf_size, len);
2128 RETV_IF(len < 0, len);
2131 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2132 contact = cursor->data;
2133 if (contact && contact->messengers && contact->messengers->cursor) {
2134 len = __ctsvc_vcard_append_messengers(contact->messengers, buf, buf_size, len);
2135 RETV_IF(len < 0, len);
2139 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2140 contact = cursor->data;
2141 if (contact && contact->relationships && contact->relationships->cursor) {
2142 len = __ctsvc_vcard_append_relationships(contact->relationships, buf, buf_size, len);
2143 RETV_IF(len < 0, len);
2147 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2148 contact = cursor->data;
2149 if (contact && contact->uid && DEFAULT_ADDRESS_BOOK_ID == contact->addressbook_id) {
2150 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_UID]);
2151 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, contact->uid);
2154 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2155 contact = cursor->data;
2156 if (contact && changed_time < contact->changed_time)
2157 changed_time = contact->changed_time;
2162 gmtime_r((time_t*)&changed_time, &ts);
2163 char temp[VCARD_ITEM_LENGTH] = {0};
2164 snprintf(temp, sizeof(temp), "%s:%04d-%02d-%02dT%02d:%02d:%02dZ%s",
2165 content_name[CTSVC_VCARD_VALUE_REV],
2166 1900+ts.tm_year, 1+ts.tm_mon, ts.tm_mday,
2167 ts.tm_hour, ts.tm_min, ts.tm_sec,
2170 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, temp);
2174 ctsvc_list_s *profile;
2178 #endif /* _CONTACTS_IPC_CLIENT */
2180 #ifdef _CONTACTS_IPC_CLIENT
2181 static int __ctsvc_vcard_make_from_person(ctsvc_person_s *person, ctsvc_list_s *list_contacts,
2182 char **vcard_stream)
2185 int buf_size = VCARD_INIT_LENGTH;
2188 RETV_IF(NULL == vcard_stream, CONTACTS_ERROR_INVALID_PARAMETER);
2189 *vcard_stream = NULL;
2191 __ctsvc_vcard_initial();
2193 buf = calloc(1, buf_size);
2195 /* LCOV_EXCL_START */
2196 ERR("calloc() Fail");
2197 return CONTACTS_ERROR_OUT_OF_MEMORY;
2198 /* LCOV_EXCL_STOP */
2201 len = __ctsvc_vcard_append_start_vcard_3_0(&buf, &buf_size, len);
2203 /* LCOV_EXCL_START */
2205 return CONTACTS_ERROR_OUT_OF_MEMORY;
2206 /* LCOV_EXCL_STOP */
2209 len = __ctsvc_vcard_append_person(person, list_contacts, &buf, &buf_size, len);
2211 /* LCOV_EXCL_START */
2213 return CONTACTS_ERROR_OUT_OF_MEMORY;
2214 /* LCOV_EXCL_STOP */
2216 len = __ctsvc_vcard_append_end_vcard(&buf, &buf_size, len);
2218 /* LCOV_EXCL_START */
2220 return CONTACTS_ERROR_OUT_OF_MEMORY;
2221 /* LCOV_EXCL_STOP */
2224 len = __ctsvc_vcard_add_folding(&buf, &buf_size, len);
2226 /* LCOV_EXCL_START */
2228 return CONTACTS_ERROR_OUT_OF_MEMORY;
2229 /* LCOV_EXCL_STOP */
2232 *vcard_stream = buf;
2234 return CONTACTS_ERROR_NONE;
2236 #endif /* _CONTACTS_IPC_CLIENT */
2238 #ifdef _CONTACTS_IPC_CLIENT
2239 EXPORT_API int contacts_vcard_make_from_person(contacts_record_h record, char **vcard_stream)
2241 CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
2243 ctsvc_person_s *person;
2244 contacts_query_h query = NULL;
2245 contacts_filter_h filter = NULL;
2246 contacts_list_h list = NULL;
2248 RETVM_IF(NULL == record || NULL == vcard_stream, CONTACTS_ERROR_INVALID_PARAMETER,
2249 "person(%p), vcard_stream(%p)", record, vcard_stream);
2250 *vcard_stream = NULL;
2252 person = (ctsvc_person_s*)record;
2254 RETVM_IF(CTSVC_RECORD_PERSON != person->base.r_type, CONTACTS_ERROR_INVALID_PARAMETER,
2255 "The record is not conatct record (type : %d)", person->base.r_type);
2258 if (CONTACTS_ERROR_NONE != (ret = contacts_filter_create(_contacts_contact._uri, &filter))) break;
2259 if (CONTACTS_ERROR_NONE != (ret = contacts_filter_add_int(filter, _contacts_contact.person_id, CONTACTS_MATCH_EQUAL, person->person_id))) break;
2260 if (CONTACTS_ERROR_NONE != (ret = contacts_query_create(_contacts_contact._uri, &query))) break;
2261 if (CONTACTS_ERROR_NONE != (ret = contacts_query_set_filter(query, filter))) break;
2262 if (CONTACTS_ERROR_NONE != (ret = contacts_db_get_records_with_query(query, 0, 0, &list))) break;
2263 if (CONTACTS_ERROR_NONE != (ret = __ctsvc_vcard_make_from_person(person, (ctsvc_list_s*)list, vcard_stream))) break;
2265 WARN_IF(CONTACTS_ERROR_NONE != ret, "__ctsvc_vcard_make_from_person() Fail(%d)", ret);
2266 contacts_query_destroy(query);
2267 contacts_filter_destroy(filter);
2268 contacts_list_destroy(list, true);
2273 static inline char* __ctsvc_vcard_remove_empty_line(char *src)
2276 if ('\n' != *src && '\r' != *src)
2283 static char* __ctsvc_vcard_check_word(char *src, const char *word)
2287 RETV_IF(NULL == src, NULL);
2289 src = __ctsvc_vcard_remove_empty_line(src);
2305 while (*src == *word) {
2309 if ('\0' == *src || '\0' == *word)
2319 static int __ctsvc_vcard_check_content_type(char **vcard)
2324 for (i = CTSVC_VCARD_VALUE_NONE+1; i < CTSVC_VCARD_VALUE_MAX; i++) {
2325 new_start = __ctsvc_vcard_check_word(*vcard, content_name[i]);
2326 if (new_start && (':' == *new_start || ';' == *new_start))
2330 if (CTSVC_VCARD_VALUE_MAX == i) {
2331 return CTSVC_VCARD_VALUE_NONE;
2338 static inline char* __ctsvc_vcard_pass_unsupported(char *vcard)
2349 static char* __ctsvc_strtok(char *val, char c)
2351 char *before = NULL;
2353 if (*val == c && (NULL == before || *before != '\\')) {
2363 static inline bool __ctsvc_vcard_check_base64_encoded(char *src)
2370 ret = strncmp(tmp, "BASE64", sizeof("BASE64") - 1);
2371 if (STRING_EQUAL == ret)
2373 } else if (':' == *tmp || '\r' == *tmp) {
2381 static inline int __ctsvc_vcard_check_quoted(char *src, int max, int *quoted)
2384 if (TRUE == *quoted)
2387 while (*src && max) {
2389 ret = strncmp(src, "QUOTED-PRINTABLE", sizeof("QUOTED-PRINTABLE") - 1);
2390 if (STRING_EQUAL == ret) {
2394 } else if (':' == *src) {
2403 static inline int __ctsvc_vcard_remove_folding(char *folded_src)
2405 char *result = folded_src;
2407 RETV_IF(NULL == folded_src, CONTACTS_ERROR_INVALID_PARAMETER);
2409 while (*folded_src) {
2410 if ('\r' == *folded_src && '\n' == *(folded_src+1) && ' ' == *(folded_src+2))
2412 else if ('\n' == *folded_src && ' ' == *(folded_src+1))
2415 if ('\0' == *folded_src)
2418 *result = *folded_src;
2423 return CONTACTS_ERROR_NONE;
2426 static inline int __ctsvc_vcard_hex_to_dec(char hex)
2432 return hex - 'a' + 10;
2434 return hex - 'A' + 10;
2439 static inline int __ctsvc_vcard_decode_quoted_val(char *val)
2444 src = strchr(val, ':');
2451 pre = __ctsvc_vcard_hex_to_dec(*(src+1));
2453 *dest = (char)((pre << 4) + __ctsvc_vcard_hex_to_dec(*(src+2)));
2457 if ('\r' == *(src+1) && '\n' == *(src+2))
2471 static inline char* __ctsvc_vcard_translate_charset(char *src, int len)
2478 ret = strncmp(val, "CHARSET", sizeof("CHARSET") - 1);
2479 if (STRING_EQUAL == ret) {
2480 val += sizeof("CHARSET");
2483 } else if (':' == *val) {
2492 UErrorCode err = U_ZERO_ERROR;
2496 char enc[32] = {0}, *dest;
2498 while (';' != *val && ':' != *val)
2502 if (0 == strcasecmp("UTF-8", enc))
2508 src_len = len - (val - src);
2510 temp_size = (src_len+1) * sizeof(UChar);
2511 temp = malloc(temp_size);
2513 ERR("malloc() Fail");
2516 conv = ucnv_open(enc, &err);
2517 WARN_IF(U_FAILURE(err), "ucnv_open() Fail(%d), enc=%s", err, enc);
2518 ucnv_toUChars(conv, temp, temp_size, val, src_len, &err);
2519 WARN_IF(U_FAILURE(err), "ucnv_toUChars() Fail(%d), enc=%s", err, enc);
2522 dest_size = temp_size*2;
2523 dest = malloc(dest_size);
2525 ERR("malloc() Fail");
2529 conv = ucnv_open("UTF-8", &err);
2530 WARN_IF(U_FAILURE(err), "ucnv_open() Fail(%d), enc=%s", err, enc);
2531 ucnv_fromUChars(conv, dest, dest_size, temp, u_strlen(temp), &err);
2532 WARN_IF(U_FAILURE(err), "ucnv_fromUChars() Fail(%d), enc=%s", err, enc);
2541 static void __ctsvc_vcard_get_prefix(char **prefix, char *src)
2543 char *temp = strchr(src, ':');
2545 int len = (int)temp - (int)src;
2546 *prefix = calloc(len+1, sizeof(char));
2548 snprintf(*prefix, len+1, "%s", src);
2554 static char* __ctsvc_vcard_get_val(int ver, char *src, char **prefix, char **dest)
2560 RETV_IF(NULL == src, NULL);
2561 RETV_IF(NULL == dest, NULL);
2580 if (CTSVC_VCARD_VER_2_1 == ver) {
2582 if ('=' == *cursor && __ctsvc_vcard_check_quoted(src, cursor - src, "ed)) {
2583 if ('\r' == *(cursor+1) && '\n' == *(cursor+2))
2586 if ('\r' == *cursor && '\n' == *(cursor+1) && ' ' != *(cursor+2))
2588 if ('\n' == *cursor && ' ' != *(cursor+1))
2596 if ('\r' == *cursor && '\n' == *(cursor+1) && ' ' != *(cursor+2))
2599 if ('\n' == *cursor && ' ' != *(cursor+1))
2606 if (src == cursor) {
2611 char temp = *cursor;
2615 __ctsvc_vcard_get_prefix(prefix, src);
2618 *dest = strdup(src);
2619 if (NULL == *dest) {
2620 ERR("strdup() Fail");
2623 if (CTSVC_VCARD_VER_2_1 != ver)
2624 __ctsvc_vcard_remove_folding(*dest);
2626 if (__ctsvc_vcard_check_quoted(*dest, -1, "ed))
2627 len = __ctsvc_vcard_decode_quoted_val(*dest);
2629 len = strlen(*dest);
2630 new_dest = __ctsvc_vcard_translate_charset(*dest, len);
2636 return (cursor + 1);
2640 static inline char* __ctsvc_get_content_value(char *val)
2644 temp = strchr(val, ':');
2650 RETVM_IF('\0' == *(temp) || '\r' == *(temp) || '\n' == *(temp),
2651 NULL, "Invalid vcard content");
2656 static char* __ctsvc_vcard_remove_escape_char(char *str)
2658 char *s = SAFE_STR(str);
2661 if (*s == '\\' && *(s+1)) {
2662 char *n = (char*)(s+1);
2678 case 0xA1: /* en/em backslash */
2679 if (*(n+1) && 0xAC == *(n+1)) {
2686 case 0x81: /* en/em backslash */
2687 if (*(n+1) && 0x5F == *(n+1)) {
2710 static inline int __ctsvc_vcard_get_display_name(ctsvc_list_s *name_list, char *val)
2715 char *first_name = NULL;
2716 char *last_name = NULL;
2717 contacts_record_h name;
2719 temp = __ctsvc_get_content_value(val);
2720 RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "vcard");
2722 contacts_list_get_count((contacts_list_h)name_list, &count);
2724 ret = contacts_record_create(_contacts_name._uri, &name);
2725 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create is Fail(%d)", ret);
2726 contacts_list_add((contacts_list_h)name_list, name);
2728 contacts_list_get_current_record_p((contacts_list_h)name_list, &name);
2731 ret = contacts_record_get_str_p(name, _contacts_name.first, &first_name);
2732 WARN_IF(ret != CONTACTS_ERROR_NONE, "contacts_record_get_str_p is Fail(%d)", ret);
2733 ret = contacts_record_get_str_p(name, _contacts_name.last, &last_name);
2734 WARN_IF(ret != CONTACTS_ERROR_NONE, "contacts_record_get_str_p is Fail(%d)", ret);
2736 if ((NULL == first_name || '\0' == *first_name) && (NULL == last_name || '\0' == *last_name))
2737 contacts_record_set_str(name, _contacts_name.first, __ctsvc_vcard_remove_escape_char(temp));
2739 return CONTACTS_ERROR_NONE;
2742 #define CTS_GET_MULTIPLE_COMPONENT(dest, src, src_temp, separator) \
2744 separator = false; \
2745 while (src_temp && *src_temp) { \
2746 if (*src_temp == ';') { \
2749 src = __ctsvc_vcard_remove_escape_char(src); \
2750 dest = SMART_STRDUP(src); \
2754 else if (*src_temp == '\\') {\
2760 if (false == separator && src && *src) { \
2761 src = __ctsvc_vcard_remove_escape_char(src); \
2762 dest = SMART_STRDUP(src); \
2766 static inline int __ctsvc_vcard_get_name(ctsvc_list_s *name_list, char *val)
2771 contacts_record_h name;
2773 start = __ctsvc_get_content_value(val);
2774 RETV_IF(NULL == start, CONTACTS_ERROR_NO_DATA);
2776 contacts_list_get_count((contacts_list_h)name_list, &count);
2778 ret = contacts_record_create(_contacts_name._uri, &name);
2779 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
2780 contacts_list_add((contacts_list_h)name_list, name);
2782 contacts_list_get_current_record_p((contacts_list_h)name_list, &name);
2785 contacts_record_set_str(name, _contacts_name.first, NULL); /* remove FN */
2788 bool separator = false;
2791 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_name_s*)name)->last, start, start_temp, separator);
2792 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_name_s*)name)->first, start, start_temp, separator);
2793 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_name_s*)name)->addition, start, start_temp, separator);
2794 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_name_s*)name)->prefix, start, start_temp, separator);
2795 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_name_s*)name)->suffix, start, start_temp, separator);
2797 ERR("invalid name type");
2800 return CONTACTS_ERROR_NONE;
2803 static inline int __ctsvc_vcard_get_phonetic_name(ctsvc_list_s *name_list, int type, char *val)
2808 const char separator = ';';
2809 contacts_record_h name;
2811 start = __ctsvc_get_content_value(val);
2812 RETV_IF(NULL == start, CONTACTS_ERROR_NO_DATA);
2814 contacts_list_get_count((contacts_list_h)name_list, &count);
2816 ret = contacts_record_create(_contacts_name._uri, &name);
2817 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
2818 contacts_list_add((contacts_list_h)name_list, name);
2820 contacts_list_get_current_record_p((contacts_list_h)name_list, &name);
2823 __ctsvc_strtok(start, separator);
2824 if (CTSVC_VCARD_VALUE_PHONETIC_FIRST_NAME == type)
2825 contacts_record_set_str(name, _contacts_name.phonetic_first, __ctsvc_vcard_remove_escape_char(start));
2826 else if (CTSVC_VCARD_VALUE_PHONETIC_MIDDLE_NAME == type)
2827 contacts_record_set_str(name, _contacts_name.phonetic_middle, __ctsvc_vcard_remove_escape_char(start));
2828 else if (CTSVC_VCARD_VALUE_PHONETIC_LAST_NAME == type)
2829 contacts_record_set_str(name, _contacts_name.phonetic_last, __ctsvc_vcard_remove_escape_char(start));
2831 return CONTACTS_ERROR_NONE;
2834 static inline int __ctsvc_vcard_get_nickname(ctsvc_list_s *nickname_list, char *val)
2836 int ret = CONTACTS_ERROR_NONE;
2840 const char *separator = ",";
2842 start = __ctsvc_get_content_value(val);
2843 RETV_IF(NULL == start, CONTACTS_ERROR_NO_DATA);
2845 temp = strtok_r(start, separator, &last);
2847 if ('\0' == *temp) continue;
2849 contacts_record_h nickname = NULL;
2850 ret = contacts_record_create(_contacts_nickname._uri, &nickname);
2851 if (ret < CONTACTS_ERROR_NONE) {
2852 GList *cursor = NULL;
2853 ERR("contacts_record_create() Fail(%d)", ret);
2854 for (cursor = nickname_list->records; cursor; cursor = cursor->next)
2855 contacts_record_destroy((contacts_record_h)(cursor->data), true);
2856 g_list_free(nickname_list->records);
2857 nickname_list->records = NULL;
2858 nickname_list->cursor = NULL;
2859 nickname_list->count = 0;
2862 contacts_record_set_str(nickname, _contacts_nickname.name, __ctsvc_vcard_remove_escape_char(start));
2863 contacts_list_add((contacts_list_h)nickname_list, nickname);
2865 temp = strtok_r(NULL, separator, &last);
2868 return CONTACTS_ERROR_NONE;
2871 static inline int __ctsvc_vcard_get_photo(contacts_record_h contact, ctsvc_list_s *image_list, char *prefix, char *val)
2877 char dest[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0};
2878 contacts_record_h image;
2881 temp = strchr(val, ':');
2882 RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "val is invalid");
2886 type = __ctsvc_vcard_get_image_type(prefix);
2888 buf = g_base64_decode(temp+1, &size);
2889 if ((0 == size) || (NULL == buf)) {
2891 return CONTACTS_ERROR_NONE;
2894 gettimeofday(&tv, NULL);
2895 ret = snprintf(dest, sizeof(dest), "%s/vcard-image-%ld%ld.%s",
2896 CTSVC_VCARD_IMAGE_LOCATION, tv.tv_sec, tv.tv_usec, __ctsvc_get_img_suffix(type));
2898 fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, 0660);
2900 /* LCOV_EXCL_START */
2902 ERR("System : open Fail(%d)", errno);
2903 return CONTACTS_ERROR_SYSTEM;
2904 /* LCOV_EXCL_STOP */
2908 ret = write(fd, buf, size);
2910 if (EINTR == errno) {
2913 ERR("write() Fail(%d)", errno);
2916 if (ENOSPC == errno)
2917 return CONTACTS_ERROR_FILE_NO_SPACE; /* No space */
2919 return CONTACTS_ERROR_SYSTEM; /* IO error */
2928 ret = contacts_record_create(_contacts_image._uri, &image);
2929 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
2931 contacts_record_set_str(image, _contacts_image.path, dest);
2932 ((ctsvc_image_s*)image)->is_vcard = true;
2934 contacts_list_add((contacts_list_h)image_list, image);
2936 /* _contacts_contact.image_thumbnail_path is a read-only property */
2937 ((ctsvc_contact_s*)contact)->image_thumbnail_path = strdup(dest);
2939 return CONTACTS_ERROR_NONE;
2943 static inline void __ctsvc_vcard_get_event_type(contacts_record_h event, char *val)
2945 int type = CONTACTS_EVENT_TYPE_OTHER;
2946 char *temp, *result, *last = NULL;
2947 char *lower, *lower_temp;
2949 temp = strtok_r(val, ";", &last);
2951 lower = strdup(temp);
2952 if (NULL == lower) {
2953 ERR("strdup() Fail");
2957 while (*lower_temp) {
2958 *lower_temp = tolower(*lower_temp);
2961 if (strstr(lower, "anniversary")) {
2962 type = CONTACTS_EVENT_TYPE_ANNIVERSARY;
2963 } else if ((result = strstr(lower, "x-"))) {
2964 type = CONTACTS_EVENT_TYPE_CUSTOM;
2965 contacts_record_set_str(event, _contacts_event.label, temp+(result-lower)+2);
2969 temp = strtok_r(NULL, ";", &last);
2971 contacts_record_set_int(event, _contacts_event.type, type);
2975 static inline int __ctsvc_vcard_get_event(ctsvc_list_s *event_list, int type, char *prefix, char *val)
2978 contacts_record_h event;
2979 char *dest, *src, *date;
2981 date = __ctsvc_get_content_value(val);
2984 return CONTACTS_ERROR_INVALID_PARAMETER;
2989 if ('0' <= *src && *src <= '9') {
2994 if (8 <= dest - date)
2998 if ('\0' == *date) {
2999 ERR("date(%d)", date);
3000 return CONTACTS_ERROR_INVALID_PARAMETER;
3003 ret = contacts_record_create(_contacts_event._uri, &event);
3004 if (ret < CONTACTS_ERROR_NONE) {
3005 ERR("contacts_record_create() Fail(%d)", ret);
3009 contacts_record_set_int(event, _contacts_event.date, atoi(date));
3011 if (CTSVC_VCARD_VALUE_BDAY == type)
3012 contacts_record_set_int(event, _contacts_event.type, CONTACTS_EVENT_TYPE_BIRTH);
3013 else if (CTSVC_VCARD_VALUE_X_ANNIVERSARY == type)
3014 contacts_record_set_int(event, _contacts_event.type, CONTACTS_EVENT_TYPE_ANNIVERSARY);
3015 else if (CTSVC_VCARD_VALUE_X_TIZEN_EVENT == type)
3016 __ctsvc_vcard_get_event_type(event, prefix);
3018 contacts_list_add((contacts_list_h)event_list, event);
3019 return CONTACTS_ERROR_NONE;
3023 static inline void __ctsvc_vcard_get_company_type(contacts_record_h company, char *val)
3025 char *temp, *result, *last = NULL;
3026 char *lower, *lower_temp;
3027 int type = CONTACTS_COMPANY_TYPE_OTHER;
3029 temp = strtok_r(val, ";", &last);
3031 lower = strdup(temp);
3032 if (NULL == lower) {
3033 ERR("strdup() Fail");
3037 while (*lower_temp) {
3038 *lower_temp = tolower(*lower_temp);
3042 result = strstr(lower, "work");
3044 type = CONTACTS_COMPANY_TYPE_WORK;
3046 result = strstr(lower, "x-");
3048 type = CONTACTS_COMPANY_TYPE_CUSTOM;
3049 contacts_record_set_str(company, _contacts_company.label, temp+(result-lower)+2);
3053 temp = strtok_r(NULL, ";", &last);
3055 contacts_record_set_int(company, _contacts_company.type, type);
3058 static contacts_record_h __ctsvc_vcard_get_company_empty_record(ctsvc_list_s *company_list, int property_id)
3060 contacts_record_h record_temp = NULL;
3061 contacts_record_h record = NULL;
3062 contacts_list_h list = (contacts_list_h)company_list;
3064 contacts_list_last(list);
3065 while (CONTACTS_ERROR_NONE == contacts_list_get_current_record_p(list, &record_temp)) {
3067 contacts_record_get_str_p(record_temp, property_id, &value);
3068 if (NULL == value) {
3069 record = record_temp;
3072 contacts_list_prev(list);
3078 static inline int __ctsvc_vcard_get_company_value(ctsvc_list_s *company_list, int property_id, char *val)
3081 contacts_record_h company;
3083 company = __ctsvc_vcard_get_company_empty_record(company_list, property_id);
3084 if (NULL == company) {
3085 int ret = contacts_record_create(_contacts_company._uri, &company);
3086 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3087 contacts_list_add((contacts_list_h)company_list, company);
3090 value = __ctsvc_get_content_value(val);
3091 RETV_IF(NULL == value, CONTACTS_ERROR_NO_DATA);
3093 contacts_record_set_str(company, property_id, __ctsvc_vcard_remove_escape_char(value));
3095 return CONTACTS_ERROR_NONE;
3098 static inline int __ctsvc_vcard_get_company(ctsvc_list_s *company_list, char *prefix, char *val)
3100 char *start, *depart;
3101 const char separator = ';';
3102 contacts_record_h company;
3104 company = __ctsvc_vcard_get_company_empty_record(company_list, _contacts_company.name);
3105 if (NULL == company) {
3106 int ret = contacts_record_create(_contacts_company._uri, &company);
3107 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3108 contacts_list_add((contacts_list_h)company_list, company);
3111 start = __ctsvc_get_content_value(val);
3112 RETV_IF(NULL == start, CONTACTS_ERROR_NO_DATA);
3114 depart = __ctsvc_strtok(start, separator);
3115 contacts_record_set_str(company, _contacts_company.name, __ctsvc_vcard_remove_escape_char(start));
3118 __ctsvc_strtok(depart, separator);
3119 contacts_record_set_str(company, _contacts_company.department, __ctsvc_vcard_remove_escape_char(depart));
3122 __ctsvc_vcard_get_company_type(company, prefix);
3124 return CONTACTS_ERROR_NONE;
3127 static inline int __ctsvc_vcard_get_company_logo(ctsvc_list_s *company_list, char *prefix, char *val)
3132 char dest[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0};
3134 contacts_record_h company;
3137 company = __ctsvc_vcard_get_company_empty_record(company_list, _contacts_company.logo);
3138 if (NULL == company) {
3139 ret = contacts_record_create(_contacts_company._uri, &company);
3140 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3141 contacts_list_add((contacts_list_h)company_list, company);
3144 temp = strchr(val, ':');
3145 RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "val is invalid");
3148 type = __ctsvc_vcard_get_image_type(prefix);
3150 buf = g_base64_decode(temp+1, &size);
3151 if ((0 == size) || (NULL == buf)) {
3153 return CONTACTS_ERROR_NONE;
3156 gettimeofday(&tv, NULL);
3157 ret = snprintf(dest, sizeof(dest), "%s/%d-%ld%ld-logo.%s", CTSVC_VCARD_IMAGE_LOCATION,
3158 getpid(), tv.tv_sec, tv.tv_usec, __ctsvc_get_img_suffix(type));
3160 fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, 0660);
3162 /* LCOV_EXCL_START */
3164 ERR("System : open Fail(%d)", errno);
3165 return CONTACTS_ERROR_SYSTEM;
3166 /* LCOV_EXCL_STOP */
3170 ret = write(fd, buf, size);
3172 if (EINTR == errno) {
3175 ERR("write() Fail(%d)", errno);
3178 if (ENOSPC == errno)
3179 return CONTACTS_ERROR_FILE_NO_SPACE; /* No space */
3181 return CONTACTS_ERROR_SYSTEM; /* IO error */
3190 ((ctsvc_company_s*)company)->is_vcard = true;
3191 contacts_record_set_str(company, _contacts_company.logo, dest);
3193 return CONTACTS_ERROR_NONE;
3196 static inline int __ctsvc_vcard_get_note(ctsvc_list_s *note_list, char *val)
3200 contacts_record_h note;
3202 ret = contacts_record_create(_contacts_note._uri, ¬e);
3203 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3204 contacts_list_add((contacts_list_h)note_list, note);
3206 temp = __ctsvc_get_content_value(val);
3207 RETV_IF(NULL == temp, CONTACTS_ERROR_NO_DATA);
3209 contacts_record_set_str(note, _contacts_note.note, __ctsvc_vcard_remove_escape_char(temp));
3211 return CONTACTS_ERROR_NONE;
3214 static inline int __ctsvc_vcard_get_time(char *val)
3221 while (*val && (*val < '0' || '9' < *val)) val++;
3225 if (4 <= i || *val < '0' || '9' < *val) break;
3228 ts.tm_year = atoi(tmp)-1900;
3231 while (*val && (*val < '0' || '9' < *val)) val++;
3235 if (2 <= i || *val < '0' || '9' < *val) break;
3238 ts.tm_mon = atoi(tmp)-1;
3241 while (*val && (*val < '0' || '9' < *val)) val++;
3245 if (2 <= i || *val < '0' || '9' < *val) break;
3248 ts.tm_mday = atoi(tmp);
3251 while (*val && (*val < '0' || '9' < *val)) val++;
3255 if (2 <= i || *val < '0' || '9' < *val) break;
3258 ts.tm_hour = atoi(tmp);
3261 while (*val && (*val < '0' || '9' < *val)) val++;
3265 if (2 <= i || *val < '0' || '9' < *val) break;
3268 ts.tm_min = atoi(tmp);
3271 while (*val && (*val < '0' || '9' < *val)) val++;
3275 if (2 <= i || *val < '0' || '9' < *val) break;
3278 ts.tm_sec = atoi(tmp);
3280 return (int)mktime(&ts);
3283 static inline void __ctsvc_vcard_get_url_type(contacts_record_h url, char *val)
3285 char *temp, *result, *last = NULL;
3286 char *lower, *lower_temp;
3287 int type = CONTACTS_URL_TYPE_OTHER;
3289 temp = strtok_r(val, ";", &last);
3291 lower = strdup(temp);
3292 if (NULL == lower) {
3293 ERR("strdup() Fail");
3297 while (*lower_temp) {
3298 *lower_temp = tolower(*lower_temp);
3301 result = strstr(lower, "home");
3302 if (result) type = CONTACTS_URL_TYPE_HOME;
3303 result = strstr(lower, "work");
3304 if (result) type = CONTACTS_URL_TYPE_WORK;
3305 result = strstr(lower, "x-");
3307 type = CONTACTS_URL_TYPE_CUSTOM;
3308 contacts_record_set_str(url, _contacts_url.label, temp+(result-lower)+2);
3312 temp = strtok_r(NULL, ";", &last);
3314 contacts_record_set_int(url, _contacts_url.type, type);
3317 static inline int __ctsvc_vcard_get_url(ctsvc_list_s *url_list, char *prefix, char *val)
3320 contacts_record_h url;
3323 temp = __ctsvc_get_content_value(val);
3324 RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "vcard");
3326 ret = contacts_record_create(_contacts_url._uri, &url);
3327 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3329 contacts_record_set_str(url, _contacts_url.url, __ctsvc_vcard_remove_escape_char(temp));
3330 __ctsvc_vcard_get_url_type(url, prefix);
3331 contacts_list_add((contacts_list_h)url_list, url);
3333 return CONTACTS_ERROR_NONE;
3336 static inline bool __ctsvc_vcard_get_number_type(contacts_record_h number, char *val)
3338 char *temp, *result, *last = NULL;
3339 char *lower, *lower_temp;
3340 int type = CONTACTS_NUMBER_TYPE_OTHER;
3343 temp = strtok_r(val, ";", &last);
3345 lower = strdup(temp);
3346 if (NULL == lower) {
3347 ERR("strdup() Fail");
3351 while (*lower_temp) {
3352 *lower_temp = tolower(*lower_temp);
3355 result = strstr(lower, "home");
3356 if (result) type |= CONTACTS_NUMBER_TYPE_HOME;
3357 result = strstr(lower, "msg");
3358 if (result) type |= CONTACTS_NUMBER_TYPE_MSG;
3359 result = strstr(lower, "work");
3360 if (result) type |= CONTACTS_NUMBER_TYPE_WORK;
3361 result = strstr(lower, "pref");
3362 if (result) pref = true;
3363 result = strstr(lower, "voice");
3364 if (result) type |= CONTACTS_NUMBER_TYPE_VOICE;
3365 result = strstr(lower, "fax");
3366 if (result) type |= CONTACTS_NUMBER_TYPE_FAX;
3367 result = strstr(lower, "cell");
3368 if (result) type |= CONTACTS_NUMBER_TYPE_CELL;
3369 result = strstr(lower, "video");
3370 if (result) type |= CONTACTS_NUMBER_TYPE_VIDEO;
3371 result = strstr(lower, "pager");
3372 if (result) type |= CONTACTS_NUMBER_TYPE_PAGER;
3373 result = strstr(lower, "bbs");
3374 if (result) type |= CONTACTS_NUMBER_TYPE_BBS;
3375 result = strstr(lower, "modem");
3376 if (result) type |= CONTACTS_NUMBER_TYPE_MODEM;
3377 result = strstr(lower, "car");
3378 if (result) type |= CONTACTS_NUMBER_TYPE_CAR;
3379 result = strstr(lower, "isdn");
3380 if (result) type |= CONTACTS_NUMBER_TYPE_ISDN;
3381 result = strstr(lower, "pcs");
3382 if (result) type |= CONTACTS_NUMBER_TYPE_PCS;
3383 result = strstr(lower, "x-");
3385 if (strstr(lower, "x-assistant")) {
3386 type |= CONTACTS_NUMBER_TYPE_ASSISTANT;
3387 } else if (strstr(lower, "x-radio")) {
3388 type |= CONTACTS_NUMBER_TYPE_RADIO;
3389 } else if (strstr(lower, "x-company-main")) {
3390 type |= CONTACTS_NUMBER_TYPE_COMPANY_MAIN;
3391 } else if (strstr(lower, "x-main")) {
3392 type |= CONTACTS_NUMBER_TYPE_MAIN;
3394 type = CONTACTS_NUMBER_TYPE_CUSTOM;
3395 contacts_record_set_str(number, _contacts_number.label, temp+(result-lower)+2);
3400 temp = strtok_r(NULL, ";", &last);
3402 contacts_record_set_int(number, _contacts_number.type, type);
3407 static char* __ctsvc_vcard_get_clean_number_for_import(char *str)
3410 char *s = SAFE_STR(str);
3413 char_len = __ctsvc_vcard_check_utf8(*s);
3414 if (3 == char_len) {
3416 if (*(s+1) == 0xbc) {
3417 if (0x90 <= *(s+2) && *(s+2) <= 0x99) { /* ef bc 90 : '0' ~ ef bc 99 : '9' */
3418 *r = '0' + (*(s+2) - 0x90);
3421 } else if (0x8b == *(s+2)) { /* ef bc 8b : '+' */
3425 } else if (0x8a == *(s+2)) { /* ef bc 8a : '*' */
3429 } else if (0x83 == *(s+2)) { /* ef bc 83 : '#' */
3433 } else if (0xb0 == *(s+2) || 0x8c == *(s+2)) { /* ef bc b0 : 'P', ef bc 8c : ',' */
3437 } else if (0xb7 == *(s+2) || 0x9b == *(s+2)) { /* ef bc b7 : 'W', ef bc 9b : ';' */
3444 } else if (*(s+1) == 0xbd) {
3445 if (0x90 == *(s+2)) {
3449 } else if (0x97 == *(s+2)) {
3460 } else if (1 == char_len) {
3514 static inline int __ctsvc_vcard_get_number(ctsvc_list_s *numbers, char *prefix, char *val)
3519 contacts_record_h number;
3521 temp = __ctsvc_get_content_value(val);
3522 RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "vcard");
3524 ret = contacts_record_create(_contacts_number._uri, &number);
3525 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3527 temp = __ctsvc_vcard_remove_escape_char(temp);
3528 contacts_record_set_str(number, _contacts_number.number, __ctsvc_vcard_get_clean_number_for_import(temp));
3530 is_default = __ctsvc_vcard_get_number_type(number, prefix);
3531 contacts_record_set_bool(number, _contacts_number.is_default, is_default);
3532 contacts_list_add((contacts_list_h)numbers, number);
3534 return CONTACTS_ERROR_NONE;
3537 static inline bool __ctsvc_vcard_get_email_type(contacts_record_h email, char *val)
3539 char *temp, *result, *last = NULL;
3540 char *lower, *lower_temp;
3541 int type = CONTACTS_EMAIL_TYPE_OTHER;
3544 temp = strtok_r(val, ";", &last);
3546 lower = strdup(temp);
3547 if (NULL == lower) {
3548 ERR("strdup() Fail");
3552 while (*lower_temp) {
3553 *lower_temp = tolower(*lower_temp);
3556 if (strstr(lower, "pref"))
3559 if (strstr(lower, "home")) {
3560 type = CONTACTS_EMAIL_TYPE_HOME;
3561 } else if (strstr(lower, "work")) {
3562 type = CONTACTS_EMAIL_TYPE_WORK;
3563 } else if (strstr(lower, "cell")) {
3564 type = CONTACTS_EMAIL_TYPE_MOBILE;
3565 } else if ((result = strstr(lower, "x-"))) {
3566 type = CONTACTS_EMAIL_TYPE_CUSTOM;
3567 contacts_record_set_str(email, _contacts_email.label, temp+(result-lower)+2);
3571 temp = strtok_r(NULL, ";", &last);
3573 contacts_record_set_int(email, _contacts_email.type, type);
3578 static inline int __ctsvc_vcard_get_email(ctsvc_list_s *emails, char *prefix, char *val)
3583 contacts_record_h email;
3585 temp = __ctsvc_get_content_value(val);
3586 RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "vcard");
3588 ret = contacts_record_create(_contacts_email._uri, &email);
3589 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3591 contacts_record_set_str(email, _contacts_email.email, __ctsvc_vcard_remove_escape_char(temp));
3592 is_default = __ctsvc_vcard_get_email_type(email, prefix);
3593 contacts_record_set_bool(email, _contacts_email.is_default, is_default);
3594 contacts_list_add((contacts_list_h)emails, email);
3596 return CONTACTS_ERROR_NONE;
3599 static inline bool __ctsvc_vcard_get_postal_type(contacts_record_h address, char *val)
3601 char *temp, *result, *last = NULL;
3602 char *lower, *lower_temp;
3603 int type = CONTACTS_ADDRESS_TYPE_OTHER;
3606 temp = strtok_r(val, ";", &last);
3608 lower = strdup(temp);
3609 if (NULL == lower) {
3610 ERR("strdup() Fail");
3614 while (*lower_temp) {
3615 *lower_temp = tolower(*lower_temp);
3618 result = strstr(lower, "dom");
3619 if (result) type |= CONTACTS_ADDRESS_TYPE_DOM;
3620 result = strstr(lower, "intl");
3621 if (result) type |= CONTACTS_ADDRESS_TYPE_INTL;
3622 result = strstr(lower, "address");
3623 if (result) type |= CONTACTS_ADDRESS_TYPE_POSTAL;
3624 result = strstr(lower, "parcel");
3625 if (result) type |= CONTACTS_ADDRESS_TYPE_PARCEL;
3626 result = strstr(lower, "home");
3627 if (result) type |= CONTACTS_ADDRESS_TYPE_HOME;
3628 result = strstr(lower, "work");
3629 if (result) type |= CONTACTS_ADDRESS_TYPE_WORK;
3630 result = strstr(lower, "x-");
3632 type = CONTACTS_ADDRESS_TYPE_CUSTOM;
3633 contacts_record_set_str(address, _contacts_address.label, temp+(result-lower)+2);
3635 result = strstr(val, "pref");
3636 if (result) pref = true;
3639 temp = strtok_r(NULL, ";", &last);
3642 contacts_record_set_int(address, _contacts_address.type, type);
3647 static inline int __ctsvc_vcard_get_address(ctsvc_list_s *address_list, char *prefix, char *val)
3651 contacts_record_h address;
3653 contacts_record_create(_contacts_address._uri, &address);
3656 text = strchr(val, ':');
3665 bool separator = false;
3667 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_address_s*)address)->pobox, text, text_temp, separator);
3668 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_address_s*)address)->extended, text, text_temp, separator);
3669 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_address_s*)address)->street, text, text_temp, separator);
3670 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_address_s*)address)->locality, text, text_temp, separator);
3671 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_address_s*)address)->region, text, text_temp, separator);
3672 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_address_s*)address)->postalcode, text, text_temp, separator);
3673 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_address_s*)address)->country, text, text_temp, separator);
3675 ERR("invalid ADR type");
3678 if (((ctsvc_address_s*)address)->pobox || ((ctsvc_address_s*)address)->extended
3679 || ((ctsvc_address_s*)address)->street || ((ctsvc_address_s*)address)->locality
3680 || ((ctsvc_address_s*)address)->region || ((ctsvc_address_s*)address)->postalcode
3681 || ((ctsvc_address_s*)address)->country) {
3682 contacts_record_set_bool(address, _contacts_address.is_default, __ctsvc_vcard_get_postal_type(address, prefix));
3684 ERR("Invalid vcard");
3685 contacts_record_destroy(address, true);
3686 return CONTACTS_ERROR_INVALID_PARAMETER;
3688 contacts_list_add((contacts_list_h)address_list, address);
3691 return CONTACTS_ERROR_NONE;
3694 static inline void __ctsvc_vcard_get_messenger_type(contacts_record_h messenger, char *val)
3696 char *temp, *result, *last = NULL;
3697 char *lower, *lower_temp;
3698 int type = CONTACTS_MESSENGER_TYPE_OTHER;
3700 temp = strtok_r(val, ";", &last);
3702 lower = strdup(temp);
3703 if (NULL == lower) {
3704 ERR("strdup() Fail");
3708 while (*lower_temp) {
3709 *lower_temp = tolower(*lower_temp);
3712 result = strstr(lower, "facebook");
3713 if (result) type = CONTACTS_MESSENGER_TYPE_FACEBOOK;
3714 result = strstr(lower, "irc");
3715 if (result) type = CONTACTS_MESSENGER_TYPE_IRC;
3716 result = strstr(lower, "x-");
3718 type = CONTACTS_MESSENGER_TYPE_CUSTOM;
3719 contacts_record_set_str(messenger, _contacts_messenger.label, temp+(result-lower)+2);
3722 temp = strtok_r(NULL, ";", &last);
3724 contacts_record_set_int(messenger, _contacts_messenger.type, type);
3727 static inline int __ctsvc_vcard_get_messenger(ctsvc_list_s *messenger_list, int type, char *prefix, char *val)
3730 contacts_record_h messenger;
3733 temp = __ctsvc_get_content_value(val);
3734 RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "vcard");
3736 ret = contacts_record_create(_contacts_messenger._uri, &messenger);
3737 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3739 contacts_record_set_str(messenger, _contacts_messenger.im_id, __ctsvc_vcard_remove_escape_char(temp));
3742 case CTSVC_VCARD_VALUE_X_MSN:
3743 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_WLM);
3745 case CTSVC_VCARD_VALUE_X_YAHOO:
3746 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_YAHOO);
3748 case CTSVC_VCARD_VALUE_X_ICQ:
3749 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_ICQ);
3751 case CTSVC_VCARD_VALUE_X_AIM:
3752 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_AIM);
3754 case CTSVC_VCARD_VALUE_X_JABBER:
3755 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_JABBER);
3757 case CTSVC_VCARD_VALUE_X_SKYPE_USERNAME:
3758 case CTSVC_VCARD_VALUE_X_SKYPE:
3759 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_SKYPE);
3761 case CTSVC_VCARD_VALUE_X_QQ:
3762 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_QQ);
3764 case CTSVC_VCARD_VALUE_X_GOOGLE_TALK:
3765 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_GOOGLE);
3767 case CTSVC_VCARD_VALUE_X_TIZEN_MESSENGER:
3768 __ctsvc_vcard_get_messenger_type(messenger, prefix);
3771 contacts_list_add((contacts_list_h)messenger_list, messenger);
3773 return CONTACTS_ERROR_NONE;
3776 static inline void __ctsvc_vcard_get_relationship_type(contacts_record_h relationship, char *val)
3778 char *temp, *result, *last = NULL;
3779 char *lower, *lower_temp;
3780 int type = CONTACTS_RELATIONSHIP_TYPE_OTHER;
3782 temp = strtok_r(val, ";", &last);
3784 lower = strdup(temp);
3785 if (NULL == lower) {
3786 ERR("strdup() Fail");
3790 while (*lower_temp) {
3791 *lower_temp = tolower(*lower_temp);
3795 if (strstr(lower, "assistant")) {
3796 type = CONTACTS_RELATIONSHIP_TYPE_ASSISTANT;
3797 } else if (strstr(lower, "brother")) {
3798 type = CONTACTS_RELATIONSHIP_TYPE_BROTHER;
3799 } else if (strstr(lower, "child")) {
3800 type = CONTACTS_RELATIONSHIP_TYPE_CHILD;
3801 } else if (strstr(lower, "domestic_partner")) {
3802 type = CONTACTS_RELATIONSHIP_TYPE_DOMESTIC_PARTNER;
3803 } else if (strstr(lower, "father")) {
3804 type = CONTACTS_RELATIONSHIP_TYPE_FATHER;
3805 } else if (strstr(lower, "friend")) {
3806 type = CONTACTS_RELATIONSHIP_TYPE_FRIEND;
3807 } else if (strstr(lower, "manager")) {
3808 type = CONTACTS_RELATIONSHIP_TYPE_MANAGER;
3809 } else if (strstr(lower, "mother")) {
3810 type = CONTACTS_RELATIONSHIP_TYPE_MOTHER;
3811 } else if (strstr(lower, "parent")) {
3812 type = CONTACTS_RELATIONSHIP_TYPE_PARENT;
3813 } else if (strstr(lower, "partner")) {
3814 type = CONTACTS_RELATIONSHIP_TYPE_PARTNER;
3815 } else if (strstr(lower, "referred_by")) {
3816 type = CONTACTS_RELATIONSHIP_TYPE_REFERRED_BY;
3817 } else if (strstr(lower, "relative")) {
3818 type = CONTACTS_RELATIONSHIP_TYPE_RELATIVE;
3819 } else if (strstr(lower, "sister")) {
3820 type = CONTACTS_RELATIONSHIP_TYPE_SISTER;
3821 } else if (strstr(lower, "spouse")) {
3822 type = CONTACTS_RELATIONSHIP_TYPE_SPOUSE;
3823 } else if ((result = strstr(lower, "x-"))) {
3824 type = CONTACTS_RELATIONSHIP_TYPE_CUSTOM;
3825 contacts_record_set_str(relationship, _contacts_relationship.label, temp+(result-lower)+2);
3828 temp = strtok_r(NULL, ";", &last);
3830 contacts_record_set_int(relationship, _contacts_relationship.type, type);
3834 static inline int __ctsvc_vcard_get_relationship(ctsvc_list_s *relationship_list, int type, char *prefix, char *val)
3838 contacts_record_h relationship;
3840 temp = __ctsvc_get_content_value(val);
3841 RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "vcard");
3843 ret = contacts_record_create(_contacts_relationship._uri, &relationship);
3844 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3846 contacts_record_set_str(relationship, _contacts_relationship.name, __ctsvc_vcard_remove_escape_char(temp));
3847 __ctsvc_vcard_get_relationship_type(relationship, prefix);
3848 contacts_list_add((contacts_list_h)relationship_list, relationship);
3850 return CONTACTS_ERROR_NONE;
3854 static char* __ctsvc_vcard_decode_base64_val(char *val)
3857 guchar *decoded_str;
3861 src = strchr(val, ':');
3867 decoded_str = g_base64_decode(src, &size);
3869 dest = calloc((src-val)+size+1, sizeof(char));
3871 g_free(decoded_str);
3872 ERR("calloc() Fail");
3876 snprintf(dest, (src-val)+1, "%s", val);
3877 snprintf(dest+(src-val), size+1, "%s", decoded_str);
3878 g_free(decoded_str);
3883 static inline int __ctsvc_vcard_get_contact(int ver, char *vcard, contacts_record_h *record)
3886 char *cursor, *new_start, *val, *prefix;
3887 ctsvc_contact_s *contact = (ctsvc_contact_s*)*record;
3894 bool base64_encoded = false;
3895 type = __ctsvc_vcard_check_content_type(&cursor);
3896 if (CTSVC_VCARD_VALUE_NONE == type) {
3897 new_start = __ctsvc_vcard_pass_unsupported(cursor);
3906 if (CTSVC_VCARD_VALUE_PHOTO != type && CTSVC_VCARD_VALUE_LOGO != type)
3907 base64_encoded = __ctsvc_vcard_check_base64_encoded(cursor);
3909 new_start = __ctsvc_vcard_get_val(ver, cursor, &prefix, &val);
3910 if (NULL == new_start) {
3925 if (base64_encoded) {
3926 char *temp = __ctsvc_vcard_decode_base64_val(val);
3928 /* LCOV_EXCL_START */
3929 ERR("__ctsvc_vcard_decode_base64_val() Fail");
3932 return CONTACTS_ERROR_OUT_OF_MEMORY;
3933 /* LCOV_EXCL_STOP */
3940 case CTSVC_VCARD_VALUE_FN:
3941 __ctsvc_vcard_get_display_name(contact->name, val);
3943 case CTSVC_VCARD_VALUE_N:
3944 __ctsvc_vcard_get_name(contact->name, val);
3946 case CTSVC_VCARD_VALUE_PHONETIC_FIRST_NAME:
3947 case CTSVC_VCARD_VALUE_PHONETIC_MIDDLE_NAME:
3948 case CTSVC_VCARD_VALUE_PHONETIC_LAST_NAME:
3949 __ctsvc_vcard_get_phonetic_name(contact->name, type, val);
3951 case CTSVC_VCARD_VALUE_NICKNAME:
3952 __ctsvc_vcard_get_nickname(contact->nicknames, val);
3954 case CTSVC_VCARD_VALUE_PHOTO:
3955 __ctsvc_vcard_get_photo(*record, contact->images, prefix, val);
3957 case CTSVC_VCARD_VALUE_BDAY:
3958 case CTSVC_VCARD_VALUE_X_ANNIVERSARY:
3959 case CTSVC_VCARD_VALUE_X_TIZEN_EVENT:
3960 __ctsvc_vcard_get_event(contact->events, type, prefix, val);
3962 case CTSVC_VCARD_VALUE_ADR:
3963 __ctsvc_vcard_get_address(contact->postal_addrs, prefix, val);
3965 case CTSVC_VCARD_VALUE_TEL:
3966 __ctsvc_vcard_get_number(contact->numbers, prefix, val);
3968 case CTSVC_VCARD_VALUE_EMAIL:
3969 __ctsvc_vcard_get_email(contact->emails, prefix, val);
3971 case CTSVC_VCARD_VALUE_TITLE:
3972 __ctsvc_vcard_get_company_value(contact->company, _contacts_company.job_title, val);
3974 case CTSVC_VCARD_VALUE_ROLE:
3975 __ctsvc_vcard_get_company_value(contact->company, _contacts_company.role, val);
3977 case CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_LOCATION:
3978 __ctsvc_vcard_get_company_value(contact->company, _contacts_company.location, val);
3980 case CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_DESCRIPTION:
3981 __ctsvc_vcard_get_company_value(contact->company, _contacts_company.description, val);
3983 case CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_PHONETIC_NAME:
3984 __ctsvc_vcard_get_company_value(contact->company, _contacts_company.phonetic_name, val);
3986 case CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_ASSISTANT_NAME:
3987 __ctsvc_vcard_get_company_value(contact->company, _contacts_company.assistant_name, val);
3989 case CTSVC_VCARD_VALUE_LOGO:
3990 __ctsvc_vcard_get_company_logo(contact->company, prefix, val);
3992 case CTSVC_VCARD_VALUE_ORG:
3993 __ctsvc_vcard_get_company(contact->company, prefix, val);
3995 case CTSVC_VCARD_VALUE_NOTE:
3996 __ctsvc_vcard_get_note(contact->note, val);
3998 case CTSVC_VCARD_VALUE_REV:
4000 contact->changed_time = __ctsvc_vcard_get_time(val);
4002 case CTSVC_VCARD_VALUE_UID:
4003 contacts_record_set_str((contacts_record_h)contact, _contacts_contact.uid, __ctsvc_vcard_remove_escape_char(val));
4005 case CTSVC_VCARD_VALUE_URL:
4006 __ctsvc_vcard_get_url(contact->urls, prefix, val);
4008 case CTSVC_VCARD_VALUE_X_MSN:
4009 case CTSVC_VCARD_VALUE_X_YAHOO:
4010 case CTSVC_VCARD_VALUE_X_ICQ:
4011 case CTSVC_VCARD_VALUE_X_AIM:
4012 case CTSVC_VCARD_VALUE_X_JABBER:
4013 case CTSVC_VCARD_VALUE_X_SKYPE_USERNAME:
4014 case CTSVC_VCARD_VALUE_X_SKYPE:
4015 case CTSVC_VCARD_VALUE_X_QQ:
4016 case CTSVC_VCARD_VALUE_X_GOOGLE_TALK:
4017 case CTSVC_VCARD_VALUE_X_TIZEN_MESSENGER:
4018 __ctsvc_vcard_get_messenger(contact->messengers, type, prefix, val);
4021 case CTSVC_VCARD_VALUE_X_TIZEN_RELATIONSHIP:
4022 __ctsvc_vcard_get_relationship(contact->relationships, type, prefix, val);
4024 case CTSVC_VCARD_VALUE_END:
4027 return CONTACTS_ERROR_NONE;
4029 ERR("__ctsvc_vcard_check_content_type() Fail(%d)", type);
4032 return CONTACTS_ERROR_INVALID_PARAMETER;
4039 ERR("Invalid vcard");
4040 return CONTACTS_ERROR_INVALID_PARAMETER;
4043 static inline int __ctsvc_vcard_check_version(const char *src)
4046 const char *ver3 = "3.0";
4052 return CTSVC_VCARD_VER_2_1;
4063 if (STRING_EQUAL == strcmp(src, ver3))
4064 return CTSVC_VCARD_VER_3_0;
4066 return CTSVC_VCARD_VER_2_1;
4069 static inline void __ctsvc_vcard_make_contact_display_name(ctsvc_contact_s *contact)
4071 ctsvc_name_s *name = NULL;
4073 free(contact->display_name);
4074 contact->display_name = NULL;
4076 free(contact->reverse_display_name);
4077 contact->reverse_display_name = NULL;
4079 if (0 < contact->name->count && contact->name->records
4080 && contact->name->records->data) {
4081 name = (ctsvc_name_s*)contact->name->records->data;
4084 if (name && (name->first || name->last || name->prefix || name->addition
4086 int reverse_lang_type = -1;
4087 char *display = NULL;
4088 char *reverse_display = NULL;
4089 int len, display_len;
4090 int temp_display_len;
4091 char *temp_display = NULL;
4092 contacts_name_display_order_e name_display_order = CONTACTS_NAME_DISPLAY_ORDER_FIRSTLAST;
4095 * Make reverse display name (Last name first)
4096 * Default : Prefix Last, First Middle(addition), Suffix
4097 * Korean, Chinese : Prefix LastFirstMiddleSuffix
4098 * Japanese : Prefix Last Middle First Suffix
4099 * reverse sort name does not include prefix
4100 * But, if there is only prefix, reverse sort_name is prefix
4102 temp_display_len = SAFE_STRLEN(name->first)
4103 + SAFE_STRLEN(name->addition)
4104 + SAFE_STRLEN(name->last)
4105 + SAFE_STRLEN(name->suffix);
4106 if (0 < temp_display_len) {
4107 temp_display_len += 7;
4108 temp_display = calloc(1, temp_display_len);
4109 if (NULL == temp_display) {
4110 ERR("calloc() Fail");
4117 len += snprintf(temp_display + len, temp_display_len - len, "%s", name->last);
4119 if (reverse_lang_type < 0)
4120 reverse_lang_type = ctsvc_check_language_type(temp_display);
4122 if (reverse_lang_type != CTSVC_LANG_KOREAN &&
4123 reverse_lang_type != CTSVC_LANG_CHINESE &&
4124 reverse_lang_type != CTSVC_LANG_JAPANESE) {
4125 if (name->first || name->addition)
4126 len += snprintf(temp_display + len, temp_display_len - len, ",");
4130 if (reverse_lang_type < 0) {
4132 reverse_lang_type = ctsvc_check_language_type(temp_display);
4133 else if (name->first)
4134 reverse_lang_type = ctsvc_check_language_type(name->first);
4135 else if (name->addition)
4136 reverse_lang_type = ctsvc_check_language_type(name->addition);
4139 if (reverse_lang_type == CTSVC_LANG_JAPANESE) {
4140 /* make temp_display name Prefix - Last - Middle - First - Suffix */
4141 if (name->addition) {
4143 len += snprintf(temp_display + len, temp_display_len - len, " ");
4144 len += snprintf(temp_display + len, temp_display_len - len, "%s", name->addition);
4149 len += snprintf(temp_display + len, temp_display_len - len, " ");
4150 len += snprintf(temp_display + len, temp_display_len - len, "%s", name->first);
4153 /* make temp_display name Prefix - Last - First -Middle - Suffix */
4155 if (*temp_display) {
4156 if (reverse_lang_type < 0)
4157 reverse_lang_type = ctsvc_check_language_type(temp_display);
4159 if (reverse_lang_type != CTSVC_LANG_KOREAN &&
4160 reverse_lang_type != CTSVC_LANG_CHINESE)
4161 len += snprintf(temp_display + len, temp_display_len - len, " ");
4163 len += snprintf(temp_display + len, temp_display_len - len, "%s", name->first);
4166 if (name->addition) {
4167 if (*temp_display) {
4168 if (reverse_lang_type < 0)
4169 reverse_lang_type = ctsvc_check_language_type(temp_display);
4171 if (reverse_lang_type != CTSVC_LANG_KOREAN &&
4172 reverse_lang_type != CTSVC_LANG_CHINESE)
4173 len += snprintf(temp_display + len, temp_display_len - len, " ");
4175 len += snprintf(temp_display + len, temp_display_len - len, "%s", name->addition);
4180 if (*temp_display) {
4181 if (reverse_lang_type < 0)
4182 reverse_lang_type = ctsvc_check_language_type(temp_display);
4184 if (reverse_lang_type == CTSVC_LANG_JAPANESE) {
4185 len += snprintf(temp_display + len, temp_display_len - len, " ");
4186 } else if (reverse_lang_type != CTSVC_LANG_KOREAN &&
4187 reverse_lang_type != CTSVC_LANG_CHINESE) {
4188 len += snprintf(temp_display + len, temp_display_len - len, ", ");
4191 len += snprintf(temp_display + len, temp_display_len - len, "%s", name->suffix);
4195 if (name->prefix && temp_display) {
4196 display_len = SAFE_STRLEN(name->prefix) + temp_display_len + 2;
4197 reverse_display = calloc(1, display_len);
4198 if (NULL == reverse_display) {
4199 ERR("calloc() Fail");
4203 snprintf(reverse_display, display_len, "%s %s", name->prefix, temp_display);
4205 } else if (temp_display) {
4206 reverse_display = temp_display;
4207 } else if (name->prefix) {
4208 reverse_display = strdup(name->prefix);
4212 * Make display name (First name first)
4213 * Default : Prefix First Middle Last, Suffix
4214 * Korean, Chinese : Prefix LastFirstMiddleSuffix (Same as reverse display name)
4215 * Japanese : Prefix First Middle Last Suffix
4216 * sort name does not include prefix
4217 * But, if there is only prefix, sort_name is prefix
4220 if (reverse_lang_type == CTSVC_LANG_KOREAN ||
4221 reverse_lang_type == CTSVC_LANG_CHINESE) {
4222 display = strdup(reverse_display);
4225 temp_display = NULL;
4226 temp_display_len = SAFE_STRLEN(name->first)
4227 + SAFE_STRLEN(name->addition)
4228 + SAFE_STRLEN(name->last)
4229 + SAFE_STRLEN(name->suffix);
4230 if (0 < temp_display_len) {
4231 temp_display_len += 6;
4232 /* make reverse_temp_display_name */
4233 temp_display = calloc(1, temp_display_len);
4234 if (NULL == temp_display) {
4235 ERR("calloc() Fail");
4236 free(reverse_display);
4244 len += snprintf(temp_display + len, temp_display_len - len, " ");
4245 len += snprintf(temp_display + len, temp_display_len - len, "%s", name->first);
4248 if (name->addition) {
4250 len += snprintf(temp_display + len, temp_display_len - len, " ");
4251 len += snprintf(temp_display + len, temp_display_len - len, "%s", name->addition);
4256 len += snprintf(temp_display + len, temp_display_len - len, " ");
4257 len += snprintf(temp_display + len, temp_display_len - len, "%s", name->last);
4261 if (*temp_display) {
4262 lang_type = ctsvc_check_language_type(temp_display);
4263 if (lang_type == CTSVC_LANG_JAPANESE)
4264 len += snprintf(temp_display + len, temp_display_len - len, " ");
4266 len += snprintf(temp_display + len, temp_display_len - len, ", ");
4268 len += snprintf(temp_display + len, temp_display_len - len, "%s", name->suffix);
4272 if (name->prefix && temp_display) {
4273 display_len = SAFE_STRLEN(name->prefix) + temp_display_len + 2;
4274 display = calloc(1, display_len);
4275 if (NULL == display) {
4276 ERR("calloc() Fail");
4278 free(reverse_display);
4281 snprintf(display, display_len, "%s %s", name->prefix, temp_display);
4283 } else if (temp_display) {
4284 display = temp_display;
4285 } else if (name->prefix) {
4286 display = strdup(name->prefix);
4290 #ifdef _CONTACTS_IPC_CLIENT
4291 contacts_setting_get_name_display_order(&name_display_order);
4293 if (CONTACTS_NAME_DISPLAY_ORDER_FIRSTLAST == name_display_order) {
4294 contact->display_name = display;
4295 free(reverse_display);
4296 #ifdef _CONTACTS_IPC_CLIENT
4298 contact->display_name = reverse_display;
4302 contact->display_source_type = CONTACTS_DISPLAY_NAME_SOURCE_TYPE_NAME;
4305 bool set_display_name = false;
4306 if (contact->company && contact->company->records) {
4307 for (cur = contact->company->records; cur; cur = cur->next) {
4308 ctsvc_company_s *company = cur->data;
4309 if (company && company->name) {
4310 set_display_name = true;
4311 contact->display_name = SAFE_STRDUP(company->name);
4312 contact->display_source_type = CONTACTS_DISPLAY_NAME_SOURCE_TYPE_COMPANY;
4318 if (false == set_display_name &&
4319 contact->nicknames && contact->nicknames->records) {
4320 for (cur = contact->nicknames->records; cur; cur = cur->next) {
4321 ctsvc_nickname_s *nickname = cur->data;
4322 if (nickname && nickname->nickname) {
4323 set_display_name = true;
4324 contact->display_name = SAFE_STRDUP(nickname->nickname);
4325 contact->display_source_type = CONTACTS_DISPLAY_NAME_SOURCE_TYPE_NICKNAME;
4331 if (false == set_display_name &&
4332 contact->numbers && contact->numbers->records) {
4333 for (cur = contact->numbers->records; cur; cur = cur->next) {
4334 ctsvc_number_s *number = cur->data;
4335 if (number && number->number) {
4336 set_display_name = true;
4337 contact->display_name = SAFE_STRDUP(number->number);
4338 contact->display_source_type = CONTACTS_DISPLAY_NAME_SOURCE_TYPE_NUMBER;
4344 if (false == set_display_name &&
4345 contact->emails && contact->emails->records) {
4346 for (cur = contact->emails->records; cur; cur = cur->next) {
4347 ctsvc_email_s *email = cur->data;
4348 if (email && email->email_addr) {
4349 set_display_name = true;
4350 contact->display_name = SAFE_STRDUP(email->email_addr);
4351 contact->display_source_type = CONTACTS_DISPLAY_NAME_SOURCE_TYPE_EMAIL;
4360 static void __ctsvc_vcard_update_contact_has_properties(ctsvc_contact_s *contact)
4362 if (contact->numbers && 0 < contact->numbers->count)
4363 contact->has_phonenumber = true;
4365 if (contact->emails && 0 < contact->emails->count)
4366 contact->has_email = true;
4369 static int __ctsvc_vcard_parse(const void *vcard_stream, contacts_record_h *record)
4372 ctsvc_contact_s *contact;
4373 char *val_begin, *new_start, *val;
4374 char *vcard = (char *)vcard_stream;
4376 RETV_IF(NULL == vcard_stream, CONTACTS_ERROR_INVALID_PARAMETER);
4378 __ctsvc_vcard_initial();
4380 vcard = __ctsvc_vcard_check_word(vcard, "BEGIN:VCARD");
4381 RETVM_IF(NULL == vcard, CONTACTS_ERROR_INVALID_PARAMETER, "The vcard is invalid.");
4383 val_begin = __ctsvc_vcard_check_word(vcard, "VERSION:");
4384 new_start = __ctsvc_vcard_get_val(CTSVC_VCARD_VER_NONE, val_begin, NULL, &val);
4385 if (NULL == new_start || NULL == val) {
4386 ver = CTSVC_VCARD_VER_2_1;
4388 ver = __ctsvc_vcard_check_version(val);
4393 contacts_record_create(_contacts_contact._uri, (contacts_record_h*)&contact);
4394 RETVM_IF(NULL == contact, CONTACTS_ERROR_OUT_OF_MEMORY, "Out of memory : contacts_record_create() Fail");
4396 ret = __ctsvc_vcard_get_contact(ver, vcard, (contacts_record_h*)&contact);
4397 if (CONTACTS_ERROR_NONE != ret) {
4398 ERR("cts_vcard_get_contact() Fail(%d)", ret);
4399 contacts_record_destroy((contacts_record_h)contact, true);
4402 __ctsvc_vcard_make_contact_display_name(contact);
4403 __ctsvc_vcard_update_contact_has_properties(contact);
4404 *record = (contacts_record_h)contact;
4405 return CONTACTS_ERROR_NONE;
4408 #define CTSVC_VCARD_MAX_SIZE 1024*1024
4410 static const char* __contacts_vcard_remove_line_break(const char *c)
4413 if ('\r' == *c && '\n' == *(c+1))
4415 else if ('\n' == *c)
4424 const char *pos_start;
4425 const char *pos_end;
4428 static void __contacts_vcard_free_sub_vcard_info_list(GList *list)
4434 for (cursor = list; cursor; cursor = cursor->next) {
4435 sub_vcard_info_s *vcard_info = cursor->data;
4441 static void __contacts_vcard_free_vcard_object_list(GList *list)
4447 for (cursor = list; cursor; cursor = cursor->next) {
4448 char *vcard_object = cursor->data;
4455 static const char* __contacts_vcard_parse_get_vcard_object(const char *cursor, GList **plist_vcard_object)
4457 char *vcard_object = NULL;
4458 bool new_line = false;
4459 const char *begin = "BEGIN:VCARD";
4460 const char *end = "END:VCARD";
4461 const char *vcard_start_cursor = cursor;
4462 const char *vcard_cursor = NULL;
4463 GList *sub_vcard_list = NULL;
4465 RETV_IF(NULL == plist_vcard_object, cursor);
4467 *plist_vcard_object = NULL;
4469 vcard_start_cursor = __contacts_vcard_remove_line_break(vcard_start_cursor);
4471 if (STRING_EQUAL != strncmp(vcard_start_cursor, begin, strlen(begin)))
4472 return vcard_start_cursor;
4474 vcard_cursor = vcard_start_cursor;
4476 vcard_cursor += strlen(begin);
4477 vcard_cursor = __contacts_vcard_remove_line_break(vcard_cursor);
4479 while (*vcard_cursor) {
4481 if (STRING_EQUAL == strncmp(vcard_cursor, end, strlen(end))) {
4482 GList *sub_vcard_cursor = NULL;
4484 const char *pos_start = NULL;
4486 vcard_cursor += strlen(end);
4487 vcard_cursor = __contacts_vcard_remove_line_break(vcard_cursor);
4489 pos_start = vcard_start_cursor;
4490 for (sub_vcard_cursor = sub_vcard_list; sub_vcard_cursor; sub_vcard_cursor = sub_vcard_cursor->next) {
4491 sub_vcard_info_s *sub_vcard_info = sub_vcard_cursor->data;
4492 const char *pos_end = sub_vcard_info->pos_start;
4493 vcard_len += (pos_end - pos_start);
4494 pos_start = sub_vcard_info->pos_end;
4496 vcard_len += (vcard_cursor - pos_start);
4497 vcard_object = calloc(vcard_len + 1, sizeof(char));
4498 if (NULL == vcard_object) {
4499 ERR("calloc() Fail");
4500 __contacts_vcard_free_sub_vcard_info_list(sub_vcard_list);
4505 pos_start = vcard_start_cursor;
4506 for (sub_vcard_cursor = sub_vcard_list; sub_vcard_cursor; sub_vcard_cursor = sub_vcard_cursor->next) {
4507 sub_vcard_info_s *sub_vcard_info = sub_vcard_cursor->data;
4508 const char *pos_end = sub_vcard_info->pos_start;
4509 memcpy(vcard_object+vcard_len, pos_start, pos_end - pos_start);
4510 vcard_len += (pos_end - pos_start);
4511 pos_start = sub_vcard_info->pos_end;
4513 __contacts_vcard_free_sub_vcard_info_list(sub_vcard_list);
4514 memcpy(vcard_object+vcard_len, pos_start, vcard_cursor - pos_start);
4515 *plist_vcard_object = g_list_append(*plist_vcard_object, vcard_object);
4517 return vcard_cursor;
4518 } else if (STRING_EQUAL == strncmp(vcard_cursor, begin, strlen(begin))) {
4520 sub_vcard_info_s *sub_vcard_info = calloc(1, sizeof(sub_vcard_info_s));
4521 if (NULL == sub_vcard_info) {
4522 ERR("calloc() Fail");
4523 __contacts_vcard_free_sub_vcard_info_list(sub_vcard_list);
4526 sub_vcard_info->pos_start = vcard_cursor;
4528 vcard_cursor = __contacts_vcard_parse_get_vcard_object(vcard_cursor, plist_vcard_object);
4529 sub_vcard_info->pos_end = vcard_cursor;
4531 sub_vcard_list = g_list_append(sub_vcard_list, sub_vcard_info);
4537 if (('\n' == *vcard_cursor) || ('\r' == *vcard_cursor && '\n' == *(vcard_cursor+1))) {
4539 vcard_cursor = __contacts_vcard_remove_line_break(vcard_cursor);
4543 __contacts_vcard_free_sub_vcard_info_list(sub_vcard_list);
4545 return vcard_cursor;
4548 EXPORT_API int contacts_vcard_parse_to_contacts(const char *vcard_stream, contacts_list_h *out_contacts)
4550 CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
4552 contacts_record_h record;
4553 contacts_list_h list = NULL;
4554 const char *cursor = NULL;
4555 char *vcard_object = NULL;
4556 GList *list_vcard_object = NULL;
4558 RETV_IF(NULL == out_contacts, CONTACTS_ERROR_INVALID_PARAMETER);
4559 *out_contacts = NULL;
4561 RETV_IF(NULL == vcard_stream, CONTACTS_ERROR_INVALID_PARAMETER);
4563 cursor = vcard_stream;
4564 while ((cursor = __contacts_vcard_parse_get_vcard_object(cursor, &list_vcard_object))) {
4565 GList *vcard_cursor = NULL;
4566 if (NULL == list_vcard_object)
4569 for (vcard_cursor = list_vcard_object; vcard_cursor; vcard_cursor = vcard_cursor->next) {
4570 vcard_object = vcard_cursor->data;
4571 if (NULL == vcard_object)
4574 ret = __ctsvc_vcard_parse(vcard_object, &record);
4575 if (ret < CONTACTS_ERROR_NONE) {
4576 ERR("__ctsvc_vcard_parse() Fail(%d)", ret);
4577 __contacts_vcard_free_vcard_object_list(list_vcard_object);
4578 contacts_list_destroy(list, true);
4583 contacts_list_create(&list);
4584 contacts_list_add(list, record);
4585 vcard_object = NULL;
4587 __contacts_vcard_free_vcard_object_list(list_vcard_object);
4589 *out_contacts = list;
4590 return CONTACTS_ERROR_NONE;
4594 static int _ctsvc_safe_add(unsigned int *total, unsigned int value)
4596 if (UINT_MAX - *total < value) {
4597 /* LCOV_EXCL_START */
4598 ERR("overflow occurs when %d + %d", *total, value);
4599 return CONTACTS_ERROR_SYSTEM;
4600 /* LCOV_EXCL_STOP */
4604 return CONTACTS_ERROR_NONE;
4607 EXPORT_API int contacts_vcard_parse_to_contact_foreach(const char *vcard_file_name,
4608 contacts_vcard_parse_cb cb, void *data)
4610 CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
4611 contacts_record_h record;
4613 unsigned int buf_size, len;
4616 int vcard_depth = 0;
4618 char line[1024] = {0};
4620 RETV_IF(NULL == vcard_file_name, CONTACTS_ERROR_INVALID_PARAMETER);
4621 RETV_IF(NULL == cb, CONTACTS_ERROR_INVALID_PARAMETER);
4623 file = fopen(vcard_file_name, "r");
4624 RETVM_IF(NULL == file, CONTACTS_ERROR_SYSTEM, "fopen() Fail(%d)", errno);
4627 buf_size = CTSVC_VCARD_MAX_SIZE;
4628 stream = malloc(CTSVC_VCARD_MAX_SIZE);
4629 if (NULL == stream) {
4630 /* LCOV_EXCL_START */
4631 ERR("Out of memory : malloc() Fail");
4633 return CONTACTS_ERROR_OUT_OF_MEMORY;
4634 /* LCOV_EXCL_STOP */
4637 while (fgets(line, sizeof(line), file)) {
4639 if (STRING_EQUAL != strncmp(line, "BEGIN:VCARD", strlen("BEGIN:VCARD")))
4642 if (buf_size - len <= strlen(line)) {
4644 buf_size += sizeof(line) * 2;
4645 new_stream = realloc(stream, buf_size);
4647 stream = new_stream;
4649 /* LCOV_EXCL_START */
4652 return CONTACTS_ERROR_OUT_OF_MEMORY;
4653 /* LCOV_EXCL_STOP */
4656 written_len = snprintf(stream + len, buf_size - len, "%s", line);
4657 if (written_len < 0) {
4658 /* LCOV_EXCL_START */
4661 ERR("snprintf() Fail(%d)", written_len);
4662 return CONTACTS_ERROR_SYSTEM;
4663 /* LCOV_EXCL_STOP */
4666 ret = _ctsvc_safe_add(&len, (unsigned int)written_len);
4667 if (CONTACTS_ERROR_NONE != ret) {
4670 ERR("_ctsvc_safe_add() Fail", len, written_len);
4674 if (STRING_EQUAL == strncmp(line, "END:VCARD", 9)) {
4677 if (0 == vcard_depth) {
4678 const char *cursor = stream;
4679 GList *list_vcard_object = NULL;
4683 while ((cursor = __contacts_vcard_parse_get_vcard_object(cursor, &list_vcard_object))) {
4684 GList *vcard_cursor = NULL;
4685 if (NULL == list_vcard_object)
4688 for (vcard_cursor = list_vcard_object; vcard_cursor; vcard_cursor = vcard_cursor->next) {
4689 char *vcard_object = vcard_cursor->data;
4691 if (NULL == vcard_object)
4694 ret = __ctsvc_vcard_parse(vcard_object, &record);
4695 if (ret < CONTACTS_ERROR_NONE) {
4696 ERR("vcard stream parsing error");
4699 __contacts_vcard_free_vcard_object_list(list_vcard_object);
4703 if (false == cb(record, data)) {
4706 __contacts_vcard_free_vcard_object_list(list_vcard_object);
4707 contacts_record_destroy(record, true);
4708 return CONTACTS_ERROR_NONE;
4710 contacts_record_destroy(record, true);
4712 __contacts_vcard_free_vcard_object_list(list_vcard_object);
4713 list_vcard_object = NULL;
4716 } else if (STRING_EQUAL == strncmp(line, "BEGIN:VCARD", 11)) { /* sub vcard object */
4723 return CONTACTS_ERROR_NONE;
4726 EXPORT_API int contacts_vcard_get_entity_count(const char *vcard_file_name, int *count)
4728 CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
4731 char line[1024] = {0};
4732 RETV_IF(NULL == count, CONTACTS_ERROR_INVALID_PARAMETER);
4735 RETV_IF(NULL == vcard_file_name, CONTACTS_ERROR_INVALID_PARAMETER);
4737 file = fopen(vcard_file_name, "r");
4738 RETVM_IF(NULL == file, CONTACTS_ERROR_SYSTEM, "System : fopen() Fail(%d)", errno);
4741 while (fgets(line, sizeof(line), file)) {
4742 if (STRING_EQUAL == strncmp(line, "END:VCARD", 9))
4749 return CONTACTS_ERROR_NONE;
4752 EXPORT_API int contacts_vcard_get_limit_size_of_photo(unsigned int *limit_size)
4754 CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
4755 #ifdef _CONTACTS_IPC_CLIENT
4757 bool result = false;
4760 RETV_IF(NULL == limit_size, CONTACTS_ERROR_INVALID_PARAMETER);
4762 #ifdef _CONTACTS_IPC_CLIENT
4763 ret = ctsvc_ipc_client_check_permission(CTSVC_PERMISSION_CONTACT_READ, &result);
4764 RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_ipc_client_check_permission() Fail(%d)", ret);
4765 RETVM_IF(result == false, CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied (contact read)");
4768 *limit_size = limit_size_of_photo;
4769 return CONTACTS_ERROR_NONE;
4772 EXPORT_API int contacts_vcard_set_limit_size_of_photo(unsigned int limit_size)
4774 CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
4775 #ifdef _CONTACTS_IPC_CLIENT
4777 bool result = false;
4780 RETV_IF(CTSVC_IMAGE_MAX_SIZE <= limit_size, CONTACTS_ERROR_INVALID_PARAMETER);
4781 RETV_IF(limit_size < 8, CONTACTS_ERROR_INVALID_PARAMETER);
4783 #ifdef _CONTACTS_IPC_CLIENT
4784 ret = ctsvc_ipc_client_check_permission(CTSVC_PERMISSION_CONTACT_WRITE, &result);
4785 RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_ipc_client_check_permission() Fail(%d)", ret);
4786 RETVM_IF(result == false, CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied (contact read)");
4789 limit_size_of_photo = limit_size;
4790 return CONTACTS_ERROR_NONE;