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 /* LCOV_EXCL_START */
205 static int __ctsvc_vcard_append_str(char **buf, int *buf_size, int len, const char *str, bool need_conversion)
209 const char *safe_str = SAFE_STR(str);
211 bool need_realloc = false;
213 str_len = strlen(safe_str);
214 while ((*buf_size-len) < (str_len+1)) {
215 *buf_size = *buf_size * 2;
220 if (NULL == (tmp = realloc(*buf, *buf_size)))
226 if (need_conversion) {
227 const char *s = safe_str;
228 char *r = (char *)(*buf+len);
233 if (*(s+1) && '\n' == *(s+1)) {
246 if (*buf_size < str_len+len+1) {
247 *buf_size = *buf_size * 2;
248 if (NULL == (tmp = realloc(*buf, *buf_size))) {
252 r = (char *)(*buf+len+str_len);
266 if (*buf_size < str_len+len+1) {
267 *buf_size = *buf_size * 2;
268 if (NULL == (tmp = realloc(*buf, *buf_size))) {
272 r = (char *)(*buf+len+str_len);
278 if (*(s+1) && 0xAC == *(s+1)) { /* en/em backslash */
282 if (*buf_size < str_len+len+1) {
283 *buf_size = *buf_size * 2;
284 if (NULL == (tmp = realloc(*buf, *buf_size))) {
288 r = (char *)(*buf+len+str_len);
295 if (*buf_size < str_len+len+1) {
296 *buf_size = *buf_size * 2;
297 if (NULL == (tmp = realloc(*buf, *buf_size))) {
301 r = (char *)(*buf+len+str_len);
310 if (*(s+1) && 0x5F == *(s+1)) { /* en/em backslash */
314 if (*buf_size < str_len+len+1) {
315 *buf_size = *buf_size * 2;
316 if (NULL == (tmp = realloc(*buf, *buf_size))) {
320 r = (char *)(*buf+len+str_len);
327 if (*buf_size < str_len+len+1) {
328 *buf_size = *buf_size * 2;
329 if (NULL == (tmp = realloc(*buf, *buf_size))) {
333 r = (char *)(*buf+len+str_len);
350 len_temp = snprintf(*buf+len, *buf_size-len+1, "%s", safe_str);
356 #define CTS_VCARD_FOLDING_LIMIT 75
358 static inline int __ctsvc_vcard_add_folding(char **buf, int *buf_size, int buf_len)
361 char *buf_copy = NULL;
362 int len, result_len = 0;
365 bool content_start = false;
366 bool encode_64 = false;
368 buf_copy = calloc(1, *buf_size);
369 if (NULL == buf_copy) {
370 ERR("calloc() Fail");
379 if (*buf_size < result_len + 5) {
381 *buf_size = *buf_size + 1000;
382 if (NULL == (tmp = realloc(buf_copy, *buf_size))) {
387 r = (buf_copy + result_len);
391 if (false == content_start) {
393 content_start = true;
394 else if (STRING_EQUAL == strncmp(s, "ENCODING=BASE64", strlen("ENCODING=BASE64")))
400 } else if ('\n' == *s) {
403 content_start = false;
408 if (false == encode_64)
409 char_len = ctsvc_check_utf8(*s);
411 if (CTS_VCARD_FOLDING_LIMIT <= len + char_len) {
438 static inline int __ctsvc_vcard_append_name(ctsvc_list_s *names, char **buf, int *buf_size, int len)
440 char display[1024] = {0};
441 GList *cursor = names->records;
444 RETV_IF(NULL == cursor, len);
448 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_N]);
450 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";CHARSET=UTF-8");
451 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ":");
452 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, name->last);
453 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
454 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, name->first);
455 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
456 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, name->addition);
457 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
458 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, name->prefix);
459 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
460 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, name->suffix);
462 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, CTSVC_CRLF);
464 if (name->first && name->last) {
465 contacts_name_display_order_e order = CONTACTS_NAME_DISPLAY_ORDER_FIRSTLAST;
466 #ifdef _CONTACTS_IPC_CLIENT
467 contacts_setting_get_name_display_order(&order);
469 if (CONTACTS_NAME_DISPLAY_ORDER_FIRSTLAST == order) {
470 snprintf(display, sizeof(display), "%s %s", name->first, name->last);
472 /* CONTACTS_NAME_DISPLAY_ORDER_LASTFIRST */
473 snprintf(display, sizeof(display), "%s, %s", name->last, name->first);
476 snprintf(display, sizeof(display), "%s%s", SAFE_STR(name->first), SAFE_STR(name->last));
479 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_FN]);
480 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, display);
482 if (name->phonetic_first) {
483 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_PHONETIC_FIRST_NAME]);
484 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, name->phonetic_first);
487 if (name->phonetic_middle) {
488 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_PHONETIC_MIDDLE_NAME]);
489 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, name->phonetic_middle);
493 if (name->phonetic_last) {
494 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_PHONETIC_LAST_NAME]);
495 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, name->phonetic_last);
501 static inline const char* __ctsvc_get_img_suffix(int type)
504 case CTSVC_VCARD_IMG_TIFF:
506 case CTSVC_VCARD_IMG_GIF:
508 case CTSVC_VCARD_IMG_PNG:
510 case CTSVC_VCARD_IMG_CGM:
512 case CTSVC_VCARD_IMG_WMF:
514 case CTSVC_VCARD_IMG_BMP:
516 case CTSVC_VCARD_IMG_MET:
518 case CTSVC_VCARD_IMG_PMB:
520 case CTSVC_VCARD_IMG_DIB:
522 case CTSVC_VCARD_IMG_PICT:
524 case CTSVC_VCARD_IMG_PDF:
526 case CTSVC_VCARD_IMG_PS:
528 case CTSVC_VCARD_IMG_QTIME:
530 case CTSVC_VCARD_IMG_MPEG:
532 case CTSVC_VCARD_IMG_MPEG2:
534 case CTSVC_VCARD_IMG_AVI:
536 case CTSVC_VCARD_IMG_JPEG:
537 case CTSVC_VCARD_IMG_NONE:
543 static inline int __ctsvc_vcard_get_image_type(const char *val)
545 char *temp, *image_path, *result;
546 RETV_IF(NULL == val, CTSVC_VCARD_IMG_NONE);
548 image_path = strdup(val);
551 *temp = tolower(*temp);
555 result = strstr(image_path, "jpeg");
558 return CTSVC_VCARD_IMG_JPEG;
561 result = strstr(image_path, "jpg");
564 return CTSVC_VCARD_IMG_JPEG;
567 result = strstr(image_path, "png");
570 return CTSVC_VCARD_IMG_PNG;
573 result = strstr(image_path, "gif");
576 return CTSVC_VCARD_IMG_GIF;
579 result = strstr(image_path, "tiff");
582 return CTSVC_VCARD_IMG_TIFF;
585 result = strstr(image_path, "cgm");
588 return CTSVC_VCARD_IMG_CGM;
591 result = strstr(image_path, "wmf");
594 return CTSVC_VCARD_IMG_WMF;
597 result = strstr(image_path, "bmp");
600 return CTSVC_VCARD_IMG_BMP;
603 result = strstr(image_path, "met");
606 return CTSVC_VCARD_IMG_MET;
609 result = strstr(image_path, "pmb");
612 return CTSVC_VCARD_IMG_PMB;
615 result = strstr(image_path, "dib");
618 return CTSVC_VCARD_IMG_DIB;
621 result = strstr(image_path, "pict");
624 return CTSVC_VCARD_IMG_PICT;
627 result = strstr(image_path, "pdf");
630 return CTSVC_VCARD_IMG_PDF;
633 result = strstr(image_path, "ps");
636 return CTSVC_VCARD_IMG_PS;
639 result = strstr(image_path, "qtime");
642 return CTSVC_VCARD_IMG_QTIME;
645 result = strstr(image_path, "mpeg");
648 return CTSVC_VCARD_IMG_MPEG;
651 result = strstr(image_path, "mpeg2");
654 return CTSVC_VCARD_IMG_MPEG2;
657 result = strstr(image_path, "avi");
660 return CTSVC_VCARD_IMG_AVI;
664 return CTSVC_VCARD_IMG_NONE;
667 static inline const char* __ctsvc_get_image_type_str(int type)
670 case CTSVC_VCARD_IMG_TIFF:
672 case CTSVC_VCARD_IMG_GIF:
674 case CTSVC_VCARD_IMG_PNG:
676 case CTSVC_VCARD_IMG_CGM:
678 case CTSVC_VCARD_IMG_WMF:
680 case CTSVC_VCARD_IMG_BMP:
682 case CTSVC_VCARD_IMG_MET:
684 case CTSVC_VCARD_IMG_PMB:
686 case CTSVC_VCARD_IMG_DIB:
688 case CTSVC_VCARD_IMG_PICT:
690 case CTSVC_VCARD_IMG_PDF:
692 case CTSVC_VCARD_IMG_PS:
694 case CTSVC_VCARD_IMG_QTIME:
696 case CTSVC_VCARD_IMG_MPEG:
698 case CTSVC_VCARD_IMG_MPEG2:
700 case CTSVC_VCARD_IMG_AVI:
702 case CTSVC_VCARD_IMG_JPEG:
708 static inline int __ctsvc_vcard_put_company_logo(const char *path, char **buf, int *buf_size, int len)
714 guchar image[CTSVC_VCARD_PHOTO_MAX_SIZE] = {0};
716 suffix = strrchr(path, '.');
717 type = __ctsvc_vcard_get_image_type((const char *)suffix);
719 fd = open(path, O_RDONLY);
720 RETVM_IF(fd < 0, CONTACTS_ERROR_SYSTEM, "System : Open Fail(%d)", errno);
723 while ((ret = read(fd, image+read_len, sizeof(image)-read_len))) {
733 RETVM_IF(ret < 0, CONTACTS_ERROR_SYSTEM, "System : read() Fail(%d)", errno);
735 buf_image = g_base64_encode(image, read_len);
738 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_LOGO], false)) < 0)
740 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, ";ENCODING=BASE64;TYPE=", false)) < 0)
742 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, __ctsvc_get_image_type_str(type), false)) < 0)
744 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, ":", false)) < 0)
746 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, buf_image, false)) < 0)
748 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, CTSVC_CRLF, false)) < 0)
750 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, CTSVC_CRLF, false)) < 0)
756 /* LCOV_EXCL_START */
757 ERR("__ctsvc_vcard_append_str() Fail");
758 return CONTACTS_ERROR_OUT_OF_MEMORY;
765 static bool __ctsvc_vcard_is_valid_custom_label(char *label)
768 RETV_IF(NULL == label || '\0' == *label, false);
772 RETV_IF(1 != ctsvc_check_utf8(c), false);
773 if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') ||
774 ('0' <= c && c <= '9') || c == '-') {
783 static inline int __ctsvc_vcard_put_company_type(int type, char *label, char **buf, int *buf_size, int len)
785 if (type == CONTACTS_COMPANY_TYPE_WORK) {
786 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=WORK");
787 } else if (type == CONTACTS_COMPANY_TYPE_CUSTOM) {
788 if (__ctsvc_vcard_is_valid_custom_label(label)) {
789 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-");
790 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, label);
796 static inline int __ctsvc_vcard_append_company(ctsvc_list_s *company_list, char **buf, int *buf_size, int len)
799 ctsvc_company_s *company;
801 for (cursor = company_list->records; cursor; cursor = cursor->next) {
803 company = cursor->data;
805 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_ORG]);
807 len = __ctsvc_vcard_put_company_type(company->type, SAFE_STR(company->label), buf, buf_size, len);
808 RETV_IF(len < 0, CONTACTS_ERROR_OUT_OF_MEMORY);
810 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";CHARSET=UTF-8");
811 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ":");
812 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, company->name);
813 if (company->department) {
814 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
815 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, company->department);
818 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, CTSVC_CRLF);
820 if (company->job_title) {
821 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_TITLE]);
822 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, company->job_title);
826 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_ROLE]);
827 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, company->role);
830 if (company->location) {
831 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_LOCATION]);
832 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, company->location);
835 if (company->description) {
836 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_DESCRIPTION]);
837 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, company->description);
840 if (company->phonetic_name) {
841 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_PHONETIC_NAME]);
842 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, company->phonetic_name);
845 if (company->assistant_name) {
846 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_ASSISTANT_NAME]);
847 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, company->assistant_name);
851 len = __ctsvc_vcard_put_company_logo(company->logo, buf, buf_size, len);
852 RETV_IF(len < 0, CONTACTS_ERROR_OUT_OF_MEMORY);
859 static inline int __ctsvc_vcard_append_note(ctsvc_list_s *note_list, char **buf, int *buf_size, int len)
864 for (cursor = note_list->records; cursor; cursor = cursor->next) {
867 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_NOTE]);
868 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, note->note);
875 static inline int __ctsvc_vcard_2_put_postal_type(int type, char *dest, int dest_size)
879 if (type & CONTACTS_ADDRESS_TYPE_DOM)
880 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "DOM");
881 if (type & CONTACTS_ADDRESS_TYPE_INTL)
882 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "INTL");
883 if (type & CONTACTS_ADDRESS_TYPE_HOME)
884 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "HOME");
885 if (type & CONTACTS_ADDRESS_TYPE_WORK)
886 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "WORK");
887 if (type & CONTACTS_ADDRESS_TYPE_POSTAL)
888 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "POSTAL");
889 if (type & CONTACTS_ADDRESS_TYPE_PARCEL)
890 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "PARCEL");
895 static inline int __ctsvc_vcard_put_postal_type(int type, char *label, char **buf, int *buf_size, int len)
897 char *type_str = NULL;
898 if (type == CONTACTS_ADDRESS_TYPE_DOM)
900 else if (type == CONTACTS_ADDRESS_TYPE_INTL)
902 else if (type == CONTACTS_ADDRESS_TYPE_HOME)
904 else if (type == CONTACTS_ADDRESS_TYPE_WORK)
906 else if (type == CONTACTS_ADDRESS_TYPE_POSTAL)
908 else if (type == CONTACTS_ADDRESS_TYPE_PARCEL)
911 if (type == CONTACTS_ADDRESS_TYPE_CUSTOM) {
912 if (__ctsvc_vcard_is_valid_custom_label(label)) {
913 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-");
914 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, label);
920 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=");
921 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, type_str);
926 static inline int __ctsvc_vcard_append_postals(ctsvc_list_s *address_list, char **buf, int *buf_size, int len)
929 ctsvc_address_s *address;
931 for (cursor = address_list->records; cursor; cursor = cursor->next) {
932 address = cursor->data;
934 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_ADR]);
936 len = __ctsvc_vcard_put_postal_type(address->type, SAFE_STR(address->label), buf, buf_size, len);
937 RETV_IF(len < 0, CONTACTS_ERROR_OUT_OF_MEMORY);
939 if (address->is_default)
940 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";PREF");
942 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";CHARSET=UTF-8");
943 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ":");
944 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, address->pobox);
945 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
946 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, address->extended);
947 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
948 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, address->street);
949 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
950 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, address->locality);
951 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
952 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, address->region);
953 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
954 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, address->postalcode);
955 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
956 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, address->country);
958 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, CTSVC_CRLF);
965 static inline int __ctsvc_vcard_append_nicknames(ctsvc_list_s *nickname_list, char **buf, int *buf_size, int len)
969 ctsvc_nickname_s *nickname;
972 for (cursor = nickname_list->records; cursor; cursor = cursor->next) {
973 nickname = cursor->data;
974 if (nickname->nickname && *nickname->nickname) {
976 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_NICKNAME]);
977 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";CHARSET=UTF-8");
978 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ":");
979 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, nickname->nickname);
982 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ",");
983 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, nickname->nickname);
988 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, CTSVC_CRLF);
993 static inline int __ctsvc_vcard_2_put_number_type(int type, char *dest, int dest_size)
996 if (type & CONTACTS_NUMBER_TYPE_HOME)
997 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "HOME");
998 if (type & CONTACTS_NUMBER_TYPE_MSG)
999 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "MSG");
1000 if (type & CONTACTS_NUMBER_TYPE_WORK)
1001 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "WORK");
1002 if (type & CONTACTS_NUMBER_TYPE_VOICE)
1003 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "VOICE");
1004 if (type & CONTACTS_NUMBER_TYPE_FAX)
1005 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "FAX");
1006 if (type & CONTACTS_NUMBER_TYPE_VOICE)
1007 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "VOICE");
1008 if (type & CONTACTS_NUMBER_TYPE_CELL)
1009 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "CELL");
1010 if (type & CONTACTS_NUMBER_TYPE_VIDEO)
1011 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "VIDEO");
1012 if (type & CONTACTS_NUMBER_TYPE_PAGER)
1013 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "PAGER");
1014 if (type & CONTACTS_NUMBER_TYPE_BBS)
1015 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "BBS");
1016 if (type & CONTACTS_NUMBER_TYPE_MODEM)
1017 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "MODEM");
1018 if (type & CONTACTS_NUMBER_TYPE_CAR)
1019 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "CAR");
1020 if (type & CONTACTS_NUMBER_TYPE_ISDN)
1021 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "ISDN");
1022 if (type & CONTACTS_NUMBER_TYPE_PCS)
1023 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "PCS");
1028 static inline int __ctsvc_vcard_put_number_type(int type, char *label, char **buf, int *buf_size, int len)
1030 if (type & CONTACTS_NUMBER_TYPE_HOME)
1031 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=HOME");
1032 if (type & CONTACTS_NUMBER_TYPE_MSG)
1033 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=MSG");
1034 if (type & CONTACTS_NUMBER_TYPE_WORK)
1035 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=WORK");
1036 if (type & CONTACTS_NUMBER_TYPE_VOICE)
1037 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=VOICE");
1038 if (type & CONTACTS_NUMBER_TYPE_FAX)
1039 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=FAX");
1040 if (type & CONTACTS_NUMBER_TYPE_CELL)
1041 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=CELL");
1042 if (type & CONTACTS_NUMBER_TYPE_VIDEO)
1043 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=VIDEO");
1044 if (type & CONTACTS_NUMBER_TYPE_PAGER)
1045 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=PAGER");
1046 if (type & CONTACTS_NUMBER_TYPE_BBS)
1047 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=BBS");
1048 if (type & CONTACTS_NUMBER_TYPE_MODEM)
1049 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=MODEM");
1050 if (type & CONTACTS_NUMBER_TYPE_CAR)
1051 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=CAR");
1052 if (type & CONTACTS_NUMBER_TYPE_ISDN)
1053 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=ISDN");
1054 if (type & CONTACTS_NUMBER_TYPE_PCS)
1055 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=PCS");
1056 if (type & CONTACTS_NUMBER_TYPE_ASSISTANT)
1057 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-ASSISTANT");
1058 if (type & CONTACTS_NUMBER_TYPE_RADIO)
1059 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-RADIO");
1060 if (type & CONTACTS_NUMBER_TYPE_COMPANY_MAIN)
1061 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-COMPANY-MAIN");
1062 if (type & CONTACTS_NUMBER_TYPE_MAIN)
1063 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-MAIN");
1064 if (type == CONTACTS_NUMBER_TYPE_CUSTOM) {
1065 if (__ctsvc_vcard_is_valid_custom_label(label)) {
1066 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-");
1067 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, label);
1074 static int __ctsvc_vcard_check_utf8(char c)
1076 if ((c & 0xff) < (128 & 0xff))
1078 else if ((c & (char)0xe0) == (char)0xc0)
1080 else if ((c & (char)0xf0) == (char)0xe0)
1082 else if ((c & (char)0xf8) == (char)0xf0)
1084 else if ((c & (char)0xfc) == (char)0xf8)
1086 else if ((c & (char)0xfe) == (char)0xfc)
1089 return CONTACTS_ERROR_INVALID_PARAMETER;
1092 static void __ctsvc_vcard_get_clean_number_for_export(char *str, char *dest)
1095 char *s = SAFE_STR(str);
1101 char_len = __ctsvc_vcard_check_utf8(*s);
1102 if (3 == char_len) {
1104 if (*(s+1) == 0xbc) {
1105 if (0x90 <= *(s+2) && *(s+2) <= 0x99) {
1106 /* ef bc 90 : '0' ~ ef bc 99 : '9' */
1107 *r = '0' + (*(s+2) - 0x90);
1110 } else if (0x8b == *(s+2)) {
1111 /* ef bc 8b : '+' */
1115 } else if (0x8a == *(s+2)) {
1116 /* ef bc 8a : '*' */
1120 } else if (0x83 == *(s+2)) {
1121 /* ef bc 83 : '#' */
1125 } else if (0x8c == *(s+2)) {
1126 /* ef bc 8c : ',' */
1130 } else if (0x9b == *(s+2)) {
1131 /* ef bc 9b : ';' */
1144 } else if (1 == char_len) {
1198 static inline int __ctsvc_vcard_append_numbers(ctsvc_list_s *number_list, char **buf, int *buf_size, int len)
1201 ctsvc_number_s *number;
1203 for (cursor = number_list->records; cursor; cursor = cursor->next) {
1204 number = cursor->data;
1205 if (number->number) {
1206 char clean_number[strlen(number->number)+1];
1207 clean_number[0] = '\0';
1208 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_TEL]);
1210 len = __ctsvc_vcard_put_number_type(number->type, SAFE_STR(number->label), buf, buf_size, len);
1211 RETV_IF(len < 0, CONTACTS_ERROR_OUT_OF_MEMORY);
1213 if (number->is_default)
1214 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";PREF");
1216 __ctsvc_vcard_get_clean_number_for_export(number->number, clean_number);
1218 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, clean_number);
1224 static inline int __ctsvc_vcard_2_put_email_type(int type, char *dest, int dest_size)
1228 if (CONTACTS_EMAIL_TYPE_HOME & type)
1229 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "HOME");
1230 if (CONTACTS_EMAIL_TYPE_WORK & type)
1231 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "WORK");
1236 static inline int __ctsvc_vcard_put_email_type(int type, char *label, char **buf, int *buf_size, int len)
1238 char *type_str = NULL;
1239 if (CONTACTS_EMAIL_TYPE_HOME == type) {
1241 } else if (CONTACTS_EMAIL_TYPE_WORK == type) {
1243 } else if (CONTACTS_EMAIL_TYPE_MOBILE == type) {
1245 } else if (CONTACTS_EMAIL_TYPE_CUSTOM == type) {
1246 if (__ctsvc_vcard_is_valid_custom_label(label)) {
1247 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-");
1248 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, label);
1254 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=");
1255 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, type_str);
1260 static inline int __ctsvc_vcard_append_emails(ctsvc_list_s *email_list, char **buf, int *buf_size, int len)
1263 ctsvc_email_s *email;
1265 for (cursor = email_list->records; cursor; cursor = cursor->next) {
1266 email = cursor->data;
1267 if (email->email_addr) {
1268 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_EMAIL]);
1270 len = __ctsvc_vcard_put_email_type(email->type, SAFE_STR(email->label), buf, buf_size, len);
1271 RETV_IF(len < 0, CONTACTS_ERROR_OUT_OF_MEMORY);
1273 if (email->is_default)
1274 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";PREF");
1276 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, email->email_addr);
1282 static inline int __ctsvc_vcard_put_url_type(int type, char *label, char **buf, int *buf_size, int len)
1284 char *type_str = NULL;
1286 if (CONTACTS_URL_TYPE_HOME == type) {
1288 } else if (CONTACTS_URL_TYPE_WORK == type) {
1290 } else if (CONTACTS_URL_TYPE_CUSTOM == type) {
1291 if (__ctsvc_vcard_is_valid_custom_label(label)) {
1292 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-");
1293 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, label);
1298 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=");
1299 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, type_str);
1304 static inline int __ctsvc_vcard_append_webs(ctsvc_list_s *url_list, char **buf, int *buf_size, int len)
1309 for (cursor = url_list->records; cursor; cursor = cursor->next) {
1312 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_URL]);
1314 len = __ctsvc_vcard_put_url_type(url->type, SAFE_STR(url->label), buf, buf_size, len);
1315 RETV_IF(len < 0, CONTACTS_ERROR_OUT_OF_MEMORY);
1317 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, url->url);
1323 #define VCARD_INIT_LENGTH 1024
1324 #define VCARD_ITEM_LENGTH 1024
1326 static inline int __ctsvc_vcard_append_events(ctsvc_list_s *event_list, char **buf, int *buf_size, int len)
1329 ctsvc_event_s *data;
1330 char event[VCARD_ITEM_LENGTH] = {0};
1332 for (cursor = event_list->records; cursor; cursor = cursor->next) {
1333 data = cursor->data;
1334 if (0 == data->date) continue;
1337 if (CONTACTS_EVENT_TYPE_BIRTH == data->type) {
1338 snprintf(event, sizeof(event), "%s:%d-%02d-%02d%s",
1339 content_name[CTSVC_VCARD_VALUE_BDAY],
1340 data->date/10000, (data->date%10000)/100, data->date%100,
1342 } else if (CONTACTS_EVENT_TYPE_ANNIVERSARY == data->type) {
1343 snprintf(event, sizeof(event), "%s;TYPE=ANNIVERSARY:%d-%02d-%02d%s",
1344 content_name[CTSVC_VCARD_VALUE_X_TIZEN_EVENT],
1345 data->date/10000, (data->date%10000)/100, data->date%100,
1347 } else if (CONTACTS_EVENT_TYPE_CUSTOM == data->type) {
1348 if (__ctsvc_vcard_is_valid_custom_label(data->label)) {
1349 snprintf(event, sizeof(event), "%s;TYPE=X-%s:%d-%02d-%02d%s",
1350 content_name[CTSVC_VCARD_VALUE_X_TIZEN_EVENT],
1351 SAFE_STR(data->label),
1352 data->date/10000, (data->date%10000)/100, data->date%100,
1355 snprintf(event, sizeof(event), "%s:%d-%02d-%02d%s",
1356 content_name[CTSVC_VCARD_VALUE_X_TIZEN_EVENT],
1357 data->date/10000, (data->date%10000)/100, data->date%100,
1361 snprintf(event, sizeof(event), "%s:%d-%02d-%02d%s",
1362 content_name[CTSVC_VCARD_VALUE_X_TIZEN_EVENT],
1363 data->date/10000, (data->date%10000)/100, data->date%100,
1366 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, event);
1372 static inline int __ctsvc_vcard_append_messengers(ctsvc_list_s *messenger_list, char **buf, int *buf_size, int len)
1375 ctsvc_messenger_s *messenger;
1376 const char *content_name_messenger = NULL;
1377 const char *content_name_x_type = NULL;
1379 for (cursor = messenger_list->records; cursor; cursor = cursor->next) {
1380 messenger = cursor->data;
1382 content_name_messenger = NULL;
1383 content_name_x_type = NULL;
1385 if (messenger->im_id && *messenger->im_id) {
1386 switch (messenger->type) {
1387 case CONTACTS_MESSENGER_TYPE_WLM:
1388 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_MSN];
1390 case CONTACTS_MESSENGER_TYPE_YAHOO:
1391 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_YAHOO];
1393 case CONTACTS_MESSENGER_TYPE_ICQ:
1394 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_ICQ];
1396 case CONTACTS_MESSENGER_TYPE_AIM:
1397 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_AIM];
1399 case CONTACTS_MESSENGER_TYPE_JABBER:
1400 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_JABBER];
1402 case CONTACTS_MESSENGER_TYPE_SKYPE:
1403 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_SKYPE_USERNAME];
1405 case CONTACTS_MESSENGER_TYPE_QQ:
1406 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_QQ];
1408 case CONTACTS_MESSENGER_TYPE_GOOGLE:
1409 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_GOOGLE_TALK];
1411 case CONTACTS_MESSENGER_TYPE_FACEBOOK:
1412 content_name_x_type = "FACEBOOK";
1414 case CONTACTS_MESSENGER_TYPE_IRC:
1415 content_name_x_type = "IRC";
1417 case CONTACTS_MESSENGER_TYPE_CUSTOM:
1418 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_X_TIZEN_MESSENGER]);
1419 if (__ctsvc_vcard_is_valid_custom_label(messenger->label)) {
1420 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-");
1421 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, messenger->label);
1423 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, messenger->im_id);
1426 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_X_TIZEN_MESSENGER]);
1427 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, messenger->im_id);
1431 if (content_name_messenger) {
1432 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name_messenger);
1433 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, messenger->im_id);
1434 } else if (content_name_x_type) {
1435 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_X_TIZEN_MESSENGER]);
1436 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=");
1437 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name_x_type);
1438 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, messenger->im_id);
1445 static inline int __ctsvc_vcard_put_relationship_type(int type, char *label, char **buf, int *buf_size, int len)
1447 const char *type_str = NULL;
1450 case CONTACTS_RELATIONSHIP_TYPE_ASSISTANT:
1451 type_str = "ASSISTANT";
1453 case CONTACTS_RELATIONSHIP_TYPE_BROTHER:
1454 type_str = "BROTHER";
1456 case CONTACTS_RELATIONSHIP_TYPE_CHILD:
1459 case CONTACTS_RELATIONSHIP_TYPE_DOMESTIC_PARTNER:
1460 type_str = "DOMESTIC_PARTNER";
1462 case CONTACTS_RELATIONSHIP_TYPE_FATHER:
1463 type_str = "FATHER";
1465 case CONTACTS_RELATIONSHIP_TYPE_FRIEND:
1466 type_str = "FRIEND";
1468 case CONTACTS_RELATIONSHIP_TYPE_MANAGER:
1469 type_str = "MANAGER";
1471 case CONTACTS_RELATIONSHIP_TYPE_MOTHER:
1472 type_str = "MOTHER";
1474 case CONTACTS_RELATIONSHIP_TYPE_PARENT:
1475 type_str = "PARENT";
1477 case CONTACTS_RELATIONSHIP_TYPE_PARTNER:
1478 type_str = "PARTNER";
1480 case CONTACTS_RELATIONSHIP_TYPE_REFERRED_BY:
1481 type_str = "REFERRED_BY";
1483 case CONTACTS_RELATIONSHIP_TYPE_RELATIVE:
1484 type_str = "RELATIVE";
1486 case CONTACTS_RELATIONSHIP_TYPE_SISTER:
1487 type_str = "SISTER";
1489 case CONTACTS_RELATIONSHIP_TYPE_SPOUSE:
1490 type_str = "SPOUSE";
1492 case CONTACTS_RELATIONSHIP_TYPE_CUSTOM:
1493 if (__ctsvc_vcard_is_valid_custom_label(label)) {
1494 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-");
1495 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, label);
1501 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=");
1502 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, type_str);
1508 static inline int __ctsvc_vcard_append_relationships(ctsvc_list_s *relationship_list, char **buf, int *buf_size, int len)
1511 ctsvc_relationship_s *relationship;
1513 for (cursor = relationship_list->records; cursor; cursor = cursor->next) {
1514 relationship = cursor->data;
1516 if (relationship->name) {
1517 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, "X-TIZEN-RELATIONSHIP");
1519 len = __ctsvc_vcard_put_relationship_type(relationship->type, SAFE_STR(relationship->label), buf, buf_size, len);
1520 RETV_IF(len < 0, CONTACTS_ERROR_OUT_OF_MEMORY);
1521 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, relationship->name);
1530 unsigned char **image;
1531 unsigned int *image_size;
1535 static bool _ctsvc_vcard_image_util_supported_jpeg_colorspace_cb(
1536 image_util_colorspace_e colorspace, void *user_data)
1542 unsigned int size_decode = 0;
1543 void *buffer = NULL;
1544 void *buffer_temp = NULL;
1546 vcard_image_info *info = user_data;
1548 ret = ctsvc_image_util_get_mimetype(colorspace, &mimetype);
1549 if (CONTACTS_ERROR_NONE != ret) {
1550 /* LCOV_EXCL_START */
1551 info->ret = CONTACTS_ERROR_SYSTEM;
1553 /* LCOV_EXCL_STOP */
1556 image_util_decode_h dh = NULL;
1558 unsigned long l_width = 0;
1559 unsigned long l_height = 0;
1560 unsigned long long ll_size_decode = 0;
1562 ret = image_util_decode_create(&dh);
1563 if (IMAGE_UTIL_ERROR_NONE != ret)
1565 ret = image_util_decode_set_input_path(dh, info->src);
1566 if (IMAGE_UTIL_ERROR_NONE != ret)
1568 ret = image_util_decode_set_colorspace(dh, colorspace);
1569 if (IMAGE_UTIL_ERROR_NONE != ret)
1571 ret = image_util_decode_set_output_buffer(dh, (unsigned char **)&buffer);
1572 if (IMAGE_UTIL_ERROR_NONE != ret)
1574 ret = image_util_decode_run(dh, &l_width, &l_height, &ll_size_decode);
1575 if (IMAGE_UTIL_ERROR_NONE != ret)
1578 width = (int)l_width;
1579 height = (int)l_height;
1580 size_decode = (unsigned int)ll_size_decode;
1583 ret = image_util_decode_destroy(dh);
1584 if (IMAGE_UTIL_ERROR_NONE != ret || 0 == width || 0 == height) {
1585 /* LCOV_EXCL_START */
1586 info->ret = CONTACTS_ERROR_SYSTEM;
1588 /* LCOV_EXCL_STOP */
1590 size = (uint64_t)size_decode;
1592 if (limit_size_of_photo < width || limit_size_of_photo < height) { /* need resize */
1596 media_packet_h packet;
1599 if (width > height) {
1600 resized_width = limit_size_of_photo;
1601 resized_height = height * limit_size_of_photo / width;
1603 resized_height = limit_size_of_photo;
1604 resized_width = width * limit_size_of_photo / height;
1607 if (resized_height % 8)
1608 resized_height -= (resized_height % 8);
1610 if (resized_width % 8)
1611 resized_width -= (resized_width % 8);
1613 fmt = ctsvc_image_util_create_media_format(mimetype, width, height);
1615 /* LCOV_EXCL_START */
1616 ERR("_ctsvc_image_create_media_format() Fail");
1617 info->ret = CONTACTS_ERROR_SYSTEM;
1620 /* LCOV_EXCL_STOP */
1623 packet = ctsvc_image_util_create_media_packet(fmt, buffer, (unsigned int)size);
1624 if (NULL == packet) {
1625 /* LCOV_EXCL_START */
1626 ERR("_ctsvc_image_create_media_packet() Fail");
1627 media_format_unref(fmt);
1628 info->ret = CONTACTS_ERROR_SYSTEM;
1631 /* LCOV_EXCL_STOP */
1634 ret = ctsvc_image_util_resize(packet, resized_width, resized_height, &buffer_temp,
1637 media_packet_destroy(packet);
1638 media_format_unref(fmt);
1640 if (CONTACTS_ERROR_NONE != ret) {
1642 info->ret = CONTACTS_ERROR_SYSTEM;
1646 buffer = buffer_temp;
1648 width = resized_width;
1649 height = resized_height;
1652 image_util_encode_h eh = NULL;
1654 unsigned long long ll_size_encode = 0;
1656 ret = image_util_encode_create(IMAGE_UTIL_JPEG, &eh);
1657 if (IMAGE_UTIL_ERROR_NONE != ret)
1659 ret = image_util_encode_set_input_buffer(eh, buffer);
1660 if (IMAGE_UTIL_ERROR_NONE != ret)
1662 ret = image_util_encode_set_resolution(eh, width, height);
1663 if (IMAGE_UTIL_ERROR_NONE != ret)
1665 ret = image_util_encode_set_colorspace(eh, colorspace);
1666 if (IMAGE_UTIL_ERROR_NONE != ret)
1668 ret = image_util_encode_set_quality(eh, CTSVC_IMAGE_ENCODE_QUALITY);
1669 if (IMAGE_UTIL_ERROR_NONE != ret)
1671 ret = image_util_encode_set_output_buffer(eh, info->image);
1672 if (IMAGE_UTIL_ERROR_NONE != ret)
1674 ret = image_util_encode_run(eh, &ll_size_encode);
1675 *(info->image_size) = (unsigned int)ll_size_encode;
1678 ret = image_util_encode_destroy(eh);
1680 if (IMAGE_UTIL_ERROR_NONE != ret) {
1681 /* LCOV_EXCL_START */
1682 ERR("image_util_encode_jpeg_to_memory %d", ret);
1683 info->ret = CONTACTS_ERROR_SYSTEM;
1685 /* LCOV_EXCL_STOP */
1688 info->ret = CONTACTS_ERROR_NONE;
1692 static inline int __ctsvc_vcard_encode_photo(const char *src,
1693 unsigned char **image, unsigned int *image_size)
1696 vcard_image_info info = {src, image, image_size, CONTACTS_ERROR_SYSTEM};
1698 ret = image_util_foreach_supported_colorspace(IMAGE_UTIL_JPEG,
1699 _ctsvc_vcard_image_util_supported_jpeg_colorspace_cb, &info);
1701 if (IMAGE_UTIL_ERROR_NONE != ret)
1702 return CONTACTS_ERROR_SYSTEM;
1707 static inline int __ctsvc_vcard_put_photo(ctsvc_list_s *image_list, char **buf, int *buf_size, int len)
1709 int ret = CONTACTS_ERROR_NONE, fd, type;
1710 unsigned int read_len;
1713 unsigned char *image = NULL;
1714 unsigned int img_buf_size = 0;
1716 ctsvc_image_s *data;
1718 for (cursor = image_list->records; cursor; cursor = cursor->next) {
1719 data = cursor->data;
1720 if (NULL == data->path) continue;
1722 ret = __ctsvc_vcard_encode_photo(data->path, &image, &read_len);
1724 if (CONTACTS_ERROR_NONE != ret) {
1725 INFO("__ctsvc_vcard_encode_photo() Fail(%d)", ret);
1727 img_buf_size = CTSVC_VCARD_PHOTO_MAX_SIZE * sizeof(unsigned char);
1728 image = calloc(1, img_buf_size);
1729 if (NULL == image) {
1730 /* LCOV_EXCL_START */
1731 ERR("calloc() Fail");
1732 return CONTACTS_ERROR_OUT_OF_MEMORY;
1733 /* LCOV_EXCL_STOP */
1736 fd = open(data->path, O_RDONLY);
1738 /* LCOV_EXCL_START */
1739 ERR("System : Open Fail(%d)", errno);
1741 return CONTACTS_ERROR_SYSTEM;
1742 /* LCOV_EXCL_STOP */
1746 while ((ret = read(fd, image+read_len, img_buf_size-read_len))) {
1757 /* LCOV_EXCL_START */
1758 ERR("System : read() Fail(%d)", errno);
1760 return CONTACTS_ERROR_SYSTEM;
1761 /* LCOV_EXCL_STOP */
1765 suffix = strrchr(data->path, '.');
1766 type = __ctsvc_vcard_get_image_type((const char *)suffix);
1768 buf_image = g_base64_encode(image, read_len);
1773 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_PHOTO], false)) < 0)
1775 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, ";ENCODING=BASE64;TYPE=", false)) < 0)
1777 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, __ctsvc_get_image_type_str(type), false)) < 0)
1779 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, ":", false)) < 0)
1781 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, buf_image, false)) < 0)
1783 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, CTSVC_CRLF, false)) < 0)
1785 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, CTSVC_CRLF, false)) < 0)
1791 /* LCOV_EXCL_START */
1792 ERR("__ctsvc_vcard_append_str() Fail");
1793 return CONTACTS_ERROR_OUT_OF_MEMORY;
1794 /* LCOV_EXCL_STOP */
1802 static inline int __ctsvc_vcard_append_contact(ctsvc_contact_s *contact, char **buf, int *buf_size, int len)
1804 if (contact->name) {
1805 len = __ctsvc_vcard_append_name(contact->name, buf, buf_size, len);
1806 RETV_IF(len < 0, len);
1808 if (contact->company) {
1809 len = __ctsvc_vcard_append_company(contact->company, buf, buf_size, len);
1810 RETV_IF(len < 0, len);
1812 if (contact->note) {
1813 len = __ctsvc_vcard_append_note(contact->note, buf, buf_size, len);
1814 RETV_IF(len < 0, len);
1816 if (contact->postal_addrs) {
1817 len = __ctsvc_vcard_append_postals(contact->postal_addrs, buf, buf_size, len);
1818 RETV_IF(len < 0, len);
1820 if (contact->numbers) {
1821 len = __ctsvc_vcard_append_numbers(contact->numbers, buf, buf_size, len);
1822 RETV_IF(len < 0, len);
1824 if (contact->emails) {
1825 len = __ctsvc_vcard_append_emails(contact->emails, buf, buf_size, len);
1826 RETV_IF(len < 0, len);
1828 if (contact->nicknames) {
1829 len = __ctsvc_vcard_append_nicknames(contact->nicknames, buf, buf_size, len);
1830 RETV_IF(len < 0, len);
1832 if (contact->urls) {
1833 len = __ctsvc_vcard_append_webs(contact->urls, buf, buf_size, len);
1834 RETV_IF(len < 0, len);
1836 if (contact->events) {
1837 len = __ctsvc_vcard_append_events(contact->events, buf, buf_size, len);
1838 RETV_IF(len < 0, len);
1840 if (contact->images) {
1841 len = __ctsvc_vcard_put_photo(contact->images, buf, buf_size, len);
1842 RETV_IF(len < 0, len);
1844 if (contact->messengers) {
1845 len = __ctsvc_vcard_append_messengers(contact->messengers, buf, buf_size, len);
1846 RETV_IF(len < 0, len);
1848 if (contact->relationships) {
1849 len = __ctsvc_vcard_append_relationships(contact->relationships, buf, buf_size, len);
1850 RETV_IF(len < 0, len);
1853 if (contact->uid && DEFAULT_ADDRESS_BOOK_ID == contact->addressbook_id) {
1854 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_UID]);
1855 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, contact->uid);
1858 if (contact->changed_time) {
1860 gmtime_r((time_t *)&contact->changed_time, &ts);
1861 char temp[VCARD_ITEM_LENGTH] = {0};
1862 snprintf(temp, sizeof(temp), "%s:%04d-%02d-%02dT%02d:%02d:%02dZ%s",
1863 content_name[CTSVC_VCARD_VALUE_REV],
1864 1900+ts.tm_year, 1+ts.tm_mon, ts.tm_mday,
1865 ts.tm_hour, ts.tm_min, ts.tm_sec,
1868 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, temp);
1871 ctsvc_list_s *profile;
1876 static inline int __ctsvc_vcard_append_my_profile(ctsvc_my_profile_s *my_profile, char **buf, int *buf_size, int len)
1878 if (my_profile->name) {
1879 len = __ctsvc_vcard_append_name(my_profile->name, buf, buf_size, len);
1880 RETV_IF(len < 0, len);
1882 if (my_profile->company) {
1883 len = __ctsvc_vcard_append_company(my_profile->company, buf, buf_size, len);
1884 RETV_IF(len < 0, len);
1886 if (my_profile->note) {
1887 len = __ctsvc_vcard_append_note(my_profile->note, buf, buf_size, len);
1888 RETV_IF(len < 0, len);
1890 if (my_profile->postal_addrs) {
1891 len = __ctsvc_vcard_append_postals(my_profile->postal_addrs, buf, buf_size, len);
1892 RETV_IF(len < 0, len);
1894 if (my_profile->numbers) {
1895 len = __ctsvc_vcard_append_numbers(my_profile->numbers, buf, buf_size, len);
1896 RETV_IF(len < 0, len);
1898 if (my_profile->emails) {
1899 len = __ctsvc_vcard_append_emails(my_profile->emails, buf, buf_size, len);
1900 RETV_IF(len < 0, len);
1902 if (my_profile->nicknames) {
1903 len = __ctsvc_vcard_append_nicknames(my_profile->nicknames, buf, buf_size, len);
1904 RETV_IF(len < 0, len);
1906 if (my_profile->urls) {
1907 len = __ctsvc_vcard_append_webs(my_profile->urls, buf, buf_size, len);
1908 RETV_IF(len < 0, len);
1910 if (my_profile->events) {
1911 len = __ctsvc_vcard_append_events(my_profile->events, buf, buf_size, len);
1912 RETV_IF(len < 0, len);
1914 if (my_profile->images) {
1915 len = __ctsvc_vcard_put_photo(my_profile->images, buf, buf_size, len);
1916 RETV_IF(len < 0, len);
1918 if (my_profile->messengers) {
1919 len = __ctsvc_vcard_append_messengers(my_profile->messengers, buf, buf_size, len);
1920 RETV_IF(len < 0, len);
1922 if (my_profile->relationships) {
1923 len = __ctsvc_vcard_append_relationships(my_profile->relationships, buf, buf_size, len);
1924 RETV_IF(len < 0, len);
1927 if (my_profile->uid && DEFAULT_ADDRESS_BOOK_ID == my_profile->addressbook_id) {
1928 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_UID]);
1929 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, my_profile->uid);
1932 if (my_profile->changed_time) {
1934 gmtime_r((time_t *)&my_profile->changed_time, &ts);
1935 char temp[VCARD_ITEM_LENGTH] = {0};
1936 snprintf(temp, sizeof(temp), "%s:%04d-%02d-%02dT%02d:%02d:%02dZ%s",
1937 content_name[CTSVC_VCARD_VALUE_REV],
1938 1900+ts.tm_year, 1+ts.tm_mon, ts.tm_mday,
1939 ts.tm_hour, ts.tm_min, ts.tm_sec,
1942 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, temp);
1946 ctsvc_list_s *profile;
1951 static inline int __ctsvc_vcard_append_start_vcard_3_0(char **buf, int *buf_size, int len)
1953 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, "BEGIN:VCARD");
1954 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, CTSVC_CRLF);
1955 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, "VERSION:3.0");
1956 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, CTSVC_CRLF);
1960 static inline int __ctsvc_vcard_append_end_vcard(char **buf, int *buf_size, int len)
1962 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, "END:VCARD");
1963 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, CTSVC_CRLF);
1967 static int __ctsvc_vcard_make(ctsvc_contact_s *contact, char **vcard_stream)
1970 int buf_size = VCARD_INIT_LENGTH;
1973 __ctsvc_vcard_initial();
1975 buf = calloc(1, buf_size);
1977 /* LCOV_EXCL_START */
1978 ERR("calloc() Fail");
1979 return CONTACTS_ERROR_OUT_OF_MEMORY;
1980 /* LCOV_EXCL_STOP */
1983 len = __ctsvc_vcard_append_start_vcard_3_0(&buf, &buf_size, len);
1985 /* LCOV_EXCL_START */
1987 return CONTACTS_ERROR_OUT_OF_MEMORY;
1988 /* LCOV_EXCL_STOP */
1991 len = __ctsvc_vcard_append_contact(contact, &buf, &buf_size, len);
1993 /* LCOV_EXCL_START */
1995 return CONTACTS_ERROR_OUT_OF_MEMORY;
1996 /* LCOV_EXCL_STOP */
1999 len = __ctsvc_vcard_append_end_vcard(&buf, &buf_size, len);
2001 /* LCOV_EXCL_START */
2003 return CONTACTS_ERROR_OUT_OF_MEMORY;
2004 /* LCOV_EXCL_STOP */
2007 len = __ctsvc_vcard_add_folding(&buf, &buf_size, len);
2009 /* LCOV_EXCL_START */
2011 return CONTACTS_ERROR_OUT_OF_MEMORY;
2012 /* LCOV_EXCL_STOP */
2014 *vcard_stream = buf;
2016 return CONTACTS_ERROR_NONE;
2019 static int __ctsvc_vcard_make_from_my_profile(ctsvc_my_profile_s *my_profile, char **vcard_stream)
2022 int buf_size = VCARD_INIT_LENGTH;
2025 __ctsvc_vcard_initial();
2027 buf = calloc(1, buf_size);
2029 /* LCOV_EXCL_START */
2030 ERR("calloc() Fail");
2031 return CONTACTS_ERROR_OUT_OF_MEMORY;
2032 /* LCOV_EXCL_STOP */
2035 len = __ctsvc_vcard_append_start_vcard_3_0(&buf, &buf_size, len);
2037 /* LCOV_EXCL_START */
2039 return CONTACTS_ERROR_OUT_OF_MEMORY;
2040 /* LCOV_EXCL_STOP */
2043 len = __ctsvc_vcard_append_my_profile(my_profile, &buf, &buf_size, len);
2045 /* LCOV_EXCL_START */
2047 return CONTACTS_ERROR_OUT_OF_MEMORY;
2048 /* LCOV_EXCL_STOP */
2051 len = __ctsvc_vcard_append_end_vcard(&buf, &buf_size, len);
2053 /* LCOV_EXCL_START */
2055 return CONTACTS_ERROR_OUT_OF_MEMORY;
2056 /* LCOV_EXCL_STOP */
2059 len = __ctsvc_vcard_add_folding(&buf, &buf_size, len);
2061 /* LCOV_EXCL_START */
2063 return CONTACTS_ERROR_OUT_OF_MEMORY;
2064 /* LCOV_EXCL_STOP */
2067 *vcard_stream = buf;
2069 return CONTACTS_ERROR_NONE;
2072 EXPORT_API int contacts_vcard_make_from_contact(contacts_record_h record, char **vcard_stream)
2074 CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
2075 ctsvc_contact_s *contact;
2076 RETV_IF(NULL == vcard_stream, CONTACTS_ERROR_INVALID_PARAMETER);
2077 *vcard_stream = NULL;
2079 RETVM_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER,
2080 "contact(%p), vcard_stream(%p)", record, vcard_stream);
2082 contact = (ctsvc_contact_s*)record;
2083 RETVM_IF(CTSVC_RECORD_CONTACT != contact->base.r_type, CONTACTS_ERROR_INVALID_PARAMETER,
2084 "The record is not conatct record (type : %d)", contact->base.r_type);
2086 return __ctsvc_vcard_make(contact, vcard_stream);
2089 EXPORT_API int contacts_vcard_make_from_my_profile(contacts_record_h record, char **vcard_stream)
2091 CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
2092 ctsvc_my_profile_s *my_profile;
2093 RETV_IF(NULL == vcard_stream, CONTACTS_ERROR_INVALID_PARAMETER);
2094 *vcard_stream = NULL;
2096 RETVM_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER,
2097 "my_profile(%p), vcard_stream(%p)", record, vcard_stream);
2099 my_profile = (ctsvc_my_profile_s*)record;
2100 RETVM_IF(CTSVC_RECORD_MY_PROFILE != my_profile->base.r_type, CONTACTS_ERROR_INVALID_PARAMETER,
2101 "The record is not conatct record (type : %d)", my_profile->base.r_type);
2103 return __ctsvc_vcard_make_from_my_profile(my_profile, vcard_stream);
2106 #ifdef _CONTACTS_IPC_CLIENT
2107 static int __ctsvc_vcard_append_person(ctsvc_person_s *person, ctsvc_list_s *list_contacts, char **buf, int *buf_size, int len)
2109 time_t changed_time = 0;
2110 ctsvc_contact_s *contact;
2111 GList *cursor = NULL;
2113 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2114 contact = cursor->data;
2115 if (contact && contact->id == person->name_contact_id && contact->name) {
2116 len = __ctsvc_vcard_append_name(contact->name, buf, buf_size, len);
2117 RETV_IF(len < 0, len);
2121 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2122 contact = cursor->data;
2123 if (contact && contact->company && contact->company->cursor) {
2124 len = __ctsvc_vcard_append_company(contact->company, buf, buf_size, len);
2125 RETV_IF(len < 0, len);
2129 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2130 contact = cursor->data;
2131 if (contact && contact->note && contact->note->cursor) {
2132 len = __ctsvc_vcard_append_note(contact->note, buf, buf_size, len);
2133 RETV_IF(len < 0, len);
2136 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2137 contact = cursor->data;
2138 if (contact && contact->postal_addrs && contact->postal_addrs->cursor) {
2139 len = __ctsvc_vcard_append_postals(contact->postal_addrs, buf, buf_size, len);
2140 RETV_IF(len < 0, len);
2143 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2144 contact = cursor->data;
2145 if (contact && contact->numbers && contact->numbers->cursor) {
2146 len = __ctsvc_vcard_append_numbers(contact->numbers, buf, buf_size, len);
2147 RETV_IF(len < 0, len);
2151 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2152 contact = cursor->data;
2153 if (contact && contact->emails && contact->emails->cursor) {
2154 len = __ctsvc_vcard_append_emails(contact->emails, buf, buf_size, len);
2155 RETV_IF(len < 0, len);
2159 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2160 contact = cursor->data;
2161 if (contact && contact->nicknames && contact->nicknames->cursor) {
2162 len = __ctsvc_vcard_append_nicknames(contact->nicknames, buf, buf_size, len);
2163 RETV_IF(len < 0, len);
2166 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2167 contact = cursor->data;
2168 if (contact && contact->urls && contact->urls->cursor) {
2169 len = __ctsvc_vcard_append_webs(contact->urls, buf, buf_size, len);
2170 RETV_IF(len < 0, len);
2174 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2175 contact = cursor->data;
2176 if (contact && contact->events && contact->events->cursor) {
2177 len = __ctsvc_vcard_append_events(contact->events, buf, buf_size, len);
2178 RETV_IF(len < 0, len);
2181 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2182 contact = cursor->data;
2183 if (contact && contact->images && contact->images->cursor) {
2184 len = __ctsvc_vcard_put_photo(contact->images, buf, buf_size, len);
2185 RETV_IF(len < 0, len);
2188 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2189 contact = cursor->data;
2190 if (contact && contact->messengers && contact->messengers->cursor) {
2191 len = __ctsvc_vcard_append_messengers(contact->messengers, buf, buf_size, len);
2192 RETV_IF(len < 0, len);
2196 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2197 contact = cursor->data;
2198 if (contact && contact->relationships && contact->relationships->cursor) {
2199 len = __ctsvc_vcard_append_relationships(contact->relationships, buf, buf_size, len);
2200 RETV_IF(len < 0, len);
2204 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2205 contact = cursor->data;
2206 if (contact && contact->uid && DEFAULT_ADDRESS_BOOK_ID == contact->addressbook_id) {
2207 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_UID]);
2208 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, contact->uid);
2211 for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2212 contact = cursor->data;
2213 if (contact && changed_time < contact->changed_time)
2214 changed_time = contact->changed_time;
2219 gmtime_r(&changed_time, &ts);
2220 char temp[VCARD_ITEM_LENGTH] = {0};
2221 snprintf(temp, sizeof(temp), "%s:%04d-%02d-%02dT%02d:%02d:%02dZ%s",
2222 content_name[CTSVC_VCARD_VALUE_REV],
2223 1900+ts.tm_year, 1+ts.tm_mon, ts.tm_mday,
2224 ts.tm_hour, ts.tm_min, ts.tm_sec,
2227 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, temp);
2231 ctsvc_list_s *profile;
2235 #endif /* _CONTACTS_IPC_CLIENT */
2237 #ifdef _CONTACTS_IPC_CLIENT
2238 static int __ctsvc_vcard_make_from_person(ctsvc_person_s *person, ctsvc_list_s *list_contacts,
2239 char **vcard_stream)
2242 int buf_size = VCARD_INIT_LENGTH;
2245 RETV_IF(NULL == vcard_stream, CONTACTS_ERROR_INVALID_PARAMETER);
2246 *vcard_stream = NULL;
2248 __ctsvc_vcard_initial();
2250 buf = calloc(1, buf_size);
2252 /* LCOV_EXCL_START */
2253 ERR("calloc() Fail");
2254 return CONTACTS_ERROR_OUT_OF_MEMORY;
2255 /* LCOV_EXCL_STOP */
2258 len = __ctsvc_vcard_append_start_vcard_3_0(&buf, &buf_size, len);
2260 /* LCOV_EXCL_START */
2262 return CONTACTS_ERROR_OUT_OF_MEMORY;
2263 /* LCOV_EXCL_STOP */
2266 len = __ctsvc_vcard_append_person(person, list_contacts, &buf, &buf_size, len);
2268 /* LCOV_EXCL_START */
2270 return CONTACTS_ERROR_OUT_OF_MEMORY;
2271 /* LCOV_EXCL_STOP */
2273 len = __ctsvc_vcard_append_end_vcard(&buf, &buf_size, len);
2275 /* LCOV_EXCL_START */
2277 return CONTACTS_ERROR_OUT_OF_MEMORY;
2278 /* LCOV_EXCL_STOP */
2281 len = __ctsvc_vcard_add_folding(&buf, &buf_size, len);
2283 /* LCOV_EXCL_START */
2285 return CONTACTS_ERROR_OUT_OF_MEMORY;
2286 /* LCOV_EXCL_STOP */
2289 *vcard_stream = buf;
2291 return CONTACTS_ERROR_NONE;
2293 #endif /* _CONTACTS_IPC_CLIENT */
2295 #ifdef _CONTACTS_IPC_CLIENT
2296 EXPORT_API int contacts_vcard_make_from_person(contacts_record_h record, char **vcard_stream)
2298 CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
2300 ctsvc_person_s *person;
2301 contacts_query_h query = NULL;
2302 contacts_filter_h filter = NULL;
2303 contacts_list_h list = NULL;
2305 RETVM_IF(NULL == record || NULL == vcard_stream, CONTACTS_ERROR_INVALID_PARAMETER,
2306 "person(%p), vcard_stream(%p)", record, vcard_stream);
2307 *vcard_stream = NULL;
2309 person = (ctsvc_person_s*)record;
2311 RETVM_IF(CTSVC_RECORD_PERSON != person->base.r_type, CONTACTS_ERROR_INVALID_PARAMETER,
2312 "The record is not conatct record (type : %d)", person->base.r_type);
2315 if (CONTACTS_ERROR_NONE != (ret = contacts_filter_create(_contacts_contact._uri, &filter))) break;
2316 if (CONTACTS_ERROR_NONE != (ret = contacts_filter_add_int(filter, _contacts_contact.person_id, CONTACTS_MATCH_EQUAL, person->person_id))) break;
2317 if (CONTACTS_ERROR_NONE != (ret = contacts_query_create(_contacts_contact._uri, &query))) break;
2318 if (CONTACTS_ERROR_NONE != (ret = contacts_query_set_filter(query, filter))) break;
2319 if (CONTACTS_ERROR_NONE != (ret = contacts_db_get_records_with_query(query, 0, 0, &list))) break;
2320 if (CONTACTS_ERROR_NONE != (ret = __ctsvc_vcard_make_from_person(person, (ctsvc_list_s*)list, vcard_stream))) break;
2322 WARN_IF(CONTACTS_ERROR_NONE != ret, "__ctsvc_vcard_make_from_person() Fail(%d)", ret);
2323 contacts_query_destroy(query);
2324 contacts_filter_destroy(filter);
2325 contacts_list_destroy(list, true);
2330 static inline char* __ctsvc_vcard_remove_empty_line(char *src)
2333 if ('\n' != *src && '\r' != *src)
2340 static char* __ctsvc_vcard_check_word(char *src, const char *word)
2344 RETV_IF(NULL == src, NULL);
2346 src = __ctsvc_vcard_remove_empty_line(src);
2362 while (*src == *word) {
2366 if ('\0' == *src || '\0' == *word)
2376 static int __ctsvc_vcard_check_content_type(char **vcard)
2381 for (i = CTSVC_VCARD_VALUE_NONE+1; i < CTSVC_VCARD_VALUE_MAX; i++) {
2382 new_start = __ctsvc_vcard_check_word(*vcard, content_name[i]);
2383 if (new_start && (':' == *new_start || ';' == *new_start))
2387 if (CTSVC_VCARD_VALUE_MAX == i) {
2388 return CTSVC_VCARD_VALUE_NONE;
2395 static bool __ctsvc_vcard_has_unsupported_format(const char *row)
2397 RETV_IF(NULL == row, false);
2399 char *xcustom1 = strstr(row, "XCUSTOM");
2400 char *xcustom2 = strstr(row, "X-CUSTOM");
2401 char *quoted1 = strstr(row, "QUOTEDPRINTABLE");
2402 char *quoted2 = strstr(row, "QUOTED-PRINTABLE");
2403 char *end_of_raw = strchr(row, '\n');
2404 bool has_xcustom = false;
2405 bool has_quoted = false;
2407 if ((xcustom1 != NULL && xcustom1 < end_of_raw) ||(xcustom2 != NULL && xcustom2 < end_of_raw))
2410 if ((quoted1 != NULL && quoted1 < end_of_raw) ||(quoted2 != NULL && quoted2 < end_of_raw))
2413 /* quoted-printable is not supported in custom type */
2414 if (has_xcustom && has_quoted) {
2415 INFO("This row has unsupported format");
2422 static inline char* __ctsvc_vcard_pass_unsupported(char *vcard)
2433 static char* __ctsvc_strtok(char *val, char c)
2435 char *before = NULL;
2437 if (*val == c && (NULL == before || *before != '\\')) {
2447 static inline bool __ctsvc_vcard_check_base64_encoded(char *src)
2454 ret = strncmp(tmp, "BASE64", sizeof("BASE64") - 1);
2455 if (STRING_EQUAL == ret)
2457 } else if (':' == *tmp || '\r' == *tmp) {
2465 static inline int __ctsvc_vcard_check_quoted(char *src, int max, int *quoted)
2468 if (TRUE == *quoted)
2471 while (*src && max) {
2473 ret = strncmp(src, "QUOTED-PRINTABLE", sizeof("QUOTED-PRINTABLE") - 1);
2474 if (STRING_EQUAL == ret) {
2478 } else if (':' == *src) {
2487 static inline int __ctsvc_vcard_remove_folding(char *folded_src)
2489 char *result = folded_src;
2491 RETV_IF(NULL == folded_src, CONTACTS_ERROR_INVALID_PARAMETER);
2493 while (*folded_src) {
2494 if ('\r' == *folded_src && '\n' == *(folded_src+1) && ' ' == *(folded_src+2))
2496 else if ('\n' == *folded_src && ' ' == *(folded_src+1))
2499 if ('\0' == *folded_src)
2502 *result = *folded_src;
2507 return CONTACTS_ERROR_NONE;
2510 static inline int __ctsvc_vcard_hex_to_dec(char hex)
2516 return hex - 'a' + 10;
2518 return hex - 'A' + 10;
2523 static inline int __ctsvc_vcard_decode_quoted_val(char *val)
2528 src = strchr(val, ':');
2535 pre = __ctsvc_vcard_hex_to_dec(*(src+1));
2537 *dest = (char)((pre << 4) + __ctsvc_vcard_hex_to_dec(*(src+2)));
2541 if ('\r' == *(src+1) && '\n' == *(src+2))
2555 static inline char* __ctsvc_vcard_translate_charset(char *src, int len)
2562 ret = strncmp(val, "CHARSET", sizeof("CHARSET") - 1);
2563 if (STRING_EQUAL == ret) {
2564 val += sizeof("CHARSET");
2567 } else if (':' == *val) {
2576 UErrorCode err = U_ZERO_ERROR;
2580 char enc[32] = {0}, *dest;
2582 while (';' != *val && ':' != *val)
2586 if (0 == strcasecmp("UTF-8", enc))
2592 src_len = len - (val - src);
2594 temp_size = (src_len+1) * sizeof(UChar);
2595 temp = malloc(temp_size);
2597 ERR("malloc() Fail");
2600 conv = ucnv_open(enc, &err);
2601 WARN_IF(U_FAILURE(err), "ucnv_open() Fail(%d), enc=%s", err, enc);
2602 ucnv_toUChars(conv, temp, temp_size, val, src_len, &err);
2603 WARN_IF(U_FAILURE(err), "ucnv_toUChars() Fail(%d), enc=%s", err, enc);
2606 dest_size = temp_size*2;
2607 dest = malloc(dest_size);
2609 ERR("malloc() Fail");
2613 conv = ucnv_open("UTF-8", &err);
2614 WARN_IF(U_FAILURE(err), "ucnv_open() Fail(%d), enc=%s", err, enc);
2615 ucnv_fromUChars(conv, dest, dest_size, temp, u_strlen(temp), &err);
2616 WARN_IF(U_FAILURE(err), "ucnv_fromUChars() Fail(%d), enc=%s", err, enc);
2625 static void __ctsvc_vcard_get_prefix(char **prefix, const char *src)
2627 char *temp = strchr(src, ':');
2629 int len = (int)temp - (int)src;
2630 *prefix = calloc(len+1, sizeof(char));
2632 snprintf(*prefix, len+1, "%s", src);
2638 static char* __ctsvc_vcard_get_val(int ver, char *src, char **prefix, char **dest)
2644 RETV_IF(NULL == src, NULL);
2645 RETV_IF(NULL == dest, NULL);
2664 if (CTSVC_VCARD_VER_2_1 == ver) {
2666 if ('=' == *cursor && __ctsvc_vcard_check_quoted(src, cursor - src, "ed)) {
2667 if ('\r' == *(cursor+1) && '\n' == *(cursor+2))
2670 if ('\r' == *cursor && '\n' == *(cursor+1) && ' ' != *(cursor+2))
2672 if ('\n' == *cursor && ' ' != *(cursor+1))
2680 if ('\r' == *cursor && '\n' == *(cursor+1) && ' ' != *(cursor+2))
2683 if ('\n' == *cursor && ' ' != *(cursor+1))
2690 if (src == cursor) {
2695 char temp = *cursor;
2699 __ctsvc_vcard_get_prefix(prefix, src);
2702 *dest = strdup(src);
2703 if (NULL == *dest) {
2704 ERR("strdup() Fail");
2707 if (CTSVC_VCARD_VER_2_1 != ver)
2708 __ctsvc_vcard_remove_folding(*dest);
2710 if (__ctsvc_vcard_check_quoted(*dest, -1, "ed))
2711 len = __ctsvc_vcard_decode_quoted_val(*dest);
2713 len = strlen(*dest);
2714 new_dest = __ctsvc_vcard_translate_charset(*dest, len);
2720 return (cursor + 1);
2724 static inline char* __ctsvc_get_content_value(char *val)
2728 temp = strchr(val, ':');
2734 RETVM_IF('\0' == *(temp) || '\r' == *(temp) || '\n' == *(temp),
2735 NULL, "Invalid vcard content");
2740 static char* __ctsvc_vcard_remove_escape_char(char *str)
2742 char *s = SAFE_STR(str);
2745 if (*s == '\\' && *(s+1)) {
2746 char *n = (char*)(s+1);
2762 case 0xA1: /* en/em backslash */
2763 if (*(n+1) && 0xAC == *(n+1)) {
2770 case 0x81: /* en/em backslash */
2771 if (*(n+1) && 0x5F == *(n+1)) {
2794 static inline int __ctsvc_vcard_get_display_name(ctsvc_list_s *name_list, char *val)
2799 char *first_name = NULL;
2800 char *last_name = NULL;
2801 contacts_record_h name;
2803 temp = __ctsvc_get_content_value(val);
2804 RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "vcard");
2806 contacts_list_get_count((contacts_list_h)name_list, &count);
2808 ret = contacts_record_create(_contacts_name._uri, &name);
2809 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create is Fail(%d)", ret);
2810 contacts_list_add((contacts_list_h)name_list, name);
2812 contacts_list_get_current_record_p((contacts_list_h)name_list, &name);
2815 ret = contacts_record_get_str_p(name, _contacts_name.first, &first_name);
2816 WARN_IF(ret != CONTACTS_ERROR_NONE, "contacts_record_get_str_p is Fail(%d)", ret);
2817 ret = contacts_record_get_str_p(name, _contacts_name.last, &last_name);
2818 WARN_IF(ret != CONTACTS_ERROR_NONE, "contacts_record_get_str_p is Fail(%d)", ret);
2820 if ((NULL == first_name || '\0' == *first_name) && (NULL == last_name || '\0' == *last_name))
2821 contacts_record_set_str(name, _contacts_name.first, __ctsvc_vcard_remove_escape_char(temp));
2823 return CONTACTS_ERROR_NONE;
2826 #define CTS_GET_MULTIPLE_COMPONENT(dest, src, src_temp, separator) \
2828 separator = false; \
2829 while (src_temp && *src_temp) { \
2830 if (*src_temp == ';') { \
2833 src = __ctsvc_vcard_remove_escape_char(src); \
2834 dest = SMART_STRDUP(src); \
2838 else if (*src_temp == '\\') {\
2844 if (false == separator && src && *src) { \
2845 src = __ctsvc_vcard_remove_escape_char(src); \
2846 dest = SMART_STRDUP(src); \
2850 static inline int __ctsvc_vcard_get_name(ctsvc_list_s *name_list, char *val)
2855 contacts_record_h name;
2857 start = __ctsvc_get_content_value(val);
2858 RETV_IF(NULL == start, CONTACTS_ERROR_NO_DATA);
2860 contacts_list_get_count((contacts_list_h)name_list, &count);
2862 ret = contacts_record_create(_contacts_name._uri, &name);
2863 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
2864 contacts_list_add((contacts_list_h)name_list, name);
2866 contacts_list_get_current_record_p((contacts_list_h)name_list, &name);
2869 contacts_record_set_str(name, _contacts_name.first, NULL); /* remove FN */
2872 bool separator = false;
2875 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_name_s*)name)->last, start, start_temp, separator);
2876 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_name_s*)name)->first, start, start_temp, separator);
2877 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_name_s*)name)->addition, start, start_temp, separator);
2878 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_name_s*)name)->prefix, start, start_temp, separator);
2879 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_name_s*)name)->suffix, start, start_temp, separator);
2881 ERR("invalid name type");
2884 return CONTACTS_ERROR_NONE;
2887 static inline int __ctsvc_vcard_get_phonetic_name(ctsvc_list_s *name_list, int type, char *val)
2892 const char separator = ';';
2893 contacts_record_h name;
2895 start = __ctsvc_get_content_value(val);
2896 RETV_IF(NULL == start, CONTACTS_ERROR_NO_DATA);
2898 contacts_list_get_count((contacts_list_h)name_list, &count);
2900 ret = contacts_record_create(_contacts_name._uri, &name);
2901 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
2902 contacts_list_add((contacts_list_h)name_list, name);
2904 contacts_list_get_current_record_p((contacts_list_h)name_list, &name);
2907 __ctsvc_strtok(start, separator);
2908 if (CTSVC_VCARD_VALUE_PHONETIC_FIRST_NAME == type)
2909 contacts_record_set_str(name, _contacts_name.phonetic_first, __ctsvc_vcard_remove_escape_char(start));
2910 else if (CTSVC_VCARD_VALUE_PHONETIC_MIDDLE_NAME == type)
2911 contacts_record_set_str(name, _contacts_name.phonetic_middle, __ctsvc_vcard_remove_escape_char(start));
2912 else if (CTSVC_VCARD_VALUE_PHONETIC_LAST_NAME == type)
2913 contacts_record_set_str(name, _contacts_name.phonetic_last, __ctsvc_vcard_remove_escape_char(start));
2915 return CONTACTS_ERROR_NONE;
2918 static inline int __ctsvc_vcard_get_nickname(ctsvc_list_s *nickname_list, char *val)
2920 int ret = CONTACTS_ERROR_NONE;
2924 const char *separator = ",";
2926 start = __ctsvc_get_content_value(val);
2927 RETV_IF(NULL == start, CONTACTS_ERROR_NO_DATA);
2929 temp = strtok_r(start, separator, &last);
2931 if ('\0' == *temp) continue;
2933 contacts_record_h nickname = NULL;
2934 ret = contacts_record_create(_contacts_nickname._uri, &nickname);
2935 if (ret < CONTACTS_ERROR_NONE) {
2936 GList *cursor = NULL;
2937 ERR("contacts_record_create() Fail(%d)", ret);
2938 for (cursor = nickname_list->records; cursor; cursor = cursor->next)
2939 contacts_record_destroy((contacts_record_h)(cursor->data), true);
2940 g_list_free(nickname_list->records);
2941 nickname_list->records = NULL;
2942 nickname_list->cursor = NULL;
2943 nickname_list->count = 0;
2946 contacts_record_set_str(nickname, _contacts_nickname.name, __ctsvc_vcard_remove_escape_char(start));
2947 contacts_list_add((contacts_list_h)nickname_list, nickname);
2949 temp = strtok_r(NULL, separator, &last);
2952 return CONTACTS_ERROR_NONE;
2955 static inline int __ctsvc_vcard_get_photo(contacts_record_h contact, ctsvc_list_s *image_list, char *prefix, char *val)
2961 char dest[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0};
2962 contacts_record_h image;
2965 temp = strchr(val, ':');
2966 RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "val is invalid");
2970 type = __ctsvc_vcard_get_image_type((const char *)prefix);
2972 buf = g_base64_decode(temp+1, &size);
2973 if ((0 == size) || (NULL == buf)) {
2975 return CONTACTS_ERROR_NONE;
2978 gettimeofday(&tv, NULL);
2979 ret = snprintf(dest, sizeof(dest), "%s/vcard-image-%ld%ld.%s",
2980 CTSVC_VCARD_IMAGE_LOCATION, tv.tv_sec, tv.tv_usec, __ctsvc_get_img_suffix(type));
2982 fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, 0660);
2984 /* LCOV_EXCL_START */
2986 ERR("System : open Fail(%d)", errno);
2987 return CONTACTS_ERROR_SYSTEM;
2988 /* LCOV_EXCL_STOP */
2992 ret = write(fd, buf, size);
2994 if (EINTR == errno) {
2997 ERR("write() Fail(%d)", errno);
3000 if (ENOSPC == errno)
3001 return CONTACTS_ERROR_FILE_NO_SPACE; /* No space */
3003 return CONTACTS_ERROR_SYSTEM; /* IO error */
3012 ret = contacts_record_create(_contacts_image._uri, &image);
3013 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3015 contacts_record_set_str(image, _contacts_image.path, dest);
3016 ((ctsvc_image_s*)image)->is_vcard = true;
3018 contacts_list_add((contacts_list_h)image_list, image);
3020 /* _contacts_contact.image_thumbnail_path is a read-only property */
3021 ((ctsvc_contact_s*)contact)->image_thumbnail_path = strdup(dest);
3023 return CONTACTS_ERROR_NONE;
3027 static inline void __ctsvc_vcard_get_event_type(contacts_record_h event, char *val)
3029 int type = CONTACTS_EVENT_TYPE_OTHER;
3030 char *temp, *result, *last = NULL;
3031 char *lower, *lower_temp;
3033 temp = strtok_r(val, ";", &last);
3035 lower = strdup(temp);
3036 if (NULL == lower) {
3037 ERR("strdup() Fail");
3041 while (*lower_temp) {
3042 *lower_temp = tolower(*lower_temp);
3045 if (strstr(lower, "anniversary")) {
3046 type = CONTACTS_EVENT_TYPE_ANNIVERSARY;
3047 } else if ((result = strstr(lower, "x-"))) {
3048 type = CONTACTS_EVENT_TYPE_CUSTOM;
3049 contacts_record_set_str(event, _contacts_event.label, temp+(result-lower)+2);
3053 temp = strtok_r(NULL, ";", &last);
3055 contacts_record_set_int(event, _contacts_event.type, type);
3059 static inline int __ctsvc_vcard_get_event(ctsvc_list_s *event_list, int type, char *prefix, char *val)
3062 contacts_record_h event;
3063 char *dest, *src, *date;
3065 date = __ctsvc_get_content_value(val);
3068 return CONTACTS_ERROR_INVALID_PARAMETER;
3073 if ('0' <= *src && *src <= '9') {
3078 if (8 <= dest - date)
3082 if ('\0' == *date) {
3083 ERR("date(%s)", date);
3084 return CONTACTS_ERROR_INVALID_PARAMETER;
3087 ret = contacts_record_create(_contacts_event._uri, &event);
3088 if (ret < CONTACTS_ERROR_NONE) {
3089 ERR("contacts_record_create() Fail(%d)", ret);
3093 contacts_record_set_int(event, _contacts_event.date, atoi(date));
3095 if (CTSVC_VCARD_VALUE_BDAY == type)
3096 contacts_record_set_int(event, _contacts_event.type, CONTACTS_EVENT_TYPE_BIRTH);
3097 else if (CTSVC_VCARD_VALUE_X_ANNIVERSARY == type)
3098 contacts_record_set_int(event, _contacts_event.type, CONTACTS_EVENT_TYPE_ANNIVERSARY);
3099 else if (CTSVC_VCARD_VALUE_X_TIZEN_EVENT == type)
3100 __ctsvc_vcard_get_event_type(event, prefix);
3102 contacts_list_add((contacts_list_h)event_list, event);
3103 return CONTACTS_ERROR_NONE;
3107 static inline void __ctsvc_vcard_get_company_type(contacts_record_h company, char *val)
3109 char *temp, *result, *last = NULL;
3110 char *lower, *lower_temp;
3111 int type = CONTACTS_COMPANY_TYPE_OTHER;
3113 temp = strtok_r(val, ";", &last);
3115 lower = strdup(temp);
3116 if (NULL == lower) {
3117 ERR("strdup() Fail");
3121 while (*lower_temp) {
3122 *lower_temp = tolower(*lower_temp);
3126 result = strstr(lower, "work");
3128 type = CONTACTS_COMPANY_TYPE_WORK;
3130 result = strstr(lower, "x-");
3132 type = CONTACTS_COMPANY_TYPE_CUSTOM;
3133 contacts_record_set_str(company, _contacts_company.label, temp+(result-lower)+2);
3137 temp = strtok_r(NULL, ";", &last);
3139 contacts_record_set_int(company, _contacts_company.type, type);
3142 static contacts_record_h __ctsvc_vcard_get_company_empty_record(ctsvc_list_s *company_list, int property_id)
3144 contacts_record_h record_temp = NULL;
3145 contacts_record_h record = NULL;
3146 contacts_list_h list = (contacts_list_h)company_list;
3148 contacts_list_last(list);
3149 while (CONTACTS_ERROR_NONE == contacts_list_get_current_record_p(list, &record_temp)) {
3151 contacts_record_get_str_p(record_temp, property_id, &value);
3152 if (NULL == value) {
3153 record = record_temp;
3156 contacts_list_prev(list);
3162 static inline int __ctsvc_vcard_get_company_value(ctsvc_list_s *company_list, int property_id, char *val)
3165 contacts_record_h company;
3167 company = __ctsvc_vcard_get_company_empty_record(company_list, property_id);
3168 if (NULL == company) {
3169 int ret = contacts_record_create(_contacts_company._uri, &company);
3170 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3171 contacts_list_add((contacts_list_h)company_list, company);
3174 value = __ctsvc_get_content_value(val);
3175 RETV_IF(NULL == value, CONTACTS_ERROR_NO_DATA);
3177 contacts_record_set_str(company, property_id, __ctsvc_vcard_remove_escape_char(value));
3179 return CONTACTS_ERROR_NONE;
3182 static inline int __ctsvc_vcard_get_company(ctsvc_list_s *company_list, char *prefix, char *val)
3184 char *start, *depart;
3185 const char separator = ';';
3186 contacts_record_h company;
3188 company = __ctsvc_vcard_get_company_empty_record(company_list, _contacts_company.name);
3189 if (NULL == company) {
3190 int ret = contacts_record_create(_contacts_company._uri, &company);
3191 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3192 contacts_list_add((contacts_list_h)company_list, company);
3195 start = __ctsvc_get_content_value(val);
3196 RETV_IF(NULL == start, CONTACTS_ERROR_NO_DATA);
3198 depart = __ctsvc_strtok(start, separator);
3199 contacts_record_set_str(company, _contacts_company.name, __ctsvc_vcard_remove_escape_char(start));
3202 __ctsvc_strtok(depart, separator);
3203 contacts_record_set_str(company, _contacts_company.department, __ctsvc_vcard_remove_escape_char(depart));
3206 __ctsvc_vcard_get_company_type(company, prefix);
3208 return CONTACTS_ERROR_NONE;
3211 static inline int __ctsvc_vcard_get_company_logo(ctsvc_list_s *company_list, char *prefix, char *val)
3216 char dest[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0};
3218 contacts_record_h company;
3221 company = __ctsvc_vcard_get_company_empty_record(company_list, _contacts_company.logo);
3222 if (NULL == company) {
3223 ret = contacts_record_create(_contacts_company._uri, &company);
3224 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3225 contacts_list_add((contacts_list_h)company_list, company);
3228 temp = strchr(val, ':');
3229 RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "val is invalid");
3232 type = __ctsvc_vcard_get_image_type((const char *)prefix);
3234 buf = g_base64_decode(temp+1, &size);
3235 if ((0 == size) || (NULL == buf)) {
3237 return CONTACTS_ERROR_NONE;
3240 gettimeofday(&tv, NULL);
3241 ret = snprintf(dest, sizeof(dest), "%s/%d-%ld%ld-logo.%s", CTSVC_VCARD_IMAGE_LOCATION,
3242 getpid(), tv.tv_sec, tv.tv_usec, __ctsvc_get_img_suffix(type));
3244 fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, 0660);
3246 /* LCOV_EXCL_START */
3248 ERR("System : open Fail(%d)", errno);
3249 return CONTACTS_ERROR_SYSTEM;
3250 /* LCOV_EXCL_STOP */
3254 ret = write(fd, buf, size);
3256 if (EINTR == errno) {
3259 ERR("write() Fail(%d)", errno);
3262 if (ENOSPC == errno)
3263 return CONTACTS_ERROR_FILE_NO_SPACE; /* No space */
3265 return CONTACTS_ERROR_SYSTEM; /* IO error */
3274 ((ctsvc_company_s*)company)->is_vcard = true;
3275 contacts_record_set_str(company, _contacts_company.logo, dest);
3277 return CONTACTS_ERROR_NONE;
3280 static inline int __ctsvc_vcard_get_note(ctsvc_list_s *note_list, char *val)
3284 contacts_record_h note;
3286 ret = contacts_record_create(_contacts_note._uri, ¬e);
3287 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3288 contacts_list_add((contacts_list_h)note_list, note);
3290 temp = __ctsvc_get_content_value(val);
3291 RETV_IF(NULL == temp, CONTACTS_ERROR_NO_DATA);
3293 contacts_record_set_str(note, _contacts_note.note, __ctsvc_vcard_remove_escape_char(temp));
3295 return CONTACTS_ERROR_NONE;
3298 static inline int __ctsvc_vcard_get_time(char *val)
3305 while (*val && (*val < '0' || '9' < *val)) val++;
3309 if (4 <= i || *val < '0' || '9' < *val) break;
3312 ts.tm_year = atoi(tmp)-1900;
3315 while (*val && (*val < '0' || '9' < *val)) val++;
3319 if (2 <= i || *val < '0' || '9' < *val) break;
3322 ts.tm_mon = atoi(tmp)-1;
3325 while (*val && (*val < '0' || '9' < *val)) val++;
3329 if (2 <= i || *val < '0' || '9' < *val) break;
3332 ts.tm_mday = atoi(tmp);
3335 while (*val && (*val < '0' || '9' < *val)) val++;
3339 if (2 <= i || *val < '0' || '9' < *val) break;
3342 ts.tm_hour = atoi(tmp);
3345 while (*val && (*val < '0' || '9' < *val)) val++;
3349 if (2 <= i || *val < '0' || '9' < *val) break;
3352 ts.tm_min = atoi(tmp);
3355 while (*val && (*val < '0' || '9' < *val)) val++;
3359 if (2 <= i || *val < '0' || '9' < *val) break;
3362 ts.tm_sec = atoi(tmp);
3364 return (int)mktime(&ts);
3367 static inline void __ctsvc_vcard_get_url_type(contacts_record_h url, char *val)
3369 char *temp, *result, *last = NULL;
3370 char *lower, *lower_temp;
3371 int type = CONTACTS_URL_TYPE_OTHER;
3373 temp = strtok_r(val, ";", &last);
3375 lower = strdup(temp);
3376 if (NULL == lower) {
3377 ERR("strdup() Fail");
3381 while (*lower_temp) {
3382 *lower_temp = tolower(*lower_temp);
3385 result = strstr(lower, "home");
3386 if (result) type = CONTACTS_URL_TYPE_HOME;
3387 result = strstr(lower, "work");
3388 if (result) type = CONTACTS_URL_TYPE_WORK;
3389 result = strstr(lower, "x-");
3391 type = CONTACTS_URL_TYPE_CUSTOM;
3392 contacts_record_set_str(url, _contacts_url.label, temp+(result-lower)+2);
3396 temp = strtok_r(NULL, ";", &last);
3398 contacts_record_set_int(url, _contacts_url.type, type);
3401 static inline int __ctsvc_vcard_get_url(ctsvc_list_s *url_list, char *prefix, char *val)
3404 contacts_record_h url;
3407 temp = __ctsvc_get_content_value(val);
3408 RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "vcard");
3410 ret = contacts_record_create(_contacts_url._uri, &url);
3411 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3413 contacts_record_set_str(url, _contacts_url.url, __ctsvc_vcard_remove_escape_char(temp));
3414 __ctsvc_vcard_get_url_type(url, prefix);
3415 contacts_list_add((contacts_list_h)url_list, url);
3417 return CONTACTS_ERROR_NONE;
3420 static inline bool __ctsvc_vcard_get_number_type(contacts_record_h number, char *val)
3422 char *temp, *result, *last = NULL;
3423 char *lower, *lower_temp;
3424 int type = CONTACTS_NUMBER_TYPE_OTHER;
3427 temp = strtok_r(val, ";", &last);
3429 lower = strdup(temp);
3430 if (NULL == lower) {
3431 ERR("strdup() Fail");
3435 while (*lower_temp) {
3436 *lower_temp = tolower(*lower_temp);
3439 result = strstr(lower, "home");
3440 if (result) type |= CONTACTS_NUMBER_TYPE_HOME;
3441 result = strstr(lower, "msg");
3442 if (result) type |= CONTACTS_NUMBER_TYPE_MSG;
3443 result = strstr(lower, "work");
3444 if (result) type |= CONTACTS_NUMBER_TYPE_WORK;
3445 result = strstr(lower, "pref");
3446 if (result) pref = true;
3447 result = strstr(lower, "voice");
3448 if (result) type |= CONTACTS_NUMBER_TYPE_VOICE;
3449 result = strstr(lower, "fax");
3450 if (result) type |= CONTACTS_NUMBER_TYPE_FAX;
3451 result = strstr(lower, "cell");
3452 if (result) type |= CONTACTS_NUMBER_TYPE_CELL;
3453 result = strstr(lower, "video");
3454 if (result) type |= CONTACTS_NUMBER_TYPE_VIDEO;
3455 result = strstr(lower, "pager");
3456 if (result) type |= CONTACTS_NUMBER_TYPE_PAGER;
3457 result = strstr(lower, "bbs");
3458 if (result) type |= CONTACTS_NUMBER_TYPE_BBS;
3459 result = strstr(lower, "modem");
3460 if (result) type |= CONTACTS_NUMBER_TYPE_MODEM;
3461 result = strstr(lower, "car");
3462 if (result) type |= CONTACTS_NUMBER_TYPE_CAR;
3463 result = strstr(lower, "isdn");
3464 if (result) type |= CONTACTS_NUMBER_TYPE_ISDN;
3465 result = strstr(lower, "pcs");
3466 if (result) type |= CONTACTS_NUMBER_TYPE_PCS;
3467 result = strstr(lower, "x-");
3469 if (strstr(lower, "x-assistant")) {
3470 type |= CONTACTS_NUMBER_TYPE_ASSISTANT;
3471 } else if (strstr(lower, "x-radio")) {
3472 type |= CONTACTS_NUMBER_TYPE_RADIO;
3473 } else if (strstr(lower, "x-company-main")) {
3474 type |= CONTACTS_NUMBER_TYPE_COMPANY_MAIN;
3475 } else if (strstr(lower, "x-main")) {
3476 type |= CONTACTS_NUMBER_TYPE_MAIN;
3478 type = CONTACTS_NUMBER_TYPE_CUSTOM;
3479 contacts_record_set_str(number, _contacts_number.label, temp+(result-lower)+2);
3484 temp = strtok_r(NULL, ";", &last);
3486 contacts_record_set_int(number, _contacts_number.type, type);
3491 static char* __ctsvc_vcard_get_clean_number_for_import(char *str)
3494 char *s = SAFE_STR(str);
3497 char_len = __ctsvc_vcard_check_utf8(*s);
3498 if (3 == char_len) {
3500 if (*(s+1) == 0xbc) {
3501 if (0x90 <= *(s+2) && *(s+2) <= 0x99) { /* ef bc 90 : '0' ~ ef bc 99 : '9' */
3502 *r = '0' + (*(s+2) - 0x90);
3505 } else if (0x8b == *(s+2)) { /* ef bc 8b : '+' */
3509 } else if (0x8a == *(s+2)) { /* ef bc 8a : '*' */
3513 } else if (0x83 == *(s+2)) { /* ef bc 83 : '#' */
3517 } else if (0xb0 == *(s+2) || 0x8c == *(s+2)) { /* ef bc b0 : 'P', ef bc 8c : ',' */
3521 } else if (0xb7 == *(s+2) || 0x9b == *(s+2)) { /* ef bc b7 : 'W', ef bc 9b : ';' */
3528 } else if (*(s+1) == 0xbd) {
3529 if (0x90 == *(s+2)) {
3533 } else if (0x97 == *(s+2)) {
3544 } else if (1 == char_len) {
3598 static inline int __ctsvc_vcard_get_number(ctsvc_list_s *numbers, char *prefix, char *val)
3603 contacts_record_h number;
3605 temp = __ctsvc_get_content_value(val);
3606 RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "vcard");
3608 ret = contacts_record_create(_contacts_number._uri, &number);
3609 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3611 temp = __ctsvc_vcard_remove_escape_char(temp);
3612 contacts_record_set_str(number, _contacts_number.number, __ctsvc_vcard_get_clean_number_for_import(temp));
3614 is_default = __ctsvc_vcard_get_number_type(number, prefix);
3615 contacts_record_set_bool(number, _contacts_number.is_default, is_default);
3616 contacts_list_add((contacts_list_h)numbers, number);
3618 return CONTACTS_ERROR_NONE;
3621 static inline bool __ctsvc_vcard_get_email_type(contacts_record_h email, char *val)
3623 char *temp, *result, *last = NULL;
3624 char *lower, *lower_temp;
3625 int type = CONTACTS_EMAIL_TYPE_OTHER;
3628 temp = strtok_r(val, ";", &last);
3630 lower = strdup(temp);
3631 if (NULL == lower) {
3632 ERR("strdup() Fail");
3636 while (*lower_temp) {
3637 *lower_temp = tolower(*lower_temp);
3640 if (strstr(lower, "pref"))
3643 if (strstr(lower, "home")) {
3644 type = CONTACTS_EMAIL_TYPE_HOME;
3645 } else if (strstr(lower, "work")) {
3646 type = CONTACTS_EMAIL_TYPE_WORK;
3647 } else if (strstr(lower, "cell")) {
3648 type = CONTACTS_EMAIL_TYPE_MOBILE;
3649 } else if ((result = strstr(lower, "x-"))) {
3650 type = CONTACTS_EMAIL_TYPE_CUSTOM;
3651 contacts_record_set_str(email, _contacts_email.label, temp+(result-lower)+2);
3655 temp = strtok_r(NULL, ";", &last);
3657 contacts_record_set_int(email, _contacts_email.type, type);
3662 static inline int __ctsvc_vcard_get_email(ctsvc_list_s *emails, char *prefix, char *val)
3667 contacts_record_h email;
3669 temp = __ctsvc_get_content_value(val);
3670 RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "vcard");
3672 ret = contacts_record_create(_contacts_email._uri, &email);
3673 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3675 contacts_record_set_str(email, _contacts_email.email, __ctsvc_vcard_remove_escape_char(temp));
3676 is_default = __ctsvc_vcard_get_email_type(email, prefix);
3677 contacts_record_set_bool(email, _contacts_email.is_default, is_default);
3678 contacts_list_add((contacts_list_h)emails, email);
3680 return CONTACTS_ERROR_NONE;
3683 static inline bool __ctsvc_vcard_get_postal_type(contacts_record_h address, char *val)
3685 char *temp, *result, *last = NULL;
3686 char *lower, *lower_temp;
3687 int type = CONTACTS_ADDRESS_TYPE_OTHER;
3690 temp = strtok_r(val, ";", &last);
3692 lower = strdup(temp);
3693 if (NULL == lower) {
3694 ERR("strdup() Fail");
3698 while (*lower_temp) {
3699 *lower_temp = tolower(*lower_temp);
3702 result = strstr(lower, "dom");
3703 if (result) type |= CONTACTS_ADDRESS_TYPE_DOM;
3704 result = strstr(lower, "intl");
3705 if (result) type |= CONTACTS_ADDRESS_TYPE_INTL;
3706 result = strstr(lower, "address");
3707 if (result) type |= CONTACTS_ADDRESS_TYPE_POSTAL;
3708 result = strstr(lower, "parcel");
3709 if (result) type |= CONTACTS_ADDRESS_TYPE_PARCEL;
3710 result = strstr(lower, "home");
3711 if (result) type |= CONTACTS_ADDRESS_TYPE_HOME;
3712 result = strstr(lower, "work");
3713 if (result) type |= CONTACTS_ADDRESS_TYPE_WORK;
3714 result = strstr(lower, "x-");
3716 type = CONTACTS_ADDRESS_TYPE_CUSTOM;
3717 contacts_record_set_str(address, _contacts_address.label, temp+(result-lower)+2);
3719 result = strstr(val, "pref");
3720 if (result) pref = true;
3723 temp = strtok_r(NULL, ";", &last);
3726 contacts_record_set_int(address, _contacts_address.type, type);
3731 static inline int __ctsvc_vcard_get_address(ctsvc_list_s *address_list, char *prefix, char *val)
3735 contacts_record_h address;
3737 contacts_record_create(_contacts_address._uri, &address);
3740 text = strchr(val, ':');
3749 bool separator = false;
3751 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_address_s*)address)->pobox, text, text_temp, separator);
3752 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_address_s*)address)->extended, text, text_temp, separator);
3753 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_address_s*)address)->street, text, text_temp, separator);
3754 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_address_s*)address)->locality, text, text_temp, separator);
3755 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_address_s*)address)->region, text, text_temp, separator);
3756 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_address_s*)address)->postalcode, text, text_temp, separator);
3757 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_address_s*)address)->country, text, text_temp, separator);
3759 ERR("invalid ADR type");
3762 if (((ctsvc_address_s*)address)->pobox || ((ctsvc_address_s*)address)->extended
3763 || ((ctsvc_address_s*)address)->street || ((ctsvc_address_s*)address)->locality
3764 || ((ctsvc_address_s*)address)->region || ((ctsvc_address_s*)address)->postalcode
3765 || ((ctsvc_address_s*)address)->country) {
3766 contacts_record_set_bool(address, _contacts_address.is_default, __ctsvc_vcard_get_postal_type(address, prefix));
3768 ERR("Invalid vcard");
3769 contacts_record_destroy(address, true);
3770 return CONTACTS_ERROR_INVALID_PARAMETER;
3772 contacts_list_add((contacts_list_h)address_list, address);
3775 return CONTACTS_ERROR_NONE;
3778 static inline void __ctsvc_vcard_get_messenger_type(contacts_record_h messenger, char *val)
3780 char *temp, *result, *last = NULL;
3781 char *lower, *lower_temp;
3782 int type = CONTACTS_MESSENGER_TYPE_OTHER;
3784 temp = strtok_r(val, ";", &last);
3786 lower = strdup(temp);
3787 if (NULL == lower) {
3788 ERR("strdup() Fail");
3792 while (*lower_temp) {
3793 *lower_temp = tolower(*lower_temp);
3796 result = strstr(lower, "facebook");
3797 if (result) type = CONTACTS_MESSENGER_TYPE_FACEBOOK;
3798 result = strstr(lower, "irc");
3799 if (result) type = CONTACTS_MESSENGER_TYPE_IRC;
3800 result = strstr(lower, "x-");
3802 type = CONTACTS_MESSENGER_TYPE_CUSTOM;
3803 contacts_record_set_str(messenger, _contacts_messenger.label, temp+(result-lower)+2);
3806 temp = strtok_r(NULL, ";", &last);
3808 contacts_record_set_int(messenger, _contacts_messenger.type, type);
3811 static inline int __ctsvc_vcard_get_messenger(ctsvc_list_s *messenger_list, int type, char *prefix, char *val)
3814 contacts_record_h messenger;
3817 temp = __ctsvc_get_content_value(val);
3818 RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "vcard");
3820 ret = contacts_record_create(_contacts_messenger._uri, &messenger);
3821 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3823 contacts_record_set_str(messenger, _contacts_messenger.im_id, __ctsvc_vcard_remove_escape_char(temp));
3826 case CTSVC_VCARD_VALUE_X_MSN:
3827 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_WLM);
3829 case CTSVC_VCARD_VALUE_X_YAHOO:
3830 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_YAHOO);
3832 case CTSVC_VCARD_VALUE_X_ICQ:
3833 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_ICQ);
3835 case CTSVC_VCARD_VALUE_X_AIM:
3836 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_AIM);
3838 case CTSVC_VCARD_VALUE_X_JABBER:
3839 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_JABBER);
3841 case CTSVC_VCARD_VALUE_X_SKYPE_USERNAME:
3842 case CTSVC_VCARD_VALUE_X_SKYPE:
3843 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_SKYPE);
3845 case CTSVC_VCARD_VALUE_X_QQ:
3846 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_QQ);
3848 case CTSVC_VCARD_VALUE_X_GOOGLE_TALK:
3849 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_GOOGLE);
3851 case CTSVC_VCARD_VALUE_X_TIZEN_MESSENGER:
3852 __ctsvc_vcard_get_messenger_type(messenger, prefix);
3855 contacts_list_add((contacts_list_h)messenger_list, messenger);
3857 return CONTACTS_ERROR_NONE;
3860 static inline void __ctsvc_vcard_get_relationship_type(contacts_record_h relationship, char *val)
3862 char *temp, *result, *last = NULL;
3863 char *lower, *lower_temp;
3864 int type = CONTACTS_RELATIONSHIP_TYPE_OTHER;
3866 temp = strtok_r(val, ";", &last);
3868 lower = strdup(temp);
3869 if (NULL == lower) {
3870 ERR("strdup() Fail");
3874 while (*lower_temp) {
3875 *lower_temp = tolower(*lower_temp);
3879 if (strstr(lower, "assistant")) {
3880 type = CONTACTS_RELATIONSHIP_TYPE_ASSISTANT;
3881 } else if (strstr(lower, "brother")) {
3882 type = CONTACTS_RELATIONSHIP_TYPE_BROTHER;
3883 } else if (strstr(lower, "child")) {
3884 type = CONTACTS_RELATIONSHIP_TYPE_CHILD;
3885 } else if (strstr(lower, "domestic_partner")) {
3886 type = CONTACTS_RELATIONSHIP_TYPE_DOMESTIC_PARTNER;
3887 } else if (strstr(lower, "father")) {
3888 type = CONTACTS_RELATIONSHIP_TYPE_FATHER;
3889 } else if (strstr(lower, "friend")) {
3890 type = CONTACTS_RELATIONSHIP_TYPE_FRIEND;
3891 } else if (strstr(lower, "manager")) {
3892 type = CONTACTS_RELATIONSHIP_TYPE_MANAGER;
3893 } else if (strstr(lower, "mother")) {
3894 type = CONTACTS_RELATIONSHIP_TYPE_MOTHER;
3895 } else if (strstr(lower, "parent")) {
3896 type = CONTACTS_RELATIONSHIP_TYPE_PARENT;
3897 } else if (strstr(lower, "partner")) {
3898 type = CONTACTS_RELATIONSHIP_TYPE_PARTNER;
3899 } else if (strstr(lower, "referred_by")) {
3900 type = CONTACTS_RELATIONSHIP_TYPE_REFERRED_BY;
3901 } else if (strstr(lower, "relative")) {
3902 type = CONTACTS_RELATIONSHIP_TYPE_RELATIVE;
3903 } else if (strstr(lower, "sister")) {
3904 type = CONTACTS_RELATIONSHIP_TYPE_SISTER;
3905 } else if (strstr(lower, "spouse")) {
3906 type = CONTACTS_RELATIONSHIP_TYPE_SPOUSE;
3907 } else if ((result = strstr(lower, "x-"))) {
3908 type = CONTACTS_RELATIONSHIP_TYPE_CUSTOM;
3909 contacts_record_set_str(relationship, _contacts_relationship.label, temp+(result-lower)+2);
3912 temp = strtok_r(NULL, ";", &last);
3914 contacts_record_set_int(relationship, _contacts_relationship.type, type);
3918 static inline int __ctsvc_vcard_get_relationship(ctsvc_list_s *relationship_list, int type, char *prefix, char *val)
3922 contacts_record_h relationship;
3924 temp = __ctsvc_get_content_value(val);
3925 RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "vcard");
3927 ret = contacts_record_create(_contacts_relationship._uri, &relationship);
3928 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3930 contacts_record_set_str(relationship, _contacts_relationship.name, __ctsvc_vcard_remove_escape_char(temp));
3931 __ctsvc_vcard_get_relationship_type(relationship, prefix);
3932 contacts_list_add((contacts_list_h)relationship_list, relationship);
3934 return CONTACTS_ERROR_NONE;
3938 static char* __ctsvc_vcard_decode_base64_val(char *val)
3941 guchar *decoded_str;
3945 src = strchr(val, ':');
3951 decoded_str = g_base64_decode(src, &size);
3953 dest = calloc((src-val)+size+1, sizeof(char));
3955 g_free(decoded_str);
3956 ERR("calloc() Fail");
3960 snprintf(dest, (src-val)+1, "%s", val);
3961 snprintf(dest+(src-val), size+1, "%s", decoded_str);
3962 g_free(decoded_str);
3967 static inline int __ctsvc_vcard_get_contact(int ver, char *vcard, contacts_record_h *record)
3970 char *cursor, *new_start, *val, *prefix;
3971 ctsvc_contact_s *contact = (ctsvc_contact_s*)*record;
3978 bool base64_encoded = false;
3979 type = __ctsvc_vcard_check_content_type(&cursor);
3980 if (CTSVC_VCARD_VALUE_NONE == type || __ctsvc_vcard_has_unsupported_format(cursor)) {
3981 new_start = __ctsvc_vcard_pass_unsupported(cursor);
3990 if (CTSVC_VCARD_VALUE_PHOTO != type && CTSVC_VCARD_VALUE_LOGO != type)
3991 base64_encoded = __ctsvc_vcard_check_base64_encoded(cursor);
3993 new_start = __ctsvc_vcard_get_val(ver, cursor, &prefix, &val);
3994 if (NULL == new_start) {
4009 if (base64_encoded) {
4010 char *temp = __ctsvc_vcard_decode_base64_val(val);
4012 /* LCOV_EXCL_START */
4013 ERR("__ctsvc_vcard_decode_base64_val() Fail");
4016 return CONTACTS_ERROR_OUT_OF_MEMORY;
4017 /* LCOV_EXCL_STOP */
4024 case CTSVC_VCARD_VALUE_FN:
4025 __ctsvc_vcard_get_display_name(contact->name, val);
4027 case CTSVC_VCARD_VALUE_N:
4028 __ctsvc_vcard_get_name(contact->name, val);
4030 case CTSVC_VCARD_VALUE_PHONETIC_FIRST_NAME:
4031 case CTSVC_VCARD_VALUE_PHONETIC_MIDDLE_NAME:
4032 case CTSVC_VCARD_VALUE_PHONETIC_LAST_NAME:
4033 __ctsvc_vcard_get_phonetic_name(contact->name, type, val);
4035 case CTSVC_VCARD_VALUE_NICKNAME:
4036 __ctsvc_vcard_get_nickname(contact->nicknames, val);
4038 case CTSVC_VCARD_VALUE_PHOTO:
4039 __ctsvc_vcard_get_photo(*record, contact->images, prefix, val);
4041 case CTSVC_VCARD_VALUE_BDAY:
4042 case CTSVC_VCARD_VALUE_X_ANNIVERSARY:
4043 case CTSVC_VCARD_VALUE_X_TIZEN_EVENT:
4044 __ctsvc_vcard_get_event(contact->events, type, prefix, val);
4046 case CTSVC_VCARD_VALUE_ADR:
4047 __ctsvc_vcard_get_address(contact->postal_addrs, prefix, val);
4049 case CTSVC_VCARD_VALUE_TEL:
4050 __ctsvc_vcard_get_number(contact->numbers, prefix, val);
4052 case CTSVC_VCARD_VALUE_EMAIL:
4053 __ctsvc_vcard_get_email(contact->emails, prefix, val);
4055 case CTSVC_VCARD_VALUE_TITLE:
4056 __ctsvc_vcard_get_company_value(contact->company, _contacts_company.job_title, val);
4058 case CTSVC_VCARD_VALUE_ROLE:
4059 __ctsvc_vcard_get_company_value(contact->company, _contacts_company.role, val);
4061 case CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_LOCATION:
4062 __ctsvc_vcard_get_company_value(contact->company, _contacts_company.location, val);
4064 case CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_DESCRIPTION:
4065 __ctsvc_vcard_get_company_value(contact->company, _contacts_company.description, val);
4067 case CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_PHONETIC_NAME:
4068 __ctsvc_vcard_get_company_value(contact->company, _contacts_company.phonetic_name, val);
4070 case CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_ASSISTANT_NAME:
4071 __ctsvc_vcard_get_company_value(contact->company, _contacts_company.assistant_name, val);
4073 case CTSVC_VCARD_VALUE_LOGO:
4074 __ctsvc_vcard_get_company_logo(contact->company, prefix, val);
4076 case CTSVC_VCARD_VALUE_ORG:
4077 __ctsvc_vcard_get_company(contact->company, prefix, val);
4079 case CTSVC_VCARD_VALUE_NOTE:
4080 __ctsvc_vcard_get_note(contact->note, val);
4082 case CTSVC_VCARD_VALUE_REV:
4084 contact->changed_time = __ctsvc_vcard_get_time(val);
4086 case CTSVC_VCARD_VALUE_UID:
4087 contacts_record_set_str((contacts_record_h)contact, _contacts_contact.uid, __ctsvc_vcard_remove_escape_char(val));
4089 case CTSVC_VCARD_VALUE_URL:
4090 __ctsvc_vcard_get_url(contact->urls, prefix, val);
4092 case CTSVC_VCARD_VALUE_X_MSN:
4093 case CTSVC_VCARD_VALUE_X_YAHOO:
4094 case CTSVC_VCARD_VALUE_X_ICQ:
4095 case CTSVC_VCARD_VALUE_X_AIM:
4096 case CTSVC_VCARD_VALUE_X_JABBER:
4097 case CTSVC_VCARD_VALUE_X_SKYPE_USERNAME:
4098 case CTSVC_VCARD_VALUE_X_SKYPE:
4099 case CTSVC_VCARD_VALUE_X_QQ:
4100 case CTSVC_VCARD_VALUE_X_GOOGLE_TALK:
4101 case CTSVC_VCARD_VALUE_X_TIZEN_MESSENGER:
4102 __ctsvc_vcard_get_messenger(contact->messengers, type, prefix, val);
4105 case CTSVC_VCARD_VALUE_X_TIZEN_RELATIONSHIP:
4106 __ctsvc_vcard_get_relationship(contact->relationships, type, prefix, val);
4108 case CTSVC_VCARD_VALUE_END:
4111 return CONTACTS_ERROR_NONE;
4113 ERR("__ctsvc_vcard_check_content_type() Fail(%d)", type);
4116 return CONTACTS_ERROR_INVALID_PARAMETER;
4123 ERR("Invalid vcard");
4124 return CONTACTS_ERROR_INVALID_PARAMETER;
4127 static inline int __ctsvc_vcard_check_version(const char *src)
4130 const char *ver3 = "3.0";
4136 return CTSVC_VCARD_VER_2_1;
4147 if (STRING_EQUAL == strcmp(src, ver3))
4148 return CTSVC_VCARD_VER_3_0;
4150 return CTSVC_VCARD_VER_2_1;
4153 static inline void __ctsvc_vcard_make_contact_display_name(ctsvc_contact_s *contact)
4155 ctsvc_name_s *name = NULL;
4157 free(contact->display_name);
4158 contact->display_name = NULL;
4160 free(contact->reverse_display_name);
4161 contact->reverse_display_name = NULL;
4163 if (0 < contact->name->count && contact->name->records
4164 && contact->name->records->data) {
4165 name = (ctsvc_name_s*)contact->name->records->data;
4168 if (name && (name->first || name->last || name->prefix || name->addition
4170 int reverse_lang_type = -1;
4171 char *display = NULL;
4172 char *reverse_display = NULL;
4173 int len, display_len;
4174 int temp_display_len;
4175 char *temp_display = NULL;
4176 contacts_name_display_order_e name_display_order = CONTACTS_NAME_DISPLAY_ORDER_FIRSTLAST;
4179 * Make reverse display name (Last name first)
4180 * Default : Prefix Last, First Middle(addition), Suffix
4181 * Korean, Chinese : Prefix LastFirstMiddleSuffix
4182 * Japanese : Prefix Last Middle First Suffix
4183 * reverse sort name does not include prefix
4184 * But, if there is only prefix, reverse sort_name is prefix
4186 temp_display_len = SAFE_STRLEN(name->first)
4187 + SAFE_STRLEN(name->addition)
4188 + SAFE_STRLEN(name->last)
4189 + SAFE_STRLEN(name->suffix);
4190 if (0 < temp_display_len) {
4191 temp_display_len += 7;
4192 temp_display = calloc(1, temp_display_len);
4193 if (NULL == temp_display) {
4194 ERR("calloc() Fail");
4201 len += snprintf(temp_display + len, temp_display_len - len, "%s", name->last);
4203 if (reverse_lang_type < 0)
4204 reverse_lang_type = ctsvc_check_language_type(temp_display);
4206 if (reverse_lang_type != CTSVC_LANG_KOREAN &&
4207 reverse_lang_type != CTSVC_LANG_CHINESE &&
4208 reverse_lang_type != CTSVC_LANG_JAPANESE) {
4209 if (name->first || name->addition)
4210 len += snprintf(temp_display + len, temp_display_len - len, ",");
4214 if (reverse_lang_type < 0) {
4216 reverse_lang_type = ctsvc_check_language_type(temp_display);
4217 else if (name->first)
4218 reverse_lang_type = ctsvc_check_language_type(name->first);
4219 else if (name->addition)
4220 reverse_lang_type = ctsvc_check_language_type(name->addition);
4223 if (reverse_lang_type == CTSVC_LANG_JAPANESE) {
4224 /* make temp_display name Prefix - Last - Middle - First - Suffix */
4225 if (name->addition) {
4227 len += snprintf(temp_display + len, temp_display_len - len, " ");
4228 len += snprintf(temp_display + len, temp_display_len - len, "%s", name->addition);
4233 len += snprintf(temp_display + len, temp_display_len - len, " ");
4234 len += snprintf(temp_display + len, temp_display_len - len, "%s", name->first);
4237 /* make temp_display name Prefix - Last - First -Middle - Suffix */
4239 if (*temp_display) {
4240 if (reverse_lang_type < 0)
4241 reverse_lang_type = ctsvc_check_language_type(temp_display);
4243 if (reverse_lang_type != CTSVC_LANG_KOREAN &&
4244 reverse_lang_type != CTSVC_LANG_CHINESE)
4245 len += snprintf(temp_display + len, temp_display_len - len, " ");
4247 len += snprintf(temp_display + len, temp_display_len - len, "%s", name->first);
4250 if (name->addition) {
4251 if (*temp_display) {
4252 if (reverse_lang_type < 0)
4253 reverse_lang_type = ctsvc_check_language_type(temp_display);
4255 if (reverse_lang_type != CTSVC_LANG_KOREAN &&
4256 reverse_lang_type != CTSVC_LANG_CHINESE)
4257 len += snprintf(temp_display + len, temp_display_len - len, " ");
4259 len += snprintf(temp_display + len, temp_display_len - len, "%s", name->addition);
4264 if (*temp_display) {
4265 if (reverse_lang_type < 0)
4266 reverse_lang_type = ctsvc_check_language_type(temp_display);
4268 if (reverse_lang_type == CTSVC_LANG_JAPANESE) {
4269 len += snprintf(temp_display + len, temp_display_len - len, " ");
4270 } else if (reverse_lang_type != CTSVC_LANG_KOREAN &&
4271 reverse_lang_type != CTSVC_LANG_CHINESE) {
4272 len += snprintf(temp_display + len, temp_display_len - len, ", ");
4275 len += snprintf(temp_display + len, temp_display_len - len, "%s", name->suffix);
4279 if (name->prefix && temp_display) {
4280 display_len = SAFE_STRLEN(name->prefix) + temp_display_len + 2;
4281 reverse_display = calloc(1, display_len);
4282 if (NULL == reverse_display) {
4283 ERR("calloc() Fail");
4287 snprintf(reverse_display, display_len, "%s %s", name->prefix, temp_display);
4289 } else if (temp_display) {
4290 reverse_display = temp_display;
4291 } else if (name->prefix) {
4292 reverse_display = strdup(name->prefix);
4296 * Make display name (First name first)
4297 * Default : Prefix First Middle Last, Suffix
4298 * Korean, Chinese : Prefix LastFirstMiddleSuffix (Same as reverse display name)
4299 * Japanese : Prefix First Middle Last Suffix
4300 * sort name does not include prefix
4301 * But, if there is only prefix, sort_name is prefix
4304 if (reverse_lang_type == CTSVC_LANG_KOREAN ||
4305 reverse_lang_type == CTSVC_LANG_CHINESE) {
4306 display = strdup(reverse_display);
4309 temp_display = NULL;
4310 temp_display_len = SAFE_STRLEN(name->first)
4311 + SAFE_STRLEN(name->addition)
4312 + SAFE_STRLEN(name->last)
4313 + SAFE_STRLEN(name->suffix);
4314 if (0 < temp_display_len) {
4315 temp_display_len += 6;
4316 /* make reverse_temp_display_name */
4317 temp_display = calloc(1, temp_display_len);
4318 if (NULL == temp_display) {
4319 ERR("calloc() Fail");
4320 free(reverse_display);
4328 len += snprintf(temp_display + len, temp_display_len - len, " ");
4329 len += snprintf(temp_display + len, temp_display_len - len, "%s", name->first);
4332 if (name->addition) {
4334 len += snprintf(temp_display + len, temp_display_len - len, " ");
4335 len += snprintf(temp_display + len, temp_display_len - len, "%s", name->addition);
4340 len += snprintf(temp_display + len, temp_display_len - len, " ");
4341 len += snprintf(temp_display + len, temp_display_len - len, "%s", name->last);
4345 if (*temp_display) {
4346 lang_type = ctsvc_check_language_type(temp_display);
4347 if (lang_type == CTSVC_LANG_JAPANESE)
4348 len += snprintf(temp_display + len, temp_display_len - len, " ");
4350 len += snprintf(temp_display + len, temp_display_len - len, ", ");
4352 len += snprintf(temp_display + len, temp_display_len - len, "%s", name->suffix);
4356 if (name->prefix && temp_display) {
4357 display_len = SAFE_STRLEN(name->prefix) + temp_display_len + 2;
4358 display = calloc(1, display_len);
4359 if (NULL == display) {
4360 ERR("calloc() Fail");
4362 free(reverse_display);
4365 snprintf(display, display_len, "%s %s", name->prefix, temp_display);
4367 } else if (temp_display) {
4368 display = temp_display;
4369 } else if (name->prefix) {
4370 display = strdup(name->prefix);
4374 #ifdef _CONTACTS_IPC_CLIENT
4375 contacts_setting_get_name_display_order(&name_display_order);
4377 if (CONTACTS_NAME_DISPLAY_ORDER_FIRSTLAST == name_display_order) {
4378 contact->display_name = display;
4379 free(reverse_display);
4380 #ifdef _CONTACTS_IPC_CLIENT
4382 contact->display_name = reverse_display;
4386 contact->display_source_type = CONTACTS_DISPLAY_NAME_SOURCE_TYPE_NAME;
4389 bool set_display_name = false;
4390 if (contact->company && contact->company->records) {
4391 for (cur = contact->company->records; cur; cur = cur->next) {
4392 ctsvc_company_s *company = cur->data;
4393 if (company && company->name) {
4394 set_display_name = true;
4395 contact->display_name = SAFE_STRDUP(company->name);
4396 contact->display_source_type = CONTACTS_DISPLAY_NAME_SOURCE_TYPE_COMPANY;
4402 if (false == set_display_name &&
4403 contact->nicknames && contact->nicknames->records) {
4404 for (cur = contact->nicknames->records; cur; cur = cur->next) {
4405 ctsvc_nickname_s *nickname = cur->data;
4406 if (nickname && nickname->nickname) {
4407 set_display_name = true;
4408 contact->display_name = SAFE_STRDUP(nickname->nickname);
4409 contact->display_source_type = CONTACTS_DISPLAY_NAME_SOURCE_TYPE_NICKNAME;
4415 if (false == set_display_name &&
4416 contact->numbers && contact->numbers->records) {
4417 for (cur = contact->numbers->records; cur; cur = cur->next) {
4418 ctsvc_number_s *number = cur->data;
4419 if (number && number->number) {
4420 set_display_name = true;
4421 contact->display_name = SAFE_STRDUP(number->number);
4422 contact->display_source_type = CONTACTS_DISPLAY_NAME_SOURCE_TYPE_NUMBER;
4428 if (false == set_display_name &&
4429 contact->emails && contact->emails->records) {
4430 for (cur = contact->emails->records; cur; cur = cur->next) {
4431 ctsvc_email_s *email = cur->data;
4432 if (email && email->email_addr) {
4433 set_display_name = true;
4434 contact->display_name = SAFE_STRDUP(email->email_addr);
4435 contact->display_source_type = CONTACTS_DISPLAY_NAME_SOURCE_TYPE_EMAIL;
4444 static void __ctsvc_vcard_update_contact_has_properties(ctsvc_contact_s *contact)
4446 if (contact->numbers && 0 < contact->numbers->count)
4447 contact->has_phonenumber = true;
4449 if (contact->emails && 0 < contact->emails->count)
4450 contact->has_email = true;
4453 static int __ctsvc_vcard_parse(const void *vcard_stream, contacts_record_h *record)
4456 ctsvc_contact_s *contact;
4457 char *val_begin, *new_start, *val;
4458 char *vcard = (char *)vcard_stream;
4460 RETV_IF(NULL == vcard_stream, CONTACTS_ERROR_INVALID_PARAMETER);
4462 __ctsvc_vcard_initial();
4464 vcard = __ctsvc_vcard_check_word(vcard, "BEGIN:VCARD");
4465 RETVM_IF(NULL == vcard, CONTACTS_ERROR_INVALID_PARAMETER, "The vcard is invalid.");
4467 val_begin = __ctsvc_vcard_check_word(vcard, "VERSION:");
4468 new_start = __ctsvc_vcard_get_val(CTSVC_VCARD_VER_NONE, val_begin, NULL, &val);
4469 if (NULL == new_start || NULL == val) {
4470 ver = CTSVC_VCARD_VER_2_1;
4472 ver = __ctsvc_vcard_check_version(val);
4477 contacts_record_create(_contacts_contact._uri, (contacts_record_h*)&contact);
4478 RETVM_IF(NULL == contact, CONTACTS_ERROR_OUT_OF_MEMORY, "Out of memory : contacts_record_create() Fail");
4480 ret = __ctsvc_vcard_get_contact(ver, vcard, (contacts_record_h*)&contact);
4481 if (CONTACTS_ERROR_NONE != ret) {
4482 ERR("cts_vcard_get_contact() Fail(%d)", ret);
4483 contacts_record_destroy((contacts_record_h)contact, true);
4486 __ctsvc_vcard_make_contact_display_name(contact);
4487 __ctsvc_vcard_update_contact_has_properties(contact);
4488 *record = (contacts_record_h)contact;
4489 return CONTACTS_ERROR_NONE;
4492 #define CTSVC_VCARD_MAX_SIZE 1024*1024
4494 static const char* __contacts_vcard_remove_line_break(const char *c)
4497 if ('\r' == *c && '\n' == *(c+1))
4499 else if ('\n' == *c)
4508 const char *pos_start;
4509 const char *pos_end;
4512 static void __contacts_vcard_free_sub_vcard_info_list(GList *list)
4518 for (cursor = list; cursor; cursor = cursor->next) {
4519 sub_vcard_info_s *vcard_info = cursor->data;
4525 static void __contacts_vcard_free_vcard_object_list(GList *list)
4531 for (cursor = list; cursor; cursor = cursor->next) {
4532 char *vcard_object = cursor->data;
4539 static const char* __contacts_vcard_parse_get_vcard_object(const char *cursor, GList **plist_vcard_object)
4541 char *vcard_object = NULL;
4542 bool new_line = false;
4543 const char *begin = "BEGIN:VCARD";
4544 const char *end = "END:VCARD";
4545 const char *vcard_start_cursor = cursor;
4546 const char *vcard_cursor = NULL;
4547 GList *sub_vcard_list = NULL;
4549 RETV_IF(NULL == plist_vcard_object, cursor);
4551 *plist_vcard_object = NULL;
4553 vcard_start_cursor = __contacts_vcard_remove_line_break(vcard_start_cursor);
4555 if (STRING_EQUAL != strncmp(vcard_start_cursor, begin, strlen(begin)))
4556 return vcard_start_cursor;
4558 vcard_cursor = vcard_start_cursor;
4560 vcard_cursor += strlen(begin);
4561 vcard_cursor = __contacts_vcard_remove_line_break(vcard_cursor);
4563 while (*vcard_cursor) {
4565 if (STRING_EQUAL == strncmp(vcard_cursor, end, strlen(end))) {
4566 GList *sub_vcard_cursor = NULL;
4568 const char *pos_start = NULL;
4570 vcard_cursor += strlen(end);
4571 vcard_cursor = __contacts_vcard_remove_line_break(vcard_cursor);
4573 pos_start = vcard_start_cursor;
4574 for (sub_vcard_cursor = sub_vcard_list; sub_vcard_cursor; sub_vcard_cursor = sub_vcard_cursor->next) {
4575 sub_vcard_info_s *sub_vcard_info = sub_vcard_cursor->data;
4576 const char *pos_end = sub_vcard_info->pos_start;
4577 vcard_len += (pos_end - pos_start);
4578 pos_start = sub_vcard_info->pos_end;
4580 vcard_len += (vcard_cursor - pos_start);
4581 vcard_object = calloc(vcard_len + 1, sizeof(char));
4582 if (NULL == vcard_object) {
4583 ERR("calloc() Fail");
4584 __contacts_vcard_free_sub_vcard_info_list(sub_vcard_list);
4589 pos_start = vcard_start_cursor;
4590 for (sub_vcard_cursor = sub_vcard_list; sub_vcard_cursor; sub_vcard_cursor = sub_vcard_cursor->next) {
4591 sub_vcard_info_s *sub_vcard_info = sub_vcard_cursor->data;
4592 const char *pos_end = sub_vcard_info->pos_start;
4593 memcpy(vcard_object+vcard_len, pos_start, pos_end - pos_start);
4594 vcard_len += (pos_end - pos_start);
4595 pos_start = sub_vcard_info->pos_end;
4597 __contacts_vcard_free_sub_vcard_info_list(sub_vcard_list);
4598 memcpy(vcard_object+vcard_len, pos_start, vcard_cursor - pos_start);
4599 *plist_vcard_object = g_list_append(*plist_vcard_object, vcard_object);
4601 return vcard_cursor;
4602 } else if (STRING_EQUAL == strncmp(vcard_cursor, begin, strlen(begin))) {
4604 sub_vcard_info_s *sub_vcard_info = calloc(1, sizeof(sub_vcard_info_s));
4605 if (NULL == sub_vcard_info) {
4606 ERR("calloc() Fail");
4607 __contacts_vcard_free_sub_vcard_info_list(sub_vcard_list);
4610 sub_vcard_info->pos_start = vcard_cursor;
4612 vcard_cursor = __contacts_vcard_parse_get_vcard_object(vcard_cursor, plist_vcard_object);
4613 sub_vcard_info->pos_end = vcard_cursor;
4615 sub_vcard_list = g_list_append(sub_vcard_list, sub_vcard_info);
4621 if (('\n' == *vcard_cursor) || ('\r' == *vcard_cursor && '\n' == *(vcard_cursor+1))) {
4623 vcard_cursor = __contacts_vcard_remove_line_break(vcard_cursor);
4627 __contacts_vcard_free_sub_vcard_info_list(sub_vcard_list);
4629 return vcard_cursor;
4632 EXPORT_API int contacts_vcard_parse_to_contacts(const char *vcard_stream, contacts_list_h *out_contacts)
4634 CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
4636 contacts_record_h record;
4637 contacts_list_h list = NULL;
4638 const char *cursor = NULL;
4639 char *vcard_object = NULL;
4640 GList *list_vcard_object = NULL;
4642 RETV_IF(NULL == out_contacts, CONTACTS_ERROR_INVALID_PARAMETER);
4643 *out_contacts = NULL;
4645 RETV_IF(NULL == vcard_stream, CONTACTS_ERROR_INVALID_PARAMETER);
4647 cursor = vcard_stream;
4648 while ((cursor = __contacts_vcard_parse_get_vcard_object(cursor, &list_vcard_object))) {
4649 GList *vcard_cursor = NULL;
4650 if (NULL == list_vcard_object)
4653 for (vcard_cursor = list_vcard_object; vcard_cursor; vcard_cursor = vcard_cursor->next) {
4654 vcard_object = vcard_cursor->data;
4655 if (NULL == vcard_object)
4658 ret = __ctsvc_vcard_parse(vcard_object, &record);
4659 if (ret < CONTACTS_ERROR_NONE) {
4660 ERR("__ctsvc_vcard_parse() Fail(%d)", ret);
4661 __contacts_vcard_free_vcard_object_list(list_vcard_object);
4662 contacts_list_destroy(list, true);
4667 contacts_list_create(&list);
4668 contacts_list_add(list, record);
4669 vcard_object = NULL;
4671 __contacts_vcard_free_vcard_object_list(list_vcard_object);
4673 *out_contacts = list;
4674 return CONTACTS_ERROR_NONE;
4678 static int _ctsvc_safe_add(unsigned int *total, unsigned int value)
4680 if (UINT_MAX - *total < value) {
4681 /* LCOV_EXCL_START */
4682 ERR("overflow occurs when %d + %d", *total, value);
4683 return CONTACTS_ERROR_SYSTEM;
4684 /* LCOV_EXCL_STOP */
4688 return CONTACTS_ERROR_NONE;
4691 EXPORT_API int contacts_vcard_parse_to_contact_foreach(const char *vcard_file_name,
4692 contacts_vcard_parse_cb cb, void *data)
4694 CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
4695 contacts_record_h record;
4697 unsigned int buf_size, len;
4700 int vcard_depth = 0;
4702 char line[1024] = {0};
4704 RETV_IF(NULL == vcard_file_name, CONTACTS_ERROR_INVALID_PARAMETER);
4705 RETV_IF(NULL == cb, CONTACTS_ERROR_INVALID_PARAMETER);
4707 file = fopen(vcard_file_name, "r");
4708 RETVM_IF(NULL == file, CONTACTS_ERROR_SYSTEM, "fopen() Fail(%d)", errno);
4711 buf_size = CTSVC_VCARD_MAX_SIZE;
4712 stream = malloc(CTSVC_VCARD_MAX_SIZE);
4713 if (NULL == stream) {
4714 /* LCOV_EXCL_START */
4715 ERR("Out of memory : malloc() Fail");
4717 return CONTACTS_ERROR_OUT_OF_MEMORY;
4718 /* LCOV_EXCL_STOP */
4721 while (fgets(line, sizeof(line), file)) {
4723 if (STRING_EQUAL != strncmp(line, "BEGIN:VCARD", strlen("BEGIN:VCARD")))
4726 if (buf_size - len <= strlen(line)) {
4728 buf_size += sizeof(line) * 2;
4729 new_stream = realloc(stream, buf_size);
4731 stream = new_stream;
4733 /* LCOV_EXCL_START */
4736 return CONTACTS_ERROR_OUT_OF_MEMORY;
4737 /* LCOV_EXCL_STOP */
4740 written_len = snprintf(stream + len, buf_size - len, "%s", line);
4741 if (written_len < 0) {
4742 /* LCOV_EXCL_START */
4745 ERR("snprintf() Fail(%d)", written_len);
4746 return CONTACTS_ERROR_SYSTEM;
4747 /* LCOV_EXCL_STOP */
4750 ret = _ctsvc_safe_add(&len, (unsigned int)written_len);
4751 if (CONTACTS_ERROR_NONE != ret) {
4754 ERR("_ctsvc_safe_add() Fail(len:%d, written_len:%d)", len, written_len);
4758 if (STRING_EQUAL == strncmp(line, "END:VCARD", 9)) {
4761 if (0 == vcard_depth) {
4762 const char *cursor = stream;
4763 GList *list_vcard_object = NULL;
4767 while ((cursor = __contacts_vcard_parse_get_vcard_object(cursor, &list_vcard_object))) {
4768 GList *vcard_cursor = NULL;
4769 if (NULL == list_vcard_object)
4772 for (vcard_cursor = list_vcard_object; vcard_cursor; vcard_cursor = vcard_cursor->next) {
4773 char *vcard_object = vcard_cursor->data;
4775 if (NULL == vcard_object)
4778 ret = __ctsvc_vcard_parse(vcard_object, &record);
4779 if (ret < CONTACTS_ERROR_NONE) {
4780 ERR("vcard stream parsing error");
4783 __contacts_vcard_free_vcard_object_list(list_vcard_object);
4787 if (false == cb(record, data)) {
4790 __contacts_vcard_free_vcard_object_list(list_vcard_object);
4791 contacts_record_destroy(record, true);
4792 return CONTACTS_ERROR_NONE;
4794 contacts_record_destroy(record, true);
4796 __contacts_vcard_free_vcard_object_list(list_vcard_object);
4797 list_vcard_object = NULL;
4800 } else if (STRING_EQUAL == strncmp(line, "BEGIN:VCARD", 11)) { /* sub vcard object */
4807 return CONTACTS_ERROR_NONE;
4810 EXPORT_API int contacts_vcard_get_entity_count(const char *vcard_file_name, int *count)
4812 CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
4815 char line[1024] = {0};
4816 RETV_IF(NULL == count, CONTACTS_ERROR_INVALID_PARAMETER);
4819 RETV_IF(NULL == vcard_file_name, CONTACTS_ERROR_INVALID_PARAMETER);
4821 file = fopen(vcard_file_name, "r");
4822 RETVM_IF(NULL == file, CONTACTS_ERROR_SYSTEM, "System : fopen() Fail(%d)", errno);
4825 while (fgets(line, sizeof(line), file)) {
4826 if (STRING_EQUAL == strncmp(line, "END:VCARD", 9))
4833 return CONTACTS_ERROR_NONE;
4836 EXPORT_API int contacts_vcard_get_limit_size_of_photo(unsigned int *limit_size)
4838 CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
4839 #ifdef _CONTACTS_IPC_CLIENT
4841 bool result = false;
4844 RETV_IF(NULL == limit_size, CONTACTS_ERROR_INVALID_PARAMETER);
4846 #ifdef _CONTACTS_IPC_CLIENT
4847 ret = ctsvc_ipc_client_check_permission(CTSVC_PERMISSION_CONTACT_READ, &result);
4848 RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_ipc_client_check_permission() Fail(%d)", ret);
4849 RETVM_IF(result == false, CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied (contact read)");
4852 *limit_size = limit_size_of_photo;
4853 return CONTACTS_ERROR_NONE;
4856 EXPORT_API int contacts_vcard_set_limit_size_of_photo(unsigned int limit_size)
4858 CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
4859 #ifdef _CONTACTS_IPC_CLIENT
4861 bool result = false;
4864 RETV_IF(CTSVC_IMAGE_MAX_SIZE <= limit_size, CONTACTS_ERROR_INVALID_PARAMETER);
4865 RETV_IF(limit_size < 8, CONTACTS_ERROR_INVALID_PARAMETER);
4867 #ifdef _CONTACTS_IPC_CLIENT
4868 ret = ctsvc_ipc_client_check_permission(CTSVC_PERMISSION_CONTACT_WRITE, &result);
4869 RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_ipc_client_check_permission() Fail(%d)", ret);
4870 RETVM_IF(result == false, CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied (contact read)");
4873 limit_size_of_photo = limit_size;
4874 return CONTACTS_ERROR_NONE;