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