From 10ecd78ea7f7f384951215ffd445ba988e30e5a6 Mon Sep 17 00:00:00 2001 From: Inhong Han Date: Mon, 1 Jul 2019 19:43:06 +0900 Subject: [PATCH] Initial commit Change-Id: Ieb7147f649b8cdbc1374b2f5fd5e96f6f9b694c6 --- AUTHORS | 1 + CMakeLists.txt | 49 ++ LICENSE | 204 +++++ capi-ui-sticker-devel.manifest | 5 + capi-ui-sticker.info | 2 + capi-ui-sticker.manifest | 5 + client/sticker_data.c | 420 +++++++++ client/sticker_data_main.h | 52 ++ client/sticker_dbus.c | 1026 ++++++++++++++++++++++ client/sticker_dbus.h | 66 ++ client/sticker_defs.h | 62 ++ consumer/CMakeLists.txt | 23 + consumer/sticker_consumer.c | 430 ++++++++++ consumer/sticker_consumer_main.h | 40 + doc/sticker_consumer_doc.h | 34 + doc/sticker_data_doc.h | 43 + doc/sticker_doc.h | 31 + doc/sticker_provider_doc.h | 34 + include/CMakeLists.txt | 11 + include/capi-ui-sticker-consumer.pc.in | 11 + include/capi-ui-sticker-provider.pc.in | 11 + include/sticker_consumer.h | 241 ++++++ include/sticker_data.h | 298 +++++++ include/sticker_error.h | 56 ++ include/sticker_provider.h | 232 +++++ packaging/capi-ui-sticker.conf | 14 + packaging/capi-ui-sticker.service | 15 + packaging/capi-ui-sticker.spec | 102 +++ packaging/org.tizen.sticker.server.service | 4 + provider/CMakeLists.txt | 23 + provider/sticker_provider.c | 333 +++++++ provider/sticker_provider_main.h | 42 + server/CMakeLists.txt | 19 + server/stickerd_data_manager.c | 1287 ++++++++++++++++++++++++++++ server/stickerd_data_manager.h | 51 ++ server/stickerd_db_manager.c | 702 +++++++++++++++ server/stickerd_db_manager.h | 63 ++ server/stickerd_dbus.c | 221 +++++ server/stickerd_dbus.h | 45 + server/stickerd_error.h | 50 ++ server/stickerd_main.c | 132 +++ sticker-parser/CMakeLists.txt | 30 + sticker-parser/sticker-parser.c | 792 +++++++++++++++++ 43 files changed, 7312 insertions(+) create mode 100644 AUTHORS create mode 100755 CMakeLists.txt create mode 100644 LICENSE create mode 100644 capi-ui-sticker-devel.manifest create mode 100644 capi-ui-sticker.info create mode 100644 capi-ui-sticker.manifest create mode 100644 client/sticker_data.c create mode 100644 client/sticker_data_main.h create mode 100644 client/sticker_dbus.c create mode 100644 client/sticker_dbus.h create mode 100644 client/sticker_defs.h create mode 100644 consumer/CMakeLists.txt create mode 100644 consumer/sticker_consumer.c create mode 100644 consumer/sticker_consumer_main.h create mode 100644 doc/sticker_consumer_doc.h create mode 100644 doc/sticker_data_doc.h create mode 100644 doc/sticker_doc.h create mode 100644 doc/sticker_provider_doc.h create mode 100644 include/CMakeLists.txt create mode 100644 include/capi-ui-sticker-consumer.pc.in create mode 100644 include/capi-ui-sticker-provider.pc.in create mode 100644 include/sticker_consumer.h create mode 100644 include/sticker_data.h create mode 100644 include/sticker_error.h create mode 100644 include/sticker_provider.h create mode 100644 packaging/capi-ui-sticker.conf create mode 100644 packaging/capi-ui-sticker.service create mode 100644 packaging/capi-ui-sticker.spec create mode 100644 packaging/org.tizen.sticker.server.service create mode 100644 provider/CMakeLists.txt create mode 100644 provider/sticker_provider.c create mode 100644 provider/sticker_provider_main.h create mode 100644 server/CMakeLists.txt create mode 100644 server/stickerd_data_manager.c create mode 100644 server/stickerd_data_manager.h create mode 100644 server/stickerd_db_manager.c create mode 100644 server/stickerd_db_manager.h create mode 100644 server/stickerd_dbus.c create mode 100644 server/stickerd_dbus.h create mode 100644 server/stickerd_error.h create mode 100644 server/stickerd_main.c create mode 100644 sticker-parser/CMakeLists.txt create mode 100644 sticker-parser/sticker-parser.c diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..b4905c3 --- /dev/null +++ b/AUTHORS @@ -0,0 +1 @@ +Inhong Han diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 0000000..07365cf --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,49 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(capi-ui-sticker) + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(EXEC_PREFIX "${PREFIX}") +SET(VERSION 0.2.56) + +ADD_DEFINITIONS("-Werror") + +## Include common directory ## +INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/include") +INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/client") +INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/provider") +INCLUDE_DIRECTORIES("${CMAKE_SOURCE_DIR}/consumer") + +## Dependent packages ## +INCLUDE(FindPkgConfig) +pkg_check_modules(pkgs REQUIRED + dlog + glib-2.0 + json-glib-1.0 + libtzplatform-config + cynara-client + cynara-session + capi-appfw-app-common + capi-appfw-package-manager + sqlite3 + gio-2.0 + gio-unix-2.0 + dbus-1 +) + +## API ## +ADD_SUBDIRECTORY(include) + +## Sticker server ## +ADD_SUBDIRECTORY(server) + +## Sticker provider library ## +ADD_SUBDIRECTORY(provider) + +## Sticker consumer library ## +ADD_SUBDIRECTORY(consumer) + +## Sticker parser ## +ADD_SUBDIRECTORY(sticker-parser) + +## config ## +INSTALL(FILES ${CMAKE_SOURCE_DIR}/capi-ui-sticker.info DESTINATION ${TZ_SYS_RO_SHARE}/parser-plugins) \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..c1f1938 --- /dev/null +++ b/LICENSE @@ -0,0 +1,204 @@ +Copyright (c) 2019 Samsung Electronics Co., Ltd. All rights reserved. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + diff --git a/capi-ui-sticker-devel.manifest b/capi-ui-sticker-devel.manifest new file mode 100644 index 0000000..dfdc35c --- /dev/null +++ b/capi-ui-sticker-devel.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/capi-ui-sticker.info b/capi-ui-sticker.info new file mode 100644 index 0000000..1c51865 --- /dev/null +++ b/capi-ui-sticker.info @@ -0,0 +1,2 @@ +type="category";name="http://tizen.org/category/sticker";path="/etc/package-manager/parserlib/category/libcapi-ui-sticker-parser.so" +type="metadata";name="http://tizen.org/metadata/sticker";path="/etc/package-manager/parserlib/metadata/libcapi-ui-sticker-parser.so" diff --git a/capi-ui-sticker.manifest b/capi-ui-sticker.manifest new file mode 100644 index 0000000..dfdc35c --- /dev/null +++ b/capi-ui-sticker.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/client/sticker_data.c b/client/sticker_data.c new file mode 100644 index 0000000..2603285 --- /dev/null +++ b/client/sticker_data.c @@ -0,0 +1,420 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include "sticker_data.h" +#include "sticker_dbus.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "STICKER_DATA" + +static char* _make_absolute_path(const char *relative_path) +{ + int ret = STICKER_ERROR_NONE; + char *app_id = NULL; + package_info_h package_info = NULL; + char *app_path = NULL; + char *file_path = NULL; + + ret = app_get_id(&app_id); + if (ret != APP_ERROR_NONE) { + LOGE("Failed to get app_id : %d", ret); + ret = STICKER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + ret = package_info_create(app_id, &package_info); + if (ret != PACKAGE_MANAGER_ERROR_NONE || package_info == NULL) { + LOGE("faild to create package_info. ret: %d", ret); + ret = STICKER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + ret = package_info_get_root_path(package_info, &app_path); + if (ret != PACKAGE_MANAGER_ERROR_NONE || app_path == NULL) { + LOGE("faild to create package_info. ret: %d", ret); + ret = STICKER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + int path_len = strlen(app_path) + strlen(relative_path) + 2; + file_path = (char *)calloc(path_len, sizeof(char)); + if (!file_path) { + LOGE("failed to alloc memory"); + ret = STICKER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + if(relative_path[0] == '/') + snprintf(file_path, path_len, "%s%s",app_path, relative_path); + else + snprintf(file_path, path_len, "%s%s%s",app_path, "/", relative_path); + + if (access(file_path, F_OK) != 0) { + LOGE("%s does not exist", file_path); + ret = STICKER_ERROR_OPERATION_FAILED; + free(file_path); + } + +cleanup: + if (app_id) + free(app_id); + + if (package_info) + package_info_destroy(package_info); + + if (app_path) + free(app_path); + + if (ret == STICKER_ERROR_NONE) + return file_path; + else + return NULL; +} + +EXPORT_API int sticker_data_create(sticker_data_h *data_handle) +{ + if (!data_handle) + return STICKER_ERROR_INVALID_PARAMETER; + + sticker_data_h data_struct = (sticker_data_h)calloc(1, sizeof(struct sticker_data_s)); + + if (!data_struct) + return STICKER_ERROR_OUT_OF_MEMORY; + + char *app_id = NULL; + int ret = app_get_id(&app_id); + if (ret != APP_ERROR_NONE) { + LOGE("Failed to get app_id : %d", ret); + free(data_struct); + ret = STICKER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + data_struct->app_id = strdup(app_id); + *data_handle = data_struct; + +cleanup: + if (app_id) + free(app_id); + + return ret; +} + +EXPORT_API int sticker_data_destroy(sticker_data_h data_handle) +{ + if (!data_handle) + return STICKER_ERROR_INVALID_PARAMETER; + + if (data_handle->app_id) { + free(data_handle->app_id); + data_handle->app_id = NULL; + } + + if (data_handle->uri) { + free(data_handle->uri); + data_handle->uri = NULL; + } + + if (data_handle->thumbnail) { + free(data_handle->thumbnail); + data_handle->thumbnail = NULL; + } + + if (data_handle->keyword) { + g_list_free_full(data_handle->keyword, free); + data_handle->keyword = NULL; + } + + if (data_handle->group) { + free(data_handle->group); + data_handle->group = NULL; + } + + if (data_handle->description) { + free(data_handle->description); + data_handle->description = NULL; + } + + if (data_handle->date) { + free(data_handle->date); + data_handle->date = NULL; + } + + free(data_handle); + data_handle = NULL; + + return STICKER_ERROR_NONE; +} + +EXPORT_API int sticker_data_clone(sticker_data_h origin_handle, sticker_data_h *target_handle) +{ + sticker_data_h handle; + + if (!origin_handle || !target_handle) + return STICKER_ERROR_INVALID_PARAMETER; + + sticker_data_create(&handle); + if (!handle) + return STICKER_ERROR_OUT_OF_MEMORY; + + handle->sticker_info_id = origin_handle->sticker_info_id; + + if (origin_handle->app_id) + handle->app_id = strdup(origin_handle->app_id); + + handle->type = origin_handle->type; + + if (origin_handle->uri) + handle->uri = strdup(origin_handle->uri); + + if (origin_handle->thumbnail) + handle->thumbnail = strdup(origin_handle->thumbnail); + + if (origin_handle->keyword) + handle->keyword = g_list_copy_deep(origin_handle->keyword, (GCopyFunc) g_strdup, NULL); + + if (origin_handle->group) + handle->group = strdup(origin_handle->group); + + if (origin_handle->description) + handle->description = strdup(origin_handle->description); + + if (origin_handle->date) + handle->date = strdup(origin_handle->date); + + *target_handle = handle; + + return STICKER_ERROR_NONE; +} + +EXPORT_API int sticker_data_get_app_id(sticker_data_h data_handle, char **app_id) +{ + if (!data_handle || !app_id) + return STICKER_ERROR_INVALID_PARAMETER; + + if (!data_handle->app_id) + return STICKER_ERROR_OPERATION_FAILED; + + *app_id = strdup(data_handle->app_id); + + return STICKER_ERROR_NONE; +} + +EXPORT_API int sticker_data_set_uri(sticker_data_h data_handle, sticker_data_uri_type_e type, const char *uri) +{ + char *file_path = NULL; + + if (!data_handle || !type || !uri) + return STICKER_ERROR_INVALID_PARAMETER; + + if (type == STICKER_DATA_URI_LOCAL_PATH) { + if (access(uri, F_OK) != 0) { + file_path = _make_absolute_path(uri); + if (file_path == NULL) { + return STICKER_ERROR_INVALID_PARAMETER; + } + } else + file_path = strdup(uri); + } + + if (data_handle->uri) + free(data_handle->uri); + + data_handle->type = type; + if (type == STICKER_DATA_URI_LOCAL_PATH) + data_handle->uri = file_path; + else + data_handle->uri = strdup(uri); + + return STICKER_ERROR_NONE; +} + +EXPORT_API int sticker_data_get_uri(sticker_data_h data_handle, sticker_data_uri_type_e *type, char **uri) +{ + if (!data_handle || !type || !uri) + return STICKER_ERROR_INVALID_PARAMETER; + + if (!data_handle->type || !data_handle->uri) + return STICKER_ERROR_OPERATION_FAILED; + + *type = data_handle->type; + *uri = strdup(data_handle->uri); + + return STICKER_ERROR_NONE; +} + +EXPORT_API int sticker_data_foreach_keyword(sticker_data_h data_handle, sticker_data_keyword_foreach_cb callback, void *user_data) +{ + if (!data_handle || !callback) + return STICKER_ERROR_INVALID_PARAMETER; + + if (!data_handle->keyword) + return STICKER_ERROR_OPERATION_FAILED; + + GList *list = NULL; + for(list = g_list_first(data_handle->keyword); list != NULL; list=list->next) { + callback(list->data, user_data); + } + + return STICKER_ERROR_NONE; +} + +EXPORT_API int sticker_data_add_keyword(sticker_data_h data_handle, const char *keyword) +{ + GList *node; + + if (!data_handle || !keyword) + return STICKER_ERROR_INVALID_PARAMETER; + + node = g_list_find_custom(data_handle->keyword, keyword, (GCompareFunc) strcmp); + + if (node) { + LOGE("keyword already exists"); + return STICKER_ERROR_INVALID_PARAMETER; + } else { + data_handle->keyword = g_list_append(data_handle->keyword, strdup(keyword)); + } + + return STICKER_ERROR_NONE; +} + +EXPORT_API int sticker_data_remove_keyword(sticker_data_h data_handle, const char *keyword) +{ + GList *node; + + if (!data_handle || !keyword) + return STICKER_ERROR_INVALID_PARAMETER; + + node = g_list_find_custom(data_handle->keyword, keyword, (GCompareFunc) strcmp); + + if (node) { + data_handle->keyword = g_list_delete_link(data_handle->keyword, node); + } else { + LOGE("keyword does not exist"); + return STICKER_ERROR_INVALID_PARAMETER; + } + + return STICKER_ERROR_NONE; +} + +EXPORT_API int sticker_data_set_group_name(sticker_data_h data_handle, const char *group) +{ + if (!data_handle || !group) + return STICKER_ERROR_INVALID_PARAMETER; + + if (data_handle->group) + free(data_handle->group); + + data_handle->group = strdup(group); + + return STICKER_ERROR_NONE; +} + +EXPORT_API int sticker_data_get_group_name(sticker_data_h data_handle, char **group) +{ + if (!data_handle || !group) + return STICKER_ERROR_INVALID_PARAMETER; + + if (!data_handle->group) + return STICKER_ERROR_OPERATION_FAILED; + + *group = strdup(data_handle->group); + + return STICKER_ERROR_NONE; +} + +EXPORT_API int sticker_data_set_thumbnail(sticker_data_h data_handle, const char *thumbnail) +{ + char *file_path = NULL; + + if (!data_handle || !thumbnail) + return STICKER_ERROR_INVALID_PARAMETER; + + if (access(thumbnail, F_OK) != 0) { + file_path = _make_absolute_path(thumbnail); + if (file_path == NULL) + return STICKER_ERROR_INVALID_PARAMETER; + } else + file_path = strdup(thumbnail); + + if (data_handle->thumbnail) + free(data_handle->thumbnail); + + data_handle->thumbnail = file_path; + + return STICKER_ERROR_NONE; +} + +EXPORT_API int sticker_data_get_thumbnail(sticker_data_h data_handle, char **thumbnail) +{ + if (!data_handle || !thumbnail) + return STICKER_ERROR_INVALID_PARAMETER; + + if (!data_handle->thumbnail) + *thumbnail = strdup(""); + else + *thumbnail = strdup(data_handle->thumbnail); + + return STICKER_ERROR_NONE; +} + +EXPORT_API int sticker_data_set_description(sticker_data_h data_handle, const char *description) +{ + if (!data_handle || !description) + return STICKER_ERROR_INVALID_PARAMETER; + + if (data_handle->description) + free(data_handle->description); + + data_handle->description = strdup(description); + + return STICKER_ERROR_NONE; +} + +EXPORT_API int sticker_data_get_description(sticker_data_h data_handle, char **description) +{ + if (!data_handle || !description) + return STICKER_ERROR_INVALID_PARAMETER; + + if (!data_handle->description) + *description = strdup(""); + else + *description = strdup(data_handle->description); + + return STICKER_ERROR_NONE; +} + +EXPORT_API int sticker_data_get_date(sticker_data_h data_handle, char **date) +{ + if (!data_handle || !date) + return STICKER_ERROR_INVALID_PARAMETER; + + if (!data_handle->date) + return STICKER_ERROR_OPERATION_FAILED; + + *date = strdup(data_handle->date); + + return STICKER_ERROR_NONE; +} diff --git a/client/sticker_data_main.h b/client/sticker_data_main.h new file mode 100644 index 0000000..058de9c --- /dev/null +++ b/client/sticker_data_main.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_UIX_STICKER_DATA_MAIN_H__ +#define __TIZEN_UIX_STICKER_DATA_MAIN_H__ + +#include +#include "sticker_data.h" + +/** + * @file sticker_data_main.h + */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct sticker_data_s{ + int sticker_info_id; + char *app_id; + sticker_data_uri_type_e type; + char *uri; + char *thumbnail; + GList *keyword; + char *group; + char *description; + char *date; +}; + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* __TIZEN_UIX_STICKER_DATA_MAIN_H__ */ \ No newline at end of file diff --git a/client/sticker_dbus.c b/client/sticker_dbus.c new file mode 100644 index 0000000..64434b4 --- /dev/null +++ b/client/sticker_dbus.c @@ -0,0 +1,1026 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "sticker_dbus.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "STICKER_DBUS" + +static int is_server_started = 0; + +static void _server_appeared_cb(GDBusConnection *connection, const gchar *name, const gchar *name_owner, gpointer user_data) +{ + LOGD("name : %s, name_owner : %s", name, name_owner); +} + +static void _server_vanished_cb(GDBusConnection *connection, const gchar *name, gpointer user_data) +{ + LOGD("name : %s", name); +} + +static int _dbus_init(GDBusConnection **gdbus_connection, guint *server_watcher_id) +{ + GError *error = NULL; + + if (*gdbus_connection == NULL) { + GDBusConnection *conn = NULL; + conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (conn == NULL) { + if (error != NULL) { + LOGE("g_bus_get_sync error message = %s", error->message); + g_error_free(error); + } + return STICKER_CLIENT_ERROR_IO_ERROR; + } + *gdbus_connection = conn; + } + + LOGD("Connected bus name : %s", g_dbus_connection_get_unique_name(*gdbus_connection)); + if (*server_watcher_id == 0) { + *server_watcher_id = g_bus_watch_name(G_BUS_TYPE_SYSTEM, + STICKER_DBUS_NAME, + G_BUS_NAME_WATCHER_FLAGS_NONE, + _server_appeared_cb, + _server_vanished_cb, + NULL, NULL); + } + + LOGD("server_watcher_id : %d", *server_watcher_id); + if (*server_watcher_id == 0) { + LOGE("Failed to get identifier"); + return STICKER_CLIENT_ERROR_IO_ERROR; + } + + return STICKER_CLIENT_ERROR_NONE; +} + +static void _get_sticker_info_from_gvariant(GVariant *body, sticker_data_h sticker_data) +{ + STICKER_DAT_TYPE key; + GVariant *value = NULL; + GVariantIter *info_iter = NULL; + GVariantIter *keyword_iter = NULL; + char *keyword = NULL; + + g_variant_get(body, "(a{iv}a(s))", &info_iter, &keyword_iter); + + if (!info_iter || !keyword_iter) { + LOGD("failed to get iter"); + return; + } + + while (g_variant_iter_loop (info_iter, "{iv}", &key, &value)) { + switch(key) { + case STICKER_DATA_TYPE_APP_ID: + sticker_data->app_id = g_variant_dup_string(value, NULL); + break; + case STICKER_DATA_TYPE_URI_TYPE: + sticker_data->type = g_variant_get_int32(value); + break; + case STICKER_DATA_TYPE_URI: + sticker_data->uri = g_variant_dup_string(value, NULL); + break; + case STICKER_DATA_TYPE_THUMBNAIL: + sticker_data->thumbnail = g_variant_dup_string(value, NULL); + break; + case STICKER_DATA_TYPE_DESCRIPTION: + sticker_data->description = g_variant_dup_string(value, NULL); + break; + case STICKER_DATA_TYPE_GROUP: + sticker_data->group = g_variant_dup_string(value, NULL); + break; + case STICKER_DATA_TYPE_DATE: + sticker_data->date = g_variant_dup_string(value, NULL); + break; + default: + break; + } + } + + while (g_variant_iter_loop (keyword_iter, "(s)", &keyword)) { + sticker_data->keyword = g_list_append(sticker_data->keyword, strdup((const char *)keyword)); + } + + if (value) + g_variant_unref(value); + + g_variant_iter_free(info_iter); + g_variant_iter_free(keyword_iter); +} + +static void _free_sticker_data(sticker_data_h sticker_data) +{ + if (sticker_data->app_id) { + free(sticker_data->app_id); + sticker_data->app_id = NULL; + } + + if (sticker_data->uri) { + free(sticker_data->uri); + sticker_data->uri = NULL; + } + + if (sticker_data->thumbnail) { + free(sticker_data->thumbnail); + sticker_data->thumbnail = NULL; + } + + if (sticker_data->keyword) { + g_list_free_full(sticker_data->keyword, free); + sticker_data->keyword = NULL; + } + + if (sticker_data->group) { + free(sticker_data->group); + sticker_data->group = NULL; + } + + if (sticker_data->description) { + free(sticker_data->description); + sticker_data->description = NULL; + } + + if (sticker_data->date) { + free(sticker_data->date); + sticker_data->date = NULL; + } + + free(sticker_data); + sticker_data = NULL; +} + +static void _call_insert_finished_cb(sticker_provider_h provider_handle, GVariant *body) +{ + int ret; + g_variant_get(body, "(i)", &ret); + + if (ret == 0) { + provider_handle->insert_finished_cb(STICKER_ERROR_NONE, provider_handle->insert_finished_cb_user_data); + } else { + provider_handle->insert_finished_cb(STICKER_ERROR_OPERATION_FAILED, provider_handle->insert_finished_cb_user_data); + } +} + +static void _handle_sticker_consumer_cb(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + LOGD("own_name : %s, signal_name : %s", g_dbus_connection_get_unique_name(connection), signal_name); + sticker_consumer_h consumer_handle = (sticker_consumer_h)user_data; + + if (consumer_handle == NULL) { + LOGE("consumer handle is not available"); + return; + } + + if (parameters == NULL) { + LOGE("failed to get sticker info"); + return; + } + + #if 0 // Receive the sticker information by asynchronous communication. + if (g_strcmp0(signal_name, "send_group_list") == 0) { + if (consumer_handle->group_foreach_cb != NULL) + _call_sticker_list_cb(consumer_handle, parameters, signal_name); + return; + } else if (g_strcmp0(signal_name, "send_keyword_list") == 0) { + if (consumer_handle->keyword_foreach_cb != NULL) + _call_sticker_list_cb(consumer_handle, parameters, signal_name); + return; + } + + sticker_data_h sticker_data = (sticker_data_h)calloc(1, sizeof(struct sticker_data_s)); + + if (!sticker_data) { + LOGE("failed to allocate memory"); + return; + } + + _get_sticker_info_from_gvariant(parameters, sticker_data); + + if (g_strcmp0(signal_name, "send_all_sticker_info") == 0) { + if (consumer_handle->data_foreach_cb != NULL) + consumer_handle->data_foreach_cb(sticker_data, consumer_handle->data_foreach_cb_user_data); + else + LOGW("No registered callback function"); + } else if (g_strcmp0(signal_name, "send_sticker_info_by_keyword") == 0) { + if (consumer_handle->data_foreach_by_keyword_cb != NULL) + consumer_handle->data_foreach_by_keyword_cb(sticker_data, consumer_handle->data_foreach_by_keyword_cb_user_data); + else + LOGW("No registered callback function"); + } else if (g_strcmp0(signal_name, "send_sticker_info_by_goup") == 0) { + if (consumer_handle->data_foreach_by_group_cb != NULL) + consumer_handle->data_foreach_by_group_cb(sticker_data, consumer_handle->data_foreach_by_group_cb_user_data); + else + LOGW("No registered callback function"); + } else if (g_strcmp0(signal_name, "send_sticker_info_by_type") == 0) { + if (consumer_handle->data_foreach_by_type_cb != NULL) + consumer_handle->data_foreach_by_type_cb(sticker_data, consumer_handle->data_foreach_by_type_cb_user_data); + else + LOGW("No registered callback function"); + } + + _free_sticker_data(sticker_data); + #endif +} + +static void _handle_sticker_provider_cb(GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + LOGD("own_name : %s, signal_name : %s", g_dbus_connection_get_unique_name(connection), signal_name); + sticker_provider_h provider_handle = (sticker_provider_h)user_data; + + if (provider_handle == NULL) { + LOGE("provider handle is not available"); + return; + } + + if (parameters == NULL) { + LOGE("failed to get sticker info"); + return; + } + + if (g_strcmp0(signal_name, "send_insert_result") == 0) { + if (provider_handle->insert_finished_cb != NULL) + _call_insert_finished_cb(provider_handle, parameters); + } + + #if 0 // Receive the sticker information by asynchronous communication. + sticker_data_h sticker_data = (sticker_data_h)calloc(1, sizeof(struct sticker_data_s)); + + if (!sticker_data) { + LOGE("failed to allocate memory"); + return; + } + + _get_sticker_info_from_gvariant(parameters, sticker_data); + + if (g_strcmp0(signal_name, "send_sticker_info_by_appid") == 0) { + if (provider_handle->data_foreach_cb != NULL) + provider_handle->data_foreach_cb(sticker_data, provider_handle->data_foreach_cb_user_data); + else + LOGW("No registered callback function"); + } + + _free_sticker_data(sticker_data); + #endif +} + +static int _dbus_signal_init(GDBusConnection *gdbus_connection, int *monitor_id, CLIENT_LIB lib, void *data) +{ + int ret = STICKER_CLIENT_ERROR_NONE; + if (*monitor_id == 0) { + int id = 0; + if (lib == STICKER_CLIENT_LIB_CONSUMER) + id = g_dbus_connection_signal_subscribe(gdbus_connection, + STICKER_DBUS_NAME, + STICKER_CONSUMER_INTERFACE_NAME, + NULL, + STICKER_OBJECT_PATH, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + _handle_sticker_consumer_cb, + data, + NULL); + else if (lib == STICKER_CLIENT_LIB_PROVIDER) + id = g_dbus_connection_signal_subscribe(gdbus_connection, + STICKER_DBUS_NAME, + STICKER_PROVIDER_INTERFACE_NAME, + NULL, + STICKER_OBJECT_PATH, + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + _handle_sticker_provider_cb, + data, + NULL); + LOGD("id : %d", id); + if (id == 0) { + ret = STICKER_CLIENT_ERROR_IO_ERROR; + LOGE("g_dbus_connection_signal_subscribe() failed"); + } else { + *monitor_id = id; + } + } + + return ret; +} + +static GDBusMessage *_get_gbus_message(GVariant *body, const char *cmd) +{ + GDBusMessage *message = NULL; + message = g_dbus_message_new_method_call( + STICKER_DBUS_NAME, + STICKER_OBJECT_PATH, + STICKER_INTERFACE_NAME, + cmd); + + if (!message) { + LOGE("Failed to create a new gdbus message"); + if (body) + g_variant_unref(body); + return NULL; + } + + if (body != NULL) + g_dbus_message_set_body(message, body); + + return message; +} + +static int _send_gdbus_sync_message(GDBusConnection *gdbus_connection, GDBusMessage *msg, GDBusMessage **reply, const char *cmd) +{ + int ret = STICKER_CLIENT_ERROR_NONE; + GError *err = NULL; + + *reply = g_dbus_connection_send_message_with_reply_sync( + gdbus_connection, + msg, + G_DBUS_SEND_MESSAGE_FLAGS_NONE, + -1, + NULL, + NULL, + &err); + + if (!*reply) { + ret = STICKER_CLIENT_ERROR_SERVICE_NOT_READY; + if (err != NULL) { + LOGE("Error occurred when sending message(%s) : %s", cmd, err->message); + if (err->code == G_DBUS_ERROR_ACCESS_DENIED) + ret = STICKER_CLIENT_ERROR_PERMISSION_DENIED; + g_error_free(err); + } + return ret; + } + + if (g_dbus_message_to_gerror(*reply, &err)) { + LOGE("error message = %s, code = %d", err->message, err->code); + if (err->code == G_DBUS_ERROR_ACCESS_DENIED) + ret = STICKER_CLIENT_ERROR_PERMISSION_DENIED; + else + ret = err->code; + g_error_free(err); + return ret; + } + + LOGD("Send a message to server(cmd : %s)", cmd); + return STICKER_CLIENT_ERROR_NONE; +} + +static int _send_sync_message(GDBusConnection *gdbus_connection, GVariant *body, GDBusMessage **reply, char *cmd) +{ + int ret = STICKER_CLIENT_ERROR_NONE; + GDBusMessage *msg = NULL; + + msg = _get_gbus_message(body, cmd); + if (msg == NULL) + return STICKER_CLIENT_ERROR_IO_ERROR; + + ret = _send_gdbus_sync_message(gdbus_connection, msg, reply, cmd); + + if (msg) + g_object_unref(msg); + + return ret; +} + +static void _gdbus_reply_message_async_cb(GDBusConnection *connection, GAsyncResult *res, gpointer user_data) +{ + GDBusMessage *reply = NULL; + GError *err = NULL; + + reply = g_dbus_connection_send_message_with_reply_finish(connection, res, &err); + + if (reply) { + if (g_dbus_message_to_gerror(reply, &err)) { + LOGE("error message = %s, code = %d", err->message, err->code); + g_error_free(err); + return; + } + } else { + LOGE("There is no reply"); + return; + } + + if (reply) + g_object_unref(reply); + + LOGD("Reply message was received"); + return; +} + +static int _send_async_message(GDBusConnection *gdbus_connection, GVariant *body, char *cmd) +{ + int ret = STICKER_CLIENT_ERROR_NONE; + GDBusMessage *msg = NULL; + + msg = _get_gbus_message(body, cmd); + if (msg == NULL) + return STICKER_CLIENT_ERROR_IO_ERROR; + + g_dbus_connection_send_message_with_reply( + gdbus_connection, + msg, + G_DBUS_SEND_MESSAGE_FLAGS_NONE, + -1, + NULL, + NULL, + (GAsyncReadyCallback)_gdbus_reply_message_async_cb, + NULL); + + if (msg) + g_object_unref(msg); + + return ret; +} + +static int _monitor_register(GDBusConnection *gdbus_connection) +{ + int ret; + GDBusMessage *reply = NULL; + + ret = _send_sync_message(gdbus_connection, g_variant_new("()"), &reply, "sticker_service_register"); + if (reply) + g_object_unref(reply); + + if (ret != STICKER_CLIENT_ERROR_NONE) { + LOGE("_send_sync_message() failed : %d", ret); + return ret; + } + + is_server_started = 1; + return ret; +} + +static void _on_name_appeared(GDBusConnection *connection, + const gchar *name, + const gchar *name_owner, + gpointer user_data) +{ + if (is_server_started == 0) + _monitor_register(connection); +} + +static void _on_name_vanished(GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + is_server_started = 0; +} + +int sticker_dbus_init(GDBusConnection **gdbus_connection, guint *server_watcher_id, + int *monitor_id, int *server_monitor_id, CLIENT_LIB lib, void *data) +{ + int ret; + + ret = _dbus_init(gdbus_connection, server_watcher_id); + if (ret != STICKER_CLIENT_ERROR_NONE) { + LOGE("_dbus_init() failed : %d", ret); + return ret; + } + + ret = _dbus_signal_init(*gdbus_connection, monitor_id, lib, data); + if (ret != STICKER_CLIENT_ERROR_NONE) { + LOGE("_dbus_signal_init() failed : %d", ret); + return ret; + } + + ret = _monitor_register(*gdbus_connection); + if (ret != STICKER_CLIENT_ERROR_NONE) { + LOGE("_monitor_register() failed : %d", ret); + return ret; + } + + if (*server_monitor_id == 0) { + *server_monitor_id = g_bus_watch_name_on_connection( + *gdbus_connection, + STICKER_DBUS_NAME, + G_BUS_NAME_WATCHER_FLAGS_NONE, + _on_name_appeared, + _on_name_vanished, + NULL, + NULL); + if (*server_monitor_id == 0) { + g_dbus_connection_signal_unsubscribe(*gdbus_connection, *monitor_id); + *monitor_id = 0; + LOGE("Failed to get identifier"); + return STICKER_CLIENT_ERROR_IO_ERROR; + } + } + + return STICKER_CLIENT_ERROR_NONE; +} + +int sticker_dbus_shutdown(GDBusConnection *gdbus_connection, int *server_monitor_id, int *monitor_id) +{ + if (*server_monitor_id) { + g_bus_unwatch_name(*server_monitor_id); + *server_monitor_id = 0; + } + + if (*monitor_id) { + g_dbus_connection_signal_unsubscribe(gdbus_connection, *monitor_id); + *monitor_id = 0; + } + + return STICKER_CLIENT_ERROR_NONE; +} + +static void _set_keyword_builder(char *keyword, GVariantBuilder *keyword_builder) +{ + if (!keyword) { + LOGE("keyword doesn't exist"); + return; + } + + g_variant_builder_add(keyword_builder, "(s)", strdup((const char *)keyword)); +} + +int sticker_dbus_insert_sticker_info(GDBusConnection *gdbus_connection, sticker_data_h sticker_data) +{ + int ret; + int ret_id = -1; + GDBusMessage *reply = NULL; + GVariant *body = NULL; + GVariant *reply_body = NULL; + GVariantBuilder *info_builder; + GVariantBuilder *keyword_builder; + + if (!sticker_data->app_id || (sticker_data->type < 1) || !sticker_data->uri || !sticker_data->group || !sticker_data->keyword) + return STICKER_CLIENT_ERROR_INVALID_PARAMETER; + + info_builder = g_variant_builder_new(G_VARIANT_TYPE("a{iv}")); + g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_APP_ID, g_variant_new_string((const gchar *)sticker_data->app_id)); + g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_URI_TYPE, g_variant_new_int32(sticker_data->type)); + g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_URI, g_variant_new_string((const gchar *)sticker_data->uri)); + if (sticker_data->thumbnail) + g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_THUMBNAIL, g_variant_new_string((const gchar *)sticker_data->thumbnail)); + if (sticker_data->description) + g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_DESCRIPTION, g_variant_new_string((const gchar *)sticker_data->description)); + g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_GROUP, g_variant_new_string((const gchar *)sticker_data->group)); + + keyword_builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)")); + g_list_foreach(sticker_data->keyword, (GFunc) _set_keyword_builder, keyword_builder); + + body = g_variant_new("(a{iv}a(s))", info_builder, keyword_builder); + + g_variant_builder_unref(info_builder); + g_variant_builder_unref(keyword_builder); + + ret = _send_sync_message(gdbus_connection, body, &reply, "insert_sticker_info"); + if (ret != STICKER_CLIENT_ERROR_NONE) { + LOGW("Failed to save sticker info"); + return ret; + } + + reply_body = g_dbus_message_get_body(reply); + g_variant_get(reply_body, "(i)", &ret_id); + sticker_data->sticker_info_id = ret_id; + + LOGD("ret_id : %d", ret_id); + if (body) + g_variant_unref(body); + + if (reply_body) + g_variant_unref(reply_body); + + if (reply) + g_object_unref(reply); + + return ret; +} + +int sticker_dbus_insert_sticker_info_by_json(GDBusConnection *gdbus_connection, const char *app_id, const char *json_path) +{ + int ret; + GVariant *body = NULL; + + body = g_variant_new("(ss)", app_id, json_path); + ret = _send_async_message(gdbus_connection, body, "update_sticker_info_by_json"); + if (ret != STICKER_CLIENT_ERROR_NONE) + LOGE("failed to send json path"); + + if (body) + g_variant_unref(body); + + return ret; +} + +int sticker_dbus_delete_sticker_info(GDBusConnection *gdbus_connection, int record_id) +{ + int ret; + GDBusMessage *reply = NULL; + GVariant *body = NULL; + + body = g_variant_new("(i)", record_id); + ret = _send_sync_message(gdbus_connection, body, &reply, "delete_sticker_info"); + if (ret != STICKER_CLIENT_ERROR_NONE) + LOGE("failed to delete sticker info"); + + if (body) + g_variant_unref(body); + + if (reply) + g_object_unref(reply); + + return ret; +} + +int sticker_dbus_update_sticker_info(GDBusConnection *gdbus_connection, sticker_data_h sticker_data) +{ + int ret; + GDBusMessage *reply = NULL; + GVariant *body = NULL; + GVariant *reply_body = NULL; + sticker_data_h origin_data = (sticker_data_h)calloc(1, sizeof(struct sticker_data_s)); + + if (!origin_data) { + LOGE("failed to allocate memory"); + return STICKER_CLIENT_ERROR_OUT_OF_MEMORY; + } + + body = g_variant_new("(i)", sticker_data->sticker_info_id); + ret = _send_sync_message(gdbus_connection, body, &reply, "get_sticker_info"); + + if (ret == STICKER_CLIENT_ERROR_NONE) { + reply_body = g_dbus_message_get_body(reply); + _get_sticker_info_from_gvariant(reply_body, origin_data); + } else { + LOGW("failed to get sticker info"); + free(origin_data); + if (reply) + g_object_unref(reply); + if (body) + g_variant_unref(body); + return ret; + } + + if (sticker_data->type != 0 && sticker_data->type != origin_data->type) { + LOGD("origin_type : %d, new_type : %d", origin_data->type, sticker_data->type); + g_variant_unref(body); + body = g_variant_new("(ii)", sticker_data->sticker_info_id, sticker_data->type); + ret = _send_sync_message(gdbus_connection, body, &reply, "update_sticker_type"); + if (ret != STICKER_CLIENT_ERROR_NONE) + LOGE("falied to update sticker type"); + } + + if (sticker_data->uri && strcmp(sticker_data->uri, origin_data->uri) != 0) { + LOGD("origin_uri : %s, new_uri : %s", origin_data->uri, sticker_data->uri); + g_variant_unref(body); + body = g_variant_new("(isis)", sticker_data->sticker_info_id, sticker_data->app_id, sticker_data->type, sticker_data->uri); + ret = _send_sync_message(gdbus_connection, body, &reply, "update_sticker_uri"); + if (ret != STICKER_CLIENT_ERROR_NONE) + LOGE("falied to update sticker uri"); + } + + if (sticker_data->thumbnail && strcmp(sticker_data->thumbnail, origin_data->thumbnail) != 0) { + LOGD("origin_thumbnail : %s, new_thumbnail : %s", origin_data->thumbnail, sticker_data->thumbnail); + g_variant_unref(body); + body = g_variant_new("(is)", sticker_data->sticker_info_id, sticker_data->thumbnail); + ret = _send_sync_message(gdbus_connection, body, &reply, "update_sticker_thumbnail"); + if (ret != STICKER_CLIENT_ERROR_NONE) + LOGE("falied to update sticker thumbnail"); + } + + if (sticker_data->description && strcmp(sticker_data->description, origin_data->description) != 0) { + LOGD("origin_description : %s, new_description : %s", origin_data->description, sticker_data->description); + g_variant_unref(body); + body = g_variant_new("(is)", sticker_data->sticker_info_id, sticker_data->description); + ret = _send_sync_message(gdbus_connection, body, &reply, "update_sticker_description"); + if (ret != STICKER_CLIENT_ERROR_NONE) + LOGE("falied to update sticker description"); + } + + if (sticker_data->group && strcmp(sticker_data->group, origin_data->group) != 0) { + LOGD("origin_group : %s, new_group : %s", origin_data->group, sticker_data->group); + g_variant_unref(body); + body = g_variant_new("(is)", sticker_data->sticker_info_id, sticker_data->group); + ret = _send_sync_message(gdbus_connection, body, &reply, "update_sticker_group"); + if (ret != STICKER_CLIENT_ERROR_NONE) + LOGE("falied to update sticker group"); + } + + if (sticker_data->keyword) { + GVariantBuilder *keyword_builder; + g_variant_unref(body); + keyword_builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)")); + g_list_foreach(sticker_data->keyword, (GFunc) _set_keyword_builder, keyword_builder); + body = g_variant_new("(ia(s))", sticker_data->sticker_info_id, keyword_builder); + ret = _send_sync_message(gdbus_connection, body, &reply, "update_sticker_keyword"); + if (ret != STICKER_CLIENT_ERROR_NONE) + LOGE("falied to update sticker keyword"); + } + + _free_sticker_data(origin_data); + + if (body) + g_variant_unref(body); + + if (reply_body) + g_variant_unref(reply_body); + + if (reply) + g_object_unref(reply); + + return ret; +} + +int sticker_dbus_get_sticker_info_by_record_id(GDBusConnection *gdbus_connection, sticker_data_h sticker_data, int record_id) +{ + int ret; + GDBusMessage *reply = NULL; + GVariant *body = NULL; + GVariant *reply_body = NULL; + + body = g_variant_new("(i)", record_id); + ret = _send_sync_message(gdbus_connection, body, &reply, "get_sticker_info"); + + if (ret == STICKER_CLIENT_ERROR_NONE) { + reply_body = g_dbus_message_get_body(reply); + sticker_data->sticker_info_id = record_id; + _get_sticker_info_from_gvariant(reply_body, sticker_data); + + if (reply_body) + g_variant_unref(reply_body); + } + + if (body) + g_variant_unref(body); + + if (reply) + g_object_unref(reply); + + return ret; +} + +int sticker_dbus_get_group_list(GDBusConnection *gdbus_connection, GList **group_list) +{ + int ret; + GDBusMessage *reply = NULL; + GVariantIter *iter = NULL; + GVariant *body = NULL; + GVariant *reply_body = NULL; + char *group = NULL; + + if (group_list == NULL) { + LOGE("group_list is invalid"); + return STICKER_CLIENT_ERROR_INVALID_PARAMETER; + } + + body = g_variant_new("()"); + ret = _send_sync_message(gdbus_connection, body, &reply, "get_group_list"); + + if (ret == STICKER_CLIENT_ERROR_NONE) { + reply_body = g_dbus_message_get_body(reply); + g_variant_get(reply_body, "(a(s))", &iter); + + if (!iter) { + LOGD("falied to get iter"); + return STICKER_CLIENT_ERROR_OPERATION_FAILED; + } + + while (g_variant_iter_loop (iter, "(s)", &group)) { + *group_list = g_list_append(*group_list, strdup((const char *)group)); + } + + g_variant_iter_free(iter); + } + + if (body) + g_variant_unref(body); + + if (reply_body) + g_variant_unref(reply_body); + + if (reply) + g_object_unref(reply); + + return ret; +} + +int sticker_dbus_get_keyword_list(GDBusConnection *gdbus_connection, GList **keyword_list) +{ + int ret; + GDBusMessage *reply = NULL; + GVariantIter *iter = NULL; + GVariant *body = NULL; + GVariant *reply_body = NULL; + char *keyword = NULL; + + if (keyword_list == NULL) { + LOGE("keyword_list is invalid"); + return STICKER_CLIENT_ERROR_INVALID_PARAMETER; + } + + body = g_variant_new("()"); + ret = _send_sync_message(gdbus_connection, body, &reply, "get_keyword_list"); + + if (ret == STICKER_CLIENT_ERROR_NONE) { + reply_body = g_dbus_message_get_body(reply); + g_variant_get(reply_body, "(a(s))", &iter); + + if (!iter) { + LOGD("falied to get iter"); + return STICKER_CLIENT_ERROR_OPERATION_FAILED; + } + + while (g_variant_iter_loop (iter, "(s)", &keyword)) { + *keyword_list = g_list_append(*keyword_list, strdup((const char *)keyword)); + } + + g_variant_iter_free(iter); + } + + if (body) + g_variant_unref(body); + + if (reply_body) + g_variant_unref(reply_body); + + if (reply) + g_object_unref(reply); + + return ret; +} + +int sticker_dbus_get_sticker_count(GDBusConnection *gdbus_connection, const char *app_id, int *count) +{ + int ret; + GDBusMessage *reply = NULL; + GVariant *body = NULL; + GVariant *reply_body = NULL; + + body = g_variant_new("(s)", app_id); + ret = _send_sync_message(gdbus_connection, body, &reply, "get_sticker_count"); + + if (ret == STICKER_CLIENT_ERROR_NONE) { + reply_body = g_dbus_message_get_body(reply); + g_variant_get(reply_body, "(i)", count); + } + + if (body) + g_variant_unref(body); + + if (reply_body) + g_variant_unref(reply_body); + + if (reply) + g_object_unref(reply); + + return ret; +} + +int sticker_dbus_get_all_sticker_info(GDBusConnection *gdbus_connection, int offset, int count, GVariantIter **id_iter) +{ + int ret; + GDBusMessage *reply = NULL; + GVariant *body = NULL; + GVariant *reply_body = NULL; + + body = g_variant_new("(ii)", offset, count); + ret = _send_sync_message(gdbus_connection, body, &reply, "get_all_sticker_info"); + if (ret == STICKER_CLIENT_ERROR_NONE) { + reply_body = g_dbus_message_get_body(reply); + g_variant_get(reply_body, "(a(i))", &(*id_iter)); + } + + if (body) + g_variant_unref(body); + + if (reply_body) + g_variant_unref(reply_body); + + if (reply) + g_object_unref(reply); + + return ret; +} + +int sticker_dbus_get_sticker_info_by_appid(GDBusConnection *gdbus_connection, const char *app_id, int offset, int count, GVariantIter **id_iter) +{ + int ret; + GDBusMessage *reply = NULL; + GVariant *body = NULL; + GVariant *reply_body = NULL; + + body = g_variant_new("(sii)", app_id, offset, count); + ret = _send_sync_message(gdbus_connection, body, &reply, "get_sticker_info_by_appid"); + if (ret == STICKER_CLIENT_ERROR_NONE) { + reply_body = g_dbus_message_get_body(reply); + g_variant_get(reply_body, "(a(i))", &(*id_iter)); + } + + if (body) + g_variant_unref(body); + + if (reply_body) + g_variant_unref(reply_body); + + if (reply) + g_object_unref(reply); + + return ret; +} + +int sticker_dbus_get_sticker_info_by_type(GDBusConnection *gdbus_connection, sticker_data_uri_type_e type, int offset, int count, GVariantIter **id_iter) +{ + int ret; + GDBusMessage *reply = NULL; + GVariant *body = NULL; + GVariant *reply_body = NULL; + + body = g_variant_new("(iii)", (int)type, offset, count); + ret = _send_sync_message(gdbus_connection, body, &reply, "get_sticker_info_by_type"); + if (ret == STICKER_CLIENT_ERROR_NONE) { + reply_body = g_dbus_message_get_body(reply); + g_variant_get(reply_body, "(a(i))", &(*id_iter)); + } + + if (body) + g_variant_unref(body); + + if (reply_body) + g_variant_unref(reply_body); + + if (reply) + g_object_unref(reply); + + return ret; +} + +int sticker_dbus_get_sticker_info_by_group(GDBusConnection *gdbus_connection, const char *group, int offset, int count, GVariantIter **id_iter) +{ + int ret; + GDBusMessage *reply = NULL; + GVariant *body = NULL; + GVariant *reply_body = NULL; + + body = g_variant_new("(sii)", group, offset, count); + ret = _send_sync_message(gdbus_connection, body, &reply, "get_sticker_info_by_group"); + if (ret == STICKER_CLIENT_ERROR_NONE) { + reply_body = g_dbus_message_get_body(reply); + g_variant_get(reply_body, "(a(i))", &(*id_iter)); + } + + if (body) + g_variant_unref(body); + + if (reply_body) + g_variant_unref(reply_body); + + if (reply) + g_object_unref(reply); + + return ret; +} + +int sticker_dbus_get_sticker_info_by_keyword(GDBusConnection *gdbus_connection, const char *keyword, int offset, int count, GVariantIter **id_iter) +{ + int ret; + GDBusMessage *reply = NULL; + GVariant *body = NULL; + GVariant *reply_body = NULL; + + body = g_variant_new("(sii)", keyword, offset, count); + ret = _send_sync_message(gdbus_connection, body, &reply, "get_sticker_info_by_keyword"); + if (ret == STICKER_CLIENT_ERROR_NONE) { + reply_body = g_dbus_message_get_body(reply); + g_variant_get(reply_body, "(a(i))", &(*id_iter)); + } + + if (body) + g_variant_unref(body); + + if (reply_body) + g_variant_unref(reply_body); + + if (reply) + g_object_unref(reply); + + return ret; +} \ No newline at end of file diff --git a/client/sticker_dbus.h b/client/sticker_dbus.h new file mode 100644 index 0000000..d8fcbcd --- /dev/null +++ b/client/sticker_dbus.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_UIX_STICKER_DBUS_H__ +#define __TIZEN_UIX_STICKER_DBUS_H__ + +#include +#include +#include +#include +#include +#include "sticker_defs.h" +#include "sticker_data.h" +#include "sticker_data_main.h" +#include "sticker_provider_main.h" +#include "sticker_consumer_main.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum sticker_client_error { + STICKER_CLIENT_ERROR_NONE, + STICKER_CLIENT_ERROR_INVALID_PARAMETER, + STICKER_CLIENT_ERROR_PERMISSION_DENIED, + STICKER_CLIENT_ERROR_OUT_OF_MEMORY, + STICKER_CLIENT_ERROR_SERVICE_NOT_READY, + STICKER_CLIENT_ERROR_OPERATION_FAILED, + STICKER_CLIENT_ERROR_IO_ERROR, +}; + +int sticker_dbus_init(GDBusConnection **gdbus_connection, guint *server_watcher_id, + int *monitor_id, int *server_monitor_id, CLIENT_LIB lib, void *data); +int sticker_dbus_shutdown(GDBusConnection *gdbus_connection, int *server_monitor_id, int *monitor_id); +int sticker_dbus_insert_sticker_info(GDBusConnection *gdbus_connection, sticker_data_h sticker_data); +int sticker_dbus_insert_sticker_info_by_json(GDBusConnection *gdbus_connection, const char *app_id, const char *json_path); +int sticker_dbus_delete_sticker_info(GDBusConnection *gdbus_connection, int record_id); +int sticker_dbus_update_sticker_info(GDBusConnection *gdbus_connection, sticker_data_h sticker_data); +int sticker_dbus_get_sticker_info_by_record_id(GDBusConnection *gdbus_connection, sticker_data_h sticker_data, int record_id); +int sticker_dbus_get_group_list(GDBusConnection *gdbus_connection, GList **group_list); +int sticker_dbus_get_keyword_list(GDBusConnection *gdbus_connection, GList **keyword_list); +int sticker_dbus_get_sticker_count(GDBusConnection *gdbus_connection, const char *app_id, int *count); +int sticker_dbus_get_all_sticker_info(GDBusConnection *gdbus_connection, int offset, int count, GVariantIter **id_iter); +int sticker_dbus_get_sticker_info_by_appid(GDBusConnection *gdbus_connection, const char *app_id, int offset, int count, GVariantIter **id_iter); +int sticker_dbus_get_sticker_info_by_type(GDBusConnection *gdbus_connection, sticker_data_uri_type_e type, int offset, int count, GVariantIter **id_iter); +int sticker_dbus_get_sticker_info_by_group(GDBusConnection *gdbus_connection, const char *group, int offset, int count, GVariantIter **id_iter); +int sticker_dbus_get_sticker_info_by_keyword(GDBusConnection *gdbus_connection, const char *keyword, int offset, int count, GVariantIter **id_iter); + +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_UIX_STICKER_DBUS_H__ */ \ No newline at end of file diff --git a/client/sticker_defs.h b/client/sticker_defs.h new file mode 100644 index 0000000..3575ecf --- /dev/null +++ b/client/sticker_defs.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_UIX_STICKER_DEFS_H__ +#define __TIZEN_UIX_STICKER_DEFS_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define HAPI __attribute__((visibility("hidden"))) + +#define DBUS_NAME "org.freedesktop.DBus" +#define DBUS_OBJECT_PATH "/org/freedesktop/DBus" +#define DBUS_INTERFACE_NAME "org.freedesktop.DBus" + +#define STICKER_DBUS_NAME "org.tizen.sticker.server" +#define STICKER_OBJECT_PATH "/org/tizen/sticker/server" +#define STICKER_INTERFACE_NAME "org.tizen.sticker_service" +#define STICKER_PROVIDER_INTERFACE_NAME "org.tizen.sticker_provider" +#define STICKER_CONSUMER_INTERFACE_NAME "org.tizen.sticker_consumer" + +#define STICKER_PRIVILEGE_MEDIASTORAGE "http://tizen.org/privilege/mediastorage" + +typedef enum { + STICKER_CLIENT_LIB_NONE, + STICKER_CLIENT_LIB_CONSUMER, + STICKER_CLIENT_LIB_PROVIDER, +} CLIENT_LIB; + +typedef enum { + STICKER_DATA_TYPE_INFO_ID = 1, + STICKER_DATA_TYPE_APP_ID, + STICKER_DATA_TYPE_URI_TYPE, + STICKER_DATA_TYPE_URI, + STICKER_DATA_TYPE_THUMBNAIL, + STICKER_DATA_TYPE_DESCRIPTION, + STICKER_DATA_TYPE_GROUP, + STICKER_DATA_TYPE_KEYWORD, + STICKER_DATA_TYPE_DATE, +} STICKER_DAT_TYPE; + +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_UIX_STICKER_DEFS_H__ */ \ No newline at end of file diff --git a/consumer/CMakeLists.txt b/consumer/CMakeLists.txt new file mode 100644 index 0000000..0e554b0 --- /dev/null +++ b/consumer/CMakeLists.txt @@ -0,0 +1,23 @@ +SET(SRCS + sticker_consumer.c + ../client/sticker_data.c + ../client/sticker_dbus.c +) + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/include) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") + +## Add definitions ## +ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"") + +## sticker consumer library ## +ADD_LIBRARY(${PROJECT_NAME}-consumer SHARED ${SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME}-consumer ${pkgs_LDFLAGS}) + +## Install library files ## +INSTALL(TARGETS ${PROJECT_NAME}-consumer DESTINATION ${LIBDIR} COMPONENT RuntimeLibraries) diff --git a/consumer/sticker_consumer.c b/consumer/sticker_consumer.c new file mode 100644 index 0000000..5024e8b --- /dev/null +++ b/consumer/sticker_consumer.c @@ -0,0 +1,430 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include "sticker_consumer.h" +#include "sticker_consumer_main.h" +#include "sticker_dbus.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "STICKER_CONSUMER" + +static cynara *p_cynara = NULL; + +static void _free_sticker_data(sticker_data_h sticker_data) +{ + if (sticker_data->app_id) { + free(sticker_data->app_id); + sticker_data->app_id = NULL; + } + + if (sticker_data->uri) { + free(sticker_data->uri); + sticker_data->uri = NULL; + } + + if (sticker_data->thumbnail) { + free(sticker_data->thumbnail); + sticker_data->thumbnail = NULL; + } + + if (sticker_data->keyword) { + g_list_free_full(sticker_data->keyword, free); + sticker_data->keyword = NULL; + } + + if (sticker_data->group) { + free(sticker_data->group); + sticker_data->group = NULL; + } + + if (sticker_data->description) { + free(sticker_data->description); + sticker_data->description = NULL; + } + + if (sticker_data->date) { + free(sticker_data->date); + sticker_data->date = NULL; + } + + free(sticker_data); + sticker_data = NULL; +} + +static int _cynara_initialize() +{ + int ret = cynara_initialize(&p_cynara, NULL); + if (ret != CYNARA_API_SUCCESS) + LOGE("Failed to cynara initialize"); + + return ret; +} + +static int _check_privilege(const char *uid, const char *privilege) +{ + int ret; + FILE *fp = NULL; + char label_path[1024] = "/proc/self/attr/current"; + char smack_label[1024] = {'\0',}; + + if (!p_cynara) { + return -1; + } + + fp = fopen(label_path, "r"); + if (fp != NULL) { + ret = fread(smack_label, 1, sizeof(smack_label), fp); + if (ret <= 0) + LOGE("Failed to fread"); + + fclose(fp); + } + + pid_t pid = getpid(); + char *session = cynara_session_from_pid(pid); + ret = cynara_check(p_cynara, smack_label, session, uid, privilege); + if (session) + free(session); + + if (ret != CYNARA_API_ACCESS_ALLOWED) { + LOGE("Access denied. The result of cynara_check() : %d.", ret); + return -1; + } + + return 0; +} + +static void _cynara_deinitialize() +{ + if (p_cynara) + cynara_finish(p_cynara); + + p_cynara = NULL; +} + +static int _sticker_check_privilege() { + char uid[16]; + int ret = STICKER_ERROR_NONE; + + if (_cynara_initialize() != CYNARA_API_SUCCESS) + return STICKER_ERROR_PERMISSION_DENIED; + + snprintf(uid, 16, "%d", getuid()); + if (_check_privilege(uid, STICKER_PRIVILEGE_MEDIASTORAGE) < 0) { + LOGE("Permission is denied"); + ret = STICKER_ERROR_PERMISSION_DENIED; + } + + _cynara_deinitialize(); + + return ret; +} + +EXPORT_API int sticker_consumer_create(sticker_consumer_h *consumer_handle) +{ + int ret; + + if (!consumer_handle) + return STICKER_ERROR_INVALID_PARAMETER; + + if (_sticker_check_privilege() != STICKER_ERROR_NONE) + return STICKER_ERROR_PERMISSION_DENIED; + + struct sticker_consumer_s *consumer_struct = (sticker_consumer_h)calloc(1, sizeof(struct sticker_consumer_s)); + + if (!consumer_struct) + return STICKER_ERROR_OUT_OF_MEMORY; + + ret = sticker_dbus_init(&consumer_struct->gdbus_connection, &consumer_struct->server_watcher_id, + &consumer_struct->monitor_id, &consumer_struct->server_monitor_id, STICKER_CLIENT_LIB_CONSUMER, (void *)consumer_struct); + if (ret != STICKER_ERROR_NONE) { + LOGE("Failed to initialize dbus : %d", ret); + free(consumer_struct); + return STICKER_ERROR_OPERATION_FAILED; + } + + *consumer_handle = consumer_struct; + + return STICKER_ERROR_NONE; +} + +EXPORT_API int sticker_consumer_destroy(sticker_consumer_h consumer_handle) +{ + LOGD("consumer_handle : %p", consumer_handle); + int ret; + + if (!consumer_handle) + return STICKER_ERROR_INVALID_PARAMETER; + + ret = sticker_dbus_shutdown(consumer_handle->gdbus_connection, &consumer_handle->server_monitor_id, &consumer_handle->monitor_id); + if (ret != STICKER_ERROR_NONE) { + LOGE("Failed to finalize dbus : %d", ret); + free(consumer_handle); + return STICKER_ERROR_OPERATION_FAILED; + } + + if (consumer_handle->gdbus_connection) + g_object_unref(consumer_handle->gdbus_connection); + + free(consumer_handle); + + return STICKER_ERROR_NONE; +} + +EXPORT_API int sticker_consumer_data_foreach_all(sticker_consumer_h consumer_handle, int offset, int count, int *result, sticker_consumer_data_foreach_cb callback, void *user_data) +{ + int ret; + int info_id; + int sticker_count = 0; + GVariantIter *id_iter = NULL; + + if (!consumer_handle || (offset < 0) || (count <= 0) || !result || !callback) + return STICKER_ERROR_INVALID_PARAMETER; + + ret = sticker_dbus_get_all_sticker_info(consumer_handle->gdbus_connection, offset, count, &id_iter); + if (ret != STICKER_ERROR_NONE) { + LOGE("Failed to get all sticker information : %d", ret); + ret = STICKER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + if (id_iter) { + while (g_variant_iter_loop (id_iter, "(i)", &info_id)) { + sticker_data_h sticker_data = (sticker_data_h)calloc(1, sizeof(struct sticker_data_s)); + if (!sticker_data) { + ret = STICKER_ERROR_OUT_OF_MEMORY; + goto cleanup; + } + + ret = sticker_dbus_get_sticker_info_by_record_id(consumer_handle->gdbus_connection, sticker_data, info_id); + if (ret == STICKER_ERROR_NONE) { + sticker_count++; + callback(sticker_data, user_data); + _free_sticker_data(sticker_data); + } else { + _free_sticker_data(sticker_data); + goto cleanup; + } + } + } + + *result = sticker_count; + +cleanup: + if (id_iter) + g_variant_iter_free(id_iter); + + return ret; +} + +EXPORT_API int sticker_consumer_data_foreach_by_keyword(sticker_consumer_h consumer_handle, int offset, int count, int *result, const char *keyword, sticker_consumer_data_foreach_cb callback, void *user_data) +{ + int ret; + int info_id; + int sticker_count = 0; + GVariantIter *id_iter = NULL; + + if (!consumer_handle || (offset < 0) || (count <= 0) || !result || !keyword || !callback) + return STICKER_ERROR_INVALID_PARAMETER; + + ret = sticker_dbus_get_sticker_info_by_keyword(consumer_handle->gdbus_connection, keyword, offset, count, &id_iter); + if (ret != STICKER_ERROR_NONE) { + LOGE("Failed to get sticker information by keyword : %d", ret); + ret = STICKER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + if (id_iter) { + while (g_variant_iter_loop (id_iter, "(i)", &info_id)) { + sticker_data_h sticker_data = (sticker_data_h)calloc(1, sizeof(struct sticker_data_s)); + if (!sticker_data) { + ret = STICKER_ERROR_OUT_OF_MEMORY; + goto cleanup; + } + + ret = sticker_dbus_get_sticker_info_by_record_id(consumer_handle->gdbus_connection, sticker_data, info_id); + if (ret == STICKER_ERROR_NONE) { + sticker_count++; + callback(sticker_data, user_data); + _free_sticker_data(sticker_data); + } else { + _free_sticker_data(sticker_data); + goto cleanup; + } + } + } + + *result = sticker_count; + +cleanup: + if (id_iter) + g_variant_iter_free(id_iter); + + return ret; +} + +EXPORT_API int sticker_consumer_data_foreach_by_group(sticker_consumer_h consumer_handle, int offset, int count, int *result, const char *group, sticker_consumer_data_foreach_cb callback, void *user_data) +{ + int ret; + int info_id; + int sticker_count = 0; + GVariantIter *id_iter = NULL; + + if (!consumer_handle || (offset < 0) || (count <= 0) || !result || !group || !callback) + return STICKER_ERROR_INVALID_PARAMETER; + + ret = sticker_dbus_get_sticker_info_by_group(consumer_handle->gdbus_connection, group, offset, count, &id_iter); + if (ret != STICKER_ERROR_NONE) { + LOGE("Failed to get sticker information by group : %d", ret); + ret = STICKER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + if (id_iter) { + while (g_variant_iter_loop (id_iter, "(i)", &info_id)) { + sticker_data_h sticker_data = (sticker_data_h)calloc(1, sizeof(struct sticker_data_s)); + if (!sticker_data) { + ret = STICKER_ERROR_OUT_OF_MEMORY; + goto cleanup; + } + + ret = sticker_dbus_get_sticker_info_by_record_id(consumer_handle->gdbus_connection, sticker_data, info_id); + if (ret == STICKER_ERROR_NONE) { + sticker_count++; + callback(sticker_data, user_data); + _free_sticker_data(sticker_data); + } else { + _free_sticker_data(sticker_data); + goto cleanup; + } + } + } + + *result = sticker_count; + +cleanup: + if (id_iter) + g_variant_iter_free(id_iter); + + return ret; +} + +EXPORT_API int sticker_consumer_data_foreach_by_type(sticker_consumer_h consumer_handle, int offset, int count, int *result, sticker_data_uri_type_e type, sticker_consumer_data_foreach_cb callback, void *user_data) +{ + int ret; + int info_id; + int sticker_count = 0; + GVariantIter *id_iter = NULL; + + if (!consumer_handle || (offset < 0) || (count <= 0) || !result || (type < 1) || !callback) + return STICKER_ERROR_INVALID_PARAMETER; + + ret = sticker_dbus_get_sticker_info_by_type(consumer_handle->gdbus_connection, type, offset, count, &id_iter); + if (ret != STICKER_ERROR_NONE) { + LOGE("Failed to get sticker information by group : %d", ret); + ret = STICKER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + if (id_iter) { + while (g_variant_iter_loop (id_iter, "(i)", &info_id)) { + sticker_data_h sticker_data = (sticker_data_h)calloc(1, sizeof(struct sticker_data_s)); + if (!sticker_data) { + ret = STICKER_ERROR_OUT_OF_MEMORY; + goto cleanup; + } + + ret = sticker_dbus_get_sticker_info_by_record_id(consumer_handle->gdbus_connection, sticker_data, info_id); + if (ret == STICKER_ERROR_NONE) { + sticker_count++; + callback(sticker_data, user_data); + _free_sticker_data(sticker_data); + } else { + _free_sticker_data(sticker_data); + goto cleanup; + } + } + } + + *result = sticker_count; + +cleanup: + if (id_iter) + g_variant_iter_free(id_iter); + + return ret; +} + +EXPORT_API int sticker_consumer_group_list_foreach_all(sticker_consumer_h consumer_handle, sticker_consumer_group_list_foreach_cb callback, void *user_data) +{ + int ret; + GList *list = NULL; + + if (!consumer_handle || !callback) + return STICKER_ERROR_INVALID_PARAMETER; + + ret = sticker_dbus_get_group_list(consumer_handle->gdbus_connection, &list); + if (ret != STICKER_ERROR_NONE) { + LOGE("Failed to get group list : %d", ret); + ret = STICKER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + for(GList *tmp = g_list_first(list); tmp != NULL; tmp=tmp->next) { + callback((const char *)tmp->data, user_data); + } + +cleanup: + if (list) + g_list_free_full(list, free); + + return ret; +} + +EXPORT_API int sticker_consumer_keyword_list_foreach_all(sticker_consumer_h consumer_handle, sticker_consumer_keyword_list_foreach_cb callback, void *user_data) +{ + int ret; + GList *list = NULL; + + if (!consumer_handle || !callback) + return STICKER_ERROR_INVALID_PARAMETER; + + ret = sticker_dbus_get_keyword_list(consumer_handle->gdbus_connection, &list); + if (ret != STICKER_ERROR_NONE) { + LOGE("Failed to get keyword list : %d", ret); + ret = STICKER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + for(GList *tmp = g_list_first(list); tmp != NULL; tmp=tmp->next) { + callback((const char *)tmp->data, user_data); + } + +cleanup: + if (list) + g_list_free_full(list, free); + + return ret; +} diff --git a/consumer/sticker_consumer_main.h b/consumer/sticker_consumer_main.h new file mode 100644 index 0000000..ba7f90d --- /dev/null +++ b/consumer/sticker_consumer_main.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_UIX_STICKER_CONSUMER_MAIN_H__ +#define __TIZEN_UIX_STICKER_CONSUMER_MAIN_H__ + +#include +#include +#include "sticker_consumer.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct sticker_consumer_s { + GDBusConnection *gdbus_connection; + guint server_watcher_id; + int monitor_id; + int server_monitor_id; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_UIX_STICKER_CONSUMER_MAIN_H__ */ \ No newline at end of file diff --git a/doc/sticker_consumer_doc.h b/doc/sticker_consumer_doc.h new file mode 100644 index 0000000..ff62eb0 --- /dev/null +++ b/doc/sticker_consumer_doc.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_UIX_STICKER_CONSUMER_DOC_H__ +#define __TIZEN_UIX_STICKER_CONSUMER_DOC_H__ + + +/** + * @ingroup CAPI_UIX_STICKER_MODULE + * @defgroup CAPI_UIX_STICKER_CONSUMER_MODULE Sticker Consumer + * @brief The @ref CAPI_UIX_STICKER_CONSUMER_MODULE API provides the functions to retrieve the sticker information. + * @section CAPI_UIX_STICKER_CONSUMER_MODULE_HEADER Required Header + * \#include + * + * @section CAPI_UIX_STICKER_CONSUMER_MODULE_OVERVIEW Overview + * The @ref CAPI_UIX_STICKER_CONSUMER_MODULE API provides the functions to retrieve the sticker information stored by the provider application. + * The application that use stickers can retrieve the sticker information using group name, keyword, and so on. + */ + + +#endif /* __TIZEN_UIX_STICKER_CONSUMER_DOC_H__ */ \ No newline at end of file diff --git a/doc/sticker_data_doc.h b/doc/sticker_data_doc.h new file mode 100644 index 0000000..0534730 --- /dev/null +++ b/doc/sticker_data_doc.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_UIX_STICKER_DATA_DOC_H__ +#define __TIZEN_UIX_STICKER_DATA_DOC_H__ + + +/** + * @ingroup CAPI_UIX_STICKER_MODULE + * @defgroup CAPI_UIX_STICKER_DATA_MODULE Sticker Data + * @brief The @ref CAPI_UIX_STICKER_DATA_MODULE API provides the functions for setting and getting sticker attributes. + * @section CAPI_UIX_STICKER_DATA_MODULE_HEADER Required Header + * \#include + * + * @section CAPI_UIX_STICKER_DATA_MODULE_OVERVIEW Overview + * The @ref CAPI_UIX_STICKER_DATA_MODULE API provides the functions to set and get sticker attributes: + *
    + *
  • Name of the provider application
  • + *
  • URI type
  • + *
  • URI
  • + *
  • Keyword
  • + *
  • Group name
  • + *
  • Thumbnail path
  • + *
  • Description
  • + *
  • Last updated date
  • + *
+ */ + + +#endif /* __TIZEN_UIX_STICKER_DATA_DOC_H__ */ \ No newline at end of file diff --git a/doc/sticker_doc.h b/doc/sticker_doc.h new file mode 100644 index 0000000..1930f25 --- /dev/null +++ b/doc/sticker_doc.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_UIX_STICKER_DOC_H__ +#define __TIZEN_UIX_STICKER_DOC_H__ + + +/** + * @ingroup CAPI_UIX_FRAMEWORK + * @defgroup CAPI_UIX_STICKER_MODULE Sticker + * @brief The @ref CAPI_UIX_STICKER_MODULE API provides the functions to manage and retrieve sticker information. + * + * @section CAPI_UIX_STICKER_MODULE_OVERVIEW Overview + * Using sticker library, a sticker application can provide sticker information to applications that want to read the sticker information as the standard specification. + */ + + +#endif /* __TIZEN_UIX_STICKER_DOC_H__ */ \ No newline at end of file diff --git a/doc/sticker_provider_doc.h b/doc/sticker_provider_doc.h new file mode 100644 index 0000000..b9be404 --- /dev/null +++ b/doc/sticker_provider_doc.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_UIX_STICKER_PROVIDER_DOC_H__ +#define __TIZEN_UIX_STICKER_PROVIDER_DOC_H__ + + +/** + * @ingroup CAPI_UIX_STICKER_MODULE + * @defgroup CAPI_UIX_STICKER_PROVIDER_MODULE Sticker Provider + * @brief The @ref CAPI_UIX_STICKER_PROVIDER_MODULE API provides the functions to create/update/delete the sticker information. + * @section CAPI_UIX_STICKER_PROVIDER_MODULE_HEADER Required Header + * \#include + * + * @section CAPI_UIX_STICKER_PROVIDER_MODULE_OVERVIEW Overview + * The sticker provider application can manager sticker information using @ref CAPI_UIX_STICKER_PROVIDER_MODULE APIs. + * However, the provider application can only update and delete their own stickers. + */ + + +#endif /* __TIZEN_UIX_STICKER_PROVIDER_DOC_H__ */ \ No newline at end of file diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt new file mode 100644 index 0000000..833e228 --- /dev/null +++ b/include/CMakeLists.txt @@ -0,0 +1,11 @@ +## configure pkgconfig files ## +CONFIGURE_FILE(capi-ui-sticker-consumer.pc.in "${PROJECT_NAME}-consumer.pc" @ONLY) +CONFIGURE_FILE(capi-ui-sticker-provider.pc.in "${PROJECT_NAME}-provider.pc" @ONLY) + +## Install header, pc files ## +INSTALL(FILES "${CMAKE_BINARY_DIR}/include/${PROJECT_NAME}-consumer.pc" DESTINATION ${LIBDIR}/pkgconfig) +INSTALL(FILES "${CMAKE_BINARY_DIR}/include/${PROJECT_NAME}-provider.pc" DESTINATION ${LIBDIR}/pkgconfig) +INSTALL(FILES "${CMAKE_BINARY_DIR}/include/sticker_error.h" DESTINATION ${INCLUDEDIR}) +INSTALL(FILES "${CMAKE_BINARY_DIR}/include/sticker_data.h" DESTINATION ${INCLUDEDIR}) +INSTALL(FILES "${CMAKE_BINARY_DIR}/include/sticker_consumer.h" DESTINATION ${INCLUDEDIR}) +INSTALL(FILES "${CMAKE_BINARY_DIR}/include/sticker_provider.h" DESTINATION ${INCLUDEDIR}) diff --git a/include/capi-ui-sticker-consumer.pc.in b/include/capi-ui-sticker-consumer.pc.in new file mode 100644 index 0000000..e4acc71 --- /dev/null +++ b/include/capi-ui-sticker-consumer.pc.in @@ -0,0 +1,11 @@ +prefix=@PREFIX@ +exec_prefix=@EXEC_PREFIX@ +libdir=@LIBDIR@ +includedir=@INCLUDEDIR@ + +Name: lib@PROJECT_NAME@-consumer +Description: Sticker Consumer APIs +Requires: glib-2.0 dbus-1 +Version: @VERSION@ +Libs: -L${libdir} -lcapi-ui-sticker-consumer +Cflags: -I${includedir} \ No newline at end of file diff --git a/include/capi-ui-sticker-provider.pc.in b/include/capi-ui-sticker-provider.pc.in new file mode 100644 index 0000000..a11a915 --- /dev/null +++ b/include/capi-ui-sticker-provider.pc.in @@ -0,0 +1,11 @@ +prefix=@PREFIX@ +exec_prefix=@EXEC_PREFIX@ +libdir=@LIBDIR@ +includedir=@INCLUDEDIR@ + +Name: lib@PROJECT_NAME@-provider +Description: Sticker Provider APIs +Requires: glib-2.0 dbus-1 +Version: @VERSION@ +Libs: -L${libdir} -lcapi-ui-sticker-provider +Cflags: -I${includedir} \ No newline at end of file diff --git a/include/sticker_consumer.h b/include/sticker_consumer.h new file mode 100644 index 0000000..2dfe76c --- /dev/null +++ b/include/sticker_consumer.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_UIX_STICKER_CONSUMER_H__ +#define __TIZEN_UIX_STICKER_CONSUMER_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file sticker_consumer.h + * @brief This file contains sticker consumer's APIs. + */ + +/** + * @addtogroup CAPI_UIX_STICKER_CONSUMER_MODULE + * @{ + */ + +/** + * @brief The sticker consumer handle. + * @since_tizen 5.5 + */ +typedef struct sticker_consumer_s *sticker_consumer_h; + +/** + * @brief Called to retrieve all sticker data in the sticker database. + * @details The sticker_consumer_data_foreach_all(), sticker_consumer_data_foreach_by_keyword(), sticker_consumer_data_foreach_by_group(), + * sticker_consumer_data_foreach_by_type() must be called to invoke this callback function, synchronously. + * @since_tizen 5.5 + * @remarks @a data_handle should not be freed and can be used only in the callback. + * If you want to use it outside of the callback, you need to use a clone which can be obtained sticker_data_clone(). + * @param[in] data_handle The sticker data handle + * @param[in] user_data The user data passed from the foreach function + * @pre sticker_consumer_data_foreach_all() will invoke this callback. + * @pre sticker_consumer_data_foreach_by_keyword() will invoke this callback. + * @pre sticker_consumer_data_foreach_by_group() will invoke this callback. + * @pre sticker_consumer_data_foreach_by_type() will invoke this callback. + * @see sticker_consumer_data_foreach_all() + * @see sticker_consumer_data_foreach_by_keyword() + * @see sticker_consumer_data_foreach_by_group() + * @see sticker_consumer_data_foreach_by_type() + */ +typedef void (*sticker_consumer_data_foreach_cb)(sticker_data_h data_handle, void *user_data); + +/** + * @brief Called to retrieve all group names in the sticker database. + * @details The sticker_consumer_group_list_foreach_all() must be called to invoke this callback function, synchronously. + * @since_tizen 5.5 + * @remarks @a group should not be freed and can be used only in the callback. + * @param[in] group The group name of the sticker + * @param[in] user_data The user data passed from the foreach function + * @pre sticker_consumer_group_list_foreach_all() will invoke this callback. + * @see sticker_consumer_group_list_foreach_all() + */ +typedef void (*sticker_consumer_group_list_foreach_cb)(const char *group, void *user_data); + +/** + * @brief Called to retrieve all keywords in the sticker database. + * @details The sticker_consumer_keyword_list_foreach_all() must be called to invoke this callback function, synchronously. + * @since_tizen 5.5 + * @remarks @a keyword should not be freed and can be used only in the callback. + * @param[in] keyword The keyword of the sticker + * @param[in] user_data The user data passed from the foreach function + * @pre sticker_consumer_keyword_list_foreach_all() will invoke this callback. + * @see sticker_consumer_keyword_list_foreach_all() + */ +typedef void (*sticker_consumer_keyword_list_foreach_cb)(const char *keyword, void *user_data); + +/** + * @brief Creates a sticker consumer handle. + * @since_tizen 5.5 + * @privlevel public + * @privilege %http://tizen.org/privilege/mediastorage + * @remarks If the function succeeds, @a consumer_handle must be released with sticker_consumer_destroy(). + * @param[out] consumer_handle The sticker consumer handle + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_PERMISSION_DENIED Permission denied + * @retval #STICKER_ERROR_OUT_OF_MEMORY Out of memory + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + * @see sticker_consumer_destroy() + */ +int sticker_consumer_create(sticker_consumer_h *consumer_handle); + +/** + * @brief Destroys a sticker consumer handle. + * @since_tizen 5.5 + * @param[in] consumer_handle The sticker consumer handle + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + * @see sticker_consumer_create() + */ +int sticker_consumer_destroy(sticker_consumer_h consumer_handle); + +/** + * @brief Retrieves all sticker data in the sticker database. + * @details If you set the @a offset as @c 10 and @a count as @c 10, then only retrieved data from @c 10 to @c 19 will be invoked. + * @since_tizen 5.5 + * @remarks It is not an error if @a result is smaller than @a count. + * @param[in] consumer_handle The sticker consumer handle + * @param[in] offset The start position (Starting from zero) + * @param[in] count The number of stickers to be retrieved with respect to the offset + * @param[out] result The number of stickers retrieved (zero indicates that no data was found) + * @param[in] callback The callback function to invoke + * @param[in] user_data The user data to be passed to the callback function + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OUT_OF_MEMORY Out of memory + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + * @post This function invokes sticker_consumer_data_foreach_cb() repeatedly for getting data. + * @see sticker_consumer_data_foreach_cb() + */ +int sticker_consumer_data_foreach_all(sticker_consumer_h consumer_handle, int offset, int count, int *result, sticker_consumer_data_foreach_cb callback, void *user_data); + +/** + * @brief Retrieves all sticker data in the sticker database using keyword. + * @details If you set the @a offset as @c 10 and @a count as @c 10, then only retrieved data from @c 10 to @c 19 will be invoked. + * @since_tizen 5.5 + * @remarks It is not an error if @a result is smaller than @a count. + * @param[in] consumer_handle The sticker consumer handle + * @param[in] offset The start position (Starting from zero) + * @param[in] count The number of stickers to be retrieved with respect to the offset + * @param[out] result The number of stickers retrieved (zero indicates that no data was found) + * @param[in] keyword The keyword of the sticker for getting sticker data + * @param[in] callback The callback function to invoke + * @param[in] user_data The user data to be passed to the callback function + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OUT_OF_MEMORY Out of memory + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + * @post This function invokes sticker_consumer_data_foreach_cb() repeatedly for getting data. + * @see sticker_consumer_data_foreach_cb() + */ +int sticker_consumer_data_foreach_by_keyword(sticker_consumer_h consumer_handle, int offset, int count, int *result, const char *keyword, sticker_consumer_data_foreach_cb callback, void *user_data); + +/** + * @brief Retrieves all sticker data in the sticker database using group name. + * @details If you set the @a offset as @c 10 and @a count as @c 10, then only retrieved data from @c 10 to @c 19 will be invoked. + * @since_tizen 5.5 + * @remarks It is not an error if @a result is smaller than @a count. + * @param[in] consumer_handle The sticker consumer handle + * @param[in] offset The start position (Starting from zero) + * @param[in] count The number of stickers to be retrieved with respect to the offset + * @param[out] result The number of stickers retrieved (zero indicates that no data was found) + * @param[in] group The group name of the sticker for getting sticker data + * @param[in] callback The callback function to invoke + * @param[in] user_data The user data to be passed to the callback function + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OUT_OF_MEMORY Out of memory + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + * @post This function invokes sticker_consumer_data_foreach_cb() repeatedly for getting data. + * @see sticker_consumer_data_foreach_cb() + */ +int sticker_consumer_data_foreach_by_group(sticker_consumer_h consumer_handle, int offset, int count, int *result, const char *group, sticker_consumer_data_foreach_cb callback, void *user_data); + +/** + * @brief Retrieves all sticker data in the sticker database using URI type. + * @details If you set the @a offset as @c 10 and @a count as @c 10, then only retrieved data from @c 10 to @c 19 will be invoked. + * @since_tizen 5.5 + * @remarks It is not an error if @a result is smaller than @a count. + * @param[in] consumer_handle The sticker consumer handle + * @param[in] offset The start position (Starting from zero) + * @param[in] count The number of stickers to be retrieved with respect to the offset + * @param[out] result The number of stickers retrieved (zero indicates that no data was found) + * @param[in] type The URI type of the sticker for getting sticker data + * @param[in] callback The callback function to invoke + * @param[in] user_data The user data to be passed to the callback function + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OUT_OF_MEMORY Out of memory + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + * @post This function invokes sticker_consumer_data_foreach_cb() repeatedly for getting data. + * @see sticker_consumer_data_foreach_cb() + */ +int sticker_consumer_data_foreach_by_type(sticker_consumer_h consumer_handle, int offset, int count, int *result, sticker_data_uri_type_e type, sticker_consumer_data_foreach_cb callback, void *user_data); + +/** + * @brief Retrieves all group name in the sticker database. + * @since_tizen 5.5 + * @param[in] consumer_handle The sticker consumer handle + * @param[in] callback The callback function to invoke + * @param[in] user_data The user data to be passed to the callback function + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + * @post This function invokes sticker_consumer_group_list_foreach_cb() repeatedly for getting data. + * @see sticker_consumer_group_list_foreach_cb() + */ +int sticker_consumer_group_list_foreach_all(sticker_consumer_h consumer_handle, sticker_consumer_group_list_foreach_cb callback, void *user_data); + +/** + * @brief Retrieves all keyword in the sticker database. + * @since_tizen 5.5 + * @param[in] consumer_handle The sticker consumer handle + * @param[in] callback The callback function to invoke + * @param[in] user_data The user data to be passed to the callback function + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + * @post This function invokes sticker_consumer_keyword_list_foreach_cb() repeatedly for getting data. + * @see sticker_consumer_keyword_list_foreach_cb() + */ +int sticker_consumer_keyword_list_foreach_all(sticker_consumer_h consumer_handle, sticker_consumer_keyword_list_foreach_cb callback, void *user_data); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_UIX_STICKER_CONSUMER_H__ */ diff --git a/include/sticker_data.h b/include/sticker_data.h new file mode 100644 index 0000000..b0d4db7 --- /dev/null +++ b/include/sticker_data.h @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_UIX_STICKER_DATA_H__ +#define __TIZEN_UIX_STICKER_DATA_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file sticker_data.h + * @brief This file contains sticker data APIs and related enumeration. + */ + +/** + * @addtogroup CAPI_UIX_STICKER_DATA_MODULE + * @{ + */ + +/** + * @brief Enumeration for sticker URI type. + * + * @since_tizen 5.5 + */ +typedef enum { + STICKER_DATA_URI_LOCAL_PATH = 1, /**< Local path URI */ + STICKER_DATA_URI_WEB_RESOURCE, /**< Web resource URI */ +} sticker_data_uri_type_e; + +/** + * @brief The sticker data handle. + * @since_tizen 5.5 + */ +typedef struct sticker_data_s *sticker_data_h; + +/** + * @brief Called to retrieve the keyword of the sticker. + * @details The sticker_data_foreach_keyword() must be called to invoke this callback function, synchronously. + * @since_tizen 5.5 + * @remarks @a keyword should not be freed and can be used only in the callback. + * @param[in] keyword The sticker keyword + * @param[in] user_data The user data passed from the foreach function + * @pre sticker_data_foreach_keyword() will invoke this callback. + * @see sticker_data_foreach_keyword() + */ +typedef void (*sticker_data_keyword_foreach_cb)(const char *keyword, void *user_data); + +/** + * @brief Creates a sticker data handle. + * @since_tizen 5.5 + * @remarks If the function succeeds, @a data_handle must be released with sticker_data_destroy(). + * @param[out] data_handle The sticker data handle + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OUT_OF_MEMORY Out of memory + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + * @see sticker_data_destroy() + */ +int sticker_data_create(sticker_data_h *data_handle); + +/** + * @brief Destroys a sticker data handle. + * @since_tizen 5.5 + * @param[in] data_handle The sticker data handle + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @see sticker_data_create() + */ +int sticker_data_destroy(sticker_data_h data_handle); + +/** + * @brief Clones a sticker data handle. + * @since_tizen 5.5 + * @remarks If the function succeeds, @a target_handle must be released with sticker_data_destroy(). + * @param[in] origin_handle The sticker data handle + * @param[out] target_handle The sticker data handle to be cloned + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OUT_OF_MEMORY Out of memory + * @see sticker_data_destroy() + */ +int sticker_data_clone(sticker_data_h origin_handle, sticker_data_h *target_handle); + +/** + * @brief Gets the name of the sticker provider application from sticker data handle. + * @since_tizen 5.5 + * @remarks @a app_id must be released using free(). + * @param[in] data_handle The sticker data handle + * @param[out] app_id The name of the application that provides sticker information + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + */ +int sticker_data_get_app_id(sticker_data_h data_handle, char **app_id); + +/** + * @brief Sets the URI and URI type of the sticker. + * @details @a uri must be a relative path like '/res/smile.png' when the type of URI is local path. + * @since_tizen 5.5 + * @remarks @a uri must have a non-null value and must be an existing file. If not, the error as invalid parameter will be returned. + * @param[in] data_handle The sticker data handle + * @param[in] type The URI type to be saved + * @param[in] uri The URI to be saved + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + * @see sticker_data_get_uri() + */ +int sticker_data_set_uri(sticker_data_h data_handle, sticker_data_uri_type_e type, const char *uri); + +/** + * @brief Gets the URI and URI type from sticker data handle. + * @since_tizen 5.5 + * @remarks @a uri must be released using free(). + * @param[in] data_handle The sticker data handle + * @param[out] type The URI type + * @param[out] uri The URI + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + * @see sticker_data_set_uri() + */ +int sticker_data_get_uri(sticker_data_h data_handle, sticker_data_uri_type_e *type, char **uri); + +/** + * @brief Retrieves all keywords of the sticker using callback function. + * @since_tizen 5.5 + * @param[in] data_handle The sticker data handle + * @param[in] callback The callback function to invoke + * @param[in] user_data The user data to be passed to the callback function + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + * @post This function invokes sticker_data_keyword_foreach_cb() repeatedly for getting keywords. + * @see sticker_data_keyword_foreach_cb() + * @see sticker_data_add_keyword() + * @see sticker_data_remove_keyword() + */ +int sticker_data_foreach_keyword(sticker_data_h data_handle, sticker_data_keyword_foreach_cb callback, void *user_data); + +/** + * @brief Adds a keyword of the sticker to the list. + * @since_tizen 5.5 + * @remarks @a keyword must have a non-null value and can not have duplicate value. If not, the error as invalid parameter will be returned. + * @param[in] data_handle The sticker data handle + * @param[in] keyword The keyword to be saved + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @see sticker_data_keyword_foreach_cb() + * @see sticker_data_foreach_keyword() + * @see sticker_data_remove_keyword() + */ +int sticker_data_add_keyword(sticker_data_h data_handle, const char *keyword); + +/** + * @brief Removes a keyword of the sticker from the list. + * @since_tizen 5.5 + * @remarks @a keyword must exist value in the list. If not, the error as invalid parameter will be returned. + * @param[in] data_handle The sticker data handle + * @param[in] keyword The keyword to be removed + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @see sticker_data_keyword_foreach_cb() + * @see sticker_data_foreach_keyword() + * @see sticker_data_add_keyword() + */ +int sticker_data_remove_keyword(sticker_data_h data_handle, const char *keyword); + +/** + * @brief Sets the group name of the sticker. + * @since_tizen 5.5 + * @remarks @a group must have a non-null value. If not, the error as invalid parameter will be returned. + * @param[in] data_handle The sticker data handle + * @param[in] group The group name to be saved + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @see sticker_data_get_group() + */ +int sticker_data_set_group_name(sticker_data_h data_handle, const char *group); + +/** + * @brief Gets the group name from sticker data handle. + * @since_tizen 5.5 + * @remarks @a group must be released using free(). + * @param[in] data_handle The sticker data handle + * @param[out] group The group name + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + * @see sticker_data_set_group() + */ +int sticker_data_get_group_name(sticker_data_h data_handle, char **group); + +/** + * @brief Sets the thumbnail local path of the sticker. + * @details @a thumbnail must be a relative path like '/res/smile_thumbnail.png'. + * @since_tizen 5.5 + * @remarks @a thumbnail must have a non-null value and must be an existing file. If not, the error as invalid parameter will be returned. + * @param[in] data_handle The sticker data handle + * @param[in] thumbnail The thumbnail path to be saved + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @see sticker_data_get_thumbnail() + */ +int sticker_data_set_thumbnail(sticker_data_h data_handle, const char *thumbnail); + +/** + * @brief Gets the thumbnail local path from sticker data handle. + * @details If the thumbnail is empty, the result will be an empty string. + * @since_tizen 5.5 + * @remarks @a thumbnail must be released using free(). + * @param[in] data_handle The sticker data handle + * @param[out] thumbnail The thumbnail path + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @see sticker_data_set_thumbnail() + */ +int sticker_data_get_thumbnail(sticker_data_h data_handle, char **thumbnail); + +/** + * @brief Sets the description of the sticker. + * @since_tizen 5.5 + * @remarks @a description must have a non-null value. If not, the error as invalid parameter will be returned. + * @param[in] data_handle The sticker data handle + * @param[in] description The description to be saved + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @see sticker_data_get_description() + */ +int sticker_data_set_description(sticker_data_h data_handle, const char *description); + +/** + * @brief Gets the description from sticker data handle. + * @details If the description is empty, the result will be an empty string. + * @since_tizen 5.5 + * @remarks @a description must be released using free(). + * @param[in] data_handle The sticker data handle + * @param[out] description The description of the sticker + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @see sticker_data_set_description() + */ +int sticker_data_get_description(sticker_data_h data_handle, char **description); + +/** + * @brief Gets the last updated date from sticker data handle. + * @details The format of @a date is YYYY-MM-DD HH:MM:SS. + * @since_tizen 5.5 + * @remarks @a date must be released using free(). + * @param[in] data_handle The sticker data handle + * @param[out] date The last updated date + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + */ +int sticker_data_get_date(sticker_data_h data_handle, char **date); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_UIX_STICKER_DATA_H__ */ \ No newline at end of file diff --git a/include/sticker_error.h b/include/sticker_error.h new file mode 100644 index 0000000..049ab05 --- /dev/null +++ b/include/sticker_error.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_UIX_STICKER_ERROR_H__ +#define __TIZEN_UIX_STICKER_ERROR_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file sticker_error.h + * @brief This file contains sticker error enumeration. + */ + +/** + * @addtogroup CAPI_UIX_STICKER_MODULE + * @{ + */ + +/** + * @brief Enumeration for sticker function error. + * + * @since_tizen 5.5 + */ +typedef enum { + STICKER_ERROR_NONE = TIZEN_ERROR_NONE, /**< Successful */ + STICKER_ERROR_INVALID_PARAMETER = TIZEN_ERROR_INVALID_PARAMETER, /**< Invalid parameter */ + STICKER_ERROR_PERMISSION_DENIED = TIZEN_ERROR_PERMISSION_DENIED, /**< Permission denied */ + STICKER_ERROR_OUT_OF_MEMORY = TIZEN_ERROR_OUT_OF_MEMORY, /**< Out of memory */ + STICKER_ERROR_OPERATION_FAILED = TIZEN_ERROR_STICKER | 0x0001, /**< Operation failed */ +} sticker_error_e; + +/** + * @} + */ +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_UIX_STICKER_ERROR_H__ */ \ No newline at end of file diff --git a/include/sticker_provider.h b/include/sticker_provider.h new file mode 100644 index 0000000..01ed6e0 --- /dev/null +++ b/include/sticker_provider.h @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_UIX_STICKER_PROVIDER_H__ +#define __TIZEN_UIX_STICKER_PROVIDER_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file sticker_provider.h + * @brief This file contains sticker provider's APIs. + */ + +/** + * @addtogroup CAPI_UIX_STICKER_PROVIDER_MODULE + * @{ + */ + +/** + * @brief The sticker provider handle. + * @since_tizen 5.5 + */ +typedef struct sticker_provider_s *sticker_provider_h; + +/** + * @brief Called to retrieve all sticker data in the sticker database. + * @details The sticker_provider_data_foreach_all() must be called to invoke this callback function, synchronously. + * @since_tizen 5.5 + * @remarks @a data_handle should not be freed and can be used only in the callback. + * If you want to use it outside of the callback, you need to use a clone which can be obtained sticker_data_clone(). + * @param[in] data_handle The sticker data handle + * @param[in] user_data The user data passed from the foreach function + * @pre sticker_provider_data_foreach_all() will invoke this callback. + * @see sticker_provider_data_foreach_all() + */ +typedef void (*sticker_provider_data_foreach_cb)(sticker_data_h data_handle, void *user_data); + +/** + * @brief Called when inserting sticker data is finished. + * @details The following error codes can be received: \n + * #STICKER_ERROR_NONE Successful \n + * #STICKER_ERROR_OPERATION_FAILED Operation failed \n + * @since_tizen 5.5 + * @param[in] error The sticker error code + * @param[in] user_data The user data passed from the foreach function + * @pre sticker_privider_insert_data_by_json_file() will invoke this callback. + * @see sticker_privider_insert_data_by_json_file() + */ +typedef void (*sticker_provider_insert_finished_cb)(sticker_error_e error, void *user_data); + +/** + * @brief Creates a sticker provider handle. + * @since_tizen 5.5 + * @remarks If the function succeeds, @a provider_handle must be released with sticker_provider_destroy(). + * @param[out] provider_handle The sticker provider handle + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OUT_OF_MEMORY Out of memory + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + * @see sticker_provider_destroy() + */ +int sticker_provider_create(sticker_provider_h *provider_handle); + +/** + * @brief Destroys a sticker provider handle. + * @since_tizen 5.5 + * @param[in] provider_handle The sticker provider handle + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + * @see sticker_provider_create() + */ +int sticker_provider_destroy(sticker_provider_h provider_handle); + +/** + * @brief Inserts a sticker data to the sticker database. + * @since_tizen 5.5 + * @remarks All data except thumbnail and description must be set in the @a data_handle to insert the sticker data. + * If the uri type is @a STICKER_DATA_URI_LOCAL_PATH, the sticker file is copied to a sticker directory. + * It is recommended to delete your sticker file after inserting a sticker data. + * @param[in] provider_handle The sticker provider handle + * @param[in] data_handle The sticker data handle to be saved + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + * @see sticker_provider_update_data() + * @see sticker_provider_delete_data() + */ +int sticker_provider_insert_data(sticker_provider_h provider_handle, sticker_data_h data_handle); + +/** + * @brief Inserts a sticker data using json file. + * @details @a json_path must be a relative path like '/data/message_sticker.json'. + * @since_tizen 5.5 + * @remarks All data except thumbnail and description must be set in the json file to insert the sticker data. + * @a json_path must have a non-null value and must be an existing file. If not, the error as invalid parameter will be returned. + * If the uri type is @a STICKER_DATA_URI_LOCAL_PATH, the sticker file is copied to a sticker directory. + * It is recommended to delete your sticker files after inserting a sticker data. + * @param[in] provider_handle The sticker provider handle + * @param[in] json_path The path of json file containing sticker information to be saved + * @param[in] callback The callback function to invoke + * @param[in] user_data The user data to be passed to the callback function + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + * @post This function invokes sticker_provider_insert_finished_cb(). + * @see sticker_provider_insert_finished_cb() + * + * @code + //json file format + { + "sticker": + [ + { + "type" : 1, + "uri" : "/res/face/heart_eyes.png", + "keyword" : ["heart eyes", "love", "cute"], + "group" : "face", + "thumbnail" : "/res/face/thumbnail/heart_eyes.png", + "description" : "Smiling face with heart eyes emoji." + }, + { + "type" : 2, + "uri" : "https://samsung.com/example/01/high_five.png", + "keyword" : ["smile", "high five"], + "group" : "face", + "thumbnail" : "", + "description" : "Smiling face with high five emoji." + }, + ..... + { + ..... + } + ] + } + * @endcode + */ +int sticker_privider_insert_data_by_json_file(sticker_provider_h provider_handle, const char *json_path, sticker_provider_insert_finished_cb callback, void *user_data); + +/** + * @brief Updates a sticker data in the sticker database. + * @since_tizen 5.5 + * @param[in] provider_handle The sticker provider handle + * @param[in] data_handle The sticker data handle to be updated + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + * @see sticker_provider_insert_data() + * @see sticker_provider_delete_data() + */ +int sticker_provider_update_data(sticker_provider_h provider_handle, sticker_data_h data_handle); + +/** + * @brief Deletes a sticker data in the sticker database. + * @since_tizen 5.5 + * @remarks The @a sticker_id must be the ID of the sticker stored in the sticker database. + * @param[in] provider_handle The sticker provider handle + * @param[in] data_handle The sticker data handle to be deleted + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + * @see sticker_provider_insert_data() + * @see sticker_provider_update_data() + */ +int sticker_provider_delete_data(sticker_provider_h provider_handle, sticker_data_h data_handle); + +/** + * @brief Gets the count of stickers stored by the provider application. + * @since_tizen 5.5 + * @param[in] provider_handle The sticker provider handle + * @param[out] count The number of stickers + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + */ +int sticker_provider_get_sticker_count(sticker_provider_h provider_handle, int *count); + +/** + * @brief Retrieves all sticker data in the sticker database. + * @details If you set the @a offset as @c 10 and @a count as @c 10, then only searched data from @c 10 to @c 19 will be invoked. + * @since_tizen 5.5 + * @remarks It is not an error if @a result is smaller than @a count. + * @param[in] provider_handle The sticker provider handle + * @param[in] offset The start position (Starting from zero) + * @param[in] count The number of stickers to be searched with respect to the offset + * @param[out] result The number of stickers retrieved (zero indicates that no data was found) + * @param[in] callback The callback function to invoke + * @param[in] user_data The user data to be passed to the callback function + * @return 0 on success, otherwise a negative error value + * @retval #STICKER_ERROR_NONE Successful + * @retval #STICKER_ERROR_INVALID_PARAMETER Invalid parameter + * @retval #STICKER_ERROR_OUT_OF_MEMORY Out of memory + * @retval #STICKER_ERROR_OPERATION_FAILED Operation failed + * @post This function invokes sticker_provider_data_foreach_cb() repeatedly for getting data. + * @see sticker_provider_data_foreach_cb() + */ +int sticker_provider_data_foreach_all(sticker_provider_h provider_handle, int offset, int count, int *result, sticker_provider_data_foreach_cb callback, void *user_data); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_UIX_STICKER_PROVIDER_H__ */ diff --git a/packaging/capi-ui-sticker.conf b/packaging/capi-ui-sticker.conf new file mode 100644 index 0000000..9d90095 --- /dev/null +++ b/packaging/capi-ui-sticker.conf @@ -0,0 +1,14 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/packaging/capi-ui-sticker.service b/packaging/capi-ui-sticker.service new file mode 100644 index 0000000..b6d7b26 --- /dev/null +++ b/packaging/capi-ui-sticker.service @@ -0,0 +1,15 @@ +[Unit] +Description=Start the sticker server + +[Service] +User=ui_fw +Group=ui_fw +BusName=org.tizen.sticker.server +Type=dbus +SmackProcessLabel=System +ExecStart=/usr/bin/sticker-server +Restart=on-failure +RestartSec=2 + +[Install] +WantedBy=multi-user.target diff --git a/packaging/capi-ui-sticker.spec b/packaging/capi-ui-sticker.spec new file mode 100644 index 0000000..45d4ec5 --- /dev/null +++ b/packaging/capi-ui-sticker.spec @@ -0,0 +1,102 @@ +Name: capi-ui-sticker +Summary: Sticker client library and daemon +Version: 0.1.0 +Release: 1 +Group: Graphics & UI Framework/Input +License: Apache-2.0 +Source0: %{name}-%{version}.tar.gz +Source1: capi-ui-sticker.service +Source2: org.tizen.sticker.server.service +Source3: capi-ui-sticker.conf +BuildRequires: cmake, coreutils +BuildRequires: pkgconfig(dlog) +BuildRequires: pkgconfig(libtzplatform-config) +BuildRequires: pkgconfig(cynara-client) +BuildRequires: pkgconfig(cynara-session) +BuildRequires: pkgconfig(capi-appfw-app-common) +BuildRequires: pkgconfig(capi-appfw-package-manager) +BuildRequires: pkgconfig(dbus-1) +BuildRequires: pkgconfig(sqlite3) +BuildRequires: pkgconfig(glib-2.0) +BuildRequires: pkgconfig(json-glib-1.0) +BuildRequires: pkgconfig(gio-2.0) +BuildRequires: pkgconfig(gio-unix-2.0) +BuildRequires: pkgconfig(pkgmgr-info) +Requires: security-config +Requires(post): /sbin/ldconfig +Requires(post): dbus +Requires(postun): /sbin/ldconfig + +%description +Sticker client library and daemon + +%package devel +Summary: Sticker client library and daemon (Development) +Group: Graphics & UI Framework/Input +Requires: %{name} = %{version}-%{release} + +%description devel +Sticker client library and daemon (Development) + +%prep +%setup -q -n %{name}-%{version} +cp %{SOURCE2} . + +%build + +export CFLAGS+=" -DTIZEN_DEBUG_ENABLE -fvisibility=hidden -Werror" +export CXXFLAGS+=" -DTIZEN_DEBUG_ENABLE -fvisibility=hidden -Werror" +export FFLAGS+=" -DTIZEN_DEBUG_ENABLE -fvisibility=hidden" + +cmake . -DCMAKE_INSTALL_PREFIX=/usr -DLIBDIR=%{_libdir} -DBINDIR=%{_bindir} -DINCLUDEDIR=%{_includedir} \ + -DTZ_SYS_RO_SHARE=%TZ_SYS_RO_SHARE -DTZ_SYS_BIN=%TZ_SYS_BIN -DTZ_SYS_SHARE=%TZ_SYS_SHARE +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +%make_install + +mkdir -p %{buildroot}%{_unitdir}/multi-user.target.wants +install -m 0644 %SOURCE1 %{buildroot}%{_unitdir}/capi-ui-sticker.service +%install_service multi-user.target.wants capi-ui-sticker.service + +mkdir -p %{buildroot}%{_datadir}/dbus-1/system-services +install -m 0644 %SOURCE2 %{buildroot}%{_datadir}/dbus-1/system-services/org.tizen.sticker.server.service + +mkdir -p %{buildroot}%{_sysconfdir}/dbus-1/system.d +install -m 0644 %SOURCE3 %{buildroot}%{_sysconfdir}/dbus-1/system.d/capi-ui-sticker.conf + +%post +/sbin/ldconfig + +mkdir -p -m 0775 %{TZ_SYS_SHARE}/sticker-data +chown -R ui_fw:ui_fw %{TZ_SYS_SHARE}/sticker-data +chsmack -t %{TZ_SYS_SHARE}/sticker-data +chsmack -a "System::Shared" %{TZ_SYS_SHARE}/sticker-data + +%postun -p /sbin/ldconfig + +%files +%manifest %{name}.manifest +%license LICENSE +%defattr(-,root,root,-) +%{_libdir}/lib*.so +%attr(0755,root,root) %{_bindir}/sticker-server +%attr(0644,root,root) %{_unitdir}/capi-ui-sticker.service +%attr(0644,root,root) %{_unitdir}/multi-user.target.wants/capi-ui-sticker.service +%attr(0644,root,root) %{_datadir}/dbus-1/system-services/org.tizen.sticker.server.service +%config %{_sysconfdir}/dbus-1/system.d/capi-ui-sticker.conf +%{TZ_SYS_RO_SHARE}/parser-plugins/capi-ui-sticker.info +%{TZ_SYS_RO_ETC}/package-manager/parserlib/category/libcapi-ui-sticker-parser.so* +%{TZ_SYS_RO_ETC}/package-manager/parserlib/metadata/libcapi-ui-sticker-parser.so* + +%files devel +%manifest %{name}-devel.manifest +%defattr(-,root,root,-) +%{_libdir}/lib*.so +%{_libdir}/pkgconfig/capi-ui-sticker-consumer.pc +%{_libdir}/pkgconfig/capi-ui-sticker-provider.pc +%{_includedir}/sticker_error.h +%{_includedir}/sticker_data.h +%{_includedir}/sticker_consumer.h +%{_includedir}/sticker_provider.h \ No newline at end of file diff --git a/packaging/org.tizen.sticker.server.service b/packaging/org.tizen.sticker.server.service new file mode 100644 index 0000000..64f3471 --- /dev/null +++ b/packaging/org.tizen.sticker.server.service @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=org.tizen.sticker.server +Exec=/bin/false +SystemdService=capi-ui-sticker.service \ No newline at end of file diff --git a/provider/CMakeLists.txt b/provider/CMakeLists.txt new file mode 100644 index 0000000..9eb6d49 --- /dev/null +++ b/provider/CMakeLists.txt @@ -0,0 +1,23 @@ +SET(SRCS + sticker_provider.c + ../client/sticker_data.c + ../client/sticker_dbus.c +) + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_BINARY_DIR}/include) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") + +## Add definitions ## +ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"") + +## sticker provider library ## +ADD_LIBRARY(${PROJECT_NAME}-provider SHARED ${SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME}-provider ${pkgs_LDFLAGS}) + +## Install library files ## +INSTALL(TARGETS ${PROJECT_NAME}-provider DESTINATION ${LIBDIR} COMPONENT RuntimeLibraries) diff --git a/provider/sticker_provider.c b/provider/sticker_provider.c new file mode 100644 index 0000000..f600adb --- /dev/null +++ b/provider/sticker_provider.c @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include + +#include "sticker_provider.h" +#include "sticker_provider_main.h" +#include "sticker_dbus.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "STICKER_PROVIDER" + +static void _free_sticker_data(sticker_data_h sticker_data) +{ + if (sticker_data->app_id) { + free(sticker_data->app_id); + sticker_data->app_id = NULL; + } + + if (sticker_data->uri) { + free(sticker_data->uri); + sticker_data->uri = NULL; + } + + if (sticker_data->thumbnail) { + free(sticker_data->thumbnail); + sticker_data->thumbnail = NULL; + } + + if (sticker_data->keyword) { + g_list_free_full(sticker_data->keyword, free); + sticker_data->keyword = NULL; + } + + if (sticker_data->group) { + free(sticker_data->group); + sticker_data->group = NULL; + } + + if (sticker_data->description) { + free(sticker_data->description); + sticker_data->description = NULL; + } + + if (sticker_data->date) { + free(sticker_data->date); + sticker_data->date = NULL; + } + + free(sticker_data); + sticker_data = NULL; +} + +EXPORT_API int sticker_provider_create(sticker_provider_h *provider_handle) +{ + int ret; + + if (!provider_handle) + return STICKER_ERROR_INVALID_PARAMETER; + + struct sticker_provider_s *provider_struct = (sticker_provider_h)calloc(1, sizeof(struct sticker_provider_s)); + + if (!provider_struct) + return STICKER_ERROR_OUT_OF_MEMORY; + + ret = sticker_dbus_init(&provider_struct->gdbus_connection, &provider_struct->server_watcher_id, + &provider_struct->monitor_id, &provider_struct->server_monitor_id, STICKER_CLIENT_LIB_PROVIDER, (void *)provider_struct); + if (ret != STICKER_ERROR_NONE) { + LOGE("Failed to initialize dbus : %d", ret); + free(provider_struct); + return STICKER_ERROR_OPERATION_FAILED; + } + + *provider_handle = provider_struct; + + return STICKER_ERROR_NONE; +} + +EXPORT_API int sticker_provider_destroy(sticker_provider_h provider_handle) +{ + LOGD("provider_handle : %p", provider_handle); + int ret; + + if (!provider_handle) + return STICKER_ERROR_INVALID_PARAMETER; + + ret = sticker_dbus_shutdown(provider_handle->gdbus_connection, &provider_handle->server_monitor_id, &provider_handle->monitor_id); + if (ret != STICKER_ERROR_NONE) { + LOGE("Failed to finalize dbus : %d", ret); + free(provider_handle); + return STICKER_ERROR_OPERATION_FAILED; + } + + if (provider_handle->gdbus_connection) + g_object_unref(provider_handle->gdbus_connection); + + free(provider_handle); + + return STICKER_ERROR_NONE; +} + +EXPORT_API int sticker_provider_insert_data(sticker_provider_h provider_handle, sticker_data_h data_handle) +{ + int ret; + + if (!provider_handle || !data_handle || (data_handle->sticker_info_id > 0)) + return STICKER_ERROR_INVALID_PARAMETER; + + ret = sticker_dbus_insert_sticker_info(provider_handle->gdbus_connection, data_handle); + if (ret != STICKER_ERROR_NONE) { + LOGE("Failed to insert sticker information : %d", ret); + return STICKER_ERROR_OPERATION_FAILED; + } + + return STICKER_ERROR_NONE; +} + +EXPORT_API int sticker_privider_insert_data_by_json_file(sticker_provider_h provider_handle, const char *json_path, sticker_provider_insert_finished_cb callback, void *user_data) +{ + int ret; + char *app_id = NULL; + package_info_h package_info = NULL; + char *app_path = NULL; + char *file_path = NULL; + + if (!provider_handle || !json_path || !callback) + return STICKER_ERROR_INVALID_PARAMETER; + + ret = app_get_id(&app_id); + if (ret != APP_ERROR_NONE) { + LOGE("Failed to get app_id : %d", ret); + ret = STICKER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + if (access(json_path, F_OK) != 0) { + ret = package_info_create(app_id, &package_info); + if (ret != PACKAGE_MANAGER_ERROR_NONE || package_info == NULL) { + LOGE("faild to create package_info. ret: %d", ret); + ret = STICKER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + ret = package_info_get_root_path(package_info, &app_path); + if (ret != PACKAGE_MANAGER_ERROR_NONE || app_path == NULL) { + LOGE("faild to create package_info. ret: %d", ret); + ret = STICKER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + int path_len = strlen(app_path) + strlen(json_path) + 2; + file_path = (char *)calloc(path_len, sizeof(char)); + if (!file_path) { + LOGE("failed to alloc memory"); + ret = STICKER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + if(json_path[0] == '/') + snprintf(file_path, path_len, "%s%s",app_path, json_path); + else + snprintf(file_path, path_len, "%s%s%s",app_path, "/", json_path); + + if (access(file_path, F_OK) != 0) { + LOGE("%s does not exist", file_path); + ret = STICKER_ERROR_INVALID_PARAMETER; + goto cleanup; + } + } else + file_path = strdup(json_path); + + SECURE_LOGD("json path : %s", file_path); + ret = sticker_dbus_insert_sticker_info_by_json(provider_handle->gdbus_connection, app_id, file_path); + if (ret != STICKER_ERROR_NONE) { + LOGE("Failed to load json file : %d", ret); + return STICKER_ERROR_OPERATION_FAILED; + } + + provider_handle->insert_finished_cb = callback; + provider_handle->insert_finished_cb_user_data = user_data; + +cleanup: + if (app_id) + free(app_id); + + if (package_info) + package_info_destroy(package_info); + + if (app_path) + free(app_path); + + if (file_path) + free(file_path); + + return ret; +} + +EXPORT_API int sticker_provider_update_data(sticker_provider_h provider_handle, sticker_data_h data_handle) +{ + int ret; + + if (!provider_handle || !data_handle || (data_handle->sticker_info_id <= 0)) + return STICKER_ERROR_INVALID_PARAMETER; + + ret = sticker_dbus_update_sticker_info(provider_handle->gdbus_connection, data_handle); + if (ret != STICKER_ERROR_NONE) { + LOGE("Failed to update sticker information : %d", ret); + return STICKER_ERROR_OPERATION_FAILED; + } + + return STICKER_ERROR_NONE; +} + +EXPORT_API int sticker_provider_delete_data(sticker_provider_h provider_handle, sticker_data_h data_handle) +{ + int ret; + + if (!provider_handle || (data_handle->sticker_info_id <= 0)) + return STICKER_ERROR_INVALID_PARAMETER; + + ret = sticker_dbus_delete_sticker_info(provider_handle->gdbus_connection, data_handle->sticker_info_id); + if (ret != STICKER_ERROR_NONE) { + LOGE("Failed to delete sticker information : %d", ret); + return STICKER_ERROR_OPERATION_FAILED; + } + + return STICKER_ERROR_NONE; +} + +EXPORT_API int sticker_provider_get_sticker_count(sticker_provider_h provider_handle, int *count) +{ + int ret; + char *app_id = NULL; + + if (!provider_handle) + return STICKER_ERROR_INVALID_PARAMETER; + + ret = app_get_id(&app_id); + if (ret != APP_ERROR_NONE) { + LOGE("Failed to get app_id : %d", ret); + ret = STICKER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + ret = sticker_dbus_get_sticker_count(provider_handle->gdbus_connection, app_id, count); + if (ret != STICKER_ERROR_NONE) { + LOGE("Failed to get sticker count : %d", ret); + ret = STICKER_ERROR_OPERATION_FAILED; + } + +cleanup: + if (app_id) + free(app_id); + + return ret; +} + +EXPORT_API int sticker_provider_data_foreach_all(sticker_provider_h provider_handle, int offset, int count, int *result, sticker_provider_data_foreach_cb callback, void *user_data) +{ + int ret; + int info_id; + int sticker_count = 0; + char *app_id = NULL; + GVariantIter *id_iter = NULL; + + if (!provider_handle || (offset < 0) || (count <= 0) || !result || !callback) + return STICKER_ERROR_INVALID_PARAMETER; + + ret = app_get_id(&app_id); + if (ret != APP_ERROR_NONE) { + LOGE("Failed to get app_id : %d", ret); + ret = STICKER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + ret = sticker_dbus_get_sticker_info_by_appid(provider_handle->gdbus_connection, app_id, offset, count, &id_iter); + if (ret != STICKER_ERROR_NONE) { + LOGE("Failed to get sticker information : %d", ret); + ret = STICKER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + if (id_iter) { + while (g_variant_iter_loop (id_iter, "(i)", &info_id)) { + sticker_data_h sticker_data = (sticker_data_h)calloc(1, sizeof(struct sticker_data_s)); + if (!sticker_data) { + ret = STICKER_ERROR_OUT_OF_MEMORY; + goto cleanup; + } + + ret = sticker_dbus_get_sticker_info_by_record_id(provider_handle->gdbus_connection, sticker_data, info_id); + if (ret == STICKER_ERROR_NONE) { + sticker_count++; + callback(sticker_data, user_data); + _free_sticker_data(sticker_data); + } else { + _free_sticker_data(sticker_data); + goto cleanup; + } + } + } + + *result = sticker_count; + +cleanup: + if (app_id) + free(app_id); + + if (id_iter) + g_variant_iter_free(id_iter); + + return ret; +} \ No newline at end of file diff --git a/provider/sticker_provider_main.h b/provider/sticker_provider_main.h new file mode 100644 index 0000000..6280801 --- /dev/null +++ b/provider/sticker_provider_main.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_UIX_STICKER_PROVIDER_MAIN_H__ +#define __TIZEN_UIX_STICKER_PROVIDER_MAIN_H__ + +#include +#include +#include "sticker_provider.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +struct sticker_provider_s { + GDBusConnection *gdbus_connection; + guint server_watcher_id; + int monitor_id; + int server_monitor_id; + sticker_provider_insert_finished_cb insert_finished_cb; + void *insert_finished_cb_user_data; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_UIX_STICKER_PROVIDER_MAIN_H__ */ \ No newline at end of file diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt new file mode 100644 index 0000000..1c15da7 --- /dev/null +++ b/server/CMakeLists.txt @@ -0,0 +1,19 @@ +SET(SRCS + stickerd_main.c + stickerd_data_manager.c + stickerd_db_manager.c + stickerd_dbus.c +) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIE") + +## Executable ## +ADD_EXECUTABLE(sticker-server ${SRCS}) +TARGET_LINK_LIBRARIES(sticker-server ${pkgs_LDFLAGS}) + +## Install library files ## +INSTALL(TARGETS sticker-server DESTINATION bin) \ No newline at end of file diff --git a/server/stickerd_data_manager.c b/server/stickerd_data_manager.c new file mode 100644 index 0000000..cb457d0 --- /dev/null +++ b/server/stickerd_data_manager.c @@ -0,0 +1,1287 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stickerd_dbus.h" +#include "stickerd_data_manager.h" +#include "stickerd_db_manager.h" +#include "sticker_defs.h" +#include "stickerd_error.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "STICKERD_DATA_MANAGER" + +#define STICKER_DIRECTORY tzplatform_mkpath(TZ_SYS_SHARE, "sticker-data") +#define MAX_ERROR_BUFFER 256 + +static GHashTable *_monitoring_hash; +static char error_buffer[MAX_ERROR_BUFFER]; + +static void _on_name_appeared(GDBusConnection *connection, + const gchar *name, + const gchar *name_owner, + gpointer user_data) +{ + LOGD("name: %s", name); +} + +static void _on_name_vanished(GDBusConnection *connection, + const gchar *name, + gpointer user_data) +{ + monitoring_info_s *info = (monitoring_info_s *)user_data; + + if (info) { + LOGD("name: %s", name); + g_bus_unwatch_name(info->watcher_id); + delete_monitoring_list(&_monitoring_hash, info->bus_name, info->uid); + + if (info->bus_name) + free(info->bus_name); + free(info); + info = NULL; + } +} + +static void _stickerd_client_dbus_method_call_handler(GDBusConnection *conn, const gchar *sender, const gchar *object_path, + const gchar *iface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, + gpointer user_data) +{ + LOGD("stickerd method_name: %s, sender: %s", method_name, sender); + + GVariant *reply_body = NULL; + int ret = STICKERD_SERVER_ERROR_OPERATION_FAILED; + + if (g_strcmp0(method_name, "sticker_service_register") == 0) { + ret = stickerd_server_register(parameters, &reply_body, sender, + _on_name_appeared, _on_name_vanished, &_monitoring_hash); + } else if (g_strcmp0(method_name, "insert_sticker_info") == 0) { + ret = stickerd_insert_sticker_info(parameters, &reply_body); + } else if (g_strcmp0(method_name, "update_sticker_info_by_json") == 0) { + ret = stickerd_insert_sticker_info_by_json(parameters, &reply_body, sender); + } else if (g_strcmp0(method_name, "delete_sticker_info") == 0) { + ret = stickerd_del_sticker_info(parameters, &reply_body); + } else if (g_strcmp0(method_name, "update_sticker_type") == 0) { + ret = stickerd_update_sticker_type(parameters, &reply_body); + } else if (g_strcmp0(method_name, "update_sticker_uri") == 0) { + ret = stickerd_update_sticker_uri(parameters, &reply_body); + } else if (g_strcmp0(method_name, "update_sticker_thumbnail") == 0) { + ret = stickerd_update_sticker_thumbnail(parameters, &reply_body); + } else if (g_strcmp0(method_name, "update_sticker_description") == 0) { + ret = stickerd_update_sticker_description(parameters, &reply_body); + } else if (g_strcmp0(method_name, "update_sticker_group") == 0) { + ret = stickerd_update_sticker_group(parameters, &reply_body); + } else if (g_strcmp0(method_name, "update_sticker_keyword") == 0) { + ret = stickerd_update_sticker_keyword(parameters, &reply_body); + } else if (g_strcmp0(method_name, "get_sticker_info") == 0) { + ret = stickerd_get_sticker_info(parameters, &reply_body); + } else if (g_strcmp0(method_name, "get_group_list") == 0) { + ret = stickerd_get_group_list(parameters, &reply_body); + } else if (g_strcmp0(method_name, "get_keyword_list") == 0) { + ret = stickerd_get_keyword_list(parameters, &reply_body); + } else if (g_strcmp0(method_name, "get_sticker_count") == 0) { + ret = stickerd_get_sticker_count(parameters, &reply_body); + } else if (g_strcmp0(method_name, "get_all_sticker_info") == 0) { + ret = stickerd_get_all_sticker_info(parameters, &reply_body); + } else if (g_strcmp0(method_name, "get_sticker_info_by_appid") == 0) { + ret = stickerd_get_sticker_info_by_app_id(parameters, &reply_body); + } else if (g_strcmp0(method_name, "get_sticker_info_by_type") == 0) { + ret = stickerd_get_sticker_info_by_type(parameters, &reply_body); + } else if (g_strcmp0(method_name, "get_sticker_info_by_group") == 0) { + ret = stickerd_get_sticker_info_by_group(parameters, &reply_body); + } else if (g_strcmp0(method_name, "get_sticker_info_by_keyword") == 0) { + ret = stickerd_get_sticker_info_by_keyword(parameters, &reply_body); + } + + if (ret == STICKERD_SERVER_ERROR_NONE) { + LOGD("method_call successful, method_name : %s", method_name); + g_dbus_method_invocation_return_value(invocation, reply_body); + } else { + LOGE("method_call failed, method_name : %s", method_name); + g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, ret, "sticker error"); + } + + if (reply_body) + g_variant_unref(reply_body); +} + +static const GDBusInterfaceVTable _sticker_interface_vtable = { + _stickerd_client_dbus_method_call_handler, + NULL, + NULL +}; + +int stickerd_register_dbus_interface(void) +{ + static gchar introspection_xml[] = + " " + " " + " " + " " + + " " + " " + " " + " " + " " + + " " + " " + " " + " " + + " " + " " + " " + + " " + " " + " " + " " + + " " + " " + " " + " " + " " + " " + + " " + " " + " " + " " + + " " + " " + " " + " " + + " " + " " + " " + " " + + " " + " " + " " + " " + + " " + " " + " " + " " + " " + + " " + " " + " " + + " " + " " + " " + + " " + " " + " " + " " + + " " + " " + " " + " " + " " + + " " + " " + " " + " " + " " + " " + + " " + " " + " " + " " + " " + " " + + " " + " " + " " + " " + " " + " " + + " " + " " + " " + " " + " " + " " + " " + " "; + + return stickerd_server_register_dbus_interface(introspection_xml, _sticker_interface_vtable); +} + +int stickerd_dbus_init(void) +{ + int ret; + + ret = stickerd_register_dbus_interface(); + if (ret != STICKERD_SERVER_ERROR_NONE) { + LOGE("Failed to register dbus interface : %d", ret); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + return STICKERD_SERVER_ERROR_NONE; +} + +static int _check_file_exist(const char *app_id, const char *path) +{ + int ret = 0; + package_info_h package_info = NULL; + char *app_path = NULL; + char *file_path = NULL; + + if (access(path, F_OK) == 0) { + ret = 0; + goto cleanup; + } + + ret = package_info_create(app_id, &package_info); + if (ret != PACKAGE_MANAGER_ERROR_NONE || package_info == NULL) { + LOGE("faild to create package_info. ret: %d", ret); + ret = -1; + goto cleanup; + } + + ret = package_info_get_root_path(package_info, &app_path); + if (ret != PACKAGE_MANAGER_ERROR_NONE || app_path == NULL) { + LOGE("faild to create package_info. ret: %d", ret); + ret = -1; + goto cleanup; + } + + int path_len = strlen(app_path) + strlen(path) + 2; + file_path = (char *)calloc(path_len, sizeof(char)); + if (!file_path) { + LOGE("Failed to alloc memory"); + ret = -1; + goto cleanup; + } + + if(path[0] == '/') + snprintf(file_path, path_len, "%s%s",app_path, path); + else + snprintf(file_path, path_len, "%s%s%s",app_path, "/", path); + + if (access(file_path, F_OK) != 0) { + LOGE("%s does not exist", file_path); + ret = -1; + } else + ret = 0; + +cleanup: + if (package_info) + package_info_destroy(package_info); + + if (app_path) { + free(app_path); + app_path = NULL; + } + + if (file_path) { + free(file_path); + file_path = NULL; + } + + return ret; +} + +static int _mkdirs(const char *path, mode_t mode) +{ + int len = 0; + char prev_path[2048]; + const char *tmp = path; + + if (!path || strlen(path) > 2048) + return -1; + + memset(prev_path, '\0', 2048); + while ((tmp = strchr(tmp, '/')) != NULL) { + len = tmp - path; + tmp++; + + if (len == 0) + continue; + + strncpy(prev_path, path, len); + prev_path[len] = 0x00; + + if (mkdir(prev_path, mode) == -1 && errno != EEXIST) { + strerror_r(errno, error_buffer, MAX_ERROR_BUFFER); + LOGE("directory create error : %s", error_buffer); + return -1; + } + } + + if (mkdir(prev_path, mode) == -1 && errno != EEXIST) { + strerror_r(errno, error_buffer, MAX_ERROR_BUFFER); + LOGE("directory create error : %s", error_buffer); + return -1; + } + + return 0; +} + +static int _file_copy(const char *src, const char *dest) +{ + int ret = 0; + int fd = -1, n_fd = -1; + char buf[4096]; + int tmp_err = 0; + int size; + + memset(buf, '\0', 4096); + fd = open(src, O_RDONLY); + n_fd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0755); + + if (fd == -1 || n_fd == -1) { + tmp_err = errno; + ret = -1; + goto cleanup; + } + + while((size = read(fd, buf, 4096))) { + if (size == -1) { + if(errno == EINTR) + continue; + + tmp_err = errno; + ret = -1; + goto cleanup; + } + + while(write(n_fd, buf, size) == -1) { + if(errno == EINTR) { + continue; + } else { + tmp_err = errno; + goto cleanup; + } + } + } + +cleanup: + if (fd != -1) + close(fd); + + if (n_fd != -1) + close(n_fd); + + errno = tmp_err; + return ret; +} + +static char* _convert_sticker_uri(const char *uri, const char *appid) +{ + int ret; + int len = strlen(STICKER_DIRECTORY) + strlen(appid) + strlen(uri) + 3; + char * new_path = (char *)calloc(len, sizeof(char)); + if (new_path == NULL) { + LOGE("Failed to alloc memory"); + return NULL; + } + + if (uri[0] == '/') + snprintf(new_path, len, "%s/%s%s",STICKER_DIRECTORY, appid, uri); + else + snprintf(new_path, len, "%s/%s/%s",STICKER_DIRECTORY, appid, uri); + + if (access(new_path, F_OK) == 0) { + LOGE("sticker file already exists"); + ret = -1; + goto cleanup; + } + + ret = _mkdirs(new_path, 0755); + if (ret != 0) { + strerror_r(errno, error_buffer, MAX_ERROR_BUFFER); + LOGE("directory create error : %s", error_buffer); + goto cleanup; + } + + ret = _file_copy(uri, new_path); + if (ret != 0) { + strerror_r(errno, error_buffer, MAX_ERROR_BUFFER); + LOGE("failed to copy sticker file : %s", error_buffer); + } + +cleanup: + if (ret == 0) { + return new_path; + } else { + free(new_path); + new_path = NULL; + return NULL; + } +} + +int stickerd_insert_sticker_info(GVariant *parameters, GVariant **reply_body) +{ + int ret; + int record_id = 0; + STICKER_DAT_TYPE key; + sticker_info_db *sticker_info = NULL; + GVariant *value = NULL; + GVariantIter *info_iter = NULL; + GVariantIter *keyword_iter = NULL; + char *keyword; + + g_variant_get(parameters, "(a{iv}a(s))", &info_iter, &keyword_iter); + if (!info_iter || !keyword_iter) { + LOGD("failed to get iter"); + ret = STICKERD_SERVER_ERROR_OUT_OF_MEMORY; + goto cleanup; + } + + sticker_info = (sticker_info_db *)calloc(1, sizeof(sticker_info_db)); + + if (!sticker_info) { + ret = STICKERD_SERVER_ERROR_OUT_OF_MEMORY; + goto cleanup; + } + + while (g_variant_iter_loop (info_iter, "{iv}", &key, &value)) { + switch(key) { + case STICKER_DATA_TYPE_APP_ID: + sticker_info->app_id = (char *) g_variant_get_string(value, NULL); + break; + case STICKER_DATA_TYPE_URI_TYPE: + sticker_info->type = g_variant_get_int32(value); + break; + case STICKER_DATA_TYPE_URI: + sticker_info->uri = (char *) g_variant_get_string(value, NULL); + break; + case STICKER_DATA_TYPE_THUMBNAIL: + sticker_info->thumbnail = (char *) g_variant_get_string(value, NULL); + break; + case STICKER_DATA_TYPE_DESCRIPTION: + sticker_info->description = (char *) g_variant_get_string(value, NULL); + break; + case STICKER_DATA_TYPE_GROUP: + sticker_info->group = (char *) g_variant_get_string(value, NULL); + break; + default: + break; + } + } + + while (g_variant_iter_loop (keyword_iter, "(s)", &keyword)) { + sticker_info->keyword = g_list_append(sticker_info->keyword, strdup((const char *)keyword)); + } + + if (sticker_info->type == 1) { + if (_check_file_exist(sticker_info->app_id, sticker_info->uri) == 0) { + sticker_info->uri = _convert_sticker_uri(sticker_info->uri, sticker_info->app_id); + if (!sticker_info->uri) { + LOGE("failed to copy sticker file"); + ret = STICKERD_SERVER_ERROR_OPERATION_FAILED; + goto cleanup; + } + } else { + LOGE("sticker file does not exist"); + ret = STICKERD_SERVER_ERROR_OPERATION_FAILED; + goto cleanup; + } + } + + ret = stickerd_db_insert_sticker_info(&record_id, sticker_info); + if (ret != STICKERD_SERVER_ERROR_NONE) { + LOGE("Failed to insert sticker info"); + ret = STICKERD_SERVER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + *reply_body = g_variant_new("(i)", record_id); + if (*reply_body == NULL) { + LOGE("Failed to create reply_body"); + ret = STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + +cleanup: + if (value) + g_variant_unref(value); + + if (info_iter) + g_variant_iter_free(info_iter); + + if (keyword_iter) + g_variant_iter_free(keyword_iter); + + if (sticker_info) { + free(sticker_info); + sticker_info = NULL; + } + + return ret; +} + +static char* _get_string_from_object(JsonObject *object, const char *key) +{ + if (json_object_has_member(object, key) == false) + return NULL; + + const char *str = json_object_get_string_member(object, key); + if (str != NULL) + return strdup(str); + else + return NULL; +} + +static int _get_int_from_object(JsonObject *object, const char *key) +{ + if (json_object_has_member(object, key) == false) + return -1; + + int type = json_object_get_int_member(object, key); + + return type; +} + +int stickerd_insert_sticker_info_by_json(GVariant *parameters, GVariant **reply_body, const char *sender) +{ + int ret = STICKERD_SERVER_ERROR_OPERATION_FAILED; + int record_id; + sticker_info_db *sticker_info = NULL; + char *app_id = NULL; + char *json_path = NULL; + JsonParser* parser = NULL; + GError* err_msg = NULL; + GVariant *body = NULL; + char *cmd = "send_insert_result"; + + *reply_body = g_variant_new("()"); + if (*reply_body == NULL) { + LOGE("Failed to create reply_body"); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + g_variant_get(parameters, "(&s&s)", &app_id, &json_path); + + if (!app_id || !json_path) { + LOGE("failed to get parameter"); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + SECURE_LOGD("app_id: %s, json path: %s", app_id, json_path); + + parser = json_parser_new(); + json_parser_load_from_file(parser, json_path, &err_msg); + if (err_msg) { + LOGE("failed to load json file. error message: %s", err_msg->message); + ret = STICKERD_SERVER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + JsonNode *root = json_parser_get_root(parser); + if (root == NULL) { + LOGE("failed to get root"); + ret = STICKERD_SERVER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + JsonObject *root_obj = json_node_get_object(root); + if (root_obj == NULL) { + LOGE("failed to get object"); + ret = STICKERD_SERVER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + JsonArray *sticker_arr = json_object_get_array_member(root_obj, "sticker"); + if (sticker_arr == NULL) { + LOGE("failed to get array member"); + ret = STICKERD_SERVER_ERROR_OPERATION_FAILED; + goto cleanup; + } + + int arr_len = json_array_get_length(sticker_arr); + for (int i = 0; i < arr_len; i++) { + JsonObject *info_object = json_array_get_object_element(sticker_arr, i); + if (info_object != NULL) { + sticker_info = (sticker_info_db *)calloc(1, sizeof(sticker_info_db)); + if (!sticker_info) { + LOGE("Failed to alloc memory"); + continue; + } + + sticker_info->app_id = app_id; + sticker_info->type = _get_int_from_object(info_object, "type"); + if (sticker_info->type < 1) + goto free_memory; + + sticker_info->uri = _get_string_from_object(info_object, "uri"); + if (!sticker_info->uri) + goto free_memory; + + if (sticker_info->type == 1) { + if (_check_file_exist(sticker_info->app_id, sticker_info->uri) == 0) { + sticker_info->uri = _convert_sticker_uri(sticker_info->uri, sticker_info->app_id); + if (!sticker_info->uri) + goto free_memory; + } + } + + sticker_info->group = _get_string_from_object(info_object, "group"); + if (!sticker_info->group) + goto free_memory; + + sticker_info->thumbnail = _get_string_from_object(info_object, "thumbnail"); + if (!sticker_info->thumbnail) + goto free_memory; + + sticker_info->description = _get_string_from_object(info_object, "description"); + + JsonArray *keyword_arr = json_object_get_array_member(info_object, "keyword"); + int keyword_arr_len = json_array_get_length(keyword_arr); + if (keyword_arr_len < 1) + goto free_memory; + + for (int j = 0; j < keyword_arr_len; j++) { + sticker_info->keyword = g_list_append(sticker_info->keyword, strdup((const char *)json_array_get_string_element(keyword_arr, j))); + } + + ret = stickerd_db_insert_sticker_info(&record_id, sticker_info); + if (ret != STICKERD_SERVER_ERROR_NONE) { + LOGE("Failed to insert sticker info"); + ret = STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + +free_memory: + free(sticker_info); + sticker_info = NULL; + } + } + +cleanup: + if (err_msg) + g_error_free(err_msg); + if (parser) + g_object_unref(parser); + + body = g_variant_new("(i)", ret); + + ret = stickerd_send_dbus_message(body, sender, cmd, STICKER_CLIENT_LIB_PROVIDER); + if (ret != STICKERD_SERVER_ERROR_NONE) + LOGE("Failed to send insert result to client"); + + if(body) + g_variant_unref(body); + + return ret; +} + +int stickerd_del_sticker_info(GVariant *parameters, GVariant **reply_body) +{ + int ret; + int record_id; + + *reply_body = g_variant_new("()"); + if (*reply_body == NULL) { + LOGE("Failed to create reply_body"); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + g_variant_get(parameters, "(i)", &record_id); + + ret = stickerd_db_delete_sticker_info(record_id); + if (ret != STICKERD_SERVER_ERROR_NONE) { + LOGE("Failed to delete sticker info"); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + return ret; +} + +int stickerd_update_sticker_type(GVariant *parameters, GVariant **reply_body) +{ + int ret; + int record_id; + int type; + + *reply_body = g_variant_new("()"); + if (*reply_body == NULL) { + LOGE("Failed to create reply_body"); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + g_variant_get(parameters, "(ii)", &record_id, &type); + + ret = stickerd_db_update_sticker_info(record_id, STICKER_DB_STICKER_TYPE, &type); + if (ret != STICKERD_SERVER_ERROR_NONE) { + LOGE("Failed to update sticker type"); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + return ret; +} + +int stickerd_update_sticker_uri(GVariant *parameters, GVariant **reply_body) +{ + int ret; + int record_id; + int type; + char *app_id; + char *uri; + + *reply_body = g_variant_new("()"); + if (*reply_body == NULL) { + LOGE("Failed to create reply_body"); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + g_variant_get(parameters, "(i&si&s)", &record_id, &app_id, &type, &uri); + + if (type == 1) { + if (_check_file_exist(app_id, uri) == 0) { + uri = _convert_sticker_uri(uri, app_id); + if (!uri) { + LOGE("failed to copy sticker file"); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + } + } + + ret = stickerd_db_update_sticker_info(record_id, STICKER_DB_STICKER_URI, (void *)uri); + if (ret != STICKERD_SERVER_ERROR_NONE) { + LOGE("Failed to update sticker uri"); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + return ret; +} + +int stickerd_update_sticker_thumbnail(GVariant *parameters, GVariant **reply_body) +{ + int ret; + int record_id; + char *thumbnail; + + *reply_body = g_variant_new("()"); + if (*reply_body == NULL) { + LOGE("Failed to create reply_body"); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + g_variant_get(parameters, "(i&s)", &record_id, &thumbnail); + + ret = stickerd_db_update_sticker_info(record_id, STICKER_DB_STICKER_THUMBNAIL, (void *)thumbnail); + if (ret != STICKERD_SERVER_ERROR_NONE) { + LOGE("Failed to update sticker thumbnail"); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + return ret; +} + +int stickerd_update_sticker_description(GVariant *parameters, GVariant **reply_body) +{ + int ret; + int record_id; + char *description; + + *reply_body = g_variant_new("()"); + if (*reply_body == NULL) { + LOGE("Failed to create reply_body"); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + g_variant_get(parameters, "(i&s)", &record_id, &description); + + ret = stickerd_db_update_sticker_info(record_id, STICKER_DB_STICKER_DESCRIPTION, (void *)description); + if (ret != STICKERD_SERVER_ERROR_NONE) { + LOGE("Failed to update sticker description"); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + return ret; +} + +int stickerd_update_sticker_group(GVariant *parameters, GVariant **reply_body) +{ + int ret; + int record_id; + char *group; + + *reply_body = g_variant_new("()"); + if (*reply_body == NULL) { + LOGE("Failed to create reply_body"); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + g_variant_get(parameters, "(i&s)", &record_id, &group); + + ret = stickerd_db_update_sticker_info(record_id, STICKER_DB_STICKER_GROUP, (void *)group); + if (ret != STICKERD_SERVER_ERROR_NONE) { + LOGE("Failed to update sticker group"); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + return ret; +} + +int stickerd_update_sticker_keyword(GVariant *parameters, GVariant **reply_body) +{ + int ret; + int record_id; + GVariantIter *keyword_iter = NULL; + char *keyword = NULL; + GList *keyword_list = NULL; + + *reply_body = g_variant_new("()"); + if (*reply_body == NULL) { + LOGE("Failed to create reply_body"); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + g_variant_get(parameters, "(ia(s))", &record_id, &keyword_iter); + + if (!keyword_iter) { + LOGD("failed to get iter"); + return STICKERD_SERVER_ERROR_OUT_OF_MEMORY; + } + + while (g_variant_iter_loop (keyword_iter, "(s)", &keyword)) { + keyword_list = g_list_append(keyword_list, strdup((const char *)keyword)); + } + + g_variant_iter_free(keyword_iter); + + ret = stickerd_db_update_sticker_info(record_id, STICKER_DB_STICKER_KEYWORD, (void *)keyword_list); + if (ret != STICKERD_SERVER_ERROR_NONE) { + LOGE("Failed to update sticker keyword"); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + return ret; +} + +static void _set_keyword_builder(char *keyword, GVariantBuilder *keyword_builder) +{ + if (!keyword) { + LOGE("keyword doesn't exist"); + return; + } + + g_variant_builder_add(keyword_builder, "(s)", strdup((const char *)keyword)); +} + +int stickerd_get_sticker_info(GVariant *parameters, GVariant **reply_body) +{ + int ret; + int record_id; + GVariantBuilder *info_builder; + GVariantBuilder *keyword_builder; + + g_variant_get(parameters, "(i)", &record_id); + sticker_info_db *sticker_info = (sticker_info_db *)calloc(1, sizeof(sticker_info_db)); + + if (!sticker_info) + return STICKERD_SERVER_ERROR_OUT_OF_MEMORY; + + ret = stickerd_db_get_sticker_info_by_record_id(record_id, sticker_info); + if (ret != STICKERD_SERVER_ERROR_NONE) { + LOGE("Failed to get sticker info"); + free(sticker_info); + sticker_info = NULL; + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + info_builder = g_variant_builder_new(G_VARIANT_TYPE("a{iv}")); + g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_APP_ID, g_variant_new_string((const gchar *)sticker_info->app_id)); + g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_URI_TYPE, g_variant_new_int32(sticker_info->type)); + g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_URI, g_variant_new_string((const gchar *)sticker_info->uri)); + g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_THUMBNAIL, g_variant_new_string((const gchar *)sticker_info->thumbnail)); + g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_DESCRIPTION, g_variant_new_string((const gchar *)sticker_info->description)); + g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_GROUP, g_variant_new_string((const gchar *)sticker_info->group)); + g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_DATE, g_variant_new_string((const gchar *)sticker_info->date)); + + keyword_builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)")); + g_list_foreach(sticker_info->keyword, (GFunc) _set_keyword_builder, keyword_builder); + + *reply_body = g_variant_new("(a{iv}a(s))", info_builder, keyword_builder); + g_variant_builder_unref(info_builder); + g_variant_builder_unref(keyword_builder); + + if (*reply_body == NULL) { + LOGE("Failed to create reply_body"); + free(sticker_info); + sticker_info = NULL; + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + free(sticker_info); + sticker_info = NULL; + return ret; +} + +int stickerd_get_group_list(GVariant *parameters, GVariant **reply_body) +{ + int ret; + GVariantBuilder *builder = NULL; + + builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)")); + ret = stickerd_db_get_group_list(builder); + + if (ret != STICKERD_SERVER_ERROR_NONE) { + LOGE("Failed to get sticker group list"); + g_variant_builder_unref(builder); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + *reply_body = g_variant_new("(a(s))", builder); + g_variant_builder_unref(builder); + + if (*reply_body == NULL) { + LOGE("Failed to create reply_body"); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + return ret; +} + +int stickerd_get_keyword_list(GVariant *parameters, GVariant **reply_body) +{ + int ret; + GVariantBuilder *builder = NULL; + + builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)")); + ret = stickerd_db_get_keyword_list(builder); + if (ret != STICKERD_SERVER_ERROR_NONE) { + LOGE("Failed to get sticker keyword list"); + g_variant_builder_unref(builder); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + *reply_body = g_variant_new("(a(s))", builder); + g_variant_builder_unref(builder); + + if (*reply_body == NULL) { + LOGE("Failed to create reply_body"); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + return ret; +} + +int stickerd_get_sticker_count(GVariant *parameters, GVariant **reply_body) +{ + int ret; + int count; + char *app_id = NULL; + + g_variant_get(parameters, "(&s)", &app_id); + + ret = stickerd_db_get_sticker_count(&count, app_id); + if (ret != STICKERD_SERVER_ERROR_NONE) { + LOGE("Failed to get sticker count"); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + *reply_body = g_variant_new("(i)", count); + if (*reply_body == NULL) { + LOGE("Failed to create reply_body"); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + return ret; +} + +#if 0 +// Send the sticker information by asynchronous communication. +static int send_sticker_info_async(int record_id, sticker_info_db_type type, const char *sender) +{ + int ret; + char *cmd = NULL; + + sticker_info_db *sticker_info = (sticker_info_db *)calloc(1, sizeof(sticker_info_db)); + + if (!sticker_info) + return STICKERD_SERVER_ERROR_OUT_OF_MEMORY; + + ret = stickerd_db_get_sticker_info_by_record_id(record_id, sticker_info); + if (ret != STICKERD_SERVER_ERROR_NONE) { + LOGE("Failed to get sticker info"); + free(sticker_info); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + switch (type) { + case STICKER_DB_STICKER_ALL: + cmd = "send_all_sticker_info"; + break; + case STICKER_DB_STICKER_APPID: + cmd = "send_sticker_info_by_appid"; + break; + case STICKER_DB_STICKER_TYPE: + cmd = "send_sticker_info_by_type"; + break; + case STICKER_DB_STICKER_GROUP: + cmd = "send_sticker_info_by_goup"; + break; + case STICKER_DB_STICKER_KEYWORD: + cmd = "send_sticker_info_by_keyword"; + break; + default: + cmd = ""; + break; + } + + GVariantBuilder *info_builder; + GVariantBuilder *keyword_builder; + + info_builder = g_variant_builder_new(G_VARIANT_TYPE("a{iv}")); + g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_INFO_ID, g_variant_new_int32(record_id)); + g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_APP_ID, g_variant_new_string((const gchar *)sticker_info->app_id)); + g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_URI_TYPE, g_variant_new_int32(sticker_info->type)); + g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_URI, g_variant_new_string((const gchar *)sticker_info->uri)); + g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_THUMBNAIL, g_variant_new_string((const gchar *)sticker_info->thumbnail)); + g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_DESCRIPTION, g_variant_new_string((const gchar *)sticker_info->description)); + g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_GROUP, g_variant_new_string((const gchar *)sticker_info->group)); + g_variant_builder_add(info_builder, "{iv}", STICKER_DATA_TYPE_DATE, g_variant_new_string((const gchar *)sticker_info->date)); + + keyword_builder = g_variant_builder_new(G_VARIANT_TYPE("a(s)")); + g_list_foreach(sticker_info->keyword, (GFunc) _set_keyword_builder, keyword_builder); + + GVariant *body = g_variant_new("(a{iv}a(s))", info_builder, keyword_builder); + g_variant_builder_unref(info_builder); + g_variant_builder_unref(keyword_builder); + + ret = stickerd_send_dbus_message(body, sender, cmd); + if (ret != STICKERD_SERVER_ERROR_NONE) { + LOGE("Failed to send sticker info to client"); + free(sticker_info); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + free(sticker_info); + return ret; +} +#endif + +static void _set_id_builder(char *id, GVariantBuilder *id_builder) +{ + if (!id) { + LOGE("id doesn't exist"); + return; + } + + g_variant_builder_add(id_builder, "(i)", atoi(id)); +} + +int stickerd_get_all_sticker_info(GVariant *parameters, GVariant **reply_body) +{ + int ret; + int offset, count; + GList *id_list = NULL; + GVariantBuilder *id_builder = NULL; + + g_variant_get(parameters, "(ii)", &offset, &count); + + ret = stickerd_db_get_record_id(STICKER_DB_STICKER_ALL, &id_list, NULL, offset, count); + if (ret != STICKERD_SERVER_ERROR_NONE) { + LOGE("Failed to get all sticker id"); + if(id_list) + g_list_free_full(id_list, free); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + id_builder = g_variant_builder_new(G_VARIANT_TYPE("a(i)")); + g_list_foreach(id_list, (GFunc) _set_id_builder, id_builder); + + *reply_body = g_variant_new("(a(i))", id_builder); + if (*reply_body == NULL) { + LOGE("Failed to create reply_body"); + ret = STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + if (id_list) + g_list_free_full(id_list, free); + + if (id_builder) + g_variant_builder_unref(id_builder); + + return ret; +} + +int stickerd_get_sticker_info_by_app_id(GVariant *parameters, GVariant **reply_body) +{ + int ret; + GList *id_list = NULL; + char *app_id = NULL; + int offset, count; + GVariantBuilder *id_builder = NULL; + + g_variant_get(parameters, "(&sii)", &app_id, &offset, &count); + + ret = stickerd_db_get_record_id(STICKER_DB_STICKER_APPID, &id_list, (void *)app_id, offset, count); + if (ret != STICKERD_SERVER_ERROR_NONE) { + LOGE("Failed to get all sticker id"); + if(id_list) + g_list_free_full(id_list, free); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + id_builder = g_variant_builder_new(G_VARIANT_TYPE("a(i)")); + g_list_foreach(id_list, (GFunc) _set_id_builder, id_builder); + + *reply_body = g_variant_new("(a(i))", id_builder); + if (*reply_body == NULL) { + LOGE("Failed to create reply_body"); + ret = STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + if (id_list) + g_list_free_full(id_list, free); + + if (id_builder) + g_variant_builder_unref(id_builder); + + return ret; +} + +int stickerd_get_sticker_info_by_type(GVariant *parameters, GVariant **reply_body) +{ + int ret; + GList *id_list = NULL; + int type, offset, count; + GVariantBuilder *id_builder = NULL; + + g_variant_get(parameters, "(iii)", &type, &offset, &count); + + ret = stickerd_db_get_record_id(STICKER_DB_STICKER_TYPE, &id_list, &type, offset, count); + if (ret != STICKERD_SERVER_ERROR_NONE) { + LOGE("Failed to get all sticker id"); + if(id_list) + g_list_free_full(id_list, free); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + id_builder = g_variant_builder_new(G_VARIANT_TYPE("a(i)")); + g_list_foreach(id_list, (GFunc) _set_id_builder, id_builder); + + *reply_body = g_variant_new("(a(i))", id_builder); + if (*reply_body == NULL) { + LOGE("Failed to create reply_body"); + ret = STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + if (id_list) + g_list_free_full(id_list, free); + + if (id_builder) + g_variant_builder_unref(id_builder); + + return ret; +} + +int stickerd_get_sticker_info_by_group(GVariant *parameters, GVariant **reply_body) +{ + int ret; + GList *id_list = NULL; + char *group = NULL; + int offset, count; + GVariantBuilder *id_builder = NULL; + + g_variant_get(parameters, "(&sii)", &group, &offset, &count); + + ret = stickerd_db_get_record_id(STICKER_DB_STICKER_GROUP, &id_list, (void *)group, offset, count); + if (ret != STICKERD_SERVER_ERROR_NONE) { + LOGE("Failed to get all sticker id"); + if(id_list) + g_list_free_full(id_list, free); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + id_builder = g_variant_builder_new(G_VARIANT_TYPE("a(i)")); + g_list_foreach(id_list, (GFunc) _set_id_builder, id_builder); + + *reply_body = g_variant_new("(a(i))", id_builder); + if (*reply_body == NULL) { + LOGE("Failed to create reply_body"); + ret = STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + if (id_list) + g_list_free_full(id_list, free); + + if (id_builder) + g_variant_builder_unref(id_builder); + + return ret; +} + +int stickerd_get_sticker_info_by_keyword(GVariant *parameters, GVariant **reply_body) +{ + int ret; + GList *id_list = NULL; + char *keyword = NULL; + int offset, count; + GVariantBuilder *id_builder = NULL; + + g_variant_get(parameters, "(&sii)", &keyword, &offset, &count); + + ret = stickerd_db_get_record_id(STICKER_DB_STICKER_KEYWORD, &id_list, (void *)keyword, offset, count); + if (ret != STICKERD_SERVER_ERROR_NONE) { + LOGE("Failed to get all sticker id"); + if(id_list) + g_list_free_full(id_list, free); + return STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + id_builder = g_variant_builder_new(G_VARIANT_TYPE("a(i)")); + g_list_foreach(id_list, (GFunc) _set_id_builder, id_builder); + + *reply_body = g_variant_new("(a(i))", id_builder); + if (*reply_body == NULL) { + LOGE("Failed to create reply_body"); + ret = STICKERD_SERVER_ERROR_OPERATION_FAILED; + } + + if (id_list) + g_list_free_full(id_list, free); + + if (id_builder) + g_variant_builder_unref(id_builder); + + return ret; +} diff --git a/server/stickerd_data_manager.h b/server/stickerd_data_manager.h new file mode 100644 index 0000000..8086dcb --- /dev/null +++ b/server/stickerd_data_manager.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_UIX_STICKERD_DATA_MANAGER_H__ +#define __TIZEN_UIX_STICKERD_DATA_MANAGER_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +int stickerd_dbus_init(void); +int stickerd_register_dbus_interface(void); +int stickerd_insert_sticker_info(GVariant *parameters, GVariant **reply_body); +int stickerd_insert_sticker_info_by_json(GVariant *parameters, GVariant **reply_body, const char *sender); +int stickerd_del_sticker_info(GVariant *parameters, GVariant **reply_body); +int stickerd_update_sticker_type(GVariant *parameters, GVariant **reply_body); +int stickerd_update_sticker_uri(GVariant *parameters, GVariant **reply_body); +int stickerd_update_sticker_thumbnail(GVariant *parameters, GVariant **reply_body); +int stickerd_update_sticker_description(GVariant *parameters, GVariant **reply_body); +int stickerd_update_sticker_group(GVariant *parameters, GVariant **reply_body); +int stickerd_update_sticker_keyword(GVariant *parameters, GVariant **reply_body); +int stickerd_get_sticker_info(GVariant *parameters, GVariant **reply_body); +int stickerd_get_group_list(GVariant *parameters, GVariant **reply_body); +int stickerd_get_keyword_list(GVariant *parameters, GVariant **reply_body); +int stickerd_get_sticker_count(GVariant *parameters, GVariant **reply_body); +int stickerd_get_all_sticker_info(GVariant *parameters, GVariant **reply_body); +int stickerd_get_sticker_info_by_app_id(GVariant *parameters, GVariant **reply_body); +int stickerd_get_sticker_info_by_type(GVariant *parameters, GVariant **reply_body); +int stickerd_get_sticker_info_by_group(GVariant *parameters, GVariant **reply_body); +int stickerd_get_sticker_info_by_keyword(GVariant *parameters, GVariant **reply_body); + +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_UIX_STICKERD_DATA_MANAGER_H__ */ \ No newline at end of file diff --git a/server/stickerd_db_manager.c b/server/stickerd_db_manager.c new file mode 100644 index 0000000..de33abc --- /dev/null +++ b/server/stickerd_db_manager.c @@ -0,0 +1,702 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include "stickerd_db_manager.h" +#include "stickerd_error.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "STICKERD_DB_MANAGER" + +/* + * Table Information + * + * sticker_info + * +-----------------+--------+------+------+-----------+-------------+------------+------+ + * | INT | TEXT | INT | TEXT | TEXT | TEXT | TEXT | TEXT | + * +-----------------+--------+------+------+-----------+-------------+------------+------+ + * | sticker_info_id | app_id | type | uri | thumbnail | description | group_name | date | + * +-----------------+--------+------+------+-----------+-------------+------------+------+ + * + * sticker_keyword_info + * +------------+-----------------+---------+ + * | INT | INT | TEXT | + * +------------+-----------------+---------+ + * | keyword_id | sticker_info_id | keyword | + * +------------+-----------------+---------+ + * + */ + +#define STICKER_DB_PATH tzplatform_mkpath(TZ_SYS_DB, ".sticker_info.db") +#define STICKER_INFO_CREATE_TABLE "CREATE TABLE IF NOT EXISTS sticker_info(sticker_info_id INTEGER PRIMARY KEY AUTOINCREMENT, app_id TEXT NOT NULL, type INTEGER NOT NULL, uri TEXT NOT NULL, thumbnail TEXT, description TEXT, group_name TEXT NOT NULL, date TEXT NOT NULL);" +#define STICKER_KEYWORD_INFO_CREATE_TABLE "CREATE TABLE IF NOT EXISTS sticker_keyword_info(keyword_id INTEGER PRIMARY KEY AUTOINCREMENT, sticker_info_id INTEGER, keyword TEXT NOT NULL, FOREIGN KEY (sticker_info_id) REFERENCES sticker_info(sticker_info_id) ON DELETE CASCADE)" + +#define STICKER_DB_INSERT_STICKER_INFO "INSERT INTO sticker_info (app_id, type, uri, thumbnail, description, group_name, date) VALUES (?, ?, ?, ?, ?, ?, DateTime('now','localtime'))" +#define STICKER_DB_INSERT_STICKER_KEYWORD_INFO "INSERT INTO sticker_keyword_info (sticker_info_id, keyword) VALUES (?, ?)" + +#define STICKER_DB_DELETE_STICKER_INFO "DELETE FROM sticker_info WHERE sticker_info_id = ?" +#define STICKER_DB_DELETE_STICKER_KEYWORD_INFO "DELETE FROM sticker_keyword_info WHERE sticker_info_id = ?" + +#define STICKER_DB_UPDATE_STICKER_TYPE "UPDATE sticker_info SET type = ?, date = DateTime('now','localtime') WHERE sticker_info_id = ?" +#define STICKER_DB_UPDATE_STICKER_URI "UPDATE sticker_info SET uri = ?, date = DateTime('now','localtime') WHERE sticker_info_id = ?" +#define STICKER_DB_UPDATE_STICKER_THUMBNAIL "UPDATE sticker_info SET thumbnail = ?, date = DateTime('now','localtime') WHERE sticker_info_id = ?" +#define STICKER_DB_UPDATE_STICKER_DESCRIPTION "UPDATE sticker_info SET description = ?, date = DateTime('now','localtime') WHERE sticker_info_id = ?" +#define STICKER_DB_UPDATE_STICKER_GROUP "UPDATE sticker_info SET group_name = ?, date = DateTime('now','localtime') WHERE sticker_info_id = ?" + +#define STICKER_DB_GET_LATEST_RECORD_ID "SELECT sticker_info_id FROM sticker_info ORDER BY sticker_info_id DESC LIMIT 1" +#define STICKER_DB_GET_STICKER_INFO_BY_RECORD_ID "SELECT * FROM sticker_info WHERE sticker_info_id = ?" +#define STICKER_DB_GET_KEYWORD_INFO_BY_RECORD_ID "SELECT keyword FROM sticker_keyword_info WHERE sticker_info_id = ?" +#define STICKER_DB_GET_ALL_GROUP_LIST "SELECT group_name from (SELECT DISTINCT group_name from sticker_info)" +#define STICKER_DB_GET_ALL_KEYWORD_LIST "SELECT keyword from (SELECT DISTINCT keyword from sticker_keyword_info)" +#define STICKER_DB_GET_STICKER_COUNT "SELECT count(*) FROM sticker_info WHERE app_id = ?" +#define STICKER_DB_GET_ALL_RECORD_ID "SELECT sticker_info_id from sticker_info LIMIT ?, ?" +#define STICKER_DB_GET_RECORD_ID_BY_APP_ID "SELECT sticker_info_id from sticker_info WHERE app_id = ? LIMIT ?, ?" +#define STICKER_DB_GET_RECORD_ID_BY_TYPE "SELECT sticker_info_id from sticker_info WHERE type = ? LIMIT ?, ?" +#define STICKER_DB_GET_RECORD_ID_BY_GROUP "SELECT sticker_info_id from sticker_info WHERE group_name = ? LIMIT ?, ?" +#define STICKER_DB_GET_RECORD_ID_BY_KEYWORD "SELECT sticker_info_id from sticker_keyword_info WHERE keyword = ? LIMIT ?, ?" + +typedef enum +{ + CMD_UPDATE, + CMD_SELECT, +} command_type; + +static gboolean is_corrupted = FALSE; + +static const char *_db_get_query(sticker_info_db_type sticker_type, command_type cmd_type) +{ + static const char* query = NULL; + + if (cmd_type == CMD_UPDATE) { + switch(sticker_type) { + case STICKER_DB_STICKER_TYPE: + query = STICKER_DB_UPDATE_STICKER_TYPE; + break; + case STICKER_DB_STICKER_URI: + query = STICKER_DB_UPDATE_STICKER_URI; + break; + case STICKER_DB_STICKER_THUMBNAIL: + query = STICKER_DB_UPDATE_STICKER_THUMBNAIL; + break; + case STICKER_DB_STICKER_DESCRIPTION: + query = STICKER_DB_UPDATE_STICKER_DESCRIPTION; + break; + case STICKER_DB_STICKER_GROUP: + query = STICKER_DB_UPDATE_STICKER_GROUP; + break; + case STICKER_DB_STICKER_KEYWORD: + query = STICKER_DB_DELETE_STICKER_KEYWORD_INFO; + break; + default : + query = ""; + break; + } + } else if (cmd_type == CMD_SELECT) { + switch(sticker_type) { + case STICKER_DB_STICKER_ALL: + query = STICKER_DB_GET_ALL_RECORD_ID; + break; + case STICKER_DB_STICKER_APPID: + query = STICKER_DB_GET_RECORD_ID_BY_APP_ID; + break; + case STICKER_DB_STICKER_TYPE: + query = STICKER_DB_GET_RECORD_ID_BY_TYPE; + break; + case STICKER_DB_STICKER_GROUP: + query = STICKER_DB_GET_RECORD_ID_BY_GROUP; + break; + case STICKER_DB_STICKER_KEYWORD: + query = STICKER_DB_GET_RECORD_ID_BY_KEYWORD; + break; + default : + query = ""; + break; + } + } + + return query; +} + +static int _recover_db(void) +{ + int ret = STICKERD_SERVER_ERROR_NONE; + sqlite3 *db = NULL; + char *err = NULL; + + LOGD("Start to recover sticker db"); + //Remove sticker database file + if (unlink(STICKER_DB_PATH) == -1) + LOGE("Failed to remove db file"); + + ret = sqlite3_open_v2(STICKER_DB_PATH, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL); + if (ret != SQLITE_OK) { + LOGE("Failed to open db : %s", sqlite3_errmsg(db)); + if (unlink(STICKER_DB_PATH) == -1) + LOGE("Failed to remove db file"); + ret = STICKERD_SERVER_ERROR_DB_FAILED; + goto cleanup; + } + + ret = sqlite3_exec(db, STICKER_INFO_CREATE_TABLE, NULL, NULL, &err); + if (ret != SQLITE_OK) { + LOGE("Failed to create sticker_info table : %s" , err); + ret = STICKERD_SERVER_ERROR_DB_FAILED; + goto cleanup; + } + + ret = sqlite3_exec(db, STICKER_KEYWORD_INFO_CREATE_TABLE, NULL, NULL, &err); + if (ret != SQLITE_OK) { + LOGE("Failed to create sticker_keyword_info table : %s", err); + ret = STICKERD_SERVER_ERROR_DB_FAILED; + } + + is_corrupted = FALSE; + +cleanup: + if (err) + sqlite3_free(err); + + if (db) + sqlite3_close(db); + + return ret; +} + +static int _integrity_check_cb(void *pid, int argc, char **argv, char **notUsed) +{ + if (strcmp(argv[0], "ok") != 0) { + LOGE("DB integrity check failed : %s", argv[0]); + is_corrupted = TRUE; + return -1; + } + + LOGD("Result integrity : %s", argv[0]); + return 0; +} + +int stickerd_db_init(void) +{ + int ret = STICKERD_SERVER_ERROR_NONE; + sqlite3 *db = NULL; + char *err = NULL; + + ret = sqlite3_open_v2(STICKER_DB_PATH, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL); + if (ret != SQLITE_OK) { + LOGE("Failed to open db : %s", sqlite3_errmsg(db)); + ret = STICKERD_SERVER_ERROR_DB_FAILED; + goto cleanup; + } + + ret = sqlite3_exec(db, STICKER_INFO_CREATE_TABLE, NULL, NULL, &err); + if (ret != SQLITE_OK) { + LOGE("Failed to create sticker_info table : %s" , err); + ret = STICKERD_SERVER_ERROR_DB_FAILED; + goto cleanup; + } + + ret = sqlite3_exec(db, STICKER_KEYWORD_INFO_CREATE_TABLE, NULL, NULL, &err); + if (ret != SQLITE_OK) { + LOGE("Failed to create sticker_keyword_info table : %s", err); + ret = STICKERD_SERVER_ERROR_DB_FAILED; + goto cleanup; + } + + ret = sqlite3_exec(db, "PRAGMA journal_mode = WAL", NULL, NULL, &err); + if (ret != SQLITE_OK) { + LOGE("Failed to set journal_mode : %s", err); + ret = STICKERD_SERVER_ERROR_DB_FAILED; + goto cleanup; + } + + ret = sqlite3_exec(db, "PRAGMA integrity_check", _integrity_check_cb, NULL, &err); + if (ret != SQLITE_OK) { + LOGE("Failed to check integrity : %s", err); + ret = STICKERD_SERVER_ERROR_DB_FAILED; + } + +cleanup: + if (err) + sqlite3_free(err); + + if (db) + sqlite3_close(db); + + if (ret == SQLITE_CORRUPT || ret == SQLITE_NOTADB || is_corrupted) + ret = _recover_db(); + + return ret; +} + +static sqlite3 *_db_open(void) +{ + int ret; + sqlite3 *db = NULL; + char *err = NULL; + + ret = sqlite3_open(STICKER_DB_PATH, &db); + if (ret != SQLITE_OK) { + LOGE("Failed to open db : %s", sqlite3_errmsg(db)); + return NULL; + } + + ret = sqlite3_exec(db, "PRAGMA foreign_keys = ON", NULL, NULL, &err); + if (ret != SQLITE_OK) { + LOGE("Failed to turn on foreign keys : %s", err); + } + + return db; +} + +int stickerd_db_insert_sticker_info(int *record_id, sticker_info_db *sticker_info) +{ + int ret; + sqlite3 *db = NULL; + sqlite3_stmt *stmt = NULL; + + db = _db_open(); + if (!db) + return STICKERD_SERVER_ERROR_DB_FAILED; + + ret = sqlite3_prepare_v2(db, STICKER_DB_INSERT_STICKER_INFO, -1, &stmt, NULL); + if (ret != SQLITE_OK) { + LOGE("fail to insert sticker information : %s", sqlite3_errmsg(db)); + goto cleanup; + } + + sqlite3_bind_text(stmt, 1, sticker_info->app_id, -1, SQLITE_TRANSIENT); + sqlite3_bind_int(stmt, 2, sticker_info->type); + sqlite3_bind_text(stmt, 3, sticker_info->uri, -1, SQLITE_TRANSIENT); + sqlite3_bind_text(stmt, 4, sticker_info->thumbnail, -1, SQLITE_TRANSIENT); + sqlite3_bind_text(stmt, 5, sticker_info->description, -1, SQLITE_TRANSIENT); + sqlite3_bind_text(stmt, 6, sticker_info->group, -1, SQLITE_TRANSIENT); + + ret = sqlite3_step(stmt); + if (ret != SQLITE_OK && ret != SQLITE_DONE) { + LOGE("sqlite3_step() failed : ret(%d)", ret); + goto cleanup; + } else if (sqlite3_changes(db) == 0) { + LOGE("No changes to DB"); + goto cleanup; + } + + sqlite3_finalize(stmt); + stmt = NULL; + + ret = sqlite3_prepare_v2(db, STICKER_DB_GET_LATEST_RECORD_ID, -1, &stmt, NULL); + if (ret != SQLITE_OK) { + LOGE("fail to get sticker id : %s", sqlite3_errmsg(db)); + goto cleanup; + } + + ret = sqlite3_step(stmt); + if (ret == SQLITE_ERROR) { + LOGE("sqlite3_step() failed : ret(%d)", ret); + *record_id = 0; + goto cleanup; + } else { + *record_id = sqlite3_column_int(stmt, 0); + LOGD("record_id : %d", *record_id); + } + + GList *list; + for(list = sticker_info->keyword; list != NULL; list=list->next) { + sqlite3_finalize(stmt); + stmt = NULL; + + ret = sqlite3_prepare_v2(db, STICKER_DB_INSERT_STICKER_KEYWORD_INFO, -1, &stmt, NULL); + if (ret != SQLITE_OK) { + LOGE("fail to insert sticker keyword : %s", sqlite3_errmsg(db)); + goto cleanup; + } + + sqlite3_bind_int(stmt, 1, *record_id); + sqlite3_bind_text(stmt, 2, (char *)list->data, -1, SQLITE_TRANSIENT); + + ret = sqlite3_step(stmt); + if (ret != SQLITE_OK && ret != SQLITE_DONE) { + LOGE("sqlite3_step() failed : ret(%d)", ret); + goto cleanup; + } else if (sqlite3_changes(db) == 0) { + LOGE("No changes to DB"); + goto cleanup; + } + } + + sqlite3_finalize(stmt); + sqlite3_close(db); + + return STICKERD_SERVER_ERROR_NONE; + +cleanup: + sqlite3_finalize(stmt); + sqlite3_close(db); + + return STICKERD_SERVER_ERROR_DB_FAILED; +} + +int stickerd_db_delete_sticker_info(int record_id) +{ + int ret; + sqlite3 *db = NULL; + sqlite3_stmt *stmt = NULL; + + db = _db_open(); + if (!db) + return STICKERD_SERVER_ERROR_DB_FAILED; + + ret = sqlite3_prepare_v2(db, STICKER_DB_DELETE_STICKER_INFO, -1, &stmt, NULL); + if (ret != SQLITE_OK) { + LOGE("fail to delete sticker information : %s", sqlite3_errmsg(db)); + goto cleanup; + } + + sqlite3_bind_int(stmt, 1, record_id); + + ret = sqlite3_step(stmt); + if (ret != SQLITE_OK && ret != SQLITE_DONE) { + LOGE("sqlite3_step() failed : ret(%d)", ret); + goto cleanup; + } else if (sqlite3_changes(db) == 0) { + LOGE("No changes to DB"); + goto cleanup; + } + + sqlite3_finalize(stmt); + sqlite3_close(db); + + return STICKERD_SERVER_ERROR_NONE; + +cleanup: + sqlite3_finalize(stmt); + sqlite3_close(db); + + return STICKERD_SERVER_ERROR_DB_FAILED; +} + +int stickerd_db_update_sticker_info(int record_id, sticker_info_db_type type, void *data) +{ + int ret; + sqlite3 *db = NULL; + sqlite3_stmt *stmt = NULL; + + db = _db_open(); + if (!db) + return STICKERD_SERVER_ERROR_DB_FAILED; + + const char* query = _db_get_query(type, CMD_UPDATE); + ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL); + if (ret != SQLITE_OK) { + LOGE("fail to update sticker information : %s", sqlite3_errmsg(db)); + goto cleanup; + } + + if (type == STICKER_DB_STICKER_TYPE) { + sqlite3_bind_int(stmt, 1, *(int *)data); + } else if (type == STICKER_DB_STICKER_KEYWORD) { + sqlite3_bind_int(stmt, 1, record_id); + } else { + sqlite3_bind_text(stmt, 1, (char *)data, -1, SQLITE_TRANSIENT); + } + + if (type != STICKER_DB_STICKER_KEYWORD) + sqlite3_bind_int(stmt, 2, record_id); + + ret = sqlite3_step(stmt); + if (ret != SQLITE_OK && ret != SQLITE_DONE) { + LOGE("sqlite3_step() failed : ret(%d)", ret); + goto cleanup; + } + + if (type == STICKER_DB_STICKER_KEYWORD) { + GList *list; + for(list = (GList *)data; list != NULL; list=list->next) { + sqlite3_finalize(stmt); + stmt = NULL; + + ret = sqlite3_prepare_v2(db, STICKER_DB_INSERT_STICKER_KEYWORD_INFO, -1, &stmt, NULL); + if (ret != SQLITE_OK) { + LOGE("fail to insert sticker information : %s", sqlite3_errmsg(db)); + goto cleanup; + } + + sqlite3_bind_int(stmt, 1, record_id); + sqlite3_bind_text(stmt, 2, (char *)list->data, -1, SQLITE_TRANSIENT); + + ret = sqlite3_step(stmt); + if (ret != SQLITE_OK && ret != SQLITE_DONE) { + LOGE("sqlite3_step() failed : ret(%d)", ret); + goto cleanup; + } else if (sqlite3_changes(db) == 0) { + LOGE("No changes to DB"); + goto cleanup; + } + } + } + + sqlite3_finalize(stmt); + sqlite3_close(db); + + return STICKERD_SERVER_ERROR_NONE; + +cleanup: + sqlite3_finalize(stmt); + sqlite3_close(db); + + return STICKERD_SERVER_ERROR_DB_FAILED; +} + +int stickerd_db_get_sticker_info_by_record_id(int record_id, sticker_info_db *sticker_info) +{ + int ret; + sqlite3 *db = NULL; + sqlite3_stmt *stmt = NULL; + + db = _db_open(); + if (!db) + return STICKERD_SERVER_ERROR_DB_FAILED; + + ret = sqlite3_prepare_v2(db, STICKER_DB_GET_STICKER_INFO_BY_RECORD_ID, -1, &stmt, NULL); + if (ret != SQLITE_OK) { + LOGE("fail to get sticker information : %s", sqlite3_errmsg(db)); + goto cleanup; + } + + sqlite3_bind_int(stmt, 1, record_id); + + ret = sqlite3_step(stmt); + if (ret == SQLITE_ERROR) { + LOGE("sqlite3_step() failed : ret(%d)", ret); + goto cleanup; + } + + const unsigned char *tmp_app_id = sqlite3_column_text(stmt, 1); + if (tmp_app_id) { + sticker_info->app_id = strdup((const char *)tmp_app_id); + } else { + LOGW("invalid record_id : %d", record_id); + goto cleanup; + } + + sticker_info->type = sqlite3_column_int(stmt, 2); + + const unsigned char *tmp_uri = sqlite3_column_text(stmt, 3); + if (tmp_uri) + sticker_info->uri = strdup((const char *)tmp_uri); + + const unsigned char *tmp_thumbnail = sqlite3_column_text(stmt, 4); + if (tmp_thumbnail) + sticker_info->thumbnail = strdup((const char *)tmp_thumbnail); + + const unsigned char *tmp_description = sqlite3_column_text(stmt, 5); + if (tmp_description) + sticker_info->description = strdup((const char *)tmp_description); + + const unsigned char *tmp_group = sqlite3_column_text(stmt, 6); + if (tmp_group) + sticker_info->group = strdup((const char *)tmp_group); + + const unsigned char *tmp_date = sqlite3_column_text(stmt, 7); + if (tmp_date) + sticker_info->date = strdup((const char *)tmp_date); + + sqlite3_finalize(stmt); + stmt = NULL; + + ret = sqlite3_prepare_v2(db, STICKER_DB_GET_KEYWORD_INFO_BY_RECORD_ID, -1, &stmt, NULL); + if (ret != SQLITE_OK) { + LOGE("fail to get sticker keyword : %s", sqlite3_errmsg(db)); + goto cleanup; + } + + sqlite3_bind_int(stmt, 1, record_id); + + while (sqlite3_step(stmt) == SQLITE_ROW) { + const unsigned char *keyword = sqlite3_column_text(stmt, 0); + if (keyword) + sticker_info->keyword = g_list_append(sticker_info->keyword, strdup((const char *)keyword)); + } + + sqlite3_finalize(stmt); + sqlite3_close(db); + + return STICKERD_SERVER_ERROR_NONE; + +cleanup: + sqlite3_finalize(stmt); + sqlite3_close(db); + + return STICKERD_SERVER_ERROR_DB_FAILED; +} + +int stickerd_db_get_group_list(GVariantBuilder *builder) +{ + int ret; + sqlite3 *db = NULL; + sqlite3_stmt *stmt = NULL; + + db = _db_open(); + if (!db) + return STICKERD_SERVER_ERROR_DB_FAILED; + + ret = sqlite3_prepare_v2(db, STICKER_DB_GET_ALL_GROUP_LIST, -1, &stmt, NULL); + if (ret != SQLITE_OK) { + LOGE("fail to get group list : %s", sqlite3_errmsg(db)); + goto cleanup; + } + + while (sqlite3_step(stmt) == SQLITE_ROW) { + const unsigned char *group = sqlite3_column_text(stmt, 0); + if (group) + g_variant_builder_add(builder, "(s)", strdup((const char *)group)); + } + + sqlite3_finalize(stmt); + sqlite3_close(db); + + return STICKERD_SERVER_ERROR_NONE; + +cleanup: + sqlite3_finalize(stmt); + sqlite3_close(db); + + return STICKERD_SERVER_ERROR_DB_FAILED; +} + +int stickerd_db_get_keyword_list(GVariantBuilder *builder) +{ + int ret; + sqlite3 *db = NULL; + sqlite3_stmt *stmt = NULL; + + db = _db_open(); + if (!db) + return STICKERD_SERVER_ERROR_DB_FAILED; + + ret = sqlite3_prepare_v2(db, STICKER_DB_GET_ALL_KEYWORD_LIST, -1, &stmt, NULL); + if (ret != SQLITE_OK) { + LOGE("fail to get keyword list : %s", sqlite3_errmsg(db)); + goto cleanup; + } + + while (sqlite3_step(stmt) == SQLITE_ROW) { + const unsigned char *keyword = sqlite3_column_text(stmt, 0); + if (keyword) + g_variant_builder_add(builder, "(s)", strdup((const char *)keyword)); + } + + sqlite3_finalize(stmt); + sqlite3_close(db); + + return STICKERD_SERVER_ERROR_NONE; + +cleanup: + sqlite3_finalize(stmt); + sqlite3_close(db); + + return STICKERD_SERVER_ERROR_DB_FAILED; +} + +int stickerd_db_get_sticker_count(int *count, char *app_id) +{ + int ret; + sqlite3 *db = NULL; + sqlite3_stmt *stmt = NULL; + + db = _db_open(); + if (!db) + return STICKERD_SERVER_ERROR_DB_FAILED; + + ret = sqlite3_prepare_v2(db, STICKER_DB_GET_STICKER_COUNT, -1, &stmt, NULL); + if (ret != SQLITE_OK) { + LOGE("fail to get sticker count : %s", sqlite3_errmsg(db)); + goto cleanup; + } + + sqlite3_bind_text(stmt, 1, app_id, -1, SQLITE_TRANSIENT); + + ret = sqlite3_step(stmt); + if (ret == SQLITE_ERROR) { + LOGE("sqlite3_step() failed : ret(%d)", ret); + goto cleanup; + } + + *count = sqlite3_column_int(stmt, 0); + + sqlite3_finalize(stmt); + sqlite3_close(db); + + return STICKERD_SERVER_ERROR_NONE; + +cleanup: + sqlite3_finalize(stmt); + sqlite3_close(db); + + return STICKERD_SERVER_ERROR_DB_FAILED; +} + +int stickerd_db_get_record_id(sticker_info_db_type type, GList **id_list, void *data, int offset, int count) +{ + int ret; + sqlite3 *db = NULL; + sqlite3_stmt *stmt = NULL; + + db = _db_open(); + if (!db) + return STICKERD_SERVER_ERROR_DB_FAILED; + + const char* query = _db_get_query(type, CMD_SELECT); + ret = sqlite3_prepare_v2(db, query, -1, &stmt, NULL); + if (ret != SQLITE_OK) { + LOGE("fail to get record id : %s", sqlite3_errmsg(db)); + goto cleanup; + } + + if (type == STICKER_DB_STICKER_TYPE) + sqlite3_bind_int(stmt, 1, *(int *)data); + else if (type != STICKER_DB_STICKER_ALL) + sqlite3_bind_text(stmt, 1, (char *)data, -1, SQLITE_TRANSIENT); + + if (type == STICKER_DB_STICKER_ALL) { + sqlite3_bind_int(stmt, 1, offset); + sqlite3_bind_int(stmt, 2, count); + } else { + sqlite3_bind_int(stmt, 2, offset); + sqlite3_bind_int(stmt, 3, count); + } + + while (sqlite3_step(stmt) == SQLITE_ROW) { + const unsigned char *tmp_id = sqlite3_column_text(stmt, 0); + if (tmp_id) + *id_list = g_list_append(*id_list, strdup((const char *)tmp_id)); + } + + sqlite3_finalize(stmt); + sqlite3_close(db); + + return STICKERD_SERVER_ERROR_NONE; + +cleanup: + sqlite3_finalize(stmt); + sqlite3_close(db); + + return STICKERD_SERVER_ERROR_DB_FAILED; +} \ No newline at end of file diff --git a/server/stickerd_db_manager.h b/server/stickerd_db_manager.h new file mode 100644 index 0000000..6e6ebb5 --- /dev/null +++ b/server/stickerd_db_manager.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_UIX_STICKERD_DB_MANAGER_H__ +#define __TIZEN_UIX_STICKERD_DB_MANAGER_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + STICKER_DB_STICKER_ALL, + STICKER_DB_STICKER_APPID, + STICKER_DB_STICKER_TYPE, + STICKER_DB_STICKER_URI, + STICKER_DB_STICKER_THUMBNAIL, + STICKER_DB_STICKER_DESCRIPTION, + STICKER_DB_STICKER_GROUP, + STICKER_DB_STICKER_KEYWORD, +} sticker_info_db_type; + +typedef struct { + char *app_id; + int type; + char *uri; + char *thumbnail; + char *description; + char *group; + GList *keyword; + char *date; +} sticker_info_db; + +int stickerd_db_init(void); +int stickerd_db_insert_sticker_info(int *record_id, sticker_info_db *sticker_info); +int stickerd_db_delete_sticker_info(int record_id); +int stickerd_db_update_sticker_info(int record_id, sticker_info_db_type type, void *data); +int stickerd_db_get_sticker_info_by_record_id(int record_id, sticker_info_db *sticker_info); +int stickerd_db_get_group_list(GVariantBuilder *builder); +int stickerd_db_get_keyword_list(GVariantBuilder *builder); +int stickerd_db_get_sticker_count(int *count, char *app_id); +int stickerd_db_get_record_id(sticker_info_db_type type, GList **id_list, void *data, int offset, int count); + +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_UIX_STICKERD_DB_MANAGER_H__ */ \ No newline at end of file diff --git a/server/stickerd_dbus.c b/server/stickerd_dbus.c new file mode 100644 index 0000000..4ff175a --- /dev/null +++ b/server/stickerd_dbus.c @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include + +#include "stickerd_dbus.h" +#include "stickerd_error.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "STICKERD_DBUS" + +static GDBusConnection *_gdbus_connection; + +int stickerd_server_register(GVariant *parameters, GVariant **reply_body, const gchar *sender, GBusNameAppearedCallback name_appeared_handler, + GBusNameVanishedCallback name_vanished_handler, GHashTable **monitoring_hash) +{ + GList *sender_list = NULL; + const char *bus_name = sender; + monitoring_info_s *m_info = NULL; + uid_t request_uid = 0; + GList *monitoring_list = NULL; + + if (bus_name == NULL) + return STICKERD_SERVER_ERROR_IO_ERROR; + + g_variant_get(parameters, "(i)", &request_uid); + monitoring_list = (GList *)g_hash_table_lookup(*monitoring_hash, GUINT_TO_POINTER(request_uid)); + sender_list = g_list_find_custom(monitoring_list, bus_name, (GCompareFunc) strcmp); + + if (sender_list == NULL) { + LOGD("Add a new sender"); + m_info = (monitoring_info_s *)calloc(1, sizeof(monitoring_info_s)); + if (m_info == NULL) { + LOGE("Failed to alloc memory"); + return STICKERD_SERVER_ERROR_IO_ERROR; + } + + m_info->bus_name = strdup(bus_name); + m_info->uid = request_uid; + m_info->watcher_id = g_bus_watch_name_on_connection( + _gdbus_connection, + bus_name, + G_BUS_NAME_WATCHER_FLAGS_NONE, + name_appeared_handler, + name_vanished_handler, + m_info, + NULL); + if (m_info->watcher_id == 0) { + LOGE("Failed to get identifier"); + free(m_info->bus_name); + free(m_info); + return STICKERD_SERVER_ERROR_IO_ERROR; + } + + monitoring_list = g_list_append(monitoring_list, strdup(bus_name)); + LOGD("sender: %s, len: %d", sender, g_list_length(monitoring_list)); + if (g_hash_table_lookup(*monitoring_hash, GUINT_TO_POINTER(request_uid)) == NULL) + g_hash_table_insert(*monitoring_hash, GUINT_TO_POINTER(request_uid), monitoring_list); + } else { + LOGW("Sender(%s) already exist", sender); + } + + *reply_body = g_variant_new("()"); + if (*reply_body == NULL) { + if (m_info) { + if (m_info->bus_name) + free(m_info->bus_name); + free(m_info); + } + monitoring_list = g_list_remove(monitoring_list, bus_name); + LOGE("Failed to make reply"); + return STICKERD_SERVER_ERROR_OUT_OF_MEMORY; + } + return STICKERD_SERVER_ERROR_NONE; +} + +int stickerd_server_register_dbus_interface(char *introspection_xml, GDBusInterfaceVTable interface_vtable) +{ + int result; + int own_id, registration_id; + GError *error = NULL; + GDBusNodeInfo *introspection_data = NULL; + + if (_gdbus_connection == NULL) { + _gdbus_connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (_gdbus_connection == NULL) { + if (error != NULL) { + LOGE("g_bus_get_sync error message = %s", error->message); + g_error_free(error); + } + result = STICKERD_SERVER_ERROR_IO_ERROR; + goto cleanup; + } + } + + own_id = g_bus_own_name(G_BUS_TYPE_SYSTEM, + STICKER_DBUS_NAME, + G_BUS_NAME_OWNER_FLAGS_NONE, + NULL, + NULL, + NULL, + NULL, NULL); + if (own_id == 0) { + LOGE("Failed to register bus name"); + result = STICKERD_SERVER_ERROR_IO_ERROR; + goto cleanup; + } + + LOGD("own_id = %d", own_id); + + introspection_data = g_dbus_node_info_new_for_xml(introspection_xml, &error); + if (introspection_data == NULL) { + LOGE("Failed to get GDBusNodeInfo"); + result = STICKERD_SERVER_ERROR_IO_ERROR; + if (error != NULL) { + LOGE("g_dbus_node_info_new_for_xml error message = %s", error->message); + g_error_free(error); + } + goto cleanup; + } + + registration_id = g_dbus_connection_register_object(_gdbus_connection, STICKER_OBJECT_PATH, + introspection_data->interfaces[0], &interface_vtable, NULL, NULL, NULL); + LOGD("registration_id = %d", registration_id); + if (registration_id == 0) { + LOGE("Failed to register object"); + result = STICKERD_SERVER_ERROR_IO_ERROR; + goto cleanup; + } + + return STICKERD_SERVER_ERROR_NONE; + +cleanup: + if (introspection_data) + g_dbus_node_info_unref(introspection_data); + + return result; +} + +int delete_monitoring_list(GHashTable **monitoring_hash, const char *sender, uid_t uid) +{ + GList *monitoring_list = NULL; + GList *del_list = NULL; + char *bus_name; + + monitoring_list = (GList *)g_hash_table_lookup(*monitoring_hash, GUINT_TO_POINTER(uid)); + if (monitoring_list == NULL) { + LOGE("The key(%d) is not found", uid); + return STICKERD_SERVER_ERROR_IO_ERROR; + } + + monitoring_list = g_list_first(monitoring_list); + del_list = g_list_find_custom(monitoring_list, sender, (GCompareFunc) strcmp); + + if (del_list) { + LOGD("Delete sender(%s)", sender); + bus_name = g_list_nth_data(del_list, 0); + if (bus_name) + free(bus_name); + monitoring_list = g_list_delete_link(monitoring_list, del_list); + + if (monitoring_list == NULL) { + g_hash_table_steal(*monitoring_hash, GUINT_TO_POINTER(uid)); + } else { + monitoring_list = g_list_first(monitoring_list); + g_hash_table_replace(*monitoring_hash, GUINT_TO_POINTER(uid), monitoring_list); + } + } + return STICKERD_SERVER_ERROR_NONE; +} + +int stickerd_send_dbus_message(GVariant *body, const char *dest, char *cmd, CLIENT_LIB lib) +{ + GError *err = NULL; + char *interface = NULL; + + if (lib == STICKER_CLIENT_LIB_PROVIDER) + interface = STICKER_PROVIDER_INTERFACE_NAME; + else if (lib == STICKER_CLIENT_LIB_CONSUMER) + interface = STICKER_CONSUMER_INTERFACE_NAME; + + if (g_variant_is_floating(body)) + g_variant_ref(body); + + if (!g_dbus_connection_emit_signal(_gdbus_connection, + dest, + STICKER_OBJECT_PATH, + interface, + cmd, + body, + &err)) { + if (err != NULL) { + LOGE("Failed to send dbus message : %s", err->message); + g_error_free(err); + } + + return STICKERD_SERVER_ERROR_IO_ERROR; + } + + LOGD("Send message to client : %s", cmd); + return STICKERD_SERVER_ERROR_NONE; +} \ No newline at end of file diff --git a/server/stickerd_dbus.h b/server/stickerd_dbus.h new file mode 100644 index 0000000..0197793 --- /dev/null +++ b/server/stickerd_dbus.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_UIX_STICKERD_DBUS_H__ +#define __TIZEN_UIX_STICKERD_DBUS_H__ + +#include +#include +#include "sticker_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct monitoring_info { + int watcher_id; + char *bus_name; + uid_t uid; +} monitoring_info_s; + +int stickerd_server_register(GVariant *parameters, GVariant **reply_body, const gchar *sender, GBusNameAppearedCallback name_appeared_handler, + GBusNameVanishedCallback name_vanished_handler, GHashTable **monitoring_hash); +int stickerd_server_unregister(GVariant *parameters, GVariant **reply_body, const gchar *sender, GHashTable **monitoring_hash); +int stickerd_server_register_dbus_interface(char *introspection_xml, GDBusInterfaceVTable interface_vtable); +int delete_monitoring_list(GHashTable **monitoring_hash, const char *sender, uid_t uid); +int stickerd_send_dbus_message(GVariant *body, const char *dest, char *cmd, CLIENT_LIB lib); + +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_UIX_STICKERD_DBUS_H__ */ \ No newline at end of file diff --git a/server/stickerd_error.h b/server/stickerd_error.h new file mode 100644 index 0000000..2afea16 --- /dev/null +++ b/server/stickerd_error.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __TIZEN_UIX_STICKERD_ERROR_H__ +#define __TIZEN_UIX_STICKERD_ERROR_H__ + +/** + * @file sticker_error.h + * @brief This file contains sticker error enumeration. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Enumeration for sticker server error. + */ +enum stickerd_server_error { + STICKERD_SERVER_ERROR_NONE, + STICKERD_SERVER_ERROR_IO_ERROR, + STICKERD_SERVER_ERROR_INVALID_PARAMETER, + STICKERD_SERVER_ERROR_PERMISSION_DENIED, + STICKERD_SERVER_ERROR_OUT_OF_MEMORY, + STICKERD_SERVER_ERROR_SERVICE_NOT_READY, + STICKERD_SERVER_ERROR_OPERATION_FAILED, + STICKERD_SERVER_ERROR_DB_FAILED, +}; + +/** + * @} + */ +#ifdef __cplusplus +} +#endif + +#endif /* __TIZEN_UIX_STICKERD_ERROR_H__ */ \ No newline at end of file diff --git a/server/stickerd_main.c b/server/stickerd_main.c new file mode 100644 index 0000000..1650437 --- /dev/null +++ b/server/stickerd_main.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "stickerd_data_manager.h" +#include "stickerd_db_manager.h" +#include "stickerd_error.h" + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "STICKERD_MAIN" + +#define MAX_ERROR_BUFFER 256 + +static GMainLoop *main_loop; +static GIOChannel *channel = NULL; +static guint source = 0; + +static gboolean signal_handler(GIOChannel *channel, GIOCondition condition, gpointer user_data) +{ + struct signalfd_siginfo fd_signal; + ssize_t size; + int sfd; + + sfd = g_io_channel_unix_get_fd(channel); + size = read(sfd, &fd_signal, sizeof(struct signalfd_siginfo)); + if (size != sizeof(struct signalfd_siginfo)) { + LOGE("Failed to read signal"); + return TRUE; + } + + LOGE("sender : %d, signal : %d", fd_signal.ssi_pid, fd_signal.ssi_signo); + g_main_loop_quit(main_loop); + + return TRUE; +} + +static void register_signal_handler() +{ + sigset_t mask; + int sfd; + int ret; + char error_buffer[MAX_ERROR_BUFFER]; + + ret = sigemptyset(&mask); + if (ret < 0) { + strerror_r(errno, error_buffer, MAX_ERROR_BUFFER); + LOGE("sigemptyset(): %s", error_buffer); + } + + ret = sigaddset(&mask, SIGTERM); + if (ret < 0) { + strerror_r(errno, error_buffer, MAX_ERROR_BUFFER); + LOGE("sigaddset(): %s", error_buffer); + } + + ret = sigprocmask(SIG_BLOCK, &mask, NULL); + if (ret < 0) { + strerror_r(errno, error_buffer, MAX_ERROR_BUFFER); + LOGE("sigprocmask(): %s", error_buffer); + } + + sfd = signalfd(-1, &mask, SFD_NONBLOCK); + if (sfd < 0) { + strerror_r(errno, error_buffer, MAX_ERROR_BUFFER); + LOGE("signalfd(): %s", error_buffer); + } + + channel = g_io_channel_unix_new(sfd); + g_io_channel_set_close_on_unref(channel, TRUE); + g_io_channel_set_encoding(channel, NULL, NULL); + g_io_channel_set_buffered(channel, FALSE); + source = g_io_add_watch(channel, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_OUT, signal_handler, NULL); + LOGD("source : %u", source); +} + +static void unregister_signal_handler() +{ + if (source > 0) + g_source_remove(source); + if (channel) + g_io_channel_unref(channel); +} + +int main(int argc, char** argv) +{ + int ret; + main_loop = g_main_loop_new(NULL, FALSE); + if (main_loop == NULL) { + LOGE("Failed to create GMainLoop structure"); + return -1; + } + + ret = stickerd_dbus_init(); + if (ret != STICKERD_SERVER_ERROR_NONE) + LOGW("Failed to init dbus"); + + ret = stickerd_db_init(); + if (ret != STICKERD_SERVER_ERROR_NONE) + LOGW("Failed to init database"); + + register_signal_handler(); + + g_main_loop_run(main_loop); + + unregister_signal_handler(); + + g_main_loop_unref(main_loop); + + return 0; +} diff --git a/sticker-parser/CMakeLists.txt b/sticker-parser/CMakeLists.txt new file mode 100644 index 0000000..c27f790 --- /dev/null +++ b/sticker-parser/CMakeLists.txt @@ -0,0 +1,30 @@ +pkg_check_modules(parser-pkgs REQUIRED + capi-base-common + dlog + glib-2.0 + json-glib-1.0 + pkgmgr-info + libtzplatform-config + capi-appfw-package-manager + sqlite3 +) + +SET(SRCS + sticker-parser.c +) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wall" ) +SET(extapi "-fvisibility=hidden") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} ${extapi}") +SET(CMAKE_SHARED_LINKER_FLAGS "-Wl,--as-needed") + +## Create Library +ADD_LIBRARY ("${PROJECT_NAME}-parser" SHARED ${SRCS}) +TARGET_LINK_LIBRARIES("${PROJECT_NAME}-parser" ${parser-pkgs_LDFLAGS} ) + +INSTALL(TARGETS ${PROJECT_NAME}-parser DESTINATION "/etc/package-manager/parserlib/category") +INSTALL(TARGETS ${PROJECT_NAME}-parser DESTINATION "/etc/package-manager/parserlib/metadata") diff --git a/sticker-parser/sticker-parser.c b/sticker-parser/sticker-parser.c new file mode 100644 index 0000000..dc27241 --- /dev/null +++ b/sticker-parser/sticker-parser.c @@ -0,0 +1,792 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef EXPORT_API +#define EXPORT_API __attribute__((visibility("default"))) +#endif + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "STICKER_PARSER" + +#define STICKER_DIRECTORY tzplatform_mkpath(TZ_SYS_SHARE, "sticker-data") +#define UIFW_ID 502 +#define APPFW_ID 301 +#define MAX_ERROR_BUFFER 256 + +static char error_buffer[MAX_ERROR_BUFFER]; + +typedef struct metadata { + const char *key; + const char *value; +} metadata; + +static char* __get_string_from_object(JsonObject *object, const char *key) +{ + if (json_object_has_member(object, key) == false) + return NULL; + + const char *str = json_object_get_string_member(object, key); + if (str != NULL) + return strdup(str); + else + return NULL; +} + +static int __get_int_from_object(JsonObject *object, const char *key) +{ + if (json_object_has_member(object, key) == false) + return -1; + + int type = json_object_get_int_member(object, key); + + return type; +} + +static sqlite3 *__db_open(const char *path) +{ + int ret; + sqlite3 *db = NULL; + char *err = NULL; + + ret = sqlite3_open(path, &db); + if (ret != SQLITE_OK) { + LOGE("Failed to open db : %s", sqlite3_errmsg(db)); + return NULL; + } + + ret = sqlite3_exec(db, "PRAGMA foreign_keys = ON", NULL, NULL, &err); + if (ret != SQLITE_OK) { + LOGE("Failed to turn on foreign keys : %s", err); + } + + return db; +} + +static int __change_ownership(const char *path, int user, int group) +{ + int ret; + uid_t uid = (uid_t)user; + gid_t gid = (gid_t)group; + + ret = chown(path, uid, gid); + if (ret != 0) { + strerror_r(errno, error_buffer, MAX_ERROR_BUFFER); + LOGE("chown() failed : %s", error_buffer); + } + + return ret; +} + +static int __remove_app_path(char *uri, const char *app_path) +{ + int n = 0; + int k = 0; + for (int i = 0; uri[i] != '\0'; i++) { + if (uri[i] == app_path[n]) { + k = i; + while (uri[i] == app_path[n]) { + if (app_path[++n] == '\0') { + for(; uri[k + n] != '\0'; k++) { + uri[k] = uri[k + n]; + } + uri[k] = '\0'; + return 1; + } + i++; + } + n = 0; + i--; + } + } + return 0; +} + +static int __mkdirs(const char *path, mode_t mode) +{ + int len = 0; + char prev_path[2048]; + const char *tmp = path; + + if (!path || strlen(path) > 2048) + return -1; + + memset(prev_path, '\0', 2048); + while ((tmp = strchr(tmp, '/')) != NULL) { + len = tmp - path; + tmp++; + + if (len == 0) + continue; + + strncpy(prev_path, path, len); + prev_path[len] = 0x00; + + if (mkdir(prev_path, mode) == -1) { + if (errno != EEXIST) { + strerror_r(errno, error_buffer, MAX_ERROR_BUFFER); + LOGE("directory create error : %s", error_buffer); + return -1; + } + } else { + if (__change_ownership(prev_path, UIFW_ID, UIFW_ID) != 0) + LOGE("failed to change ownership"); + } + } + + if (mkdir(prev_path, mode) == -1) { + if (errno != EEXIST) { + strerror_r(errno, error_buffer, MAX_ERROR_BUFFER); + LOGE("directory create error : %s", error_buffer); + return -1; + } + } else { + if (__change_ownership(prev_path, UIFW_ID, UIFW_ID) != 0) + LOGE("failed to change ownership"); + } + return 0; +} + +static int __file_copy(const char *src, const char *dest) +{ + int ret = 0; + int fd = -1, n_fd = -1; + char buf[4096]; + int tmp_err = 0; + int size; + + memset(buf, '\0', 4096); + fd = open(src, O_RDONLY); + n_fd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0755); + + if (fd == -1 || n_fd == -1) { + tmp_err = errno; + ret = -1; + goto cleanup; + } + + while((size = read(fd, buf, 4096))) { + if (size == -1) { + if(errno == EINTR) + continue; + + tmp_err = errno; + ret = -1; + goto cleanup; + } + + while(write(n_fd, buf, size) == -1) { + if(errno == EINTR) { + continue; + } else { + tmp_err = errno; + goto cleanup; + } + } + } + +cleanup: + if (fd != -1) + close(fd); + + if (n_fd != -1) + close(n_fd); + + errno = tmp_err; + return ret; +} + +static char* __convert_sticker_uri(const char *uri, const char *appid, const char *app_path) +{ + int ret; + char *rel_path = strdup(uri); + + __remove_app_path(rel_path, app_path); + int len = strlen(STICKER_DIRECTORY) + strlen(appid) + strlen(rel_path) + 2; + char *new_path = (char *)calloc(len, sizeof(char)); + if (new_path == NULL) { + free(rel_path); + rel_path = NULL; + return NULL; + } + + snprintf(new_path, len, "%s/%s%s",STICKER_DIRECTORY, appid, rel_path); + + if (access(new_path, F_OK) == 0) { + LOGE("sticker file already exists"); + ret = -1; + goto cleanup; + } + + ret = __mkdirs(new_path, 0755); + if (ret != 0) { + LOGE("directory create error"); + goto cleanup; + } + + if (__file_copy(uri, new_path) == -1) { + strerror_r(errno, error_buffer, MAX_ERROR_BUFFER); + LOGE("failed to copy sticker file : %s", error_buffer); + ret = -1; + goto cleanup; + } + + ret = unlink(uri); + if (ret != 0) { + strerror_r(errno, error_buffer, MAX_ERROR_BUFFER); + LOGE("failed to remove sticker file : %s", error_buffer); + } + + if (__change_ownership(new_path, UIFW_ID, UIFW_ID) != 0) + LOGE("failed to change ownership"); + +cleanup: + free(rel_path); + rel_path = NULL; + + if (ret == 0) { + return new_path; + } else { + free(new_path); + new_path = NULL; + return NULL; + } +} + +static void __insert_sticker_info(const char *app_id, int type, const char *uri, const char *group, const char *thumbnail, const char *description) +{ + int ret; + sqlite3 *db = NULL; + sqlite3_stmt *stmt = NULL; + const char *db_path; + + db_path = tzplatform_mkpath(TZ_SYS_DB, ".sticker_info.db"); + db = __db_open(db_path); + if (!db) + return; + + ret = sqlite3_prepare_v2(db, "INSERT INTO sticker_info (app_id, type, uri, thumbnail, description, group_name, date) VALUES (?, ?, ?, ?, ?, ?, DateTime('now','localtime'))",-1, &stmt, NULL); + if (ret == SQLITE_OK) { + sqlite3_bind_text(stmt, 1, app_id, -1, SQLITE_TRANSIENT); + sqlite3_bind_int(stmt, 2, type); + sqlite3_bind_text(stmt, 3, uri, -1, SQLITE_TRANSIENT); + sqlite3_bind_text(stmt, 4, thumbnail, -1, SQLITE_TRANSIENT); + sqlite3_bind_text(stmt, 5, description, -1, SQLITE_TRANSIENT); + sqlite3_bind_text(stmt, 6, group, -1, SQLITE_TRANSIENT); + + ret = sqlite3_step(stmt); + if (ret != SQLITE_OK && ret != SQLITE_DONE) + LOGE("sqlite3_step() failed : ret(%d)", ret); + + if (sqlite3_changes(db) == 0) + LOGE("No changes to DB"); + + sqlite3_finalize(stmt); + sqlite3_close(db); + } else { + LOGE("failed to insert sticker information : %s", sqlite3_errmsg(db)); + sqlite3_finalize(stmt); + sqlite3_close(db); + } + + return; +} + +static void __insert_sticker_keyword_info(const char *keyword) +{ + int ret; + int record_id; + sqlite3 *db = NULL; + sqlite3_stmt *stmt = NULL; + const char *db_path; + + db_path = tzplatform_mkpath(TZ_SYS_DB, ".sticker_info.db"); + db = __db_open(db_path); + if (!db) + return; + + ret = sqlite3_prepare_v2(db, "SELECT sticker_info_id FROM sticker_info ORDER BY sticker_info_id DESC LIMIT 1", -1, &stmt, NULL); + if (ret == SQLITE_OK) { + ret = sqlite3_step(stmt); + if (ret == SQLITE_ERROR) { + LOGE("sqlite3_step() failed : ret(%d)", ret); + sqlite3_finalize(stmt); + sqlite3_close(db); + } else { + record_id = sqlite3_column_int(stmt, 0); + + sqlite3_finalize(stmt); + stmt = NULL; + + ret = sqlite3_prepare_v2(db, "INSERT INTO sticker_keyword_info (sticker_info_id, keyword) VALUES (?, ?)", -1, &stmt, NULL); + if (ret == SQLITE_OK) { + sqlite3_bind_int(stmt, 1, record_id); + sqlite3_bind_text(stmt, 2, keyword, -1, SQLITE_TRANSIENT); + + ret = sqlite3_step(stmt); + if (ret != SQLITE_OK && ret != SQLITE_DONE) + LOGE("sqlite3_step() failed : ret(%d)", ret); + + if (sqlite3_changes(db) == 0) + LOGE("No changes to DB"); + + sqlite3_finalize(stmt); + sqlite3_close(db); + } else { + LOGE("fail to insert sticker keyword : %s", sqlite3_errmsg(db)); + sqlite3_finalize(stmt); + sqlite3_close(db); + } + } + } else { + LOGE("fail to insert sticker information : %s", sqlite3_errmsg(db)); + sqlite3_finalize(stmt); + sqlite3_close(db); + } + + return; +} + +static int __get_sticker_info_from_json(const char *appid, const char *file_path, const char *app_path) +{ + int ret = 1; + JsonParser* parser = NULL; + GError* err_msg = NULL; + char *uri = NULL; + char *group = NULL; + char *description = NULL; + char *thumbnail = NULL; + char *uri_path = NULL; + + parser = json_parser_new(); + json_parser_load_from_file(parser, file_path, &err_msg); + if (err_msg) { + LOGE("failed to load json file. error message: %s", err_msg->message); + ret = 0; + goto cleanup; + } + + JsonNode *root = json_parser_get_root(parser); + if (root == NULL) { + LOGE("failed to get root"); + ret = 0; + goto cleanup; + } + + JsonObject *root_obj = json_node_get_object(root); + if (root_obj == NULL) { + LOGE("failed to get object"); + ret = 0; + goto cleanup; + } + + JsonArray *sticker_arr = json_object_get_array_member(root_obj, "sticker"); + if (sticker_arr == NULL) { + LOGE("failed to get array member"); + ret = 0; + goto cleanup; + } + + int arr_len = json_array_get_length(sticker_arr); + for (int i = 0; i < arr_len; i++) { + JsonObject *info_object = json_array_get_object_element(sticker_arr, i); + if (info_object != NULL) { + int type = __get_int_from_object(info_object, "type"); + if (type < 1) + continue; + + uri = __get_string_from_object(info_object, "uri"); + if (!uri) + goto free_memory; + + group = __get_string_from_object(info_object, "group"); + if (!group) + goto free_memory; + + thumbnail = __get_string_from_object(info_object, "thumbnail"); + description = __get_string_from_object(info_object, "description"); + + JsonArray *keyword_arr = json_object_get_array_member(info_object, "keyword"); + int keyword_arr_len = json_array_get_length(keyword_arr); + if (keyword_arr_len < 1) + goto free_memory; + + if (type == 1) { + if (access(uri, F_OK) == 0) { + char *new_uri = __convert_sticker_uri(uri, appid, app_path); + if (!new_uri) + goto free_memory; + __insert_sticker_info(appid, type, new_uri, group, thumbnail, description); + + if (new_uri) { + free(new_uri); + new_uri = NULL; + } + } else { + int path_len = strlen(app_path) + strlen(uri) + 2; + uri_path = (char *)calloc(path_len, sizeof(char)); + if (!uri_path) { + LOGE("failed to alloc memory"); + goto free_memory; + } + + if (uri[0] == '/') + snprintf(uri_path, path_len, "%s%s",app_path, uri); + else + snprintf(uri_path, path_len, "%s%s%s",app_path, "/", uri); + + if (access(uri_path, F_OK) == 0) { + char *new_uri = __convert_sticker_uri(uri_path, appid, app_path); + if (!new_uri) { + free(uri_path); + uri_path = NULL; + goto free_memory; + } + __insert_sticker_info(appid, type, new_uri, group, thumbnail, description); + + free(new_uri); + new_uri = NULL; + + free(uri_path); + uri_path = NULL; + } else { + LOGE("%s does not exist", uri_path); + free(uri_path); + uri_path = NULL; + goto free_memory; + } + } + } else { + __insert_sticker_info(appid, type, uri, group, thumbnail, description); + } + + for (int j = 0; j < keyword_arr_len; j++) { + __insert_sticker_keyword_info(json_array_get_string_element(keyword_arr, j)); + } + +free_memory: + if (uri) { + free(uri); + uri = NULL; + } + + if (group) { + free(group); + group = NULL; + } + + if (thumbnail) { + free(thumbnail); + thumbnail = NULL; + } + + if (description) { + free(description); + description = NULL; + } + } + } + +cleanup: + if (err_msg) + g_error_free(err_msg); + + if (parser) + g_object_unref(parser); + + return ret; +} + +static void __delete_sticker_info(const char *db_path, int record_id) +{ + int ret; + sqlite3 *db = NULL; + sqlite3_stmt *stmt = NULL; + + db = __db_open(db_path); + if (!db) + return; + + ret = sqlite3_prepare_v2(db, "DELETE FROM sticker_info WHERE sticker_info_id = ?", -1, &stmt, NULL); + if (ret != SQLITE_OK) { + LOGE("failed to delete sticker information : %s", sqlite3_errmsg(db)); + sqlite3_finalize(stmt); + sqlite3_close(db); + goto cleanup; + } + + sqlite3_bind_int(stmt, 1, record_id); + + ret = sqlite3_step(stmt); + if (ret != SQLITE_OK && ret != SQLITE_DONE) { + LOGE("sqlite3_step() failed : ret(%d)", ret); + goto cleanup; + } + + if (sqlite3_changes(db) == 0) { + LOGE("No changes to DB"); + goto cleanup; + } + + sqlite3_finalize(stmt); + sqlite3_close(db); + return; + +cleanup: + sqlite3_finalize(stmt); + sqlite3_close(db); + return; +} + +static int __remove_directory(const char *path, int is_error_stop) +{ + DIR *dir_ptr = NULL; + struct dirent *file = NULL; + struct stat buf; + char filename[1024]; + + memset(filename, '\0', 1024); + + if (__change_ownership(path, APPFW_ID, APPFW_ID) != 0) + LOGE("failed to change ownership"); + + dir_ptr = opendir(path); + if (dir_ptr == NULL) + return unlink(path); + + while ((file = readdir(dir_ptr)) != NULL) { + if (strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0) + continue; + + snprintf(filename, strlen(path) + strlen(file->d_name) + 2, "%s/%s", path, file->d_name); + + if (lstat(filename, &buf) == -1) + continue; + + if (S_ISDIR(buf.st_mode)) { + if (__remove_directory(filename, is_error_stop) == -1 && is_error_stop) { + closedir(dir_ptr); + return -1; + } + } else if (S_ISREG(buf.st_mode) || S_ISLNK(buf.st_mode)) { + if (unlink(filename) == -1 && is_error_stop) { + closedir(dir_ptr); + return -1; + } + } + } + + closedir(dir_ptr); + return rmdir(path); +} + +EXPORT_API +int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgid, const char *appid, GList *list) +{ + LOGD("METADATA INSTALL"); + LOGD("pkgid: %s, appid: %s", pkgid, appid); + + metadata *md = NULL; + GList *md_list = NULL; + package_info_h package_info = NULL; + char *app_path = NULL; + char *file_path = NULL; + int ret = 0; + + ret = package_info_create(pkgid, &package_info); + if (ret != PACKAGE_MANAGER_ERROR_NONE || package_info == NULL) { + LOGE("faild to create package_info. ret: %d", ret); + goto cleanup; + } + + ret = package_info_get_root_path(package_info, &app_path); + if (ret != PACKAGE_MANAGER_ERROR_NONE || app_path == NULL) { + LOGE("faild to create package_info. ret: %d", ret); + goto cleanup; + } + + for(md_list = g_list_first(list); md_list != NULL; md_list = md_list->next) { + md = (metadata *)md_list->data; + int path_len = strlen(app_path) + strlen((char *)md->value) + 2; + file_path = (char *)calloc(path_len, sizeof(char)); + if (!file_path) { + LOGE("failed to alloc memory"); + continue; + } + + if ((char)md->value[0] == '/') + snprintf(file_path, path_len, "%s%s",app_path, (char *)md->value); + else + snprintf(file_path, path_len, "%s%s%s",app_path, "/", (char *)md->value); + + if (__get_sticker_info_from_json(appid, file_path, app_path) == 0) + LOGE("failed to get sticker information [path : %s]", file_path); + + free(file_path); + file_path = NULL; + } + +cleanup: + if (package_info) + package_info_destroy(package_info); + + if (app_path) { + free(app_path); + app_path = NULL; + } + + return 0; +} + +EXPORT_API +int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgid, const char *appid, GList *list) +{ + LOGD("METADATA UNINSTALL"); + LOGD("pkgid: %s, appid: %s", pkgid, appid); + + int ret; + int del_id; + sqlite3 *db = NULL; + sqlite3_stmt *stmt = NULL; + const char *db_path; + GList *id_list = NULL; + + db_path = tzplatform_mkpath(TZ_SYS_DB, ".sticker_info.db"); + db = __db_open(db_path); + if (!db) + return 0; + + ret = sqlite3_prepare_v2(db, "SELECT sticker_info_id from sticker_info WHERE app_id = ?", -1, &stmt, NULL); + if (ret == SQLITE_OK) { + sqlite3_bind_text(stmt, 1, appid, -1, SQLITE_TRANSIENT); + while (sqlite3_step(stmt) == SQLITE_ROW) { + const unsigned char *record_id = sqlite3_column_text(stmt, 0); + if (record_id) + id_list = g_list_append(id_list, strdup((const char *)record_id)); + } + + sqlite3_finalize(stmt); + sqlite3_close(db); + + for(GList *tmp = g_list_first(id_list); tmp != NULL; tmp = tmp->next) { + del_id = atoi((const char*)tmp->data); + __delete_sticker_info(db_path, del_id); + } + + if (id_list) + g_list_free_full(id_list, free); + } else { + LOGE("failed to get sticker id"); + sqlite3_finalize(stmt); + sqlite3_close(db); + } + + return 0; +} + +EXPORT_API +int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgid, const char *appid, GList *list) +{ + LOGD("METADATA UPGRADE"); + LOGD("pkgid: %s, appid: %s", pkgid, appid); + + PKGMGR_MDPARSER_PLUGIN_UNINSTALL(pkgid, appid, list); + PKGMGR_MDPARSER_PLUGIN_INSTALL(pkgid, appid, list); + return 0; +} + +EXPORT_API +int PKGMGR_CATEGORY_PARSER_PLUGIN_INSTALL(const char *pkgid, const char *appid, GList *list) +{ + LOGD("STICKER CATEGORY INSTALL"); + LOGD("pkgid: %s, appid: %s", pkgid, appid); + + int len = strlen(STICKER_DIRECTORY) + strlen(appid) + 2; + char *dir_path = (char *)calloc(len, sizeof(char)); + + if (dir_path != NULL) { + snprintf(dir_path, len, "%s%s%s", STICKER_DIRECTORY, "/", appid); + LOGD("directory path : %s", dir_path); + + if (mkdir(dir_path, 0755) == -1 && errno != EEXIST) { + strerror_r(errno, error_buffer, MAX_ERROR_BUFFER); + LOGE("directory create error : %s", error_buffer); + } else { + if (__change_ownership(dir_path, UIFW_ID, UIFW_ID) != 0) + LOGE("failed to change ownership"); + } + + free(dir_path); + dir_path = NULL; + } + + return 0; +} + +EXPORT_API +int PKGMGR_CATEGORY_PARSER_PLUGIN_UNINSTALL(const char *pkgid, const char *appid, GList *list) +{ + LOGD("STICKER CATEGORY UNINSTALL"); + LOGD("pkgid: %s, appid: %s", pkgid, appid); + + int len = strlen(STICKER_DIRECTORY) + strlen(appid) + 2; + char * dir_path = (char *)calloc(len, sizeof(char)); + + if (dir_path != NULL) { + snprintf(dir_path, len, "%s%s%s", STICKER_DIRECTORY, "/", appid); + LOGD("directory path : %s", dir_path); + + if (__remove_directory(dir_path, 0) < 0) { + strerror_r(errno, error_buffer, MAX_ERROR_BUFFER); + LOGE("directory remove error : %s", error_buffer); + } + + free(dir_path); + dir_path = NULL; + } + + return 0; +} + +EXPORT_API +int PKGMGR_CATEGORY_PARSER_PLUGIN_UPGRADE(const char *pkgid, const char *appid, GList *list) +{ + LOGD("STICKER CATEGORY UPGRADE"); + LOGD("pkgid: %s, appid: %s", pkgid, appid); + + PKGMGR_CATEGORY_PARSER_PLUGIN_UNINSTALL(pkgid, appid, list); + PKGMGR_CATEGORY_PARSER_PLUGIN_INSTALL(pkgid, appid, list); + + return 0; +} \ No newline at end of file -- 2.7.4