[contacts-service][Non-ACR][SATIZENVUL-1375 privilege escalation]
[platform/core/pim/contacts-service.git] / common / ctsvc_vcard.c
1 /*
2  * Contacts Service
3  *
4  * Copyright (c) 2010 - 2015 Samsung Electronics Co., Ltd. All rights reserved.
5  *
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
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  *
18  */
19 #include <glib.h>
20 #include <errno.h>
21 #include <ctype.h>
22 #include <fcntl.h>
23 #include <unistd.h>
24 #include <sys/time.h>
25 #include <unicode/ucnv.h>
26 #include <unicode/ustring.h>
27 #include <tzplatform_config.h>
28 #include <limits.h>
29
30 #ifdef _CONTACTS_IPC_CLIENT
31 #include "ctsvc_client_ipc.h"
32 #endif
33
34 #include "contacts.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"
41
42 #define DEFAULT_ADDRESS_BOOK_ID 0
43
44 #define SMART_STRDUP(src) (src && *src) ? strdup(src) : NULL
45 #define CTSVC_VCARD_PHOTO_MAX_SIZE 1024*1024
46
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; \
51         } \
52 } while (0)
53
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; \
58         } \
59 } while (0)
60
61
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); \
67 } while (0)
68
69 enum {
70         CTSVC_VCARD_VER_NONE,
71         CTSVC_VCARD_VER_2_1,
72         CTSVC_VCARD_VER_3_0,
73         CTSVC_VCARD_VER_4_0,
74 };
75
76 enum {
77         CTSVC_VCARD_VALUE_NONE,
78         CTSVC_VCARD_VALUE_FN,
79         CTSVC_VCARD_VALUE_N,
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
116 };
117
118 enum {
119         CTSVC_VCARD_IMG_NONE,
120         CTSVC_VCARD_IMG_PNG,    /* Portable Network Graphics */
121         /* vcard  2.1 spec */
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 */
138 };
139
140 static const char *content_name[CTSVC_VCARD_VALUE_MAX] = {0};
141 const char *CTSVC_CRLF = "\r\n";
142
143 static int limit_size_of_photo = CTSVC_IMAGE_MAX_SIZE;
144
145 static void __ctsvc_vcard_initial(void)
146 {
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";
200         }
201 };
202
203 static int __ctsvc_vcard_append_str(char **buf, int *buf_size, int len, const char *str, bool need_conversion)
204 {
205         int len_temp = 0;
206         char *tmp = NULL;
207         const char *safe_str = SAFE_STR(str);
208         int str_len = 0;
209         bool need_realloc = false;
210
211         str_len = strlen(safe_str);
212         while ((*buf_size-len) < (str_len+1)) {
213                 *buf_size = *buf_size * 2;
214                 need_realloc = true;
215         }
216
217         if (need_realloc) {
218                 if (NULL == (tmp = realloc(*buf, *buf_size)))
219                         return -1;
220                 else
221                         *buf = tmp;
222         }
223
224         if (need_conversion) {
225                 const char *s = safe_str;
226                 char *r = (char *)(*buf+len);
227
228                 while (*s) {
229                         switch (*s) {
230                         case '\r':
231                                 if (*(s+1) && '\n' == *(s+1)) {
232                                         s++;
233                                         *r = '\\';
234                                         r++;
235                                         *r = 'n';
236                                 } else {
237                                         *r = *s;
238                                 }
239                                 break;
240                         case '\n':
241                                 *r = '\\';
242                                 r++;
243                                 str_len++;
244                                 if (*buf_size < str_len+len+1) {
245                                         *buf_size = *buf_size * 2;
246                                         if (NULL == (tmp = realloc(*buf, *buf_size))) {
247                                                 return -1;
248                                         } else {
249                                                 *buf = tmp;
250                                                 r = (char *)(*buf+len+str_len);
251                                         }
252                                 }
253                                 *r = 'n';
254                                 break;
255                         case ';':
256                         case ':':
257                         case ',':
258                         case '<':
259                         case '>':
260                         case '\\':
261                                 *r = '\\';
262                                 r++;
263                                 str_len++;
264                                 if (*buf_size < str_len+len+1) {
265                                         *buf_size = *buf_size * 2;
266                                         if (NULL == (tmp = realloc(*buf, *buf_size))) {
267                                                 return -1;
268                                         } else {
269                                                 *buf = tmp;
270                                                 r = (char *)(*buf+len+str_len);
271                                         }
272                                 }
273                                 *r = *s;
274                                 break;
275                         case 0xA1:
276                                 if (*(s+1) && 0xAC == *(s+1)) { /* en/em backslash */
277                                         *r = '\\';
278                                         r++;
279                                         str_len++;
280                                         if (*buf_size < str_len+len+1) {
281                                                 *buf_size = *buf_size * 2;
282                                                 if (NULL == (tmp = realloc(*buf, *buf_size))) {
283                                                         return -1;
284                                                 } else {
285                                                         *buf = tmp;
286                                                         r = (char *)(*buf+len+str_len);
287                                                 }
288                                         }
289
290                                         *r = *s;
291                                         r++;
292                                         s++;
293                                         if (*buf_size < str_len+len+1) {
294                                                 *buf_size = *buf_size * 2;
295                                                 if (NULL == (tmp = realloc(*buf, *buf_size))) {
296                                                         return -1;
297                                                 } else {
298                                                         *buf = tmp;
299                                                         r = (char *)(*buf+len+str_len);
300                                                 }
301                                         }
302                                         *r = *s;
303                                 } else {
304                                         *r = *s;
305                                 }
306                                 break;
307                         case 0x81:
308                                 if (*(s+1) && 0x5F == *(s+1)) { /* en/em backslash */
309                                         *r = '\\';
310                                         r++;
311                                         str_len++;
312                                         if (*buf_size < str_len+len+1) {
313                                                 *buf_size = *buf_size * 2;
314                                                 if (NULL == (tmp = realloc(*buf, *buf_size))) {
315                                                         return -1;
316                                                 } else {
317                                                         *buf = tmp;
318                                                         r = (char *)(*buf+len+str_len);
319                                                 }
320                                         }
321
322                                         *r = *s;
323                                         r++;
324                                         s++;
325                                         if (*buf_size < str_len+len+1) {
326                                                 *buf_size = *buf_size * 2;
327                                                 if (NULL == (tmp = realloc(*buf, *buf_size))) {
328                                                         return -1;
329                                                 } else {
330                                                         *buf = tmp;
331                                                         r = (char *)(*buf+len+str_len);
332                                                 }
333                                         }
334                                         *r = *s;
335                                 } else {
336                                         *r = *s;
337                                 }
338                                 break;
339                         default:
340                                 *r = *s;
341                                 break;
342                         }
343                         r++;
344                         s++;
345                 }
346                 len_temp = str_len;
347         } else {
348                 len_temp = snprintf(*buf+len, *buf_size-len+1, "%s", safe_str);
349         }
350         len += len_temp;
351         return len;
352 }
353
354 #define CTS_VCARD_FOLDING_LIMIT 75
355
356 static inline int __ctsvc_vcard_add_folding(char **buf, int *buf_size, int buf_len)
357 {
358         int char_len = 0;
359         char *buf_copy = NULL;
360         int len, result_len = 0;
361         char *r;
362         const char *s;
363         bool content_start = false;
364         bool encode_64 = false;
365
366         buf_copy = calloc(1, *buf_size);
367         if (NULL == buf_copy) {
368                 ERR("calloc() Fail");
369                 return 0;
370         }
371
372         s = *buf;
373         r = buf_copy;
374         len = result_len;
375
376         while (*s) {
377                 if (*buf_size < result_len + 5) {
378                         char *tmp = NULL;
379                         *buf_size = *buf_size + 1000;
380                         if (NULL == (tmp = realloc(buf_copy, *buf_size))) {
381                                 free(buf_copy);
382                                 return -1;
383                         } else {
384                                 buf_copy = tmp;
385                                 r = (buf_copy + result_len);
386                         }
387                 }
388
389                 if (false == content_start) {
390                         if (':' == *s)
391                                 content_start = true;
392                         else if (STRING_EQUAL == strncmp(s, "ENCODING=BASE64", strlen("ENCODING=BASE64")))
393                                 encode_64 = true;
394                 }
395
396                 if ('\r' == *s) {
397                         len--;
398                 } else if ('\n' == *s) {
399                         len = -1;
400                         char_len = 0;
401                         content_start = false;
402                         encode_64 = false;
403                 }
404
405                 if (0 == char_len) {
406                         if (false == encode_64)
407                                 char_len = ctsvc_check_utf8(*s);
408
409                         if (CTS_VCARD_FOLDING_LIMIT <= len + char_len) {
410                                 *r = '\r';
411                                 r++;
412                                 *r = '\n';
413                                 r++;
414                                 *r = ' ';
415                                 r++;
416                                 len = 1;
417                                 result_len += 3;
418                         }
419                 }
420
421                 if (char_len)
422                         char_len--;
423
424                 *r = *s;
425                 r++;
426                 s++;
427                 len++;
428                 result_len++;
429         }
430         *r = '\0';
431         free(*buf);
432         *buf = buf_copy;
433         return result_len;
434 }
435
436 static inline int __ctsvc_vcard_append_name(ctsvc_list_s *names, char **buf, int *buf_size, int len)
437 {
438         char display[1024] = {0};
439         GList *cursor = names->records;
440         ctsvc_name_s *name;
441
442         RETV_IF(NULL == cursor, len);
443
444         name = cursor->data;
445
446         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_N]);
447
448         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";CHARSET=UTF-8");
449         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ":");
450         CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, name->last);
451         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
452         CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, name->first);
453         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
454         CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, name->addition);
455         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
456         CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, name->prefix);
457         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
458         CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, name->suffix);
459
460         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, CTSVC_CRLF);
461
462         if (name->first && name->last) {
463                 contacts_name_display_order_e order = CONTACTS_NAME_DISPLAY_ORDER_FIRSTLAST;
464 #ifdef _CONTACTS_IPC_CLIENT
465                 contacts_setting_get_name_display_order(&order);
466 #endif
467                 if (CONTACTS_NAME_DISPLAY_ORDER_FIRSTLAST == order) {
468                         snprintf(display, sizeof(display), "%s %s", name->first, name->last);
469                 } else {
470                         /* CONTACTS_NAME_DISPLAY_ORDER_LASTFIRST */
471                         snprintf(display, sizeof(display), "%s, %s", name->last, name->first);
472                 }
473         } else {
474                 snprintf(display, sizeof(display), "%s%s", SAFE_STR(name->first), SAFE_STR(name->last));
475         }
476
477         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_FN]);
478         CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, display);
479
480         if (name->phonetic_first) {
481                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_PHONETIC_FIRST_NAME]);
482                 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, name->phonetic_first);
483         }
484
485         if (name->phonetic_middle) {
486                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_PHONETIC_MIDDLE_NAME]);
487                 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, name->phonetic_middle);
488         }
489
490
491         if (name->phonetic_last) {
492                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_PHONETIC_LAST_NAME]);
493                 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, name->phonetic_last);
494         }
495
496         return len;
497 }
498
499 static inline const char* __ctsvc_get_img_suffix(int type)
500 {
501         switch (type) {
502         case CTSVC_VCARD_IMG_TIFF:
503                 return "tiff";
504         case CTSVC_VCARD_IMG_GIF:
505                 return "gif";
506         case CTSVC_VCARD_IMG_PNG:
507                 return "png";
508         case CTSVC_VCARD_IMG_CGM:
509                 return "cgm";
510         case CTSVC_VCARD_IMG_WMF:
511                 return "wmf";
512         case CTSVC_VCARD_IMG_BMP:
513                 return "bmp";
514         case CTSVC_VCARD_IMG_MET:
515                 return "met";
516         case CTSVC_VCARD_IMG_PMB:
517                 return "pmb";
518         case CTSVC_VCARD_IMG_DIB:
519                 return "dib";
520         case CTSVC_VCARD_IMG_PICT:
521                 return "pict";
522         case CTSVC_VCARD_IMG_PDF:
523                 return "pdf";
524         case CTSVC_VCARD_IMG_PS:
525                 return "ps";
526         case CTSVC_VCARD_IMG_QTIME:
527                 return "qtime";
528         case CTSVC_VCARD_IMG_MPEG:
529                 return "mpeg";
530         case CTSVC_VCARD_IMG_MPEG2:
531                 return "mpeg2";
532         case CTSVC_VCARD_IMG_AVI:
533                 return "avi";
534         case CTSVC_VCARD_IMG_JPEG:
535                 return "jpeg";
536         default:
537                 ERR("Wrong Image type is: CTSVC_VCARD_IMG_NONE");
538                 return NULL;
539         }
540 }
541
542 static inline int __ctsvc_vcard_get_image_type(char *val)
543 {
544         char *temp, *result;
545         RETV_IF(NULL == val, CTSVC_VCARD_IMG_NONE);
546
547         temp = val;
548         while (*temp) {
549                 *temp = tolower(*temp);
550                 temp++;
551         }
552
553         result = strstr(val, "jpeg");
554         if (result) return CTSVC_VCARD_IMG_JPEG;
555
556         result = strstr(val, "jpg");
557         if (result) return CTSVC_VCARD_IMG_JPEG;
558
559         result = strstr(val, "png");
560         if (result) return CTSVC_VCARD_IMG_PNG;
561
562         result = strstr(val, "gif");
563         if (result) return CTSVC_VCARD_IMG_GIF;
564
565         result = strstr(val, "tiff");
566         if (result) return CTSVC_VCARD_IMG_TIFF;
567
568         result = strstr(val, "cgm");
569         if (result) return CTSVC_VCARD_IMG_CGM;
570
571         result = strstr(val, "wmf");
572         if (result) return CTSVC_VCARD_IMG_WMF;
573
574         result = strstr(val, "bmp");
575         if (result) return CTSVC_VCARD_IMG_BMP;
576
577         result = strstr(val, "met");
578         if (result) return CTSVC_VCARD_IMG_MET;
579
580         result = strstr(val, "pmb");
581         if (result) return CTSVC_VCARD_IMG_PMB;
582
583         result = strstr(val, "dib");
584         if (result) return CTSVC_VCARD_IMG_DIB;
585
586         result = strstr(val, "pict");
587         if (result) return CTSVC_VCARD_IMG_PICT;
588
589         result = strstr(val, "pdf");
590         if (result) return CTSVC_VCARD_IMG_PDF;
591
592         result = strstr(val, "ps");
593         if (result) return CTSVC_VCARD_IMG_PS;
594
595         result = strstr(val, "qtime");
596         if (result) return CTSVC_VCARD_IMG_QTIME;
597
598         result = strstr(val, "mpeg");
599         if (result) return CTSVC_VCARD_IMG_MPEG;
600
601         result = strstr(val, "mpeg2");
602         if (result) return CTSVC_VCARD_IMG_MPEG2;
603
604         result = strstr(val, "avi");
605         if (result) return CTSVC_VCARD_IMG_AVI;
606
607         return CTSVC_VCARD_IMG_NONE;
608 }
609
610 static inline const char* __ctsvc_get_image_type_str(int type)
611 {
612         switch (type) {
613         case CTSVC_VCARD_IMG_TIFF:
614                 return "TIFF";
615         case CTSVC_VCARD_IMG_GIF:
616                 return "GIF";
617         case CTSVC_VCARD_IMG_PNG:
618                 return "PNG";
619         case CTSVC_VCARD_IMG_CGM:
620                 return "CGM";
621         case CTSVC_VCARD_IMG_WMF:
622                 return "WMF";
623         case CTSVC_VCARD_IMG_BMP:
624                 return "BMP";
625         case CTSVC_VCARD_IMG_MET:
626                 return "MET";
627         case CTSVC_VCARD_IMG_PMB:
628                 return "PMB";
629         case CTSVC_VCARD_IMG_DIB:
630                 return "DIB";
631         case CTSVC_VCARD_IMG_PICT:
632                 return "PICT";
633         case CTSVC_VCARD_IMG_PDF:
634                 return "PDF";
635         case CTSVC_VCARD_IMG_PS:
636                 return "PS";
637         case CTSVC_VCARD_IMG_QTIME:
638                 return "QTIME";
639         case CTSVC_VCARD_IMG_MPEG:
640                 return "MPEG";
641         case CTSVC_VCARD_IMG_MPEG2:
642                 return "MPEG2";
643         case CTSVC_VCARD_IMG_AVI:
644                 return "AVI";
645         case CTSVC_VCARD_IMG_JPEG:
646         default:
647                 return "JPEG";
648         }
649 }
650
651 static inline int __ctsvc_vcard_put_company_logo(const char *path, char **buf, int *buf_size, int len)
652 {
653         int ret, fd, type;
654         gsize read_len;
655         char *suffix;
656         gchar *buf_image;
657         guchar image[CTSVC_VCARD_PHOTO_MAX_SIZE] = {0};
658
659         suffix = strrchr(path, '.');
660         type = __ctsvc_vcard_get_image_type(suffix);
661
662         fd = open(path, O_RDONLY);
663         RETVM_IF(fd < 0, CONTACTS_ERROR_SYSTEM, "System : Open Fail(%d)", errno);
664
665         read_len = 0;
666         while ((ret = read(fd, image+read_len, sizeof(image)-read_len))) {
667                 if (-1 == ret) {
668                         if (EINTR == errno)
669                                 continue;
670                         else
671                                 break;
672                 }
673                 read_len += ret;
674         }
675         close(fd);
676         RETVM_IF(ret < 0, CONTACTS_ERROR_SYSTEM, "System : read() Fail(%d)", errno);
677
678         buf_image = g_base64_encode(image, read_len);
679         if (buf_image) {
680                 do {
681                         if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_LOGO], false)) < 0)
682                                 break;
683                         if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, ";ENCODING=BASE64;TYPE=", false)) < 0)
684                                 break;
685                         if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, __ctsvc_get_image_type_str(type), false)) < 0)
686                                 break;
687                         if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, ":", false)) < 0)
688                                 break;
689                         if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, buf_image, false)) < 0)
690                                 break;
691                         if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, CTSVC_CRLF, false)) < 0)
692                                 break;
693                         if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, CTSVC_CRLF, false)) < 0)
694                                 break;
695                 } while (0);
696
697                 g_free(buf_image);
698                 if (len < 0) {
699                         /* LCOV_EXCL_START */
700                         ERR("__ctsvc_vcard_append_str() Fail");
701                         return CONTACTS_ERROR_OUT_OF_MEMORY;
702                         /* LCOV_EXCL_STOP */
703                 }
704         }
705         return len;
706 }
707
708 static bool __ctsvc_vcard_is_valid_custom_label(char *label)
709 {
710         char *src = label;
711         RETV_IF(NULL == label || '\0' == *label, false);
712
713         while (*src) {
714                 char c = src[0];
715                 RETV_IF(1 != ctsvc_check_utf8(c), false);
716                 if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') ||
717                                 ('0' <= c && c <= '9') || c == '-') {
718                         src++;
719                         continue;
720                 }
721                 return false;
722         }
723         return true;
724 }
725
726 static inline int __ctsvc_vcard_put_company_type(int type, char *label, char **buf, int *buf_size, int len)
727 {
728         if (type == CONTACTS_COMPANY_TYPE_WORK) {
729                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=WORK");
730         } else if (type == CONTACTS_COMPANY_TYPE_CUSTOM) {
731                 if (__ctsvc_vcard_is_valid_custom_label(label)) {
732                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-");
733                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, label);
734                 }
735         }
736         return len;
737 }
738
739 static inline int __ctsvc_vcard_append_company(ctsvc_list_s *company_list, char **buf, int *buf_size, int len)
740 {
741         GList *cursor;
742         ctsvc_company_s *company;
743
744         for (cursor = company_list->records; cursor; cursor = cursor->next) {
745
746                 company = cursor->data;
747
748                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_ORG]);
749
750                 len = __ctsvc_vcard_put_company_type(company->type, SAFE_STR(company->label), buf, buf_size, len);
751                 RETV_IF(len < 0, CONTACTS_ERROR_OUT_OF_MEMORY);
752
753                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";CHARSET=UTF-8");
754                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ":");
755                 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, company->name);
756                 if (company->department) {
757                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
758                         CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, company->department);
759                 }
760
761                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, CTSVC_CRLF);
762
763                 if (company->job_title) {
764                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_TITLE]);
765                         CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, company->job_title);
766                 }
767
768                 if (company->role) {
769                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_ROLE]);
770                         CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, company->role);
771                 }
772
773                 if (company->location) {
774                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_LOCATION]);
775                         CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, company->location);
776                 }
777
778                 if (company->description) {
779                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_DESCRIPTION]);
780                         CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, company->description);
781                 }
782
783                 if (company->phonetic_name) {
784                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_PHONETIC_NAME]);
785                         CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, company->phonetic_name);
786                 }
787
788                 if (company->assistant_name) {
789                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_ASSISTANT_NAME]);
790                         CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, company->assistant_name);
791                 }
792
793                 if (company->logo) {
794                         len = __ctsvc_vcard_put_company_logo(company->logo, buf, buf_size, len);
795                         RETV_IF(len < 0, CONTACTS_ERROR_OUT_OF_MEMORY);
796                 }
797         }
798
799         return len;
800 }
801
802 static inline int __ctsvc_vcard_append_note(ctsvc_list_s *note_list, char **buf, int *buf_size, int len)
803 {
804         GList *cursor;
805         ctsvc_note_s *note;
806
807         for (cursor = note_list->records; cursor; cursor = cursor->next) {
808                 note = cursor->data;
809                 if (note->note) {
810                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_NOTE]);
811                         CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, note->note);
812                 }
813         }
814
815         return len;
816 }
817
818 static inline int __ctsvc_vcard_2_put_postal_type(int type, char *dest, int dest_size)
819 {
820         int ret_len = 0;
821
822         if (type & CONTACTS_ADDRESS_TYPE_DOM)
823                 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "DOM");
824         if (type & CONTACTS_ADDRESS_TYPE_INTL)
825                 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "INTL");
826         if (type & CONTACTS_ADDRESS_TYPE_HOME)
827                 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "HOME");
828         if (type & CONTACTS_ADDRESS_TYPE_WORK)
829                 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "WORK");
830         if (type & CONTACTS_ADDRESS_TYPE_POSTAL)
831                 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "POSTAL");
832         if (type & CONTACTS_ADDRESS_TYPE_PARCEL)
833                 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "PARCEL");
834
835         return ret_len;
836 }
837
838 static inline int __ctsvc_vcard_put_postal_type(int type, char *label, char **buf, int *buf_size, int len)
839 {
840         char *type_str = NULL;
841         if (type == CONTACTS_ADDRESS_TYPE_DOM)
842                 type_str = "DOM";
843         else if (type == CONTACTS_ADDRESS_TYPE_INTL)
844                 type_str = "INTL";
845         else if (type == CONTACTS_ADDRESS_TYPE_HOME)
846                 type_str = "HOME";
847         else if (type == CONTACTS_ADDRESS_TYPE_WORK)
848                 type_str = "WORK";
849         else if (type == CONTACTS_ADDRESS_TYPE_POSTAL)
850                 type_str = "POSTAL";
851         else if (type == CONTACTS_ADDRESS_TYPE_PARCEL)
852                 type_str = "PARCEL";
853
854         if (type == CONTACTS_ADDRESS_TYPE_CUSTOM) {
855                 if (__ctsvc_vcard_is_valid_custom_label(label)) {
856                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-");
857                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, label);
858                 }
859                 return len;
860         }
861
862         if (type_str) {
863                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=");
864                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, type_str);
865         }
866         return len;
867 }
868
869 static inline int __ctsvc_vcard_append_postals(ctsvc_list_s *address_list, char **buf, int *buf_size, int len)
870 {
871         GList *cursor;
872         ctsvc_address_s *address;
873
874         for (cursor = address_list->records; cursor; cursor = cursor->next) {
875                 address = cursor->data;
876                 if (address) {
877                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_ADR]);
878
879                         len = __ctsvc_vcard_put_postal_type(address->type, SAFE_STR(address->label), buf, buf_size, len);
880                         RETV_IF(len < 0, CONTACTS_ERROR_OUT_OF_MEMORY);
881
882                         if (address->is_default)
883                                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";PREF");
884
885                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";CHARSET=UTF-8");
886                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ":");
887                         CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, address->pobox);
888                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
889                         CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, address->extended);
890                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
891                         CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, address->street);
892                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
893                         CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, address->locality);
894                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
895                         CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, address->region);
896                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
897                         CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, address->postalcode);
898                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";");
899                         CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, address->country);
900
901                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, CTSVC_CRLF);
902                 }
903         }
904
905         return len;
906 }
907
908 static inline int __ctsvc_vcard_append_nicknames(ctsvc_list_s *nickname_list, char **buf, int *buf_size, int len)
909 {
910         bool first;
911         GList *cursor;
912         ctsvc_nickname_s *nickname;
913
914         first = true;
915         for (cursor = nickname_list->records; cursor; cursor = cursor->next) {
916                 nickname = cursor->data;
917                 if (nickname->nickname && *nickname->nickname) {
918                         if (first) {
919                                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_NICKNAME]);
920                                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";CHARSET=UTF-8");
921                                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ":");
922                                 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, nickname->nickname);
923                                 first = false;
924                         } else {
925                                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ",");
926                                 CTSVC_VCARD_APPEND_CONTENT_STR(buf, buf_size, len, nickname->nickname);
927                         }
928                 }
929         }
930         if (false == first)
931                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, CTSVC_CRLF);
932
933         return len;
934 }
935
936 static inline int __ctsvc_vcard_2_put_number_type(int type, char *dest, int dest_size)
937 {
938         int ret_len = 0;
939         if (type & CONTACTS_NUMBER_TYPE_HOME)
940                 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "HOME");
941         if (type & CONTACTS_NUMBER_TYPE_MSG)
942                 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "MSG");
943         if (type & CONTACTS_NUMBER_TYPE_WORK)
944                 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "WORK");
945         if (type & CONTACTS_NUMBER_TYPE_VOICE)
946                 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "VOICE");
947         if (type & CONTACTS_NUMBER_TYPE_FAX)
948                 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "FAX");
949         if (type & CONTACTS_NUMBER_TYPE_VOICE)
950                 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "VOICE");
951         if (type & CONTACTS_NUMBER_TYPE_CELL)
952                 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "CELL");
953         if (type & CONTACTS_NUMBER_TYPE_VIDEO)
954                 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "VIDEO");
955         if (type & CONTACTS_NUMBER_TYPE_PAGER)
956                 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "PAGER");
957         if (type & CONTACTS_NUMBER_TYPE_BBS)
958                 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "BBS");
959         if (type & CONTACTS_NUMBER_TYPE_MODEM)
960                 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "MODEM");
961         if (type & CONTACTS_NUMBER_TYPE_CAR)
962                 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "CAR");
963         if (type & CONTACTS_NUMBER_TYPE_ISDN)
964                 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "ISDN");
965         if (type & CONTACTS_NUMBER_TYPE_PCS)
966                 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "PCS");
967
968         return ret_len;
969 }
970
971 static inline int __ctsvc_vcard_put_number_type(int type, char *label, char **buf, int *buf_size, int len)
972 {
973         if (type & CONTACTS_NUMBER_TYPE_HOME)
974                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=HOME");
975         if (type & CONTACTS_NUMBER_TYPE_MSG)
976                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=MSG");
977         if (type & CONTACTS_NUMBER_TYPE_WORK)
978                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=WORK");
979         if (type & CONTACTS_NUMBER_TYPE_VOICE)
980                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=VOICE");
981         if (type & CONTACTS_NUMBER_TYPE_FAX)
982                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=FAX");
983         if (type & CONTACTS_NUMBER_TYPE_CELL)
984                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=CELL");
985         if (type & CONTACTS_NUMBER_TYPE_VIDEO)
986                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=VIDEO");
987         if (type & CONTACTS_NUMBER_TYPE_PAGER)
988                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=PAGER");
989         if (type & CONTACTS_NUMBER_TYPE_BBS)
990                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=BBS");
991         if (type & CONTACTS_NUMBER_TYPE_MODEM)
992                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=MODEM");
993         if (type & CONTACTS_NUMBER_TYPE_CAR)
994                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=CAR");
995         if (type & CONTACTS_NUMBER_TYPE_ISDN)
996                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=ISDN");
997         if (type & CONTACTS_NUMBER_TYPE_PCS)
998                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=PCS");
999         if (type & CONTACTS_NUMBER_TYPE_ASSISTANT)
1000                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-ASSISTANT");
1001         if (type & CONTACTS_NUMBER_TYPE_RADIO)
1002                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-RADIO");
1003         if (type & CONTACTS_NUMBER_TYPE_COMPANY_MAIN)
1004                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-COMPANY-MAIN");
1005         if (type & CONTACTS_NUMBER_TYPE_MAIN)
1006                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-MAIN");
1007         if (type == CONTACTS_NUMBER_TYPE_CUSTOM) {
1008                 if (__ctsvc_vcard_is_valid_custom_label(label)) {
1009                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-");
1010                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, label);
1011                 }
1012                 return len;
1013         }
1014         return len;
1015 }
1016
1017 static int __ctsvc_vcard_check_utf8(char c)
1018 {
1019         if ((c & 0xff) < (128 & 0xff))
1020                 return 1;
1021         else if ((c & (char)0xe0) == (char)0xc0)
1022                 return 2;
1023         else if ((c & (char)0xf0) == (char)0xe0)
1024                 return 3;
1025         else if ((c & (char)0xf8) == (char)0xf0)
1026                 return 4;
1027         else if ((c & (char)0xfc) == (char)0xf8)
1028                 return 5;
1029         else if ((c & (char)0xfe) == (char)0xfc)
1030                 return 6;
1031         else
1032                 return CONTACTS_ERROR_INVALID_PARAMETER;
1033 }
1034
1035 static void __ctsvc_vcard_get_clean_number_for_export(char *str, char *dest)
1036 {
1037         int char_len = 0;
1038         char *s = SAFE_STR(str);
1039         char *r = NULL;
1040
1041         r = dest;
1042
1043         while (*s) {
1044                 char_len = __ctsvc_vcard_check_utf8(*s);
1045                 if (3 == char_len) {
1046                         if (*s == 0xef) {
1047                                 if (*(s+1) == 0xbc) {
1048                                         if (0x90 <= *(s+2) && *(s+2) <= 0x99) {
1049                                                 /* ef bc 90 : '0' ~ ef bc 99 : '9' */
1050                                                 *r = '0' + (*(s+2) - 0x90);
1051                                                 r++;
1052                                                 s += 3;
1053                                         } else if (0x8b == *(s+2)) {
1054                                                 /* ef bc 8b : '+' */
1055                                                 *r = '+';
1056                                                 r++;
1057                                                 s += 3;
1058                                         } else if (0x8a == *(s+2)) {
1059                                                 /* ef bc 8a : '*' */
1060                                                 *r = '*';
1061                                                 r++;
1062                                                 s += 3;
1063                                         } else if (0x83 == *(s+2)) {
1064                                                 /* ef bc 83 : '#' */
1065                                                 *r = '#';
1066                                                 r++;
1067                                                 s += 3;
1068                                         } else if (0x8c == *(s+2)) {
1069                                                 /* ef bc 8c : ',' */
1070                                                 *r = 'p';
1071                                                 r++;
1072                                                 s += 3;
1073                                         } else if (0x9b == *(s+2)) {
1074                                                 /* ef bc 9b : ';' */
1075                                                 *r = 'w';
1076                                                 r++;
1077                                                 s += 3;
1078                                         } else {
1079                                                 s += char_len;
1080                                         }
1081                                 } else {
1082                                         s += char_len;
1083                                 }
1084                         } else {
1085                                 s += char_len;
1086                         }
1087                 } else if (1 == char_len) {
1088                         switch (*s) {
1089                         case '/':
1090                         case '.':
1091                         case '0' ... '9':
1092                         case '#':
1093                         case '*':
1094                         case '(':
1095                         case ')':
1096                         case '+':
1097                                 *r = *s;
1098                                 r++;
1099                                 s++;
1100                                 break;
1101                         case ',':
1102                         case 'p':
1103                         case 'P':
1104                                 *r = 'p';
1105                                 r++;
1106                                 s++;
1107                                 break;
1108                         case ';':
1109                         case 'w':
1110                         case 'W':
1111                                 *r = 'w';
1112                                 r++;
1113                                 s++;
1114                                 break;
1115                         case 'a' ... 'o':
1116                         case 'q' ... 'v':
1117                         case 'x' ... 'z':
1118                                 *r = *s - 0x20;
1119                                 r++;
1120                                 s++;
1121                                 break;
1122                         case 'A' ... 'O':
1123                         case 'Q' ... 'V':
1124                         case 'X' ... 'Z':
1125                                 *r = *s;
1126                                 r++;
1127                                 s++;
1128                                 break;
1129                         default:
1130                                 s++;
1131                                 break;
1132                         }
1133                 } else {
1134                         s += char_len;
1135                 }
1136         }
1137         *r = '\0';
1138         return;
1139 }
1140
1141 static inline int __ctsvc_vcard_append_numbers(ctsvc_list_s *number_list, char **buf, int *buf_size, int len)
1142 {
1143         GList *cursor;
1144         ctsvc_number_s *number;
1145
1146         for (cursor = number_list->records; cursor; cursor = cursor->next) {
1147                 number = cursor->data;
1148                 if (number->number) {
1149                         char clean_number[strlen(number->number)+1];
1150                         clean_number[0] = '\0';
1151                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_TEL]);
1152
1153                         len = __ctsvc_vcard_put_number_type(number->type, SAFE_STR(number->label), buf, buf_size, len);
1154                         RETV_IF(len < 0, CONTACTS_ERROR_OUT_OF_MEMORY);
1155
1156                         if (number->is_default)
1157                                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";PREF");
1158
1159                         __ctsvc_vcard_get_clean_number_for_export(number->number, clean_number);
1160                         if (*clean_number)
1161                                 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, clean_number);
1162                 }
1163         }
1164         return len;
1165 }
1166
1167 static inline int __ctsvc_vcard_2_put_email_type(int type, char *dest, int dest_size)
1168 {
1169         int ret_len = 0;
1170
1171         if (CONTACTS_EMAIL_TYPE_HOME & type)
1172                 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "HOME");
1173         if (CONTACTS_EMAIL_TYPE_WORK & type)
1174                 ret_len += snprintf(dest+ret_len, dest_size-ret_len, ";%s", "WORK");
1175
1176         return ret_len;
1177 }
1178
1179 static inline int __ctsvc_vcard_put_email_type(int type, char *label, char **buf, int *buf_size, int len)
1180 {
1181         char *type_str = NULL;
1182         if (CONTACTS_EMAIL_TYPE_HOME == type) {
1183                 type_str = "HOME";
1184         } else if (CONTACTS_EMAIL_TYPE_WORK == type) {
1185                 type_str = "WORK";
1186         } else if (CONTACTS_EMAIL_TYPE_MOBILE == type) {
1187                 type_str = "CELL";
1188         } else if (CONTACTS_EMAIL_TYPE_CUSTOM == type) {
1189                 if (__ctsvc_vcard_is_valid_custom_label(label)) {
1190                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-");
1191                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, label);
1192                 }
1193                 return len;
1194         }
1195
1196         if (type_str) {
1197                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=");
1198                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, type_str);
1199         }
1200         return len;
1201 }
1202
1203 static inline int __ctsvc_vcard_append_emails(ctsvc_list_s *email_list, char **buf, int *buf_size, int len)
1204 {
1205         GList *cursor;
1206         ctsvc_email_s *email;
1207
1208         for (cursor = email_list->records; cursor; cursor = cursor->next) {
1209                 email = cursor->data;
1210                 if (email->email_addr) {
1211                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_EMAIL]);
1212
1213                         len = __ctsvc_vcard_put_email_type(email->type, SAFE_STR(email->label), buf, buf_size, len);
1214                         RETV_IF(len < 0, CONTACTS_ERROR_OUT_OF_MEMORY);
1215
1216                         if (email->is_default)
1217                                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";PREF");
1218
1219                         CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, email->email_addr);
1220                 }
1221         }
1222         return len;
1223 }
1224
1225 static inline int __ctsvc_vcard_put_url_type(int type, char *label, char **buf, int *buf_size, int len)
1226 {
1227         char *type_str = NULL;
1228
1229         if (CONTACTS_URL_TYPE_HOME == type) {
1230                 type_str = "HOME";
1231         } else if (CONTACTS_URL_TYPE_WORK == type) {
1232                 type_str = "WORK";
1233         } else if (CONTACTS_URL_TYPE_CUSTOM == type) {
1234                 if (__ctsvc_vcard_is_valid_custom_label(label)) {
1235                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-");
1236                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, label);
1237                 }
1238                 return len;
1239         }
1240         if (type_str) {
1241                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=");
1242                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, type_str);
1243         }
1244         return len;
1245 }
1246
1247 static inline int __ctsvc_vcard_append_webs(ctsvc_list_s *url_list, char **buf, int *buf_size, int len)
1248 {
1249         GList *cursor;
1250         ctsvc_url_s *url;
1251
1252         for (cursor = url_list->records; cursor; cursor = cursor->next) {
1253                 url = cursor->data;
1254
1255                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_URL]);
1256
1257                 len = __ctsvc_vcard_put_url_type(url->type, SAFE_STR(url->label), buf, buf_size, len);
1258                 RETV_IF(len < 0, CONTACTS_ERROR_OUT_OF_MEMORY);
1259
1260                 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, url->url);
1261         }
1262
1263         return len;
1264 }
1265
1266 #define VCARD_INIT_LENGTH 1024
1267 #define VCARD_ITEM_LENGTH 1024
1268
1269 static inline int __ctsvc_vcard_append_events(ctsvc_list_s *event_list, char **buf, int *buf_size, int len)
1270 {
1271         GList *cursor;
1272         ctsvc_event_s *data;
1273         char event[VCARD_ITEM_LENGTH] = {0};
1274
1275         for (cursor = event_list->records; cursor; cursor = cursor->next) {
1276                 data = cursor->data;
1277                 if (0 == data->date) continue;
1278
1279                 event[0] = '\0';
1280                 if (CONTACTS_EVENT_TYPE_BIRTH == data->type) {
1281                         snprintf(event, sizeof(event), "%s:%d-%02d-%02d%s",
1282                                         content_name[CTSVC_VCARD_VALUE_BDAY],
1283                                         data->date/10000, (data->date%10000)/100, data->date%100,
1284                                         CTSVC_CRLF);
1285                 } else if (CONTACTS_EVENT_TYPE_ANNIVERSARY == data->type) {
1286                         snprintf(event, sizeof(event), "%s;TYPE=ANNIVERSARY:%d-%02d-%02d%s",
1287                                         content_name[CTSVC_VCARD_VALUE_X_TIZEN_EVENT],
1288                                         data->date/10000, (data->date%10000)/100, data->date%100,
1289                                         CTSVC_CRLF);
1290                 } else if (CONTACTS_EVENT_TYPE_CUSTOM == data->type) {
1291                         if (__ctsvc_vcard_is_valid_custom_label(data->label)) {
1292                                 snprintf(event, sizeof(event), "%s;TYPE=X-%s:%d-%02d-%02d%s",
1293                                                 content_name[CTSVC_VCARD_VALUE_X_TIZEN_EVENT],
1294                                                 SAFE_STR(data->label),
1295                                                 data->date/10000, (data->date%10000)/100, data->date%100,
1296                                                 CTSVC_CRLF);
1297                         } else {
1298                                 snprintf(event, sizeof(event), "%s:%d-%02d-%02d%s",
1299                                                 content_name[CTSVC_VCARD_VALUE_X_TIZEN_EVENT],
1300                                                 data->date/10000, (data->date%10000)/100, data->date%100,
1301                                                 CTSVC_CRLF);
1302                         }
1303                 } else {
1304                         snprintf(event, sizeof(event), "%s:%d-%02d-%02d%s",
1305                                         content_name[CTSVC_VCARD_VALUE_X_TIZEN_EVENT],
1306                                         data->date/10000, (data->date%10000)/100, data->date%100,
1307                                         CTSVC_CRLF);
1308                 }
1309                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, event);
1310         }
1311
1312         return len;
1313 }
1314
1315 static inline int __ctsvc_vcard_append_messengers(ctsvc_list_s *messenger_list, char **buf, int *buf_size, int len)
1316 {
1317         GList *cursor;
1318         ctsvc_messenger_s *messenger;
1319         const char *content_name_messenger = NULL;
1320         const char *content_name_x_type = NULL;
1321
1322         for (cursor = messenger_list->records; cursor; cursor = cursor->next) {
1323                 messenger = cursor->data;
1324
1325                 content_name_messenger = NULL;
1326                 content_name_x_type = NULL;
1327
1328                 if (messenger->im_id && *messenger->im_id) {
1329                         switch (messenger->type) {
1330                         case CONTACTS_MESSENGER_TYPE_WLM:
1331                                 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_MSN];
1332                                 break;
1333                         case CONTACTS_MESSENGER_TYPE_YAHOO:
1334                                 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_YAHOO];
1335                                 break;
1336                         case CONTACTS_MESSENGER_TYPE_ICQ:
1337                                 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_ICQ];
1338                                 break;
1339                         case CONTACTS_MESSENGER_TYPE_AIM:
1340                                 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_AIM];
1341                                 break;
1342                         case CONTACTS_MESSENGER_TYPE_JABBER:
1343                                 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_JABBER];
1344                                 break;
1345                         case CONTACTS_MESSENGER_TYPE_SKYPE:
1346                                 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_SKYPE_USERNAME];
1347                                 break;
1348                         case CONTACTS_MESSENGER_TYPE_QQ:
1349                                 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_QQ];
1350                                 break;
1351                         case CONTACTS_MESSENGER_TYPE_GOOGLE:
1352                                 content_name_messenger = content_name[CTSVC_VCARD_VALUE_X_GOOGLE_TALK];
1353                                 break;
1354                         case CONTACTS_MESSENGER_TYPE_FACEBOOK:
1355                                 content_name_x_type = "FACEBOOK";
1356                                 break;
1357                         case CONTACTS_MESSENGER_TYPE_IRC:
1358                                 content_name_x_type = "IRC";
1359                                 break;
1360                         case CONTACTS_MESSENGER_TYPE_CUSTOM:
1361                                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_X_TIZEN_MESSENGER]);
1362                                 if (__ctsvc_vcard_is_valid_custom_label(messenger->label)) {
1363                                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-");
1364                                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, messenger->label);
1365                                 }
1366                                 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, messenger->im_id);
1367                                 break;
1368                         default:
1369                                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_X_TIZEN_MESSENGER]);
1370                                 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, messenger->im_id);
1371                                 break;
1372                         }
1373
1374                         if (content_name_messenger) {
1375                                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name_messenger);
1376                                 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, messenger->im_id);
1377                         } else if (content_name_x_type) {
1378                                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_X_TIZEN_MESSENGER]);
1379                                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=");
1380                                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name_x_type);
1381                                 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, messenger->im_id);
1382                         }
1383                 }
1384         }
1385         return len;
1386 }
1387
1388 static inline int __ctsvc_vcard_put_relationship_type(int type, char *label, char **buf, int *buf_size, int len)
1389 {
1390         const char *type_str = NULL;
1391
1392         switch (type) {
1393         case CONTACTS_RELATIONSHIP_TYPE_ASSISTANT:
1394                 type_str = "ASSISTANT";
1395                 break;
1396         case CONTACTS_RELATIONSHIP_TYPE_BROTHER:
1397                 type_str = "BROTHER";
1398                 break;
1399         case CONTACTS_RELATIONSHIP_TYPE_CHILD:
1400                 type_str = "CHILD";
1401                 break;
1402         case CONTACTS_RELATIONSHIP_TYPE_DOMESTIC_PARTNER:
1403                 type_str = "DOMESTIC_PARTNER";
1404                 break;
1405         case CONTACTS_RELATIONSHIP_TYPE_FATHER:
1406                 type_str = "FATHER";
1407                 break;
1408         case CONTACTS_RELATIONSHIP_TYPE_FRIEND:
1409                 type_str = "FRIEND";
1410                 break;
1411         case CONTACTS_RELATIONSHIP_TYPE_MANAGER:
1412                 type_str = "MANAGER";
1413                 break;
1414         case CONTACTS_RELATIONSHIP_TYPE_MOTHER:
1415                 type_str = "MOTHER";
1416                 break;
1417         case CONTACTS_RELATIONSHIP_TYPE_PARENT:
1418                 type_str = "PARENT";
1419                 break;
1420         case CONTACTS_RELATIONSHIP_TYPE_PARTNER:
1421                 type_str = "PARTNER";
1422                 break;
1423         case CONTACTS_RELATIONSHIP_TYPE_REFERRED_BY:
1424                 type_str = "REFERRED_BY";
1425                 break;
1426         case CONTACTS_RELATIONSHIP_TYPE_RELATIVE:
1427                 type_str = "RELATIVE";
1428                 break;
1429         case CONTACTS_RELATIONSHIP_TYPE_SISTER:
1430                 type_str = "SISTER";
1431                 break;
1432         case CONTACTS_RELATIONSHIP_TYPE_SPOUSE:
1433                 type_str = "SPOUSE";
1434                 break;
1435         case CONTACTS_RELATIONSHIP_TYPE_CUSTOM:
1436                 if (__ctsvc_vcard_is_valid_custom_label(label)) {
1437                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=X-");
1438                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, label);
1439                 }
1440                 return len;
1441         }
1442
1443         if (type_str) {
1444                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, ";TYPE=");
1445                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, type_str);
1446         }
1447
1448         return len;
1449 }
1450
1451 static inline int __ctsvc_vcard_append_relationships(ctsvc_list_s *relationship_list, char **buf, int *buf_size, int len)
1452 {
1453         GList *cursor;
1454         ctsvc_relationship_s *relationship;
1455
1456         for (cursor = relationship_list->records; cursor; cursor = cursor->next) {
1457                 relationship = cursor->data;
1458
1459                 if (relationship->name) {
1460                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, "X-TIZEN-RELATIONSHIP");
1461
1462                         len = __ctsvc_vcard_put_relationship_type(relationship->type, SAFE_STR(relationship->label), buf, buf_size, len);
1463                         RETV_IF(len < 0, CONTACTS_ERROR_OUT_OF_MEMORY);
1464                         CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, relationship->name);
1465                 }
1466         }
1467
1468         return len;
1469 }
1470
1471 typedef struct {
1472         const char *src;
1473         unsigned char **image;
1474         unsigned int *image_size;
1475         int ret;
1476 } vcard_image_info;
1477
1478 static bool _ctsvc_vcard_image_util_supported_jpeg_colorspace_cb(
1479                 image_util_colorspace_e colorspace, void *user_data)
1480 {
1481         int width = 0;
1482         int height = 0;
1483         int mimetype = 0;
1484         uint64_t size = 0;
1485         unsigned int size_decode = 0;
1486         void *buffer = NULL;
1487         void *buffer_temp = NULL;
1488         int ret;
1489         vcard_image_info *info = user_data;
1490
1491         ret = ctsvc_image_util_get_mimetype(colorspace, &mimetype);
1492         if (CONTACTS_ERROR_NONE != ret) {
1493                 /* LCOV_EXCL_START */
1494                 info->ret = CONTACTS_ERROR_SYSTEM;
1495                 return true;
1496                 /* LCOV_EXCL_STOP */
1497         }
1498
1499         image_util_decode_h dh = NULL;
1500         do {
1501                 unsigned long l_width = 0;
1502                 unsigned long l_height = 0;
1503                 unsigned long long ll_size_decode = 0;
1504
1505                 ret = image_util_decode_create(&dh);
1506                 if (IMAGE_UTIL_ERROR_NONE != ret)
1507                         break;
1508                 ret = image_util_decode_set_input_path(dh, info->src);
1509                 if (IMAGE_UTIL_ERROR_NONE != ret)
1510                         break;
1511                 ret = image_util_decode_set_colorspace(dh, colorspace);
1512                 if (IMAGE_UTIL_ERROR_NONE != ret)
1513                         break;
1514                 ret = image_util_decode_set_output_buffer(dh, (unsigned char **)&buffer);
1515                 if (IMAGE_UTIL_ERROR_NONE != ret)
1516                         break;
1517                 ret = image_util_decode_run(dh, &l_width, &l_height, &ll_size_decode);
1518                 if (IMAGE_UTIL_ERROR_NONE != ret)
1519                         break;
1520
1521                 width = (int)l_width;
1522                 height = (int)l_height;
1523                 size_decode = (unsigned int)ll_size_decode;
1524         } while (0);
1525         if (dh)
1526                 ret = image_util_decode_destroy(dh);
1527         if (IMAGE_UTIL_ERROR_NONE != ret || 0 == width || 0 == height) {
1528                 /* LCOV_EXCL_START */
1529                 info->ret = CONTACTS_ERROR_SYSTEM;
1530                 return true;
1531                 /* LCOV_EXCL_STOP */
1532         }
1533         size = (uint64_t)size_decode;
1534
1535         if (limit_size_of_photo < width || limit_size_of_photo < height) { /* need resize */
1536                 int resized_width;
1537                 int resized_height;
1538                 media_format_h fmt;
1539                 media_packet_h packet;
1540
1541                 /* set resize */
1542                 if (width > height) {
1543                         resized_width = limit_size_of_photo;
1544                         resized_height = height * limit_size_of_photo / width;
1545                 } else {
1546                         resized_height = limit_size_of_photo;
1547                         resized_width = width * limit_size_of_photo / height;
1548                 }
1549
1550                 if (resized_height % 8)
1551                         resized_height -= (resized_height % 8);
1552
1553                 if (resized_width % 8)
1554                         resized_width -= (resized_width % 8);
1555
1556                 fmt = ctsvc_image_util_create_media_format(mimetype, width, height);
1557                 if (NULL == fmt) {
1558                         /* LCOV_EXCL_START */
1559                         ERR("_ctsvc_image_create_media_format() Fail");
1560                         info->ret = CONTACTS_ERROR_SYSTEM;
1561                         free(buffer);
1562                         return false;
1563                         /* LCOV_EXCL_STOP */
1564                 }
1565
1566                 packet = ctsvc_image_util_create_media_packet(fmt, buffer, (unsigned int)size);
1567                 if (NULL == packet) {
1568                         /* LCOV_EXCL_START */
1569                         ERR("_ctsvc_image_create_media_packet() Fail");
1570                         media_format_unref(fmt);
1571                         info->ret = CONTACTS_ERROR_SYSTEM;
1572                         free(buffer);
1573                         return false;
1574                         /* LCOV_EXCL_STOP */
1575                 }
1576
1577                 ret = ctsvc_image_util_resize(packet, resized_width, resized_height, &buffer_temp,
1578                                 &size);
1579
1580                 media_packet_destroy(packet);
1581                 media_format_unref(fmt);
1582
1583                 if (CONTACTS_ERROR_NONE != ret) {
1584                         free(buffer);
1585                         info->ret = CONTACTS_ERROR_SYSTEM;
1586                         return false;
1587                 }
1588                 free(buffer);
1589                 buffer = buffer_temp;
1590
1591                 width = resized_width;
1592                 height = resized_height;
1593         }
1594
1595         image_util_encode_h eh = NULL;
1596         do {
1597                 unsigned long long ll_size_encode = 0;
1598
1599                 ret = image_util_encode_create(IMAGE_UTIL_JPEG, &eh);
1600                 if (IMAGE_UTIL_ERROR_NONE != ret)
1601                         break;
1602                 ret = image_util_encode_set_input_buffer(eh, buffer);
1603                 if (IMAGE_UTIL_ERROR_NONE != ret)
1604                         break;
1605                 ret = image_util_encode_set_resolution(eh, width, height);
1606                 if (IMAGE_UTIL_ERROR_NONE != ret)
1607                         break;
1608                 ret = image_util_encode_set_colorspace(eh, colorspace);
1609                 if (IMAGE_UTIL_ERROR_NONE != ret)
1610                         break;
1611                 ret = image_util_encode_set_quality(eh, CTSVC_IMAGE_ENCODE_QUALITY);
1612                 if (IMAGE_UTIL_ERROR_NONE != ret)
1613                         break;
1614                 ret = image_util_encode_set_output_buffer(eh, info->image);
1615                 if (IMAGE_UTIL_ERROR_NONE != ret)
1616                         break;
1617                 ret = image_util_encode_run(eh, &ll_size_encode);
1618                 *(info->image_size) = (unsigned int)ll_size_encode;
1619         } while (0);
1620         if (eh)
1621                 ret = image_util_encode_destroy(eh);
1622         free(buffer);
1623         if (IMAGE_UTIL_ERROR_NONE != ret) {
1624                 /* LCOV_EXCL_START */
1625                 ERR("image_util_encode_jpeg_to_memory", ret);
1626                 info->ret = CONTACTS_ERROR_SYSTEM;
1627                 return false;
1628                 /* LCOV_EXCL_STOP */
1629         }
1630
1631         info->ret = CONTACTS_ERROR_NONE;
1632         return false;
1633 }
1634
1635 static inline int __ctsvc_vcard_encode_photo(const char *src,
1636                 unsigned char **image, unsigned int *image_size)
1637 {
1638         int ret;
1639         vcard_image_info info = {src, image, image_size, CONTACTS_ERROR_SYSTEM};
1640
1641         ret = image_util_foreach_supported_colorspace(IMAGE_UTIL_JPEG,
1642                         _ctsvc_vcard_image_util_supported_jpeg_colorspace_cb, &info);
1643
1644         if (IMAGE_UTIL_ERROR_NONE != ret)
1645                 return CONTACTS_ERROR_SYSTEM;
1646
1647         return info.ret;
1648 }
1649
1650 static inline int __ctsvc_vcard_put_photo(ctsvc_list_s *image_list, char **buf, int *buf_size, int len)
1651 {
1652         int ret = CONTACTS_ERROR_NONE, fd, type;
1653         unsigned int read_len;
1654         char *suffix;
1655         gchar *buf_image;
1656         unsigned char *image = NULL;
1657         unsigned int img_buf_size = 0;
1658         GList *cursor;
1659         ctsvc_image_s *data;
1660
1661         for (cursor = image_list->records; cursor; cursor = cursor->next) {
1662                 data = cursor->data;
1663                 if (NULL == data->path) continue;
1664
1665                 ret = __ctsvc_vcard_encode_photo(data->path, &image, &read_len);
1666
1667                 if (CONTACTS_ERROR_NONE != ret) {
1668                         INFO("__ctsvc_vcard_encode_photo() Fail(%d)", ret);
1669
1670                         img_buf_size = CTSVC_VCARD_PHOTO_MAX_SIZE * sizeof(unsigned char);
1671                         image = calloc(1, img_buf_size);
1672                         if (NULL == image) {
1673                                 /* LCOV_EXCL_START */
1674                                 ERR("calloc() Fail");
1675                                 return CONTACTS_ERROR_OUT_OF_MEMORY;
1676                                 /* LCOV_EXCL_STOP */
1677                         }
1678
1679                         fd = open(data->path, O_RDONLY);
1680                         if (fd < 0) {
1681                                 /* LCOV_EXCL_START */
1682                                 ERR("System : Open Fail(%d)", errno);
1683                                 free(image);
1684                                 return CONTACTS_ERROR_SYSTEM;
1685                                 /* LCOV_EXCL_STOP */
1686                         }
1687
1688                         read_len = 0;
1689                         while ((ret = read(fd, image+read_len, img_buf_size-read_len))) {
1690                                 if (-1 == ret) {
1691                                         if (EINTR == errno)
1692                                                 continue;
1693                                         else
1694                                                 break;
1695                                 }
1696                                 read_len += ret;
1697                         }
1698                         close(fd);
1699                         if (ret < 0) {
1700                                 /* LCOV_EXCL_START */
1701                                 ERR("System : read() Fail(%d)", errno);
1702                                 free(image);
1703                                 return CONTACTS_ERROR_SYSTEM;
1704                                 /* LCOV_EXCL_STOP */
1705                         }
1706                 }
1707
1708                 suffix = strrchr(data->path, '.');
1709                 type = __ctsvc_vcard_get_image_type(suffix);
1710
1711                 buf_image = g_base64_encode(image, read_len);
1712                 free(image);
1713
1714                 if (buf_image) {
1715                         do {
1716                                 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_PHOTO], false)) < 0)
1717                                         break;
1718                                 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, ";ENCODING=BASE64;TYPE=", false)) < 0)
1719                                         break;
1720                                 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, __ctsvc_get_image_type_str(type), false)) < 0)
1721                                         break;
1722                                 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, ":", false)) < 0)
1723                                         break;
1724                                 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, buf_image, false)) < 0)
1725                                         break;
1726                                 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, CTSVC_CRLF, false)) < 0)
1727                                         break;
1728                                 if ((len = __ctsvc_vcard_append_str(buf, buf_size, len, CTSVC_CRLF, false)) < 0)
1729                                         break;
1730                         } while (0);
1731
1732                         g_free(buf_image);
1733                         if (len < 0) {
1734                                 /* LCOV_EXCL_START */
1735                                 ERR("__ctsvc_vcard_append_str() Fail");
1736                                 return CONTACTS_ERROR_OUT_OF_MEMORY;
1737                                 /* LCOV_EXCL_STOP */
1738                         }
1739                 }
1740         }
1741
1742         return len;
1743 }
1744
1745 static inline int __ctsvc_vcard_append_contact(ctsvc_contact_s *contact, char **buf, int *buf_size, int len)
1746 {
1747         if (contact->name) {
1748                 len = __ctsvc_vcard_append_name(contact->name, buf, buf_size, len);
1749                 RETV_IF(len < 0, len);
1750         }
1751         if (contact->company) {
1752                 len = __ctsvc_vcard_append_company(contact->company, buf, buf_size, len);
1753                 RETV_IF(len < 0, len);
1754         }
1755         if (contact->note) {
1756                 len = __ctsvc_vcard_append_note(contact->note, buf, buf_size, len);
1757                 RETV_IF(len < 0, len);
1758         }
1759         if (contact->postal_addrs) {
1760                 len = __ctsvc_vcard_append_postals(contact->postal_addrs, buf, buf_size, len);
1761                 RETV_IF(len < 0, len);
1762         }
1763         if (contact->numbers) {
1764                 len = __ctsvc_vcard_append_numbers(contact->numbers, buf, buf_size, len);
1765                 RETV_IF(len < 0, len);
1766         }
1767         if (contact->emails) {
1768                 len = __ctsvc_vcard_append_emails(contact->emails, buf, buf_size, len);
1769                 RETV_IF(len < 0, len);
1770         }
1771         if (contact->nicknames) {
1772                 len = __ctsvc_vcard_append_nicknames(contact->nicknames, buf, buf_size, len);
1773                 RETV_IF(len < 0, len);
1774         }
1775         if (contact->urls) {
1776                 len = __ctsvc_vcard_append_webs(contact->urls, buf, buf_size, len);
1777                 RETV_IF(len < 0, len);
1778         }
1779         if (contact->events) {
1780                 len = __ctsvc_vcard_append_events(contact->events, buf, buf_size, len);
1781                 RETV_IF(len < 0, len);
1782         }
1783         if (contact->images) {
1784                 len = __ctsvc_vcard_put_photo(contact->images, buf, buf_size, len);
1785                 RETV_IF(len < 0, len);
1786         }
1787         if (contact->messengers) {
1788                 len = __ctsvc_vcard_append_messengers(contact->messengers, buf, buf_size, len);
1789                 RETV_IF(len < 0, len);
1790         }
1791         if (contact->relationships) {
1792                 len = __ctsvc_vcard_append_relationships(contact->relationships, buf, buf_size, len);
1793                 RETV_IF(len < 0, len);
1794         }
1795
1796         if (contact->uid && DEFAULT_ADDRESS_BOOK_ID == contact->addressbook_id) {
1797                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_UID]);
1798                 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, contact->uid);
1799         }
1800
1801         if (contact->changed_time) {
1802                 struct tm ts;
1803                 gmtime_r((time_t *)&contact->changed_time, &ts);
1804                 char temp[VCARD_ITEM_LENGTH] = {0};
1805                 snprintf(temp, sizeof(temp), "%s:%04d-%02d-%02dT%02d:%02d:%02dZ%s",
1806                                 content_name[CTSVC_VCARD_VALUE_REV],
1807                                 1900+ts.tm_year, 1+ts.tm_mon, ts.tm_mday,
1808                                 ts.tm_hour, ts.tm_min, ts.tm_sec,
1809                                 CTSVC_CRLF);
1810
1811                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, temp);
1812         }
1813 #if 0
1814         ctsvc_list_s *profile;
1815 #endif
1816         return len;
1817 }
1818
1819 static inline int __ctsvc_vcard_append_my_profile(ctsvc_my_profile_s *my_profile, char **buf, int *buf_size, int len)
1820 {
1821         if (my_profile->name) {
1822                 len = __ctsvc_vcard_append_name(my_profile->name, buf, buf_size, len);
1823                 RETV_IF(len < 0, len);
1824         }
1825         if (my_profile->company) {
1826                 len = __ctsvc_vcard_append_company(my_profile->company, buf, buf_size, len);
1827                 RETV_IF(len < 0, len);
1828         }
1829         if (my_profile->note) {
1830                 len = __ctsvc_vcard_append_note(my_profile->note, buf, buf_size, len);
1831                 RETV_IF(len < 0, len);
1832         }
1833         if (my_profile->postal_addrs) {
1834                 len = __ctsvc_vcard_append_postals(my_profile->postal_addrs, buf, buf_size, len);
1835                 RETV_IF(len < 0, len);
1836         }
1837         if (my_profile->numbers) {
1838                 len = __ctsvc_vcard_append_numbers(my_profile->numbers, buf, buf_size, len);
1839                 RETV_IF(len < 0, len);
1840         }
1841         if (my_profile->emails) {
1842                 len = __ctsvc_vcard_append_emails(my_profile->emails, buf, buf_size, len);
1843                 RETV_IF(len < 0, len);
1844         }
1845         if (my_profile->nicknames) {
1846                 len = __ctsvc_vcard_append_nicknames(my_profile->nicknames, buf, buf_size, len);
1847                 RETV_IF(len < 0, len);
1848         }
1849         if (my_profile->urls) {
1850                 len = __ctsvc_vcard_append_webs(my_profile->urls, buf, buf_size, len);
1851                 RETV_IF(len < 0, len);
1852         }
1853         if (my_profile->events) {
1854                 len = __ctsvc_vcard_append_events(my_profile->events, buf, buf_size, len);
1855                 RETV_IF(len < 0, len);
1856         }
1857         if (my_profile->images) {
1858                 len = __ctsvc_vcard_put_photo(my_profile->images, buf, buf_size, len);
1859                 RETV_IF(len < 0, len);
1860         }
1861         if (my_profile->messengers) {
1862                 len = __ctsvc_vcard_append_messengers(my_profile->messengers, buf, buf_size, len);
1863                 RETV_IF(len < 0, len);
1864         }
1865         if (my_profile->relationships) {
1866                 len = __ctsvc_vcard_append_relationships(my_profile->relationships, buf, buf_size, len);
1867                 RETV_IF(len < 0, len);
1868         }
1869
1870         if (my_profile->uid && DEFAULT_ADDRESS_BOOK_ID == my_profile->addressbook_id) {
1871                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_UID]);
1872                 CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, my_profile->uid);
1873         }
1874
1875         if (my_profile->changed_time) {
1876                 struct tm ts;
1877                 gmtime_r((time_t *)&my_profile->changed_time, &ts);
1878                 char temp[VCARD_ITEM_LENGTH] = {0};
1879                 snprintf(temp, sizeof(temp), "%s:%04d-%02d-%02dT%02d:%02d:%02dZ%s",
1880                                 content_name[CTSVC_VCARD_VALUE_REV],
1881                                 1900+ts.tm_year, 1+ts.tm_mon, ts.tm_mday,
1882                                 ts.tm_hour, ts.tm_min, ts.tm_sec,
1883                                 CTSVC_CRLF);
1884
1885                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, temp);
1886         }
1887
1888 #if 0
1889         ctsvc_list_s *profile;
1890 #endif
1891         return len;
1892 }
1893
1894 static inline int __ctsvc_vcard_append_start_vcard_3_0(char **buf, int *buf_size, int len)
1895 {
1896         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, "BEGIN:VCARD");
1897         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, CTSVC_CRLF);
1898         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, "VERSION:3.0");
1899         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, CTSVC_CRLF);
1900         return len;
1901 }
1902
1903 static inline int __ctsvc_vcard_append_end_vcard(char **buf, int *buf_size, int len)
1904 {
1905         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, "END:VCARD");
1906         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, CTSVC_CRLF);
1907         return len;
1908 }
1909
1910 static int __ctsvc_vcard_make(ctsvc_contact_s *contact, char **vcard_stream)
1911 {
1912         char *buf = NULL;
1913         int buf_size = VCARD_INIT_LENGTH;
1914         int len = 0;
1915
1916         __ctsvc_vcard_initial();
1917
1918         buf = calloc(1, buf_size);
1919         if (NULL == buf) {
1920                 /* LCOV_EXCL_START */
1921                 ERR("calloc() Fail");
1922                 return CONTACTS_ERROR_OUT_OF_MEMORY;
1923                 /* LCOV_EXCL_STOP */
1924         }
1925
1926         len = __ctsvc_vcard_append_start_vcard_3_0(&buf, &buf_size, len);
1927         if (len < 0) {
1928                 /* LCOV_EXCL_START */
1929                 free(buf);
1930                 return CONTACTS_ERROR_OUT_OF_MEMORY;
1931                 /* LCOV_EXCL_STOP */
1932         }
1933
1934         len = __ctsvc_vcard_append_contact(contact, &buf, &buf_size, len);
1935         if (len < 0) {
1936                 /* LCOV_EXCL_START */
1937                 free(buf);
1938                 return CONTACTS_ERROR_OUT_OF_MEMORY;
1939                 /* LCOV_EXCL_STOP */
1940         }
1941
1942         len = __ctsvc_vcard_append_end_vcard(&buf, &buf_size, len);
1943         if (len < 0) {
1944                 /* LCOV_EXCL_START */
1945                 free(buf);
1946                 return CONTACTS_ERROR_OUT_OF_MEMORY;
1947                 /* LCOV_EXCL_STOP */
1948         }
1949
1950         len = __ctsvc_vcard_add_folding(&buf, &buf_size, len);
1951         if (len < 0) {
1952                 /* LCOV_EXCL_START */
1953                 free(buf);
1954                 return CONTACTS_ERROR_OUT_OF_MEMORY;
1955                 /* LCOV_EXCL_STOP */
1956         }
1957         *vcard_stream = buf;
1958
1959         return CONTACTS_ERROR_NONE;
1960 }
1961
1962 static int __ctsvc_vcard_make_from_my_profile(ctsvc_my_profile_s *my_profile, char **vcard_stream)
1963 {
1964         char *buf = NULL;
1965         int buf_size = VCARD_INIT_LENGTH;
1966         int len = 0;
1967
1968         __ctsvc_vcard_initial();
1969
1970         buf = calloc(1, buf_size);
1971         if (NULL == buf) {
1972                 /* LCOV_EXCL_START */
1973                 ERR("calloc() Fail");
1974                 return CONTACTS_ERROR_OUT_OF_MEMORY;
1975                 /* LCOV_EXCL_STOP */
1976         }
1977
1978         len = __ctsvc_vcard_append_start_vcard_3_0(&buf, &buf_size, len);
1979         if (len < 0) {
1980                 /* LCOV_EXCL_START */
1981                 free(buf);
1982                 return CONTACTS_ERROR_OUT_OF_MEMORY;
1983                 /* LCOV_EXCL_STOP */
1984         }
1985
1986         len = __ctsvc_vcard_append_my_profile(my_profile, &buf, &buf_size, len);
1987         if (len < 0) {
1988                 /* LCOV_EXCL_START */
1989                 free(buf);
1990                 return CONTACTS_ERROR_OUT_OF_MEMORY;
1991                 /* LCOV_EXCL_STOP */
1992         }
1993
1994         len = __ctsvc_vcard_append_end_vcard(&buf, &buf_size, len);
1995         if (len < 0) {
1996                 /* LCOV_EXCL_START */
1997                 free(buf);
1998                 return CONTACTS_ERROR_OUT_OF_MEMORY;
1999                 /* LCOV_EXCL_STOP */
2000         }
2001
2002         len = __ctsvc_vcard_add_folding(&buf, &buf_size, len);
2003         if (len < 0) {
2004                 /* LCOV_EXCL_START */
2005                 free(buf);
2006                 return CONTACTS_ERROR_OUT_OF_MEMORY;
2007                 /* LCOV_EXCL_STOP */
2008         }
2009
2010         *vcard_stream = buf;
2011
2012         return CONTACTS_ERROR_NONE;
2013 }
2014
2015 EXPORT_API int contacts_vcard_make_from_contact(contacts_record_h record, char **vcard_stream)
2016 {
2017         CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
2018         ctsvc_contact_s *contact;
2019         RETV_IF(NULL == vcard_stream, CONTACTS_ERROR_INVALID_PARAMETER);
2020         *vcard_stream = NULL;
2021
2022         RETVM_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER,
2023                         "contact(%p), vcard_stream(%p)", record, vcard_stream);
2024
2025         contact = (ctsvc_contact_s*)record;
2026         RETVM_IF(CTSVC_RECORD_CONTACT != contact->base.r_type, CONTACTS_ERROR_INVALID_PARAMETER,
2027                         "The record is not conatct record (type : %d)", contact->base.r_type);
2028
2029         return __ctsvc_vcard_make(contact, vcard_stream);
2030 }
2031
2032 EXPORT_API int contacts_vcard_make_from_my_profile(contacts_record_h record, char **vcard_stream)
2033 {
2034         CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
2035         ctsvc_my_profile_s *my_profile;
2036         RETV_IF(NULL == vcard_stream, CONTACTS_ERROR_INVALID_PARAMETER);
2037         *vcard_stream = NULL;
2038
2039         RETVM_IF(NULL == record, CONTACTS_ERROR_INVALID_PARAMETER,
2040                         "my_profile(%p), vcard_stream(%p)", record, vcard_stream);
2041
2042         my_profile = (ctsvc_my_profile_s*)record;
2043         RETVM_IF(CTSVC_RECORD_MY_PROFILE != my_profile->base.r_type, CONTACTS_ERROR_INVALID_PARAMETER,
2044                         "The record is not conatct record (type : %d)", my_profile->base.r_type);
2045
2046         return __ctsvc_vcard_make_from_my_profile(my_profile, vcard_stream);
2047 }
2048
2049 #ifdef _CONTACTS_IPC_CLIENT
2050 static int __ctsvc_vcard_append_person(ctsvc_person_s *person, ctsvc_list_s *list_contacts, char **buf, int *buf_size, int len)
2051 {
2052         int changed_time = 0;
2053         ctsvc_contact_s *contact;
2054         GList *cursor = NULL;
2055
2056         for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2057                 contact = cursor->data;
2058                 if (contact && contact->id == person->name_contact_id && contact->name) {
2059                         len = __ctsvc_vcard_append_name(contact->name, buf, buf_size, len);
2060                         RETV_IF(len < 0, len);
2061                 }
2062         }
2063
2064         for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2065                 contact = cursor->data;
2066                 if (contact && contact->company && contact->company->cursor) {
2067                         len = __ctsvc_vcard_append_company(contact->company, buf, buf_size, len);
2068                         RETV_IF(len < 0, len);
2069                 }
2070         }
2071
2072         for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2073                 contact = cursor->data;
2074                 if (contact && contact->note && contact->note->cursor) {
2075                         len = __ctsvc_vcard_append_note(contact->note, buf, buf_size, len);
2076                         RETV_IF(len < 0, len);
2077                 }
2078         }
2079         for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2080                 contact = cursor->data;
2081                 if (contact && contact->postal_addrs && contact->postal_addrs->cursor) {
2082                         len = __ctsvc_vcard_append_postals(contact->postal_addrs, buf, buf_size, len);
2083                         RETV_IF(len < 0, len);
2084                 }
2085         }
2086         for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2087                 contact = cursor->data;
2088                 if (contact && contact->numbers && contact->numbers->cursor) {
2089                         len = __ctsvc_vcard_append_numbers(contact->numbers, buf, buf_size, len);
2090                         RETV_IF(len < 0, len);
2091                 }
2092         }
2093
2094         for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2095                 contact = cursor->data;
2096                 if (contact && contact->emails && contact->emails->cursor) {
2097                         len = __ctsvc_vcard_append_emails(contact->emails, buf, buf_size, len);
2098                         RETV_IF(len < 0, len);
2099                 }
2100         }
2101
2102         for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2103                 contact = cursor->data;
2104                 if (contact && contact->nicknames && contact->nicknames->cursor) {
2105                         len = __ctsvc_vcard_append_nicknames(contact->nicknames, buf, buf_size, len);
2106                         RETV_IF(len < 0, len);
2107                 }
2108         }
2109         for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2110                 contact = cursor->data;
2111                 if (contact && contact->urls && contact->urls->cursor) {
2112                         len = __ctsvc_vcard_append_webs(contact->urls, buf, buf_size, len);
2113                         RETV_IF(len < 0, len);
2114                 }
2115         }
2116
2117         for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2118                 contact = cursor->data;
2119                 if (contact && contact->events && contact->events->cursor) {
2120                         len = __ctsvc_vcard_append_events(contact->events, buf, buf_size, len);
2121                         RETV_IF(len < 0, len);
2122                 }
2123         }
2124         for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2125                 contact = cursor->data;
2126                 if (contact && contact->images && contact->images->cursor) {
2127                         len = __ctsvc_vcard_put_photo(contact->images, buf, buf_size, len);
2128                         RETV_IF(len < 0, len);
2129                 }
2130         }
2131         for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2132                 contact = cursor->data;
2133                 if (contact && contact->messengers && contact->messengers->cursor) {
2134                         len = __ctsvc_vcard_append_messengers(contact->messengers, buf, buf_size, len);
2135                         RETV_IF(len < 0, len);
2136                 }
2137         }
2138
2139         for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2140                 contact = cursor->data;
2141                 if (contact && contact->relationships && contact->relationships->cursor) {
2142                         len = __ctsvc_vcard_append_relationships(contact->relationships, buf, buf_size, len);
2143                         RETV_IF(len < 0, len);
2144                 }
2145         }
2146
2147         for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2148                 contact = cursor->data;
2149                 if (contact && contact->uid && DEFAULT_ADDRESS_BOOK_ID == contact->addressbook_id) {
2150                         CTSVC_VCARD_APPEND_STR(buf, buf_size, len, content_name[CTSVC_VCARD_VALUE_UID]);
2151                         CTSVC_VCARD_APPEND_CONTENT(buf, buf_size, len, contact->uid);
2152                 }
2153         }
2154         for (cursor = list_contacts->records; cursor; cursor = cursor->next) {
2155                 contact = cursor->data;
2156                 if (contact && changed_time < contact->changed_time)
2157                         changed_time = contact->changed_time;
2158         }
2159
2160         if (changed_time) {
2161                 struct tm ts;
2162                 gmtime_r((time_t*)&changed_time, &ts);
2163                 char temp[VCARD_ITEM_LENGTH] = {0};
2164                 snprintf(temp, sizeof(temp), "%s:%04d-%02d-%02dT%02d:%02d:%02dZ%s",
2165                                 content_name[CTSVC_VCARD_VALUE_REV],
2166                                 1900+ts.tm_year, 1+ts.tm_mon, ts.tm_mday,
2167                                 ts.tm_hour, ts.tm_min, ts.tm_sec,
2168                                 CTSVC_CRLF);
2169
2170                 CTSVC_VCARD_APPEND_STR(buf, buf_size, len, temp);
2171         }
2172
2173 #if 0
2174         ctsvc_list_s *profile;
2175 #endif
2176         return len;
2177 }
2178 #endif /* _CONTACTS_IPC_CLIENT */
2179
2180 #ifdef _CONTACTS_IPC_CLIENT
2181 static int __ctsvc_vcard_make_from_person(ctsvc_person_s *person, ctsvc_list_s *list_contacts,
2182                 char **vcard_stream)
2183 {
2184         char *buf = NULL;
2185         int buf_size = VCARD_INIT_LENGTH;
2186         int len = 0;
2187
2188         RETV_IF(NULL == vcard_stream, CONTACTS_ERROR_INVALID_PARAMETER);
2189         *vcard_stream = NULL;
2190
2191         __ctsvc_vcard_initial();
2192
2193         buf = calloc(1, buf_size);
2194         if (NULL == buf) {
2195                 /* LCOV_EXCL_START */
2196                 ERR("calloc() Fail");
2197                 return CONTACTS_ERROR_OUT_OF_MEMORY;
2198                 /* LCOV_EXCL_STOP */
2199         }
2200
2201         len = __ctsvc_vcard_append_start_vcard_3_0(&buf, &buf_size, len);
2202         if (len < 0) {
2203                 /* LCOV_EXCL_START */
2204                 free(buf);
2205                 return CONTACTS_ERROR_OUT_OF_MEMORY;
2206                 /* LCOV_EXCL_STOP */
2207         }
2208
2209         len = __ctsvc_vcard_append_person(person, list_contacts, &buf, &buf_size, len);
2210         if (len < 0) {
2211                 /* LCOV_EXCL_START */
2212                 free(buf);
2213                 return CONTACTS_ERROR_OUT_OF_MEMORY;
2214                 /* LCOV_EXCL_STOP */
2215         }
2216         len = __ctsvc_vcard_append_end_vcard(&buf, &buf_size, len);
2217         if (len < 0) {
2218                 /* LCOV_EXCL_START */
2219                 free(buf);
2220                 return CONTACTS_ERROR_OUT_OF_MEMORY;
2221                 /* LCOV_EXCL_STOP */
2222         }
2223
2224         len = __ctsvc_vcard_add_folding(&buf, &buf_size, len);
2225         if (len < 0) {
2226                 /* LCOV_EXCL_START */
2227                 free(buf);
2228                 return CONTACTS_ERROR_OUT_OF_MEMORY;
2229                 /* LCOV_EXCL_STOP */
2230         }
2231
2232         *vcard_stream = buf;
2233
2234         return CONTACTS_ERROR_NONE;
2235 }
2236 #endif /* _CONTACTS_IPC_CLIENT */
2237
2238 #ifdef _CONTACTS_IPC_CLIENT
2239 EXPORT_API int contacts_vcard_make_from_person(contacts_record_h record, char **vcard_stream)
2240 {
2241         CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
2242         int ret;
2243         ctsvc_person_s *person;
2244         contacts_query_h query = NULL;
2245         contacts_filter_h filter = NULL;
2246         contacts_list_h list = NULL;
2247
2248         RETVM_IF(NULL == record || NULL == vcard_stream, CONTACTS_ERROR_INVALID_PARAMETER,
2249                         "person(%p), vcard_stream(%p)", record, vcard_stream);
2250         *vcard_stream = NULL;
2251
2252         person = (ctsvc_person_s*)record;
2253
2254         RETVM_IF(CTSVC_RECORD_PERSON != person->base.r_type, CONTACTS_ERROR_INVALID_PARAMETER,
2255                         "The record is not conatct record (type : %d)", person->base.r_type);
2256
2257         do {
2258                 if (CONTACTS_ERROR_NONE != (ret = contacts_filter_create(_contacts_contact._uri, &filter))) break;
2259                 if (CONTACTS_ERROR_NONE != (ret = contacts_filter_add_int(filter, _contacts_contact.person_id, CONTACTS_MATCH_EQUAL, person->person_id))) break;
2260                 if (CONTACTS_ERROR_NONE != (ret = contacts_query_create(_contacts_contact._uri, &query))) break;
2261                 if (CONTACTS_ERROR_NONE != (ret = contacts_query_set_filter(query, filter))) break;
2262                 if (CONTACTS_ERROR_NONE != (ret = contacts_db_get_records_with_query(query, 0, 0, &list))) break;
2263                 if (CONTACTS_ERROR_NONE != (ret = __ctsvc_vcard_make_from_person(person, (ctsvc_list_s*)list, vcard_stream))) break;
2264         } while (0);
2265         WARN_IF(CONTACTS_ERROR_NONE != ret, "__ctsvc_vcard_make_from_person() Fail(%d)", ret);
2266         contacts_query_destroy(query);
2267         contacts_filter_destroy(filter);
2268         contacts_list_destroy(list, true);
2269         return ret;
2270 }
2271 #endif
2272
2273 static inline char* __ctsvc_vcard_remove_empty_line(char *src)
2274 {
2275         while (*src) {
2276                 if ('\n' != *src && '\r' != *src)
2277                         break;
2278                 src++;
2279         }
2280         return src;
2281 }
2282
2283 static char* __ctsvc_vcard_check_word(char *src, const char *word)
2284 {
2285         bool start = false;
2286
2287         RETV_IF(NULL == src, NULL);
2288
2289         src = __ctsvc_vcard_remove_empty_line(src);
2290
2291         while (*src) {
2292                 switch (*src) {
2293                 case ' ':
2294                 case ':':
2295                 case ';':
2296                         src++;
2297                         break;
2298                 default:
2299                         start = true;
2300                         break;
2301                 }
2302                 if (start) break;
2303         }
2304
2305         while (*src == *word) {
2306                 src++;
2307                 word++;
2308
2309                 if ('\0' == *src || '\0' == *word)
2310                         break;
2311         }
2312
2313         if ('\0' == *word)
2314                 return src;
2315         else
2316                 return NULL;
2317 }
2318
2319 static int __ctsvc_vcard_check_content_type(char **vcard)
2320 {
2321         int i;
2322         char *new_start;
2323
2324         for (i = CTSVC_VCARD_VALUE_NONE+1; i < CTSVC_VCARD_VALUE_MAX; i++) {
2325                 new_start = __ctsvc_vcard_check_word(*vcard, content_name[i]);
2326                 if (new_start && (':' == *new_start || ';' == *new_start))
2327                         break;
2328         }
2329
2330         if (CTSVC_VCARD_VALUE_MAX == i) {
2331                 return CTSVC_VCARD_VALUE_NONE;
2332         } else {
2333                 *vcard = new_start;
2334                 return i;
2335         }
2336 }
2337
2338 static inline char* __ctsvc_vcard_pass_unsupported(char *vcard)
2339 {
2340         while (*vcard) {
2341                 if ('\n' == *vcard)
2342                         return (vcard + 1);
2343                 vcard++;
2344         }
2345
2346         return NULL;
2347 }
2348
2349 static char* __ctsvc_strtok(char *val, char c)
2350 {
2351         char *before = NULL;
2352         while (*val) {
2353                 if (*val == c && (NULL == before || *before != '\\')) {
2354                         *val = '\0';
2355                         return (val+1);
2356                 }
2357                 before = val;
2358                 val++;
2359         }
2360         return val;
2361 }
2362
2363 static inline bool __ctsvc_vcard_check_base64_encoded(char *src)
2364 {
2365         int ret;
2366         char *tmp = src;
2367
2368         while (*tmp) {
2369                 if ('B' == *tmp) {
2370                         ret = strncmp(tmp, "BASE64", sizeof("BASE64") - 1);
2371                         if (STRING_EQUAL == ret)
2372                                 return true;
2373                 } else if (':' == *tmp || '\r' == *tmp) {
2374                         break;
2375                 }
2376                 tmp++;
2377         }
2378         return false;
2379 }
2380
2381 static inline int __ctsvc_vcard_check_quoted(char *src, int max, int *quoted)
2382 {
2383         int ret;
2384         if (TRUE == *quoted)
2385                 return TRUE;
2386
2387         while (*src && max) {
2388                 if ('Q' == *src) {
2389                         ret = strncmp(src, "QUOTED-PRINTABLE", sizeof("QUOTED-PRINTABLE") - 1);
2390                         if (STRING_EQUAL == ret) {
2391                                 *quoted = TRUE;
2392                                 return TRUE;
2393                         }
2394                 } else if (':' == *src) {
2395                         break;
2396                 }
2397                 src++;
2398                 max--;
2399         }
2400         return FALSE;
2401 }
2402
2403 static inline int __ctsvc_vcard_remove_folding(char *folded_src)
2404 {
2405         char *result = folded_src;
2406
2407         RETV_IF(NULL == folded_src, CONTACTS_ERROR_INVALID_PARAMETER);
2408
2409         while (*folded_src) {
2410                 if ('\r' == *folded_src && '\n' == *(folded_src+1) && ' ' == *(folded_src+2))
2411                         folded_src += 3;
2412                 else if ('\n' == *folded_src && ' ' == *(folded_src+1))
2413                         folded_src += 2;
2414
2415                 if ('\0' == *folded_src)
2416                         break;
2417
2418                 *result = *folded_src;
2419                 result++;
2420                 folded_src++;
2421         }
2422         *result = '\0';
2423         return CONTACTS_ERROR_NONE;
2424 }
2425
2426 static inline int __ctsvc_vcard_hex_to_dec(char hex)
2427 {
2428         switch (hex) {
2429         case '0' ... '9':
2430                 return hex - '0';
2431         case 'a' ... 'f':
2432                 return hex - 'a' + 10;
2433         case 'A' ... 'F':
2434                 return hex - 'A' + 10;
2435         default:
2436                 return -1;
2437         }
2438 }
2439 static inline int __ctsvc_vcard_decode_quoted_val(char *val)
2440 {
2441         char *src, *dest;
2442         int pre;
2443
2444         src = strchr(val, ':');
2445         if (NULL == src)
2446                 src = val;
2447
2448         dest = src;
2449         while (*src) {
2450                 if ('=' == *src) {
2451                         pre = __ctsvc_vcard_hex_to_dec(*(src+1));
2452                         if (0 <= pre) {
2453                                 *dest = (char)((pre << 4) + __ctsvc_vcard_hex_to_dec(*(src+2)));
2454                                 dest++;
2455                                 src += 2;
2456                         } else {
2457                                 if ('\r' == *(src+1) && '\n' == *(src+2))
2458                                         src += 2;
2459                         }
2460                 } else {
2461                         *dest = *src;
2462                         dest++;
2463                 }
2464                 src++;
2465         }
2466
2467         *dest = '\0';
2468         return dest - val;
2469 }
2470
2471 static inline char* __ctsvc_vcard_translate_charset(char *src, int len)
2472 {
2473         int ret;
2474         char *val = src;
2475
2476         while (*val) {
2477                 if ('C' == *val) {
2478                         ret = strncmp(val, "CHARSET", sizeof("CHARSET") - 1);
2479                         if (STRING_EQUAL == ret) {
2480                                 val += sizeof("CHARSET");
2481                                 break;
2482                         }
2483                 } else if (':' == *val) {
2484                         return NULL;
2485                 }
2486                 val++;
2487         }
2488
2489         if (*val) {
2490                 UChar *temp;
2491                 UConverter *conv;
2492                 UErrorCode err = U_ZERO_ERROR;
2493                 int dest_size = 0;
2494                 int temp_size = 0;
2495                 int src_len, i = 0;
2496                 char enc[32] = {0}, *dest;
2497
2498                 while (';' != *val && ':' != *val)
2499                         enc[i++] = *val++;
2500
2501                 enc[i] = '\0';
2502                 if (0 == strcasecmp("UTF-8", enc))
2503                         return NULL;
2504
2505                 while (':' != *val)
2506                         val++;
2507
2508                 src_len = len - (val - src);
2509
2510                 temp_size = (src_len+1) * sizeof(UChar);
2511                 temp = malloc(temp_size);
2512                 if (NULL == temp) {
2513                         ERR("malloc() Fail");
2514                         return NULL;
2515                 }
2516                 conv = ucnv_open(enc, &err);
2517                 WARN_IF(U_FAILURE(err), "ucnv_open() Fail(%d), enc=%s", err, enc);
2518                 ucnv_toUChars(conv, temp, temp_size, val, src_len, &err);
2519                 WARN_IF(U_FAILURE(err), "ucnv_toUChars() Fail(%d), enc=%s", err, enc);
2520                 ucnv_close(conv);
2521
2522                 dest_size = temp_size*2;
2523                 dest = malloc(dest_size);
2524                 if (NULL == dest) {
2525                         ERR("malloc() Fail");
2526                         free(temp);
2527                         return NULL;
2528                 }
2529                 conv = ucnv_open("UTF-8", &err);
2530                 WARN_IF(U_FAILURE(err), "ucnv_open() Fail(%d), enc=%s", err, enc);
2531                 ucnv_fromUChars(conv, dest, dest_size, temp, u_strlen(temp), &err);
2532                 WARN_IF(U_FAILURE(err), "ucnv_fromUChars() Fail(%d), enc=%s", err, enc);
2533                 ucnv_close(conv);
2534                 free(temp);
2535
2536                 return dest;
2537         }
2538         return NULL;
2539 }
2540
2541 static void __ctsvc_vcard_get_prefix(char **prefix, char *src)
2542 {
2543         char *temp = strchr(src, ':');
2544         if (temp) {
2545                 int len = (int)temp - (int)src;
2546                 *prefix = calloc(len+1, sizeof(char));
2547                 if (*prefix)
2548                         snprintf(*prefix, len+1, "%s", src);
2549         } else {
2550                 *prefix = NULL;
2551         }
2552 }
2553
2554 static char* __ctsvc_vcard_get_val(int ver, char *src, char **prefix, char **dest)
2555 {
2556         int quoted;
2557         bool start = false;
2558         char *cursor;
2559
2560         RETV_IF(NULL == src, NULL);
2561         RETV_IF(NULL == dest, NULL);
2562
2563         while (*src) {
2564                 switch (*src) {
2565                 case '\n':
2566                         return NULL;
2567                 case '\r':
2568                 case ' ':
2569                         src++;
2570                         break;
2571                 default:
2572                         start = true;
2573                         break;
2574                 }
2575                 if (start) break;
2576         }
2577
2578         quoted = FALSE;
2579         cursor = src;
2580         if (CTSVC_VCARD_VER_2_1 == ver) {
2581                 while (*cursor) {
2582                         if ('=' == *cursor && __ctsvc_vcard_check_quoted(src, cursor - src, &quoted)) {
2583                                 if ('\r' == *(cursor+1) && '\n' == *(cursor+2))
2584                                         cursor += 2;
2585                         } else {
2586                                 if ('\r' == *cursor && '\n' == *(cursor+1) && ' ' != *(cursor+2))
2587                                         break;
2588                                 if ('\n' == *cursor && ' ' != *(cursor+1))
2589                                         break;
2590                         }
2591
2592                         cursor++;
2593                 }
2594         } else {
2595                 while (*cursor) {
2596                         if ('\r' == *cursor && '\n' == *(cursor+1) && ' ' != *(cursor+2))
2597                                 break;
2598
2599                         if ('\n' == *cursor && ' ' != *(cursor+1))
2600                                 break;
2601
2602                         cursor++;
2603                 }
2604         }
2605
2606         if (src == cursor) {
2607                 *dest = NULL;
2608                 return NULL;
2609         } else {
2610                 int len = 0;
2611                 char temp = *cursor;
2612                 char *new_dest;
2613
2614                 if (prefix)
2615                         __ctsvc_vcard_get_prefix(prefix, src);
2616
2617                 *cursor = '\0';
2618                 *dest = strdup(src);
2619                 if (NULL == *dest) {
2620                         ERR("strdup() Fail");
2621                         return NULL;
2622                 }
2623                 if (CTSVC_VCARD_VER_2_1 != ver)
2624                         __ctsvc_vcard_remove_folding(*dest);
2625
2626                 if (__ctsvc_vcard_check_quoted(*dest, -1, &quoted))
2627                         len = __ctsvc_vcard_decode_quoted_val(*dest);
2628                 if (0 == len)
2629                         len = strlen(*dest);
2630                 new_dest = __ctsvc_vcard_translate_charset(*dest, len);
2631                 if (new_dest) {
2632                         free(*dest);
2633                         *dest = new_dest;
2634                 }
2635                 *cursor = temp;
2636                 return (cursor + 1);
2637         }
2638 }
2639
2640 static inline char* __ctsvc_get_content_value(char *val)
2641 {
2642         char *temp;
2643
2644         temp = strchr(val, ':');
2645         if (temp)
2646                 temp++;
2647         else
2648                 temp = val;
2649
2650         RETVM_IF('\0' == *(temp) || '\r' == *(temp) || '\n' == *(temp),
2651                         NULL, "Invalid vcard content");
2652
2653         return temp;
2654 }
2655
2656 static char* __ctsvc_vcard_remove_escape_char(char *str)
2657 {
2658         char *s = SAFE_STR(str);
2659         char *r = s;
2660         while (*s) {
2661                 if (*s == '\\' && *(s+1)) {
2662                         char *n = (char*)(s+1);
2663                         switch (*n) {
2664                         case 'n':
2665                         case 'N':
2666                                 *r = '\n';
2667                                 s++;
2668                                 break;
2669                         case ';':
2670                         case ':':
2671                         case ',':
2672                         case '<':
2673                         case '>':
2674                         case '\\':
2675                                 *r = *n;
2676                                 s++;
2677                                 break;
2678                         case 0xA1:  /* en/em backslash */
2679                                 if (*(n+1) && 0xAC == *(n+1)) {
2680                                         *r = *n;
2681                                         r++;
2682                                         *r = *(n+1);
2683                                         s += 2;
2684                                 }
2685                                 break;
2686                         case 0x81:  /* en/em backslash */
2687                                 if (*(n+1) && 0x5F == *(n+1)) {
2688                                         *r = *n;
2689                                         r++;
2690                                         *r = *(n+1);
2691                                         s += 2;
2692                                 }
2693                                 break;
2694                         default:
2695                                 *r = *s;
2696                                 break;
2697                         }
2698                         r++;
2699                         s++;
2700                 } else {
2701                         *r = *s;
2702                         r++;
2703                         s++;
2704                 }
2705         }
2706         *r = '\0';
2707         return str;
2708 }
2709
2710 static inline int __ctsvc_vcard_get_display_name(ctsvc_list_s *name_list, char *val)
2711 {
2712         int ret;
2713         int count;
2714         char *temp;
2715         char *first_name = NULL;
2716         char *last_name = NULL;
2717         contacts_record_h name;
2718
2719         temp = __ctsvc_get_content_value(val);
2720         RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "vcard");
2721
2722         contacts_list_get_count((contacts_list_h)name_list, &count);
2723         if (count <= 0) {
2724                 ret = contacts_record_create(_contacts_name._uri, &name);
2725                 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create is Fail(%d)", ret);
2726                 contacts_list_add((contacts_list_h)name_list, name);
2727         } else {
2728                 contacts_list_get_current_record_p((contacts_list_h)name_list, &name);
2729         }
2730
2731         ret = contacts_record_get_str_p(name, _contacts_name.first, &first_name);
2732         WARN_IF(ret != CONTACTS_ERROR_NONE, "contacts_record_get_str_p is Fail(%d)", ret);
2733         ret = contacts_record_get_str_p(name, _contacts_name.last, &last_name);
2734         WARN_IF(ret != CONTACTS_ERROR_NONE, "contacts_record_get_str_p is Fail(%d)", ret);
2735
2736         if ((NULL == first_name || '\0' == *first_name) && (NULL == last_name || '\0' == *last_name))
2737                 contacts_record_set_str(name, _contacts_name.first, __ctsvc_vcard_remove_escape_char(temp));
2738
2739         return CONTACTS_ERROR_NONE;
2740 }
2741
2742 #define CTS_GET_MULTIPLE_COMPONENT(dest, src, src_temp, separator) \
2743         src_temp = src; \
2744 separator = false; \
2745 while (src_temp && *src_temp) { \
2746         if (*src_temp == ';') { \
2747                 separator = true; \
2748                 *src_temp = '\0'; \
2749                 src = __ctsvc_vcard_remove_escape_char(src); \
2750                 dest = SMART_STRDUP(src); \
2751                 src = src_temp+1; \
2752                 break; \
2753         } \
2754         else if (*src_temp == '\\') {\
2755                 src_temp += 2; \
2756                 continue; \
2757         } \
2758         src_temp++; \
2759 } \
2760 if (false == separator && src && *src) { \
2761         src = __ctsvc_vcard_remove_escape_char(src); \
2762         dest = SMART_STRDUP(src); \
2763         break; \
2764 }
2765
2766 static inline int __ctsvc_vcard_get_name(ctsvc_list_s *name_list, char *val)
2767 {
2768         int ret;
2769         int count;
2770         char *start;
2771         contacts_record_h name;
2772
2773         start = __ctsvc_get_content_value(val);
2774         RETV_IF(NULL == start, CONTACTS_ERROR_NO_DATA);
2775
2776         contacts_list_get_count((contacts_list_h)name_list, &count);
2777         if (count <= 0) {
2778                 ret = contacts_record_create(_contacts_name._uri, &name);
2779                 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
2780                 contacts_list_add((contacts_list_h)name_list, name);
2781         } else {
2782                 contacts_list_get_current_record_p((contacts_list_h)name_list, &name);
2783         }
2784
2785         contacts_record_set_str(name, _contacts_name.first, NULL);  /* remove FN */
2786
2787         do {
2788                 bool separator = false;
2789                 char *start_temp;
2790
2791                 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_name_s*)name)->last, start, start_temp, separator);
2792                 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_name_s*)name)->first, start, start_temp, separator);
2793                 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_name_s*)name)->addition, start, start_temp, separator);
2794                 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_name_s*)name)->prefix, start, start_temp, separator);
2795                 CTS_GET_MULTIPLE_COMPONENT(((ctsvc_name_s*)name)->suffix, start, start_temp, separator);
2796
2797                 ERR("invalid name type");
2798         } while (0);
2799
2800         return CONTACTS_ERROR_NONE;
2801 }
2802
2803 static inline int __ctsvc_vcard_get_phonetic_name(ctsvc_list_s *name_list, int type, char *val)
2804 {
2805         int ret;
2806         int count;
2807         char *start;
2808         const char separator = ';';
2809         contacts_record_h name;
2810
2811         start = __ctsvc_get_content_value(val);
2812         RETV_IF(NULL == start, CONTACTS_ERROR_NO_DATA);
2813
2814         contacts_list_get_count((contacts_list_h)name_list, &count);
2815         if (count <= 0) {
2816                 ret = contacts_record_create(_contacts_name._uri, &name);
2817                 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
2818                 contacts_list_add((contacts_list_h)name_list, name);
2819         } else {
2820                 contacts_list_get_current_record_p((contacts_list_h)name_list, &name);
2821         }
2822
2823         __ctsvc_strtok(start, separator);
2824         if (CTSVC_VCARD_VALUE_PHONETIC_FIRST_NAME == type)
2825                 contacts_record_set_str(name, _contacts_name.phonetic_first, __ctsvc_vcard_remove_escape_char(start));
2826         else if (CTSVC_VCARD_VALUE_PHONETIC_MIDDLE_NAME == type)
2827                 contacts_record_set_str(name, _contacts_name.phonetic_middle, __ctsvc_vcard_remove_escape_char(start));
2828         else if (CTSVC_VCARD_VALUE_PHONETIC_LAST_NAME == type)
2829                 contacts_record_set_str(name, _contacts_name.phonetic_last, __ctsvc_vcard_remove_escape_char(start));
2830
2831         return CONTACTS_ERROR_NONE;
2832 }
2833
2834 static inline int __ctsvc_vcard_get_nickname(ctsvc_list_s *nickname_list, char *val)
2835 {
2836         int ret = CONTACTS_ERROR_NONE;
2837         char *temp;
2838         char *start;
2839         char *last;
2840         const char *separator = ",";
2841
2842         start = __ctsvc_get_content_value(val);
2843         RETV_IF(NULL == start, CONTACTS_ERROR_NO_DATA);
2844
2845         temp = strtok_r(start, separator, &last);
2846         while (temp) {
2847                 if ('\0' == *temp) continue;
2848
2849                 contacts_record_h nickname = NULL;
2850                 ret = contacts_record_create(_contacts_nickname._uri, &nickname);
2851                 if (ret < CONTACTS_ERROR_NONE) {
2852                         GList *cursor = NULL;
2853                         ERR("contacts_record_create() Fail(%d)", ret);
2854                         for (cursor = nickname_list->records; cursor; cursor = cursor->next)
2855                                 contacts_record_destroy((contacts_record_h)(cursor->data), true);
2856                         g_list_free(nickname_list->records);
2857                         nickname_list->records = NULL;
2858                         nickname_list->cursor = NULL;
2859                         nickname_list->count = 0;
2860                         return ret;
2861                 }
2862                 contacts_record_set_str(nickname, _contacts_nickname.name, __ctsvc_vcard_remove_escape_char(start));
2863                 contacts_list_add((contacts_list_h)nickname_list, nickname);
2864
2865                 temp = strtok_r(NULL, separator, &last);
2866         }
2867
2868         return CONTACTS_ERROR_NONE;
2869 }
2870
2871 static inline int __ctsvc_vcard_get_photo(contacts_record_h contact, ctsvc_list_s *image_list, char *prefix, char *val)
2872 {
2873         int ret, type, fd;
2874         gsize size;
2875         guchar *buf;
2876         char *temp;
2877         char dest[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0};
2878         contacts_record_h image;
2879         struct timeval tv;
2880
2881         temp = strchr(val, ':');
2882         RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "val is invalid");
2883
2884         *temp = '\0';
2885
2886         type = __ctsvc_vcard_get_image_type(prefix);
2887
2888         buf = g_base64_decode(temp+1, &size);
2889         if ((0 == size) || (NULL == buf)) {
2890                 g_free(buf);
2891                 return CONTACTS_ERROR_NONE;
2892         }
2893
2894         gettimeofday(&tv, NULL);
2895         ret = snprintf(dest, sizeof(dest), "%s/vcard-image-%ld%ld.%s",
2896                         CTSVC_VCARD_IMAGE_LOCATION, tv.tv_sec, tv.tv_usec, __ctsvc_get_img_suffix(type));
2897
2898         fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, 0660);
2899         if (fd < 0) {
2900                 /* LCOV_EXCL_START */
2901                 g_free(buf);
2902                 ERR("System : open Fail(%d)", errno);
2903                 return CONTACTS_ERROR_SYSTEM;
2904                 /* LCOV_EXCL_STOP */
2905         }
2906
2907         while (0 < size) {
2908                 ret = write(fd, buf, size);
2909                 if (ret <= 0) {
2910                         if (EINTR == errno) {
2911                                 continue;
2912                         } else {
2913                                 ERR("write() Fail(%d)", errno);
2914                                 close(fd);
2915                                 g_free(buf);
2916                                 if (ENOSPC == errno)
2917                                         return CONTACTS_ERROR_FILE_NO_SPACE;   /* No space */
2918                                 else
2919                                         return CONTACTS_ERROR_SYSTEM;   /* IO error */
2920                         }
2921                 }
2922                 size -= ret;
2923         }
2924
2925         close(fd);
2926         g_free(buf);
2927
2928         ret = contacts_record_create(_contacts_image._uri, &image);
2929         RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
2930
2931         contacts_record_set_str(image, _contacts_image.path, dest);
2932         ((ctsvc_image_s*)image)->is_vcard = true;
2933
2934         contacts_list_add((contacts_list_h)image_list, image);
2935
2936         /* _contacts_contact.image_thumbnail_path is a read-only property */
2937         ((ctsvc_contact_s*)contact)->image_thumbnail_path = strdup(dest);
2938
2939         return CONTACTS_ERROR_NONE;
2940
2941 }
2942
2943 static inline void __ctsvc_vcard_get_event_type(contacts_record_h event, char *val)
2944 {
2945         int type = CONTACTS_EVENT_TYPE_OTHER;
2946         char *temp, *result, *last = NULL;
2947         char *lower, *lower_temp;
2948
2949         temp = strtok_r(val, ";", &last);
2950         while (temp) {
2951                 lower = strdup(temp);
2952                 if (NULL == lower) {
2953                         ERR("strdup() Fail");
2954                         break;
2955                 }
2956                 lower_temp = lower;
2957                 while (*lower_temp) {
2958                         *lower_temp = tolower(*lower_temp);
2959                         lower_temp++;
2960                 }
2961                 if (strstr(lower, "anniversary")) {
2962                         type = CONTACTS_EVENT_TYPE_ANNIVERSARY;
2963                 } else if ((result = strstr(lower, "x-"))) {
2964                         type = CONTACTS_EVENT_TYPE_CUSTOM;
2965                         contacts_record_set_str(event, _contacts_event.label, temp+(result-lower)+2);
2966                 }
2967
2968                 free(lower);
2969                 temp = strtok_r(NULL, ";", &last);
2970         }
2971         contacts_record_set_int(event, _contacts_event.type, type);
2972 }
2973
2974
2975 static inline int __ctsvc_vcard_get_event(ctsvc_list_s *event_list, int type, char *prefix, char *val)
2976 {
2977         int ret;
2978         contacts_record_h event;
2979         char *dest, *src, *date;
2980
2981         date = __ctsvc_get_content_value(val);
2982         if (NULL == date) {
2983                 ERR("vcard");
2984                 return CONTACTS_ERROR_INVALID_PARAMETER;
2985         }
2986
2987         dest = src = date;
2988         while (*src) {
2989                 if ('0' <= *src && *src <= '9') {
2990                         *dest = *src;
2991                         dest++;
2992                 }
2993                 src++;
2994                 if (8 <= dest - date)
2995                         break;
2996         }
2997         *dest = '\0';
2998         if ('\0' == *date) {
2999                 ERR("date(%d)", date);
3000                 return CONTACTS_ERROR_INVALID_PARAMETER;
3001         }
3002
3003         ret = contacts_record_create(_contacts_event._uri, &event);
3004         if (ret < CONTACTS_ERROR_NONE) {
3005                 ERR("contacts_record_create() Fail(%d)", ret);
3006                 return ret;
3007         }
3008
3009         contacts_record_set_int(event, _contacts_event.date, atoi(date));
3010
3011         if (CTSVC_VCARD_VALUE_BDAY == type)
3012                 contacts_record_set_int(event, _contacts_event.type, CONTACTS_EVENT_TYPE_BIRTH);
3013         else if (CTSVC_VCARD_VALUE_X_ANNIVERSARY == type)
3014                 contacts_record_set_int(event, _contacts_event.type, CONTACTS_EVENT_TYPE_ANNIVERSARY);
3015         else if (CTSVC_VCARD_VALUE_X_TIZEN_EVENT == type)
3016                 __ctsvc_vcard_get_event_type(event, prefix);
3017
3018         contacts_list_add((contacts_list_h)event_list, event);
3019         return CONTACTS_ERROR_NONE;
3020 }
3021
3022
3023 static inline void __ctsvc_vcard_get_company_type(contacts_record_h company, char *val)
3024 {
3025         char *temp, *result, *last = NULL;
3026         char *lower, *lower_temp;
3027         int type = CONTACTS_COMPANY_TYPE_OTHER;
3028
3029         temp = strtok_r(val, ";", &last);
3030         while (temp) {
3031                 lower = strdup(temp);
3032                 if (NULL == lower) {
3033                         ERR("strdup() Fail");
3034                         break;
3035                 }
3036                 lower_temp = lower;
3037                 while (*lower_temp) {
3038                         *lower_temp = tolower(*lower_temp);
3039                         lower_temp++;
3040                 }
3041
3042                 result = strstr(lower, "work");
3043                 if (result)
3044                         type = CONTACTS_COMPANY_TYPE_WORK;
3045
3046                 result = strstr(lower, "x-");
3047                 if (result) {
3048                         type = CONTACTS_COMPANY_TYPE_CUSTOM;
3049                         contacts_record_set_str(company, _contacts_company.label, temp+(result-lower)+2);
3050                 }
3051
3052                 free(lower);
3053                 temp = strtok_r(NULL, ";", &last);
3054         }
3055         contacts_record_set_int(company, _contacts_company.type, type);
3056 }
3057
3058 static contacts_record_h __ctsvc_vcard_get_company_empty_record(ctsvc_list_s *company_list, int property_id)
3059 {
3060         contacts_record_h record_temp = NULL;
3061         contacts_record_h record = NULL;
3062         contacts_list_h list = (contacts_list_h)company_list;
3063
3064         contacts_list_last(list);
3065         while (CONTACTS_ERROR_NONE == contacts_list_get_current_record_p(list, &record_temp)) {
3066                 char *value = NULL;
3067                 contacts_record_get_str_p(record_temp, property_id, &value);
3068                 if (NULL == value) {
3069                         record = record_temp;
3070                         break;
3071                 }
3072                 contacts_list_prev(list);
3073         }
3074
3075         return record;
3076 }
3077
3078 static inline int __ctsvc_vcard_get_company_value(ctsvc_list_s *company_list, int property_id, char *val)
3079 {
3080         char *value;
3081         contacts_record_h company;
3082
3083         company = __ctsvc_vcard_get_company_empty_record(company_list, property_id);
3084         if (NULL == company) {
3085                 int ret = contacts_record_create(_contacts_company._uri, &company);
3086                 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3087                 contacts_list_add((contacts_list_h)company_list, company);
3088         }
3089
3090         value = __ctsvc_get_content_value(val);
3091         RETV_IF(NULL == value, CONTACTS_ERROR_NO_DATA);
3092
3093         contacts_record_set_str(company, property_id, __ctsvc_vcard_remove_escape_char(value));
3094
3095         return CONTACTS_ERROR_NONE;
3096 }
3097
3098 static inline int __ctsvc_vcard_get_company(ctsvc_list_s *company_list, char *prefix, char *val)
3099 {
3100         char *start, *depart;
3101         const char separator = ';';
3102         contacts_record_h company;
3103
3104         company = __ctsvc_vcard_get_company_empty_record(company_list, _contacts_company.name);
3105         if (NULL == company) {
3106                 int ret = contacts_record_create(_contacts_company._uri, &company);
3107                 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3108                 contacts_list_add((contacts_list_h)company_list, company);
3109         }
3110
3111         start = __ctsvc_get_content_value(val);
3112         RETV_IF(NULL == start, CONTACTS_ERROR_NO_DATA);
3113
3114         depart = __ctsvc_strtok(start, separator);
3115         contacts_record_set_str(company, _contacts_company.name, __ctsvc_vcard_remove_escape_char(start));
3116
3117         if (depart) {
3118                 __ctsvc_strtok(depart, separator);
3119                 contacts_record_set_str(company, _contacts_company.department, __ctsvc_vcard_remove_escape_char(depart));
3120         }
3121
3122         __ctsvc_vcard_get_company_type(company, prefix);
3123
3124         return CONTACTS_ERROR_NONE;
3125 }
3126
3127 static inline int __ctsvc_vcard_get_company_logo(ctsvc_list_s *company_list, char *prefix, char *val)
3128 {
3129         int ret, type, fd;
3130         gsize size;
3131         guchar *buf;
3132         char dest[CTSVC_IMG_FULL_PATH_SIZE_MAX] = {0};
3133         char *temp;
3134         contacts_record_h company;
3135         struct timeval tv;
3136
3137         company = __ctsvc_vcard_get_company_empty_record(company_list, _contacts_company.logo);
3138         if (NULL == company) {
3139                 ret = contacts_record_create(_contacts_company._uri, &company);
3140                 RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3141                 contacts_list_add((contacts_list_h)company_list, company);
3142         }
3143
3144         temp = strchr(val, ':');
3145         RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "val is invalid");
3146
3147         *temp = '\0';
3148         type = __ctsvc_vcard_get_image_type(prefix);
3149
3150         buf = g_base64_decode(temp+1, &size);
3151         if ((0 == size) || (NULL == buf)) {
3152                 g_free(buf);
3153                 return CONTACTS_ERROR_NONE;
3154         }
3155
3156         gettimeofday(&tv, NULL);
3157         ret = snprintf(dest, sizeof(dest), "%s/%d-%ld%ld-logo.%s", CTSVC_VCARD_IMAGE_LOCATION,
3158                         getpid(), tv.tv_sec, tv.tv_usec, __ctsvc_get_img_suffix(type));
3159
3160         fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, 0660);
3161         if (fd < 0) {
3162                 /* LCOV_EXCL_START */
3163                 g_free(buf);
3164                 ERR("System : open Fail(%d)", errno);
3165                 return CONTACTS_ERROR_SYSTEM;
3166                 /* LCOV_EXCL_STOP */
3167         }
3168
3169         while (0 < size) {
3170                 ret = write(fd, buf, size);
3171                 if (ret <= 0) {
3172                         if (EINTR == errno) {
3173                                 continue;
3174                         } else {
3175                                 ERR("write() Fail(%d)", errno);
3176                                 close(fd);
3177                                 g_free(buf);
3178                                 if (ENOSPC == errno)
3179                                         return CONTACTS_ERROR_FILE_NO_SPACE;   /* No space */
3180                                 else
3181                                         return CONTACTS_ERROR_SYSTEM;   /* IO error */
3182                         }
3183                 }
3184                 size -= ret;
3185         }
3186
3187         close(fd);
3188         g_free(buf);
3189
3190         ((ctsvc_company_s*)company)->is_vcard = true;
3191         contacts_record_set_str(company, _contacts_company.logo, dest);
3192
3193         return CONTACTS_ERROR_NONE;
3194 }
3195
3196 static inline int __ctsvc_vcard_get_note(ctsvc_list_s *note_list, char *val)
3197 {
3198         int ret;
3199         char *temp;
3200         contacts_record_h note;
3201
3202         ret = contacts_record_create(_contacts_note._uri, &note);
3203         RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3204         contacts_list_add((contacts_list_h)note_list, note);
3205
3206         temp = __ctsvc_get_content_value(val);
3207         RETV_IF(NULL == temp, CONTACTS_ERROR_NO_DATA);
3208
3209         contacts_record_set_str(note, _contacts_note.note, __ctsvc_vcard_remove_escape_char(temp));
3210
3211         return CONTACTS_ERROR_NONE;
3212 }
3213
3214 static inline int __ctsvc_vcard_get_time(char *val)
3215 {
3216         int i;
3217         char tmp[10] = {0};
3218         struct tm ts = {0};
3219
3220         i = 0;
3221         while (*val && (*val < '0' || '9' < *val)) val++;
3222         while (*val) {
3223                 tmp[i++] = *val;
3224                 val++;
3225                 if (4 <= i || *val < '0' || '9' < *val) break;
3226         }
3227         tmp[i] = 0;
3228         ts.tm_year = atoi(tmp)-1900;
3229
3230         i = 0;
3231         while (*val && (*val < '0' || '9' < *val)) val++;
3232         while (*val) {
3233                 tmp[i++] = *val;
3234                 val++;
3235                 if (2 <= i || *val < '0' || '9' < *val) break;
3236         }
3237         tmp[i] = 0;
3238         ts.tm_mon = atoi(tmp)-1;
3239
3240         i = 0;
3241         while (*val && (*val < '0' || '9' < *val)) val++;
3242         while (*val) {
3243                 tmp[i++] = *val;
3244                 val++;
3245                 if (2 <= i || *val < '0' || '9' < *val) break;
3246         }
3247         tmp[i] = 0;
3248         ts.tm_mday = atoi(tmp);
3249
3250         i = 0;
3251         while (*val && (*val < '0' || '9' < *val)) val++;
3252         while (*val) {
3253                 tmp[i++] = *val;
3254                 val++;
3255                 if (2 <= i || *val < '0' || '9' < *val) break;
3256         }
3257         tmp[i] = 0;
3258         ts.tm_hour = atoi(tmp);
3259
3260         i = 0;
3261         while (*val && (*val < '0' || '9' < *val)) val++;
3262         while (*val) {
3263                 tmp[i++] = *val;
3264                 val++;
3265                 if (2 <= i || *val < '0' || '9' < *val) break;
3266         }
3267         tmp[i] = 0;
3268         ts.tm_min = atoi(tmp);
3269
3270         i = 0;
3271         while (*val && (*val < '0' || '9' < *val)) val++;
3272         while (*val) {
3273                 tmp[i++] = *val;
3274                 val++;
3275                 if (2 <= i || *val < '0' || '9' < *val) break;
3276         }
3277         tmp[i] = 0;
3278         ts.tm_sec = atoi(tmp);
3279
3280         return (int)mktime(&ts);
3281 }
3282
3283 static inline void __ctsvc_vcard_get_url_type(contacts_record_h url, char *val)
3284 {
3285         char *temp, *result, *last = NULL;
3286         char *lower, *lower_temp;
3287         int type = CONTACTS_URL_TYPE_OTHER;
3288
3289         temp = strtok_r(val, ";", &last);
3290         while (temp) {
3291                 lower = strdup(temp);
3292                 if (NULL == lower) {
3293                         ERR("strdup() Fail");
3294                         break;
3295                 }
3296                 lower_temp = lower;
3297                 while (*lower_temp) {
3298                         *lower_temp = tolower(*lower_temp);
3299                         lower_temp++;
3300                 }
3301                 result = strstr(lower, "home");
3302                 if (result) type = CONTACTS_URL_TYPE_HOME;
3303                 result = strstr(lower, "work");
3304                 if (result) type = CONTACTS_URL_TYPE_WORK;
3305                 result = strstr(lower, "x-");
3306                 if (result) {
3307                         type = CONTACTS_URL_TYPE_CUSTOM;
3308                         contacts_record_set_str(url, _contacts_url.label, temp+(result-lower)+2);
3309                 }
3310
3311                 free(lower);
3312                 temp = strtok_r(NULL, ";", &last);
3313         }
3314         contacts_record_set_int(url, _contacts_url.type, type);
3315 }
3316
3317 static inline int __ctsvc_vcard_get_url(ctsvc_list_s *url_list, char *prefix, char *val)
3318 {
3319         int ret;
3320         contacts_record_h url;
3321         char *temp;
3322
3323         temp = __ctsvc_get_content_value(val);
3324         RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "vcard");
3325
3326         ret = contacts_record_create(_contacts_url._uri, &url);
3327         RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3328
3329         contacts_record_set_str(url, _contacts_url.url, __ctsvc_vcard_remove_escape_char(temp));
3330         __ctsvc_vcard_get_url_type(url, prefix);
3331         contacts_list_add((contacts_list_h)url_list, url);
3332
3333         return CONTACTS_ERROR_NONE;
3334 }
3335
3336 static inline bool __ctsvc_vcard_get_number_type(contacts_record_h number, char *val)
3337 {
3338         char *temp, *result, *last = NULL;
3339         char *lower, *lower_temp;
3340         int type = CONTACTS_NUMBER_TYPE_OTHER;
3341         bool pref = false;
3342
3343         temp = strtok_r(val, ";", &last);
3344         while (temp) {
3345                 lower = strdup(temp);
3346                 if (NULL == lower) {
3347                         ERR("strdup() Fail");
3348                         break;
3349                 }
3350                 lower_temp = lower;
3351                 while (*lower_temp) {
3352                         *lower_temp = tolower(*lower_temp);
3353                         lower_temp++;
3354                 }
3355                 result = strstr(lower, "home");
3356                 if (result) type |= CONTACTS_NUMBER_TYPE_HOME;
3357                 result = strstr(lower, "msg");
3358                 if (result) type |= CONTACTS_NUMBER_TYPE_MSG;
3359                 result = strstr(lower, "work");
3360                 if (result) type |= CONTACTS_NUMBER_TYPE_WORK;
3361                 result = strstr(lower, "pref");
3362                 if (result) pref = true;
3363                 result = strstr(lower, "voice");
3364                 if (result) type |= CONTACTS_NUMBER_TYPE_VOICE;
3365                 result = strstr(lower, "fax");
3366                 if (result) type |= CONTACTS_NUMBER_TYPE_FAX;
3367                 result = strstr(lower, "cell");
3368                 if (result) type |= CONTACTS_NUMBER_TYPE_CELL;
3369                 result = strstr(lower, "video");
3370                 if (result) type |= CONTACTS_NUMBER_TYPE_VIDEO;
3371                 result = strstr(lower, "pager");
3372                 if (result) type |= CONTACTS_NUMBER_TYPE_PAGER;
3373                 result = strstr(lower, "bbs");
3374                 if (result) type |= CONTACTS_NUMBER_TYPE_BBS;
3375                 result = strstr(lower, "modem");
3376                 if (result) type |= CONTACTS_NUMBER_TYPE_MODEM;
3377                 result = strstr(lower, "car");
3378                 if (result) type |= CONTACTS_NUMBER_TYPE_CAR;
3379                 result = strstr(lower, "isdn");
3380                 if (result) type |= CONTACTS_NUMBER_TYPE_ISDN;
3381                 result = strstr(lower, "pcs");
3382                 if (result) type |= CONTACTS_NUMBER_TYPE_PCS;
3383                 result = strstr(lower, "x-");
3384                 if (result) {
3385                         if (strstr(lower, "x-assistant")) {
3386                                 type |= CONTACTS_NUMBER_TYPE_ASSISTANT;
3387                         } else if (strstr(lower, "x-radio")) {
3388                                 type |= CONTACTS_NUMBER_TYPE_RADIO;
3389                         } else if (strstr(lower, "x-company-main")) {
3390                                 type |= CONTACTS_NUMBER_TYPE_COMPANY_MAIN;
3391                         } else if (strstr(lower, "x-main")) {
3392                                 type |= CONTACTS_NUMBER_TYPE_MAIN;
3393                         } else {
3394                                 type = CONTACTS_NUMBER_TYPE_CUSTOM;
3395                                 contacts_record_set_str(number, _contacts_number.label, temp+(result-lower)+2);
3396                         }
3397                 }
3398
3399                 free(lower);
3400                 temp = strtok_r(NULL, ";", &last);
3401         }
3402         contacts_record_set_int(number, _contacts_number.type, type);
3403
3404         return pref;
3405 }
3406
3407 static char* __ctsvc_vcard_get_clean_number_for_import(char *str)
3408 {
3409         int char_len = 0;
3410         char *s = SAFE_STR(str);
3411         char *r = s;
3412         while (*s) {
3413                 char_len = __ctsvc_vcard_check_utf8(*s);
3414                 if (3 == char_len) {
3415                         if (*s == 0xef) {
3416                                 if (*(s+1) == 0xbc) {
3417                                         if (0x90 <= *(s+2) && *(s+2) <= 0x99) {   /* ef bc 90 : '0' ~ ef bc 99 : '9' */
3418                                                 *r = '0' + (*(s+2) - 0x90);
3419                                                 r++;
3420                                                 s += 3;
3421                                         } else if (0x8b == *(s+2)) {   /* ef bc 8b : '+' */
3422                                                 *r = '+';
3423                                                 r++;
3424                                                 s += 3;
3425                                         } else if (0x8a == *(s+2)) {   /* ef bc 8a : '*' */
3426                                                 *r = '*';
3427                                                 r++;
3428                                                 s += 3;
3429                                         } else if (0x83 == *(s+2)) {   /* ef bc 83 : '#' */
3430                                                 *r = '#';
3431                                                 r++;
3432                                                 s += 3;
3433                                         } else if (0xb0 == *(s+2) || 0x8c == *(s+2)) {   /* ef bc b0 : 'P', ef bc 8c : ',' */
3434                                                 *r = ',';
3435                                                 r++;
3436                                                 s += 3;
3437                                         } else if (0xb7 == *(s+2) || 0x9b == *(s+2)) {   /* ef bc b7 : 'W', ef bc 9b : ';' */
3438                                                 *r = ';';
3439                                                 r++;
3440                                                 s += 3;
3441                                         } else {
3442                                                 s += char_len;
3443                                         }
3444                                 } else if (*(s+1) == 0xbd) {
3445                                         if (0x90 == *(s+2)) {
3446                                                 *r = ',';
3447                                                 r++;
3448                                                 s += 3;
3449                                         } else if (0x97 == *(s+2)) {
3450                                                 *r = ';';
3451                                                 r++;
3452                                                 s += 3;
3453                                         }
3454                                 } else {
3455                                         s += char_len;
3456                                 }
3457                         } else {
3458                                 s += char_len;
3459                         }
3460                 } else if (1 == char_len) {
3461                         switch (*s) {
3462                         case '/':
3463                         case '.':
3464                         case '0' ... '9':
3465                         case '#':
3466                         case '*':
3467                         case '(':
3468                         case ')':
3469                         case ',':
3470                         case ';':
3471                         case '+':
3472                                 *r = *s;
3473                                 r++;
3474                                 s++;
3475                                 break;
3476                         case 'p':
3477                         case 'P':
3478                                 *r = ',';
3479                                 r++;
3480                                 s++;
3481                                 break;
3482                         case 'w':
3483                         case 'W':
3484                                 *r = ';';
3485                                 r++;
3486                                 s++;
3487                                 break;
3488                         case 'a' ... 'o':
3489                         case 'q' ... 'v':
3490                         case 'x' ... 'z':
3491                                 *r = *s - 0x20;
3492                                 r++;
3493                                 s++;
3494                                 break;
3495                         case 'A' ... 'O':
3496                         case 'Q' ... 'V':
3497                         case 'X' ... 'Z':
3498                                 *r = *s;
3499                                 r++;
3500                                 s++;
3501                                 break;
3502                         default:
3503                                 s++;
3504                                 break;
3505                         }
3506                 } else {
3507                         s += char_len;
3508                 }
3509         }
3510         *r = '\0';
3511         return str;
3512 }
3513
3514 static inline int __ctsvc_vcard_get_number(ctsvc_list_s *numbers, char *prefix, char *val)
3515 {
3516         bool is_default;
3517         int ret;
3518         char *temp;
3519         contacts_record_h number;
3520
3521         temp = __ctsvc_get_content_value(val);
3522         RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "vcard");
3523
3524         ret = contacts_record_create(_contacts_number._uri, &number);
3525         RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3526
3527         temp = __ctsvc_vcard_remove_escape_char(temp);
3528         contacts_record_set_str(number, _contacts_number.number, __ctsvc_vcard_get_clean_number_for_import(temp));
3529
3530         is_default = __ctsvc_vcard_get_number_type(number, prefix);
3531         contacts_record_set_bool(number, _contacts_number.is_default, is_default);
3532         contacts_list_add((contacts_list_h)numbers, number);
3533
3534         return CONTACTS_ERROR_NONE;
3535 }
3536
3537 static inline bool __ctsvc_vcard_get_email_type(contacts_record_h email, char *val)
3538 {
3539         char *temp, *result, *last = NULL;
3540         char *lower, *lower_temp;
3541         int type = CONTACTS_EMAIL_TYPE_OTHER;
3542         bool pref = false;
3543
3544         temp = strtok_r(val, ";", &last);
3545         while (temp) {
3546                 lower = strdup(temp);
3547                 if (NULL == lower) {
3548                         ERR("strdup() Fail");
3549                         break;
3550                 }
3551                 lower_temp = lower;
3552                 while (*lower_temp) {
3553                         *lower_temp = tolower(*lower_temp);
3554                         lower_temp++;
3555                 }
3556                 if (strstr(lower, "pref"))
3557                         pref = true;
3558
3559                 if (strstr(lower, "home")) {
3560                         type = CONTACTS_EMAIL_TYPE_HOME;
3561                 } else if (strstr(lower, "work")) {
3562                         type = CONTACTS_EMAIL_TYPE_WORK;
3563                 } else if (strstr(lower, "cell")) {
3564                         type = CONTACTS_EMAIL_TYPE_MOBILE;
3565                 } else if ((result = strstr(lower, "x-"))) {
3566                         type = CONTACTS_EMAIL_TYPE_CUSTOM;
3567                         contacts_record_set_str(email, _contacts_email.label, temp+(result-lower)+2);
3568                 }
3569
3570                 free(lower);
3571                 temp = strtok_r(NULL, ";", &last);
3572         }
3573         contacts_record_set_int(email, _contacts_email.type, type);
3574
3575         return pref;
3576 }
3577
3578 static inline int __ctsvc_vcard_get_email(ctsvc_list_s *emails, char *prefix, char *val)
3579 {
3580         bool is_default;
3581         int ret;
3582         char *temp;
3583         contacts_record_h email;
3584
3585         temp = __ctsvc_get_content_value(val);
3586         RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "vcard");
3587
3588         ret = contacts_record_create(_contacts_email._uri, &email);
3589         RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3590
3591         contacts_record_set_str(email, _contacts_email.email, __ctsvc_vcard_remove_escape_char(temp));
3592         is_default = __ctsvc_vcard_get_email_type(email, prefix);
3593         contacts_record_set_bool(email, _contacts_email.is_default, is_default);
3594         contacts_list_add((contacts_list_h)emails, email);
3595
3596         return CONTACTS_ERROR_NONE;
3597 }
3598
3599 static inline bool __ctsvc_vcard_get_postal_type(contacts_record_h address, char *val)
3600 {
3601         char *temp, *result, *last = NULL;
3602         char *lower, *lower_temp;
3603         int type = CONTACTS_ADDRESS_TYPE_OTHER;
3604         bool pref = false;
3605
3606         temp = strtok_r(val, ";", &last);
3607         while (temp) {
3608                 lower = strdup(temp);
3609                 if (NULL == lower) {
3610                         ERR("strdup() Fail");
3611                         break;
3612                 }
3613                 lower_temp = lower;
3614                 while (*lower_temp) {
3615                         *lower_temp = tolower(*lower_temp);
3616                         lower_temp++;
3617                 }
3618                 result = strstr(lower, "dom");
3619                 if (result) type |= CONTACTS_ADDRESS_TYPE_DOM;
3620                 result = strstr(lower, "intl");
3621                 if (result) type |= CONTACTS_ADDRESS_TYPE_INTL;
3622                 result = strstr(lower, "address");
3623                 if (result) type |= CONTACTS_ADDRESS_TYPE_POSTAL;
3624                 result = strstr(lower, "parcel");
3625                 if (result) type |= CONTACTS_ADDRESS_TYPE_PARCEL;
3626                 result = strstr(lower, "home");
3627                 if (result) type |= CONTACTS_ADDRESS_TYPE_HOME;
3628                 result = strstr(lower, "work");
3629                 if (result) type |= CONTACTS_ADDRESS_TYPE_WORK;
3630                 result = strstr(lower, "x-");
3631                 if (result) {
3632                         type = CONTACTS_ADDRESS_TYPE_CUSTOM;
3633                         contacts_record_set_str(address, _contacts_address.label, temp+(result-lower)+2);
3634                 }
3635                 result = strstr(val, "pref");
3636                 if (result) pref = true;
3637
3638                 free(lower);
3639                 temp = strtok_r(NULL, ";", &last);
3640         }
3641
3642         contacts_record_set_int(address, _contacts_address.type, type);
3643
3644         return pref;
3645 }
3646
3647 static inline int __ctsvc_vcard_get_address(ctsvc_list_s *address_list, char *prefix, char *val)
3648 {
3649         char *text;
3650         char *text_temp;
3651         contacts_record_h address;
3652
3653         contacts_record_create(_contacts_address._uri, &address);
3654         if (address) {
3655
3656                 text = strchr(val, ':');
3657                 if (text) {
3658                         text++;
3659                         *(text-1) = '\0';
3660                 } else {
3661                         text = val;
3662                 }
3663
3664                 do {
3665                         bool separator = false;
3666
3667                         CTS_GET_MULTIPLE_COMPONENT(((ctsvc_address_s*)address)->pobox, text, text_temp, separator);
3668                         CTS_GET_MULTIPLE_COMPONENT(((ctsvc_address_s*)address)->extended, text, text_temp, separator);
3669                         CTS_GET_MULTIPLE_COMPONENT(((ctsvc_address_s*)address)->street, text, text_temp, separator);
3670                         CTS_GET_MULTIPLE_COMPONENT(((ctsvc_address_s*)address)->locality, text, text_temp, separator);
3671                         CTS_GET_MULTIPLE_COMPONENT(((ctsvc_address_s*)address)->region, text, text_temp, separator);
3672                         CTS_GET_MULTIPLE_COMPONENT(((ctsvc_address_s*)address)->postalcode, text, text_temp, separator);
3673                         CTS_GET_MULTIPLE_COMPONENT(((ctsvc_address_s*)address)->country, text, text_temp, separator);
3674
3675                         ERR("invalid ADR type");
3676                 } while (0);
3677
3678                 if (((ctsvc_address_s*)address)->pobox || ((ctsvc_address_s*)address)->extended
3679                                 || ((ctsvc_address_s*)address)->street || ((ctsvc_address_s*)address)->locality
3680                                 || ((ctsvc_address_s*)address)->region || ((ctsvc_address_s*)address)->postalcode
3681                                 || ((ctsvc_address_s*)address)->country) {
3682                         contacts_record_set_bool(address, _contacts_address.is_default, __ctsvc_vcard_get_postal_type(address, prefix));
3683                 } else {
3684                         ERR("Invalid vcard");
3685                         contacts_record_destroy(address, true);
3686                         return CONTACTS_ERROR_INVALID_PARAMETER;
3687                 }
3688                 contacts_list_add((contacts_list_h)address_list, address);
3689         }
3690
3691         return CONTACTS_ERROR_NONE;
3692 }
3693
3694 static inline void __ctsvc_vcard_get_messenger_type(contacts_record_h messenger, char *val)
3695 {
3696         char *temp, *result, *last = NULL;
3697         char *lower, *lower_temp;
3698         int type = CONTACTS_MESSENGER_TYPE_OTHER;
3699
3700         temp = strtok_r(val, ";", &last);
3701         while (temp) {
3702                 lower = strdup(temp);
3703                 if (NULL == lower) {
3704                         ERR("strdup() Fail");
3705                         break;
3706                 }
3707                 lower_temp = lower;
3708                 while (*lower_temp) {
3709                         *lower_temp = tolower(*lower_temp);
3710                         lower_temp++;
3711                 }
3712                 result = strstr(lower, "facebook");
3713                 if (result) type = CONTACTS_MESSENGER_TYPE_FACEBOOK;
3714                 result = strstr(lower, "irc");
3715                 if (result) type = CONTACTS_MESSENGER_TYPE_IRC;
3716                 result = strstr(lower, "x-");
3717                 if (result) {
3718                         type = CONTACTS_MESSENGER_TYPE_CUSTOM;
3719                         contacts_record_set_str(messenger, _contacts_messenger.label, temp+(result-lower)+2);
3720                 }
3721                 free(lower);
3722                 temp = strtok_r(NULL, ";", &last);
3723         }
3724         contacts_record_set_int(messenger, _contacts_messenger.type, type);
3725 }
3726
3727 static inline int __ctsvc_vcard_get_messenger(ctsvc_list_s *messenger_list, int type, char *prefix, char *val)
3728 {
3729         int ret;
3730         contacts_record_h messenger;
3731         char *temp;
3732
3733         temp = __ctsvc_get_content_value(val);
3734         RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "vcard");
3735
3736         ret = contacts_record_create(_contacts_messenger._uri, &messenger);
3737         RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3738
3739         contacts_record_set_str(messenger, _contacts_messenger.im_id, __ctsvc_vcard_remove_escape_char(temp));
3740
3741         switch (type) {
3742         case CTSVC_VCARD_VALUE_X_MSN:
3743                 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_WLM);
3744                 break;
3745         case CTSVC_VCARD_VALUE_X_YAHOO:
3746                 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_YAHOO);
3747                 break;
3748         case CTSVC_VCARD_VALUE_X_ICQ:
3749                 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_ICQ);
3750                 break;
3751         case CTSVC_VCARD_VALUE_X_AIM:
3752                 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_AIM);
3753                 break;
3754         case CTSVC_VCARD_VALUE_X_JABBER:
3755                 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_JABBER);
3756                 break;
3757         case CTSVC_VCARD_VALUE_X_SKYPE_USERNAME:
3758         case CTSVC_VCARD_VALUE_X_SKYPE:
3759                 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_SKYPE);
3760                 break;
3761         case CTSVC_VCARD_VALUE_X_QQ:
3762                 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_QQ);
3763                 break;
3764         case CTSVC_VCARD_VALUE_X_GOOGLE_TALK:
3765                 contacts_record_set_int(messenger, _contacts_messenger.type, CONTACTS_MESSENGER_TYPE_GOOGLE);
3766                 break;
3767         case CTSVC_VCARD_VALUE_X_TIZEN_MESSENGER:
3768                 __ctsvc_vcard_get_messenger_type(messenger, prefix);
3769                 break;
3770         }
3771         contacts_list_add((contacts_list_h)messenger_list, messenger);
3772
3773         return CONTACTS_ERROR_NONE;
3774 }
3775
3776 static inline void __ctsvc_vcard_get_relationship_type(contacts_record_h relationship, char *val)
3777 {
3778         char *temp, *result, *last = NULL;
3779         char *lower, *lower_temp;
3780         int type = CONTACTS_RELATIONSHIP_TYPE_OTHER;
3781
3782         temp = strtok_r(val, ";", &last);
3783         while (temp) {
3784                 lower = strdup(temp);
3785                 if (NULL == lower) {
3786                         ERR("strdup() Fail");
3787                         break;
3788                 }
3789                 lower_temp = lower;
3790                 while (*lower_temp) {
3791                         *lower_temp = tolower(*lower_temp);
3792                         lower_temp++;
3793                 }
3794
3795                 if (strstr(lower, "assistant")) {
3796                         type = CONTACTS_RELATIONSHIP_TYPE_ASSISTANT;
3797                 } else if (strstr(lower, "brother")) {
3798                         type = CONTACTS_RELATIONSHIP_TYPE_BROTHER;
3799                 } else if (strstr(lower, "child")) {
3800                         type = CONTACTS_RELATIONSHIP_TYPE_CHILD;
3801                 } else if (strstr(lower, "domestic_partner")) {
3802                         type = CONTACTS_RELATIONSHIP_TYPE_DOMESTIC_PARTNER;
3803                 } else if (strstr(lower, "father")) {
3804                         type = CONTACTS_RELATIONSHIP_TYPE_FATHER;
3805                 } else if (strstr(lower, "friend")) {
3806                         type = CONTACTS_RELATIONSHIP_TYPE_FRIEND;
3807                 } else if (strstr(lower, "manager")) {
3808                         type = CONTACTS_RELATIONSHIP_TYPE_MANAGER;
3809                 } else if (strstr(lower, "mother")) {
3810                         type = CONTACTS_RELATIONSHIP_TYPE_MOTHER;
3811                 } else if (strstr(lower, "parent")) {
3812                         type = CONTACTS_RELATIONSHIP_TYPE_PARENT;
3813                 } else if (strstr(lower, "partner")) {
3814                         type = CONTACTS_RELATIONSHIP_TYPE_PARTNER;
3815                 } else if (strstr(lower, "referred_by")) {
3816                         type = CONTACTS_RELATIONSHIP_TYPE_REFERRED_BY;
3817                 } else if (strstr(lower, "relative")) {
3818                         type = CONTACTS_RELATIONSHIP_TYPE_RELATIVE;
3819                 } else if (strstr(lower, "sister")) {
3820                         type = CONTACTS_RELATIONSHIP_TYPE_SISTER;
3821                 } else if (strstr(lower, "spouse")) {
3822                         type = CONTACTS_RELATIONSHIP_TYPE_SPOUSE;
3823                 } else if ((result = strstr(lower, "x-"))) {
3824                         type = CONTACTS_RELATIONSHIP_TYPE_CUSTOM;
3825                         contacts_record_set_str(relationship, _contacts_relationship.label, temp+(result-lower)+2);
3826                 }
3827                 free(lower);
3828                 temp = strtok_r(NULL, ";", &last);
3829         }
3830         contacts_record_set_int(relationship, _contacts_relationship.type, type);
3831 }
3832
3833
3834 static inline int __ctsvc_vcard_get_relationship(ctsvc_list_s *relationship_list, int type, char *prefix, char *val)
3835 {
3836         int ret;
3837         char *temp;
3838         contacts_record_h relationship;
3839
3840         temp = __ctsvc_get_content_value(val);
3841         RETVM_IF(NULL == temp, CONTACTS_ERROR_INVALID_PARAMETER, "vcard");
3842
3843         ret = contacts_record_create(_contacts_relationship._uri, &relationship);
3844         RETVM_IF(ret < CONTACTS_ERROR_NONE, ret, "contacts_record_create() Fail(%d)", ret);
3845
3846         contacts_record_set_str(relationship, _contacts_relationship.name, __ctsvc_vcard_remove_escape_char(temp));
3847         __ctsvc_vcard_get_relationship_type(relationship, prefix);
3848         contacts_list_add((contacts_list_h)relationship_list, relationship);
3849
3850         return CONTACTS_ERROR_NONE;
3851
3852 }
3853
3854 static char* __ctsvc_vcard_decode_base64_val(char *val)
3855 {
3856         gsize size = 0;
3857         guchar *decoded_str;
3858         char *src;
3859         char *dest = NULL;
3860
3861         src = strchr(val, ':');
3862         if (NULL == src)
3863                 src = val;
3864         else
3865                 src++;
3866
3867         decoded_str = g_base64_decode(src, &size);
3868
3869         dest = calloc((src-val)+size+1, sizeof(char));
3870         if (NULL == dest) {
3871                 g_free(decoded_str);
3872                 ERR("calloc() Fail");
3873                 return NULL;
3874         }
3875
3876         snprintf(dest, (src-val)+1, "%s", val);
3877         snprintf(dest+(src-val), size+1, "%s", decoded_str);
3878         g_free(decoded_str);
3879
3880         return dest;
3881 }
3882
3883 static inline int __ctsvc_vcard_get_contact(int ver, char *vcard, contacts_record_h *record)
3884 {
3885         int type;
3886         char *cursor, *new_start, *val, *prefix;
3887         ctsvc_contact_s *contact = (ctsvc_contact_s*)*record;
3888
3889         cursor = vcard;
3890         while (cursor) {
3891                 val = NULL;
3892                 prefix = NULL;
3893
3894                 bool base64_encoded = false;
3895                 type = __ctsvc_vcard_check_content_type(&cursor);
3896                 if (CTSVC_VCARD_VALUE_NONE == type) {
3897                         new_start = __ctsvc_vcard_pass_unsupported(cursor);
3898                         if (new_start) {
3899                                 cursor = new_start;
3900                                 continue;
3901                         } else {
3902                                 break;
3903                         }
3904                 }
3905
3906                 if (CTSVC_VCARD_VALUE_PHOTO != type && CTSVC_VCARD_VALUE_LOGO != type)
3907                         base64_encoded = __ctsvc_vcard_check_base64_encoded(cursor);
3908
3909                 new_start = __ctsvc_vcard_get_val(ver, cursor, &prefix, &val);
3910                 if (NULL == new_start) {
3911                         if (prefix)
3912                                 free(prefix);
3913                         if (val)
3914                                 free(val);
3915                         continue;
3916                 }
3917
3918                 if (NULL == val) {
3919                         cursor = new_start;
3920                         if (prefix)
3921                                 free(prefix);
3922                         continue;
3923                 }
3924
3925                 if (base64_encoded) {
3926                         char *temp = __ctsvc_vcard_decode_base64_val(val);
3927                         if (NULL == temp) {
3928                                 /* LCOV_EXCL_START */
3929                                 ERR("__ctsvc_vcard_decode_base64_val() Fail");
3930                                 free(prefix);
3931                                 free(val);
3932                                 return CONTACTS_ERROR_OUT_OF_MEMORY;
3933                                 /* LCOV_EXCL_STOP */
3934                         }
3935                         free(val);
3936                         val = temp;
3937                 }
3938
3939                 switch (type) {
3940                 case CTSVC_VCARD_VALUE_FN:
3941                         __ctsvc_vcard_get_display_name(contact->name, val);
3942                         break;
3943                 case CTSVC_VCARD_VALUE_N:
3944                         __ctsvc_vcard_get_name(contact->name, val);
3945                         break;
3946                 case CTSVC_VCARD_VALUE_PHONETIC_FIRST_NAME:
3947                 case CTSVC_VCARD_VALUE_PHONETIC_MIDDLE_NAME:
3948                 case CTSVC_VCARD_VALUE_PHONETIC_LAST_NAME:
3949                         __ctsvc_vcard_get_phonetic_name(contact->name, type, val);
3950                         break;
3951                 case CTSVC_VCARD_VALUE_NICKNAME:
3952                         __ctsvc_vcard_get_nickname(contact->nicknames, val);
3953                         break;
3954                 case CTSVC_VCARD_VALUE_PHOTO:
3955                         __ctsvc_vcard_get_photo(*record, contact->images, prefix, val);
3956                         break;
3957                 case CTSVC_VCARD_VALUE_BDAY:
3958                 case CTSVC_VCARD_VALUE_X_ANNIVERSARY:
3959                 case CTSVC_VCARD_VALUE_X_TIZEN_EVENT:
3960                         __ctsvc_vcard_get_event(contact->events, type, prefix, val);
3961                         break;
3962                 case CTSVC_VCARD_VALUE_ADR:
3963                         __ctsvc_vcard_get_address(contact->postal_addrs, prefix, val);
3964                         break;
3965                 case CTSVC_VCARD_VALUE_TEL:
3966                         __ctsvc_vcard_get_number(contact->numbers, prefix, val);
3967                         break;
3968                 case CTSVC_VCARD_VALUE_EMAIL:
3969                         __ctsvc_vcard_get_email(contact->emails, prefix, val);
3970                         break;
3971                 case CTSVC_VCARD_VALUE_TITLE:
3972                         __ctsvc_vcard_get_company_value(contact->company, _contacts_company.job_title, val);
3973                         break;
3974                 case CTSVC_VCARD_VALUE_ROLE:
3975                         __ctsvc_vcard_get_company_value(contact->company, _contacts_company.role, val);
3976                         break;
3977                 case CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_LOCATION:
3978                         __ctsvc_vcard_get_company_value(contact->company, _contacts_company.location, val);
3979                         break;
3980                 case CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_DESCRIPTION:
3981                         __ctsvc_vcard_get_company_value(contact->company, _contacts_company.description, val);
3982                         break;
3983                 case CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_PHONETIC_NAME:
3984                         __ctsvc_vcard_get_company_value(contact->company, _contacts_company.phonetic_name, val);
3985                         break;
3986                 case CTSVC_VCARD_VALUE_X_TIZEN_COMPANY_ASSISTANT_NAME:
3987                         __ctsvc_vcard_get_company_value(contact->company, _contacts_company.assistant_name, val);
3988                         break;
3989                 case CTSVC_VCARD_VALUE_LOGO:
3990                         __ctsvc_vcard_get_company_logo(contact->company, prefix, val);
3991                         break;
3992                 case CTSVC_VCARD_VALUE_ORG:
3993                         __ctsvc_vcard_get_company(contact->company, prefix, val);
3994                         break;
3995                 case CTSVC_VCARD_VALUE_NOTE:
3996                         __ctsvc_vcard_get_note(contact->note, val);
3997                         break;
3998                 case CTSVC_VCARD_VALUE_REV:
3999                         if (*val)
4000                                 contact->changed_time = __ctsvc_vcard_get_time(val);
4001                         break;
4002                 case CTSVC_VCARD_VALUE_UID:
4003                         contacts_record_set_str((contacts_record_h)contact, _contacts_contact.uid, __ctsvc_vcard_remove_escape_char(val));
4004                         break;
4005                 case CTSVC_VCARD_VALUE_URL:
4006                         __ctsvc_vcard_get_url(contact->urls, prefix, val);
4007                         break;
4008                 case CTSVC_VCARD_VALUE_X_MSN:
4009                 case CTSVC_VCARD_VALUE_X_YAHOO:
4010                 case CTSVC_VCARD_VALUE_X_ICQ:
4011                 case CTSVC_VCARD_VALUE_X_AIM:
4012                 case CTSVC_VCARD_VALUE_X_JABBER:
4013                 case CTSVC_VCARD_VALUE_X_SKYPE_USERNAME:
4014                 case CTSVC_VCARD_VALUE_X_SKYPE:
4015                 case CTSVC_VCARD_VALUE_X_QQ:
4016                 case CTSVC_VCARD_VALUE_X_GOOGLE_TALK:
4017                 case CTSVC_VCARD_VALUE_X_TIZEN_MESSENGER:
4018                         __ctsvc_vcard_get_messenger(contact->messengers, type, prefix, val);
4019                         break;
4020
4021                 case CTSVC_VCARD_VALUE_X_TIZEN_RELATIONSHIP:
4022                         __ctsvc_vcard_get_relationship(contact->relationships, type, prefix, val);
4023                         break;
4024                 case CTSVC_VCARD_VALUE_END:
4025                         free(val);
4026                         free(prefix);
4027                         return CONTACTS_ERROR_NONE;
4028                 default:
4029                         ERR("__ctsvc_vcard_check_content_type() Fail(%d)", type);
4030                         free(val);
4031                         free(prefix);
4032                         return CONTACTS_ERROR_INVALID_PARAMETER;
4033                 }
4034                 free(val);
4035                 free(prefix);
4036                 cursor = new_start;
4037         }
4038
4039         ERR("Invalid vcard");
4040         return CONTACTS_ERROR_INVALID_PARAMETER;
4041 }
4042
4043 static inline int __ctsvc_vcard_check_version(const char *src)
4044 {
4045         bool start = false;
4046         const char *ver3 = "3.0";
4047
4048         while (*src) {
4049                 switch (*src) {
4050                 case '\n':
4051                 case '\r':
4052                         return CTSVC_VCARD_VER_2_1;
4053                 case ' ':
4054                         src++;
4055                         break;
4056                 default:
4057                         start = true;
4058                         break;
4059                 }
4060                 if (start) break;
4061         }
4062
4063         if (STRING_EQUAL == strcmp(src, ver3))
4064                 return CTSVC_VCARD_VER_3_0;
4065         else
4066                 return CTSVC_VCARD_VER_2_1;
4067 }
4068
4069 static inline void __ctsvc_vcard_make_contact_display_name(ctsvc_contact_s *contact)
4070 {
4071         ctsvc_name_s *name = NULL;
4072
4073         free(contact->display_name);
4074         contact->display_name = NULL;
4075
4076         free(contact->reverse_display_name);
4077         contact->reverse_display_name = NULL;
4078
4079         if (0 < contact->name->count && contact->name->records
4080                         && contact->name->records->data) {
4081                 name = (ctsvc_name_s*)contact->name->records->data;
4082         }
4083
4084         if (name && (name->first || name->last || name->prefix || name->addition
4085                                 || name->suffix)) {
4086                 int reverse_lang_type = -1;
4087                 char *display = NULL;
4088                 char *reverse_display = NULL;
4089                 int len, display_len;
4090                 int temp_display_len;
4091                 char *temp_display = NULL;
4092                 contacts_name_display_order_e name_display_order = CONTACTS_NAME_DISPLAY_ORDER_FIRSTLAST;
4093
4094                 /*
4095                  * Make reverse display name (Last name first)
4096                  * Default         : Prefix Last, First Middle(addition), Suffix
4097                  * Korean, Chinese : Prefix LastFirstMiddleSuffix
4098                  * Japanese        : Prefix Last Middle First Suffix
4099                  * reverse sort name does not include prefix
4100                  *    But, if there is only prefix, reverse sort_name is prefix
4101                  */
4102                 temp_display_len = SAFE_STRLEN(name->first)
4103                         + SAFE_STRLEN(name->addition)
4104                         + SAFE_STRLEN(name->last)
4105                         + SAFE_STRLEN(name->suffix);
4106                 if (0 < temp_display_len) {
4107                         temp_display_len += 7;
4108                         temp_display = calloc(1, temp_display_len);
4109                         if (NULL == temp_display) {
4110                                 ERR("calloc() Fail");
4111                                 return;
4112                         }
4113
4114                         len = 0;
4115
4116                         if (name->last) {
4117                                 len += snprintf(temp_display + len, temp_display_len - len, "%s", name->last);
4118
4119                                 if (reverse_lang_type < 0)
4120                                         reverse_lang_type = ctsvc_check_language_type(temp_display);
4121
4122                                 if (reverse_lang_type != CTSVC_LANG_KOREAN &&
4123                                                 reverse_lang_type != CTSVC_LANG_CHINESE &&
4124                                                 reverse_lang_type != CTSVC_LANG_JAPANESE) {
4125                                         if (name->first || name->addition)
4126                                                 len += snprintf(temp_display + len, temp_display_len - len, ",");
4127                                 }
4128                         }
4129
4130                         if (reverse_lang_type < 0) {
4131                                 if (*temp_display)
4132                                         reverse_lang_type = ctsvc_check_language_type(temp_display);
4133                                 else if (name->first)
4134                                         reverse_lang_type = ctsvc_check_language_type(name->first);
4135                                 else if (name->addition)
4136                                         reverse_lang_type = ctsvc_check_language_type(name->addition);
4137                         }
4138
4139                         if (reverse_lang_type == CTSVC_LANG_JAPANESE) {
4140                                 /* make temp_display name Prefix - Last - Middle - First - Suffix */
4141                                 if (name->addition) {
4142                                         if (*temp_display)
4143                                                 len += snprintf(temp_display + len, temp_display_len - len, " ");
4144                                         len += snprintf(temp_display + len, temp_display_len - len, "%s", name->addition);
4145                                 }
4146
4147                                 if (name->first) {
4148                                         if (*temp_display)
4149                                                 len += snprintf(temp_display + len, temp_display_len - len, " ");
4150                                         len += snprintf(temp_display + len, temp_display_len - len, "%s", name->first);
4151                                 }
4152                         } else {
4153                                 /* make temp_display name Prefix - Last - First -Middle - Suffix */
4154                                 if (name->first) {
4155                                         if (*temp_display) {
4156                                                 if (reverse_lang_type < 0)
4157                                                         reverse_lang_type = ctsvc_check_language_type(temp_display);
4158
4159                                                 if (reverse_lang_type != CTSVC_LANG_KOREAN &&
4160                                                                 reverse_lang_type != CTSVC_LANG_CHINESE)
4161                                                         len += snprintf(temp_display + len, temp_display_len - len, " ");
4162                                         }
4163                                         len += snprintf(temp_display + len, temp_display_len - len, "%s", name->first);
4164                                 }
4165
4166                                 if (name->addition) {
4167                                         if (*temp_display) {
4168                                                 if (reverse_lang_type < 0)
4169                                                         reverse_lang_type = ctsvc_check_language_type(temp_display);
4170
4171                                                 if (reverse_lang_type != CTSVC_LANG_KOREAN &&
4172                                                                 reverse_lang_type != CTSVC_LANG_CHINESE)
4173                                                         len += snprintf(temp_display + len, temp_display_len - len, " ");
4174                                         }
4175                                         len += snprintf(temp_display + len, temp_display_len - len, "%s", name->addition);
4176                                 }
4177                         }
4178
4179                         if (name->suffix) {
4180                                 if (*temp_display) {
4181                                         if (reverse_lang_type < 0)
4182                                                 reverse_lang_type = ctsvc_check_language_type(temp_display);
4183
4184                                         if (reverse_lang_type == CTSVC_LANG_JAPANESE) {
4185                                                 len += snprintf(temp_display + len, temp_display_len - len, " ");
4186                                         } else if (reverse_lang_type != CTSVC_LANG_KOREAN &&
4187                                                         reverse_lang_type != CTSVC_LANG_CHINESE)  {
4188                                                 len += snprintf(temp_display + len, temp_display_len - len, ", ");
4189                                         }
4190                                 }
4191                                 len += snprintf(temp_display + len, temp_display_len - len, "%s", name->suffix);
4192                         }
4193                 }
4194
4195                 if (name->prefix && temp_display) {
4196                         display_len = SAFE_STRLEN(name->prefix) + temp_display_len + 2;
4197                         reverse_display = calloc(1, display_len);
4198                         if (NULL == reverse_display) {
4199                                 ERR("calloc() Fail");
4200                                 free(temp_display);
4201                                 return;
4202                         }
4203                         snprintf(reverse_display, display_len, "%s %s", name->prefix, temp_display);
4204                         free(temp_display);
4205                 } else if (temp_display) {
4206                         reverse_display = temp_display;
4207                 } else if (name->prefix) {
4208                         reverse_display = strdup(name->prefix);
4209                 }
4210
4211                 /*
4212                  * Make display name (First name first)
4213                  * Default         : Prefix First Middle Last, Suffix
4214                  * Korean, Chinese : Prefix LastFirstMiddleSuffix (Same as reverse display name)
4215                  * Japanese        : Prefix First Middle Last Suffix
4216                  * sort name does not include prefix
4217                  *    But, if there is only prefix, sort_name is prefix
4218                  */
4219
4220                 if (reverse_lang_type == CTSVC_LANG_KOREAN ||
4221                                 reverse_lang_type == CTSVC_LANG_CHINESE) {
4222                         display = strdup(reverse_display);
4223                 } else {
4224                         int lang_type = -1;
4225                         temp_display = NULL;
4226                         temp_display_len = SAFE_STRLEN(name->first)
4227                                 + SAFE_STRLEN(name->addition)
4228                                 + SAFE_STRLEN(name->last)
4229                                 + SAFE_STRLEN(name->suffix);
4230                         if (0 < temp_display_len) {
4231                                 temp_display_len += 6;
4232                                 /* make reverse_temp_display_name */
4233                                 temp_display = calloc(1, temp_display_len);
4234                                 if (NULL == temp_display) {
4235                                         ERR("calloc() Fail");
4236                                         free(reverse_display);
4237                                         return;
4238                                 }
4239
4240                                 len = 0;
4241
4242                                 if (name->first) {
4243                                         if (*temp_display)
4244                                                 len += snprintf(temp_display + len, temp_display_len - len, " ");
4245                                         len += snprintf(temp_display + len, temp_display_len - len, "%s", name->first);
4246                                 }
4247
4248                                 if (name->addition) {
4249                                         if (*temp_display)
4250                                                 len += snprintf(temp_display + len, temp_display_len - len, " ");
4251                                         len += snprintf(temp_display + len, temp_display_len - len, "%s", name->addition);
4252                                 }
4253
4254                                 if (name->last) {
4255                                         if (*temp_display)
4256                                                 len += snprintf(temp_display + len, temp_display_len - len, " ");
4257                                         len += snprintf(temp_display + len, temp_display_len - len, "%s", name->last);
4258                                 }
4259
4260                                 if (name->suffix) {
4261                                         if (*temp_display) {
4262                                                 lang_type = ctsvc_check_language_type(temp_display);
4263                                                 if (lang_type == CTSVC_LANG_JAPANESE)
4264                                                         len += snprintf(temp_display + len, temp_display_len - len, " ");
4265                                                 else
4266                                                         len += snprintf(temp_display + len, temp_display_len - len, ", ");
4267                                         }
4268                                         len += snprintf(temp_display + len, temp_display_len - len, "%s", name->suffix);
4269                                 }
4270                         }
4271
4272                         if (name->prefix && temp_display) {
4273                                 display_len = SAFE_STRLEN(name->prefix) + temp_display_len + 2;
4274                                 display = calloc(1, display_len);
4275                                 if (NULL == display) {
4276                                         ERR("calloc() Fail");
4277                                         free(temp_display);
4278                                         free(reverse_display);
4279                                         return;
4280                                 }
4281                                 snprintf(display, display_len, "%s %s", name->prefix, temp_display);
4282                                 free(temp_display);
4283                         } else if (temp_display) {
4284                                 display = temp_display;
4285                         } else if (name->prefix) {
4286                                 display = strdup(name->prefix);
4287                         }
4288                 }
4289
4290 #ifdef _CONTACTS_IPC_CLIENT
4291                 contacts_setting_get_name_display_order(&name_display_order);
4292 #endif
4293                 if (CONTACTS_NAME_DISPLAY_ORDER_FIRSTLAST == name_display_order) {
4294                         contact->display_name = display;
4295                         free(reverse_display);
4296 #ifdef _CONTACTS_IPC_CLIENT
4297                 } else {
4298                         contact->display_name = reverse_display;
4299                         free(display);
4300 #endif
4301                 }
4302                 contact->display_source_type = CONTACTS_DISPLAY_NAME_SOURCE_TYPE_NAME;
4303         } else {
4304                 GList *cur;
4305                 bool set_display_name = false;
4306                 if (contact->company && contact->company->records) {
4307                         for (cur = contact->company->records; cur; cur = cur->next) {
4308                                 ctsvc_company_s *company = cur->data;
4309                                 if (company && company->name) {
4310                                         set_display_name = true;
4311                                         contact->display_name = SAFE_STRDUP(company->name);
4312                                         contact->display_source_type = CONTACTS_DISPLAY_NAME_SOURCE_TYPE_COMPANY;
4313                                         break;
4314                                 }
4315                         }
4316                 }
4317
4318                 if (false == set_display_name &&
4319                                 contact->nicknames && contact->nicknames->records) {
4320                         for (cur = contact->nicknames->records; cur; cur = cur->next) {
4321                                 ctsvc_nickname_s *nickname = cur->data;
4322                                 if (nickname && nickname->nickname) {
4323                                         set_display_name = true;
4324                                         contact->display_name = SAFE_STRDUP(nickname->nickname);
4325                                         contact->display_source_type = CONTACTS_DISPLAY_NAME_SOURCE_TYPE_NICKNAME;
4326                                         break;
4327                                 }
4328                         }
4329                 }
4330
4331                 if (false == set_display_name &&
4332                                 contact->numbers && contact->numbers->records) {
4333                         for (cur = contact->numbers->records; cur; cur = cur->next) {
4334                                 ctsvc_number_s *number = cur->data;
4335                                 if (number && number->number) {
4336                                         set_display_name = true;
4337                                         contact->display_name = SAFE_STRDUP(number->number);
4338                                         contact->display_source_type = CONTACTS_DISPLAY_NAME_SOURCE_TYPE_NUMBER;
4339                                         break;
4340                                 }
4341                         }
4342                 }
4343
4344                 if (false == set_display_name &&
4345                                 contact->emails && contact->emails->records) {
4346                         for (cur = contact->emails->records; cur; cur = cur->next) {
4347                                 ctsvc_email_s *email = cur->data;
4348                                 if (email && email->email_addr) {
4349                                         set_display_name = true;
4350                                         contact->display_name = SAFE_STRDUP(email->email_addr);
4351                                         contact->display_source_type = CONTACTS_DISPLAY_NAME_SOURCE_TYPE_EMAIL;
4352                                         break;
4353                                 }
4354                         }
4355                 }
4356         }
4357         return;
4358 }
4359
4360 static void __ctsvc_vcard_update_contact_has_properties(ctsvc_contact_s *contact)
4361 {
4362         if (contact->numbers && 0 < contact->numbers->count)
4363                 contact->has_phonenumber = true;
4364
4365         if (contact->emails && 0 < contact->emails->count)
4366                 contact->has_email = true;
4367 }
4368
4369 static int __ctsvc_vcard_parse(const void *vcard_stream, contacts_record_h *record)
4370 {
4371         int ret, ver;
4372         ctsvc_contact_s *contact;
4373         char *val_begin, *new_start, *val;
4374         char *vcard = (char *)vcard_stream;
4375
4376         RETV_IF(NULL == vcard_stream, CONTACTS_ERROR_INVALID_PARAMETER);
4377
4378         __ctsvc_vcard_initial();
4379
4380         vcard = __ctsvc_vcard_check_word(vcard, "BEGIN:VCARD");
4381         RETVM_IF(NULL == vcard, CONTACTS_ERROR_INVALID_PARAMETER, "The vcard is invalid.");
4382
4383         val_begin = __ctsvc_vcard_check_word(vcard, "VERSION:");
4384         new_start = __ctsvc_vcard_get_val(CTSVC_VCARD_VER_NONE, val_begin, NULL, &val);
4385         if (NULL == new_start || NULL == val) {
4386                 ver = CTSVC_VCARD_VER_2_1;
4387         } else {
4388                 ver = __ctsvc_vcard_check_version(val);
4389                 free(val);
4390                 vcard = new_start;
4391         }
4392
4393         contacts_record_create(_contacts_contact._uri, (contacts_record_h*)&contact);
4394         RETVM_IF(NULL == contact, CONTACTS_ERROR_OUT_OF_MEMORY, "Out of memory : contacts_record_create() Fail");
4395
4396         ret = __ctsvc_vcard_get_contact(ver, vcard, (contacts_record_h*)&contact);
4397         if (CONTACTS_ERROR_NONE != ret) {
4398                 ERR("cts_vcard_get_contact() Fail(%d)", ret);
4399                 contacts_record_destroy((contacts_record_h)contact, true);
4400                 return ret;
4401         }
4402         __ctsvc_vcard_make_contact_display_name(contact);
4403         __ctsvc_vcard_update_contact_has_properties(contact);
4404         *record = (contacts_record_h)contact;
4405         return CONTACTS_ERROR_NONE;
4406 }
4407
4408 #define CTSVC_VCARD_MAX_SIZE 1024*1024
4409
4410 static const char* __contacts_vcard_remove_line_break(const char *c)
4411 {
4412         while (c) {
4413                 if ('\r' == *c && '\n' == *(c+1))
4414                         c += 2;
4415                 else if ('\n' == *c)
4416                         c++;
4417                 else
4418                         break;
4419         }
4420         return c;
4421 }
4422
4423 typedef struct {
4424         const char *pos_start;
4425         const char *pos_end;
4426 } sub_vcard_info_s;
4427
4428 static void __contacts_vcard_free_sub_vcard_info_list(GList *list)
4429 {
4430         if (NULL == list)
4431                 return;
4432
4433         GList *cursor;
4434         for (cursor = list; cursor; cursor = cursor->next) {
4435                 sub_vcard_info_s *vcard_info = cursor->data;
4436                 free(vcard_info);
4437         }
4438         g_list_free(list);
4439 }
4440
4441 static void __contacts_vcard_free_vcard_object_list(GList *list)
4442 {
4443         if (NULL == list)
4444                 return;
4445
4446         GList *cursor;
4447         for (cursor = list; cursor; cursor = cursor->next) {
4448                 char *vcard_object = cursor->data;
4449                 free(vcard_object);
4450         }
4451         g_list_free(list);
4452
4453 }
4454
4455 static const char* __contacts_vcard_parse_get_vcard_object(const char *cursor, GList **plist_vcard_object)
4456 {
4457         char *vcard_object = NULL;
4458         bool new_line = false;
4459         const char *begin = "BEGIN:VCARD";
4460         const char *end = "END:VCARD";
4461         const char *vcard_start_cursor = cursor;
4462         const char *vcard_cursor = NULL;
4463         GList *sub_vcard_list = NULL;
4464
4465         RETV_IF(NULL == plist_vcard_object, cursor);
4466
4467         *plist_vcard_object = NULL;
4468
4469         vcard_start_cursor = __contacts_vcard_remove_line_break(vcard_start_cursor);
4470
4471         if (STRING_EQUAL != strncmp(vcard_start_cursor, begin, strlen(begin)))
4472                 return vcard_start_cursor;
4473
4474         vcard_cursor = vcard_start_cursor;
4475
4476         vcard_cursor += strlen(begin);
4477         vcard_cursor = __contacts_vcard_remove_line_break(vcard_cursor);
4478
4479         while (*vcard_cursor) {
4480                 if (new_line) {
4481                         if (STRING_EQUAL == strncmp(vcard_cursor, end, strlen(end))) {
4482                                 GList *sub_vcard_cursor = NULL;
4483                                 int vcard_len = 0;
4484                                 const char *pos_start = NULL;
4485
4486                                 vcard_cursor += strlen(end);
4487                                 vcard_cursor = __contacts_vcard_remove_line_break(vcard_cursor);
4488
4489                                 pos_start = vcard_start_cursor;
4490                                 for (sub_vcard_cursor = sub_vcard_list; sub_vcard_cursor; sub_vcard_cursor = sub_vcard_cursor->next) {
4491                                         sub_vcard_info_s *sub_vcard_info = sub_vcard_cursor->data;
4492                                         const char *pos_end = sub_vcard_info->pos_start;
4493                                         vcard_len += (pos_end - pos_start);
4494                                         pos_start = sub_vcard_info->pos_end;
4495                                 }
4496                                 vcard_len += (vcard_cursor - pos_start);
4497                                 vcard_object = calloc(vcard_len + 1, sizeof(char));
4498                                 if (NULL == vcard_object) {
4499                                         ERR("calloc() Fail");
4500                                         __contacts_vcard_free_sub_vcard_info_list(sub_vcard_list);
4501                                         return NULL;
4502                                 }
4503
4504                                 vcard_len = 0;
4505                                 pos_start = vcard_start_cursor;
4506                                 for (sub_vcard_cursor = sub_vcard_list; sub_vcard_cursor; sub_vcard_cursor = sub_vcard_cursor->next) {
4507                                         sub_vcard_info_s *sub_vcard_info = sub_vcard_cursor->data;
4508                                         const char *pos_end = sub_vcard_info->pos_start;
4509                                         memcpy(vcard_object+vcard_len, pos_start, pos_end - pos_start);
4510                                         vcard_len += (pos_end - pos_start);
4511                                         pos_start = sub_vcard_info->pos_end;
4512                                 }
4513                                 __contacts_vcard_free_sub_vcard_info_list(sub_vcard_list);
4514                                 memcpy(vcard_object+vcard_len, pos_start, vcard_cursor - pos_start);
4515                                 *plist_vcard_object = g_list_append(*plist_vcard_object, vcard_object);
4516
4517                                 return vcard_cursor;
4518                         } else if (STRING_EQUAL == strncmp(vcard_cursor, begin, strlen(begin))) {
4519                                 /* sub vcard */
4520                                 sub_vcard_info_s *sub_vcard_info = calloc(1, sizeof(sub_vcard_info_s));
4521                                 if (NULL == sub_vcard_info) {
4522                                         ERR("calloc() Fail");
4523                                         __contacts_vcard_free_sub_vcard_info_list(sub_vcard_list);
4524                                         return NULL;
4525                                 }
4526                                 sub_vcard_info->pos_start = vcard_cursor;
4527
4528                                 vcard_cursor = __contacts_vcard_parse_get_vcard_object(vcard_cursor, plist_vcard_object);
4529                                 sub_vcard_info->pos_end = vcard_cursor;
4530
4531                                 sub_vcard_list = g_list_append(sub_vcard_list, sub_vcard_info);
4532                                 continue;
4533                         }
4534                         new_line = false;
4535                 }
4536                 vcard_cursor++;
4537                 if (('\n' == *vcard_cursor) || ('\r' == *vcard_cursor && '\n' == *(vcard_cursor+1))) {
4538                         new_line = true;
4539                         vcard_cursor = __contacts_vcard_remove_line_break(vcard_cursor);
4540                 }
4541         }
4542
4543         __contacts_vcard_free_sub_vcard_info_list(sub_vcard_list);
4544
4545         return vcard_cursor;
4546 }
4547
4548 EXPORT_API int contacts_vcard_parse_to_contacts(const char *vcard_stream, contacts_list_h *out_contacts)
4549 {
4550         CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
4551         int ret;
4552         contacts_record_h record;
4553         contacts_list_h list = NULL;
4554         const char *cursor = NULL;
4555         char *vcard_object = NULL;
4556         GList *list_vcard_object = NULL;
4557
4558         RETV_IF(NULL == out_contacts, CONTACTS_ERROR_INVALID_PARAMETER);
4559         *out_contacts = NULL;
4560
4561         RETV_IF(NULL == vcard_stream, CONTACTS_ERROR_INVALID_PARAMETER);
4562
4563         cursor = vcard_stream;
4564         while ((cursor = __contacts_vcard_parse_get_vcard_object(cursor, &list_vcard_object))) {
4565                 GList *vcard_cursor = NULL;
4566                 if (NULL == list_vcard_object)
4567                         break;
4568
4569                 for (vcard_cursor = list_vcard_object; vcard_cursor; vcard_cursor = vcard_cursor->next) {
4570                         vcard_object = vcard_cursor->data;
4571                         if (NULL == vcard_object)
4572                                 continue;
4573
4574                         ret = __ctsvc_vcard_parse(vcard_object, &record);
4575                         if (ret < CONTACTS_ERROR_NONE) {
4576                                 ERR("__ctsvc_vcard_parse() Fail(%d)", ret);
4577                                 __contacts_vcard_free_vcard_object_list(list_vcard_object);
4578                                 contacts_list_destroy(list, true);
4579                                 return ret;
4580                         }
4581
4582                         if (NULL == list)
4583                                 contacts_list_create(&list);
4584                         contacts_list_add(list, record);
4585                         vcard_object = NULL;
4586                 }
4587                 __contacts_vcard_free_vcard_object_list(list_vcard_object);
4588         }
4589         *out_contacts = list;
4590         return CONTACTS_ERROR_NONE;
4591 }
4592
4593
4594 static int  _ctsvc_safe_add(unsigned int *total, unsigned int value)
4595 {
4596         if (UINT_MAX - *total < value) {
4597                 /* LCOV_EXCL_START */
4598                 ERR("overflow occurs when %d + %d", *total, value);
4599                 return CONTACTS_ERROR_SYSTEM;
4600                 /* LCOV_EXCL_STOP */
4601         }
4602
4603         *total += value;
4604         return CONTACTS_ERROR_NONE;
4605 }
4606
4607 EXPORT_API int contacts_vcard_parse_to_contact_foreach(const char *vcard_file_name,
4608                 contacts_vcard_parse_cb cb, void *data)
4609 {
4610         CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
4611         contacts_record_h record;
4612         FILE *file;
4613         unsigned int buf_size, len;
4614         int written_len;
4615         int ret;
4616         int vcard_depth = 0;
4617         char *stream;
4618         char line[1024] = {0};
4619
4620         RETV_IF(NULL == vcard_file_name, CONTACTS_ERROR_INVALID_PARAMETER);
4621         RETV_IF(NULL == cb, CONTACTS_ERROR_INVALID_PARAMETER);
4622
4623         file = fopen(vcard_file_name, "r");
4624         RETVM_IF(NULL == file, CONTACTS_ERROR_SYSTEM, "fopen() Fail(%d)", errno);
4625
4626         len = 0;
4627         buf_size = CTSVC_VCARD_MAX_SIZE;
4628         stream = malloc(CTSVC_VCARD_MAX_SIZE);
4629         if (NULL == stream) {
4630                 /* LCOV_EXCL_START */
4631                 ERR("Out of memory : malloc() Fail");
4632                 fclose(file);
4633                 return CONTACTS_ERROR_OUT_OF_MEMORY;
4634                 /* LCOV_EXCL_STOP */
4635         }
4636
4637         while (fgets(line, sizeof(line), file)) {
4638                 if (0 == len)
4639                         if (STRING_EQUAL != strncmp(line, "BEGIN:VCARD", strlen("BEGIN:VCARD")))
4640                                 continue;
4641
4642                 if (buf_size - len <= strlen(line)) {
4643                         char *new_stream;
4644                         buf_size += sizeof(line) * 2;
4645                         new_stream = realloc(stream, buf_size);
4646                         if (new_stream) {
4647                                 stream = new_stream;
4648                         } else {
4649                                 /* LCOV_EXCL_START */
4650                                 free(stream);
4651                                 fclose(file);
4652                                 return CONTACTS_ERROR_OUT_OF_MEMORY;
4653                                 /* LCOV_EXCL_STOP */
4654                         }
4655                 }
4656                 written_len = snprintf(stream + len, buf_size - len, "%s", line);
4657                 if (written_len < 0) {
4658                         /* LCOV_EXCL_START */
4659                         free(stream);
4660                         fclose(file);
4661                         ERR("snprintf() Fail(%d)", written_len);
4662                         return CONTACTS_ERROR_SYSTEM;
4663                         /* LCOV_EXCL_STOP */
4664                 }
4665
4666                 ret = _ctsvc_safe_add(&len, (unsigned int)written_len);
4667                 if (CONTACTS_ERROR_NONE != ret) {
4668                         free(stream);
4669                         fclose(file);
4670                         ERR("_ctsvc_safe_add() Fail", len, written_len);
4671                         return ret;
4672                 }
4673
4674                 if (STRING_EQUAL == strncmp(line, "END:VCARD", 9)) {
4675                         vcard_depth--;
4676
4677                         if (0 == vcard_depth) {
4678                                 const char *cursor = stream;
4679                                 GList *list_vcard_object = NULL;
4680
4681                                 len = 0;
4682
4683                                 while ((cursor = __contacts_vcard_parse_get_vcard_object(cursor, &list_vcard_object))) {
4684                                         GList *vcard_cursor = NULL;
4685                                         if (NULL == list_vcard_object)
4686                                                 break;
4687
4688                                         for (vcard_cursor = list_vcard_object; vcard_cursor; vcard_cursor = vcard_cursor->next) {
4689                                                 char *vcard_object = vcard_cursor->data;
4690
4691                                                 if (NULL == vcard_object)
4692                                                         continue;
4693
4694                                                 ret = __ctsvc_vcard_parse(vcard_object, &record);
4695                                                 if (ret < CONTACTS_ERROR_NONE) {
4696                                                         ERR("vcard stream parsing error");
4697                                                         free(stream);
4698                                                         fclose(file);
4699                                                         __contacts_vcard_free_vcard_object_list(list_vcard_object);
4700                                                         return ret;
4701                                                 }
4702
4703                                                 if (false == cb(record, data)) {
4704                                                         free(stream);
4705                                                         fclose(file);
4706                                                         __contacts_vcard_free_vcard_object_list(list_vcard_object);
4707                                                         contacts_record_destroy(record, true);
4708                                                         return CONTACTS_ERROR_NONE;
4709                                                 }
4710                                                 contacts_record_destroy(record, true);
4711                                         }
4712                                         __contacts_vcard_free_vcard_object_list(list_vcard_object);
4713                                         list_vcard_object = NULL;
4714                                 }
4715                         }
4716                 } else if (STRING_EQUAL == strncmp(line, "BEGIN:VCARD", 11)) { /* sub vcard object */
4717                         vcard_depth++;
4718                 }
4719         }
4720
4721         free(stream);
4722         fclose(file);
4723         return CONTACTS_ERROR_NONE;
4724 }
4725
4726 EXPORT_API int contacts_vcard_get_entity_count(const char *vcard_file_name, int *count)
4727 {
4728         CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
4729         FILE *file;
4730         int cnt;
4731         char line[1024] = {0};
4732         RETV_IF(NULL == count, CONTACTS_ERROR_INVALID_PARAMETER);
4733         *count = 0;
4734
4735         RETV_IF(NULL == vcard_file_name, CONTACTS_ERROR_INVALID_PARAMETER);
4736
4737         file = fopen(vcard_file_name, "r");
4738         RETVM_IF(NULL == file, CONTACTS_ERROR_SYSTEM, "System : fopen() Fail(%d)", errno);
4739
4740         cnt = 0;
4741         while (fgets(line, sizeof(line), file)) {
4742                 if (STRING_EQUAL == strncmp(line, "END:VCARD", 9))
4743                         cnt++;
4744         }
4745         fclose(file);
4746
4747         *count = cnt;
4748
4749         return CONTACTS_ERROR_NONE;
4750 }
4751
4752 EXPORT_API int contacts_vcard_get_limit_size_of_photo(unsigned int *limit_size)
4753 {
4754         CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
4755 #ifdef _CONTACTS_IPC_CLIENT
4756         int ret;
4757         bool result = false;
4758 #endif
4759
4760         RETV_IF(NULL == limit_size, CONTACTS_ERROR_INVALID_PARAMETER);
4761
4762 #ifdef _CONTACTS_IPC_CLIENT
4763         ret = ctsvc_ipc_client_check_permission(CTSVC_PERMISSION_CONTACT_READ, &result);
4764         RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_ipc_client_check_permission() Fail(%d)", ret);
4765         RETVM_IF(result == false, CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied (contact read)");
4766 #endif
4767
4768         *limit_size = limit_size_of_photo;
4769         return CONTACTS_ERROR_NONE;
4770 }
4771
4772 EXPORT_API int contacts_vcard_set_limit_size_of_photo(unsigned int limit_size)
4773 {
4774         CHECK_CONTACT_SUPPORTED(CONTACT_FEATURE);
4775 #ifdef _CONTACTS_IPC_CLIENT
4776         int ret;
4777         bool result = false;
4778 #endif
4779
4780         RETV_IF(CTSVC_IMAGE_MAX_SIZE <= limit_size, CONTACTS_ERROR_INVALID_PARAMETER);
4781         RETV_IF(limit_size < 8, CONTACTS_ERROR_INVALID_PARAMETER);
4782
4783 #ifdef _CONTACTS_IPC_CLIENT
4784         ret = ctsvc_ipc_client_check_permission(CTSVC_PERMISSION_CONTACT_WRITE, &result);
4785         RETVM_IF(CONTACTS_ERROR_NONE != ret, ret, "ctsvc_ipc_client_check_permission() Fail(%d)", ret);
4786         RETVM_IF(result == false, CONTACTS_ERROR_PERMISSION_DENIED, "Permission denied (contact read)");
4787 #endif
4788
4789         limit_size_of_photo = limit_size;
4790         return CONTACTS_ERROR_NONE;
4791 }
4792