4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Hocheol Seo <hocheol.seo@samsung.com>
7 * Girishashok Joshi <girish.joshi@samsung.com>
8 * Chanyeol Park <chanyeol.park@samsung.com>
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
36 #include <sys/types.h>
42 #include "phonebook.h"
44 #include <dbus/dbus.h>
45 #define QUERY_GET_PHONEBOOK_SIZE "GetPhonebookSize"
47 #define QUERY_GET_PHONEBOOK "GetPhonebook"
48 #define QUERY_GET_CALLS "GetCalls"
50 #define QUERY_GET_PHONEBOOK_LIST "GetPhonebookList"
51 #define QUERY_GET_CALLS_LIST "GetCallsList"
53 #define QUERY_GET_PHONEBOOK_ENTRY "GetPhonebookEntry"
54 #define QUERY_GET_CALLS_ENTRY "GetCallsEntry"
56 #define QUERY_CALL_TYPE_INCOMING "incoming"
57 #define QUERY_CALL_TYPE_OUTGOING "outgoing"
58 #define QUERY_CALL_TYPE_MISSED "missed"
59 #define QUERY_CALL_TYPE_COMBINED "combined"
61 struct phonebook_tizen_data {
63 DBusPendingCallNotifyFunction reply_cb;
65 const struct apparam_field *params;
67 phonebook_entry_cb entry_cb;
68 phonebook_cache_ready_cb ready_cb;
74 static void get_phonebook_reply(DBusPendingCall *call, void *user_data);
75 static void get_phonebook_size_reply(DBusPendingCall *call, void *user_data);
76 static void get_phonebook_list_reply(DBusPendingCall *call, void *user_data);
77 static void get_phonebook_entry_reply(DBusPendingCall *call, void *user_data);
78 int get_phonebook_data(const char *query, const char *call_type,
79 struct phonebook_tizen_data *s_data);
80 static gboolean get_sim_phonebook_reply(void *user_data);
82 static gboolean folder_is_valid(const char *folder)
87 if (g_str_equal(folder, "/"))
89 else if (g_str_equal(folder, "/telecom"))
91 else if (g_str_equal(folder, "/telecom/pb"))
93 else if (g_str_equal(folder, "/telecom/ich"))
95 else if (g_str_equal(folder, "/telecom/och"))
97 else if (g_str_equal(folder, "/telecom/mch"))
99 else if (g_str_equal(folder, "/telecom/cch"))
105 int phonebook_init(void)
110 void phonebook_exit(void)
115 char *phonebook_set_folder(const char *current_folder,
116 const char *new_folder, uint8_t flags, int *err)
118 char *tmp1, *tmp2, *base, *path = NULL;
119 gboolean root, child;
123 root = (g_strcmp0("/", current_folder) == 0);
124 child = (new_folder && strlen(new_folder) != 0);
128 /* Go back to root */
130 path = g_strdup("/");
134 path = g_build_filename(current_folder, new_folder, NULL);
140 path = g_strdup("/");
145 * Removing one level of the current folder. Current folder
146 * contains AT LEAST one level since it is not at root folder.
147 * Use glib utility functions to handle invalid chars in the
148 * folder path properly.
150 tmp1 = g_path_get_basename(current_folder);
151 tmp2 = g_strrstr(current_folder, tmp1);
152 len = tmp2 - (current_folder + 1);
157 base = g_strdup("/");
159 base = g_strndup(current_folder, len);
161 /* Return: one level only */
167 path = g_build_filename(base, new_folder, NULL);
177 if (path && !folder_is_valid(path))
191 void phonebook_req_finalize(void *request)
193 struct phonebook_tizen_data *data = request;
200 g_free(data->req_name);
204 void *phonebook_pull(const char *name, const struct apparam_field *params,
205 phonebook_cb cb, void *user_data, int *err)
207 struct phonebook_tizen_data *data;
209 DBG("name %s", name);
211 if (!g_str_has_suffix(name, ".vcf")) {
212 DBG("invaild request");
218 data = g_new0(struct phonebook_tizen_data, 1);
219 data->params = params;
220 data->user_data = user_data;
222 data->req_name = g_strdup(name);
230 int phonebook_pull_read(void *request)
232 struct phonebook_tizen_data *s_data = request;
234 const char *call_type = NULL;
236 DBG("name %s", s_data->req_name);
238 s_data->reply_cb = get_phonebook_reply;
240 if (g_strcmp0(s_data->req_name, "/telecom/ich.vcf") == 0) {
241 call_type = QUERY_CALL_TYPE_INCOMING;
242 query = QUERY_GET_CALLS;
243 } else if (g_strcmp0(s_data->req_name, "/telecom/och.vcf") == 0) {
244 call_type = QUERY_CALL_TYPE_OUTGOING;
245 query = QUERY_GET_CALLS;
246 } else if (g_strcmp0(s_data->req_name, "/telecom/mch.vcf") == 0) {
247 call_type = QUERY_CALL_TYPE_MISSED;
248 query = QUERY_GET_CALLS;
249 } else if (g_strcmp0(s_data->req_name, "/telecom/cch.vcf") == 0) {
250 call_type = QUERY_CALL_TYPE_COMBINED;
251 query = QUERY_GET_CALLS;
252 } else if (g_strcmp0(s_data->req_name, "/SIM1/telecom/pb.vcf") == 0) {
253 g_idle_add(get_sim_phonebook_reply, s_data);
255 } else if (s_data->params->maxlistcount == 0) {
256 query = QUERY_GET_PHONEBOOK_SIZE;
257 s_data->reply_cb = get_phonebook_size_reply;
259 query = QUERY_GET_PHONEBOOK;
262 get_phonebook_data(query, call_type, s_data);
267 void *phonebook_get_entry(const char *folder, const char *id,
268 const struct apparam_field *params, phonebook_cb cb,
269 void *user_data, int *err)
271 struct phonebook_tizen_data *s_data;
272 DBusPendingCallNotifyFunction reply_cb;
275 DBG("folder %s id %s", folder, id);
277 if (g_strcmp0(folder, "/telecom/pb") == 0) {
278 query = QUERY_GET_PHONEBOOK_ENTRY;
280 query = QUERY_GET_CALLS_ENTRY;
283 reply_cb = get_phonebook_entry_reply;
285 s_data = g_new0(struct phonebook_tizen_data, 1);
286 s_data->params = params;
287 s_data->user_data = user_data;
289 s_data->reply_cb = reply_cb;
292 get_phonebook_data(query, NULL, s_data);
300 void *phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
301 phonebook_cache_ready_cb ready_cb, void *user_data, int *err)
303 struct phonebook_tizen_data *s_data;
304 DBusPendingCallNotifyFunction reply_cb;
306 const char *call_type = NULL;
308 DBG("name %s", name);
310 if (g_strcmp0(name, "/telecom/pb") == 0) {
311 query = QUERY_GET_PHONEBOOK_LIST;
312 } else if (g_strcmp0(name, "/telecom/ich") == 0) {
313 call_type = QUERY_CALL_TYPE_INCOMING;
314 query = QUERY_GET_CALLS_LIST;
315 } else if (g_strcmp0(name, "/telecom/och") == 0) {
316 call_type = QUERY_CALL_TYPE_OUTGOING;
317 query = QUERY_GET_CALLS_LIST;
318 } else if (g_strcmp0(name, "/telecom/mch") == 0) {
319 call_type = QUERY_CALL_TYPE_MISSED;
320 query = QUERY_GET_CALLS_LIST;
321 } else if (g_strcmp0(name, "/telecom/cch") == 0) {
322 call_type = QUERY_CALL_TYPE_COMBINED;
323 query = QUERY_GET_CALLS_LIST;
330 reply_cb = get_phonebook_list_reply;
332 s_data = g_new0(struct phonebook_tizen_data, 1);
333 s_data->user_data = user_data;
334 s_data->entry_cb = entry_cb;
335 s_data->ready_cb = ready_cb;
336 s_data->reply_cb = reply_cb;
337 s_data->params = NULL;
339 get_phonebook_data(query, call_type, s_data);
347 static void get_phonebook_reply(DBusPendingCall *call, void *user_data)
349 DBusMessage *reply = dbus_pending_call_steal_reply(call);
350 DBusMessageIter iter, element;
351 struct phonebook_tizen_data *s_data = user_data;
353 uint32_t phonebook_size = 0;
359 buffer = g_string_new("");
361 dbus_error_init(&derr);
362 if (dbus_set_error_from_message(&derr, reply)) {
363 error("Replied with an error: %s, %s", derr.name, derr.message);
364 dbus_error_free(&derr);
366 dbus_message_iter_init(reply, &iter);
368 if (dbus_message_iter_get_arg_type(&iter) ==
370 dbus_message_iter_get_basic(&iter, &lastpart);
371 dbus_message_iter_next(&iter);
374 dbus_message_iter_recurse(&iter, &element);
376 while(dbus_message_iter_get_arg_type(&element) !=
380 if (dbus_message_iter_get_arg_type(&element) !=
382 DBG("element is not a string");
383 dbus_message_iter_next(&element);
387 dbus_message_iter_get_basic(&element, &arg);
389 g_string_append(buffer, arg);
391 dbus_message_iter_next(&element);
396 DBG("phonebooksize : %d\n", phonebook_size);
399 s_data->cb(buffer->str, buffer->len, phonebook_size, 0, lastpart,
402 g_string_free(buffer, TRUE);
404 dbus_message_unref(reply);
407 static void get_phonebook_size_reply(DBusPendingCall *call, void *user_data)
409 DBusMessage *reply = dbus_pending_call_steal_reply(call);
410 struct phonebook_tizen_data *s_data = user_data;
412 uint32_t phonebook_size;
416 dbus_error_init(&derr);
417 if (dbus_set_error_from_message(&derr, reply)) {
418 error("Replied with an error: %s, %s", derr.name, derr.message);
419 dbus_error_free(&derr);
422 dbus_message_get_args(reply, NULL, DBUS_TYPE_UINT32,
423 &phonebook_size, DBUS_TYPE_INVALID);
424 DBG("phonebooksize:%d\n", phonebook_size);
427 s_data->cb(NULL, 0, phonebook_size, 0, TRUE, s_data->user_data);
429 dbus_message_unref(reply);
432 static void get_phonebook_list_reply(DBusPendingCall *call, void *user_data)
434 DBusMessage *reply = dbus_pending_call_steal_reply(call);
435 DBusMessageIter iter, iter_struct, entry;
436 struct phonebook_tizen_data *s_data = user_data;
439 const char *name = NULL;
440 const char *tel = NULL;
445 dbus_error_init(&derr);
446 if (dbus_set_error_from_message(&derr, reply)) {
447 error("Replied with an error: %s, %s", derr.name, derr.message);
448 dbus_error_free(&derr);
451 dbus_message_iter_init(reply, &iter);
453 dbus_message_iter_recurse(&iter, &iter_struct);
455 while (dbus_message_iter_get_arg_type(&iter_struct) ==
457 dbus_message_iter_recurse(&iter_struct, &entry);
459 dbus_message_iter_get_basic(&entry, &name);
460 dbus_message_iter_next(&entry);
461 dbus_message_iter_get_basic(&entry, &tel);
462 dbus_message_iter_next(&entry);
463 dbus_message_iter_get_basic(&entry, &handle);
465 //DBG("[handle:%d name:%s tel:%s]\n", handle, name, tel);
467 snprintf(id, sizeof(id), "%d.vcf", handle);
469 s_data->entry_cb(id, handle, name, NULL, tel,
472 dbus_message_iter_next(&iter_struct);
476 s_data->ready_cb(s_data->user_data);
478 dbus_message_unref(reply);
481 static void get_phonebook_entry_reply(DBusPendingCall *call, void *user_data)
483 DBusMessage *reply = dbus_pending_call_steal_reply(call);
484 struct phonebook_tizen_data *s_data = user_data;
486 const char *phonebook_entry;
490 dbus_error_init(&derr);
491 if (dbus_set_error_from_message(&derr, reply)) {
492 error("Replied with an error: %s, %s", derr.name, derr.message);
493 dbus_error_free(&derr);
495 dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING,
496 &phonebook_entry, DBUS_TYPE_INVALID);
497 DBG("phonebook_entry:[%s]\n", phonebook_entry);
500 s_data->cb(phonebook_entry, strlen(phonebook_entry), 1, 0, TRUE,
503 dbus_message_unref(reply);
506 int get_phonebook_data(const char *query, const char *call_type,
507 struct phonebook_tizen_data *s_data)
509 DBusConnection *conn;
510 DBusPendingCall *call;
511 DBusMessage *message;
513 DBG("call_type:%s", call_type);
515 conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
517 error("Can't get on session bus");
521 message = dbus_message_new_method_call("org.bluez.pb_agent",
522 "/org/bluez/pb_agent",
526 error("Can't allocate new message");
531 DBG("phonebook_get_entry");
532 dbus_message_append_args(message, DBUS_TYPE_STRING, &s_data->id,
534 } else if (s_data->params) {
535 DBG("phonebook_pull_read");
537 dbus_message_append_args(message, DBUS_TYPE_UINT16,
538 &s_data->params->maxlistcount,
540 &s_data->params->liststartoffset,
541 DBUS_TYPE_STRING, &call_type,
544 dbus_message_append_args(message, DBUS_TYPE_UINT16,
545 &s_data->params->maxlistcount,
547 &s_data->params->liststartoffset,
550 } else if (call_type) {
551 DBG("phonebook_create_cache");
552 dbus_message_append_args(message, DBUS_TYPE_STRING, &call_type,
556 if (dbus_connection_send_with_reply(conn, message, &call,
558 error("Could not send dbus message");
559 dbus_message_unref(message);
563 dbus_pending_call_set_notify(call, s_data->reply_cb, s_data, NULL);
564 dbus_message_unref(message);
566 //dbus_connection_unref(conn);
571 static gboolean get_sim_phonebook_reply(void *user_data)
573 struct phonebook_tizen_data *s_data = user_data;
574 uint32_t phonebook_size = 0;
579 /* We don't support phonebook of SIM
581 s_data->cb(NULL, 0, phonebook_size, 0, lastpart, s_data->user_data);