08aaea26b92185c044a822c8e844392a94fe8d7c
[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 /* image util APIs will be deprecated in Tizen 5.0. So we should replace it to new API
762      https://developer.tizen.org/development/guides/native-application/media-and-camera/image-editing#decode
763      https://developer.tizen.org/development/guides/native-application/media-and-camera/image-editing#encode
764 */
765 #if 0
766 static image_util_rotation_e __bt_pbap_get_rotation_info(const char *path)
767 {
768         FN_START;
769         ExifData *ed = NULL;
770         ExifEntry *entry;
771         image_util_rotation_e rotation = IMAGE_UTIL_ROTATION_NONE;
772         int orientation = 0;
773
774         ed = exif_data_new_from_file(path);
775         if (ed == NULL) {
776                 ERR("exif_data_new_from_file : ExifData is NULL");
777                 return IMAGE_UTIL_ROTATION_NONE;
778         }
779
780         entry = exif_data_get_entry(ed, EXIF_TAG_ORIENTATION);
781         if (entry) {
782                 ExifByteOrder mByteOrder = exif_data_get_byte_order(ed);
783                 orientation = (int)exif_get_short(entry->data, mByteOrder);
784                 if (orientation < 0 || orientation > 8)
785                         orientation = 0;
786         }
787
788         exif_data_unref(ed);
789
790         switch (orientation) {
791         case 1: /* Top-left */
792                 rotation = IMAGE_UTIL_ROTATION_NONE;
793                 break;
794         case 2: /* Top-right */
795                 rotation = IMAGE_UTIL_ROTATION_FLIP_HORZ;
796                 break;
797         case 3: /* Bottom-right */
798                 rotation = IMAGE_UTIL_ROTATION_180;
799                 break;
800         case 4: /* Bottom-left */
801                 rotation = IMAGE_UTIL_ROTATION_FLIP_VERT;
802                 break;
803         case 6: /* Right-top */
804                 rotation = IMAGE_UTIL_ROTATION_90;
805                 break;
806         case 8: /* Left-bottom */
807                 rotation = IMAGE_UTIL_ROTATION_270;
808                 break;
809         case 5: /* Left-top */
810         case 7: /* Right-bottom */
811         case 0:
812         default:
813                 break;
814         };
815
816         FN_END;
817         return rotation;
818 }
819
820
821 static bool __bt_pbap_image_util_supported_jpeg_colorspace_cb(
822                         image_util_colorspace_e colorspace, void *user_data)
823 {
824         FN_START;
825         unsigned char *img_target = 0;
826         unsigned char *img_source = 0;
827         gchar *type = NULL;
828         gchar *param = NULL;
829         gchar *contents = NULL;
830         int width = 0;
831         int height = 0;
832         int resized_width = 0;
833         int resized_height = 0;
834         int dest_fd = 0;
835         unsigned int size_decode = 0;
836         image_util_rotation_e rotation;
837         image_util_error_e ret = 0;
838         gsize len = 0;
839
840         bt_image_info_t *info = (bt_image_info_t *)user_data;
841         rotation = __bt_pbap_get_rotation_info(info->src);
842         ret = image_util_decode_jpeg(info->src, colorspace, &img_source, &width,
843                                                         &height, &size_decode);
844         if (ret != IMAGE_UTIL_ERROR_NONE) {
845                 ERR("Can not decode");
846                 memset(info, 0x00, sizeof(bt_image_info_t));
847                 return true;
848         }
849
850         DBG("decoding completed width = %d, height = %d, size = %d\n", width,
851                                                         height, size_decode);
852         if (width > PBAP_IMAGE_THUMB_SIZE  || height > PBAP_IMAGE_THUMB_SIZE) {
853                 if (width <= 0 || height <= 0) {
854                         free(img_source);
855                         ERR("image size error(%d)", PBAP_IMAGE_THUMB_SIZE);
856                         memset(info, 0x00, sizeof(bt_image_info_t));
857                         return false;
858                 }
859
860                 if (width > height) {
861                         resized_width = PBAP_IMAGE_THUMB_SIZE ;
862                         resized_height = height * PBAP_IMAGE_THUMB_SIZE / width;
863                 } else {
864                         resized_height = PBAP_IMAGE_THUMB_SIZE;
865                         resized_width = width * PBAP_IMAGE_THUMB_SIZE / height;
866                 }
867
868                 if (resized_height % 8)
869                         resized_height += 8 - (resized_height % 8);
870                 if (resized_width % 8)
871                         resized_width += 8 - (resized_width % 8);
872
873                 DBG("original size[%d, %d] changed to resize[%d,%d]", width,
874                                         height, resized_width, resized_height);
875
876                 ret = image_util_calculate_buffer_size(resized_width,
877                                                         resized_height,
878                                                         colorspace ,
879                                                         &size_decode);
880
881                 img_target = g_malloc0(size_decode);
882
883                 /* do resize */
884                 ret = image_util_resize(img_target, &resized_width,
885                                         &resized_height, img_source, width,
886                                         height, colorspace);
887                 if (ret != IMAGE_UTIL_ERROR_NONE) {
888                         ERR("image_util_resize failed(%d)", ret);
889                         g_free(img_target);
890                         free(img_source);
891                         memset(info, 0x00, sizeof(bt_image_info_t));
892                         return false;
893                 }
894                 free(img_source);
895         } else {
896                 resized_width = width;
897                 resized_height = height;
898                 img_target = img_source;
899         }
900         DBG("Resized w = %d, ht = %d, size = %d\n", width, height, size_decode);
901
902         if (IMAGE_UTIL_ROTATION_NONE != rotation) {
903                 int rotated_width, rotated_height;
904                 unsigned char *img_rotate = 0;
905                 img_rotate = g_malloc0(size_decode);
906                 ret = image_util_rotate(img_rotate, &rotated_width, &rotated_height,
907                                         rotation, img_target, resized_width,
908                                         resized_height, colorspace);
909                 if (ret != 0)
910                         ERR("image_util_rotate failed");
911                 resized_width = rotated_width;
912                 resized_height = rotated_height;
913                 g_free(img_target);
914                 img_target = img_rotate;
915         }
916
917         /* image encode */
918         ret = image_util_encode_jpeg(img_target, resized_width, resized_height,
919                                         colorspace, PBAP_IMAGE_ENCODE_QUALITY,
920                                         info->dest);
921         g_free(img_target);
922         if (ret != IMAGE_UTIL_ERROR_NONE) {
923                 ERR("image_util_encode_jpeg failed(%d)", ret);
924                 info->ret = CONTACTS_ERROR_INTERNAL;
925                 goto done;
926         }
927         DBG("Encoding done\n");
928
929         dest_fd = open(info->dest, O_RDONLY);
930         if (dest_fd < 0) {
931                 ERR("System : Open Failed(%d)", errno);
932                 ERR_SECURE("Open : dest path(%s)", info->dest);
933                 goto done;
934         }
935
936         ret = fchown(dest_fd, getuid(), PBAP_SECURITY_FILE_GROUP);
937         if (0 != ret) {
938                 ERR("fchown Failed(%d)", errno);
939                 DBG_SECURE("fchown : dest path(%s)", info->dest);
940                 close(dest_fd);
941                 goto done;
942         }
943
944         ret = fchmod(dest_fd, PBAP_SECURITY_IMAGE_PERMISSION);
945         if (0 != ret) {
946                 ERR("fchmod Failed(%d)", errno);
947                 ERR_SECURE("fchmod : dest path(%s)", info->dest);
948                 close(dest_fd);
949                 goto done;
950         }
951         close(dest_fd);
952
953         info->ret = CONTACTS_ERROR_NONE;
954         type = __bluetooth_pb_contact_photo_type(info->dest);
955         DBG("Cintact image thumb type is = %s\n", type);
956
957         if (type) {
958                 param = g_strdup_printf("TYPE=%s", type);
959                 g_free(type);
960         }
961
962         if (g_file_get_contents(info->dest, &contents, &len, NULL) == FALSE) {
963                 ERR("can not read file contents:%s\n", info->dest);
964                 goto done;
965         }
966
967         __bluetooth_pb_vcard_append_base64_encode_v21(info->string,
968                         "PHOTO", param, contents, len, TRUE);
969
970 done:
971         g_free(param);
972         g_free(contents);
973         remove(info->dest);
974         memset(info, 0x00, sizeof(bt_image_info_t));
975         DBG("Cintact image thumb created successfuly\n");
976         FN_END;
977         return false;
978 }
979 #endif
980
981 static void __bluetooth_pb_vcard_append_photo_v21(GString *string,
982                                                 contacts_record_h person)
983 {
984         FN_START;
985         gint status;
986         gchar *filename = NULL;
987         struct stat stat_info;
988         gchar *type = NULL;
989         gchar *param = NULL;
990         gchar *contents = NULL;
991         gsize len = 0;
992         char *ptr = NULL;
993
994         status = contacts_record_get_str_p(person,
995                         _contacts_person.image_thumbnail_path,
996                         &filename);
997
998         if (status != CONTACTS_ERROR_NONE || NULL == filename)
999                 return;
1000
1001         stat_info.st_size = 0;
1002
1003         if (0 > stat(filename, &stat_info))
1004                 ERR("fstat failed, file does not exist %s", filename);
1005
1006         if (PBAP_THUMB_FILE_SIZE > stat_info.st_size) {
1007                 DBG_SECURE("File size small, so use thubnail %s\n", filename);
1008
1009                 type = __bluetooth_pb_contact_photo_type(filename);
1010                 if (type) {
1011                         param = g_strdup_printf("TYPE=%s", type);
1012                         g_free(type);
1013                 }
1014
1015                 if (g_file_get_contents(filename, &contents, &len, NULL) ==
1016                                                                         FALSE) {
1017                         ERR("can not read file contents:%s\n", filename);
1018                         g_free(param);
1019                         return;
1020                 }
1021                 DBG("Retrieved the contents of the file \n");
1022                 __bluetooth_pb_vcard_append_base64_encode_v21(string,
1023                                 "PHOTO", param, contents, len, TRUE);
1024
1025                 g_free(param);
1026                 g_free(contents);
1027                 return;
1028         }
1029
1030         ptr = strrchr(filename, '.');
1031         if (NULL != ptr) {
1032                 memset(dest_thumb_path, 0x00, sizeof(dest_thumb_path));
1033                 g_strlcpy(dest_thumb_path, filename, ptr - filename);
1034                 g_strlcat(dest_thumb_path, PBAP_THMB_PATH,
1035                                                 sizeof(dest_thumb_path));
1036                 g_strlcat(dest_thumb_path, ptr, sizeof(dest_thumb_path));
1037                 DBG("Thumbnail path is = %s", dest_thumb_path);
1038         }
1039         DBG_SECURE("filename = %s Thumbnail path is = %s", filename, dest_thumb_path);
1040
1041 /* image_util_foreach_supported_jpeg_colorspace API will be deprecated in Tizen 5.0. So we should replace it to new API
1042      https://developer.tizen.org/development/guides/native-application/media-and-camera/image-editing#decode
1043      https://developer.tizen.org/development/guides/native-application/media-and-camera/image-editing#encode
1044 */
1045 #if 0
1046         bt_image_info_t img_info;
1047         int res = 0;
1048
1049         img_info.src = filename;
1050         img_info.dest = dest_thumb_path;
1051         img_info.ret = CONTACTS_ERROR_INTERNAL;
1052         img_info.person = person;
1053         img_info.string = string;
1054
1055         res = image_util_foreach_supported_jpeg_colorspace(
1056                 __bt_pbap_image_util_supported_jpeg_colorspace_cb, &img_info);
1057
1058         if (res != IMAGE_UTIL_ERROR_NONE)
1059                 ERR("Image resizing is failed");
1060 #endif
1061
1062         FN_END;
1063 }
1064
1065 static void __bluetooth_pb_vcard_append_bday_v21(GString *string,
1066                                                 contacts_record_h contact)
1067 {
1068         FN_START;
1069         gint count = 0;
1070
1071         gint status;
1072         gint i;
1073
1074         status = contacts_record_get_child_record_count(contact,
1075                         _contacts_contact.event, &count);
1076
1077         if (status != CONTACTS_ERROR_NONE)
1078                 return;
1079
1080         for (i = 0; i < count; i++) {
1081                 contacts_record_h event = NULL;
1082
1083                 gint date;
1084
1085                 gchar *bday;
1086
1087                 contacts_event_type_e type;
1088
1089                 status = contacts_record_get_child_record_at_p(contact,
1090                                 _contacts_contact.event, i, &event);
1091
1092                 if (status != CONTACTS_ERROR_NONE)
1093                         continue;
1094
1095                 status = contacts_record_get_int(event,
1096                                 _contacts_event.type,
1097                                 (gint *) &type);
1098
1099                 if (status != CONTACTS_ERROR_NONE)
1100                         continue;
1101
1102                 if (type != CONTACTS_EVENT_TYPE_BIRTH)
1103                         continue;
1104
1105                 status = contacts_record_get_int(event,
1106                                 _contacts_event.date,
1107                                 &date);
1108
1109                 if (status != CONTACTS_ERROR_NONE)
1110                         continue;
1111
1112                 if (date <= 0)
1113                         continue;
1114
1115                 bday = g_strdup_printf("%04d-%02d-%02d",
1116                                 (date/10000), (date/100)%100, date%100);
1117                 __bluetooth_pb_vcard_append_qp_encode_v21(string, "BDAY",
1118                                 NULL, bday);
1119                 g_free(bday);
1120         }
1121         FN_END;
1122 }
1123
1124 static void __bluetooth_pb_vcard_append_adr_v21(GString *string,
1125                                                 contacts_record_h contact)
1126 {
1127         FN_START;
1128         gint count = 0;
1129
1130         gint status;
1131         gint i;
1132
1133         status = contacts_record_get_child_record_count(contact,
1134                         _contacts_contact.address,
1135                         &count);
1136
1137         if (status != CONTACTS_ERROR_NONE)
1138                 return;
1139
1140         for (i = 0; i < count; i++) {
1141                 contacts_record_h address = NULL;
1142
1143                 gchar **addrv;
1144                 gchar **paramv;
1145
1146                 gchar *addr;
1147                 gchar *param;
1148
1149                 status = contacts_record_get_child_record_at_p(contact,
1150                                 _contacts_contact.address, i, &address);
1151
1152                 if (status != CONTACTS_ERROR_NONE)
1153                         continue;
1154
1155                 addrv = __bluetooth_pb_contact_addr(address);
1156
1157                 if (addrv == NULL)
1158                         continue;
1159
1160                 addr = __bluetooth_pb_vcard_strv_concat(addrv, ";");
1161                 g_strfreev(addrv);
1162
1163                 paramv = __bluetooth_pb_contact_addr_param(address);
1164                 if (paramv) {
1165                         param = __bluetooth_pb_vcard_strv_concat(paramv, ";");
1166                         g_strfreev(paramv);
1167
1168                         __bluetooth_pb_vcard_append_qp_encode_v21(string, "ADR",
1169                                         param, addr);
1170                         g_free(param);
1171                 }
1172
1173                 g_free(addr);
1174         }
1175         FN_END;
1176 }
1177
1178 static void __bluetooth_pb_vcard_append_email_v21(GString *string,
1179                                                 contacts_record_h contact)
1180 {
1181         FN_START;
1182         gint count = 0;
1183
1184         gint status;
1185         gint i;
1186
1187         status = contacts_record_get_child_record_count(contact,
1188                         _contacts_contact.email,
1189                         &count);
1190
1191         if (status != CONTACTS_ERROR_NONE)
1192                 return;
1193
1194         for (i = 0; i < count; i++) {
1195                 contacts_record_h email = NULL;
1196
1197                 gchar *tmp = NULL;
1198                 gchar *escaped;
1199
1200                 status = contacts_record_get_child_record_at_p(contact,
1201                                 _contacts_contact.email, i, &email);
1202
1203                 if (status != CONTACTS_ERROR_NONE)
1204                         continue;
1205
1206                 status = contacts_record_get_str_p(email,
1207                                 _contacts_email.email,
1208                                 &tmp);
1209
1210                 if (status != CONTACTS_ERROR_NONE)
1211                         continue;
1212
1213                 escaped = __bluetooth_pb_vcard_escape(tmp);
1214                 __bluetooth_pb_vcard_append_qp_encode_v21(string, "EMAIL", NULL,
1215                                                                 escaped);
1216
1217                 g_free(escaped);
1218         }
1219         FN_END;
1220 }
1221
1222 static void __bluetooth_pb_vcard_append_title_v21(GString *string,
1223                                                 contacts_record_h contact)
1224 {
1225         FN_START;
1226         gint count = 0;
1227
1228         gint status;
1229         gint i;
1230
1231         status = contacts_record_get_child_record_count(contact,
1232                         _contacts_contact.company,
1233                         &count);
1234
1235         if (status != CONTACTS_ERROR_NONE)
1236                 return;
1237
1238         for (i = 0; i < count; i++) {
1239                 contacts_record_h company = NULL;
1240
1241                 char *title = NULL;
1242                 gchar *escaped;
1243
1244                 status = contacts_record_get_child_record_at_p(contact,
1245                                         _contacts_contact.company, i, &company);
1246
1247                 if (status != CONTACTS_ERROR_NONE)
1248                         continue;
1249
1250                 status = contacts_record_get_str_p(company,
1251                                 _contacts_company.job_title,
1252                                 &title);
1253
1254                 if (status != CONTACTS_ERROR_NONE)
1255                         continue;
1256
1257                 escaped = __bluetooth_pb_vcard_escape(title);
1258                 __bluetooth_pb_vcard_append_qp_encode_v21(string, "TITLE", NULL,
1259                                                                 escaped);
1260
1261                 g_free(escaped);
1262         }
1263         FN_END;
1264 }
1265
1266 static void __bluetooth_pb_vcard_append_role_v21(GString *string,
1267                                                 contacts_record_h contact)
1268 {
1269         FN_START;
1270         gint count = 0;
1271
1272         gint status;
1273         gint i;
1274
1275         status = contacts_record_get_child_record_count(contact,
1276                         _contacts_contact.company,
1277                         &count);
1278
1279         if (status != CONTACTS_ERROR_NONE)
1280                 return;
1281
1282         for (i = 0; i < count; i++) {
1283                 contacts_record_h company = NULL;
1284
1285                 char *role = NULL;
1286                 gchar *escaped;
1287
1288                 status = contacts_record_get_child_record_at_p(contact,
1289                                 _contacts_contact.company, i, &company);
1290
1291                 if (status != CONTACTS_ERROR_NONE)
1292                         continue;
1293
1294                 status = contacts_record_get_str_p(company,
1295                                 _contacts_company.role,
1296                                 &role);
1297
1298                 if (status != CONTACTS_ERROR_NONE)
1299                         continue;
1300
1301                 escaped = __bluetooth_pb_vcard_escape(role);
1302                 __bluetooth_pb_vcard_append_qp_encode_v21(string, "ROLE", NULL,
1303                                                                 escaped);
1304
1305                 g_free(escaped);
1306         }
1307         FN_END;
1308 }
1309
1310 static void __bluetooth_pb_vcard_append_org_v21(GString *string,
1311                                                 contacts_record_h contact)
1312 {
1313         FN_START;
1314         gint count = 0;
1315
1316         gint status;
1317         gint i;
1318
1319         status = contacts_record_get_child_record_count(contact,
1320                         _contacts_contact.company,
1321                         &count);
1322
1323         if (status != CONTACTS_ERROR_NONE)
1324                 return;
1325
1326         for (i = 0; i < count; i++) {
1327                 contacts_record_h company = NULL;
1328
1329                 GString *str;
1330
1331                 gchar *name = NULL;
1332                 gchar *department = NULL;
1333
1334                 gint name_status;
1335                 gint department_status;
1336
1337                 status = contacts_record_get_child_record_at_p(contact,
1338                                 _contacts_contact.company, i, &company);
1339
1340                 if (status != CONTACTS_ERROR_NONE)
1341                         continue;
1342
1343
1344                 name_status = contacts_record_get_str_p(company,
1345                                 _contacts_company.name,
1346                                 &name);
1347
1348                 department_status = contacts_record_get_str_p(company,
1349                                 _contacts_company.department,
1350                                 &department);
1351
1352                 if ((name_status != CONTACTS_ERROR_NONE) &&
1353                                 (department_status != CONTACTS_ERROR_NONE))
1354                         continue;
1355
1356                 str = g_string_new(NULL);
1357
1358                 if (name) {
1359                         gchar *escaped;
1360
1361                         escaped = __bluetooth_pb_vcard_escape(name);
1362                         g_string_append(str, escaped);
1363                         g_free(escaped);
1364                 }
1365
1366                 g_string_append(str, ";");
1367
1368                 if (department) {
1369                         gchar *escaped;
1370
1371                         escaped = __bluetooth_pb_vcard_escape(department);
1372                         g_string_append(str, escaped);
1373                         g_free(escaped);
1374                 }
1375
1376                 __bluetooth_pb_vcard_append_qp_encode_v21(string, "ORG", NULL,
1377                                                                 str->str);
1378
1379                 g_string_free(str, TRUE);
1380
1381         }
1382         FN_END;
1383 }
1384
1385 static void __bluetooth_pb_vcard_append_note_v21(GString *string,
1386                                                 contacts_record_h contact)
1387 {
1388         FN_START;
1389         gint count = 0;
1390
1391         gint status;
1392         gint i;
1393
1394         status = contacts_record_get_child_record_count(contact,
1395                         _contacts_contact.note,
1396                         &count);
1397
1398         if (status != CONTACTS_ERROR_NONE)
1399                 return;
1400
1401         for (i = 0; i < count; i++) {
1402                 contacts_record_h note = NULL;
1403
1404                 char *tmp = NULL;
1405                 gchar *escaped;
1406
1407                 status = contacts_record_get_child_record_at_p(contact,
1408                                 _contacts_contact.note, i, &note);
1409
1410                 if (status != CONTACTS_ERROR_NONE)
1411                         continue;
1412
1413                 status = contacts_record_get_str_p(note,
1414                                 _contacts_note.note,
1415                                 &tmp);
1416
1417                 if (status != CONTACTS_ERROR_NONE)
1418                         continue;
1419
1420                 escaped = __bluetooth_pb_vcard_escape(tmp);
1421                 __bluetooth_pb_vcard_append_qp_encode_v21(string, "NOTE", NULL,
1422                                                                 escaped);
1423
1424                 g_free(escaped);
1425         }
1426         FN_END;
1427 }
1428
1429 static void __bluetooth_pb_vcard_append_rev_v21(GString *string,
1430                                                 contacts_record_h contact)
1431 {
1432         FN_START;
1433         gint time = 0;
1434         gint status;
1435
1436         gchar *rev;
1437         struct tm result;
1438
1439         status = contacts_record_get_int(contact,
1440                         _contacts_contact.changed_time,
1441                         &time);
1442
1443         if (status != CONTACTS_ERROR_NONE)
1444                 return;
1445
1446         if (time <= 0)
1447                 return;
1448
1449         gmtime_r((const time_t *)(&time), &result);
1450
1451         rev = g_strdup_printf("%04d-%02d-%02dT%02d:%02d:%02dZ",
1452                         (1900 + result.tm_year), (1 + result.tm_mon),
1453                         result.tm_mday, result.tm_hour, result.tm_min,
1454                         result.tm_sec);
1455
1456         __bluetooth_pb_vcard_append_qp_encode_v21(string, "REV", NULL, rev);
1457
1458         g_free(rev);
1459         FN_END;
1460 }
1461
1462 static void __bluetooth_pb_vcard_append_url_v21(GString *string,
1463                                                 contacts_record_h contact)
1464 {
1465         FN_START;
1466         gint count = 0;
1467
1468         gint i;
1469         gint status;
1470
1471         status = contacts_record_get_child_record_count(contact,
1472                         _contacts_contact.url,
1473                         &count);
1474
1475         if (status != CONTACTS_ERROR_NONE)
1476                 return;
1477
1478         for (i = 0; i < count; i++) {
1479                 contacts_record_h url = NULL;
1480
1481                 gchar *tmp = NULL;
1482                 gchar *escaped;
1483
1484                 status = contacts_record_get_child_record_at_p(contact,
1485                                 _contacts_contact.url, i, &url);
1486
1487                 if (status != CONTACTS_ERROR_NONE)
1488                         return;
1489
1490                 if (url == NULL)
1491                         continue;
1492
1493                 status = contacts_record_get_str_p(url,
1494                                 _contacts_url.url,
1495                                 &tmp);
1496
1497                 if (status != CONTACTS_ERROR_NONE)
1498                         continue;
1499
1500                 escaped = __bluetooth_pb_vcard_escape(tmp);
1501                 __bluetooth_pb_vcard_append_qp_encode_v21(string, "URL", NULL,
1502                                                                 escaped);
1503
1504                 g_free(escaped);
1505         }
1506         FN_END;
1507 }
1508
1509 static void __bluetooth_pb_vcard_append_uid_v21(GString *string,
1510                                                 contacts_record_h contact)
1511 {
1512         FN_START;
1513         int status;
1514
1515         gchar *uid = NULL;
1516         gchar *escaped;
1517
1518         status = contacts_record_get_str_p(contact,
1519                         _contacts_contact.uid,
1520                         &uid);
1521
1522         if (status != CONTACTS_ERROR_NONE)
1523                 return;
1524
1525         escaped = __bluetooth_pb_vcard_escape(uid);
1526         __bluetooth_pb_vcard_append_qp_encode_v21(string, "UID", NULL, escaped);
1527
1528         g_free(escaped);
1529         FN_END;
1530 }
1531
1532 static void __bluetooth_pb_vcard_append_v30(GString *string,
1533                                         const gchar *name,
1534                                         const gchar *param,
1535                                         const gchar *value)
1536 {
1537         FN_START;
1538         if (string == NULL)
1539                 return;
1540         if (name == NULL)
1541                 return;
1542
1543         g_string_append(string, name);
1544
1545         if (param)
1546                 g_string_append_printf(string, ";%s", param);
1547
1548         g_string_append(string, ":");
1549
1550         if (value)
1551                 g_string_append(string, value);
1552
1553         g_string_append(string, "\r\n");
1554         FN_END;
1555 }
1556
1557 static void __bluetooth_pb_vcard_remove_v30(GString *string,
1558                                         const gchar *property_name)
1559 {
1560         FN_START;
1561         gchar *pos = NULL;
1562         gchar *st_pos = NULL;
1563
1564         gboolean matched = FALSE;
1565
1566         if (string == NULL || property_name == NULL)
1567                 return;
1568
1569         pos = string->str;
1570
1571         while (*pos != '\0') {
1572                 if (matched == FALSE) {
1573                         if (g_ascii_strncasecmp(pos, "\r\n", 2) == 0) {
1574                                 gint attrlen = 0;
1575
1576                                 st_pos = pos;
1577                                 pos += 2;
1578
1579                                 attrlen = strlen(property_name);
1580                                 if (g_ascii_strncasecmp(pos, property_name,
1581                                                                 attrlen) == 0) {
1582                                         pos += attrlen;
1583
1584                                         if (*pos == ':' || *pos == ';') {
1585                                                 matched = TRUE;
1586                                                 pos++;
1587                                         }
1588                                 }
1589                                 continue;
1590                         }
1591                 } else {
1592                         if (g_ascii_strncasecmp(pos, "\r\n", 2) == 0) {
1593                                 pos += 2;
1594
1595                                 if (*pos != ' ' && *pos != '\t') {
1596                                         /* +2 means move over \r\n */
1597                                         g_string_erase(string,
1598                                                 (st_pos+2)-(string->str),
1599                                                 pos-(st_pos+2));
1600
1601                                         pos = st_pos;
1602                                         matched = FALSE;
1603                                 }
1604                                 continue;
1605                         }
1606                 }
1607
1608                 pos++;
1609         }
1610         FN_END;
1611 }
1612
1613 static gchar *__bluetooth_pb_vcard_filter_v30(const gchar *vcard,
1614                                         guint64 filter)
1615 {
1616         FN_START;
1617         GString *string = NULL;
1618
1619         if (vcard == NULL)
1620                 return NULL;
1621
1622         string = g_string_new(vcard);
1623
1624         if ((filter & VCARD_BDAY) == 0)
1625                 __bluetooth_pb_vcard_remove_v30(string, "BDAY");
1626
1627         if ((filter & VCARD_ADR) == 0)
1628                 __bluetooth_pb_vcard_remove_v30(string, "ADR");
1629
1630         if ((filter & VCARD_EMAIL) == 0)
1631                 __bluetooth_pb_vcard_remove_v30(string, "EMAIL");
1632
1633         if ((filter & VCARD_TITLE) == 0)
1634                 __bluetooth_pb_vcard_remove_v30(string, "TITLE");
1635
1636         if ((filter & VCARD_ROLE) == 0)
1637                 __bluetooth_pb_vcard_remove_v30(string, "ROLE");
1638
1639         if ((filter & VCARD_ORG) == 0)
1640                 __bluetooth_pb_vcard_remove_v30(string, "ORG");
1641
1642         if ((filter & VCARD_NOTE) == 0)
1643                 __bluetooth_pb_vcard_remove_v30(string, "NOTE");
1644
1645         if ((filter & VCARD_REV) == 0)
1646                 __bluetooth_pb_vcard_remove_v30(string, "REV");
1647
1648         if ((filter & VCARD_URL) == 0)
1649                 __bluetooth_pb_vcard_remove_v30(string, "URL");
1650
1651         if ((filter & VCARD_UID) == 0)
1652                 __bluetooth_pb_vcard_remove_v30(string, "UID");
1653
1654         if ((filter & VCARD_NICKNAME) == 0)
1655                 __bluetooth_pb_vcard_remove_v30(string, "NICKNAME");
1656
1657         FN_END;
1658         return g_string_free(string, FALSE);
1659 }
1660
1661 static gchar *__bluetooth_pb_vcard_real_contact_valist_v21(gint person_id,
1662                                                         gint phonelog_id,
1663                                                         guint64 filter,
1664                                                         const gchar *first_name,
1665                                                         va_list args)
1666 {
1667         FN_START;
1668         contacts_record_h person = NULL;
1669         contacts_record_h contact = NULL;
1670
1671         GString *str = NULL;
1672
1673         gint contact_id = 0;
1674         gint status;
1675
1676         guint64 f = filter;
1677
1678         const gchar *name = first_name;
1679
1680         status = contacts_db_get_record(_contacts_person._uri,
1681                         person_id,
1682                         &person);
1683
1684         if (status != CONTACTS_ERROR_NONE)
1685                 return NULL;
1686
1687         status = contacts_record_get_int(person,
1688                         _contacts_person.display_contact_id,
1689                         &contact_id);
1690
1691         if (status != CONTACTS_ERROR_NONE)
1692                 return NULL;
1693
1694         status = contacts_db_get_record(_contacts_contact._uri,
1695                         contact_id,
1696                         &contact);
1697
1698         if (status != CONTACTS_ERROR_NONE) {
1699                 contacts_record_destroy(person, TRUE);
1700                 return NULL;;
1701         }
1702
1703         if (f == 0)
1704                 f = ~f;
1705
1706         DBG("filter[%x]\n", filter);
1707
1708         str = g_string_new("BEGIN:VCARD\r\nVERSION:2.1\r\n");
1709
1710         /* N, TEL is default */
1711         __bluetooth_pb_vcard_append_n_v21(str, contact);
1712
1713         if (phonelog_id > 0) {
1714                 gchar *number;
1715
1716                 number = _bluetooth_pb_number_from_phonelog_id(phonelog_id);
1717                 __bluetooth_pb_vcard_append_qp_encode_v21(str, "TEL", "X-0",
1718                                                                         number);
1719                 g_free(number);
1720
1721
1722         } else {
1723                 __bluetooth_pb_vcard_append_tel_v21(str, contact);
1724         }
1725
1726         if (f & VCARD_FN)
1727                 __bluetooth_pb_vcard_append_fn_v21(str, person);
1728 /*      Need to check filter
1729         if (f & VCARD_SOUND)*/
1730                 __bluetooth_pb_vcard_append_phonetic_first_v21(str, contact);
1731         if (f & VCARD_PHOTO)
1732                 __bluetooth_pb_vcard_append_photo_v21(str, person);
1733         if (f & VCARD_BDAY)
1734                 __bluetooth_pb_vcard_append_bday_v21(str, contact);
1735         if (f & VCARD_ADR)
1736                 __bluetooth_pb_vcard_append_adr_v21(str, contact);
1737         if (f & VCARD_EMAIL)
1738                 __bluetooth_pb_vcard_append_email_v21(str, contact);
1739         if (f & VCARD_TITLE)
1740                 __bluetooth_pb_vcard_append_title_v21(str, contact);
1741         if (f & VCARD_ROLE)
1742                 __bluetooth_pb_vcard_append_role_v21(str, contact);
1743         if (f & VCARD_ORG)
1744                 __bluetooth_pb_vcard_append_org_v21(str, contact);
1745         if (f & VCARD_NOTE)
1746                 __bluetooth_pb_vcard_append_note_v21(str, contact);
1747         if (f & VCARD_REV)
1748                 __bluetooth_pb_vcard_append_rev_v21(str, contact);
1749         if (f & VCARD_URL)
1750                 __bluetooth_pb_vcard_append_url_v21(str, contact);
1751         if (f & VCARD_UID)
1752                 __bluetooth_pb_vcard_append_uid_v21(str, contact);
1753
1754         while (name) {
1755                 const gchar *param = va_arg(args, const gchar *);
1756                 const gchar *value = va_arg(args, const gchar *);
1757
1758                 if (value) {
1759                         gchar *escaped = NULL;
1760
1761                         escaped = __bluetooth_pb_vcard_escape(value);
1762                         __bluetooth_pb_vcard_append_qp_encode_v21(str, name,
1763                                                                 param, escaped);
1764
1765                         g_free(escaped);
1766                 }
1767
1768                 name = va_arg(args, const gchar *);
1769         }
1770
1771         g_string_append(str, "END:VCARD\r\n");
1772
1773         contacts_record_destroy(contact, TRUE);
1774         contacts_record_destroy(person, TRUE);
1775
1776         FN_END;
1777         return g_string_free(str, FALSE);
1778 }
1779
1780
1781 static gchar *__bluetooth_pb_vcard_real_contact_valist_v30(gint person_id,
1782                                                         gint phonelog_id,
1783                                                         guint64 filter,
1784                                                         const gchar *first_name,
1785                                                         va_list args)
1786 {
1787         FN_START;
1788         contacts_record_h person = NULL;
1789
1790         GString *str = NULL;
1791
1792         gint status;
1793
1794         const gchar *name = first_name;
1795         gchar *vcard = NULL;
1796
1797         status = contacts_db_get_record(_contacts_person._uri,
1798                         person_id,
1799                         &person);
1800
1801         if (status != CONTACTS_ERROR_NONE)
1802                 return NULL;
1803
1804         status = contacts_vcard_make_from_person(person, &vcard);
1805
1806         if (status != CONTACTS_ERROR_NONE)
1807                 return NULL;
1808
1809         /* removing the END:VCARD\r\n" to append extra data */
1810         str = g_string_new_len(vcard, (strlen(vcard)-11));
1811         g_free(vcard);
1812
1813         /* append contents on vcard */
1814         while (name) {
1815                 const gchar *param = va_arg(args, const gchar *);
1816                 const gchar *value = va_arg(args, const gchar *);
1817
1818                 __bluetooth_pb_vcard_append_v30(str, name, param, value);
1819
1820                 name = va_arg(args, const gchar *);
1821         }
1822
1823         /* if phonelog_id exist, we shall show only the phone number, which was
1824            used for that phone log */
1825         if (phonelog_id > 0) {
1826                 gchar *number;
1827
1828                 __bluetooth_pb_vcard_remove_v30(str, "TEL");
1829
1830                 number = _bluetooth_pb_number_from_phonelog_id(phonelog_id);
1831                 __bluetooth_pb_vcard_append_v30(str, "TEL", NULL, number);
1832                 g_free(number);
1833         }
1834
1835         /* Remove Full contact image and add thumbnail image */
1836         __bluetooth_pb_vcard_remove_v30(str, "PHOTO");
1837         if (filter & VCARD_PHOTO)
1838                 __bluetooth_pb_vcard_append_photo_v21(str, person); /* Photo is same as vCard 2.1 */
1839
1840         /* Destroy contact record */
1841         status = contacts_record_destroy(person, TRUE);
1842         if (status != CONTACTS_ERROR_NONE)
1843                 ERR("Failed to destroy person");
1844
1845         g_string_append(str, "END:VCARD\r\n");
1846
1847         vcard = g_string_free(str, FALSE);
1848
1849         /* temporary fixed for some application crash */
1850         if (filter == 0)
1851                 filter = ~VCARD_NOTE;
1852
1853         if (filter) {
1854                 gchar *new_vcard = NULL;
1855
1856                 new_vcard = __bluetooth_pb_vcard_filter_v30(vcard, filter);
1857
1858                 if (new_vcard) {
1859                         g_free(vcard);
1860                         vcard = new_vcard;
1861                 }
1862         }
1863
1864         FN_END;
1865         return vcard;
1866 }
1867
1868
1869 static gchar *__bluetooth_pb_vcard_real_contact_with_properties(gint person_id,
1870                                                         gint phonelog_id,
1871                                                         guint64 filter,
1872                                                         guint8 format,
1873                                                         const gchar *first_name,
1874                                                         ...)
1875 {
1876         FN_START;
1877         DBG(" format [%d]\n", format);
1878         gchar *vcard = NULL;
1879         va_list args;
1880
1881         va_start(args, first_name);
1882
1883         switch (format) {
1884         case VCARD_FORMAT_3_0:
1885                 vcard = __bluetooth_pb_vcard_real_contact_valist_v30(person_id,
1886                                 phonelog_id, filter,
1887                                 first_name, args);
1888                 break;
1889         case VCARD_FORMAT_2_1:
1890         default:
1891                 vcard = __bluetooth_pb_vcard_real_contact_valist_v21(person_id,
1892                                 phonelog_id, filter,
1893                                 first_name, args);
1894                 break;
1895         }
1896
1897         va_end(args);
1898
1899         FN_END;
1900         return vcard;
1901 }
1902
1903 static gchar *__bluetooth_pb_vcard_real_call_v21(gint phonelog_id,
1904                                                 guint filter,
1905                                                 const char *attr)
1906 {
1907         FN_START;
1908         GString *str;
1909         gchar *number;
1910
1911         str = g_string_new("BEGIN:VCARD\r\nVERSION:2.1\r\n");
1912
1913         __bluetooth_pb_vcard_append_qp_encode_v21(str, "N", NULL, NULL);
1914
1915         number = _bluetooth_pb_number_from_phonelog_id(phonelog_id);
1916         __bluetooth_pb_vcard_append_qp_encode_v21(str, "TEL", "X-0", number);
1917         g_free(number);
1918
1919         if (((filter == 0) || (filter & VCARD_X_IRMC_CALL_DATETIME))
1920                         && attr) {
1921                 gchar *datetime = NULL;
1922
1923                 datetime = __bluetooth_pb_phonelog_datetime(phonelog_id);
1924                 __bluetooth_pb_vcard_append_qp_encode_v21(str,
1925                                                         "X-IRMC-CALL-DATETIME",
1926                                                         attr, datetime);
1927                 g_free(datetime);
1928         }
1929
1930         g_string_append(str, "END:VCARD\r\n");
1931
1932         FN_END;
1933         return g_string_free(str, FALSE);
1934 }
1935
1936 static gchar *__bluetooth_pb_vcard_real_call_v30(gint phonelog_id,
1937                                                 guint filter,
1938                                                 const gchar *attr)
1939 {
1940         FN_START;
1941         GString *str;
1942         gchar *number;
1943
1944         str = g_string_new("BEGIN:VCARD\r\nVERSION:3.0\r\n");
1945
1946         __bluetooth_pb_vcard_append_v30(str, "N", NULL, NULL);
1947         __bluetooth_pb_vcard_append_v30(str, "FN", NULL, NULL);
1948
1949         number = _bluetooth_pb_number_from_phonelog_id(phonelog_id);
1950         __bluetooth_pb_vcard_append_v30(str, "TEL", NULL, number);
1951         g_free(number);
1952
1953         if (((filter == 0) || (filter & VCARD_X_IRMC_CALL_DATETIME))
1954                         && attr) {
1955                 gchar *datetime = NULL;
1956
1957                 datetime = __bluetooth_pb_phonelog_datetime(phonelog_id);
1958                 __bluetooth_pb_vcard_append_v30(str,
1959                                 "X-IRMC-CALL-DATETIME", attr, datetime);
1960                 g_free(datetime);
1961         }
1962
1963         g_string_append(str, "END:VCARD\r\n");
1964
1965         FN_END;
1966         return g_string_free(str, FALSE);
1967 }
1968
1969 static gchar *__bluetooth_pb_vcard_real_call(gint phonelog_id,
1970                                         guint filter,
1971                                         guint8 format,
1972                                         const gchar *attr)
1973 {
1974         FN_START;
1975         gchar *vcard = NULL;
1976
1977         switch (format) {
1978         case VCARD_FORMAT_3_0:
1979                 vcard = __bluetooth_pb_vcard_real_call_v30(phonelog_id,
1980                                 filter, attr);
1981                 break;
1982         case VCARD_FORMAT_2_1:
1983         default:
1984                 vcard = __bluetooth_pb_vcard_real_call_v21(phonelog_id,
1985                                 filter, attr);
1986                 break;
1987         }
1988
1989         FN_END;
1990         return vcard;
1991 }
1992
1993 static gchar **__bluetooth_pb_contact_add_field_str(contacts_record_h record,
1994                                                 int *field,
1995                                                 gint field_size)
1996 {
1997         FN_START;
1998         gchar **strv;
1999
2000         gint status;
2001         gint i;
2002
2003         gboolean valid = FALSE;
2004
2005         /* check empty field */
2006         for (i = 0; i < field_size; i++) {
2007                 gchar *tmp = NULL;
2008
2009                 status = contacts_record_get_str_p(record, field[i], &tmp);
2010
2011                 if (status != CONTACTS_ERROR_NONE)
2012                         continue;
2013
2014                 if (tmp) {
2015                         valid = TRUE;
2016                         break;
2017                 }
2018         }
2019
2020         if (valid == FALSE)
2021                 return NULL;
2022
2023         strv = g_new0(gchar *, field_size + 1);
2024
2025         for (i = 0; i < field_size; i++) {
2026                 gchar *tmp;
2027
2028                 status = contacts_record_get_str_p(record, field[i], &tmp);
2029
2030                 if (status != CONTACTS_ERROR_NONE)
2031                         continue;
2032
2033                 if (tmp == NULL)
2034                         strv[i] = g_strdup("");
2035                 else
2036                         strv[i] = __bluetooth_pb_vcard_escape(tmp);
2037         }
2038
2039         FN_END;
2040         return strv;
2041 }
2042
2043 static gchar **__bluetooth_pb_contact_tel_param(contacts_record_h number)
2044 {
2045         FN_START;
2046         gchar **strv = NULL;
2047
2048         const gint TEL_PARAM_LEN = 13;
2049
2050         gint status;
2051         gint i = 0;
2052
2053         contacts_number_type_e type;
2054
2055         bool is_default = false;
2056
2057         status = contacts_record_get_bool(number, _contacts_number.is_default,
2058                         &is_default);
2059
2060         if (status != CONTACTS_ERROR_NONE)
2061                 return NULL;
2062
2063         status = contacts_record_get_int(number,
2064                         _contacts_number.type,
2065                         (gint *)&type);
2066
2067         if (status != CONTACTS_ERROR_NONE)
2068                 return NULL;
2069
2070         strv = g_new0(char *, TEL_PARAM_LEN + 1);/* tel param max size is 13 */
2071
2072         if (is_default) {
2073                 strv[i] = g_strdup("PREF");
2074                 i++;
2075         }
2076
2077         if (type & CONTACTS_NUMBER_TYPE_HOME) {
2078                 strv[i] = g_strdup("HOME");
2079                 i++;
2080         }
2081
2082         if (type & CONTACTS_NUMBER_TYPE_WORK) {
2083                 strv[i] = g_strdup("WORK");
2084                 i++;
2085         }
2086
2087         if (type & CONTACTS_NUMBER_TYPE_VOICE) {
2088                 strv[i] = g_strdup("VOICE");
2089                 i++;
2090         }
2091
2092         if (type & CONTACTS_NUMBER_TYPE_FAX) {
2093                 strv[i] = g_strdup("FAX");
2094                 i++;
2095         }
2096
2097         if (type & CONTACTS_NUMBER_TYPE_MSG) {
2098                 strv[i] = g_strdup("MSG");
2099                 i++;
2100         }
2101
2102         if (type & CONTACTS_NUMBER_TYPE_CELL) {
2103                 strv[i] = g_strdup("CELL");
2104                 i++;
2105         }
2106
2107         if (type & CONTACTS_NUMBER_TYPE_PAGER) {
2108                 strv[i] = g_strdup("PAGER");
2109                 i++;
2110         }
2111
2112         if (type & CONTACTS_NUMBER_TYPE_BBS) {
2113                 strv[i] = g_strdup("BBS");
2114                 i++;
2115         }
2116
2117         if (type & CONTACTS_NUMBER_TYPE_MODEM) {
2118                 strv[i] = g_strdup("MODEM");
2119                 i++;
2120         }
2121
2122         if (type & CONTACTS_NUMBER_TYPE_CAR) {
2123                 strv[i] = g_strdup("CAR");
2124                 i++;
2125         }
2126
2127         if (type & CONTACTS_NUMBER_TYPE_ISDN) {
2128                 strv[i] = g_strdup("ISDN");
2129                 i++;
2130         }
2131
2132         if (type & CONTACTS_NUMBER_TYPE_VIDEO) {
2133                 strv[i] = g_strdup("VIDEO");
2134                 i++;
2135         }
2136
2137         /* CTS_NUM_TYPE_PCS is not part of vcard2.1 */
2138         FN_END;
2139         return strv;
2140 }
2141
2142
2143 static gchar *__bluetooth_pb_contact_photo_type(const gchar *filename)
2144 {
2145         FN_START;
2146         gchar *filetype = NULL;
2147         gchar *ext = NULL;
2148
2149         if (g_file_test(filename, G_FILE_TEST_IS_REGULAR) == FALSE) {
2150                 ERR_SECURE("file does not regular:%s\n", filename);
2151                 return NULL;
2152         }
2153
2154         ext = strrchr(filename, '.');
2155         if (ext == NULL) {
2156                 ERR("file doesn't have extension\n");
2157                 return NULL;
2158         }
2159
2160         ext++;
2161
2162         if (g_ascii_strcasecmp(ext, "gif") == 0)
2163                 filetype = "GIF";
2164         else if (g_ascii_strcasecmp(ext, "cgm") == 0)
2165                 filetype = "CGM";
2166         else if (g_ascii_strcasecmp(ext, "wmf") == 0)
2167                 filetype = "WMF";
2168         else if (g_ascii_strcasecmp(ext, "bmp") == 0)
2169                 filetype = "BMP";
2170         else if (g_ascii_strcasecmp(ext, "met") == 0)
2171                 filetype = "MET";
2172         else if (g_ascii_strcasecmp(ext, "dib") == 0)
2173                 filetype = "DIB";
2174         else if (g_ascii_strcasecmp(ext, "pict") == 0 ||
2175                         g_ascii_strcasecmp(ext, "pct") == 0 ||
2176                         g_ascii_strcasecmp(ext, "pic") == 0)
2177                 filetype = "PICT";
2178         else if (g_ascii_strcasecmp(ext, "tiff") == 0 ||
2179                         g_ascii_strcasecmp(ext, "tif") == 0)
2180                 filetype = "TIFF";
2181         else if (g_ascii_strcasecmp(ext, "ps") == 0)
2182                 filetype = "PS";
2183         else if (g_ascii_strcasecmp(ext, "pdf") == 0)
2184                 filetype = "PDF";
2185         else if (g_ascii_strcasecmp(ext, "jpeg") == 0 ||
2186                         g_ascii_strcasecmp(ext, "jpg") == 0 ||
2187                         g_ascii_strcasecmp(ext, "jpe") == 0)
2188                 filetype = "JPEG";
2189         else if (g_ascii_strcasecmp(ext, "mpeg") == 0 ||
2190                         g_ascii_strcasecmp(ext, "mpg") == 0)
2191                 filetype = "MPEG";
2192         else if (g_ascii_strcasecmp(ext, "m2v") == 0)
2193                 filetype = "MPEG2";
2194         else if (g_ascii_strcasecmp(ext, "avi") == 0)
2195                 filetype = "AVI";
2196         else if (g_ascii_strcasecmp(ext, "mov") == 0)
2197                 filetype = "QTIME";
2198         else if (g_ascii_strcasecmp(ext, "png") == 0)
2199                 filetype = "PNG";
2200
2201         FN_END;
2202         return g_strdup(filetype);
2203 }
2204
2205 static gchar **__bluetooth_pb_contact_addr(contacts_record_h address)
2206 {
2207         FN_START;
2208         const gint ADDR_LEN = 7;
2209
2210         gchar **strv = NULL;
2211
2212         gint addr[] = { _contacts_address.postbox,
2213                         _contacts_address.extended,
2214                         _contacts_address.street,
2215                         _contacts_address.locality,
2216                         _contacts_address.region,
2217                         _contacts_address.postal_code,
2218                         _contacts_address.country };
2219
2220         strv = __bluetooth_pb_contact_add_field_str(address,
2221                         addr, ADDR_LEN);
2222         FN_END;
2223         return strv;
2224 }
2225
2226 static gchar **__bluetooth_pb_contact_addr_param(contacts_record_h address)
2227 {
2228         FN_START;
2229         contacts_address_type_e type;
2230
2231         gint status;
2232         gint i = 0;
2233
2234         gchar **strv = NULL;
2235
2236         status = contacts_record_get_int(address,
2237                         _contacts_address.type,
2238                         (gint *)&type);
2239
2240         if (status != CONTACTS_ERROR_NONE)
2241                 return NULL;
2242
2243         strv = g_new0(gchar *, 7);      /* ADDR param max size is 6 */
2244
2245         if (type & CONTACTS_ADDRESS_TYPE_HOME) {
2246                 strv[i] = g_strdup("HOME");
2247                 i++;
2248         }
2249         if (type & CONTACTS_ADDRESS_TYPE_WORK) {
2250                 strv[i] = g_strdup("WORK");
2251                 i++;
2252         }
2253         if (type & CONTACTS_ADDRESS_TYPE_DOM) {
2254                 strv[i] = g_strdup("DOM");
2255                 i++;
2256         }
2257         if (type & CONTACTS_ADDRESS_TYPE_INTL) {
2258                 strv[i] = g_strdup("INTL");
2259                 i++;
2260         }
2261         if (type & CONTACTS_ADDRESS_TYPE_POSTAL) {
2262                 strv[i] = g_strdup("POSTAL");
2263                 i++;
2264         }
2265         if (type & CONTACTS_ADDRESS_TYPE_PARCEL) {
2266                 strv[i] = g_strdup("PARCEL");
2267                 i++;
2268         }
2269         FN_END;
2270         return strv;
2271 }
2272
2273 static gchar *__bluetooth_pb_phonelog_datetime(gint phonelog_id)
2274 {
2275         FN_START;
2276         contacts_record_h phone_log;
2277
2278         char time_str[32] = {0,};
2279
2280         gint status;
2281         gint time = 0;
2282
2283         struct tm time_info;
2284
2285         status = contacts_db_get_record(_contacts_phone_log._uri,
2286                         phonelog_id,
2287                         &phone_log);
2288
2289         if (status != CONTACTS_ERROR_NONE)
2290                 return NULL;
2291
2292         status = contacts_record_get_int(phone_log,
2293                         _contacts_phone_log.log_time,
2294                         &time);
2295
2296         if (status != CONTACTS_ERROR_NONE)
2297                 return NULL;
2298
2299         if (time <= 0)
2300                 return NULL;
2301
2302         localtime_r((time_t *)&time, &time_info);
2303
2304         strftime(time_str, sizeof(time_str),
2305                         "%Y%m%dT%H%M%S", &time_info);
2306
2307         contacts_record_destroy(phone_log, TRUE);
2308
2309         FN_END;
2310         return g_strdup(time_str);
2311 }
2312
2313 static gchar *__bluetooth_pb_name_from_contact(contacts_record_h contact)
2314 {
2315         FN_START;
2316         contacts_record_h name = NULL;
2317
2318         GString *str;
2319         gint status;
2320         gint i;
2321
2322         gint name_size = 5;
2323         gint name_val[] = { _contacts_name.last,
2324                         _contacts_name.first,
2325                         _contacts_name.addition,
2326                         _contacts_name.prefix,
2327                         _contacts_name.suffix };
2328
2329
2330         status = contacts_record_get_child_record_at_p(contact,
2331                         _contacts_contact.name, 0, &name);
2332
2333         if (status != CONTACTS_ERROR_NONE)
2334                 return NULL;
2335
2336         str = g_string_new(NULL);
2337
2338         for (i = 0; i < name_size; i++) {
2339                 gchar *tmp = NULL;
2340                 gchar *escape = NULL;
2341
2342                 if (i > 0)
2343                         g_string_append_c(str, ';');
2344
2345                 status = contacts_record_get_str_p(name, name_val[i], &tmp);
2346
2347                 if (status != CONTACTS_ERROR_NONE)
2348                         continue;
2349
2350                 escape = __bluetooth_pb_vcard_escape(tmp);
2351                 g_string_append(str, escape);
2352
2353                 g_free(escape);
2354         }
2355
2356         FN_END;
2357         return g_string_free(str, FALSE);
2358 }
2359
2360 static gchar *__bluetooth_pb_phonetic_name_from_contact(contacts_record_h contact)
2361 {
2362         FN_START;
2363         contacts_record_h name = NULL;
2364
2365         GString *str;
2366
2367         gint status;
2368
2369         gchar *phonetic_first = NULL;
2370         gchar *phonetic_last = NULL;
2371         gchar *escape = NULL;
2372
2373         status = contacts_record_get_child_record_at_p(contact,
2374                         _contacts_contact.name, 0, &name);
2375
2376         if (status != CONTACTS_ERROR_NONE)
2377                 return NULL;
2378
2379         status = contacts_record_get_str_p(name, _contacts_name.phonetic_first, &phonetic_first);
2380
2381         if (status != CONTACTS_ERROR_NONE)
2382                 return NULL;
2383
2384         if (phonetic_first == NULL)
2385                 return NULL;
2386
2387         str = g_string_new(NULL);
2388
2389         status = contacts_record_get_str_p(name, _contacts_name.phonetic_last, &phonetic_last);
2390
2391         if ((status == CONTACTS_ERROR_NONE) && (phonetic_last != NULL)) {
2392                 escape = __bluetooth_pb_vcard_escape(phonetic_last);
2393                 g_string_append(str, escape);
2394                 g_free(escape);
2395                 g_string_append_c(str, ' ');
2396         }
2397
2398         escape = __bluetooth_pb_vcard_escape(phonetic_first);
2399         g_string_append(str, escape);
2400
2401         g_free(escape);
2402         g_string_append_c(str, ';');
2403         g_string_append_c(str, ';');
2404         g_string_append_c(str, ';');
2405         g_string_append_c(str, ';');
2406
2407         FN_END;
2408         return g_string_free(str, FALSE);
2409 }
2410
2411
2412 static gchar *__bluetooth_pb_number_from_contact(contacts_record_h contact)
2413 {
2414         FN_START;
2415         gint count = 0;
2416
2417         gint status;
2418         gint i;
2419
2420         gchar *str = NULL;
2421
2422         status = contacts_record_get_child_record_count(contact,
2423                         _contacts_contact.number,
2424                         &count);
2425
2426         if (status != CONTACTS_ERROR_NONE)
2427                 return NULL;
2428
2429         for (i = 0; i < count; i++) {
2430                 contacts_record_h number = NULL;
2431
2432                 gchar *tmp = NULL;
2433
2434                 bool is_default = false;
2435
2436                 status = contacts_record_get_child_record_at_p(contact,
2437                                 _contacts_contact.number, i, &number);
2438
2439                 if (status != CONTACTS_ERROR_NONE)
2440                         continue;
2441
2442                 status = contacts_record_get_bool(number,
2443                                 _contacts_number.is_default,
2444                                 &is_default);
2445
2446                 if (status != CONTACTS_ERROR_NONE)
2447                         continue;
2448
2449                 if (is_default == FALSE)
2450                         continue;
2451
2452                 status = contacts_record_get_str_p(number,
2453                                 _contacts_number.number,
2454                                 &tmp);
2455
2456                 if (status != CONTACTS_ERROR_NONE)
2457                         continue;
2458
2459                 if (tmp) {
2460                         str = g_strdup(tmp);
2461                         break;
2462                 }
2463         }
2464
2465         /* get first number */
2466         if (str == NULL) {
2467                 gchar *tmp = NULL;
2468
2469                 contacts_record_h number = NULL;
2470
2471                 status = contacts_record_get_child_record_at_p(contact,
2472                                 _contacts_contact.number, 0, &number);
2473
2474                 if (status != CONTACTS_ERROR_NONE)
2475                         return NULL;
2476
2477                 status = contacts_record_get_str_p(number,
2478                                 _contacts_number.number,
2479                                 &tmp);
2480
2481                 if (status != CONTACTS_ERROR_NONE)
2482                         return NULL;
2483
2484                 str = g_strdup(tmp);
2485         }
2486
2487         FN_END;
2488         return str;
2489 }
2490
2491 static gint __bluetooth_pb_person_id_from_phonelog_id(gint phonelog_id)
2492 {
2493         FN_START;
2494         contacts_query_h query = NULL;
2495         contacts_filter_h filter = NULL;
2496         contacts_list_h record_list = NULL;
2497
2498         contacts_record_h phone_log = NULL;
2499         contacts_record_h record = NULL;
2500
2501         gint status;
2502         gint person_id = 0;
2503
2504         status = contacts_db_get_record(_contacts_phone_log._uri,
2505                         phonelog_id,
2506                         &phone_log);
2507
2508         if (status != CONTACTS_ERROR_NONE)
2509                 return 0;
2510
2511         status = contacts_record_get_int(phone_log,
2512                         _contacts_phone_log.person_id,
2513                         &person_id);
2514
2515         if (status != CONTACTS_ERROR_NONE) {
2516                 contacts_record_destroy(phone_log, TRUE);
2517                 return 0;
2518         }
2519
2520         contacts_record_destroy(phone_log, TRUE);
2521
2522         if (person_id)
2523                 return person_id;
2524
2525         status = contacts_filter_create(_contacts_person_phone_log._uri,
2526                         &filter);
2527
2528         if (status != CONTACTS_ERROR_NONE)
2529                 return 0;
2530
2531
2532         status = contacts_filter_add_int(filter,
2533                         _contacts_person_phone_log.log_id,
2534                         CONTACTS_MATCH_EQUAL,
2535                         phonelog_id);
2536
2537         if (status != CONTACTS_ERROR_NONE)
2538                 goto done;
2539
2540         status = contacts_query_create(_contacts_person_phone_log._uri, &query);
2541
2542         if (status != CONTACTS_ERROR_NONE)
2543                 goto done;
2544
2545         status = contacts_query_set_filter(query, filter);
2546
2547         if (status != CONTACTS_ERROR_NONE)
2548                 goto done;
2549
2550         status = contacts_db_get_records_with_query(query, -1, -1,
2551                                                                 &record_list);
2552
2553         if (status != CONTACTS_ERROR_NONE)
2554                 goto done;
2555
2556         status = contacts_list_first(record_list);
2557
2558         if (status != CONTACTS_ERROR_NONE)
2559                 goto done;
2560
2561         status = contacts_list_get_current_record_p(record_list, &record);
2562
2563         if (status != CONTACTS_ERROR_NONE)
2564                 goto done;
2565
2566         status = contacts_record_get_int(record,
2567                         _contacts_person_phone_log.person_id,
2568                         &person_id);
2569
2570         if (status != CONTACTS_ERROR_NONE)
2571                 goto done;
2572
2573 done:
2574         if (record_list != NULL)
2575                 contacts_list_destroy(record_list, TRUE);
2576
2577         contacts_filter_destroy(filter);
2578
2579         if (query != NULL)
2580                 contacts_query_destroy(query);
2581
2582         FN_END;
2583         return person_id;
2584 }
2585
2586 int _bluetooth_get_contact_addressbook(gint person_id)
2587 {
2588         contacts_record_h person = NULL;
2589         contacts_record_h contact = NULL;
2590         contacts_record_h addressbook = NULL;
2591
2592         char* addressbook_name = NULL;
2593         gint contact_id = 0;
2594         gint address_book_id = 0;
2595         gint status;
2596
2597         status = contacts_db_get_record(_contacts_person._uri,
2598                         person_id,
2599                         &person);
2600         if (status != CONTACTS_ERROR_NONE)
2601                 return PBAP_ADDRESSBOOK_PHONE; /* Default*/
2602
2603         status = contacts_record_get_int(person,
2604                         _contacts_person.display_contact_id,
2605                         &contact_id);
2606         contacts_record_destroy(person, TRUE);
2607
2608         if (status != CONTACTS_ERROR_NONE)
2609                 return PBAP_ADDRESSBOOK_PHONE; /* Default*/
2610
2611         status = contacts_db_get_record(_contacts_contact._uri,
2612                         contact_id,
2613                         &contact);
2614         if (status != CONTACTS_ERROR_NONE)
2615                 return PBAP_ADDRESSBOOK_PHONE; /* Default*/
2616
2617         status = contacts_record_get_int(contact,
2618                         _contacts_contact.address_book_id,
2619                         &address_book_id);
2620         contacts_record_destroy(contact, TRUE);
2621
2622         if (status != CONTACTS_ERROR_NONE)
2623                 return PBAP_ADDRESSBOOK_PHONE; /* Default*/
2624
2625         status = contacts_db_get_record(_contacts_address_book._uri,
2626                         address_book_id,
2627                         &addressbook);
2628         if (status != CONTACTS_ERROR_NONE)
2629                 return PBAP_ADDRESSBOOK_PHONE; /* Default*/
2630
2631         status = contacts_record_get_str_p(addressbook, _contacts_address_book.name,
2632                                                 &addressbook_name);
2633         contacts_record_destroy(addressbook, TRUE);
2634
2635         if (status != CONTACTS_ERROR_NONE)
2636                 return PBAP_ADDRESSBOOK_PHONE; /* Default*/
2637
2638         if (address_book_id == 0 || _bt_is_sim_addressbook(addressbook_name) == false)
2639                 return PBAP_ADDRESSBOOK_PHONE;
2640
2641         return PBAP_ADDRESSBOOK_SIM;
2642 }
2643 /* API for vcard */
2644 gchar *_bluetooth_pb_vcard_contact(gint person_id,
2645                                 guint64 filter,
2646                                 guint8 format)
2647 {
2648         FN_START;
2649         gchar *str = NULL;
2650
2651         if (person_id <= 0)
2652                 return NULL;
2653
2654         str = __bluetooth_pb_vcard_real_contact_with_properties(person_id, 0,
2655                         filter, format,
2656                         NULL);
2657         FN_END;
2658         return str;
2659 }
2660
2661 gchar *_bluetooth_pb_vcard_contact_owner(const gchar *number,
2662                                         guint64 filter,
2663                                         guint8 format)
2664 {
2665         FN_START;
2666         GString *str = g_string_new("BEGIN:VCARD\r\n");
2667         gchar *fn;
2668         gchar *name;
2669
2670         fn = _bluetooth_pb_owner_name();
2671         name = g_strdup_printf("%s;;;;", fn);
2672
2673         switch (format) {
2674         case VCARD_FORMAT_3_0:
2675                 g_string_append(str, "VERSION:3.0\r\n");
2676
2677                 __bluetooth_pb_vcard_append_v30(str, "N", NULL, name);
2678                 __bluetooth_pb_vcard_append_v30(str, "FN", NULL, fn);
2679                 __bluetooth_pb_vcard_append_v30(str, "TEL", "TYPE=CELL",
2680                                                                         number);
2681                 break;
2682         case VCARD_FORMAT_2_1:
2683         default:
2684                 g_string_append(str, "VERSION:2.1\r\n");
2685
2686                 __bluetooth_pb_vcard_append_qp_encode_v21(str, "N", NULL, name);
2687
2688                 if (filter == 0 || (filter & VCARD_FN))
2689                         __bluetooth_pb_vcard_append_qp_encode_v21(str, "FN",
2690                                                                 NULL, fn);
2691
2692                 __bluetooth_pb_vcard_append_qp_encode_v21(str, "TEL", "CELL",
2693                                                                         number);
2694                 break;
2695
2696         }
2697
2698         g_string_append(str, "END:VCARD\r\n");
2699
2700         g_free(fn);
2701         g_free(name);
2702
2703         FN_END;
2704         return g_string_free(str, FALSE);
2705 }
2706
2707 gchar *_bluetooth_pb_vcard_call(gint phonelog_id,
2708                                 guint64 filter,
2709                                 guint8 format,
2710                                 const gchar *attr)
2711 {
2712         FN_START;
2713         gint person_id = 0;
2714
2715         gchar *str = NULL;
2716
2717         if (attr == NULL) {
2718                 ERR("Unknown attribute type ignored\n");
2719                 return NULL;
2720         }
2721
2722         person_id = __bluetooth_pb_person_id_from_phonelog_id(phonelog_id);
2723
2724         DBG("person_id %d\n", person_id);
2725
2726         if (person_id) {
2727                 if (filter == 0 || (filter & VCARD_X_IRMC_CALL_DATETIME)) {
2728                         gchar *datetime = NULL;
2729
2730                         datetime = __bluetooth_pb_phonelog_datetime(
2731                                                                 phonelog_id);
2732
2733                         str = __bluetooth_pb_vcard_real_contact_with_properties(
2734                                         person_id,
2735                                         phonelog_id,
2736                                         filter, format,
2737                                         "X-IRMC-CALL-DATETIME", attr, datetime,
2738                                         NULL);
2739
2740                         if (datetime)
2741                                 g_free(datetime);
2742                 } else {
2743                         str = __bluetooth_pb_vcard_real_contact_with_properties(
2744                                         person_id,
2745                                         phonelog_id,
2746                                         filter, format,
2747                                         NULL);
2748                 }
2749         } else
2750                 str = __bluetooth_pb_vcard_real_call(phonelog_id, filter,
2751                                                                 format, attr);
2752
2753         FN_END;
2754         return str;
2755 }
2756
2757 gchar *_bluetooth_pb_fn_from_person_id(gint person_id)
2758 {
2759         FN_START;
2760         contacts_record_h person = NULL;
2761
2762         gint status;
2763
2764         gchar *str = NULL;
2765
2766         status = contacts_db_get_record(_contacts_person._uri,
2767                         person_id,
2768                         &person);
2769
2770         if (status != CONTACTS_ERROR_NONE)
2771                 return NULL;
2772
2773         status = contacts_record_get_str(person,
2774                         _contacts_person.display_name,
2775                         &str);
2776
2777         if (status != CONTACTS_ERROR_NONE)
2778                 return NULL;
2779
2780         contacts_record_destroy(person, TRUE);
2781
2782         FN_END;
2783         return str;
2784 }
2785
2786 gchar *_bluetooth_pb_name_from_person_id(gint person_id)
2787 {
2788         FN_START;
2789         contacts_record_h person = NULL;
2790         contacts_record_h contact = NULL;
2791
2792         gint status;
2793         gint contact_id = 0;
2794
2795         gchar *str;
2796
2797         status = contacts_db_get_record(_contacts_person._uri,
2798                         person_id,
2799                         &person);
2800
2801         if (status != CONTACTS_ERROR_NONE)
2802                 return NULL;
2803
2804         status = contacts_record_get_int(person,
2805                         _contacts_person.display_contact_id,
2806                         &contact_id);
2807
2808         if (status != CONTACTS_ERROR_NONE) {
2809                 contacts_record_destroy(person, TRUE);
2810                 return NULL;
2811         }
2812
2813         status = contacts_db_get_record(_contacts_contact._uri,
2814                         contact_id,
2815                         &contact);
2816
2817         if (status != CONTACTS_ERROR_NONE) {
2818                 contacts_record_destroy(person, TRUE);
2819                 return NULL;
2820         }
2821
2822         str = __bluetooth_pb_name_from_contact(contact);
2823
2824         contacts_record_destroy(contact, TRUE);
2825         contacts_record_destroy(person, TRUE);
2826
2827         FN_END;
2828         return str;
2829 }
2830
2831 gchar *_bluetooth_pb_number_from_person_id(gint person_id)
2832 {
2833         FN_START;
2834         contacts_record_h person = NULL;
2835         contacts_record_h contact = NULL;
2836
2837         gint status;
2838         gint contact_id = 0;
2839
2840         gchar *str;
2841
2842         status = contacts_db_get_record(_contacts_person._uri,
2843                         person_id,
2844                         &person);
2845
2846         if (status != CONTACTS_ERROR_NONE)
2847                 return NULL;
2848
2849
2850         status = contacts_record_get_int(person,
2851                         _contacts_person.display_contact_id,
2852                         &contact_id);
2853
2854         if (status != CONTACTS_ERROR_NONE) {
2855                 contacts_record_destroy(person, TRUE);
2856                 return NULL;
2857         }
2858
2859         status = contacts_db_get_record(_contacts_contact._uri,
2860                         contact_id,
2861                         &contact);
2862
2863         if (status != CONTACTS_ERROR_NONE) {
2864                 contacts_record_destroy(person, TRUE);
2865                 return NULL;
2866         }
2867
2868         str = __bluetooth_pb_number_from_contact(contact);
2869
2870         contacts_record_destroy(contact, TRUE);
2871         contacts_record_destroy(person, TRUE);
2872
2873         FN_END;
2874         return str;
2875 }
2876
2877 gchar *_bluetooth_pb_fn_from_phonelog_id(gint phonelog_id)
2878 {
2879         FN_START;
2880         gint person_id = 0;
2881         gchar *str = NULL;
2882
2883         person_id = __bluetooth_pb_person_id_from_phonelog_id(phonelog_id);
2884
2885         if (person_id > 0)
2886                 str = _bluetooth_pb_fn_from_person_id(person_id);
2887         else
2888                 str = g_strdup("");
2889
2890         FN_END;
2891         return str;
2892 }
2893
2894 gchar *_bluetooth_pb_name_from_phonelog_id(gint phonelog_id)
2895 {
2896         FN_START;
2897         gint person_id = 0;
2898         gchar *str = NULL;
2899
2900         person_id = __bluetooth_pb_person_id_from_phonelog_id(phonelog_id);
2901
2902         if (person_id > 0)
2903                 str = _bluetooth_pb_name_from_person_id(person_id);
2904         else {
2905                 gchar *tmp;
2906
2907                 tmp = _bluetooth_pb_number_from_phonelog_id(phonelog_id);
2908                 str = g_strdup_printf("%s;;;;", tmp);
2909
2910                 g_free(tmp);
2911         }
2912
2913         FN_END;
2914         return str;
2915 }
2916
2917 gchar *_bluetooth_pb_number_from_phonelog_id(gint phonelog_id)
2918 {
2919         FN_START;
2920         contacts_record_h phone_log;
2921
2922         gint status;
2923
2924         gchar *str;
2925         gchar *tmp = NULL;
2926
2927         status = contacts_db_get_record(_contacts_phone_log._uri,
2928                         phonelog_id, &phone_log);
2929
2930         if (status != CONTACTS_ERROR_NONE)
2931                 return NULL;
2932
2933         status = contacts_record_get_str_p(phone_log,
2934                         _contacts_phone_log.address,
2935                         &tmp);
2936
2937         if (status != CONTACTS_ERROR_NONE) {
2938                 contacts_record_destroy(phone_log, TRUE);
2939                 return NULL;
2940         }
2941
2942         str = g_strdup(tmp);
2943
2944         contacts_record_destroy(phone_log, TRUE);
2945
2946         FN_END;
2947         return str;
2948 }
2949
2950 gchar *_bluetooth_pb_owner_name(void)
2951 {
2952         FN_START;
2953         gchar *name;
2954
2955         name = vconf_get_str(VCONFKEY_SETAPPL_DEVICE_NAME_STR);
2956
2957         if (name == NULL)
2958                 name = g_strdup("My Name");
2959
2960         FN_END;
2961         return name;
2962 }
2963
2964 bool _bt_is_sim_addressbook(const char *addressbook)
2965 {
2966         return g_str_has_prefix(addressbook, SIM_ADDRESSBOOK_PREFIX);
2967 }