365c1db974ba6fd606ac01575a4195d3e8579234
[platform/core/connectivity/bluetooth-agent.git] / pb-agent / bluetooth_pb_vcard.c
1 /*
2  * Bluetooth-agent
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:  Hocheol Seo <hocheol.seo@samsung.com>
7  *               Girishashok Joshi <girish.joshi@samsung.com>
8  *               Chanyeol Park <chanyeol.park@samsung.com>
9  *               Jaekyun Lee <jkyun.lee@samsung.com>
10  *
11  * Licensed under the Apache License, Version 2.0 (the "License");
12  * you may not use this file except in compliance with the License.
13  * You may obtain a copy of the License at
14  *
15  *              http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  *
23  */
24 #include <time.h>
25 #include <string.h>
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <stdio.h>
29 #include <glib.h>
30 #include <vconf.h>
31 #include <dlog.h>
32 #include <fcntl.h>
33 #include <errno.h>
34 #include <sys/stat.h>
35 #include <contacts.h>
36 #include <image_util.h>
37 #include <image_util_internal.h>
38 #include <libexif/exif-data.h>
39 #include <unistd.h>
40
41 #include "bluetooth_pb_vcard.h"
42 #include "bluetooth_pb_agent.h"
43
44 #define QP_ENC_LEN      3
45 #define LINEBREAK_LEN   75
46
47 typedef struct {
48         const char *src;
49         const char *dest;
50         int ret;
51         contacts_record_h person;
52         GString *string;
53 } bt_image_info_t;
54
55 gchar dest_thumb_path[255];
56 #define PBAP_IMAGE_THUMB_SIZE 48
57 #define PBAP_THMB_PATH "_thumb"
58 #define PBAP_THUMB_FILE_SIZE 4096
59 #define PBAP_IMAGE_ENCODE_QUALITY       90
60 #define PBAP_SECURITY_FILE_GROUP 6005
61 #define PBAP_SECURITY_DEFAULT_PERMISSION 0660
62 #define PBAP_SECURITY_DIR_DEFAULT_PERMISSION 0770
63 #define PBAP_SECURITY_IMAGE_PERMISSION 0440
64
65 static gchar *__bluetooth_pb_vcard_escape(const gchar *str);
66
67 static gchar *__bluetooth_pb_vcard_strv_concat(gchar **strv,
68                                         const gchar *delimeter);
69
70 static gboolean __bluetooth_pb_vcard_qp_encode_check(const gchar *str);
71
72 static gint __bluetooth_pb_vcard_qp_encode_strlen(const gchar *str,
73                                                 gint len);
74
75 static void __bluetooth_pb_vcard_qp_encode_append_to_hex(GString *string,
76                                                         const gchar *str,
77                                                         gint len,
78                                                         gint *line_pos);
79
80 static void __bluetooth_pb_vcard_qp_encode_append_printable_c(GString *string,
81                                                         gchar ch,
82                                                         gint *line_pos);
83
84 static void __bluetooth_pb_vcard_qp_encode_append(GString *string,
85                                                 const gchar *str,
86                                                 gint len,
87                                                 gint *line_pos);
88
89 static gchar *__bluetooth_pb_vcard_qp_encode(const gchar *str);
90
91 static void __bluetooth_pb_vcard_append_param_v21(GString *string,
92                                                  const gchar *param);
93
94 static void __bluetooth_pb_vcard_append_qp_encode_v21(GString *string,
95                                         const gchar *name,
96                                         const gchar *param,
97                                         const gchar *value);
98
99 static void __bluetooth_pb_vcard_append_base64_encode_v21(GString *string,
100                                                         const gchar *name,
101                                                         const gchar *param,
102                                                         const gchar *value,
103                                                         gsize len,
104                                                         gboolean folding);
105
106 static void __bluetooth_pb_vcard_append_n_v21(GString *string,
107                                         contacts_record_h contact);
108
109 static void __bluetooth_pb_vcard_append_phonetic_first_v21(GString *string,
110                                         contacts_record_h contact);
111
112 static void __bluetooth_pb_vcard_append_tel_v21(GString *string,
113                                                 contacts_record_h conatct);
114
115 static void __bluetooth_pb_vcard_append_fn_v21(GString *string,
116                                         contacts_record_h person);
117
118 static void __bluetooth_pb_vcard_append_photo_v21(GString *string,
119                                                 contacts_record_h person);
120
121 static void __bluetooth_pb_vcard_append_bday_v21(GString *string,
122                                                 contacts_record_h contact);
123
124 static void __bluetooth_pb_vcard_append_adr_v21(GString *string,
125                                                 contacts_record_h contact);
126
127 static void __bluetooth_pb_vcard_append_email_v21(GString *string,
128                                                 contacts_record_h contact);
129
130 static void __bluetooth_pb_vcard_append_title_v21(GString *string,
131                                                 contacts_record_h contact);
132
133 static void __bluetooth_pb_vcard_append_role_v21(GString *string,
134                                                 contacts_record_h contact);
135
136 static void __bluetooth_pb_vcard_append_org_v21(GString *string,
137                                                 contacts_record_h contact);
138
139 static void __bluetooth_pb_vcard_append_note_v21(GString *string,
140                                                 contacts_record_h contact);
141
142 static void __bluetooth_pb_vcard_append_rev_v21(GString *string,
143                                                 contacts_record_h contact);
144
145 static void __bluetooth_pb_vcard_append_url_v21(GString *string,
146                                                 contacts_record_h contact);
147
148 static void __bluetooth_pb_vcard_append_uid_v21(GString *string,
149                                                 contacts_record_h contact);
150
151 static void __bluetooth_pb_vcard_append_v30(GString *string,
152                                         const gchar *name,
153                                         const gchar *param,
154                                         const gchar *value);
155
156 static void __bluetooth_pb_vcard_remove_v30(GString *string,
157                                         const gchar *property_name);
158
159 static gchar *__bluetooth_pb_vcard_filter_v30(const gchar *vcard,
160                                         guint64 filter);
161
162 static gchar *__bluetooth_pb_vcard_real_contact_valist_v21(gint person_id,
163                                                         gint phonelog_id,
164                                                         guint64 filter,
165                                                         const gchar *first_name,
166                                                         va_list args);
167
168 static gchar *__bluetooth_pb_vcard_real_contact_valist_v30(gint person_id,
169                                                         gint phonelog_id,
170                                                         guint64 filter,
171                                                         const gchar *first_name,
172                                                         va_list args);
173
174 static gchar *__bluetooth_pb_vcard_real_contact_with_properties(gint person_id,
175                                                         gint phonelog_id,
176                                                         guint64 filter,
177                                                         guint8 format,
178                                                         const gchar *first_name,
179                                                         ...);
180
181 static gchar *__bluetooth_pb_vcard_real_call_v21(gint phonelog_id,
182                                                 guint filter,
183                                                 const gchar *attr);
184
185 static gchar *__bluetooth_pb_vcard_real_call_v30(gint phonelog_id,
186                                                 guint filter,
187                                                 const gchar *attr);
188
189 static gchar *__bluetooth_pb_vcard_real_call(gint phonelog_id,
190                                         guint filter,
191                                         guint8 format,
192                                         const gchar *attr);
193
194 static gchar **__bluetooth_pb_contact_add_field_str(contacts_record_h record,
195                                                 int *field,
196                                                 gint field_size);
197
198 static gchar **__bluetooth_pb_contact_tel_param(contacts_record_h number);
199
200 static gchar *__bluetooth_pb_contact_photo_type(const gchar *filename);
201
202 static gchar **__bluetooth_pb_contact_addr(contacts_record_h address);
203
204 static gchar **__bluetooth_pb_contact_addr_param(contacts_record_h address);
205
206 static gchar *__bluetooth_pb_phonelog_datetime(gint phonelog_id);
207
208 static gchar *__bluetooth_pb_name_from_contact(contacts_record_h contact);
209
210 static gchar *__bluetooth_pb_phonetic_name_from_contact(contacts_record_h contact);
211
212 static gchar *__bluetooth_pb_number_from_contact(contacts_record_h contact);
213
214 static gint __bluetooth_pb_person_id_from_phonelog_id(gint phonelog_id);
215
216 /* LCOV_EXCL_START */
217 static gchar *__bluetooth_pb_vcard_escape(const gchar *str)
218 {
219         FN_START;
220         GString *escaped;
221
222         gchar *st = NULL;
223         gchar *pos = NULL;
224
225         if (str == NULL)
226                 return NULL;
227
228         escaped = g_string_new(NULL);
229
230         st = (gchar *)str;
231         pos = st;
232
233         while (*pos != '\0') {
234                 if (*pos == ';') {
235                         g_string_append_len(escaped, st, (pos - st));
236                         g_string_append(escaped, "\\;");
237
238                         pos++;
239                         st = pos;
240                 } else {
241                         pos++;
242                 }
243         }
244
245         g_string_append_len(escaped, st, (pos - st));
246         FN_END;
247         return g_string_free(escaped, FALSE);
248 }
249
250 static gchar *__bluetooth_pb_vcard_strv_concat(gchar **strv,
251                                         const gchar *separator)
252 {
253         FN_START;
254         GString *string = g_string_new(NULL);
255         gint i;
256
257         for (i = 0; strv[i] != NULL; i++) {
258                 if (i > 0)
259                         g_string_append(string, ";");
260
261                 g_string_append(string, strv[i]);
262         }
263
264         FN_END;
265         return g_string_free(string, FALSE);
266 }
267 /* LCOV_EXCL_STOP */
268
269 static gboolean __bluetooth_pb_vcard_qp_encode_check(const gchar *str)
270 {
271         FN_START;
272         gchar *pos = NULL;
273
274         if (str == NULL)
275                 return FALSE;
276
277         pos = (gchar *)str;
278         while (*pos != '\0') {
279                 /* ascii code ' ' : 32, '~' : 126 */
280                 if ((guchar)*pos < ' ' || (guchar)*pos > '~')
281                         return TRUE;
282
283                 pos++;
284         }
285         FN_END;
286         return FALSE;
287 }
288
289 /* LCOV_EXCL_START */
290 /* get string length, which convert to quoted-printable encoding */
291 static gint __bluetooth_pb_vcard_qp_encode_strlen(const gchar *str,
292                                                 gint len)
293 {
294         FN_START;
295         gchar *pos;
296
297         gint count = 0;
298         gint length = len;
299
300         if (str == NULL)
301                 return 0;
302
303         if (strlen(str) < len)
304                 length = -1;
305
306         pos = (gchar *)str;
307
308         while (*pos != '\0' && (((pos - str) < length) || length < 0)) {
309                 if ((guchar)*pos == '\t') {
310                         count++;
311                         pos++;
312                         continue;
313                 }
314
315                 if ((guchar)*pos < ' ' || (guchar)*pos == '=') {
316                         count += QP_ENC_LEN;
317                         pos++;
318                         continue;
319                 }
320
321                 /* check no-ascii utf-8 character */
322                 if ((guchar)*pos > '~') {
323
324                         gchar *next;
325
326                         next = g_utf8_next_char(pos);
327
328                         count += QP_ENC_LEN * (next - pos);
329                         pos = next;
330                         continue;
331                 }
332
333                 pos++;
334                 count++;
335         }
336
337         FN_END;
338         return count;
339 }
340
341 /* convert to quoted printable code */
342 static void __bluetooth_pb_vcard_qp_encode_append_to_hex(GString *string,
343                                                         const gchar *str,
344                                                         gint len,
345                                                         gint *line_pos)
346 {
347         FN_START;
348         int i;
349
350         if (str == NULL || len == 0)
351                 return;
352
353         /* add soft linebreak when it exceed */
354         if ((*line_pos + (QP_ENC_LEN * len) > LINEBREAK_LEN)) {
355                 g_string_append(string, "=\r\n");
356                 *line_pos = 0;
357         }
358
359         for (i = 0; i < len; i++) {
360                 g_string_append_printf(string, "=%02X", (guchar)*(str+i));
361                 *line_pos += QP_ENC_LEN;
362         }
363         FN_END;
364 }
365
366 /* append plain visiable ascii character */
367 static void __bluetooth_pb_vcard_qp_encode_append_printable_c(GString *string,
368                                                         gchar ch,
369                                                         gint *line_pos)
370 {
371         FN_START;
372         /* add soft linebreak when it exceed */
373         if (*line_pos + 1 > LINEBREAK_LEN) {
374                 g_string_append(string, "=\r\n");
375                 *line_pos = 0;
376         }
377         g_string_append_c(string, ch);
378         (*line_pos)++;
379         FN_END;
380 }
381
382 static void __bluetooth_pb_vcard_qp_encode_append(GString *string,
383                                                 const gchar *str,
384                                                 gint len,
385                                                 gint *line_pos)
386 {
387         FN_START;
388         gint encode_len;
389
390         gint i = 0;
391
392         if (string == NULL)
393                 return;
394
395         encode_len = __bluetooth_pb_vcard_qp_encode_strlen(str, len);
396
397         /* add soft linebreak when it exceed */
398         if (((*line_pos + encode_len) > LINEBREAK_LEN) && (*line_pos > 1)) {
399                 g_string_append(string, "=\r\n");
400                 *line_pos = 0;
401         }
402
403         while (i < len) {
404                 gchar *pos;
405
406                 pos = ((gchar *)str) + i;
407
408                 /* converts invisiable character and escape character '='
409                         to quoted-printable */
410                 if ((guchar)*pos != '\t' &&
411                                 ((guchar)*pos < ' ' || (guchar)*pos == '=')) {
412                         __bluetooth_pb_vcard_qp_encode_append_to_hex(string,
413                                                         pos, 1, line_pos);
414                         i++;
415
416                         continue;
417                 }
418
419                 /* converts non-ascii utf-8 character to quoted-printable */
420                 if ((guchar)*pos > '~') {
421                         gchar *next;
422                         int ch_len;
423
424                         next = g_utf8_next_char(pos);
425
426                         ch_len = next - pos;
427                         __bluetooth_pb_vcard_qp_encode_append_to_hex(string,
428                                                         pos, ch_len, line_pos);
429                         i += ch_len;
430
431                         continue;
432                 }
433
434                 __bluetooth_pb_vcard_qp_encode_append_printable_c(string, *pos,
435                                                                 line_pos);
436                 i++;
437         }
438         FN_END;
439 }
440
441 static gchar *__bluetooth_pb_vcard_qp_encode(const gchar *str)
442 {
443         FN_START;
444         GString *enc;
445
446         gchar *st_pos;
447         gchar *pos;
448
449         gint line_pos = 0;
450
451         if (str == NULL)
452                 return NULL;
453
454         enc = g_string_new(NULL);
455
456         st_pos = (gchar *)str;
457         pos = (gchar *)str;
458
459         while (*pos != '\0') {
460                 /* split string with given delimeter ' ' or '\t' */
461                 if (*pos == ' ' || *pos == '\t') {
462                         __bluetooth_pb_vcard_qp_encode_append(enc, st_pos,
463                                         (pos - st_pos), &line_pos);
464
465                         st_pos = pos;
466                         pos++;
467
468                         continue;
469                 }
470
471                 /* split string with given delimeter '\r', '\n' or
472                         '\r\n' - newline */
473                 if (*pos == '\r' || *pos == '\n') {
474                         __bluetooth_pb_vcard_qp_encode_append(enc, st_pos,
475                                         (pos - st_pos), &line_pos);
476
477                         /* converts newline to qp_encode with soft linebreak
478                          for example, converts \r\n to =0D=0A=\r\n */
479                         __bluetooth_pb_vcard_qp_encode_append_to_hex(enc,
480                                                         "\r\n", 2, &line_pos);
481                         g_string_append(enc, "=\r\n ");
482
483                         line_pos = 1;
484
485                         if (*pos == '\r' && *(pos + 1) == '\n')
486                                 pos += 2;
487                         else
488                                 pos++;
489
490                         st_pos = pos;
491
492                         continue;
493                 }
494
495                 pos++;
496         }
497
498         __bluetooth_pb_vcard_qp_encode_append(enc, st_pos,
499                         (pos - st_pos), &line_pos);
500
501         FN_END;
502         return g_string_free(enc, FALSE);
503 }
504 /* LCOV_EXCL_STOP */
505
506 static void __bluetooth_pb_vcard_append_param_v21(GString *string,
507                                                  const gchar *param)
508 {
509         FN_START;
510         gchar *pos = NULL;
511
512         if (param == NULL)
513                 return;
514
515         pos = (gchar *)param;
516
517         /* trim ';' on first */
518         while (*pos != '\0') {
519                 if (*pos != ';')
520                         break;
521
522                 pos++;
523         }
524
525         if (*pos != '\0')
526                 g_string_append_printf(string, ";%s", pos);
527         FN_END;
528 }
529
530 static void __bluetooth_pb_vcard_append_qp_encode_v21(GString *string,
531                                                 const gchar *name,
532                                                 const gchar *param,
533                                                 const gchar *value)
534 {
535         FN_START;
536         GString *property = NULL;
537
538         if (name == NULL)
539                 return;
540
541         property = g_string_new(name);
542         __bluetooth_pb_vcard_append_param_v21(property, param);
543
544         if (__bluetooth_pb_vcard_qp_encode_check(value)) {
545                 /* LCOV_EXCL_START */
546                 gchar *enc = NULL;
547
548                 __bluetooth_pb_vcard_append_param_v21(property,
549                                 "CHARSET=UTF-8");
550                 __bluetooth_pb_vcard_append_param_v21(property,
551                                 "ENCODING=QUOTED-PRINTABLE");
552                 g_string_append(property, ":");
553
554                 enc = __bluetooth_pb_vcard_qp_encode(value);
555
556                 if (enc) {
557                         g_string_append(property, enc);
558                         g_free(enc);
559                 }
560                 /* LCOV_EXCL_STOP */
561         } else {
562                 g_string_append(property, ":");
563                 if (value)
564                         g_string_append(property , value);
565         }
566
567         g_string_append_printf(string, "%s\r\n", property->str);
568
569         g_string_free(property, TRUE);
570         FN_END;
571 }
572
573 /* LCOV_EXCL_START */
574 static void __bluetooth_pb_vcard_append_base64_encode_v21(GString *string,
575                                                         const gchar *name,
576                                                         const gchar *param,
577                                                         const gchar *value,
578                                                         gsize len,
579                                                         gboolean folding)
580 {
581         FN_START;
582         gchar *enc = NULL;
583
584         if (name == NULL)
585                 return;
586         DBG("base 64 encoding\n");
587
588         g_string_append(string, name);
589
590         __bluetooth_pb_vcard_append_param_v21(string, param);
591         __bluetooth_pb_vcard_append_param_v21(string, "ENCODING=BASE64");
592
593         g_string_append(string, ":");
594
595         if (value == NULL)
596                 return;
597
598         enc = g_base64_encode((const guchar *)value, len);
599
600         if (folding == FALSE) {
601                 g_string_append(string, enc);
602         } else {
603                 gint enc_len = strlen(enc);
604                 gint i = 0;
605
606                 /* count ' ' size for folding */
607                 gint fline_len = LINEBREAK_LEN - 1;
608
609                 for (i = 0; (i * fline_len) < enc_len; i++) {
610                         g_string_append(string, "\r\n ");
611                         if ((i * fline_len) + fline_len > enc_len)
612                                 g_string_append(string, enc + (i * fline_len));
613                         else
614                                 g_string_append_len(string, enc +
615                                                 (i * fline_len), fline_len);
616                 }
617
618                 /* some application requires more \r\n */
619                 g_string_append(string, "\r\n");
620         }
621         g_string_append(string, "\r\n");
622         DBG("base 64 encoding\n");
623
624         g_free(enc);
625         FN_END;
626 }
627
628 static void __bluetooth_pb_vcard_append_n_v21(GString *string,
629                                         contacts_record_h contact)
630 {
631         FN_START;
632         gchar *str;
633
634         str = __bluetooth_pb_name_from_contact(contact);
635         __bluetooth_pb_vcard_append_qp_encode_v21(string, "N", NULL, str);
636
637         g_free(str);
638         FN_END;
639 }
640
641 static void __bluetooth_pb_vcard_append_phonetic_first_v21(GString *string,
642                                         contacts_record_h contact)
643 {
644         FN_START;
645         gchar *str;
646
647         str = __bluetooth_pb_phonetic_name_from_contact(contact);
648
649         if (str != NULL) {
650                 __bluetooth_pb_vcard_append_qp_encode_v21(string, "SOUND", "X-IRMC-N", str);
651                 g_free(str);
652         }
653         FN_END;
654 }
655
656 static void __bluetooth_pb_vcard_append_tel_v21(GString *string,
657                                                 contacts_record_h contact)
658 {
659         FN_START;
660         gint count = 0;
661
662         gint i;
663         gint status;
664
665         status = contacts_record_get_child_record_count(contact,
666                         _contacts_contact.number,
667                         &count);
668
669         if (status != CONTACTS_ERROR_NONE)
670                 return;
671
672         for (i = 0; i < count; i++) {
673                 contacts_record_h number = NULL;
674
675                 gchar **paramv = NULL;
676                 gchar *param = NULL;
677
678                 gchar *tel = NULL;
679                 gchar *escaped = NULL;
680
681                 status = contacts_record_get_child_record_at_p(contact,
682                                 _contacts_contact.number, i, &number);
683
684                 if (status != CONTACTS_ERROR_NONE)
685                         continue;
686
687                 status = contacts_record_get_str_p(number,
688                                 _contacts_number.number,
689                                 &tel);
690
691                 if (status != CONTACTS_ERROR_NONE)
692                         continue;
693
694                 escaped = __bluetooth_pb_vcard_escape(tel);
695
696                 paramv = __bluetooth_pb_contact_tel_param(number);
697                 if (paramv) {
698                         param = __bluetooth_pb_vcard_strv_concat(paramv, ";");
699                         g_strfreev(paramv);
700                         __bluetooth_pb_vcard_append_qp_encode_v21(string, "TEL", param,
701                                                                 escaped);
702                         g_free(param);
703                 }
704
705                 g_free(escaped);
706         }
707         FN_END;
708 }
709
710 static void __bluetooth_pb_vcard_append_fn_v21(GString *string,
711                                         contacts_record_h person)
712 {
713         FN_START;
714         gint status;
715
716         gchar *fn = NULL;
717         gchar *tmp = NULL;
718
719         status = contacts_record_get_str_p(person,
720                         _contacts_person.display_name,
721                         &tmp);
722
723         if (status != CONTACTS_ERROR_NONE)
724                 return;
725
726         fn = __bluetooth_pb_vcard_escape(tmp);
727
728         __bluetooth_pb_vcard_append_qp_encode_v21(string, "FN", NULL, fn);
729
730         g_free(fn);
731 }
732 /* LCOV_EXCL_STOP */
733
734 /* image util APIs will be deprecated in Tizen 5.0. So we should replace it to new API
735      https://developer.tizen.org/development/guides/native-application/media-and-camera/image-editing#decode
736      https://developer.tizen.org/development/guides/native-application/media-and-camera/image-editing#encode
737 */
738 #if 0
739 static image_util_rotation_e __bt_pbap_get_rotation_info(const char *path)
740 {
741         FN_START;
742         ExifData *ed = NULL;
743         ExifEntry *entry;
744         image_util_rotation_e rotation = IMAGE_UTIL_ROTATION_NONE;
745         int orientation = 0;
746
747         ed = exif_data_new_from_file(path);
748         if (ed == NULL) {
749                 ERR("exif_data_new_from_file : ExifData is NULL");
750                 return IMAGE_UTIL_ROTATION_NONE;
751         }
752
753         entry = exif_data_get_entry(ed, EXIF_TAG_ORIENTATION);
754         if (entry) {
755                 ExifByteOrder mByteOrder = exif_data_get_byte_order(ed);
756                 orientation = (int)exif_get_short(entry->data, mByteOrder);
757                 if (orientation < 0 || orientation > 8)
758                         orientation = 0;
759         }
760
761         exif_data_unref(ed);
762
763         switch (orientation) {
764         case 1: /* Top-left */
765                 rotation = IMAGE_UTIL_ROTATION_NONE;
766                 break;
767         case 2: /* Top-right */
768                 rotation = IMAGE_UTIL_ROTATION_FLIP_HORZ;
769                 break;
770         case 3: /* Bottom-right */
771                 rotation = IMAGE_UTIL_ROTATION_180;
772                 break;
773         case 4: /* Bottom-left */
774                 rotation = IMAGE_UTIL_ROTATION_FLIP_VERT;
775                 break;
776         case 6: /* Right-top */
777                 rotation = IMAGE_UTIL_ROTATION_90;
778                 break;
779         case 8: /* Left-bottom */
780                 rotation = IMAGE_UTIL_ROTATION_270;
781                 break;
782         case 5: /* Left-top */
783         case 7: /* Right-bottom */
784         case 0:
785         default:
786                 break;
787         };
788
789         FN_END;
790         return rotation;
791 }
792
793
794 static bool __bt_pbap_image_util_supported_jpeg_colorspace_cb(
795                         image_util_colorspace_e colorspace, void *user_data)
796 {
797         FN_START;
798         unsigned char *img_target = 0;
799         unsigned char *img_source = 0;
800         gchar *type = NULL;
801         gchar *param = NULL;
802         gchar *contents = NULL;
803         int width = 0;
804         int height = 0;
805         int resized_width = 0;
806         int resized_height = 0;
807         int dest_fd = 0;
808         unsigned int size_decode = 0;
809         image_util_rotation_e rotation;
810         image_util_error_e ret = 0;
811         gsize len = 0;
812
813         bt_image_info_t *info = (bt_image_info_t *)user_data;
814         rotation = __bt_pbap_get_rotation_info(info->src);
815         ret = image_util_decode_jpeg(info->src, colorspace, &img_source, &width,
816                                                         &height, &size_decode);
817         if (ret != IMAGE_UTIL_ERROR_NONE) {
818                 ERR("Can not decode");
819                 memset(info, 0x00, sizeof(bt_image_info_t));
820                 return true;
821         }
822
823         DBG("decoding completed width = %d, height = %d, size = %d\n", width,
824                                                         height, size_decode);
825         if (width > PBAP_IMAGE_THUMB_SIZE  || height > PBAP_IMAGE_THUMB_SIZE) {
826                 if (width <= 0 || height <= 0) {
827                         free(img_source);
828                         ERR("image size error(%d)", PBAP_IMAGE_THUMB_SIZE);
829                         memset(info, 0x00, sizeof(bt_image_info_t));
830                         return false;
831                 }
832
833                 if (width > height) {
834                         resized_width = PBAP_IMAGE_THUMB_SIZE ;
835                         resized_height = height * PBAP_IMAGE_THUMB_SIZE / width;
836                 } else {
837                         resized_height = PBAP_IMAGE_THUMB_SIZE;
838                         resized_width = width * PBAP_IMAGE_THUMB_SIZE / height;
839                 }
840
841                 if (resized_height % 8)
842                         resized_height += 8 - (resized_height % 8);
843                 if (resized_width % 8)
844                         resized_width += 8 - (resized_width % 8);
845
846                 DBG("original size[%d, %d] changed to resize[%d,%d]", width,
847                                         height, resized_width, resized_height);
848
849                 ret = image_util_calculate_buffer_size(resized_width,
850                                                         resized_height,
851                                                         colorspace ,
852                                                         &size_decode);
853
854                 img_target = g_malloc0(size_decode);
855
856                 /* do resize */
857                 ret = image_util_resize(img_target, &resized_width,
858                                         &resized_height, img_source, width,
859                                         height, colorspace);
860                 if (ret != IMAGE_UTIL_ERROR_NONE) {
861                         ERR("image_util_resize failed(%d)", ret);
862                         g_free(img_target);
863                         free(img_source);
864                         memset(info, 0x00, sizeof(bt_image_info_t));
865                         return false;
866                 }
867                 free(img_source);
868         } else {
869                 resized_width = width;
870                 resized_height = height;
871                 img_target = img_source;
872         }
873         DBG("Resized w = %d, ht = %d, size = %d\n", width, height, size_decode);
874
875         if (IMAGE_UTIL_ROTATION_NONE != rotation) {
876                 int rotated_width, rotated_height;
877                 unsigned char *img_rotate = 0;
878                 img_rotate = g_malloc0(size_decode);
879                 ret = image_util_rotate(img_rotate, &rotated_width, &rotated_height,
880                                         rotation, img_target, resized_width,
881                                         resized_height, colorspace);
882                 if (ret != 0)
883                         ERR("image_util_rotate failed");
884                 resized_width = rotated_width;
885                 resized_height = rotated_height;
886                 g_free(img_target);
887                 img_target = img_rotate;
888         }
889
890         /* image encode */
891         ret = image_util_encode_jpeg(img_target, resized_width, resized_height,
892                                         colorspace, PBAP_IMAGE_ENCODE_QUALITY,
893                                         info->dest);
894         g_free(img_target);
895         if (ret != IMAGE_UTIL_ERROR_NONE) {
896                 ERR("image_util_encode_jpeg failed(%d)", ret);
897                 info->ret = CONTACTS_ERROR_INTERNAL;
898                 goto done;
899         }
900         DBG("Encoding done\n");
901
902         dest_fd = open(info->dest, O_RDONLY);
903         if (dest_fd < 0) {
904                 ERR("System : Open Failed(%d)", errno);
905                 ERR_SECURE("Open : dest path(%s)", info->dest);
906                 goto done;
907         }
908
909         ret = fchown(dest_fd, getuid(), PBAP_SECURITY_FILE_GROUP);
910         if (0 != ret) {
911                 ERR("fchown Failed(%d)", errno);
912                 DBG_SECURE("fchown : dest path(%s)", info->dest);
913                 close(dest_fd);
914                 goto done;
915         }
916
917         ret = fchmod(dest_fd, PBAP_SECURITY_IMAGE_PERMISSION);
918         if (0 != ret) {
919                 ERR("fchmod Failed(%d)", errno);
920                 ERR_SECURE("fchmod : dest path(%s)", info->dest);
921                 close(dest_fd);
922                 goto done;
923         }
924         close(dest_fd);
925
926         info->ret = CONTACTS_ERROR_NONE;
927         type = __bluetooth_pb_contact_photo_type(info->dest);
928         DBG("Cintact image thumb type is = %s\n", type);
929
930         if (type) {
931                 param = g_strdup_printf("TYPE=%s", type);
932                 g_free(type);
933         }
934
935         if (g_file_get_contents(info->dest, &contents, &len, NULL) == FALSE) {
936                 ERR("can not read file contents:%s\n", info->dest);
937                 goto done;
938         }
939
940         __bluetooth_pb_vcard_append_base64_encode_v21(info->string,
941                         "PHOTO", param, contents, len, TRUE);
942
943 done:
944         g_free(param);
945         g_free(contents);
946         remove(info->dest);
947         memset(info, 0x00, sizeof(bt_image_info_t));
948         DBG("Cintact image thumb created successfuly\n");
949         FN_END;
950         return false;
951 }
952 #endif
953
954 /* LCOV_EXCL_START */
955 static void __bluetooth_pb_vcard_append_photo_v21(GString *string,
956                                                 contacts_record_h person)
957 {
958         FN_START;
959         gint status;
960         gchar *filename = NULL;
961         struct stat stat_info;
962         gchar *type = NULL;
963         gchar *param = NULL;
964         gchar *contents = NULL;
965         gsize len = 0;
966         char *ptr = NULL;
967
968         status = contacts_record_get_str_p(person,
969                         _contacts_person.image_thumbnail_path,
970                         &filename);
971
972         if (status != CONTACTS_ERROR_NONE || NULL == filename)
973                 return;
974
975         stat_info.st_size = 0;
976
977         if (0 > stat(filename, &stat_info))
978                 ERR("fstat failed, file does not exist %s", filename);
979
980         if (PBAP_THUMB_FILE_SIZE > stat_info.st_size) {
981                 DBG_SECURE("File size small, so use thubnail %s\n", filename);
982
983                 type = __bluetooth_pb_contact_photo_type(filename);
984                 if (type) {
985                         param = g_strdup_printf("TYPE=%s", type);
986                         g_free(type);
987                 }
988
989                 if (g_file_get_contents(filename, &contents, &len, NULL) ==
990                                                                         FALSE) {
991                         ERR("can not read file contents:%s\n", filename);
992                         g_free(param);
993                         return;
994                 }
995                 DBG("Retrieved the contents of the file \n");
996                 __bluetooth_pb_vcard_append_base64_encode_v21(string,
997                                 "PHOTO", param, contents, len, TRUE);
998
999                 g_free(param);
1000                 g_free(contents);
1001                 return;
1002         }
1003
1004         ptr = strrchr(filename, '.');
1005         if (NULL != ptr) {
1006                 memset(dest_thumb_path, 0x00, sizeof(dest_thumb_path));
1007                 g_strlcpy(dest_thumb_path, filename, ptr - filename);
1008                 g_strlcat(dest_thumb_path, PBAP_THMB_PATH,
1009                                                 sizeof(dest_thumb_path));
1010                 g_strlcat(dest_thumb_path, ptr, sizeof(dest_thumb_path));
1011                 DBG("Thumbnail path is = %s", dest_thumb_path);
1012         }
1013         DBG_SECURE("filename = %s Thumbnail path is = %s", filename, dest_thumb_path);
1014
1015 /* image_util_foreach_supported_jpeg_colorspace API will be deprecated in Tizen 5.0. So we should replace it to new API
1016      https://developer.tizen.org/development/guides/native-application/media-and-camera/image-editing#decode
1017      https://developer.tizen.org/development/guides/native-application/media-and-camera/image-editing#encode
1018 */
1019 #if 0
1020         bt_image_info_t img_info;
1021         int res = 0;
1022
1023         img_info.src = filename;
1024         img_info.dest = dest_thumb_path;
1025         img_info.ret = CONTACTS_ERROR_INTERNAL;
1026         img_info.person = person;
1027         img_info.string = string;
1028
1029         res = image_util_foreach_supported_jpeg_colorspace(
1030                 __bt_pbap_image_util_supported_jpeg_colorspace_cb, &img_info);
1031
1032         if (res != IMAGE_UTIL_ERROR_NONE)
1033                 ERR("Image resizing is failed");
1034 #endif
1035
1036         FN_END;
1037 }
1038
1039 static void __bluetooth_pb_vcard_append_bday_v21(GString *string,
1040                                                 contacts_record_h contact)
1041 {
1042         FN_START;
1043         gint count = 0;
1044
1045         gint status;
1046         gint i;
1047
1048         status = contacts_record_get_child_record_count(contact,
1049                         _contacts_contact.event, &count);
1050
1051         if (status != CONTACTS_ERROR_NONE)
1052                 return;
1053
1054         for (i = 0; i < count; i++) {
1055                 contacts_record_h event = NULL;
1056
1057                 gint date;
1058
1059                 gchar *bday;
1060
1061                 contacts_event_type_e type;
1062
1063                 status = contacts_record_get_child_record_at_p(contact,
1064                                 _contacts_contact.event, i, &event);
1065
1066                 if (status != CONTACTS_ERROR_NONE)
1067                         continue;
1068
1069                 status = contacts_record_get_int(event,
1070                                 _contacts_event.type,
1071                                 (gint *) &type);
1072
1073                 if (status != CONTACTS_ERROR_NONE)
1074                         continue;
1075
1076                 if (type != CONTACTS_EVENT_TYPE_BIRTH)
1077                         continue;
1078
1079                 status = contacts_record_get_int(event,
1080                                 _contacts_event.date,
1081                                 &date);
1082
1083                 if (status != CONTACTS_ERROR_NONE)
1084                         continue;
1085
1086                 if (date <= 0)
1087                         continue;
1088
1089                 bday = g_strdup_printf("%04d-%02d-%02d",
1090                                 (date/10000), (date/100)%100, date%100);
1091                 __bluetooth_pb_vcard_append_qp_encode_v21(string, "BDAY",
1092                                 NULL, bday);
1093                 g_free(bday);
1094         }
1095         FN_END;
1096 }
1097
1098 static void __bluetooth_pb_vcard_append_adr_v21(GString *string,
1099                                                 contacts_record_h contact)
1100 {
1101         FN_START;
1102         gint count = 0;
1103
1104         gint status;
1105         gint i;
1106
1107         status = contacts_record_get_child_record_count(contact,
1108                         _contacts_contact.address,
1109                         &count);
1110
1111         if (status != CONTACTS_ERROR_NONE)
1112                 return;
1113
1114         for (i = 0; i < count; i++) {
1115                 contacts_record_h address = NULL;
1116
1117                 gchar **addrv;
1118                 gchar **paramv;
1119
1120                 gchar *addr;
1121                 gchar *param;
1122
1123                 status = contacts_record_get_child_record_at_p(contact,
1124                                 _contacts_contact.address, i, &address);
1125
1126                 if (status != CONTACTS_ERROR_NONE)
1127                         continue;
1128
1129                 addrv = __bluetooth_pb_contact_addr(address);
1130
1131                 if (addrv == NULL)
1132                         continue;
1133
1134                 addr = __bluetooth_pb_vcard_strv_concat(addrv, ";");
1135                 g_strfreev(addrv);
1136
1137                 paramv = __bluetooth_pb_contact_addr_param(address);
1138                 if (paramv) {
1139                         param = __bluetooth_pb_vcard_strv_concat(paramv, ";");
1140                         g_strfreev(paramv);
1141
1142                         __bluetooth_pb_vcard_append_qp_encode_v21(string, "ADR",
1143                                         param, addr);
1144                         g_free(param);
1145                 }
1146
1147                 g_free(addr);
1148         }
1149         FN_END;
1150 }
1151
1152 static void __bluetooth_pb_vcard_append_email_v21(GString *string,
1153                                                 contacts_record_h contact)
1154 {
1155         FN_START;
1156         gint count = 0;
1157
1158         gint status;
1159         gint i;
1160
1161         status = contacts_record_get_child_record_count(contact,
1162                         _contacts_contact.email,
1163                         &count);
1164
1165         if (status != CONTACTS_ERROR_NONE)
1166                 return;
1167
1168         for (i = 0; i < count; i++) {
1169                 contacts_record_h email = NULL;
1170
1171                 gchar *tmp = NULL;
1172                 gchar *escaped;
1173
1174                 status = contacts_record_get_child_record_at_p(contact,
1175                                 _contacts_contact.email, i, &email);
1176
1177                 if (status != CONTACTS_ERROR_NONE)
1178                         continue;
1179
1180                 status = contacts_record_get_str_p(email,
1181                                 _contacts_email.email,
1182                                 &tmp);
1183
1184                 if (status != CONTACTS_ERROR_NONE)
1185                         continue;
1186
1187                 escaped = __bluetooth_pb_vcard_escape(tmp);
1188                 __bluetooth_pb_vcard_append_qp_encode_v21(string, "EMAIL", NULL,
1189                                                                 escaped);
1190
1191                 g_free(escaped);
1192         }
1193         FN_END;
1194 }
1195
1196 static void __bluetooth_pb_vcard_append_title_v21(GString *string,
1197                                                 contacts_record_h contact)
1198 {
1199         FN_START;
1200         gint count = 0;
1201
1202         gint status;
1203         gint i;
1204
1205         status = contacts_record_get_child_record_count(contact,
1206                         _contacts_contact.company,
1207                         &count);
1208
1209         if (status != CONTACTS_ERROR_NONE)
1210                 return;
1211
1212         for (i = 0; i < count; i++) {
1213                 contacts_record_h company = NULL;
1214
1215                 char *title = NULL;
1216                 gchar *escaped;
1217
1218                 status = contacts_record_get_child_record_at_p(contact,
1219                                         _contacts_contact.company, i, &company);
1220
1221                 if (status != CONTACTS_ERROR_NONE)
1222                         continue;
1223
1224                 status = contacts_record_get_str_p(company,
1225                                 _contacts_company.job_title,
1226                                 &title);
1227
1228                 if (status != CONTACTS_ERROR_NONE)
1229                         continue;
1230
1231                 escaped = __bluetooth_pb_vcard_escape(title);
1232                 __bluetooth_pb_vcard_append_qp_encode_v21(string, "TITLE", NULL,
1233                                                                 escaped);
1234
1235                 g_free(escaped);
1236         }
1237         FN_END;
1238 }
1239
1240 static void __bluetooth_pb_vcard_append_role_v21(GString *string,
1241                                                 contacts_record_h contact)
1242 {
1243         FN_START;
1244         gint count = 0;
1245
1246         gint status;
1247         gint i;
1248
1249         status = contacts_record_get_child_record_count(contact,
1250                         _contacts_contact.company,
1251                         &count);
1252
1253         if (status != CONTACTS_ERROR_NONE)
1254                 return;
1255
1256         for (i = 0; i < count; i++) {
1257                 contacts_record_h company = NULL;
1258
1259                 char *role = NULL;
1260                 gchar *escaped;
1261
1262                 status = contacts_record_get_child_record_at_p(contact,
1263                                 _contacts_contact.company, i, &company);
1264
1265                 if (status != CONTACTS_ERROR_NONE)
1266                         continue;
1267
1268                 status = contacts_record_get_str_p(company,
1269                                 _contacts_company.role,
1270                                 &role);
1271
1272                 if (status != CONTACTS_ERROR_NONE)
1273                         continue;
1274
1275                 escaped = __bluetooth_pb_vcard_escape(role);
1276                 __bluetooth_pb_vcard_append_qp_encode_v21(string, "ROLE", NULL,
1277                                                                 escaped);
1278
1279                 g_free(escaped);
1280         }
1281         FN_END;
1282 }
1283
1284 static void __bluetooth_pb_vcard_append_org_v21(GString *string,
1285                                                 contacts_record_h contact)
1286 {
1287         FN_START;
1288         gint count = 0;
1289
1290         gint status;
1291         gint i;
1292
1293         status = contacts_record_get_child_record_count(contact,
1294                         _contacts_contact.company,
1295                         &count);
1296
1297         if (status != CONTACTS_ERROR_NONE)
1298                 return;
1299
1300         for (i = 0; i < count; i++) {
1301                 contacts_record_h company = NULL;
1302
1303                 GString *str;
1304
1305                 gchar *name = NULL;
1306                 gchar *department = NULL;
1307
1308                 gint name_status;
1309                 gint department_status;
1310
1311                 status = contacts_record_get_child_record_at_p(contact,
1312                                 _contacts_contact.company, i, &company);
1313
1314                 if (status != CONTACTS_ERROR_NONE)
1315                         continue;
1316
1317
1318                 name_status = contacts_record_get_str_p(company,
1319                                 _contacts_company.name,
1320                                 &name);
1321
1322                 department_status = contacts_record_get_str_p(company,
1323                                 _contacts_company.department,
1324                                 &department);
1325
1326                 if ((name_status != CONTACTS_ERROR_NONE) &&
1327                                 (department_status != CONTACTS_ERROR_NONE))
1328                         continue;
1329
1330                 str = g_string_new(NULL);
1331
1332                 if (name) {
1333                         gchar *escaped;
1334
1335                         escaped = __bluetooth_pb_vcard_escape(name);
1336                         g_string_append(str, escaped);
1337                         g_free(escaped);
1338                 }
1339
1340                 g_string_append(str, ";");
1341
1342                 if (department) {
1343                         gchar *escaped;
1344
1345                         escaped = __bluetooth_pb_vcard_escape(department);
1346                         g_string_append(str, escaped);
1347                         g_free(escaped);
1348                 }
1349
1350                 __bluetooth_pb_vcard_append_qp_encode_v21(string, "ORG", NULL,
1351                                                                 str->str);
1352
1353                 g_string_free(str, TRUE);
1354
1355         }
1356         FN_END;
1357 }
1358
1359 static void __bluetooth_pb_vcard_append_note_v21(GString *string,
1360                                                 contacts_record_h contact)
1361 {
1362         FN_START;
1363         gint count = 0;
1364
1365         gint status;
1366         gint i;
1367
1368         status = contacts_record_get_child_record_count(contact,
1369                         _contacts_contact.note,
1370                         &count);
1371
1372         if (status != CONTACTS_ERROR_NONE)
1373                 return;
1374
1375         for (i = 0; i < count; i++) {
1376                 contacts_record_h note = NULL;
1377
1378                 char *tmp = NULL;
1379                 gchar *escaped;
1380
1381                 status = contacts_record_get_child_record_at_p(contact,
1382                                 _contacts_contact.note, i, &note);
1383
1384                 if (status != CONTACTS_ERROR_NONE)
1385                         continue;
1386
1387                 status = contacts_record_get_str_p(note,
1388                                 _contacts_note.note,
1389                                 &tmp);
1390
1391                 if (status != CONTACTS_ERROR_NONE)
1392                         continue;
1393
1394                 escaped = __bluetooth_pb_vcard_escape(tmp);
1395                 __bluetooth_pb_vcard_append_qp_encode_v21(string, "NOTE", NULL,
1396                                                                 escaped);
1397
1398                 g_free(escaped);
1399         }
1400         FN_END;
1401 }
1402
1403 static void __bluetooth_pb_vcard_append_rev_v21(GString *string,
1404                                                 contacts_record_h contact)
1405 {
1406         FN_START;
1407         gint time = 0;
1408         gint status;
1409
1410         gchar *rev;
1411         struct tm result;
1412
1413         status = contacts_record_get_int(contact,
1414                         _contacts_contact.changed_time,
1415                         &time);
1416
1417         if (status != CONTACTS_ERROR_NONE)
1418                 return;
1419
1420         if (time <= 0)
1421                 return;
1422
1423         gmtime_r((const time_t *)(&time), &result);
1424
1425         rev = g_strdup_printf("%04d-%02d-%02dT%02d:%02d:%02dZ",
1426                         (1900 + result.tm_year), (1 + result.tm_mon),
1427                         result.tm_mday, result.tm_hour, result.tm_min,
1428                         result.tm_sec);
1429
1430         __bluetooth_pb_vcard_append_qp_encode_v21(string, "REV", NULL, rev);
1431
1432         g_free(rev);
1433         FN_END;
1434 }
1435
1436 static void __bluetooth_pb_vcard_append_url_v21(GString *string,
1437                                                 contacts_record_h contact)
1438 {
1439         FN_START;
1440         gint count = 0;
1441
1442         gint i;
1443         gint status;
1444
1445         status = contacts_record_get_child_record_count(contact,
1446                         _contacts_contact.url,
1447                         &count);
1448
1449         if (status != CONTACTS_ERROR_NONE)
1450                 return;
1451
1452         for (i = 0; i < count; i++) {
1453                 contacts_record_h url = NULL;
1454
1455                 gchar *tmp = NULL;
1456                 gchar *escaped;
1457
1458                 status = contacts_record_get_child_record_at_p(contact,
1459                                 _contacts_contact.url, i, &url);
1460
1461                 if (status != CONTACTS_ERROR_NONE)
1462                         return;
1463
1464                 if (url == NULL)
1465                         continue;
1466
1467                 status = contacts_record_get_str_p(url,
1468                                 _contacts_url.url,
1469                                 &tmp);
1470
1471                 if (status != CONTACTS_ERROR_NONE)
1472                         continue;
1473
1474                 escaped = __bluetooth_pb_vcard_escape(tmp);
1475                 __bluetooth_pb_vcard_append_qp_encode_v21(string, "URL", NULL,
1476                                                                 escaped);
1477
1478                 g_free(escaped);
1479         }
1480         FN_END;
1481 }
1482
1483 static void __bluetooth_pb_vcard_append_uid_v21(GString *string,
1484                                                 contacts_record_h contact)
1485 {
1486         FN_START;
1487         int status;
1488
1489         gchar *uid = NULL;
1490         gchar *escaped;
1491
1492         status = contacts_record_get_str_p(contact,
1493                         _contacts_contact.uid,
1494                         &uid);
1495
1496         if (status != CONTACTS_ERROR_NONE)
1497                 return;
1498
1499         escaped = __bluetooth_pb_vcard_escape(uid);
1500         __bluetooth_pb_vcard_append_qp_encode_v21(string, "UID", NULL, escaped);
1501
1502         g_free(escaped);
1503         FN_END;
1504 }
1505 /* LCOV_EXCL_STOP */
1506
1507 static void __bluetooth_pb_vcard_append_v30(GString *string,
1508                                         const gchar *name,
1509                                         const gchar *param,
1510                                         const gchar *value)
1511 {
1512         FN_START;
1513         if (string == NULL)
1514                 return;
1515         if (name == NULL)
1516                 return;
1517
1518         g_string_append(string, name);
1519
1520         if (param)
1521                 g_string_append_printf(string, ";%s", param);
1522
1523         g_string_append(string, ":");
1524
1525         if (value)
1526                 g_string_append(string, value);
1527
1528         g_string_append(string, "\r\n");
1529         FN_END;
1530 }
1531
1532 /* LCOV_EXCL_START */
1533 static void __bluetooth_pb_vcard_remove_v30(GString *string,
1534                                         const gchar *property_name)
1535 {
1536         FN_START;
1537         gchar *pos = NULL;
1538         gchar *st_pos = NULL;
1539
1540         gboolean matched = FALSE;
1541
1542         if (string == NULL || property_name == NULL)
1543                 return;
1544
1545         pos = string->str;
1546
1547         while (*pos != '\0') {
1548                 if (matched == FALSE) {
1549                         if (g_ascii_strncasecmp(pos, "\r\n", 2) == 0) {
1550                                 gint attrlen = 0;
1551
1552                                 st_pos = pos;
1553                                 pos += 2;
1554
1555                                 attrlen = strlen(property_name);
1556                                 if (g_ascii_strncasecmp(pos, property_name,
1557                                                                 attrlen) == 0) {
1558                                         pos += attrlen;
1559
1560                                         if (*pos == ':' || *pos == ';') {
1561                                                 matched = TRUE;
1562                                                 pos++;
1563                                         }
1564                                 }
1565                                 continue;
1566                         }
1567                 } else {
1568                         if (g_ascii_strncasecmp(pos, "\r\n", 2) == 0) {
1569                                 pos += 2;
1570
1571                                 if (*pos != ' ' && *pos != '\t') {
1572                                         /* +2 means move over \r\n */
1573                                         g_string_erase(string,
1574                                                 (st_pos+2)-(string->str),
1575                                                 pos-(st_pos+2));
1576
1577                                         pos = st_pos;
1578                                         matched = FALSE;
1579                                 }
1580                                 continue;
1581                         }
1582                 }
1583
1584                 pos++;
1585         }
1586         FN_END;
1587 }
1588
1589 static gchar *__bluetooth_pb_vcard_filter_v30(const gchar *vcard,
1590                                         guint64 filter)
1591 {
1592         FN_START;
1593         GString *string = NULL;
1594
1595         if (vcard == NULL)
1596                 return NULL;
1597
1598         string = g_string_new(vcard);
1599
1600         if ((filter & VCARD_BDAY) == 0)
1601                 __bluetooth_pb_vcard_remove_v30(string, "BDAY");
1602
1603         if ((filter & VCARD_ADR) == 0)
1604                 __bluetooth_pb_vcard_remove_v30(string, "ADR");
1605
1606         if ((filter & VCARD_EMAIL) == 0)
1607                 __bluetooth_pb_vcard_remove_v30(string, "EMAIL");
1608
1609         if ((filter & VCARD_TITLE) == 0)
1610                 __bluetooth_pb_vcard_remove_v30(string, "TITLE");
1611
1612         if ((filter & VCARD_ROLE) == 0)
1613                 __bluetooth_pb_vcard_remove_v30(string, "ROLE");
1614
1615         if ((filter & VCARD_ORG) == 0)
1616                 __bluetooth_pb_vcard_remove_v30(string, "ORG");
1617
1618         if ((filter & VCARD_NOTE) == 0)
1619                 __bluetooth_pb_vcard_remove_v30(string, "NOTE");
1620
1621         if ((filter & VCARD_REV) == 0)
1622                 __bluetooth_pb_vcard_remove_v30(string, "REV");
1623
1624         if ((filter & VCARD_URL) == 0)
1625                 __bluetooth_pb_vcard_remove_v30(string, "URL");
1626
1627         if ((filter & VCARD_UID) == 0)
1628                 __bluetooth_pb_vcard_remove_v30(string, "UID");
1629
1630         if ((filter & VCARD_NICKNAME) == 0)
1631                 __bluetooth_pb_vcard_remove_v30(string, "NICKNAME");
1632
1633         FN_END;
1634         return g_string_free(string, FALSE);
1635 }
1636
1637 static gchar *__bluetooth_pb_vcard_real_contact_valist_v21(gint person_id,
1638                                                         gint phonelog_id,
1639                                                         guint64 filter,
1640                                                         const gchar *first_name,
1641                                                         va_list args)
1642 {
1643         FN_START;
1644         contacts_record_h person = NULL;
1645         contacts_record_h contact = NULL;
1646
1647         GString *str = NULL;
1648
1649         gint contact_id = 0;
1650         gint status;
1651
1652         guint64 f = filter;
1653
1654         const gchar *name = first_name;
1655
1656         status = contacts_db_get_record(_contacts_person._uri,
1657                         person_id,
1658                         &person);
1659
1660         if (status != CONTACTS_ERROR_NONE)
1661                 return NULL;
1662
1663         status = contacts_record_get_int(person,
1664                         _contacts_person.display_contact_id,
1665                         &contact_id);
1666
1667         if (status != CONTACTS_ERROR_NONE)
1668                 return NULL;
1669
1670         status = contacts_db_get_record(_contacts_contact._uri,
1671                         contact_id,
1672                         &contact);
1673
1674         if (status != CONTACTS_ERROR_NONE) {
1675                 contacts_record_destroy(person, TRUE);
1676                 return NULL;;
1677         }
1678
1679         if (f == 0)
1680                 f = ~f;
1681
1682         DBG("filter[%x]\n", filter);
1683
1684         str = g_string_new("BEGIN:VCARD\r\nVERSION:2.1\r\n");
1685
1686         /* N, TEL is default */
1687         __bluetooth_pb_vcard_append_n_v21(str, contact);
1688
1689         if (phonelog_id > 0) {
1690                 gchar *number;
1691
1692                 number = _bluetooth_pb_number_from_phonelog_id(phonelog_id);
1693                 __bluetooth_pb_vcard_append_qp_encode_v21(str, "TEL", "X-0",
1694                                                                         number);
1695                 g_free(number);
1696
1697
1698         } else {
1699                 __bluetooth_pb_vcard_append_tel_v21(str, contact);
1700         }
1701
1702         if (f & VCARD_FN)
1703                 __bluetooth_pb_vcard_append_fn_v21(str, person);
1704 /*      Need to check filter
1705         if (f & VCARD_SOUND)*/
1706                 __bluetooth_pb_vcard_append_phonetic_first_v21(str, contact);
1707         if (f & VCARD_PHOTO)
1708                 __bluetooth_pb_vcard_append_photo_v21(str, person);
1709         if (f & VCARD_BDAY)
1710                 __bluetooth_pb_vcard_append_bday_v21(str, contact);
1711         if (f & VCARD_ADR)
1712                 __bluetooth_pb_vcard_append_adr_v21(str, contact);
1713         if (f & VCARD_EMAIL)
1714                 __bluetooth_pb_vcard_append_email_v21(str, contact);
1715         if (f & VCARD_TITLE)
1716                 __bluetooth_pb_vcard_append_title_v21(str, contact);
1717         if (f & VCARD_ROLE)
1718                 __bluetooth_pb_vcard_append_role_v21(str, contact);
1719         if (f & VCARD_ORG)
1720                 __bluetooth_pb_vcard_append_org_v21(str, contact);
1721         if (f & VCARD_NOTE)
1722                 __bluetooth_pb_vcard_append_note_v21(str, contact);
1723         if (f & VCARD_REV)
1724                 __bluetooth_pb_vcard_append_rev_v21(str, contact);
1725         if (f & VCARD_URL)
1726                 __bluetooth_pb_vcard_append_url_v21(str, contact);
1727         if (f & VCARD_UID)
1728                 __bluetooth_pb_vcard_append_uid_v21(str, contact);
1729
1730         while (name) {
1731                 const gchar *param = va_arg(args, const gchar *);
1732                 const gchar *value = va_arg(args, const gchar *);
1733
1734                 if (value) {
1735                         gchar *escaped = NULL;
1736
1737                         escaped = __bluetooth_pb_vcard_escape(value);
1738                         __bluetooth_pb_vcard_append_qp_encode_v21(str, name,
1739                                                                 param, escaped);
1740
1741                         g_free(escaped);
1742                 }
1743
1744                 name = va_arg(args, const gchar *);
1745         }
1746
1747         g_string_append(str, "END:VCARD\r\n");
1748
1749         contacts_record_destroy(contact, TRUE);
1750         contacts_record_destroy(person, TRUE);
1751
1752         FN_END;
1753         return g_string_free(str, FALSE);
1754 }
1755 /* LCOV_EXCL_STOP */
1756
1757 static gchar *__bluetooth_pb_vcard_real_contact_valist_v30(gint person_id,
1758                                                         gint phonelog_id,
1759                                                         guint64 filter,
1760                                                         const gchar *first_name,
1761                                                         va_list args)
1762 {
1763         FN_START;
1764         contacts_record_h person = NULL;
1765
1766         GString *str = NULL;
1767
1768         gint status;
1769
1770         const gchar *name = first_name;
1771         gchar *vcard = NULL;
1772
1773         status = contacts_db_get_record(_contacts_person._uri,
1774                         person_id,
1775                         &person);
1776
1777         if (status != CONTACTS_ERROR_NONE)
1778                 return NULL;
1779
1780         /* LCOV_EXCL_START */
1781         status = contacts_vcard_make_from_person(person, &vcard);
1782
1783         if (status != CONTACTS_ERROR_NONE)
1784                 return NULL;
1785
1786         /* removing the END:VCARD\r\n" to append extra data */
1787         str = g_string_new_len(vcard, (strlen(vcard)-11));
1788         g_free(vcard);
1789
1790         /* append contents on vcard */
1791         while (name) {
1792                 const gchar *param = va_arg(args, const gchar *);
1793                 const gchar *value = va_arg(args, const gchar *);
1794
1795                 __bluetooth_pb_vcard_append_v30(str, name, param, value);
1796
1797                 name = va_arg(args, const gchar *);
1798         }
1799
1800         /* if phonelog_id exist, we shall show only the phone number, which was
1801            used for that phone log */
1802         if (phonelog_id > 0) {
1803                 gchar *number;
1804
1805                 __bluetooth_pb_vcard_remove_v30(str, "TEL");
1806
1807                 number = _bluetooth_pb_number_from_phonelog_id(phonelog_id);
1808                 __bluetooth_pb_vcard_append_v30(str, "TEL", NULL, number);
1809                 g_free(number);
1810         }
1811
1812         /* Remove Full contact image and add thumbnail image */
1813         __bluetooth_pb_vcard_remove_v30(str, "PHOTO");
1814         if (filter & VCARD_PHOTO)
1815                 __bluetooth_pb_vcard_append_photo_v21(str, person); /* Photo is same as vCard 2.1 */
1816
1817         /* Destroy contact record */
1818         status = contacts_record_destroy(person, TRUE);
1819         if (status != CONTACTS_ERROR_NONE)
1820                 ERR("Failed to destroy person");
1821
1822         g_string_append(str, "END:VCARD\r\n");
1823
1824         vcard = g_string_free(str, FALSE);
1825
1826         /* temporary fixed for some application crash */
1827         if (filter == 0)
1828                 filter = ~VCARD_NOTE;
1829
1830         if (filter) {
1831                 gchar *new_vcard = NULL;
1832
1833                 new_vcard = __bluetooth_pb_vcard_filter_v30(vcard, filter);
1834
1835                 if (new_vcard) {
1836                         g_free(vcard);
1837                         vcard = new_vcard;
1838                 }
1839         }
1840
1841         FN_END;
1842         return vcard;
1843         /* LCOV_EXCL_STOP */
1844 }
1845
1846
1847 static gchar *__bluetooth_pb_vcard_real_contact_with_properties(gint person_id,
1848                                                         gint phonelog_id,
1849                                                         guint64 filter,
1850                                                         guint8 format,
1851                                                         const gchar *first_name,
1852                                                         ...)
1853 {
1854         FN_START;
1855         DBG(" format [%d]\n", format);
1856         gchar *vcard = NULL;
1857         va_list args;
1858
1859         va_start(args, first_name);
1860
1861         switch (format) {
1862         case VCARD_FORMAT_3_0:
1863                 vcard = __bluetooth_pb_vcard_real_contact_valist_v30(person_id,
1864                                 phonelog_id, filter,
1865                                 first_name, args);
1866                 break;
1867         case VCARD_FORMAT_2_1:
1868         default:
1869                 vcard = __bluetooth_pb_vcard_real_contact_valist_v21(person_id,
1870                                 phonelog_id, filter,
1871                                 first_name, args);
1872                 break;
1873         }
1874
1875         va_end(args);
1876
1877         FN_END;
1878         return vcard;
1879 }
1880
1881 static gchar *__bluetooth_pb_vcard_real_call_v21(gint phonelog_id,
1882                                                 guint filter,
1883                                                 const char *attr)
1884 {
1885         FN_START;
1886         GString *str;
1887         gchar *number;
1888
1889         str = g_string_new("BEGIN:VCARD\r\nVERSION:2.1\r\n");
1890
1891         __bluetooth_pb_vcard_append_qp_encode_v21(str, "N", NULL, NULL);
1892
1893         number = _bluetooth_pb_number_from_phonelog_id(phonelog_id);
1894         __bluetooth_pb_vcard_append_qp_encode_v21(str, "TEL", "X-0", number);
1895         g_free(number);
1896
1897         /* LCOV_EXCL_START */
1898         if (((filter == 0) || (filter & VCARD_X_IRMC_CALL_DATETIME))
1899                         && attr) {
1900                 gchar *datetime = NULL;
1901
1902                 datetime = __bluetooth_pb_phonelog_datetime(phonelog_id);
1903                 __bluetooth_pb_vcard_append_qp_encode_v21(str,
1904                                                         "X-IRMC-CALL-DATETIME",
1905                                                         attr, datetime);
1906                 g_free(datetime);
1907         }
1908         /* LCOV_EXCL_STOP */
1909
1910         g_string_append(str, "END:VCARD\r\n");
1911
1912         FN_END;
1913         return g_string_free(str, FALSE);
1914 }
1915
1916 /* LCOV_EXCL_START */
1917 static gchar *__bluetooth_pb_vcard_real_call_v30(gint phonelog_id,
1918                                                 guint filter,
1919                                                 const gchar *attr)
1920 {
1921         FN_START;
1922         GString *str;
1923         gchar *number;
1924
1925         str = g_string_new("BEGIN:VCARD\r\nVERSION:3.0\r\n");
1926
1927         __bluetooth_pb_vcard_append_v30(str, "N", NULL, NULL);
1928         __bluetooth_pb_vcard_append_v30(str, "FN", NULL, NULL);
1929
1930         number = _bluetooth_pb_number_from_phonelog_id(phonelog_id);
1931         __bluetooth_pb_vcard_append_v30(str, "TEL", NULL, number);
1932         g_free(number);
1933
1934         if (((filter == 0) || (filter & VCARD_X_IRMC_CALL_DATETIME))
1935                         && attr) {
1936                 gchar *datetime = NULL;
1937
1938                 datetime = __bluetooth_pb_phonelog_datetime(phonelog_id);
1939                 __bluetooth_pb_vcard_append_v30(str,
1940                                 "X-IRMC-CALL-DATETIME", attr, datetime);
1941                 g_free(datetime);
1942         }
1943
1944         g_string_append(str, "END:VCARD\r\n");
1945
1946         FN_END;
1947         return g_string_free(str, FALSE);
1948 }
1949 /* LCOV_EXCL_STOP */
1950
1951 static gchar *__bluetooth_pb_vcard_real_call(gint phonelog_id,
1952                                         guint filter,
1953                                         guint8 format,
1954                                         const gchar *attr)
1955 {
1956         FN_START;
1957         gchar *vcard = NULL;
1958
1959         switch (format) {
1960         case VCARD_FORMAT_3_0:
1961                 vcard = __bluetooth_pb_vcard_real_call_v30(phonelog_id,
1962                                 filter, attr);
1963                 break;
1964         case VCARD_FORMAT_2_1:
1965         default:
1966                 vcard = __bluetooth_pb_vcard_real_call_v21(phonelog_id,
1967                                 filter, attr);
1968                 break;
1969         }
1970
1971         FN_END;
1972         return vcard;
1973 }
1974
1975 /* LCOV_EXCL_START */
1976 static gchar **__bluetooth_pb_contact_add_field_str(contacts_record_h record,
1977                                                 int *field,
1978                                                 gint field_size)
1979 {
1980         FN_START;
1981         gchar **strv;
1982
1983         gint status;
1984         gint i;
1985
1986         gboolean valid = FALSE;
1987
1988         /* check empty field */
1989         for (i = 0; i < field_size; i++) {
1990                 gchar *tmp = NULL;
1991
1992                 status = contacts_record_get_str_p(record, field[i], &tmp);
1993
1994                 if (status != CONTACTS_ERROR_NONE)
1995                         continue;
1996
1997                 if (tmp) {
1998                         valid = TRUE;
1999                         break;
2000                 }
2001         }
2002
2003         if (valid == FALSE)
2004                 return NULL;
2005
2006         strv = g_new0(gchar *, field_size + 1);
2007
2008         for (i = 0; i < field_size; i++) {
2009                 gchar *tmp;
2010
2011                 status = contacts_record_get_str_p(record, field[i], &tmp);
2012
2013                 if (status != CONTACTS_ERROR_NONE)
2014                         continue;
2015
2016                 if (tmp == NULL)
2017                         strv[i] = g_strdup("");
2018                 else
2019                         strv[i] = __bluetooth_pb_vcard_escape(tmp);
2020         }
2021
2022         FN_END;
2023         return strv;
2024 }
2025
2026 static gchar **__bluetooth_pb_contact_tel_param(contacts_record_h number)
2027 {
2028         FN_START;
2029         gchar **strv = NULL;
2030
2031         const gint TEL_PARAM_LEN = 13;
2032
2033         gint status;
2034         gint i = 0;
2035
2036         contacts_number_type_e type;
2037
2038         bool is_default = false;
2039
2040         status = contacts_record_get_bool(number, _contacts_number.is_default,
2041                         &is_default);
2042
2043         if (status != CONTACTS_ERROR_NONE)
2044                 return NULL;
2045
2046         status = contacts_record_get_int(number,
2047                         _contacts_number.type,
2048                         (gint *)&type);
2049
2050         if (status != CONTACTS_ERROR_NONE)
2051                 return NULL;
2052
2053         strv = g_new0(char *, TEL_PARAM_LEN + 1);/* tel param max size is 13 */
2054
2055         if (is_default) {
2056                 strv[i] = g_strdup("PREF");
2057                 i++;
2058         }
2059
2060         if (type & CONTACTS_NUMBER_TYPE_HOME) {
2061                 strv[i] = g_strdup("HOME");
2062                 i++;
2063         }
2064
2065         if (type & CONTACTS_NUMBER_TYPE_WORK) {
2066                 strv[i] = g_strdup("WORK");
2067                 i++;
2068         }
2069
2070         if (type & CONTACTS_NUMBER_TYPE_VOICE) {
2071                 strv[i] = g_strdup("VOICE");
2072                 i++;
2073         }
2074
2075         if (type & CONTACTS_NUMBER_TYPE_FAX) {
2076                 strv[i] = g_strdup("FAX");
2077                 i++;
2078         }
2079
2080         if (type & CONTACTS_NUMBER_TYPE_MSG) {
2081                 strv[i] = g_strdup("MSG");
2082                 i++;
2083         }
2084
2085         if (type & CONTACTS_NUMBER_TYPE_CELL) {
2086                 strv[i] = g_strdup("CELL");
2087                 i++;
2088         }
2089
2090         if (type & CONTACTS_NUMBER_TYPE_PAGER) {
2091                 strv[i] = g_strdup("PAGER");
2092                 i++;
2093         }
2094
2095         if (type & CONTACTS_NUMBER_TYPE_BBS) {
2096                 strv[i] = g_strdup("BBS");
2097                 i++;
2098         }
2099
2100         if (type & CONTACTS_NUMBER_TYPE_MODEM) {
2101                 strv[i] = g_strdup("MODEM");
2102                 i++;
2103         }
2104
2105         if (type & CONTACTS_NUMBER_TYPE_CAR) {
2106                 strv[i] = g_strdup("CAR");
2107                 i++;
2108         }
2109
2110         if (type & CONTACTS_NUMBER_TYPE_ISDN) {
2111                 strv[i] = g_strdup("ISDN");
2112                 i++;
2113         }
2114
2115         if (type & CONTACTS_NUMBER_TYPE_VIDEO) {
2116                 strv[i] = g_strdup("VIDEO");
2117                 i++;
2118         }
2119
2120         /* CTS_NUM_TYPE_PCS is not part of vcard2.1 */
2121         FN_END;
2122         return strv;
2123 }
2124
2125
2126 static gchar *__bluetooth_pb_contact_photo_type(const gchar *filename)
2127 {
2128         FN_START;
2129         gchar *filetype = NULL;
2130         gchar *ext = NULL;
2131
2132         if (g_file_test(filename, G_FILE_TEST_IS_REGULAR) == FALSE) {
2133                 ERR_SECURE("file does not regular:%s\n", filename);
2134                 return NULL;
2135         }
2136
2137         ext = strrchr(filename, '.');
2138         if (ext == NULL) {
2139                 ERR("file doesn't have extension\n");
2140                 return NULL;
2141         }
2142
2143         ext++;
2144
2145         if (g_ascii_strcasecmp(ext, "gif") == 0)
2146                 filetype = "GIF";
2147         else if (g_ascii_strcasecmp(ext, "cgm") == 0)
2148                 filetype = "CGM";
2149         else if (g_ascii_strcasecmp(ext, "wmf") == 0)
2150                 filetype = "WMF";
2151         else if (g_ascii_strcasecmp(ext, "bmp") == 0)
2152                 filetype = "BMP";
2153         else if (g_ascii_strcasecmp(ext, "met") == 0)
2154                 filetype = "MET";
2155         else if (g_ascii_strcasecmp(ext, "dib") == 0)
2156                 filetype = "DIB";
2157         else if (g_ascii_strcasecmp(ext, "pict") == 0 ||
2158                         g_ascii_strcasecmp(ext, "pct") == 0 ||
2159                         g_ascii_strcasecmp(ext, "pic") == 0)
2160                 filetype = "PICT";
2161         else if (g_ascii_strcasecmp(ext, "tiff") == 0 ||
2162                         g_ascii_strcasecmp(ext, "tif") == 0)
2163                 filetype = "TIFF";
2164         else if (g_ascii_strcasecmp(ext, "ps") == 0)
2165                 filetype = "PS";
2166         else if (g_ascii_strcasecmp(ext, "pdf") == 0)
2167                 filetype = "PDF";
2168         else if (g_ascii_strcasecmp(ext, "jpeg") == 0 ||
2169                         g_ascii_strcasecmp(ext, "jpg") == 0 ||
2170                         g_ascii_strcasecmp(ext, "jpe") == 0)
2171                 filetype = "JPEG";
2172         else if (g_ascii_strcasecmp(ext, "mpeg") == 0 ||
2173                         g_ascii_strcasecmp(ext, "mpg") == 0)
2174                 filetype = "MPEG";
2175         else if (g_ascii_strcasecmp(ext, "m2v") == 0)
2176                 filetype = "MPEG2";
2177         else if (g_ascii_strcasecmp(ext, "avi") == 0)
2178                 filetype = "AVI";
2179         else if (g_ascii_strcasecmp(ext, "mov") == 0)
2180                 filetype = "QTIME";
2181         else if (g_ascii_strcasecmp(ext, "png") == 0)
2182                 filetype = "PNG";
2183
2184         FN_END;
2185         return g_strdup(filetype);
2186 }
2187
2188 static gchar **__bluetooth_pb_contact_addr(contacts_record_h address)
2189 {
2190         FN_START;
2191         const gint ADDR_LEN = 7;
2192
2193         gchar **strv = NULL;
2194
2195         gint addr[] = { _contacts_address.postbox,
2196                         _contacts_address.extended,
2197                         _contacts_address.street,
2198                         _contacts_address.locality,
2199                         _contacts_address.region,
2200                         _contacts_address.postal_code,
2201                         _contacts_address.country };
2202
2203         strv = __bluetooth_pb_contact_add_field_str(address,
2204                         addr, ADDR_LEN);
2205         FN_END;
2206         return strv;
2207 }
2208
2209 static gchar **__bluetooth_pb_contact_addr_param(contacts_record_h address)
2210 {
2211         FN_START;
2212         contacts_address_type_e type;
2213
2214         gint status;
2215         gint i = 0;
2216
2217         gchar **strv = NULL;
2218
2219         status = contacts_record_get_int(address,
2220                         _contacts_address.type,
2221                         (gint *)&type);
2222
2223         if (status != CONTACTS_ERROR_NONE)
2224                 return NULL;
2225
2226         strv = g_new0(gchar *, 7);      /* ADDR param max size is 6 */
2227
2228         if (type & CONTACTS_ADDRESS_TYPE_HOME) {
2229                 strv[i] = g_strdup("HOME");
2230                 i++;
2231         }
2232         if (type & CONTACTS_ADDRESS_TYPE_WORK) {
2233                 strv[i] = g_strdup("WORK");
2234                 i++;
2235         }
2236         if (type & CONTACTS_ADDRESS_TYPE_DOM) {
2237                 strv[i] = g_strdup("DOM");
2238                 i++;
2239         }
2240         if (type & CONTACTS_ADDRESS_TYPE_INTL) {
2241                 strv[i] = g_strdup("INTL");
2242                 i++;
2243         }
2244         if (type & CONTACTS_ADDRESS_TYPE_POSTAL) {
2245                 strv[i] = g_strdup("POSTAL");
2246                 i++;
2247         }
2248         if (type & CONTACTS_ADDRESS_TYPE_PARCEL) {
2249                 strv[i] = g_strdup("PARCEL");
2250                 i++;
2251         }
2252         FN_END;
2253         return strv;
2254 }
2255
2256 static gchar *__bluetooth_pb_phonelog_datetime(gint phonelog_id)
2257 {
2258         FN_START;
2259         contacts_record_h phone_log;
2260
2261         char time_str[32] = {0,};
2262
2263         gint status;
2264         gint time = 0;
2265
2266         struct tm time_info;
2267
2268         status = contacts_db_get_record(_contacts_phone_log._uri,
2269                         phonelog_id,
2270                         &phone_log);
2271
2272         if (status != CONTACTS_ERROR_NONE)
2273                 return NULL;
2274
2275         status = contacts_record_get_int(phone_log,
2276                         _contacts_phone_log.log_time,
2277                         &time);
2278
2279         if (status != CONTACTS_ERROR_NONE)
2280                 return NULL;
2281
2282         if (time <= 0)
2283                 return NULL;
2284
2285         localtime_r((time_t *)&time, &time_info);
2286
2287         strftime(time_str, sizeof(time_str),
2288                         "%Y%m%dT%H%M%S", &time_info);
2289
2290         contacts_record_destroy(phone_log, TRUE);
2291
2292         FN_END;
2293         return g_strdup(time_str);
2294 }
2295
2296 static gchar *__bluetooth_pb_name_from_contact(contacts_record_h contact)
2297 {
2298         FN_START;
2299         contacts_record_h name = NULL;
2300
2301         GString *str;
2302         gint status;
2303         gint i;
2304
2305         gint name_size = 5;
2306         gint name_val[] = { _contacts_name.last,
2307                         _contacts_name.first,
2308                         _contacts_name.addition,
2309                         _contacts_name.prefix,
2310                         _contacts_name.suffix };
2311
2312
2313         status = contacts_record_get_child_record_at_p(contact,
2314                         _contacts_contact.name, 0, &name);
2315
2316         if (status != CONTACTS_ERROR_NONE)
2317                 return NULL;
2318
2319         str = g_string_new(NULL);
2320
2321         for (i = 0; i < name_size; i++) {
2322                 gchar *tmp = NULL;
2323                 gchar *escape = NULL;
2324
2325                 if (i > 0)
2326                         g_string_append_c(str, ';');
2327
2328                 status = contacts_record_get_str_p(name, name_val[i], &tmp);
2329
2330                 if (status != CONTACTS_ERROR_NONE)
2331                         continue;
2332
2333                 escape = __bluetooth_pb_vcard_escape(tmp);
2334                 g_string_append(str, escape);
2335
2336                 g_free(escape);
2337         }
2338
2339         FN_END;
2340         return g_string_free(str, FALSE);
2341 }
2342
2343 static gchar *__bluetooth_pb_phonetic_name_from_contact(contacts_record_h contact)
2344 {
2345         FN_START;
2346         contacts_record_h name = NULL;
2347
2348         GString *str;
2349
2350         gint status;
2351
2352         gchar *phonetic_first = NULL;
2353         gchar *phonetic_last = NULL;
2354         gchar *escape = NULL;
2355
2356         status = contacts_record_get_child_record_at_p(contact,
2357                         _contacts_contact.name, 0, &name);
2358
2359         if (status != CONTACTS_ERROR_NONE)
2360                 return NULL;
2361
2362         status = contacts_record_get_str_p(name, _contacts_name.phonetic_first, &phonetic_first);
2363
2364         if (status != CONTACTS_ERROR_NONE)
2365                 return NULL;
2366
2367         if (phonetic_first == NULL)
2368                 return NULL;
2369
2370         str = g_string_new(NULL);
2371
2372         status = contacts_record_get_str_p(name, _contacts_name.phonetic_last, &phonetic_last);
2373
2374         if ((status == CONTACTS_ERROR_NONE) && (phonetic_last != NULL)) {
2375                 escape = __bluetooth_pb_vcard_escape(phonetic_last);
2376                 g_string_append(str, escape);
2377                 g_free(escape);
2378                 g_string_append_c(str, ' ');
2379         }
2380
2381         escape = __bluetooth_pb_vcard_escape(phonetic_first);
2382         g_string_append(str, escape);
2383
2384         g_free(escape);
2385         g_string_append_c(str, ';');
2386         g_string_append_c(str, ';');
2387         g_string_append_c(str, ';');
2388         g_string_append_c(str, ';');
2389
2390         FN_END;
2391         return g_string_free(str, FALSE);
2392 }
2393
2394
2395 static gchar *__bluetooth_pb_number_from_contact(contacts_record_h contact)
2396 {
2397         FN_START;
2398         gint count = 0;
2399
2400         gint status;
2401         gint i;
2402
2403         gchar *str = NULL;
2404
2405         status = contacts_record_get_child_record_count(contact,
2406                         _contacts_contact.number,
2407                         &count);
2408
2409         if (status != CONTACTS_ERROR_NONE)
2410                 return NULL;
2411
2412         for (i = 0; i < count; i++) {
2413                 contacts_record_h number = NULL;
2414
2415                 gchar *tmp = NULL;
2416
2417                 bool is_default = false;
2418
2419                 status = contacts_record_get_child_record_at_p(contact,
2420                                 _contacts_contact.number, i, &number);
2421
2422                 if (status != CONTACTS_ERROR_NONE)
2423                         continue;
2424
2425                 status = contacts_record_get_bool(number,
2426                                 _contacts_number.is_default,
2427                                 &is_default);
2428
2429                 if (status != CONTACTS_ERROR_NONE)
2430                         continue;
2431
2432                 if (is_default == FALSE)
2433                         continue;
2434
2435                 status = contacts_record_get_str_p(number,
2436                                 _contacts_number.number,
2437                                 &tmp);
2438
2439                 if (status != CONTACTS_ERROR_NONE)
2440                         continue;
2441
2442                 if (tmp) {
2443                         str = g_strdup(tmp);
2444                         break;
2445                 }
2446         }
2447
2448         /* get first number */
2449         if (str == NULL) {
2450                 gchar *tmp = NULL;
2451
2452                 contacts_record_h number = NULL;
2453
2454                 status = contacts_record_get_child_record_at_p(contact,
2455                                 _contacts_contact.number, 0, &number);
2456
2457                 if (status != CONTACTS_ERROR_NONE)
2458                         return NULL;
2459
2460                 status = contacts_record_get_str_p(number,
2461                                 _contacts_number.number,
2462                                 &tmp);
2463
2464                 if (status != CONTACTS_ERROR_NONE)
2465                         return NULL;
2466
2467                 str = g_strdup(tmp);
2468         }
2469
2470         FN_END;
2471         return str;
2472 }
2473 /* LCOV_EXCL_STOP */
2474
2475 static gint __bluetooth_pb_person_id_from_phonelog_id(gint phonelog_id)
2476 {
2477         FN_START;
2478         contacts_query_h query = NULL;
2479         contacts_filter_h filter = NULL;
2480         contacts_list_h record_list = NULL;
2481
2482         contacts_record_h phone_log = NULL;
2483         contacts_record_h record = NULL;
2484
2485         gint status;
2486         gint person_id = 0;
2487
2488         status = contacts_db_get_record(_contacts_phone_log._uri,
2489                         phonelog_id,
2490                         &phone_log);
2491
2492         if (status != CONTACTS_ERROR_NONE)
2493                 return 0;
2494
2495         /* LCOV_EXCL_START */
2496         status = contacts_record_get_int(phone_log,
2497                         _contacts_phone_log.person_id,
2498                         &person_id);
2499
2500         if (status != CONTACTS_ERROR_NONE) {
2501                 contacts_record_destroy(phone_log, TRUE);
2502                 return 0;
2503         }
2504
2505         contacts_record_destroy(phone_log, TRUE);
2506
2507         if (person_id)
2508                 return person_id;
2509
2510         status = contacts_filter_create(_contacts_person_phone_log._uri,
2511                         &filter);
2512
2513         if (status != CONTACTS_ERROR_NONE)
2514                 return 0;
2515
2516
2517         status = contacts_filter_add_int(filter,
2518                         _contacts_person_phone_log.log_id,
2519                         CONTACTS_MATCH_EQUAL,
2520                         phonelog_id);
2521
2522         if (status != CONTACTS_ERROR_NONE)
2523                 goto done;
2524
2525         status = contacts_query_create(_contacts_person_phone_log._uri, &query);
2526
2527         if (status != CONTACTS_ERROR_NONE)
2528                 goto done;
2529
2530         status = contacts_query_set_filter(query, filter);
2531
2532         if (status != CONTACTS_ERROR_NONE)
2533                 goto done;
2534
2535         status = contacts_db_get_records_with_query(query, -1, -1,
2536                                                                 &record_list);
2537
2538         if (status != CONTACTS_ERROR_NONE)
2539                 goto done;
2540
2541         status = contacts_list_first(record_list);
2542
2543         if (status != CONTACTS_ERROR_NONE)
2544                 goto done;
2545
2546         status = contacts_list_get_current_record_p(record_list, &record);
2547
2548         if (status != CONTACTS_ERROR_NONE)
2549                 goto done;
2550
2551         status = contacts_record_get_int(record,
2552                         _contacts_person_phone_log.person_id,
2553                         &person_id);
2554
2555         if (status != CONTACTS_ERROR_NONE)
2556                 goto done;
2557
2558 done:
2559         if (record_list != NULL)
2560                 contacts_list_destroy(record_list, TRUE);
2561
2562         contacts_filter_destroy(filter);
2563
2564         if (query != NULL)
2565                 contacts_query_destroy(query);
2566
2567         FN_END;
2568         return person_id;
2569         /* LCOV_EXCL_STOP */
2570 }
2571
2572 int _bluetooth_get_contact_addressbook(gint person_id)
2573 {
2574         contacts_record_h person = NULL;
2575         contacts_record_h contact = NULL;
2576         contacts_record_h addressbook = NULL;
2577
2578         char* addressbook_name = NULL;
2579         gint contact_id = 0;
2580         gint address_book_id = 0;
2581         gint status;
2582
2583         status = contacts_db_get_record(_contacts_person._uri,
2584                         person_id,
2585                         &person);
2586         if (status != CONTACTS_ERROR_NONE)
2587                 return PBAP_ADDRESSBOOK_PHONE; /* Default*/
2588
2589         /* LCOV_EXCL_START */
2590         status = contacts_record_get_int(person,
2591                         _contacts_person.display_contact_id,
2592                         &contact_id);
2593         contacts_record_destroy(person, TRUE);
2594
2595         if (status != CONTACTS_ERROR_NONE)
2596                 return PBAP_ADDRESSBOOK_PHONE; /* Default*/
2597
2598         status = contacts_db_get_record(_contacts_contact._uri,
2599                         contact_id,
2600                         &contact);
2601         if (status != CONTACTS_ERROR_NONE)
2602                 return PBAP_ADDRESSBOOK_PHONE; /* Default*/
2603
2604         status = contacts_record_get_int(contact,
2605                         _contacts_contact.address_book_id,
2606                         &address_book_id);
2607         contacts_record_destroy(contact, TRUE);
2608
2609         if (status != CONTACTS_ERROR_NONE)
2610                 return PBAP_ADDRESSBOOK_PHONE; /* Default*/
2611
2612         status = contacts_db_get_record(_contacts_address_book._uri,
2613                         address_book_id,
2614                         &addressbook);
2615         if (status != CONTACTS_ERROR_NONE)
2616                 return PBAP_ADDRESSBOOK_PHONE; /* Default*/
2617
2618         status = contacts_record_get_str_p(addressbook, _contacts_address_book.name,
2619                                                 &addressbook_name);
2620         contacts_record_destroy(addressbook, TRUE);
2621
2622         if (status != CONTACTS_ERROR_NONE)
2623                 return PBAP_ADDRESSBOOK_PHONE; /* Default*/
2624
2625         if (address_book_id == 0 || _bt_is_sim_addressbook(addressbook_name) == false)
2626                 return PBAP_ADDRESSBOOK_PHONE;
2627
2628         return PBAP_ADDRESSBOOK_SIM;
2629         /* LCOV_EXCL_STOP */
2630 }
2631 /* API for vcard */
2632 gchar *_bluetooth_pb_vcard_contact(gint person_id,
2633                                 guint64 filter,
2634                                 guint8 format)
2635 {
2636         FN_START;
2637         gchar *str = NULL;
2638
2639         if (person_id <= 0)
2640                 return NULL;
2641
2642         str = __bluetooth_pb_vcard_real_contact_with_properties(person_id, 0,
2643                         filter, format,
2644                         NULL);
2645         FN_END;
2646         return str;
2647 }
2648
2649 gchar *_bluetooth_pb_vcard_contact_owner(const gchar *number,
2650                                         guint64 filter,
2651                                         guint8 format)
2652 {
2653         FN_START;
2654         GString *str = g_string_new("BEGIN:VCARD\r\n");
2655         gchar *fn;
2656         gchar *name;
2657
2658         fn = _bluetooth_pb_owner_name();
2659         name = g_strdup_printf("%s;;;;", fn);
2660
2661         switch (format) {
2662         case VCARD_FORMAT_3_0:
2663                 g_string_append(str, "VERSION:3.0\r\n");
2664
2665                 __bluetooth_pb_vcard_append_v30(str, "N", NULL, name);
2666                 __bluetooth_pb_vcard_append_v30(str, "FN", NULL, fn);
2667                 __bluetooth_pb_vcard_append_v30(str, "TEL", "TYPE=CELL",
2668                                                                         number);
2669                 break;
2670         case VCARD_FORMAT_2_1:
2671         default:
2672                 g_string_append(str, "VERSION:2.1\r\n");
2673
2674                 __bluetooth_pb_vcard_append_qp_encode_v21(str, "N", NULL, name);
2675
2676                 if (filter == 0 || (filter & VCARD_FN))
2677                         __bluetooth_pb_vcard_append_qp_encode_v21(str, "FN",
2678                                                                 NULL, fn);
2679
2680                 __bluetooth_pb_vcard_append_qp_encode_v21(str, "TEL", "CELL",
2681                                                                         number);
2682                 break;
2683
2684         }
2685
2686         g_string_append(str, "END:VCARD\r\n");
2687
2688         g_free(fn);
2689         g_free(name);
2690
2691         FN_END;
2692         return g_string_free(str, FALSE);
2693 }
2694
2695 gchar *_bluetooth_pb_vcard_call(gint phonelog_id,
2696                                 guint64 filter,
2697                                 guint8 format,
2698                                 const gchar *attr)
2699 {
2700         FN_START;
2701         gint person_id = 0;
2702
2703         gchar *str = NULL;
2704
2705         if (attr == NULL) {
2706                 ERR("Unknown attribute type ignored\n");
2707                 return NULL;
2708         }
2709
2710         person_id = __bluetooth_pb_person_id_from_phonelog_id(phonelog_id);
2711
2712         DBG("person_id %d\n", person_id);
2713
2714         if (person_id) {
2715                 /* LCOV_EXCL_START */
2716                 if (filter == 0 || (filter & VCARD_X_IRMC_CALL_DATETIME)) {
2717                         gchar *datetime = NULL;
2718
2719                         datetime = __bluetooth_pb_phonelog_datetime(
2720                                                                 phonelog_id);
2721
2722                         str = __bluetooth_pb_vcard_real_contact_with_properties(
2723                                         person_id,
2724                                         phonelog_id,
2725                                         filter, format,
2726                                         "X-IRMC-CALL-DATETIME", attr, datetime,
2727                                         NULL);
2728
2729                         if (datetime)
2730                                 g_free(datetime);
2731                 } else {
2732                         str = __bluetooth_pb_vcard_real_contact_with_properties(
2733                                         person_id,
2734                                         phonelog_id,
2735                                         filter, format,
2736                                         NULL);
2737                 }
2738                 /* LCOV_EXCL_STOP */
2739         } else
2740                 str = __bluetooth_pb_vcard_real_call(phonelog_id, filter,
2741                                                                 format, attr);
2742
2743         FN_END;
2744         return str;
2745 }
2746
2747 gchar *_bluetooth_pb_fn_from_person_id(gint person_id)
2748 {
2749         FN_START;
2750         contacts_record_h person = NULL;
2751
2752         gint status;
2753
2754         gchar *str = NULL;
2755
2756         status = contacts_db_get_record(_contacts_person._uri,
2757                         person_id,
2758                         &person);
2759
2760         if (status != CONTACTS_ERROR_NONE)
2761                 return NULL;
2762
2763         /* LCOV_EXCL_START */
2764         status = contacts_record_get_str(person,
2765                         _contacts_person.display_name,
2766                         &str);
2767
2768         if (status != CONTACTS_ERROR_NONE)
2769                 return NULL;
2770
2771         contacts_record_destroy(person, TRUE);
2772
2773         FN_END;
2774         return str;
2775         /* LCOV_EXCL_STOP */
2776 }
2777
2778 gchar *_bluetooth_pb_name_from_person_id(gint person_id)
2779 {
2780         FN_START;
2781         contacts_record_h person = NULL;
2782         contacts_record_h contact = NULL;
2783
2784         gint status;
2785         gint contact_id = 0;
2786
2787         gchar *str;
2788
2789         status = contacts_db_get_record(_contacts_person._uri,
2790                         person_id,
2791                         &person);
2792
2793         if (status != CONTACTS_ERROR_NONE)
2794                 return NULL;
2795
2796         /* LCOV_EXCL_START */
2797         status = contacts_record_get_int(person,
2798                         _contacts_person.display_contact_id,
2799                         &contact_id);
2800
2801         if (status != CONTACTS_ERROR_NONE) {
2802                 contacts_record_destroy(person, TRUE);
2803                 return NULL;
2804         }
2805
2806         status = contacts_db_get_record(_contacts_contact._uri,
2807                         contact_id,
2808                         &contact);
2809
2810         if (status != CONTACTS_ERROR_NONE) {
2811                 contacts_record_destroy(person, TRUE);
2812                 return NULL;
2813         }
2814
2815         str = __bluetooth_pb_name_from_contact(contact);
2816
2817         contacts_record_destroy(contact, TRUE);
2818         contacts_record_destroy(person, TRUE);
2819         /* LCOV_EXCL_STOP */
2820
2821         FN_END;
2822         return str;
2823 }
2824
2825 gchar *_bluetooth_pb_number_from_person_id(gint person_id)
2826 {
2827         FN_START;
2828         contacts_record_h person = NULL;
2829         contacts_record_h contact = NULL;
2830
2831         gint status;
2832         gint contact_id = 0;
2833
2834         gchar *str;
2835
2836         status = contacts_db_get_record(_contacts_person._uri,
2837                         person_id,
2838                         &person);
2839
2840         if (status != CONTACTS_ERROR_NONE)
2841                 return NULL;
2842
2843         /* LCOV_EXCL_START */
2844         status = contacts_record_get_int(person,
2845                         _contacts_person.display_contact_id,
2846                         &contact_id);
2847
2848         if (status != CONTACTS_ERROR_NONE) {
2849                 contacts_record_destroy(person, TRUE);
2850                 return NULL;
2851         }
2852
2853         status = contacts_db_get_record(_contacts_contact._uri,
2854                         contact_id,
2855                         &contact);
2856
2857         if (status != CONTACTS_ERROR_NONE) {
2858                 contacts_record_destroy(person, TRUE);
2859                 return NULL;
2860         }
2861
2862         str = __bluetooth_pb_number_from_contact(contact);
2863
2864         contacts_record_destroy(contact, TRUE);
2865         contacts_record_destroy(person, TRUE);
2866         /* LCOV_EXCL_STOP */
2867
2868         FN_END;
2869         return str;
2870 }
2871
2872 gchar *_bluetooth_pb_fn_from_phonelog_id(gint phonelog_id)
2873 {
2874         FN_START;
2875         gint person_id = 0;
2876         gchar *str = NULL;
2877
2878         person_id = __bluetooth_pb_person_id_from_phonelog_id(phonelog_id);
2879
2880         if (person_id > 0)
2881                 str = _bluetooth_pb_fn_from_person_id(person_id);
2882         else
2883                 str = g_strdup("");
2884
2885         FN_END;
2886         return str;
2887 }
2888
2889 gchar *_bluetooth_pb_name_from_phonelog_id(gint phonelog_id)
2890 {
2891         FN_START;
2892         gint person_id = 0;
2893         gchar *str = NULL;
2894
2895         person_id = __bluetooth_pb_person_id_from_phonelog_id(phonelog_id);
2896
2897         if (person_id > 0)
2898                 str = _bluetooth_pb_name_from_person_id(person_id);
2899         else {
2900                 gchar *tmp;
2901
2902                 tmp = _bluetooth_pb_number_from_phonelog_id(phonelog_id);
2903                 str = g_strdup_printf("%s;;;;", tmp);
2904
2905                 g_free(tmp);
2906         }
2907
2908         FN_END;
2909         return str;
2910 }
2911
2912 gchar *_bluetooth_pb_number_from_phonelog_id(gint phonelog_id)
2913 {
2914         FN_START;
2915         contacts_record_h phone_log;
2916
2917         gint status;
2918
2919         gchar *str;
2920         gchar *tmp = NULL;
2921
2922         status = contacts_db_get_record(_contacts_phone_log._uri,
2923                         phonelog_id, &phone_log);
2924
2925         if (status != CONTACTS_ERROR_NONE)
2926                 return NULL;
2927
2928         /* LCOV_EXCL_START */
2929         status = contacts_record_get_str_p(phone_log,
2930                         _contacts_phone_log.address,
2931                         &tmp);
2932
2933         if (status != CONTACTS_ERROR_NONE) {
2934                 contacts_record_destroy(phone_log, TRUE);
2935                 return NULL;
2936         }
2937
2938         str = g_strdup(tmp);
2939
2940         contacts_record_destroy(phone_log, TRUE);
2941         /* LCOV_EXCL_STOP */
2942
2943         FN_END;
2944         return str;
2945 }
2946
2947 gchar *_bluetooth_pb_owner_name(void)
2948 {
2949         FN_START;
2950         gchar *name;
2951
2952         name = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
2953
2954         if (name == NULL)
2955                 name = g_strdup("My Name"); /* LCOV_EXCL_LINE */
2956
2957         FN_END;
2958         return name;
2959 }
2960
2961 bool _bt_is_sim_addressbook(const char *addressbook)
2962 {
2963         return g_str_has_prefix(addressbook, SIM_ADDRESSBOOK_PREFIX);
2964 }