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