From 6797354a2583bbe5e2bc529f3313ff2620294bb8 Mon Sep 17 00:00:00 2001 From: DoHyun Pyun Date: Mon, 1 Aug 2016 10:45:54 +0900 Subject: [PATCH] Implement ID based contact share method Change-Id: Ibea1bda8d4c8d49e1a15a971099a06c91ff540cc Signed-off-by: DoHyun Pyun --- CMakeLists.txt | 1 + data/ug-bluetooth-efl.xml | 1 + include/bt-type-define.h | 2 + include/bt-util.h | 4 + packaging/ug-bluetooth-efl.spec | 1 + src/libraries/bt-util.c | 253 ++++++++++++++++++++++++++++++++++++++++ src/ui/bt-main-view.c | 209 ++++++++++++++++++++++----------- 7 files changed, 404 insertions(+), 67 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b5de9e5..a09094d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,7 @@ SET(PKG_MODULES glib-2.0 gio-2.0 dpm + contacts-service2 ) INCLUDE(FindPkgConfig) diff --git a/data/ug-bluetooth-efl.xml b/data/ug-bluetooth-efl.xml index 96647f5..4a1f601 100644 --- a/data/ug-bluetooth-efl.xml +++ b/data/ug-bluetooth-efl.xml @@ -111,5 +111,6 @@ http://tizen.org/privilege/network.get http://tizen.org/privilege/network.set http://tizen.org/privilege/systemsettings.admin + http://tizen.org/privilege/contact.read diff --git a/include/bt-type-define.h b/include/bt-type-define.h index 4670f8a..76d571e 100644 --- a/include/bt-type-define.h +++ b/include/bt-type-define.h @@ -130,6 +130,8 @@ extern "C" { #define BT_APPCONTROL_VISIBILITY_MIME "application/x-bluetooth-visibility" +#define BT_VCF_FOLDER_PATH "/tmp/" + /* AppControl Output */ #define BT_APPCONTROL_ADDRESS "http://tizen.org/appcontrol/data/bluetooth/address" #define BT_APPCONTROL_NAME "http://tizen.org/appcontrol/data/bluetooth/name" diff --git a/include/bt-util.h b/include/bt-util.h index 5906eda..e2b0bd7 100644 --- a/include/bt-util.h +++ b/include/bt-util.h @@ -103,6 +103,10 @@ gboolean _bt_util_is_space_str(const char *name_str); void _bt_util_max_len_reached_cb(void *data, Evas_Object *obj, void *event_info); +char *_bt_util_vcard_create_from_id(int id, bool my_profile, const char *working_dir); + +char *_bt_util_vcard_create_from_id_list(const int *id_list, int count, const char *working_dir, volatile bool *cancel); + int _bt_util_create_dpm_context(void *ug_data); void _bt_util_destroy_dpm_context(void *ug_data); diff --git a/packaging/ug-bluetooth-efl.spec b/packaging/ug-bluetooth-efl.spec index 885304b..31d66b2 100644 --- a/packaging/ug-bluetooth-efl.spec +++ b/packaging/ug-bluetooth-efl.spec @@ -38,6 +38,7 @@ BuildRequires: pkgconfig(capi-appfw-application) BuildRequires: pkgconfig(notification) BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(gio-2.0) +BuildRequires: pkgconfig(contacts-service2) BuildRequires: pkgconfig(dpm) %description diff --git a/src/libraries/bt-util.c b/src/libraries/bt-util.c index 538377f..04cf151 100644 --- a/src/libraries/bt-util.c +++ b/src/libraries/bt-util.c @@ -26,6 +26,9 @@ #include #include #include +#include +#include +#include #include "bt-main-ug.h" #include "bt-util.h" @@ -772,3 +775,253 @@ gboolean _bt_util_is_dpm_restricted(void *handle) return (dpm_state == 0) ? TRUE : FALSE; } +static bool __bt_util_file_exists(const char *file) +{ + bool res = false; + if (file) { + struct stat st; + res = stat(file, &st) == 0 || strcmp(file, "/") == 0; + } + + return res; +} + +static bool __bt_util_file_remove(const char *file) +{ + bool res = false; + if (file) { + res = remove(file) == 0; + } + + return res; +} + +static char *__bt_util_make_vcard_file_path(const char *working_dir, const char *display_name) +{ + char file_path[PATH_MAX] = { 0 }; + int id = 0; + + if (!working_dir) { + return NULL; + } + + if (!display_name) { + display_name = "Unknown"; + } + + do { + snprintf(file_path, sizeof(file_path), "%s%s-%u.vcf", working_dir, display_name, id); + ++id; + } while (__bt_util_file_exists(file_path)); + + BT_DBG("file_path = %s", file_path); + + return strdup(file_path); +} + +static bool __bt_util_write_vcard_to_file(int fd, contacts_record_h record, bool my_profile) +{ + char *vcard_buff = NULL; + bool ok = false; + + do { + int size_left = 0; + + if (my_profile) { + contacts_vcard_make_from_my_profile(record, &vcard_buff); + } else { + contacts_vcard_make_from_person(record, &vcard_buff); + } + + if (!vcard_buff) { + BT_ERR("vcard_buff is NULL"); + break; + } + + size_left = strlen(vcard_buff); + while (size_left) { + int written = write(fd, vcard_buff, size_left); + if (written == -1) { + BT_ERR("write() failed: %d", errno); + break; + } + size_left -= written; + } + + ok = (size_left == 0); + } while (false); + + free(vcard_buff); + + return ok; +} + +static bool __bt_util_write_vcard_to_file_from_id(int fd, int person_id) +{ + contacts_record_h record = NULL; + bool ok = false; + + do { + int ret = contacts_db_get_record(_contacts_person._uri, person_id, &record); + if (ret != CONTACTS_ERROR_NONE) { + BT_ERR("contacts_db_get_record() failed: %d", ret); + record = NULL; + break; + } + + if (!__bt_util_write_vcard_to_file(fd, record, false)) { + BT_ERR("_write_vcard_to_file() failed"); + break; + } + + ok = true; + } while (false); + + if (record) { + contacts_record_destroy(record, true); + } + + return ok; +} + +char *_bt_util_vcard_create_from_id(int id, bool my_profile, const char *working_dir) +{ + FN_START; + + contacts_record_h record = NULL; + char *vcard_path = NULL; + int fd = -1; + bool ok = false; + int ret; + + BT_DBG("id = %i my_profile = %d", id, my_profile); + + ret = contacts_connect(); + if (ret != CONTACTS_ERROR_NONE) + BT_ERR("contacts_connect failed : ct_err = [%d]", ret); + + do { + char *display_name = NULL; + + int ret = contacts_db_get_record((my_profile ? + _contacts_my_profile._uri : + _contacts_person._uri), id, &record); + if (ret != CONTACTS_ERROR_NONE) { + BT_ERR("contacts_db_get_record() failed: %d", ret); + record = NULL; + break; + } + + if (my_profile) { + contacts_record_get_str_p(record, _contacts_my_profile.display_name, &display_name); + } else { + contacts_record_get_str_p(record, _contacts_person.display_name, &display_name); + } + + vcard_path = __bt_util_make_vcard_file_path(working_dir, "Contact"); + if (!vcard_path) { + BT_ERR("_make_vcard_file_path() failed"); + break; + } + + fd = open(vcard_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) { + BT_ERR("open(%s) Failed(%d)", vcard_path, errno); + break; + } + + if (!__bt_util_write_vcard_to_file(fd, record, my_profile)) { + BT_ERR("_write_vcard_to_file() failed"); + break; + } + + ok = true; + } while (false); + + ret = contacts_disconnect(); + if (ret != CONTACTS_ERROR_NONE) + BT_ERR("contacts_disconnect failed : ct_err = [%d]", ret); + + if (record) { + contacts_record_destroy(record, true); + } + + if (fd != -1) { + close(fd); + if (!ok) { + __bt_util_file_remove(vcard_path); + } + } + + if (!ok) { + free(vcard_path); + vcard_path = NULL; + } + + FN_END; + + return vcard_path; +} + +char *_bt_util_vcard_create_from_id_list(const int *id_list, int count, const char *working_dir, volatile bool *cancel) +{ + FN_START; + + char *vcard_path = NULL; + int fd = -1; + bool ok = false; + int ret; + + if (!id_list || count <= 0) { + return NULL; + } + + ret = contacts_connect(); + if (ret != CONTACTS_ERROR_NONE) + BT_ERR("contacts_connect failed : ct_err = [%d]", ret); + + do { + int i = 0; + + vcard_path = __bt_util_make_vcard_file_path(working_dir, "Contacts"); + if (!vcard_path) { + BT_ERR("_make_vcard_file_path() failed"); + break; + } + + fd = open(vcard_path, O_WRONLY | O_CREAT | O_TRUNC, 0644); + if (fd == -1) { + BT_ERR("open(%s) Failed(%d)", vcard_path, errno); + break; + } + + for (i = 0; !(*cancel) && (i < count); ++i) { + if (!__bt_util_write_vcard_to_file_from_id(fd, id_list[i])) { + BT_ERR("_composer_write_vcard_to_file() failed"); + break; + } + } + + ok = (i == count); + } while (false); + + ret = contacts_disconnect(); + if (ret != CONTACTS_ERROR_NONE) + BT_ERR("contacts_disconnect failed : ct_err = [%d]", ret); + + if (fd != -1) { + close(fd); + if (!ok) { + __bt_util_file_remove(vcard_path); + } + } + + if (!ok) { + free(vcard_path); + vcard_path = NULL; + } + + FN_END; + + return vcard_path; +} diff --git a/src/ui/bt-main-view.c b/src/ui/bt-main-view.c index 1531afd..8442c51 100644 --- a/src/ui/bt-main-view.c +++ b/src/ui/bt-main-view.c @@ -50,6 +50,8 @@ #define MULTI_SHARE_SERVICE_DATA_PATH "http://tizen.org/appcontrol/data/path" #define APP_CONTROL_OPERATION_SHARE_CONTACT "http://tizen.org/appcontrol/operation/share_contact" +#define APP_CONTROL_MIME_CONTACT "application/vnd.tizen.contact" +#define APP_CONTROL_MY_PROFILE_DATA_TYPE "my_profile" #define SERVICE_SHARE_CONTACT_MODE "http://tizen.org/appcontrol/data/social/namecard_share_mode" #define SERVICE_SHARE_CONTACT_ITEM "http://tizen.org/appcontrol/data/social/item_type" #define SHARE_CONTACT_DATA_PATH "/opt/usr/media/Downloads/.bluetooth" @@ -4247,65 +4249,101 @@ void __bt_main_parse_service(bt_ug_data *ugd, app_control_h service) BT_INFO("operation: %s", operation); if (g_strcmp0(operation, APP_CONTROL_OPERATION_SHARE) == 0) { + char *mime = NULL; + launch_type = strdup("send"); - if (app_control_get_uri(service, (char **)&uri) < 0) - BT_ERR("Get uri error"); + app_control_get_mime(service, &mime); - if (uri) { - uri_scheme = g_uri_parse_scheme(uri); - DBG_SECURE("uri_scheme: %s", uri_scheme); - - if (uri_scheme == NULL) { - /* File transfer */ - file_path = g_filename_from_uri(uri, NULL, NULL); - if (app_control_add_extra_data(service, "type", "file") < 0) - BT_ERR("Fail to add extra data"); - } else if (g_strcmp0(uri_scheme, "file") == 0) { - /* File transfer */ - file_path = g_filename_from_uri(uri, NULL, NULL); - if (file_path == NULL) { - file_path = strdup(uri + 7); /* file:// */ + if (mime && strcmp(mime, APP_CONTROL_MIME_CONTACT) == 0) { + char *id_str = NULL; + app_control_get_extra_data(service, APP_CONTROL_DATA_ID, &id_str); + + if (id_str) { + bool my_profile = false; + char *data_type = NULL; + int id = atoi(id_str); + + app_control_get_extra_data(service, APP_CONTROL_DATA_TYPE, &data_type); + my_profile = data_type && strcmp(data_type, APP_CONTROL_MY_PROFILE_DATA_TYPE) == 0; + file_path = _bt_util_vcard_create_from_id(id, my_profile, + BT_VCF_FOLDER_PATH); + + if (file_path) { + DBG_SECURE("file path: %s", file_path); + + if (app_control_add_extra_data(service, "type", "file") < 0) + BT_ERR("Fail to add extra data"); + + if (app_control_add_extra_data_array + (service, "files", &file_path, 1) < 0) + BT_ERR("Fail to add extra data"); } - if (app_control_add_extra_data(service, "type", "file") < 0) - BT_ERR("Fail to add extra data"); - } else { - if (app_control_add_extra_data(service, "type", "text") < 0) - BT_ERR("Fail to add extra data"); - } - if (file_path == NULL) { - BT_ERR("Not include URI info"); - file_path = strdup(uri); + free(data_type); + free(id_str); } - - g_free(uri_scheme); } else { - char *value = NULL; + if (app_control_get_uri(service, (char **)&uri) < 0) + BT_ERR("Get uri error"); - BT_INFO("url is not set"); - if (app_control_get_extra_data(service, - MULTI_SHARE_SERVICE_DATA_PATH, &value) < 0) - BT_ERR("Fail to get extra data"); + if (uri) { + uri_scheme = g_uri_parse_scheme(uri); + DBG_SECURE("uri_scheme: %s", uri_scheme); + + if (uri_scheme == NULL) { + /* File transfer */ + file_path = g_filename_from_uri(uri, NULL, NULL); + if (app_control_add_extra_data(service, "type", "file") < 0) + BT_ERR("Fail to add extra data"); + } else if (g_strcmp0(uri_scheme, "file") == 0) { + /* File transfer */ + file_path = g_filename_from_uri(uri, NULL, NULL); + if (file_path == NULL) { + file_path = strdup(uri + 7); /* file:// */ + } + if (app_control_add_extra_data(service, "type", "file") < 0) + BT_ERR("Fail to add extra data"); + } else { + if (app_control_add_extra_data(service, "type", "text") < 0) + BT_ERR("Fail to add extra data"); + } + + if (file_path == NULL) { + BT_ERR("Not include URI info"); + file_path = strdup(uri); + } - if (value) { - file_path = g_strdup(value); - free(value); + g_free(uri_scheme); + } else { + char *value = NULL; - DBG_SECURE("file_path: %s", file_path); + BT_INFO("url is not set"); + if (app_control_get_extra_data(service, + MULTI_SHARE_SERVICE_DATA_PATH, &value) < 0) + BT_ERR("Fail to get extra data"); - if (app_control_add_extra_data(service, "type", "file") < 0) - BT_ERR("Fail to add extra data"); + if (value) { + file_path = g_strdup(value); + free(value); - } else { - BT_ERR("Not include path info"); - goto done; + DBG_SECURE("file_path: %s", file_path); + + if (app_control_add_extra_data(service, "type", "file") < 0) + BT_ERR("Fail to add extra data"); + + } else { + BT_ERR("Not include path info"); + goto done; + } } + + if (app_control_add_extra_data_array + (service, "files", &file_path, 1) < 0) + BT_ERR("Fail to add extra data"); } - if (app_control_add_extra_data_array - (service, "files", &file_path, 1) < 0) - BT_ERR("Fail to add extra data"); + g_free(mime); } else if (g_strcmp0(operation, APP_CONTROL_OPERATION_SHARE_TEXT) == 0) { BT_DBG("APP_CONTROL_OPERATION_SHARE_TEXT"); @@ -4345,17 +4383,69 @@ void __bt_main_parse_service(bt_ug_data *ugd, app_control_h service) BT_ERR("Fail to add extra data"); } else if (g_strcmp0(operation, APP_CONTROL_OPERATION_MULTI_SHARE) == 0) { - launch_type = strdup("send"); - char **array_value = NULL; int array_length; int ret, i; + char *mime = NULL; + + launch_type = strdup("send"); + + int *id_list = NULL; + char **person_id = NULL; + int person_id_size = 0; + bool cancel = false; + + app_control_get_mime(service, &mime); + + if (mime && !strcmp(mime, APP_CONTROL_MIME_CONTACT)) { + if (app_control_get_extra_data_array(service, APP_CONTROL_DATA_ID, + &person_id, &person_id_size) == APP_CONTROL_ERROR_NONE && person_id) { + int i = 0; + id_list = calloc(person_id_size, sizeof(int)); + if (id_list) { + for (i = 0; i < person_id_size; i++) { + id_list[i] = atoi(person_id[i]); + } + file_path = _bt_util_vcard_create_from_id_list(id_list, + person_id_size, BT_VCF_FOLDER_PATH, &cancel); + if (file_path) { + DBG_SECURE("file path: %s", file_path); + + if (app_control_add_extra_data(service, "type", "file") < 0) + BT_ERR("Fail to add extra data"); + + if (app_control_add_extra_data_array + (service, "files", &file_path, 1) < 0) + BT_ERR("Fail to add extra data"); + } + free(id_list); + } + } + g_free(person_id); + } else { + ret = app_control_get_extra_data_array(service, + MULTI_SHARE_SERVICE_DATA_PATH, + &array_value, &array_length); + if (ret != APP_CONTROL_ERROR_NONE) { + BT_ERR("Get data error"); + if (array_value) { + for (i = 0; i < array_length; i++) { + if (array_value[i]) { + free(array_value[i]); + } + } + free(array_value); + } + goto done; + } + + if (app_control_add_extra_data_array + (service, "files", (const char **)array_value, + array_length) < 0) + BT_ERR("Fail to add extra data"); - ret = app_control_get_extra_data_array(service, - MULTI_SHARE_SERVICE_DATA_PATH, - &array_value, &array_length); - if (ret != APP_CONTROL_ERROR_NONE) { - BT_ERR("Get data error"); + if (app_control_add_extra_data(service, "type", "file") < 0) + BT_ERR("Fail to add extra data"); if (array_value) { for (i = 0; i < array_length; i++) { if (array_value[i]) { @@ -4364,24 +4454,9 @@ void __bt_main_parse_service(bt_ug_data *ugd, app_control_h service) } free(array_value); } - goto done; } - if (app_control_add_extra_data_array - (service, "files", (const char **)array_value, - array_length) < 0) - BT_ERR("Fail to add extra data"); - - if (app_control_add_extra_data(service, "type", "file") < 0) - BT_ERR("Fail to add extra data"); - if (array_value) { - for (i = 0; i < array_length; i++) { - if (array_value[i]) { - free(array_value[i]); - } - } - free(array_value); - } + g_free(mime); } else if (g_strcmp0(operation, BT_APPCONTROL_PICK_OPERATION) == 0) { BT_DBG("Pick Operation"); launch_type = strdup("pick"); -- 2.7.4