#define PHONEBOOK_PATH "/org/bluez/pb_agent"
#define PHONEBOOK_INTERFACE "org.bluez.PbAgent"
+#define QUERY_GET_PHONEBOOK_FOLDER_LIST "GetPhonebookFolderList"
#define QUERY_GET_PHONEBOOK_SIZE "GetPhonebookSize"
#define QUERY_GET_PHONEBOOK "GetPhonebook"
#define QUERY_GET_PHONEBOOK_LIST "GetPhonebookList"
#define QUERY_GET_PHONEBOOK_ENTRY "GetPhonebookEntry"
+#define QUERY_DESTROY_AGENT "DestroyAgent"
+
+static GPtrArray *folder_list = NULL;
struct phonebook_data {
phonebook_cb cb;
void *user_data;
};
-static gboolean folder_is_valid(const char *folder)
+static gboolean folder_is_valid(const gchar *folder,
+ gboolean leaf_only)
{
- if (folder == NULL)
+ int i;
+ int folder_len;
+
+ if (folder_list == NULL || folder == NULL)
return FALSE;
- if (g_str_equal(folder, "/"))
- return TRUE;
- else if (g_str_equal(folder, "/telecom"))
- return TRUE;
- else if (g_str_equal(folder, "/telecom/pb"))
- return TRUE;
- else if (g_str_equal(folder, "/telecom/ich"))
- return TRUE;
- else if (g_str_equal(folder, "/telecom/och"))
- return TRUE;
- else if (g_str_equal(folder, "/telecom/mch"))
- return TRUE;
- else if (g_str_equal(folder, "/telecom/cch"))
- return TRUE;
+ folder_len = strlen(folder);
+
+ for (i = 0 ; i < folder_list->len; i++) {
+ char *str = (char *)g_ptr_array_index(folder_list, i);
+
+ if (folder_len > strlen(str))
+ continue;
+
+ if (g_strcmp0(str, folder) == 0)
+ return TRUE;
+
+ if (leaf_only == TRUE)
+ continue;
+
+ if (strncmp(str, folder, folder_len) == 0) {
+
+ if (*(folder + folder_len - 1) == '/')
+ return TRUE; /* folder is ended with '/' */
+
+ if (*(str + folder_len) == '/')
+ return TRUE; /* folder is matched */
+ }
+ }
return FALSE;
}
va_list args;
+ DBG("%s\n", method);
+
if (!method) {
error("Can't get method name");
return FALSE;
}
- DBG("%s\n", method);
-
connection = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL);
if (!connection) {
error("Can't get on session bus");
dbus_message_append_args_valist(message, first_arg_type, args);
va_end(args);
- if (dbus_connection_send_with_reply(connection, message, &call, -1) ==
- FALSE) {
+ if (dbus_connection_send_with_reply(connection, message, &call, -1) == FALSE) {
dbus_message_unref(message);
dbus_connection_unref(connection);
return FALSE;
DBusError derr;
uint32_t phonebook_size;
+ unsigned int new_missed_call = 0;
+
DBG("");
if (!reply) {
dbus_error_free(&derr);
phonebook_size = 0;
} else {
- dbus_message_get_args(reply, NULL, DBUS_TYPE_UINT32,
- &phonebook_size, DBUS_TYPE_INVALID);
+ dbus_message_get_args(reply, NULL,
+ DBUS_TYPE_UINT32, &phonebook_size,
+ DBUS_TYPE_UINT32, &new_missed_call,
+ DBUS_TYPE_INVALID);
DBG("phonebooksize:%d\n", phonebook_size);
}
- s_data->cb(NULL, 0, phonebook_size, 0, TRUE, s_data->user_data);
+ s_data->cb(NULL, 0, phonebook_size, new_missed_call, TRUE, s_data->user_data);
dbus_message_unref(reply);
}
DBusError derr;
GString *buffer;
- guint new_missed_call = 0;
+ unsigned int new_missed_call = 0;
uint32_t count = 0;
DBusMessageIter recurse_iter;
dbus_message_iter_recurse(&iter, &recurse_iter);
- while (dbus_message_iter_get_arg_type(&recurse_iter) ==
- DBUS_TYPE_STRING) {
+ while (dbus_message_iter_get_arg_type(&recurse_iter) == DBUS_TYPE_STRING) {
gchar *str;
- dbus_message_iter_get_basic(&recurse_iter,
- &str);
+ dbus_message_iter_get_basic(&recurse_iter, &str);
dbus_message_iter_next(&recurse_iter);
g_string_append(buffer, str);
dbus_message_iter_next(&iter);
}
- if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_UINT16)
+ if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_UINT32)
dbus_message_iter_get_basic(&iter, &new_missed_call);
DBG("new_missed_call %d\n", new_missed_call);
}
- s_data->cb(buffer->str, buffer->len, count, new_missed_call, 1,
- s_data->user_data);
+ s_data->cb(buffer->str, buffer->len, count, new_missed_call, 1, s_data->user_data);
g_string_free(buffer, TRUE);
dbus_message_unref(reply);
DBusMessage *reply = dbus_pending_call_steal_reply(call);
struct phonebook_data *s_data = user_data;
DBusError derr;
- const char *phonebook_entry = NULL;
- uint32_t phonebook_entry_size = 0;
- int vcards = 1;
+ const char *phonebook_entry;
DBG("");
dbus_error_init(&derr);
if (dbus_set_error_from_message(&derr, reply)) {
- error("Replied with an error: %s, %s",
- derr.name, derr.message);
+ error("Replied with an error: %s, %s", derr.name, derr.message);
dbus_error_free(&derr);
- vcards = -1;
} else {
dbus_message_get_args(reply, NULL, DBUS_TYPE_STRING,
&phonebook_entry, DBUS_TYPE_INVALID);
- if (phonebook_entry)
- phonebook_entry_size = strlen(phonebook_entry);
DBG("phonebook_entry:[%s]\n", phonebook_entry);
}
- s_data->cb(phonebook_entry, phonebook_entry_size, vcards, 0, TRUE,
+ s_data->cb(phonebook_entry, strlen(phonebook_entry), 1, 0, TRUE,
s_data->user_data);
dbus_message_unref(reply);
}
-static gboolean get_sim_phonebook_reply(void *user_data)
-{
- struct phonebook_data *s_data = user_data;
- uint32_t phonebook_size = 0;
- int lastpart = 1;
-
- DBG("");
-
- /* We don't support phonebook of SIM
- * Send dummy data */
- s_data->cb(NULL, 0, phonebook_size, 0, lastpart, s_data->user_data);
-
- return FALSE;
-}
-
static gboolean clear_signal(DBusConnection *conn, DBusMessage *msg,
void *user_data)
{
return TRUE;
}
+static gboolean phonebook_folder_list_init(struct phonebook_session *session)
+{
+ DBusMessage *message;
+ DBusMessage *reply;
+
+ DBusMessageIter iter;
+ DBusMessageIter recurse_iter;
+
+ DBusError error;
+
+ if (session->connection == NULL) {
+ session->connection = g_dbus_setup_bus(DBUS_BUS_SYSTEM,
+ NULL, NULL);
+ }
+
+ if (session->connection == NULL) {
+ DBG("Can't get on s bus");
+ return FALSE;
+ }
+
+ message = dbus_message_new_method_call(PHONEBOOK_DESTINATION,
+ PHONEBOOK_PATH,
+ PHONEBOOK_INTERFACE,
+ QUERY_GET_PHONEBOOK_FOLDER_LIST);
+
+ if (message == NULL) {
+ DBG("Can't allocate dbus message");
+ return FALSE;
+ }
+
+ dbus_error_init(&error);
+
+ reply = dbus_connection_send_with_reply_and_block(session->connection,
+ message, -1, &error);
+
+ if (!reply) {
+ if (dbus_error_is_set(&error) == TRUE) {
+ DBG("%s", error.message);
+ dbus_error_free(&error);
+ } else {
+ DBG("Failed to get contacts");
+ }
+ dbus_message_unref(message);
+ return FALSE;
+ }
+
+ dbus_message_iter_init(reply, &iter);
+
+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) {
+ dbus_message_unref(message);
+ dbus_message_unref(reply);
+ return FALSE;
+ }
+
+ if (folder_list) {
+ g_ptr_array_free(folder_list, TRUE);
+ folder_list = NULL;
+ }
+
+ folder_list = g_ptr_array_new();
+
+ dbus_message_iter_recurse(&iter, &recurse_iter);
+
+ while (dbus_message_iter_get_arg_type(&recurse_iter)
+ == DBUS_TYPE_STRING) {
+ gchar *str;
+
+ dbus_message_iter_get_basic(&recurse_iter, &str);
+ DBG("folder list %s\n", str);
+ g_ptr_array_add(folder_list, g_strdup(str));
+
+ dbus_message_iter_next(&recurse_iter);
+ }
+
+ dbus_message_unref(message);
+ dbus_message_unref(reply);
+ return TRUE;
+}
int phonebook_init(void)
{
int phonebook_connect(void **user_data)
{
struct phonebook_session *session;
+ gboolean ret;
DBG("");
*user_data = session;
- return 0;
+ ret = phonebook_folder_list_init(session);
+
+ if (ret)
+ return 0;
+
+ return -1;
}
void phonebook_disconnect(void *user_data)
{
struct phonebook_session *session;
-
+ DBusMessage *message;
DBG("");
session = user_data;
- g_dbus_remove_watch(session->connection, session->clear_id);
- dbus_connection_unref(session->connection);
+ if (folder_list) {
+ g_ptr_array_free(folder_list, TRUE);
+ folder_list = NULL;
+ }
+
+ if (!session->connection) {
+ g_free(session);
+ return;
+ }
+
+
+ if (session->clear_id)
+ g_dbus_remove_watch(session->connection, session->clear_id);
+
+ message = dbus_message_new_method_call(PHONEBOOK_DESTINATION,
+ PHONEBOOK_PATH,
+ PHONEBOOK_INTERFACE,
+ QUERY_DESTROY_AGENT);
+ if (message) {
+ if (dbus_connection_send(session->connection, message,
+ NULL) == FALSE)
+ error("Could not send dbus message");
+
+ dbus_message_unref(message);
+ }
+
+ dbus_connection_unref(session->connection);
g_free(session);
}
child = (new_folder && strlen(new_folder) != 0);
switch (flags) {
- case 0x02:
- /* Go back to root */
- if (!child) {
- path = g_strdup("/");
- goto done;
- }
+ case 0x02:
+ /* Go back to root */
+ if (!child) {
+ path = g_strdup("/");
+ goto done;
+ }
- path = g_build_filename(current_folder, new_folder, NULL);
- break;
- case 0x03:
- /* Go up 1 level */
- if (root) {
- /* Already root */
- path = g_strdup("/");
- goto done;
- }
+ path = g_build_filename(current_folder, new_folder, NULL);
+ break;
+ case 0x03:
+ /* Go up 1 level */
+ if (root) {
+ /* Already root */
+ path = g_strdup("/");
+ goto done;
+ }
- /*
- * Removing one level of the current folder. Current folder
- * contains AT LEAST one level since it is not at root folder.
- * Use glib utility functions to handle invalid chars in the
- * folder path properly.
- */
- tmp1 = g_path_get_basename(current_folder);
- tmp2 = g_strrstr(current_folder, tmp1);
- len = tmp2 - (current_folder + 1);
-
- g_free(tmp1);
-
- if (len == 0)
- base = g_strdup("/");
- else
- base = g_strndup(current_folder, len);
-
- /* Return: one level only */
- if (!child) {
- path = base;
- goto done;
- }
+ /*
+ * Removing one level of the current folder. Current folder
+ * contains AT LEAST one level since it is not at root folder.
+ * Use glib utility functions to handle invalid chars in the
+ * folder path properly.
+ */
+ tmp1 = g_path_get_basename(current_folder);
+ tmp2 = g_strrstr(current_folder, tmp1);
+ len = tmp2 - (current_folder + 1);
+
+ g_free(tmp1);
+
+ if (len == 0)
+ base = g_strdup("/");
+ else
+ base = g_strndup(current_folder, len);
+
+ /* Return: one level only */
+ if (!child) {
+ path = base;
+ goto done;
+ }
- path = g_build_filename(base, new_folder, NULL);
- g_free(base);
+ path = g_build_filename(base, new_folder, NULL);
+ g_free(base);
- break;
- default:
- ret = -EBADR;
- break;
+ break;
+ default:
+ ret = -EBADR;
+ break;
}
done:
- if (path && !folder_is_valid(path))
+ if (path && !folder_is_valid(path, FALSE))
ret = -ENOENT;
if (ret < 0) {
if (err)
*err = ret;
+ DBG("path : %s\n", path);
+
return path;
}
phonebook_cb cb, void *user_data, int *err)
{
struct phonebook_data *data;
+ char *folder;
DBG("name %s", name);
if (!g_str_has_suffix(name, ".vcf")) {
- DBG("invaild request");
if (err)
- *err = -EBADR;
+ *err = -ENOENT;
+
return NULL;
}
+ folder = g_strndup(name, strlen(name) - 4);
+
+ if (!folder_is_valid(folder, TRUE)) {
+ if (err)
+ *err = -ENOENT;
+
+ g_free(folder);
+ return NULL;
+ }
+
+ g_free(folder);
+
data = g_new0(struct phonebook_data, 1);
data->params = params;
data->user_data = user_data;
return 0;
}
- if (g_strcmp0(data->req_name, "/SIM1/telecom/pb.vcf") == 0) {
- g_idle_add(get_sim_phonebook_reply, data);
- return 0;
- }
-
phonebook_request(data,
QUERY_GET_PHONEBOOK,
get_phonebook_reply,
void *user_data, int *err)
{
struct phonebook_data *data;
+ gboolean req = FALSE;
if (!g_str_has_suffix(id, ".vcf")) {
- DBG("invaild request");
if (err)
- *err = -EBADR;
+ *err = -ENOENT;
+
+ return NULL;
+ }
+
+ if (!folder_is_valid(folder, TRUE)) {
+ if (err)
+ *err = - ENOENT;
+
return NULL;
}
+
DBG("folder %s id %s", folder, id);
data = g_new0(struct phonebook_data, 1);
data->user_data = user_data;
data->cb = cb;
- phonebook_request(data,
+ req = phonebook_request(data,
QUERY_GET_PHONEBOOK_ENTRY,
get_phonebook_entry_reply,
DBUS_TYPE_STRING, &folder,
DBUS_TYPE_BYTE, &data->params->format,
DBUS_TYPE_INVALID);
+ if (*err) {
+ if (req)
+ *err = 0;
+ else {
+ *err = -ENOENT;
+ g_free(data);
+ data = NULL;
+ }
+ }
+
return data;
}
struct phonebook_data *data;
gboolean req = FALSE;
+ if (!folder_is_valid(name, TRUE)) {
+ if (err)
+ *err = - ENOENT;
+
+ return NULL;
+ }
+
DBG("name %s", name);
data = g_new0(struct phonebook_data, 1);
if (*err) {
if (req)
*err = 0;
- else
+ else {
*err = -ENOENT;
+ g_free(data);
+ data = NULL;
+ }
}
return data;