Initial commit 44/208944/36 accepted/tizen/unified/20190905.060548 submit/tizen/20190904.093136
authorInhong Han <inhong1.han@samsung.com>
Mon, 1 Jul 2019 10:43:06 +0000 (19:43 +0900)
committerInHong Han <inhong1.han@samsung.com>
Wed, 4 Sep 2019 08:06:11 +0000 (17:06 +0900)
Change-Id: Ieb7147f649b8cdbc1374b2f5fd5e96f6f9b694c6

43 files changed:
AUTHORS [new file with mode: 0644]
CMakeLists.txt [new file with mode: 0755]
LICENSE [new file with mode: 0644]
capi-ui-sticker-devel.manifest [new file with mode: 0644]
capi-ui-sticker.info [new file with mode: 0644]
capi-ui-sticker.manifest [new file with mode: 0644]
client/sticker_data.c [new file with mode: 0644]
client/sticker_data_main.h [new file with mode: 0644]
client/sticker_dbus.c [new file with mode: 0644]
client/sticker_dbus.h [new file with mode: 0644]
client/sticker_defs.h [new file with mode: 0644]
consumer/CMakeLists.txt [new file with mode: 0644]
consumer/sticker_consumer.c [new file with mode: 0644]
consumer/sticker_consumer_main.h [new file with mode: 0644]
doc/sticker_consumer_doc.h [new file with mode: 0644]
doc/sticker_data_doc.h [new file with mode: 0644]
doc/sticker_doc.h [new file with mode: 0644]
doc/sticker_provider_doc.h [new file with mode: 0644]
include/CMakeLists.txt [new file with mode: 0644]
include/capi-ui-sticker-consumer.pc.in [new file with mode: 0644]
include/capi-ui-sticker-provider.pc.in [new file with mode: 0644]
include/sticker_consumer.h [new file with mode: 0644]
include/sticker_data.h [new file with mode: 0644]
include/sticker_error.h [new file with mode: 0644]
include/sticker_provider.h [new file with mode: 0644]
packaging/capi-ui-sticker.conf [new file with mode: 0644]
packaging/capi-ui-sticker.service [new file with mode: 0644]
packaging/capi-ui-sticker.spec [new file with mode: 0644]
packaging/org.tizen.sticker.server.service [new file with mode: 0644]
provider/CMakeLists.txt [new file with mode: 0644]
provider/sticker_provider.c [new file with mode: 0644]
provider/sticker_provider_main.h [new file with mode: 0644]
server/CMakeLists.txt [new file with mode: 0644]
server/stickerd_data_manager.c [new file with mode: 0644]
server/stickerd_data_manager.h [new file with mode: 0644]
server/stickerd_db_manager.c [new file with mode: 0644]
server/stickerd_db_manager.h [new file with mode: 0644]
server/stickerd_dbus.c [new file with mode: 0644]
server/stickerd_dbus.h [new file with mode: 0644]
server/stickerd_error.h [new file with mode: 0644]
server/stickerd_main.c [new file with mode: 0644]
sticker-parser/CMakeLists.txt [new file with mode: 0644]
sticker-parser/sticker-parser.c [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
new file mode 100644 (file)
index 0000000..b4905c3
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Inhong Han <inhong1.han@samsung.com>
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..07365cf
--- /dev/null
@@ -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 (file)
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 (file)
index 0000000..dfdc35c
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+ <request>
+  <domain name="_"/>
+ </request>
+</manifest>
diff --git a/capi-ui-sticker.info b/capi-ui-sticker.info
new file mode 100644 (file)
index 0000000..1c51865
--- /dev/null
@@ -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 (file)
index 0000000..dfdc35c
--- /dev/null
@@ -0,0 +1,5 @@
+<manifest>
+ <request>
+  <domain name="_"/>
+ </request>
+</manifest>
diff --git a/client/sticker_data.c b/client/sticker_data.c
new file mode 100644 (file)
index 0000000..2603285
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dlog.h>
+#include <app_common.h>
+#include <package_manager.h>
+
+#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 (file)
index 0000000..058de9c
--- /dev/null
@@ -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 <glib.h>
+#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 (file)
index 0000000..64434b4
--- /dev/null
@@ -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 <dlog.h>
+
+#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 (file)
index 0000000..d8fcbcd
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <dbus/dbus.h>
+#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 (file)
index 0000000..3575ecf
--- /dev/null
@@ -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 <tzplatform_config.h>
+
+#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 (file)
index 0000000..0e554b0
--- /dev/null
@@ -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 (file)
index 0000000..5024e8b
--- /dev/null
@@ -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 <dlog.h>
+#include <gio/gio.h>
+#include <dbus/dbus.h>
+#include <cynara-client.h>
+#include <cynara-error.h>
+#include <cynara-session.h>
+
+#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 (file)
index 0000000..ba7f90d
--- /dev/null
@@ -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 <gio/gio.h>
+#include <dbus/dbus.h>
+#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 (file)
index 0000000..ff62eb0
--- /dev/null
@@ -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 <sticker_consumer.h>
+ *
+ * @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 (file)
index 0000000..0534730
--- /dev/null
@@ -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 <sticker_data.h>
+ *
+ * @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:
+ * <ul>
+ *   <li>Name of the provider application</li>
+ *   <li>URI type</li>
+ *   <li>URI</li>
+ *   <li>Keyword</li>
+ *   <li>Group name</li>
+ *   <li>Thumbnail path</li>
+ *   <li>Description</li>
+ *   <li>Last updated date</li>
+ * </ul>
+ */
+
+
+#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 (file)
index 0000000..1930f25
--- /dev/null
@@ -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 (file)
index 0000000..b9be404
--- /dev/null
@@ -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 <sticker_provider.h>
+ *
+ * @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 (file)
index 0000000..833e228
--- /dev/null
@@ -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 (file)
index 0000000..e4acc71
--- /dev/null
@@ -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 (file)
index 0000000..a11a915
--- /dev/null
@@ -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 (file)
index 0000000..2dfe76c
--- /dev/null
@@ -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 <sticker_error.h>
+#include <sticker_data.h>
+
+#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 (file)
index 0000000..b0d4db7
--- /dev/null
@@ -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 <sticker_error.h>
+
+#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 (file)
index 0000000..049ab05
--- /dev/null
@@ -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 <tizen.h>
+
+#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 (file)
index 0000000..01ed6e0
--- /dev/null
@@ -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 <sticker_error.h>
+#include <sticker_data.h>
+
+#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 (file)
index 0000000..9d90095
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
+
+<busconfig>
+  <policy group="users">
+    <allow own="org.tizen.sticker.server"/>
+    <allow send_destination="org.tizen.sticker.server"/>
+  </policy>
+  <policy group="ui_fw">
+    <allow own="org.tizen.sticker.server"/>
+    <allow send_destination="org.tizen.sticker.server"/>
+  </policy>
+</busconfig>
\ No newline at end of file
diff --git a/packaging/capi-ui-sticker.service b/packaging/capi-ui-sticker.service
new file mode 100644 (file)
index 0000000..b6d7b26
--- /dev/null
@@ -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 (file)
index 0000000..45d4ec5
--- /dev/null
@@ -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 (file)
index 0000000..64f3471
--- /dev/null
@@ -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 (file)
index 0000000..9eb6d49
--- /dev/null
@@ -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 (file)
index 0000000..f600adb
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dlog.h>
+#include <app_common.h>
+#include <package_manager.h>
+
+#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 (file)
index 0000000..6280801
--- /dev/null
@@ -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 <gio/gio.h>
+#include <dbus/dbus.h>
+#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 (file)
index 0000000..1c15da7
--- /dev/null
@@ -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 (file)
index 0000000..cb457d0
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <tzplatform_config.h>
+#include <gio/gunixfdlist.h>
+#include <dlog.h>
+#include <json-glib/json-glib.h>
+#include <package_manager.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <dirent.h>
+#include <fcntl.h>
+
+#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[] =
+            "  <node>"
+            "  <interface name='org.tizen.sticker_service'>"
+            "        <method name='sticker_service_register'>"
+            "        </method>"
+
+            "        <method name='insert_sticker_info'>"
+            "          <arg type='a{iv}' name='sticker_info' direction='in'/>"
+            "          <arg type='a(s)' name='keyword_list' direction='in'/>"
+            "          <arg type='i' name='record_id' direction='out'/>"
+            "        </method>"
+
+            "        <method name='update_sticker_info_by_json'>"
+            "          <arg type='s' name='app_id' direction='in'/>"
+            "          <arg type='s' name='json_path' direction='in'/>"
+            "        </method>"
+
+            "        <method name='delete_sticker_info'>"
+            "          <arg type='i' name='record_id' direction='in'/>"
+            "        </method>"
+
+            "        <method name='update_sticker_type'>"
+            "          <arg type='i' name='record_id' direction='in'/>"
+            "          <arg type='i' name='type' direction='in'/>"
+            "        </method>"
+
+            "        <method name='update_sticker_uri'>"
+            "          <arg type='i' name='record_id' direction='in'/>"
+            "          <arg type='s' name='app_id' direction='in'/>"
+            "          <arg type='i' name='type' direction='in'/>"
+            "          <arg type='s' name='uri' direction='in'/>"
+            "        </method>"
+
+            "        <method name='update_sticker_thumbnail'>"
+            "          <arg type='i' name='record_id' direction='in'/>"
+            "          <arg type='s' name='thumbnail' direction='in'/>"
+            "        </method>"
+
+            "        <method name='update_sticker_description'>"
+            "          <arg type='i' name='record_id' direction='in'/>"
+            "          <arg type='s' name='description' direction='in'/>"
+            "        </method>"
+
+            "        <method name='update_sticker_group'>"
+            "          <arg type='i' name='record_id' direction='in'/>"
+            "          <arg type='s' name='group' direction='in'/>"
+            "        </method>"
+
+            "        <method name='update_sticker_keyword'>"
+            "          <arg type='i' name='record_id' direction='in'/>"
+            "          <arg type='a(s)' name='keyword' direction='in'/>"
+            "        </method>"
+
+            "        <method name='get_sticker_info'>"
+            "          <arg type='i' name='record_id' direction='in'/>"
+            "          <arg type='a{iv}' name='sticker_info' direction='out'/>"
+            "          <arg type='a(s)' name='keyword_list' direction='out'/>"
+            "        </method>"
+
+            "        <method name='get_group_list'>"
+            "          <arg type='a(s)' name='group_list' direction='out'/>"
+            "        </method>"
+
+            "        <method name='get_keyword_list'>"
+            "          <arg type='a(s)' name='keyword_list' direction='out'/>"
+            "        </method>"
+
+            "        <method name='get_sticker_count'>"
+            "          <arg type='s' name='app_id' direction='in'/>"
+            "          <arg type='i' name='count' direction='out'/>"
+            "        </method>"
+
+            "        <method name='get_all_sticker_info'>"
+            "          <arg type='i' name='offset' direction='in'/>"
+            "          <arg type='i' name='count' direction='in'/>"
+            "          <arg type='a(i)' name='id_list' direction='out'/>"
+            "        </method>"
+
+            "        <method name='get_sticker_info_by_appid'>"
+            "          <arg type='s' name='app_id' direction='in'/>"
+            "          <arg type='i' name='offset' direction='in'/>"
+            "          <arg type='i' name='count' direction='in'/>"
+            "          <arg type='a(i)' name='id_list' direction='out'/>"
+            "        </method>"
+
+            "        <method name='get_sticker_info_by_type'>"
+            "          <arg type='i' name='type' direction='in'/>"
+            "          <arg type='i' name='offset' direction='in'/>"
+            "          <arg type='i' name='count' direction='in'/>"
+            "          <arg type='a(i)' name='id_list' direction='out'/>"
+            "        </method>"
+
+            "        <method name='get_sticker_info_by_group'>"
+            "          <arg type='s' name='group' direction='in'/>"
+            "          <arg type='i' name='offset' direction='in'/>"
+            "          <arg type='i' name='count' direction='in'/>"
+            "          <arg type='a(i)' name='id_list' direction='out'/>"
+            "        </method>"
+
+            "        <method name='get_sticker_info_by_keyword'>"
+            "          <arg type='s' name='keyword' direction='in'/>"
+            "          <arg type='i' name='offset' direction='in'/>"
+            "          <arg type='i' name='count' direction='in'/>"
+            "          <arg type='a(i)' name='id_list' direction='out'/>"
+            "        </method>"
+            "  </interface>"
+            "  </node>";
+
+    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 (file)
index 0000000..8086dcb
--- /dev/null
@@ -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 <gio/gio.h>
+
+#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 (file)
index 0000000..de33abc
--- /dev/null
@@ -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 <unistd.h>
+#include <string.h>
+#include <dlog.h>
+#include <sqlite3.h>
+
+#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 (file)
index 0000000..6e6ebb5
--- /dev/null
@@ -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 <glib.h>
+#include <tzplatform_config.h>
+
+#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 (file)
index 0000000..4ff175a
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <gio/gio.h>
+#include <dlog.h>
+
+#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 (file)
index 0000000..0197793
--- /dev/null
@@ -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 <gio/gio.h>
+#include <stdlib.h>
+#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 (file)
index 0000000..2afea16
--- /dev/null
@@ -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 (file)
index 0000000..1650437
--- /dev/null
@@ -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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dlog.h>
+#include <glib.h>
+#include <sys/signalfd.h>
+#include <signal.h>
+
+#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 (file)
index 0000000..c27f790
--- /dev/null
@@ -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 (file)
index 0000000..dc27241
--- /dev/null
@@ -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 <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlog.h>
+#include <glib.h>
+#include <json-glib/json-glib.h>
+#include <pkgmgr-info.h>
+#include <sqlite3.h>
+#include <tzplatform_config.h>
+#include <package_manager.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <dirent.h>
+#include <fcntl.h>
+
+#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