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