Fix the memory leak
[platform/core/connectivity/bluetooth-agent.git] / pb-agent / bluetooth_pb_agent.c
1 /*
2  * bluetooth-agent
3  *
4  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *              http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <unistd.h>
24 #include <signal.h>
25 #include <glib.h>
26 #include <dbus/dbus-glib.h>
27
28
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32
33 #include <contacts.h>
34
35 #include <TapiUtility.h>
36 #include <ITapiSim.h>
37
38 #include "bluetooth_pb_agent.h"
39 #include "bluetooth_pb_vcard.h"
40
41 #define BLUETOOTH_PB_AGENT_TIMEOUT 600
42
43 static gchar *bluetooth_pb_agent_folder_list[] = {
44         "/telecom/pb",
45         "/telecom/ich",
46         "/telecom/och",
47         "/telecom/mch",
48         "/telecom/cch",
49         NULL
50 };
51
52 typedef enum {
53         TELECOM_PB = 0,
54         TELECOM_ICH,
55         TELECOM_OCH,
56         TELECOM_MCH,
57         TELECOM_CCH,
58         TELECOM_NONE
59 } PhoneBookType;
60
61 typedef struct {
62         GObject parent;
63
64         DBusGConnection *bus;
65         DBusGProxy *proxy;
66
67         TapiHandle *tapi_handle;
68         gchar *tel_number;
69
70         GHashTable *contact_list;
71
72         guint timeout_id;
73
74         PhoneBookType pb_type;
75 } BluetoothPbAgent;
76
77 typedef struct {
78         GObjectClass parent;
79
80         void (*clear) (BluetoothPbAgent *agent);
81 } BluetoothPbAgentClass;
82
83 enum {
84         CLEAR,
85         LAST_SIGNAL
86 };
87
88 GType bluetooth_pb_agent_get_type(void);
89
90 #define BLUETOOTH_PB_TYPE_AGENT (bluetooth_pb_agent_get_type())
91
92 #define BLUETOOTH_PB_AGENT(object) \
93         (G_TYPE_CHECK_INSTANCE_CAST((object), \
94         BLUETOOTH_PB_TYPE_AGENT , BluetoothPbAgent))
95 #define BLUETOOTH_PB_AGENT_CLASS(klass) \
96         (G_TYPE_CHECK_CLASS_CAST((klass), \
97         BLUETOOTH_PB_TYPE_AGENT , BluetoothPbAgentClass))
98 #define BLUETOOTH_IS_PB_AGENT(object) \
99         (G_TYPE_CHECK_INSTANCE_TYPE((object), \
100         BLUETOOTH_PB_TYPE_AGENT))
101 #define BLUETOOTH_IS_PB_AGENT_CLASS(klass) \
102         (G_TYPE_CHECK_CLASS_TYPE((klass), \
103         BLUETOOTH_PB_TYPE_AGENT))
104 #define BLUETOOTH_PB_AGENT_GET_CLASS(obj) \
105         (G_TYPE_INSTANCE_GET_CLASS((obj), \
106         BLUETOOTH_PB_TYPE_AGENT , BluetoothPbAgentClass))
107
108 G_DEFINE_TYPE(BluetoothPbAgent, bluetooth_pb_agent, G_TYPE_OBJECT)
109
110 #define DBUS_STRUCT_STRING_STRING_UINT (dbus_g_type_get_struct("GValueArray", G_TYPE_STRING, \
111                                                         G_TYPE_STRING, G_TYPE_UINT, G_TYPE_INVALID))
112
113 static guint signals[LAST_SIGNAL] = { 0 };
114
115 static GMainLoop *mainloop = NULL;
116
117 static void bluetooth_pb_agent_finalize(GObject *obj);
118
119 static void bluetooth_pb_agent_clear(BluetoothPbAgent *agent);
120
121 /* Dbus messages */
122 static gboolean bluetooth_pb_get_phonebook_folder_list(BluetoothPbAgent *agent,
123                                                 const gchar ***folder_list,
124                                                 GError **error);
125
126 static gboolean bluetooth_pb_get_phonebook(BluetoothPbAgent *agent,
127                                         const char *name,
128                                         guint64 filter,
129                                         guint8 format,
130                                         guint16 max_list_count,
131                                         guint16 list_start_offset,
132                                         DBusGMethodInvocation *context);
133
134 static gboolean bluetooth_pb_get_phonebook_size(BluetoothPbAgent *agent,
135                                                 const char *name,
136                                                 DBusGMethodInvocation *context);
137
138 static gboolean bluetooth_pb_get_phonebook_list(BluetoothPbAgent *agent,
139                                                 const char *name,
140                                                 DBusGMethodInvocation *context);
141
142 static gboolean bluetooth_pb_get_phonebook_entry(BluetoothPbAgent *agent,
143                                                 const gchar *folder,
144                                                 const gchar *id,
145                                                 guint64 filter,
146                                                 guint8 format,
147                                                 DBusGMethodInvocation *context);
148
149 static gboolean bluetooth_pb_get_phonebook_size_at(BluetoothPbAgent *agent,
150                                         const gchar *command,
151                                         DBusGMethodInvocation *context);
152
153 static gboolean bluetooth_pb_get_phonebook_entries_at(BluetoothPbAgent *agent,
154                                         const gchar *command,
155                                         gint32 start_index,
156                                         gint32 end_index,
157                                         DBusGMethodInvocation *context);
158
159 static gboolean bluetooth_pb_get_phonebook_entries_find_at(BluetoothPbAgent *agent,
160                                                         const gchar *command,
161                                                         const gchar *find_text,
162                                                         DBusGMethodInvocation *context);
163
164 static gboolean bluetooth_pb_get_total_object_count(BluetoothPbAgent *agent,
165                                                 gchar *path,
166                                                 DBusGMethodInvocation *context);
167
168 static gboolean bluetooth_pb_add_contact (BluetoothPbAgent *agent,
169                                         const char *filename,
170                                         GError **error);
171
172 static void __bluetooth_pb_dbus_return_error(DBusGMethodInvocation *context,
173                                         gint code,
174                                         const gchar *message);
175
176 static PhoneBookType __bluetooth_pb_get_pb_type(const char *name);
177
178 static PhoneBookType __bluetooth_pb_get_storage_pb_type(const char *name);
179
180 static gint __bluetooth_pb_phone_log_filter_append(contacts_filter_h filter,
181                                                 gint *match,
182                                                 gint size);
183
184 static contacts_query_h __bluetooth_pb_query_phone_log(gint *match,
185                                                 gint size);
186
187 static contacts_query_h __bluetooth_pb_query_person(void);
188
189 static contacts_query_h __bluetooth_pb_query_person_number(void);
190
191 static contacts_query_h __bluetooth_pb_query_phone_log_incoming(void);
192
193 static contacts_query_h __bluetooth_pb_query_phone_log_outgoing(void);
194
195 static contacts_query_h __bluetooth_pb_query_phone_log_missed(void);
196
197 static contacts_query_h __bluetooth_pb_query_phone_log_combined(void);
198
199 static gboolean __bluetooth_pb_get_count(PhoneBookType pb_type,
200                                 guint *count);
201
202 static gboolean __bluetooth_pb_get_count_new_missed_call(guint *count);
203
204 static const char *__bluetooth_pb_phone_log_get_log_type(contacts_record_h record);
205
206 static void __bluetooth_pb_get_vcards(BluetoothPbAgent *agent,
207                                 PhoneBookType pb_type,
208                                 guint64 filter,
209                                 guint8 format,
210                                 guint16 max_list_count,
211                                 guint16 list_start_offset,
212                                 GPtrArray *vcards);
213
214 static void __bluetooth_pb_get_contact_list(BluetoothPbAgent *agent,
215                                         contacts_query_h query,
216                                         GPtrArray *ptr_array);
217
218 static void __bluetooth_pb_get_phone_log_list(BluetoothPbAgent *agent,
219                                         contacts_query_h query,
220                                         GPtrArray *ptr_array);
221
222 static void __bluetooth_pb_get_list(BluetoothPbAgent *agent,
223                                 PhoneBookType pb_type,
224                                 GPtrArray *ptr_array);
225
226 static void __bluetooth_pb_get_contact_list_number(BluetoothPbAgent *agent,
227                                                 contacts_query_h query,
228                                                 gint start_index,
229                                                 gint end_index,
230                                                 GPtrArray *ptr_array);
231
232 static void __bluetooth_pb_get_phone_log_list_number(BluetoothPbAgent *agent,
233                                                 contacts_query_h query,
234                                                 gint start_index,
235                                                 gint end_index,
236                                                 GPtrArray *ptr_array);
237
238 static void __bluetooth_pb_get_list_number(BluetoothPbAgent *agent,
239                                                 PhoneBookType pb_type,
240                                                 gint start_index,
241                                                 gint end_index,
242                                                 GPtrArray *ptr_array);
243
244 static void __bluetooth_pb_get_contact_list_name(BluetoothPbAgent *agent,
245                                                 contacts_query_h query,
246                                                 const gchar *find_text,
247                                                 GPtrArray *ptr_array);
248
249 static void __bluetooth_pb_get_phone_log_list_name(BluetoothPbAgent *agent,
250                                                 contacts_query_h query,
251                                                 const gchar *find_text,
252                                                 GPtrArray *ptr_array);
253
254 static void __bluetooth_pb_get_list_name(BluetoothPbAgent *agent,
255                                         PhoneBookType pb_type,
256                                         const gchar *find_text,
257                                         GPtrArray *ptr_array);
258
259 static void __bluetooth_pb_list_hash_reset(BluetoothPbAgent *agent);
260
261 static gboolean __bluetooth_pb_list_hash_insert(BluetoothPbAgent *agent,
262                                                 gint handle,
263                                                 gint id);
264
265 static gint __bluetooth_pb_list_hash_lookup_id(BluetoothPbAgent *agent,
266                                         gint handle);
267
268 static void __bluetooth_pb_list_ptr_array_add(GPtrArray *ptr_array,
269                                                 const gchar *name,
270                                                 const gchar *number,
271                                                 gint handle);
272
273 static void __bluetooth_pb_list_ptr_array_free(gpointer data);
274
275 static void __bluetooth_pb_agent_signal_handler(int signum);
276
277 static void __bluetooth_pb_contact_changed(const gchar *view_uri,
278                                         void *user_data);
279
280 static void __bluetooth_pb_agent_timeout_add_seconds(BluetoothPbAgent *agent);
281
282 static gboolean __bluetooth_pb_agent_timeout_calback(gpointer user_data);
283
284 static void __bluetooth_pb_tel_callback(TapiHandle *handle,
285                                         int result,
286                                         void *data,
287                                         void *user_data);
288
289 static void __bluetooth_pb_agent_dbus_init(BluetoothPbAgent *agent);
290
291 #include "bluetooth_pb_agent_glue.h"
292
293 static void bluetooth_pb_agent_init(BluetoothPbAgent *agent)
294 {
295         agent->bus = NULL;
296         agent->proxy = NULL;
297
298         agent->tapi_handle = NULL;
299         agent->tel_number = NULL;
300
301         agent->contact_list = NULL;
302         agent->timeout_id = 0;
303
304         agent->pb_type = TELECOM_NONE;
305 }
306
307 static void bluetooth_pb_agent_class_init(BluetoothPbAgentClass *klass)
308 {
309         GObjectClass *object_class = (GObjectClass *) klass;
310
311         klass->clear = bluetooth_pb_agent_clear;
312
313         object_class->finalize = bluetooth_pb_agent_finalize;
314
315         signals[CLEAR] = g_signal_new("clear",
316                         G_TYPE_FROM_CLASS(klass),
317                         G_SIGNAL_RUN_LAST,
318                         G_STRUCT_OFFSET(BluetoothPbAgentClass, clear),
319                         NULL, NULL,
320                         g_cclosure_marshal_VOID__VOID,
321                         G_TYPE_NONE, 0);
322
323         dbus_g_object_type_install_info(BLUETOOTH_PB_TYPE_AGENT,
324                                         &dbus_glib_bluetooth_pb_object_info);
325 }
326
327 static void bluetooth_pb_agent_finalize(GObject *obj)
328 {
329         BluetoothPbAgent *agent  = BLUETOOTH_PB_AGENT(obj);
330
331         DBG("+\n");
332
333         if (agent->tapi_handle) {
334                 tel_deinit(agent->tapi_handle);
335                 agent->tapi_handle = NULL;
336         }
337
338         if (agent->tel_number) {
339                 g_free(agent->tel_number);
340                 agent->tel_number = NULL;
341         }
342
343         if(agent->timeout_id) {
344                 g_source_remove(agent->timeout_id);
345                 agent->timeout_id = 0;
346         }
347
348         if (agent->contact_list) {
349                 g_hash_table_destroy(agent->contact_list);
350                 agent->contact_list = NULL;
351         }
352
353         if (agent->proxy) {
354                 g_object_unref(agent->proxy);
355                 agent->proxy = NULL;
356         }
357
358         if (agent->bus) {
359                 dbus_g_connection_unref(agent->bus);
360                 agent->bus = NULL;
361         }
362
363
364         G_OBJECT_CLASS(bluetooth_pb_agent_parent_class)->finalize(obj);
365 }
366
367 static void bluetooth_pb_agent_clear(BluetoothPbAgent *agent)
368 {
369         DBG("+\n");
370
371         if (agent->contact_list) {
372                 g_hash_table_destroy(agent->contact_list);
373                 agent->contact_list = NULL;
374         }
375
376         agent->pb_type = TELECOM_NONE;
377 }
378
379 static gboolean bluetooth_pb_get_phonebook_folder_list(BluetoothPbAgent *agent,
380                                                 const gchar ***folder_list,
381                                                 GError **error)
382 {
383         gint size;
384         gint i;
385         gchar **folder;
386
387         size = G_N_ELEMENTS(bluetooth_pb_agent_folder_list);
388         folder = g_new0(gchar *, size);
389
390         for (i = 0; i < size; i++)
391                 folder[i] = g_strdup(bluetooth_pb_agent_folder_list[i]);
392
393         *folder_list = (const gchar **)folder;
394
395         return TRUE;
396 }
397
398 static gboolean bluetooth_pb_get_phonebook(BluetoothPbAgent *agent,
399                                         const char *name,
400                                         guint64 filter,
401                                         guint8 format,
402                                         guint16 max_list_count,
403                                         guint16 list_start_offset,
404                                         DBusGMethodInvocation *context)
405 {
406         PhoneBookType pb_type = TELECOM_NONE;
407         GPtrArray *vcards = NULL;
408         gchar **vcards_str = NULL;
409
410         guint new_missed_call = 0;
411
412         DBG("name: %s filter: %lld format: %d max_list_count: %d list_start_offset: %d\n",
413                         name, filter, format, max_list_count, list_start_offset);
414
415         __bluetooth_pb_agent_timeout_add_seconds(agent);
416
417         pb_type = __bluetooth_pb_get_pb_type(name);
418
419         if (pb_type == TELECOM_NONE) {
420                 __bluetooth_pb_dbus_return_error(context,
421                                         G_FILE_ERROR_INVAL,
422                                         "unsupported name defined");
423                 return FALSE;
424         }
425
426         vcards = g_ptr_array_new();
427
428         if (max_list_count > 0) {
429                 __bluetooth_pb_get_vcards(agent, pb_type,
430                                 filter, format,
431                                 max_list_count, list_start_offset,
432                                 vcards);
433
434         }
435
436         g_ptr_array_add(vcards, NULL);
437
438         vcards_str = (gchar **) g_ptr_array_free(vcards, FALSE);
439
440         dbus_g_method_return(context, vcards_str, new_missed_call);
441
442         g_strfreev(vcards_str);
443
444         return TRUE;
445 }
446
447 static gboolean bluetooth_pb_get_phonebook_size(BluetoothPbAgent *agent,
448                                                 const char *name,
449                                                 DBusGMethodInvocation *context)
450 {
451         PhoneBookType pb_type = TELECOM_NONE;
452
453         guint new_missed_call = 0;
454         guint count = 0;
455
456         DBG("name: %s\n", name);
457
458         __bluetooth_pb_agent_timeout_add_seconds(agent);
459
460         pb_type = __bluetooth_pb_get_pb_type(name);
461
462         if (__bluetooth_pb_get_count(pb_type, &count) == FALSE) {
463                 __bluetooth_pb_dbus_return_error(context,
464                                         G_FILE_ERROR_INVAL,
465                                         "unsupported name defined");
466                 return FALSE;
467         }
468
469         /* for owner */
470         if (pb_type == TELECOM_PB)
471                 count++;
472
473         __bluetooth_pb_get_count_new_missed_call(&new_missed_call);
474
475         dbus_g_method_return(context, count, new_missed_call);
476
477         return TRUE;
478 }
479
480
481 static gboolean bluetooth_pb_get_phonebook_list(BluetoothPbAgent *agent,
482                                                 const char *name,
483                                                 DBusGMethodInvocation *context)
484 {
485         PhoneBookType pb_type = TELECOM_NONE;
486
487         GPtrArray *ptr_array;
488
489         DBG("name: %s\n", name);
490
491         __bluetooth_pb_agent_timeout_add_seconds(agent);
492
493         pb_type = __bluetooth_pb_get_pb_type(name);
494
495         if (pb_type == TELECOM_NONE) {
496                 __bluetooth_pb_dbus_return_error(context,
497                                         G_FILE_ERROR_INVAL,
498                                         "unsupported name defined");
499                 return FALSE;
500         }
501
502         ptr_array = g_ptr_array_new_with_free_func(__bluetooth_pb_list_ptr_array_free);
503
504         __bluetooth_pb_get_list(agent, pb_type, ptr_array);
505
506         dbus_g_method_return(context, ptr_array);
507
508         if (ptr_array)
509                 g_ptr_array_free(ptr_array, TRUE);
510
511         return TRUE;
512 }
513
514
515 static gboolean bluetooth_pb_get_phonebook_entry(BluetoothPbAgent *agent,
516                                                 const gchar *folder,
517                                                 const gchar *id,
518                                                 guint64 filter,
519                                                 guint8 format,
520                                                 DBusGMethodInvocation *context)
521 {
522         PhoneBookType pb_type = TELECOM_NONE;
523
524         gint handle = 0;
525         gint cid = -1;
526         gchar *str = NULL;
527
528         const gchar *attr = NULL;
529
530         DBG("folder: %s id: %s filter: %ld format: %d\n",
531                         folder, id, filter, format);
532
533         __bluetooth_pb_agent_timeout_add_seconds(agent);
534
535         if (!g_str_has_suffix(id, ".vcf")) {
536                 __bluetooth_pb_dbus_return_error(context,
537                                         G_FILE_ERROR_INVAL,
538                                         "invalid vcf file");
539                 return FALSE;
540         }
541
542         handle = (gint)g_ascii_strtoll(id, NULL, 10);
543
544         pb_type = __bluetooth_pb_get_pb_type(folder);
545
546         if (pb_type == TELECOM_NONE) {
547                 __bluetooth_pb_dbus_return_error(context,
548                                 G_FILE_ERROR_INVAL,
549                                 "unsupported name defined");
550                 return FALSE;
551         }
552
553         /* create index cache */
554         __bluetooth_pb_get_list(agent, pb_type, NULL);
555
556         cid = __bluetooth_pb_list_hash_lookup_id(agent, handle);
557
558         switch(pb_type) {
559         case TELECOM_PB:
560                 if (handle == 0) {
561                         str = _bluetooth_pb_vcard_contact_owner(agent->tel_number,
562                                                                 filter, format);
563                 } else {
564                         str = _bluetooth_pb_vcard_contact(cid, filter, format);
565                 }
566                 break;
567         case TELECOM_ICH:
568                 str = _bluetooth_pb_vcard_call(cid, filter, format, "RECEIVED");
569                 break;
570         case TELECOM_OCH:
571                 str = _bluetooth_pb_vcard_call(cid, filter, format, "DIALED");
572                 break;
573         case TELECOM_MCH:
574                 str = _bluetooth_pb_vcard_call(cid, filter, format, "MISSED");
575                 break;
576         case TELECOM_CCH: {
577                 contacts_record_h record = NULL;
578
579                 gint status;
580
581                 status = contacts_db_get_record(_contacts_phone_log._uri,
582                                 cid, &record);
583
584                 if (status != CONTACTS_ERROR_NONE)
585                         break;
586
587                 attr = __bluetooth_pb_phone_log_get_log_type(record);
588                 str = _bluetooth_pb_vcard_call(cid, filter, format, attr);
589
590                 contacts_record_destroy(record, TRUE);
591                 break;
592         }
593         default:
594                 __bluetooth_pb_dbus_return_error(context,
595                                         G_FILE_ERROR_INVAL,
596                                         "unsupported name defined");
597                 return FALSE;
598         }
599
600         dbus_g_method_return(context, str);
601         g_free(str);
602
603         return TRUE;
604 }
605
606 static gboolean bluetooth_pb_get_phonebook_size_at(BluetoothPbAgent *agent,
607                                         const gchar *command,
608                                         DBusGMethodInvocation *context)
609 {
610         PhoneBookType pb_type = TELECOM_NONE;
611         guint count = 0;
612
613         DBG("command: %s\n", command);
614
615         __bluetooth_pb_agent_timeout_add_seconds(agent);
616
617         pb_type = __bluetooth_pb_get_storage_pb_type(command);
618
619         if (__bluetooth_pb_get_count(pb_type, &count) == FALSE) {
620                 __bluetooth_pb_dbus_return_error(context,
621                                         G_FILE_ERROR_INVAL,
622                                         "unsupported name defined");
623                 return FALSE;
624         }
625
626         dbus_g_method_return(context, count);
627
628         return TRUE;
629 }
630
631 static gboolean bluetooth_pb_get_phonebook_entries_at(BluetoothPbAgent *agent,
632                                         const gchar *command,
633                                         gint start_index,
634                                         gint end_index,
635                                         DBusGMethodInvocation *context)
636 {
637         PhoneBookType pb_type = TELECOM_NONE;
638
639         GPtrArray *ptr_array = NULL;
640
641         DBG("command: %s, start_index: %d, end_index: %d\n",
642                         command, start_index, end_index);
643
644         __bluetooth_pb_agent_timeout_add_seconds(agent);
645
646         pb_type = __bluetooth_pb_get_storage_pb_type(command);
647
648         if (pb_type == TELECOM_NONE || pb_type == TELECOM_CCH) {
649                 __bluetooth_pb_dbus_return_error(context,
650                                         G_FILE_ERROR_INVAL,
651                                         "unsupported name defined");
652                 return FALSE;
653         }
654
655         ptr_array = g_ptr_array_new_with_free_func(__bluetooth_pb_list_ptr_array_free);
656
657         __bluetooth_pb_get_list_number(agent, pb_type,
658                         start_index, end_index,
659                         ptr_array);
660
661         dbus_g_method_return(context, ptr_array);
662
663         if (ptr_array)
664                 g_ptr_array_free(ptr_array, TRUE);
665
666         return TRUE;
667 }
668
669 static gboolean bluetooth_pb_get_phonebook_entries_find_at(BluetoothPbAgent *agent,
670                                                         const gchar *command,
671                                                         const gchar *find_text,
672                                                         DBusGMethodInvocation *context)
673 {
674         PhoneBookType pb_type = TELECOM_NONE;
675
676         GPtrArray *ptr_array = NULL;
677
678         DBG("command: %s, find text: %s\n", command, find_text);
679
680         __bluetooth_pb_agent_timeout_add_seconds(agent);
681
682         pb_type = __bluetooth_pb_get_storage_pb_type(command);
683
684         if (pb_type == TELECOM_NONE || pb_type == TELECOM_CCH) {
685                 __bluetooth_pb_dbus_return_error(context,
686                                         G_FILE_ERROR_INVAL,
687                                         "unsupported name defined");
688                 return FALSE;
689         }
690
691         ptr_array = g_ptr_array_new_with_free_func(__bluetooth_pb_list_ptr_array_free);
692
693         __bluetooth_pb_get_list_name(agent, pb_type,
694                         find_text, ptr_array);
695
696         dbus_g_method_return(context, ptr_array);
697
698         if (ptr_array)
699                 g_ptr_array_free(ptr_array, TRUE);
700
701         return TRUE;
702 }
703
704 static gboolean bluetooth_pb_get_total_object_count(BluetoothPbAgent *agent,
705                                         gchar *path, DBusGMethodInvocation *context)
706 {
707         guint count = 0;
708         PhoneBookType pb_type = TELECOM_NONE;
709
710         DBG("%s() %d\n", __FUNCTION__, __LINE__);
711
712         __bluetooth_pb_agent_timeout_add_seconds(agent);
713
714         pb_type = __bluetooth_pb_get_storage_pb_type(path);
715
716         if (__bluetooth_pb_get_count(pb_type, &count) == FALSE) {
717                 __bluetooth_pb_dbus_return_error(context,
718                                         G_FILE_ERROR_INVAL,
719                                         "unsupported name defined");
720                 return FALSE;
721         }
722
723         dbus_g_method_return(context, count);
724
725         DBG("%s() %d\n", __FUNCTION__, __LINE__);
726
727         return TRUE;
728 }
729
730
731 #if 0
732 static int __bluetooth_pb_agent_read_file(const char *file_path, char **stream)
733 {
734         FILE *fp = NULL;
735         int read_len = -1;
736         int received_file_size = 0;
737         struct stat file_attr;
738
739         if (file_path == NULL || stream == NULL) {
740                 DBG("Invalid data \n");
741                 return -1;
742         }
743
744         DBG("file_path = %s\n", file_path);
745
746         if ((fp = fopen(file_path, "r+")) == NULL) {
747                 DBG("Cannot open %s\n", file_path);
748                 return -1;
749         }
750
751         if (fstat(fileno(fp), &file_attr) == 0) {
752                 received_file_size = file_attr.st_size;
753                 DBG("file_attr.st_size = %d, size = %d\n", file_attr.st_size, received_file_size);
754
755                 if (received_file_size <= 0) {
756                         DBG("Some problem in the file size [%s]  \n", file_path);
757                         fclose(fp);
758                         fp = NULL;
759                         return -1;
760                 }
761
762                 *stream = (char *)malloc(sizeof(char) * received_file_size);
763                 if (NULL == *stream) {
764                         fclose(fp);
765                         fp = NULL;
766                         return -1;
767                 }
768         } else {
769                 DBG("Some problem in the file [%s]  \n", file_path);
770                 fclose(fp);
771                 fp = NULL;
772                 return -1;
773         }
774
775         read_len = fread(*stream, 1, received_file_size, fp);
776
777         if (read_len == 0) {
778                 if (fp != NULL) {
779                         fclose(fp);
780                         fp = NULL;
781                 }
782                 DBG("Cannot open %s\n", file_path);
783                 return -1;
784         }
785
786         if (fp != NULL) {
787                 fclose(fp);
788                 fp = NULL;
789         }
790         return 0;
791 }
792 #endif
793
794 static gboolean bluetooth_pb_add_contact(BluetoothPbAgent *agent, const char *filename,
795                                          GError **error)
796 {
797         /* Contact API is changed, Temporary blocked */
798 #if 0
799         CTSstruct *contact_record = NULL;
800         GSList *numbers_list = NULL, *cursor;
801         int is_success = 0;
802         int is_duplicated = 0;
803         int err = 0;
804         char *stream = NULL;
805
806         DBG("file_path = %s\n", filename);
807
808         err = contacts_svc_connect();
809         DBG("contact_db_service_connect fucntion call [error] = %d \n", err);
810
811         err = __bluetooth_pb_agent_read_file(filename, &stream);
812
813         if (err != 0) {
814                 contacts_svc_disconnect();
815                 DBG("contacts_svc_disconnect fucntion call [error] = %d \n", err);
816
817                 if (NULL != stream) {
818                         free(stream);
819                         stream = NULL;
820                 }
821                 return FALSE;
822         }
823
824         is_success = contacts_svc_get_contact_from_vcard((const void *)stream, &contact_record);
825
826         DBG("contacts_svc_get_contact_from_vcard fucntion call [is_success] = %d \n", is_success);
827
828         if (0 == is_success) {
829                 contacts_svc_struct_get_list(contact_record, CTS_CF_NUMBER_LIST, &numbers_list);
830                 cursor = numbers_list;
831
832                 for (; cursor; cursor = g_slist_next(cursor)) {
833                         if (contacts_svc_find_contact_by(CTS_FIND_BY_NUMBER,
834                                                         contacts_svc_value_get_str(cursor->data,
835                                                                 CTS_NUM_VAL_NUMBER_STR)) > 0) {
836                                 DBG("is_duplicated\n");
837                                 is_duplicated = TRUE;
838                         }
839                 }
840
841                 if (is_duplicated == FALSE) {
842                         contacts_svc_insert_contact(0, contact_record);
843                 }
844         } else {
845                 DBG("Fail \n");
846         }
847
848         err = contacts_svc_disconnect();
849         DBG("contacts_svc_disconnect fucntion call [error] = %d \n", err);
850
851         if (NULL != stream) {
852                 free(stream);
853                 stream = NULL;
854         }
855 #endif
856
857         return TRUE;
858 }
859
860 static void __bluetooth_pb_dbus_return_error(DBusGMethodInvocation *context,
861                                         gint code,
862                                         const gchar *message)
863 {
864         GQuark quark;
865         GError *error = NULL;
866
867         quark = g_type_qname(bluetooth_pb_agent_get_type());
868         error = g_error_new_literal(quark, code, message);
869
870         DBG("%s\n", message);
871
872         dbus_g_method_return_error(context, error);
873         g_error_free(error);
874 }
875
876 static PhoneBookType __bluetooth_pb_get_pb_type(const char *name)
877 {
878         gchar *suffix = ".vcf";
879         gint len;
880         gint size;
881         gint i;
882
883         if (name == NULL)
884                 return TELECOM_NONE;
885
886         len = strlen(name);
887
888         if (g_str_has_suffix(name, suffix))
889                 len -= strlen(suffix);
890
891         size = G_N_ELEMENTS(bluetooth_pb_agent_folder_list) - 1;
892         for (i = 0; i < size; i++) {
893                 if (strncmp(name, bluetooth_pb_agent_folder_list[i], len) == 0)
894                         return i;
895         }
896
897         return TELECOM_NONE;
898 }
899
900 static PhoneBookType __bluetooth_pb_get_storage_pb_type(const char *name)
901 {
902         if (name == NULL)
903                 return TELECOM_NONE;
904
905         if (g_strcmp0(name, "\"ME\"") == 0 )
906                 return TELECOM_PB;
907
908         if (g_strcmp0(name, "\"RC\"") == 0)
909                 return TELECOM_ICH;
910
911         if (g_strcmp0(name, "\"DC\"") == 0)
912                 return TELECOM_OCH;
913
914         if (g_strcmp0(name, "\"MC\"") == 0)
915                 return TELECOM_MCH;
916
917         return TELECOM_NONE;
918 }
919
920 static gint __bluetooth_pb_phone_log_filter_append(contacts_filter_h filter,
921                                                 gint *match,
922                                                 gint size)
923 {
924         gint i;
925         gint status;
926
927         for (i = 0; i < size; i++) {
928
929                 if ( i > 0) {
930                         status = contacts_filter_add_operator(filter,
931                                         CONTACTS_FILTER_OPERATOR_OR);
932
933                         if (status != CONTACTS_ERROR_NONE)
934                                 return status;
935                 }
936
937                 status = contacts_filter_add_int(filter,
938                                 _contacts_phone_log.log_type,
939                                 CONTACTS_MATCH_EQUAL,
940                                 match[i]);
941
942                 if (status != CONTACTS_ERROR_NONE)
943                         return status;
944         }
945
946         return CONTACTS_ERROR_NONE;
947 }
948
949 static contacts_query_h __bluetooth_pb_query_phone_log(gint *match,
950                                                 gint size)
951 {
952         contacts_query_h query = NULL;
953         contacts_filter_h filter = NULL;
954
955         gint status;
956
957         status = contacts_query_create(_contacts_phone_log._uri,
958                                 &query);
959
960         if (status != CONTACTS_ERROR_NONE)
961                 return NULL;
962
963         status = contacts_filter_create(_contacts_phone_log._uri, &filter);
964
965         if (status != CONTACTS_ERROR_NONE) {
966                 contacts_query_destroy(query);
967                 return NULL;
968         }
969
970         status = __bluetooth_pb_phone_log_filter_append(filter, match, size);
971
972         if (status != CONTACTS_ERROR_NONE) {
973                 contacts_filter_destroy(filter);
974                 contacts_query_destroy(query);
975                 return NULL;
976         }
977
978         status = contacts_query_set_filter(query, filter);
979
980         if (status != CONTACTS_ERROR_NONE) {
981                 contacts_filter_destroy(filter);
982                 contacts_query_destroy(query);
983                 return NULL;
984         }
985
986         status = contacts_query_set_sort(query,
987                         _contacts_phone_log.log_time,
988                         false);
989
990         if (status != CONTACTS_ERROR_NONE) {
991                 contacts_filter_destroy(filter);
992                 contacts_query_destroy(query);
993                 return NULL;
994         }
995
996         contacts_filter_destroy(filter);
997
998         return query;
999 }
1000
1001 static contacts_query_h __bluetooth_pb_query_person(void)
1002 {
1003         contacts_query_h query = NULL;
1004
1005         gint status;
1006
1007         status = contacts_query_create(_contacts_person._uri,
1008                         &query);
1009
1010         if (status != CONTACTS_ERROR_NONE)
1011                 return NULL;
1012
1013         return query;
1014 }
1015
1016 static contacts_query_h __bluetooth_pb_query_person_number(void)
1017 {
1018         contacts_query_h query = NULL;
1019
1020         gint status;
1021
1022         status = contacts_query_create(_contacts_person_number._uri,
1023                                 &query);
1024
1025         if (status != CONTACTS_ERROR_NONE)
1026                 return NULL;
1027
1028         return query;
1029 }
1030
1031 static contacts_query_h __bluetooth_pb_query_phone_log_incoming(void)
1032 {
1033         gint size = 2;
1034         gint match[] = {
1035                 CONTACTS_PLOG_TYPE_VOICE_INCOMMING,
1036                 CONTACTS_PLOG_TYPE_VIDEO_INCOMMING
1037         };
1038
1039         return __bluetooth_pb_query_phone_log(match, size);
1040 }
1041
1042 static contacts_query_h __bluetooth_pb_query_phone_log_outgoing(void)
1043 {
1044         gint size = 2;
1045         gint match[] = {
1046                 CONTACTS_PLOG_TYPE_VOICE_OUTGOING,
1047                 CONTACTS_PLOG_TYPE_VIDEO_OUTGOING
1048         };
1049
1050         return __bluetooth_pb_query_phone_log(match, size);
1051
1052 }
1053
1054 static contacts_query_h __bluetooth_pb_query_phone_log_missed(void)
1055 {
1056         gint size = 4;
1057         gint match[] = {
1058                 CONTACTS_PLOG_TYPE_VOICE_INCOMMING_UNSEEN,
1059                 CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_UNSEEN,
1060                 CONTACTS_PLOG_TYPE_VOICE_INCOMMING_SEEN,
1061                 CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_SEEN
1062         };
1063
1064         return __bluetooth_pb_query_phone_log(match, size);
1065 }
1066
1067 static contacts_query_h __bluetooth_pb_query_phone_log_combined(void)
1068 {
1069         gint size = 8;
1070         gint match[] = {
1071                 CONTACTS_PLOG_TYPE_VOICE_INCOMMING,
1072                 CONTACTS_PLOG_TYPE_VIDEO_INCOMMING,
1073                 CONTACTS_PLOG_TYPE_VOICE_OUTGOING,
1074                 CONTACTS_PLOG_TYPE_VIDEO_OUTGOING,
1075                 CONTACTS_PLOG_TYPE_VOICE_INCOMMING_UNSEEN,
1076                 CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_UNSEEN,
1077                 CONTACTS_PLOG_TYPE_VOICE_INCOMMING_SEEN,
1078                 CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_SEEN
1079         };
1080
1081         return __bluetooth_pb_query_phone_log(match, size);
1082 }
1083
1084 static gboolean __bluetooth_pb_get_count(PhoneBookType pb_type,
1085                                 guint *count)
1086 {
1087         contacts_query_h query = NULL;
1088
1089         gint status;
1090         gint signed_count;
1091
1092         switch (pb_type) {
1093         case TELECOM_PB:
1094                 query = __bluetooth_pb_query_person();
1095                 break;
1096         case TELECOM_ICH:
1097                 query = __bluetooth_pb_query_phone_log_incoming();
1098                 break;
1099         case TELECOM_OCH:
1100                 query = __bluetooth_pb_query_phone_log_outgoing();
1101                 break;
1102         case TELECOM_MCH:
1103                 query = __bluetooth_pb_query_phone_log_missed();
1104                 break;
1105         case TELECOM_CCH:
1106                 query = __bluetooth_pb_query_phone_log_combined();
1107                 break;
1108         default:
1109                 return FALSE;
1110         }
1111
1112         if (query == NULL)
1113                 return FALSE;
1114
1115         status = contacts_db_get_count_with_query(query, &signed_count);
1116
1117         if (status != CONTACTS_ERROR_NONE) {
1118                 contacts_query_destroy(query);
1119                 return FALSE;
1120         }
1121
1122         contacts_query_destroy(query);
1123
1124         if (signed_count < 0)
1125                 signed_count = 0;
1126
1127         *count = (gint) signed_count;
1128
1129         return TRUE;
1130 }
1131
1132 static gboolean __bluetooth_pb_get_count_new_missed_call(guint *count)
1133 {
1134         contacts_query_h query = NULL;
1135
1136         gint status;
1137         gint signed_count;
1138
1139         gint size = 2;
1140         gint match[] = {
1141                 CONTACTS_PLOG_TYPE_VOICE_INCOMMING_UNSEEN,
1142                 CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_UNSEEN
1143         };
1144
1145         query = __bluetooth_pb_query_phone_log(match, size);
1146
1147         if (query == NULL)
1148                 return FALSE;
1149
1150         status = contacts_db_get_count_with_query(query, &signed_count);
1151
1152         if (status != CONTACTS_ERROR_NONE) {
1153                 contacts_query_destroy(query);
1154                 return FALSE;
1155         }
1156
1157         contacts_query_destroy(query);
1158
1159         if (signed_count < 0)
1160                 signed_count = 0;
1161
1162         *count = (guint)signed_count;
1163
1164         return TRUE;
1165 }
1166
1167 static const char *__bluetooth_pb_phone_log_get_log_type(contacts_record_h record)
1168 {
1169         gint status;
1170         gint log_type;
1171
1172         status = contacts_record_get_int(record,
1173                         _contacts_phone_log.log_type,
1174                         &log_type);
1175
1176         if (status != CONTACTS_ERROR_NONE)
1177                 return NULL;
1178
1179         switch (log_type) {
1180         case CONTACTS_PLOG_TYPE_VOICE_INCOMMING:
1181         case CONTACTS_PLOG_TYPE_VIDEO_INCOMMING:
1182                 return "RECEIVED";
1183         case CONTACTS_PLOG_TYPE_VOICE_OUTGOING:
1184         case CONTACTS_PLOG_TYPE_VIDEO_OUTGOING:
1185                 return "DIALED";
1186         case CONTACTS_PLOG_TYPE_VOICE_INCOMMING_UNSEEN:
1187         case CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_UNSEEN:
1188         case CONTACTS_PLOG_TYPE_VOICE_INCOMMING_SEEN:
1189         case CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_SEEN:
1190                 return "MISSED";
1191         default:
1192                 return NULL;
1193         }
1194 }
1195
1196 static void __bluetooth_pb_get_vcards(BluetoothPbAgent *agent,
1197                                 PhoneBookType pb_type,
1198                                 guint64 filter,
1199                                 guint8 format,
1200                                 guint16 max_list_count,
1201                                 guint16 list_start_offset,
1202                                 GPtrArray *vcards)
1203 {
1204         contacts_list_h record_list = NULL;
1205         contacts_query_h query = NULL;
1206
1207         gint status;
1208
1209         gint limit;
1210         gint offset;
1211
1212         guint property_id = 0;
1213
1214         const char *attr = NULL;
1215
1216         gboolean get_log = FALSE;
1217
1218         /* contact offset is n - 1 of PBAP */
1219         offset = (gint)list_start_offset - 1;
1220
1221         if ( max_list_count >= 65535)
1222                 limit = -1;     /* contact limit -1 means unrestricted */
1223         else
1224                 limit = (gint)max_list_count;
1225
1226         switch (pb_type) {
1227         case TELECOM_PB:
1228                 /* for owner */
1229                 if (list_start_offset == 0) {
1230                         char *vcard;
1231
1232                         vcard = _bluetooth_pb_vcard_contact_owner(agent->tel_number,
1233                                                                 filter, format);
1234                         if (vcard)
1235                                 g_ptr_array_add(vcards, vcard);
1236
1237                         offset = 0;
1238
1239                         if (limit > 0)
1240                                 limit--;
1241                 }
1242
1243                 query = __bluetooth_pb_query_person();
1244                 property_id = _contacts_person.id;
1245                 break;
1246         case TELECOM_ICH:
1247                 query = __bluetooth_pb_query_phone_log_incoming();
1248                 property_id = _contacts_phone_log.id;
1249                 attr = "RECEIVED";
1250                 break;
1251         case TELECOM_OCH:
1252                 query = __bluetooth_pb_query_phone_log_outgoing();
1253                 property_id = _contacts_phone_log.id;
1254                 attr = "DIALED";
1255                 break;
1256         case TELECOM_MCH:
1257                 query = __bluetooth_pb_query_phone_log_missed();
1258                 property_id = _contacts_phone_log.id;
1259                 attr = "MISSED";
1260                 break;
1261         case TELECOM_CCH:
1262                 query = __bluetooth_pb_query_phone_log_combined();
1263                 property_id = _contacts_phone_log.id;
1264                 get_log = TRUE;
1265                 break;
1266         default:
1267                 return;
1268         }
1269
1270         status = contacts_db_get_records_with_query(query, offset, limit, &record_list);
1271
1272         if (status != CONTACTS_ERROR_NONE) {
1273                 contacts_query_destroy(query);
1274                 return;
1275         }
1276
1277         status = contacts_list_first(record_list);
1278
1279         if (status != CONTACTS_ERROR_NONE) {
1280                 contacts_list_destroy(record_list, TRUE);
1281                 contacts_query_destroy(query);
1282                 return;
1283         }
1284
1285         do {
1286                 contacts_record_h record;
1287
1288                 gint id;
1289
1290                 gchar *vcard = NULL;
1291
1292                 record = NULL;
1293                 status = contacts_list_get_current_record_p(record_list, &record);
1294
1295                 if (status != CONTACTS_ERROR_NONE)
1296                         continue;
1297                 id = 0;
1298                 status = contacts_record_get_int(record, property_id, &id);
1299
1300                 if (status != CONTACTS_ERROR_NONE)
1301                         continue;
1302
1303                 if (property_id == _contacts_person.id)
1304                         vcard = _bluetooth_pb_vcard_contact(id, filter, format);
1305                 else {
1306                         if (get_log)
1307                                 attr = __bluetooth_pb_phone_log_get_log_type(record);
1308
1309                         vcard = _bluetooth_pb_vcard_call(id, filter, format, attr);
1310                 }
1311
1312                 if (vcard)
1313                         g_ptr_array_add(vcards, vcard);
1314
1315         } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
1316
1317         contacts_list_destroy(record_list, TRUE);
1318         contacts_query_destroy(query);
1319 }
1320
1321 static void __bluetooth_pb_get_contact_list(BluetoothPbAgent *agent,
1322                                         contacts_query_h query,
1323                                         GPtrArray *ptr_array)
1324 {
1325         contacts_list_h record_list = NULL;
1326
1327         gint status;
1328         int i = 1;
1329
1330         /* Add owner */
1331         if (ptr_array) {
1332                 gchar *tmp;
1333                 gchar *name;
1334
1335                 tmp = _bluetooth_pb_owner_name();
1336                 name = g_strdup_printf("%s;;;;", tmp);
1337                 g_free(tmp);
1338
1339                 __bluetooth_pb_list_ptr_array_add(ptr_array,
1340                                 name, agent->tel_number, 0);
1341
1342                 g_free(name);
1343         }
1344
1345         status = contacts_db_get_records_with_query(query,
1346                         -1, -1, &record_list);
1347
1348         if (status != CONTACTS_ERROR_NONE)
1349                 return;
1350
1351         status = contacts_list_first(record_list);
1352
1353         if (status != CONTACTS_ERROR_NONE) {
1354                 contacts_list_destroy(record_list, TRUE);
1355                 return;
1356         }
1357
1358         __bluetooth_pb_list_hash_reset(agent);
1359
1360         do {
1361                 contacts_record_h record;
1362
1363                 gint id;
1364
1365                 record = NULL;
1366                 status = contacts_list_get_current_record_p(record_list,
1367                                 &record);
1368
1369                 if (status != CONTACTS_ERROR_NONE)
1370                         continue;
1371
1372                 id = 0;
1373                 status = contacts_record_get_int(record,
1374                                 _contacts_person.id,
1375                                 &id);
1376
1377                 if (status != CONTACTS_ERROR_NONE)
1378                         continue;
1379
1380                 __bluetooth_pb_list_hash_insert(agent, i, id);
1381
1382                 /* create list */
1383                 if (ptr_array) {
1384                         gchar *name;
1385                         gchar *number;
1386
1387                         name = _bluetooth_pb_name_from_person_id(id);
1388                         number = _bluetooth_pb_number_from_person_id(id);
1389
1390                         __bluetooth_pb_list_ptr_array_add(ptr_array,
1391                                         name, number, i);
1392
1393                         g_free(name);
1394                         g_free(number);
1395                 }
1396
1397                 i++;
1398
1399         } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
1400
1401         contacts_list_destroy(record_list, TRUE);
1402 }
1403
1404 static void __bluetooth_pb_get_phone_log_list(BluetoothPbAgent *agent,
1405                                         contacts_query_h query,
1406                                         GPtrArray *ptr_array)
1407 {
1408         contacts_list_h record_list = NULL;
1409
1410         gint status;
1411         int i = 1;
1412
1413         status = contacts_db_get_records_with_query(query,
1414                         -1, -1, &record_list);
1415
1416         if (status != CONTACTS_ERROR_NONE)
1417                 return;
1418
1419         status = contacts_list_first(record_list);
1420
1421         if (status != CONTACTS_ERROR_NONE) {
1422                 contacts_list_destroy(record_list, TRUE);
1423                 return;
1424         }
1425
1426         __bluetooth_pb_list_hash_reset(agent);
1427
1428         do {
1429                 contacts_record_h record;
1430
1431                 gint id;
1432
1433                 record = NULL;
1434                 status = contacts_list_get_current_record_p(record_list,
1435                                 &record);
1436
1437                 if (status != CONTACTS_ERROR_NONE)
1438                         continue;
1439
1440                 id = 0;
1441                 status = contacts_record_get_int(record,
1442                                 _contacts_phone_log.id,
1443                                 &id);
1444
1445                 if (status != CONTACTS_ERROR_NONE)
1446                         continue;
1447
1448                 __bluetooth_pb_list_hash_insert(agent, i, id);
1449
1450                 /* create list */
1451                 if (ptr_array) {
1452                         gchar *name;
1453                         gchar *number;
1454
1455                         name = _bluetooth_pb_name_from_phonelog_id(id);
1456
1457                         number = NULL;
1458                         contacts_record_get_str_p(record,
1459                                         _contacts_phone_log.address,
1460                                         &number);
1461
1462                         __bluetooth_pb_list_ptr_array_add(ptr_array,
1463                                         name, number, i);
1464
1465                         g_free(name);
1466                 }
1467
1468                 i++;
1469
1470         } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
1471
1472         contacts_list_destroy(record_list, TRUE);
1473 }
1474
1475
1476 static void __bluetooth_pb_get_list(BluetoothPbAgent *agent,
1477                                 PhoneBookType pb_type,
1478                                 GPtrArray *ptr_array)
1479 {
1480         contacts_query_h query;
1481
1482         /* no requires refresh cache */
1483         if (ptr_array == NULL && agent->pb_type == pb_type)
1484                 return;
1485
1486         switch (pb_type) {
1487         case TELECOM_PB:
1488                 query = __bluetooth_pb_query_person();
1489                 __bluetooth_pb_get_contact_list(agent, query, ptr_array);
1490                 break;
1491         case TELECOM_ICH:
1492                 query = __bluetooth_pb_query_phone_log_incoming();
1493                 __bluetooth_pb_get_phone_log_list(agent, query, ptr_array);
1494                 break;
1495         case TELECOM_OCH:
1496                 query = __bluetooth_pb_query_phone_log_outgoing();
1497                 __bluetooth_pb_get_phone_log_list(agent, query, ptr_array);
1498                 break;
1499         case TELECOM_MCH:
1500                 query = __bluetooth_pb_query_phone_log_missed();
1501                 __bluetooth_pb_get_phone_log_list(agent, query, ptr_array);
1502                 break;
1503         case TELECOM_CCH:
1504                 query = __bluetooth_pb_query_phone_log_combined();
1505                 __bluetooth_pb_get_phone_log_list(agent, query, ptr_array);
1506                 break;
1507         default:
1508                 return;
1509         }
1510
1511         agent->pb_type = pb_type;
1512
1513         if (query)
1514                 contacts_query_destroy(query);
1515 }
1516
1517 static void __bluetooth_pb_get_contact_list_number(BluetoothPbAgent *agent,
1518                                                 contacts_query_h query,
1519                                                 gint start_index,
1520                                                 gint end_index,
1521                                                 GPtrArray *ptr_array)
1522 {
1523         contacts_list_h record_list = NULL;
1524
1525         gint status;
1526
1527         gint i;
1528
1529         gint from;
1530         gint to;
1531         gint offset;
1532
1533         from = start_index;
1534         to = end_index;
1535
1536         if (from < 1)
1537                 from = 1;
1538
1539         if (to < 1)
1540                 to = 1;
1541
1542         offset = to - from + 1;
1543         if (offset <= 0)
1544                 return;
1545
1546         i = from;
1547
1548         status = contacts_db_get_records_with_query(query,
1549                         from - 1 , offset,
1550                         &record_list);
1551
1552         if (status != CONTACTS_ERROR_NONE)
1553                 return;
1554
1555         status = contacts_list_first(record_list);
1556
1557         if (status != CONTACTS_ERROR_NONE) {
1558                 contacts_list_destroy(record_list, TRUE);
1559                 return;
1560         }
1561
1562         do {
1563                 contacts_record_h record;
1564
1565                 gchar *display_name;
1566                 gchar *number;
1567
1568                 record = NULL;
1569                 status = contacts_list_get_current_record_p(record_list,
1570                                 &record);
1571
1572                 if (status != CONTACTS_ERROR_NONE)
1573                         continue;
1574
1575                 display_name = NULL;
1576                 number = NULL;
1577
1578                 contacts_record_get_str_p(record,
1579                                 _contacts_person_number.display_name,
1580                                 &display_name);
1581                 contacts_record_get_str_p(record,
1582                                 _contacts_person_number.number,
1583                                 &number);
1584
1585                 __bluetooth_pb_list_ptr_array_add(ptr_array,
1586                                 display_name, number, i);
1587
1588                 i++;
1589         } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
1590
1591         contacts_list_destroy(record_list, TRUE);
1592 }
1593
1594 static void __bluetooth_pb_get_phone_log_list_number(BluetoothPbAgent *agent,
1595                                                 contacts_query_h query,
1596                                                 gint start_index,
1597                                                 gint end_index,
1598                                                 GPtrArray *ptr_array)
1599 {
1600         contacts_list_h record_list = NULL;
1601
1602         gint status;
1603
1604         gint i;
1605
1606         gint from;
1607         gint to;
1608         gint offset;
1609
1610         from = start_index;
1611         to = end_index;
1612
1613         if (from < 1)
1614                 from = 1;
1615
1616         if (to < 1)
1617                 to = 1;
1618
1619         offset = to - from + 1;
1620         if (offset <= 0)
1621                 return;
1622
1623         i = from;
1624
1625         status = contacts_db_get_records_with_query(query,
1626                         from - 1 , offset,
1627                         &record_list);
1628
1629         if (status != CONTACTS_ERROR_NONE)
1630                 return;
1631
1632         status = contacts_list_first(record_list);
1633         if (status != CONTACTS_ERROR_NONE) {
1634                 contacts_list_destroy(record_list, TRUE);
1635                 return;
1636         }
1637
1638         do {
1639                 contacts_record_h record = NULL;
1640
1641                 gint id;
1642
1643                 gchar *display_name;
1644                 gchar *number;
1645
1646                 record = NULL;
1647                 status = contacts_list_get_current_record_p(record_list,
1648                                 &record);
1649
1650                 if (status != CONTACTS_ERROR_NONE)
1651                         continue;
1652
1653                 id = 0;
1654                 status = contacts_record_get_int(record,
1655                                 _contacts_phone_log.id,
1656                                 &id);
1657
1658                 display_name = _bluetooth_pb_fn_from_phonelog_id(id);
1659
1660                 number = NULL;
1661                 contacts_record_get_str_p(record,
1662                                 _contacts_phone_log.address,
1663                                 &number);
1664
1665
1666                 __bluetooth_pb_list_ptr_array_add(ptr_array,
1667                                 display_name, number, i);
1668
1669                 i++;
1670
1671                 g_free(display_name);
1672
1673         } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
1674
1675         contacts_list_destroy(record_list, TRUE);
1676 }
1677
1678 static void __bluetooth_pb_get_list_number(BluetoothPbAgent *agent,
1679                                                 PhoneBookType pb_type,
1680                                                 gint start_index,
1681                                                 gint end_index,
1682                                                 GPtrArray *ptr_array)
1683 {
1684         contacts_query_h query;
1685
1686         switch (pb_type) {
1687         case TELECOM_PB:
1688                 query = __bluetooth_pb_query_person_number();
1689                 __bluetooth_pb_get_contact_list_number(agent, query,
1690                                 start_index, end_index, ptr_array);
1691                 break;
1692         case TELECOM_ICH:
1693                 query = __bluetooth_pb_query_phone_log_incoming();
1694                 __bluetooth_pb_get_phone_log_list_number(agent, query,
1695                                 start_index, end_index, ptr_array);
1696                 break;
1697         case TELECOM_OCH:
1698                 query = __bluetooth_pb_query_phone_log_outgoing();
1699                 __bluetooth_pb_get_phone_log_list_number(agent, query,
1700                                 start_index, end_index, ptr_array);
1701                 break;
1702         case TELECOM_MCH:
1703                 query = __bluetooth_pb_query_phone_log_missed();
1704                 __bluetooth_pb_get_phone_log_list_number(agent, query,
1705                                 start_index, end_index, ptr_array);
1706                 break;
1707         case TELECOM_CCH:
1708                 query = __bluetooth_pb_query_phone_log_combined();
1709                 __bluetooth_pb_get_phone_log_list_number(agent, query,
1710                                 start_index, end_index, ptr_array);
1711                 break;
1712         default:
1713                 return;
1714         }
1715
1716         if (query)
1717                 contacts_query_destroy(query);
1718 }
1719
1720 static void __bluetooth_pb_get_contact_list_name(BluetoothPbAgent *agent,
1721                                                 contacts_query_h query,
1722                                                 const gchar *find_text,
1723                                                 GPtrArray *ptr_array)
1724 {
1725         contacts_list_h record_list = NULL;
1726
1727         gint status;
1728         gint i = 1;
1729
1730         status = contacts_db_get_records_with_query(query,
1731                         -1, -1, &record_list);
1732
1733         if (status != CONTACTS_ERROR_NONE)
1734                 return;
1735
1736         status = contacts_list_first(record_list);
1737
1738         if (status != CONTACTS_ERROR_NONE) {
1739                 contacts_list_destroy(record_list, TRUE);
1740                 return;
1741         }
1742
1743         do {
1744                 contacts_record_h record;
1745
1746                 gchar *display_name;
1747
1748                 record = NULL;
1749                 status = contacts_list_get_current_record_p(record_list,
1750                                 &record);
1751
1752                 if (status != CONTACTS_ERROR_NONE)
1753                         continue;
1754
1755                 display_name = NULL;
1756                 contacts_record_get_str_p(record,
1757                                 _contacts_person_number.display_name,
1758                                 &display_name);
1759
1760                 if (g_str_has_prefix(display_name, find_text)) {
1761                         gchar *number;
1762
1763                         number = NULL;
1764                         contacts_record_get_str_p(record,
1765                                         _contacts_person_number.number,
1766                                         &number);
1767
1768                         __bluetooth_pb_list_ptr_array_add(ptr_array,
1769                                         display_name, number, i);
1770                 }
1771
1772                 i++;
1773         } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
1774 }
1775
1776 static void __bluetooth_pb_get_phone_log_list_name(BluetoothPbAgent *agent,
1777                                                 contacts_query_h query,
1778                                                 const gchar *find_text,
1779                                                 GPtrArray *ptr_array)
1780 {
1781         contacts_list_h record_list = NULL;
1782
1783         gint status;
1784
1785         gint i = 1;
1786
1787         status = contacts_db_get_records_with_query(query,
1788                         -1, -1,
1789                         &record_list);
1790
1791         if (status != CONTACTS_ERROR_NONE)
1792                 return;
1793
1794         status = contacts_list_first(record_list);
1795
1796         if (status != CONTACTS_ERROR_NONE) {
1797                 contacts_list_destroy(record_list, TRUE);
1798                 return;
1799         }
1800
1801         do {
1802                 contacts_record_h record = NULL;
1803
1804                 gint id;
1805
1806                 gchar *display_name;
1807
1808                 record = NULL;
1809                 status = contacts_list_get_current_record_p(record_list,
1810                                 &record);
1811
1812                 if (status != CONTACTS_ERROR_NONE)
1813                         continue;
1814
1815                 id = 0;
1816                 status = contacts_record_get_int(record,
1817                                 _contacts_phone_log.id,
1818                                 &id);
1819
1820                 display_name = _bluetooth_pb_fn_from_phonelog_id(id);
1821
1822                 if (g_str_has_prefix(display_name, find_text)) {
1823                         gchar *number = NULL;
1824
1825                         number = NULL;
1826                         contacts_record_get_str_p(record,
1827                                         _contacts_phone_log.address,
1828                                         &number);
1829
1830                         __bluetooth_pb_list_ptr_array_add(ptr_array,
1831                                         display_name, number, i);
1832                 }
1833
1834                 i++;
1835
1836                 g_free(display_name);
1837
1838         } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
1839
1840         contacts_list_destroy(record_list, TRUE);
1841 }
1842
1843 static void __bluetooth_pb_get_list_name(BluetoothPbAgent *agent,
1844                                         PhoneBookType pb_type,
1845                                         const gchar *find_text,
1846                                         GPtrArray *ptr_array)
1847 {
1848         contacts_query_h query;
1849
1850         switch (pb_type) {
1851         case TELECOM_PB:
1852                 query = __bluetooth_pb_query_person_number();
1853                 __bluetooth_pb_get_contact_list_name(agent, query,
1854                                 find_text, ptr_array);
1855                 break;
1856         case TELECOM_ICH:
1857                 query = __bluetooth_pb_query_phone_log_incoming();
1858                 __bluetooth_pb_get_phone_log_list_name(agent, query,
1859                                 find_text, ptr_array);
1860                 break;
1861         case TELECOM_OCH:
1862                 query = __bluetooth_pb_query_phone_log_outgoing();
1863                 __bluetooth_pb_get_phone_log_list_name(agent, query,
1864                                 find_text, ptr_array);
1865                 break;
1866         case TELECOM_MCH:
1867                 query = __bluetooth_pb_query_phone_log_missed();
1868                 __bluetooth_pb_get_phone_log_list_name(agent, query,
1869                                 find_text, ptr_array);
1870                 break;
1871         case TELECOM_CCH:
1872                 query = __bluetooth_pb_query_phone_log_combined();
1873                 __bluetooth_pb_get_phone_log_list_name(agent, query,
1874                                 find_text, ptr_array);
1875                 break;
1876         default:
1877                 return;
1878         }
1879
1880         if (query)
1881                 contacts_query_destroy(query);
1882 }
1883
1884 static void __bluetooth_pb_list_hash_reset(BluetoothPbAgent *agent)
1885 {
1886         if(agent->contact_list)
1887                 g_hash_table_destroy(agent->contact_list);
1888
1889         agent->contact_list = g_hash_table_new(g_direct_hash, g_direct_equal);
1890 }
1891
1892 static gboolean __bluetooth_pb_list_hash_insert(BluetoothPbAgent *agent,
1893                                                 gint handle,
1894                                                 gint id)
1895 {
1896         if (agent->contact_list == NULL)
1897                 return FALSE;
1898
1899         g_hash_table_insert(agent->contact_list,
1900                         GINT_TO_POINTER(handle), GINT_TO_POINTER(id));
1901
1902         return TRUE;
1903 }
1904
1905 static gint __bluetooth_pb_list_hash_lookup_id(BluetoothPbAgent *agent,
1906                                         gint handle)
1907 {
1908         gint id;
1909
1910         if (agent->contact_list == NULL)
1911                 return 0;
1912
1913         id = GPOINTER_TO_INT(g_hash_table_lookup(agent->contact_list,
1914                                 GINT_TO_POINTER(handle)));
1915
1916         return id;
1917 }
1918
1919 static void __bluetooth_pb_list_ptr_array_add(GPtrArray *ptr_array,
1920                                                 const gchar *name,
1921                                                 const gchar *number,
1922                                                 gint handle)
1923 {
1924         GValue value = { 0, };
1925
1926         g_value_init(&value, DBUS_STRUCT_STRING_STRING_UINT);
1927         g_value_take_boxed(&value,
1928                         dbus_g_type_specialized_construct(DBUS_STRUCT_STRING_STRING_UINT));
1929
1930         dbus_g_type_struct_set(&value,
1931                                 0, g_strdup(name),
1932                                 1, g_strdup(number),
1933                                 2, handle,
1934                                 G_MAXUINT);
1935
1936         g_ptr_array_add(ptr_array, g_value_get_boxed(&value));
1937 }
1938
1939 static void __bluetooth_pb_list_ptr_array_free(gpointer data)
1940 {
1941         GValue value = { 0, };
1942
1943         gchar *name = NULL;
1944         gchar *number = NULL;
1945
1946         if(data == NULL)
1947                 return;
1948
1949         g_value_init(&value, DBUS_STRUCT_STRING_STRING_UINT);
1950         g_value_set_boxed(&value, data);
1951
1952         dbus_g_type_struct_get(&value,
1953                         0, &name,
1954                         1, &number,
1955                         G_MAXUINT);
1956
1957         g_free(name);
1958         g_free(number);
1959 }
1960
1961 static void __bluetooth_pb_agent_signal_handler(int signum)
1962 {
1963         if (mainloop)
1964                 g_main_loop_quit(mainloop);
1965         else
1966                 exit(0);
1967 }
1968
1969
1970 static void __bluetooth_pb_contact_changed(const gchar *view_uri,
1971                                         void *user_data)
1972 {
1973         BluetoothPbAgent *agent;
1974
1975         g_return_if_fail(BLUETOOTH_IS_PB_AGENT(user_data));
1976         agent = BLUETOOTH_PB_AGENT(user_data);
1977
1978         g_signal_emit(agent, signals[CLEAR], 0);
1979         g_object_unref(agent);
1980 }
1981
1982 static void __bluetooth_pb_agent_timeout_add_seconds(BluetoothPbAgent *agent)
1983 {
1984         g_return_if_fail(BLUETOOTH_IS_PB_AGENT(agent));
1985
1986         if(agent->timeout_id)
1987                 g_source_remove(agent->timeout_id);
1988
1989         agent->timeout_id = g_timeout_add_seconds(BLUETOOTH_PB_AGENT_TIMEOUT,
1990                                 __bluetooth_pb_agent_timeout_calback,
1991                                 agent);
1992 }
1993
1994 static gboolean __bluetooth_pb_agent_timeout_calback(gpointer user_data)
1995 {
1996         BluetoothPbAgent *agent;
1997
1998         g_return_val_if_fail(BLUETOOTH_IS_PB_AGENT(user_data), FALSE);
1999
2000         agent = BLUETOOTH_PB_AGENT(user_data);
2001         agent->timeout_id = 0;
2002
2003         if (mainloop)
2004                 g_main_loop_quit(mainloop);
2005
2006         return FALSE;
2007 }
2008
2009 static void __bluetooth_pb_tel_callback(TapiHandle *handle,
2010                                         int result,
2011                                         void *data,
2012                                         void *user_data)
2013 {
2014         BluetoothPbAgent *agent;
2015         TelSimMsisdnList_t *number;
2016
2017         g_return_if_fail(BLUETOOTH_IS_PB_AGENT(user_data));
2018
2019         agent = BLUETOOTH_PB_AGENT(user_data);
2020
2021         __bluetooth_pb_agent_dbus_init(agent);
2022
2023         number = (TelSimMsisdnList_t *)data;
2024         agent->tel_number = g_strdup(number->list[0].num);
2025
2026         tel_deinit(agent->tapi_handle);
2027         agent->tapi_handle = NULL;
2028 }
2029
2030 static void __bluetooth_pb_agent_dbus_init(BluetoothPbAgent *agent)
2031 {
2032         guint result = 0;
2033         GError *error = NULL;
2034
2035         agent->bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
2036
2037         if (error != NULL) {
2038                 DBG("Couldn't connect to system bus[%s]\n", error->message);
2039                 g_error_free(error);
2040                 return;
2041         }
2042
2043         agent->proxy = dbus_g_proxy_new_for_name(agent->bus,
2044                         DBUS_SERVICE_DBUS,
2045                         DBUS_PATH_DBUS,
2046                         DBUS_INTERFACE_DBUS);
2047
2048         if (agent->proxy == NULL) {
2049                 DBG("Failed to get a proxy for D-Bus\n");
2050                 return;
2051         }
2052
2053         if (!dbus_g_proxy_call(agent->proxy,
2054                                 "RequestName", &error,
2055                                 G_TYPE_STRING, BT_PB_SERVICE_NAME,
2056                                 G_TYPE_UINT, 0,
2057                                 G_TYPE_INVALID,
2058                                 G_TYPE_UINT, &result,
2059                                 G_TYPE_INVALID)) {
2060                 if (error != NULL) {
2061                         DBG("RequestName RPC failed[%s]\n", error->message);
2062                         g_error_free(error);
2063                 }
2064
2065                 g_object_unref(agent->proxy);
2066                 agent->proxy = NULL;
2067
2068                 return;
2069         }
2070         DBG("result : %d %d\n", result, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
2071         if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
2072                 DBG("Failed to get the primary well-known name.\n");
2073
2074                 g_object_unref(agent->proxy);
2075                 agent->proxy = NULL;
2076
2077                 return;
2078         }
2079
2080         g_object_unref(agent->proxy);
2081         agent->proxy = NULL;
2082
2083         dbus_g_connection_register_g_object(agent->bus,
2084                         BT_PB_SERVICE_OBJECT_PATH,
2085                         G_OBJECT(agent));
2086 }
2087
2088 int main(int argc, char **argv)
2089 {
2090         BluetoothPbAgent *agent;
2091
2092         gint ret = EXIT_SUCCESS;
2093         gint tapi_result;
2094
2095         struct sigaction sa;
2096
2097         g_type_init();
2098
2099         mainloop = g_main_loop_new(NULL, FALSE);
2100         if (mainloop == NULL) {
2101                 DBG("Couldn't create GMainLoop\n");
2102                 return EXIT_FAILURE;
2103         }
2104
2105         agent = g_object_new(BLUETOOTH_PB_TYPE_AGENT, NULL);
2106
2107         /* connect contact */
2108         if (contacts_connect2() != CONTACTS_ERROR_NONE) {
2109                 DBG("Can not connect contacts server\n");
2110                 g_object_unref(agent);
2111                 return EXIT_FAILURE;
2112         }
2113
2114         if (contacts_db_add_changed_cb(_contacts_event._uri,
2115                         __bluetooth_pb_contact_changed,
2116                         g_object_ref(agent)) != CONTACTS_ERROR_NONE) {
2117                 DBG("Can not add changed callback");
2118         }
2119
2120         /* set signal */
2121         memset(&sa, 0, sizeof(sa));
2122         sa.sa_handler = __bluetooth_pb_agent_signal_handler;
2123         sigaction(SIGTERM, &sa, NULL);
2124         sigaction(SIGINT, &sa, NULL);
2125
2126         /* init tapi */
2127         agent->tapi_handle = tel_init(NULL);
2128         tapi_result = tel_get_sim_msisdn(agent->tapi_handle,
2129                         __bluetooth_pb_tel_callback, agent);
2130
2131         if (tapi_result != TAPI_API_SUCCESS) {
2132                 __bluetooth_pb_agent_dbus_init(agent);
2133         }
2134
2135
2136         __bluetooth_pb_agent_timeout_add_seconds(agent);
2137
2138         g_main_loop_run(mainloop);
2139
2140         DBG("Terminate the bluetooth-pb-agent\n");
2141
2142         if (agent) {
2143                 contacts_db_remove_changed_cb(_contacts_event._uri,
2144                                 __bluetooth_pb_contact_changed,
2145                                 g_object_ref(agent));
2146
2147                 g_object_unref(agent);
2148         }
2149
2150
2151         contacts_disconnect2();
2152
2153         g_signal_emit(agent, signals[CLEAR], 0);
2154
2155         if (agent)
2156                 g_object_unref(agent);
2157
2158         return ret;
2159 }