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