d86ae7486821708520f2be370468cb56eda8b5b7
[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                 return;
1282         }
1283
1284         do {
1285                 contacts_record_h record;
1286
1287                 gint id;
1288
1289                 gchar *vcard = NULL;
1290
1291                 record = NULL;
1292                 status = contacts_list_get_current_record_p(record_list, &record);
1293
1294                 if (status != CONTACTS_ERROR_NONE)
1295                         continue;
1296                 id = 0;
1297                 status = contacts_record_get_int(record, property_id, &id);
1298
1299                 if (status != CONTACTS_ERROR_NONE)
1300                         continue;
1301
1302                 if (property_id == _contacts_person.id)
1303                         vcard = _bluetooth_pb_vcard_contact(id, filter, format);
1304                 else {
1305                         if (get_log)
1306                                 attr = __bluetooth_pb_phone_log_get_log_type(record);
1307
1308                         vcard = _bluetooth_pb_vcard_call(id, filter, format, attr);
1309                 }
1310
1311                 if (vcard)
1312                         g_ptr_array_add(vcards, vcard);
1313
1314         } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
1315
1316         contacts_list_destroy(record_list, TRUE);
1317         contacts_query_destroy(query);
1318 }
1319
1320 static void __bluetooth_pb_get_contact_list(BluetoothPbAgent *agent,
1321                                         contacts_query_h query,
1322                                         GPtrArray *ptr_array)
1323 {
1324         contacts_list_h record_list = NULL;
1325
1326         gint status;
1327         int i = 1;
1328
1329         /* Add owner */
1330         if (ptr_array) {
1331                 gchar *tmp;
1332                 gchar *name;
1333
1334                 tmp = _bluetooth_pb_owner_name();
1335                 name = g_strdup_printf("%s;;;;", tmp);
1336                 g_free(tmp);
1337
1338                 __bluetooth_pb_list_ptr_array_add(ptr_array,
1339                                 name, agent->tel_number, 0);
1340
1341                 g_free(name);
1342         }
1343
1344         status = contacts_db_get_records_with_query(query,
1345                         -1, -1, &record_list);
1346
1347         if (status != CONTACTS_ERROR_NONE)
1348                 return;
1349
1350         status = contacts_list_first(record_list);
1351
1352         if (status != CONTACTS_ERROR_NONE) {
1353                 contacts_list_destroy(record_list, TRUE);
1354                 return;
1355         }
1356
1357         __bluetooth_pb_list_hash_reset(agent);
1358
1359         do {
1360                 contacts_record_h record;
1361
1362                 gint id;
1363
1364                 record = NULL;
1365                 status = contacts_list_get_current_record_p(record_list,
1366                                 &record);
1367
1368                 if (status != CONTACTS_ERROR_NONE)
1369                         continue;
1370
1371                 id = 0;
1372                 status = contacts_record_get_int(record,
1373                                 _contacts_person.id,
1374                                 &id);
1375
1376                 if (status != CONTACTS_ERROR_NONE)
1377                         continue;
1378
1379                 __bluetooth_pb_list_hash_insert(agent, i, id);
1380
1381                 /* create list */
1382                 if (ptr_array) {
1383                         gchar *name;
1384                         gchar *number;
1385
1386                         name = _bluetooth_pb_name_from_person_id(id);
1387                         number = _bluetooth_pb_number_from_person_id(id);
1388
1389                         __bluetooth_pb_list_ptr_array_add(ptr_array,
1390                                         name, number, i);
1391
1392                         g_free(name);
1393                         g_free(number);
1394                 }
1395
1396                 i++;
1397
1398         } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
1399
1400         contacts_list_destroy(record_list, TRUE);
1401 }
1402
1403 static void __bluetooth_pb_get_phone_log_list(BluetoothPbAgent *agent,
1404                                         contacts_query_h query,
1405                                         GPtrArray *ptr_array)
1406 {
1407         contacts_list_h record_list = NULL;
1408
1409         gint status;
1410         int i = 1;
1411
1412         status = contacts_db_get_records_with_query(query,
1413                         -1, -1, &record_list);
1414
1415         if (status != CONTACTS_ERROR_NONE)
1416                 return;
1417
1418         status = contacts_list_first(record_list);
1419
1420         if (status != CONTACTS_ERROR_NONE) {
1421                 contacts_list_destroy(record_list, TRUE);
1422                 return;
1423         }
1424
1425         __bluetooth_pb_list_hash_reset(agent);
1426
1427         do {
1428                 contacts_record_h record;
1429
1430                 gint id;
1431
1432                 record = NULL;
1433                 status = contacts_list_get_current_record_p(record_list,
1434                                 &record);
1435
1436                 if (status != CONTACTS_ERROR_NONE)
1437                         continue;
1438
1439                 id = 0;
1440                 status = contacts_record_get_int(record,
1441                                 _contacts_phone_log.id,
1442                                 &id);
1443
1444                 if (status != CONTACTS_ERROR_NONE)
1445                         continue;
1446
1447                 __bluetooth_pb_list_hash_insert(agent, i, id);
1448
1449                 /* create list */
1450                 if (ptr_array) {
1451                         gchar *name;
1452                         gchar *number;
1453
1454                         name = _bluetooth_pb_name_from_phonelog_id(id);
1455
1456                         number = NULL;
1457                         contacts_record_get_str_p(record,
1458                                         _contacts_phone_log.address,
1459                                         &number);
1460
1461                         __bluetooth_pb_list_ptr_array_add(ptr_array,
1462                                         name, number, i);
1463
1464                         g_free(name);
1465                 }
1466
1467                 i++;
1468
1469         } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
1470
1471         contacts_list_destroy(record_list, TRUE);
1472 }
1473
1474
1475 static void __bluetooth_pb_get_list(BluetoothPbAgent *agent,
1476                                 PhoneBookType pb_type,
1477                                 GPtrArray *ptr_array)
1478 {
1479         contacts_query_h query;
1480
1481         /* no requires refresh cache */
1482         if (ptr_array == NULL && agent->pb_type == pb_type)
1483                 return;
1484
1485         switch (pb_type) {
1486         case TELECOM_PB:
1487                 query = __bluetooth_pb_query_person();
1488                 __bluetooth_pb_get_contact_list(agent, query, ptr_array);
1489                 break;
1490         case TELECOM_ICH:
1491                 query = __bluetooth_pb_query_phone_log_incoming();
1492                 __bluetooth_pb_get_phone_log_list(agent, query, ptr_array);
1493                 break;
1494         case TELECOM_OCH:
1495                 query = __bluetooth_pb_query_phone_log_outgoing();
1496                 __bluetooth_pb_get_phone_log_list(agent, query, ptr_array);
1497                 break;
1498         case TELECOM_MCH:
1499                 query = __bluetooth_pb_query_phone_log_missed();
1500                 __bluetooth_pb_get_phone_log_list(agent, query, ptr_array);
1501                 break;
1502         case TELECOM_CCH:
1503                 query = __bluetooth_pb_query_phone_log_combined();
1504                 __bluetooth_pb_get_phone_log_list(agent, query, ptr_array);
1505                 break;
1506         default:
1507                 return;
1508         }
1509
1510         agent->pb_type = pb_type;
1511
1512         if (query)
1513                 contacts_query_destroy(query);
1514 }
1515
1516 static void __bluetooth_pb_get_contact_list_number(BluetoothPbAgent *agent,
1517                                                 contacts_query_h query,
1518                                                 gint start_index,
1519                                                 gint end_index,
1520                                                 GPtrArray *ptr_array)
1521 {
1522         contacts_list_h record_list = NULL;
1523
1524         gint status;
1525
1526         gint i;
1527
1528         gint from;
1529         gint to;
1530         gint offset;
1531
1532         from = start_index;
1533         to = end_index;
1534
1535         if (from < 1)
1536                 from = 1;
1537
1538         if (to < 1)
1539                 to = 1;
1540
1541         offset = to - from + 1;
1542         if (offset <= 0)
1543                 return;
1544
1545         i = from;
1546
1547         status = contacts_db_get_records_with_query(query,
1548                         from - 1 , offset,
1549                         &record_list);
1550
1551         if (status != CONTACTS_ERROR_NONE)
1552                 return;
1553
1554         status = contacts_list_first(record_list);
1555
1556         if (status != CONTACTS_ERROR_NONE) {
1557                 contacts_list_destroy(record_list, TRUE);
1558                 return;
1559         }
1560
1561         do {
1562                 contacts_record_h record;
1563
1564                 gchar *display_name;
1565                 gchar *number;
1566
1567                 record = NULL;
1568                 status = contacts_list_get_current_record_p(record_list,
1569                                 &record);
1570
1571                 if (status != CONTACTS_ERROR_NONE)
1572                         continue;
1573
1574                 display_name = NULL;
1575                 number = NULL;
1576
1577                 contacts_record_get_str_p(record,
1578                                 _contacts_person_number.display_name,
1579                                 &display_name);
1580                 contacts_record_get_str_p(record,
1581                                 _contacts_person_number.number,
1582                                 &number);
1583
1584                 __bluetooth_pb_list_ptr_array_add(ptr_array,
1585                                 display_name, number, i);
1586
1587                 i++;
1588         } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
1589
1590         contacts_list_destroy(record_list, TRUE);
1591 }
1592
1593 static void __bluetooth_pb_get_phone_log_list_number(BluetoothPbAgent *agent,
1594                                                 contacts_query_h query,
1595                                                 gint start_index,
1596                                                 gint end_index,
1597                                                 GPtrArray *ptr_array)
1598 {
1599         contacts_list_h record_list = NULL;
1600
1601         gint status;
1602
1603         gint i;
1604
1605         gint from;
1606         gint to;
1607         gint offset;
1608
1609         from = start_index;
1610         to = end_index;
1611
1612         if (from < 1)
1613                 from = 1;
1614
1615         if (to < 1)
1616                 to = 1;
1617
1618         offset = to - from + 1;
1619         if (offset <= 0)
1620                 return;
1621
1622         i = from;
1623
1624         status = contacts_db_get_records_with_query(query,
1625                         from - 1 , offset,
1626                         &record_list);
1627
1628         if (status != CONTACTS_ERROR_NONE)
1629                 return;
1630
1631         status = contacts_list_first(record_list);
1632         if (status != CONTACTS_ERROR_NONE) {
1633                 contacts_list_destroy(record_list, TRUE);
1634                 return;
1635         }
1636
1637         do {
1638                 contacts_record_h record = NULL;
1639
1640                 gint id;
1641
1642                 gchar *display_name;
1643                 gchar *number;
1644
1645                 record = NULL;
1646                 status = contacts_list_get_current_record_p(record_list,
1647                                 &record);
1648
1649                 if (status != CONTACTS_ERROR_NONE)
1650                         continue;
1651
1652                 id = 0;
1653                 status = contacts_record_get_int(record,
1654                                 _contacts_phone_log.id,
1655                                 &id);
1656
1657                 display_name = _bluetooth_pb_fn_from_phonelog_id(id);
1658
1659                 number = NULL;
1660                 contacts_record_get_str_p(record,
1661                                 _contacts_phone_log.address,
1662                                 &number);
1663
1664
1665                 __bluetooth_pb_list_ptr_array_add(ptr_array,
1666                                 display_name, number, i);
1667
1668                 i++;
1669
1670                 g_free(display_name);
1671
1672         } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
1673
1674         contacts_list_destroy(record_list, TRUE);
1675 }
1676
1677 static void __bluetooth_pb_get_list_number(BluetoothPbAgent *agent,
1678                                                 PhoneBookType pb_type,
1679                                                 gint start_index,
1680                                                 gint end_index,
1681                                                 GPtrArray *ptr_array)
1682 {
1683         contacts_query_h query;
1684
1685         switch (pb_type) {
1686         case TELECOM_PB:
1687                 query = __bluetooth_pb_query_person_number();
1688                 __bluetooth_pb_get_contact_list_number(agent, query,
1689                                 start_index, end_index, ptr_array);
1690                 break;
1691         case TELECOM_ICH:
1692                 query = __bluetooth_pb_query_phone_log_incoming();
1693                 __bluetooth_pb_get_phone_log_list_number(agent, query,
1694                                 start_index, end_index, ptr_array);
1695                 break;
1696         case TELECOM_OCH:
1697                 query = __bluetooth_pb_query_phone_log_outgoing();
1698                 __bluetooth_pb_get_phone_log_list_number(agent, query,
1699                                 start_index, end_index, ptr_array);
1700                 break;
1701         case TELECOM_MCH:
1702                 query = __bluetooth_pb_query_phone_log_missed();
1703                 __bluetooth_pb_get_phone_log_list_number(agent, query,
1704                                 start_index, end_index, ptr_array);
1705                 break;
1706         case TELECOM_CCH:
1707                 query = __bluetooth_pb_query_phone_log_combined();
1708                 __bluetooth_pb_get_phone_log_list_number(agent, query,
1709                                 start_index, end_index, ptr_array);
1710                 break;
1711         default:
1712                 return;
1713         }
1714
1715         if (query)
1716                 contacts_query_destroy(query);
1717 }
1718
1719 static void __bluetooth_pb_get_contact_list_name(BluetoothPbAgent *agent,
1720                                                 contacts_query_h query,
1721                                                 const gchar *find_text,
1722                                                 GPtrArray *ptr_array)
1723 {
1724         contacts_list_h record_list = NULL;
1725
1726         gint status;
1727         gint i = 1;
1728
1729         status = contacts_db_get_records_with_query(query,
1730                         -1, -1, &record_list);
1731
1732         if (status != CONTACTS_ERROR_NONE)
1733                 return;
1734
1735         status = contacts_list_first(record_list);
1736
1737         if (status != CONTACTS_ERROR_NONE) {
1738                 contacts_list_destroy(record_list, TRUE);
1739                 return;
1740         }
1741
1742         do {
1743                 contacts_record_h record;
1744
1745                 gchar *display_name;
1746
1747                 record = NULL;
1748                 status = contacts_list_get_current_record_p(record_list,
1749                                 &record);
1750
1751                 if (status != CONTACTS_ERROR_NONE)
1752                         continue;
1753
1754                 display_name = NULL;
1755                 contacts_record_get_str_p(record,
1756                                 _contacts_person_number.display_name,
1757                                 &display_name);
1758
1759                 if (g_str_has_prefix(display_name, find_text)) {
1760                         gchar *number;
1761
1762                         number = NULL;
1763                         contacts_record_get_str_p(record,
1764                                         _contacts_person_number.number,
1765                                         &number);
1766
1767                         __bluetooth_pb_list_ptr_array_add(ptr_array,
1768                                         display_name, number, i);
1769                 }
1770
1771                 i++;
1772         } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
1773 }
1774
1775 static void __bluetooth_pb_get_phone_log_list_name(BluetoothPbAgent *agent,
1776                                                 contacts_query_h query,
1777                                                 const gchar *find_text,
1778                                                 GPtrArray *ptr_array)
1779 {
1780         contacts_list_h record_list = NULL;
1781
1782         gint status;
1783
1784         gint i = 1;
1785
1786         status = contacts_db_get_records_with_query(query,
1787                         -1, -1,
1788                         &record_list);
1789
1790         if (status != CONTACTS_ERROR_NONE)
1791                 return;
1792
1793         status = contacts_list_first(record_list);
1794
1795         if (status != CONTACTS_ERROR_NONE) {
1796                 contacts_list_destroy(record_list, TRUE);
1797                 return;
1798         }
1799
1800         do {
1801                 contacts_record_h record = NULL;
1802
1803                 gint id;
1804
1805                 gchar *display_name;
1806
1807                 record = NULL;
1808                 status = contacts_list_get_current_record_p(record_list,
1809                                 &record);
1810
1811                 if (status != CONTACTS_ERROR_NONE)
1812                         continue;
1813
1814                 id = 0;
1815                 status = contacts_record_get_int(record,
1816                                 _contacts_phone_log.id,
1817                                 &id);
1818
1819                 display_name = _bluetooth_pb_fn_from_phonelog_id(id);
1820
1821                 if (g_str_has_prefix(display_name, find_text)) {
1822                         gchar *number = NULL;
1823
1824                         number = NULL;
1825                         contacts_record_get_str_p(record,
1826                                         _contacts_phone_log.address,
1827                                         &number);
1828
1829                         __bluetooth_pb_list_ptr_array_add(ptr_array,
1830                                         display_name, number, i);
1831                 }
1832
1833                 i++;
1834
1835                 g_free(display_name);
1836
1837         } while (contacts_list_next(record_list) == CONTACTS_ERROR_NONE);
1838
1839         contacts_list_destroy(record_list, TRUE);
1840 }
1841
1842 static void __bluetooth_pb_get_list_name(BluetoothPbAgent *agent,
1843                                         PhoneBookType pb_type,
1844                                         const gchar *find_text,
1845                                         GPtrArray *ptr_array)
1846 {
1847         contacts_query_h query;
1848
1849         switch (pb_type) {
1850         case TELECOM_PB:
1851                 query = __bluetooth_pb_query_person_number();
1852                 __bluetooth_pb_get_contact_list_name(agent, query,
1853                                 find_text, ptr_array);
1854                 break;
1855         case TELECOM_ICH:
1856                 query = __bluetooth_pb_query_phone_log_incoming();
1857                 __bluetooth_pb_get_phone_log_list_name(agent, query,
1858                                 find_text, ptr_array);
1859                 break;
1860         case TELECOM_OCH:
1861                 query = __bluetooth_pb_query_phone_log_outgoing();
1862                 __bluetooth_pb_get_phone_log_list_name(agent, query,
1863                                 find_text, ptr_array);
1864                 break;
1865         case TELECOM_MCH:
1866                 query = __bluetooth_pb_query_phone_log_missed();
1867                 __bluetooth_pb_get_phone_log_list_name(agent, query,
1868                                 find_text, ptr_array);
1869                 break;
1870         case TELECOM_CCH:
1871                 query = __bluetooth_pb_query_phone_log_combined();
1872                 __bluetooth_pb_get_phone_log_list_name(agent, query,
1873                                 find_text, ptr_array);
1874                 break;
1875         default:
1876                 return;
1877         }
1878
1879         if (query)
1880                 contacts_query_destroy(query);
1881 }
1882
1883 static void __bluetooth_pb_list_hash_reset(BluetoothPbAgent *agent)
1884 {
1885         if(agent->contact_list)
1886                 g_hash_table_destroy(agent->contact_list);
1887
1888         agent->contact_list = g_hash_table_new(g_direct_hash, g_direct_equal);
1889 }
1890
1891 static gboolean __bluetooth_pb_list_hash_insert(BluetoothPbAgent *agent,
1892                                                 gint handle,
1893                                                 gint id)
1894 {
1895         if (agent->contact_list == NULL)
1896                 return FALSE;
1897
1898         g_hash_table_insert(agent->contact_list,
1899                         GINT_TO_POINTER(handle), GINT_TO_POINTER(id));
1900
1901         return TRUE;
1902 }
1903
1904 static gint __bluetooth_pb_list_hash_lookup_id(BluetoothPbAgent *agent,
1905                                         gint handle)
1906 {
1907         gint id;
1908
1909         if (agent->contact_list == NULL)
1910                 return 0;
1911
1912         id = GPOINTER_TO_INT(g_hash_table_lookup(agent->contact_list,
1913                                 GINT_TO_POINTER(handle)));
1914
1915         return id;
1916 }
1917
1918 static void __bluetooth_pb_list_ptr_array_add(GPtrArray *ptr_array,
1919                                                 const gchar *name,
1920                                                 const gchar *number,
1921                                                 gint handle)
1922 {
1923         GValue value = { 0, };
1924
1925         g_value_init(&value, DBUS_STRUCT_STRING_STRING_UINT);
1926         g_value_take_boxed(&value,
1927                         dbus_g_type_specialized_construct(DBUS_STRUCT_STRING_STRING_UINT));
1928
1929         dbus_g_type_struct_set(&value,
1930                                 0, g_strdup(name),
1931                                 1, g_strdup(number),
1932                                 2, handle,
1933                                 G_MAXUINT);
1934
1935         g_ptr_array_add(ptr_array, g_value_get_boxed(&value));
1936 }
1937
1938 static void __bluetooth_pb_list_ptr_array_free(gpointer data)
1939 {
1940         GValue value = { 0, };
1941
1942         gchar *name = NULL;
1943         gchar *number = NULL;
1944
1945         if(data == NULL)
1946                 return;
1947
1948         g_value_init(&value, DBUS_STRUCT_STRING_STRING_UINT);
1949         g_value_set_boxed(&value, data);
1950
1951         dbus_g_type_struct_get(&value,
1952                         0, &name,
1953                         1, &number,
1954                         G_MAXUINT);
1955
1956         g_free(name);
1957         g_free(number);
1958 }
1959
1960 static void __bluetooth_pb_agent_signal_handler(int signum)
1961 {
1962         if (mainloop)
1963                 g_main_loop_quit(mainloop);
1964         else
1965                 exit(0);
1966 }
1967
1968
1969 static void __bluetooth_pb_contact_changed(const gchar *view_uri,
1970                                         void *user_data)
1971 {
1972         BluetoothPbAgent *agent;
1973
1974         g_return_if_fail(BLUETOOTH_IS_PB_AGENT(user_data));
1975         agent = BLUETOOTH_PB_AGENT(user_data);
1976
1977         g_signal_emit(agent, signals[CLEAR], 0);
1978         g_object_unref(agent);
1979 }
1980
1981 static void __bluetooth_pb_agent_timeout_add_seconds(BluetoothPbAgent *agent)
1982 {
1983         g_return_if_fail(BLUETOOTH_IS_PB_AGENT(agent));
1984
1985         if(agent->timeout_id)
1986                 g_source_remove(agent->timeout_id);
1987
1988         agent->timeout_id = g_timeout_add_seconds(BLUETOOTH_PB_AGENT_TIMEOUT,
1989                                 __bluetooth_pb_agent_timeout_calback,
1990                                 agent);
1991 }
1992
1993 static gboolean __bluetooth_pb_agent_timeout_calback(gpointer user_data)
1994 {
1995         BluetoothPbAgent *agent;
1996
1997         g_return_val_if_fail(BLUETOOTH_IS_PB_AGENT(user_data), FALSE);
1998
1999         agent = BLUETOOTH_PB_AGENT(user_data);
2000         agent->timeout_id = 0;
2001
2002         if (mainloop)
2003                 g_main_loop_quit(mainloop);
2004
2005         return FALSE;
2006 }
2007
2008 static void __bluetooth_pb_tel_callback(TapiHandle *handle,
2009                                         int result,
2010                                         void *data,
2011                                         void *user_data)
2012 {
2013         BluetoothPbAgent *agent;
2014         TelSimMsisdnList_t *number;
2015
2016         g_return_if_fail(BLUETOOTH_IS_PB_AGENT(user_data));
2017
2018         agent = BLUETOOTH_PB_AGENT(user_data);
2019
2020         __bluetooth_pb_agent_dbus_init(agent);
2021
2022         number = (TelSimMsisdnList_t *)data;
2023         agent->tel_number = g_strdup(number->list[0].num);
2024
2025         tel_deinit(agent->tapi_handle);
2026         agent->tapi_handle = NULL;
2027 }
2028
2029 static void __bluetooth_pb_agent_dbus_init(BluetoothPbAgent *agent)
2030 {
2031         guint result = 0;
2032         GError *error = NULL;
2033
2034         agent->bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
2035
2036         if (error != NULL) {
2037                 DBG("Couldn't connect to system bus[%s]\n", error->message);
2038                 g_error_free(error);
2039                 return;
2040         }
2041
2042         agent->proxy = dbus_g_proxy_new_for_name(agent->bus,
2043                         DBUS_SERVICE_DBUS,
2044                         DBUS_PATH_DBUS,
2045                         DBUS_INTERFACE_DBUS);
2046
2047         if (agent->proxy == NULL) {
2048                 DBG("Failed to get a proxy for D-Bus\n");
2049                 return;
2050         }
2051
2052         if (!dbus_g_proxy_call(agent->proxy,
2053                                 "RequestName", &error,
2054                                 G_TYPE_STRING, BT_PB_SERVICE_NAME,
2055                                 G_TYPE_UINT, 0,
2056                                 G_TYPE_INVALID,
2057                                 G_TYPE_UINT, &result,
2058                                 G_TYPE_INVALID)) {
2059                 if (error != NULL) {
2060                         DBG("RequestName RPC failed[%s]\n", error->message);
2061                         g_error_free(error);
2062                 }
2063
2064                 g_object_unref(agent->proxy);
2065                 agent->proxy = NULL;
2066
2067                 return;
2068         }
2069         DBG("result : %d %d\n", result, DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER);
2070         if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
2071                 DBG("Failed to get the primary well-known name.\n");
2072
2073                 g_object_unref(agent->proxy);
2074                 agent->proxy = NULL;
2075
2076                 return;
2077         }
2078
2079         g_object_unref(agent->proxy);
2080         agent->proxy = NULL;
2081
2082         dbus_g_connection_register_g_object(agent->bus,
2083                         BT_PB_SERVICE_OBJECT_PATH,
2084                         G_OBJECT(agent));
2085 }
2086
2087 int main(int argc, char **argv)
2088 {
2089         BluetoothPbAgent *agent;
2090
2091         gint ret = EXIT_SUCCESS;
2092         gint tapi_result;
2093
2094         struct sigaction sa;
2095
2096         g_type_init();
2097
2098         mainloop = g_main_loop_new(NULL, FALSE);
2099         if (mainloop == NULL) {
2100                 DBG("Couldn't create GMainLoop\n");
2101                 return EXIT_FAILURE;
2102         }
2103
2104         agent = g_object_new(BLUETOOTH_PB_TYPE_AGENT, NULL);
2105
2106         /* connect contact */
2107         if (contacts_connect2() != CONTACTS_ERROR_NONE) {
2108                 DBG("Can not connect contacts server\n");
2109                 g_object_unref(agent);
2110                 return EXIT_FAILURE;
2111         }
2112
2113         if (contacts_db_add_changed_cb(_contacts_event._uri,
2114                         __bluetooth_pb_contact_changed,
2115                         g_object_ref(agent)) != CONTACTS_ERROR_NONE) {
2116                 DBG("Can not add changed callback");
2117         }
2118
2119         /* set signal */
2120         memset(&sa, 0, sizeof(sa));
2121         sa.sa_handler = __bluetooth_pb_agent_signal_handler;
2122         sigaction(SIGTERM, &sa, NULL);
2123         sigaction(SIGINT, &sa, NULL);
2124
2125         /* init tapi */
2126         agent->tapi_handle = tel_init(NULL);
2127         tapi_result = tel_get_sim_msisdn(agent->tapi_handle,
2128                         __bluetooth_pb_tel_callback, agent);
2129
2130         if (tapi_result != TAPI_API_SUCCESS) {
2131                 __bluetooth_pb_agent_dbus_init(agent);
2132         }
2133
2134
2135         __bluetooth_pb_agent_timeout_add_seconds(agent);
2136
2137         g_main_loop_run(mainloop);
2138
2139         DBG("Terminate the bluetooth-pb-agent\n");
2140
2141         if (agent) {
2142                 contacts_db_remove_changed_cb(_contacts_event._uri,
2143                                 __bluetooth_pb_contact_changed,
2144                                 g_object_ref(agent));
2145
2146                 g_object_unref(agent);
2147         }
2148
2149
2150         contacts_disconnect2();
2151
2152         g_signal_emit(agent, signals[CLEAR], 0);
2153
2154         if (agent)
2155                 g_object_unref(agent);
2156
2157         return ret;
2158 }