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