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