summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt6
-rw-r--r--lib/CMakeLists.txt49
-rw-r--r--lib/LICENSE204
-rw-r--r--lib/include/shortcut.h268
-rw-r--r--lib/include/shortcut_PG.h59
-rw-r--r--lib/shortcut.pc.in10
-rw-r--r--lib/src/main.c776
-rw-r--r--libshortcut.manifest22
-rw-r--r--packaging/libshortcut.spec66
-rw-r--r--pkgmgr_shortcut/CMakeLists.txt31
-rw-r--r--pkgmgr_shortcut/include/dlist.h44
-rw-r--r--pkgmgr_shortcut/src/dlist.c181
-rw-r--r--pkgmgr_shortcut/src/service_register.c776
-rw-r--r--sample.xml62
-rw-r--r--test/Makefile4
-rw-r--r--test/application.c57
-rw-r--r--test/homescreen.c40
-rw-r--r--test/shortcut.c41
-rwxr-xr-xtest_db_builder.sh80
19 files changed, 2776 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..ea60a32
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,6 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+
+set(CMAKE_SKIP_BUILD_RPATH true)
+
+ADD_SUBDIRECTORY("pkgmgr_shortcut")
+ADD_SUBDIRECTORY("lib")
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
new file mode 100644
index 0000000..0e27e2d
--- /dev/null
+++ b/lib/CMakeLists.txt
@@ -0,0 +1,49 @@
+PROJECT(shortcut C)
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/lib/include)
+
+SET(PREFIX ${CMAKE_INSTALL_PREFIX})
+SET(EXEC_PREFIX "\${prefix}")
+SET(LIBDIR "\${exec_prefix}/lib")
+SET(INCLUDEDIR "\${prefix}/include/${PROJECT_NAME}")
+SET(VERSION_MAJOR 0)
+SET(VERSION "${VERSION_MAJOR}.0.1")
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(svc_pkgs REQUIRED
+ dlog
+ sqlite3
+ libxml-2.0
+ glib-2.0
+ db-util
+ com-core
+ vconf
+)
+
+FOREACH(flag ${svc_pkgs_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden -g -Wall -Werror")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+
+ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"")
+ADD_DEFINITIONS("-DLOG_TAG=\"SHORTCUT\"")
+
+ADD_LIBRARY(${PROJECT_NAME} SHARED
+ src/main.c
+)
+
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${svc_pkgs_LDFLAGS})
+
+CONFIGURE_FILE(${PROJECT_NAME}.pc.in ${PROJECT_NAME}.pc @ONLY)
+SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${PROJECT_NAME}.pc")
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION lib)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/lib/include/shortcut.h DESTINATION include/${PROJECT_NAME})
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/lib/include/shortcut_PG.h DESTINATION include/${PROJECT_NAME})
+INSTALL(FILES ${CMAKE_BINARY_DIR}/lib/${PROJECT_NAME}.pc DESTINATION lib/pkgconfig)
+INSTALL(FILES ${CMAKE_SOURCE_DIR}/lib/LICENSE DESTINATION /usr/share/license RENAME "lib${PROJECT_NAME}")
+
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${VERSION_MAJOR})
+SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES VERSION ${VERSION})
diff --git a/lib/LICENSE b/lib/LICENSE
new file mode 100644
index 0000000..9c13a9b
--- /dev/null
+++ b/lib/LICENSE
@@ -0,0 +1,204 @@
+Copyright (c) 2000 - 2011 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/lib/include/shortcut.h b/lib/include/shortcut.h
new file mode 100644
index 0000000..f05f5ae
--- /dev/null
+++ b/lib/include/shortcut.h
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2000 - 2011 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 __SHORTCUT_H__
+#define __SHORTCUT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @addtogroup APPLICATION_FRAMEWORK
+ * @{
+ */
+
+/**
+ * @defgroup SHORTCUT Add to home (shortcut)
+ * @author Sung-jae Park <nicesj.park@samsung.com>
+ * @version 0.1
+ * @brief To enhance the Add to home feature. Two types of API set are supported.
+ * One for the homescreen developers.
+ * The others for the application developers who should implement the Add to home feature.
+ */
+
+/**
+ * @brief This function prototype is used to define a callback function for the add_to_home reqeust.
+ * The homescreen should define a callback as this type and implementing the service code
+ * for adding a new application shortcut.
+ * @param[in] appid Shortcut is added for this package.
+ * @param[in] name Name for created shortcut icon.
+ * @param[in] type 3 kinds of types are defined.
+ * @param[in] content_info Specific information for creating a new shortcut.
+ * @param[in] icon Absolute path of an icon file for this shortcut.
+ * @param[in] pid Process ID of who request add_to_home.
+ * @param[in] data Callback data.
+ * @return int Developer should returns the result of handling shortcut creation request.
+ * Returns 0, if succeed to handles the add_to_home request, or returns proper errno.
+ * @see shortcut_set_request_cb
+ * @pre None
+ * @post None
+ * @remarks None
+ */
+typedef int (*request_cb_t)(const char *appid, const char *name, int type, const char *content_info, const char *icon, int pid, double period, void *data);
+
+/**
+ * @brief This function prototype is used to define for receiving the result of add_to_home.
+ * @param[in] ret Result value, it could be 0 if succeed to add a shortcut, or errno.
+ * @param[in] pid Process ID of who handles this add_to_home request.
+ * @param[in] data Callback data.
+ * @return int Returns 0, if there is no error or returns errno.
+ * @see add_to_home_shortcut()
+ * @pre None
+ * @post None
+ * @remarks None
+ */
+typedef int (*result_cb_t)(int ret, int pid, void *data);
+
+/**
+ * @brief Basically, three types of shortcut is defined.
+ * Every homescreen developer should support these types of shortcut.
+ * Or returns proper errno to figure out why the application failed to add a shortcut.
+ * LAUNCH_BY_PACKAGE is used for adding a package itself as a shortcut
+ * LAUNCH_BY_URI is used for adding a shortcut for "uri" data.
+ */
+enum shortcut_type {
+ /*!< Deprecated type */
+ SHORTCUT_PACKAGE = 0x00000000, /**< Launch the package using given pakcage name. */
+ SHORTCUT_DATA = 0x00000001, /**< Launch the related package with given data(content_info). */
+ SHORTCUT_FILE = 0x00000002, /**< Launch the related package with given filename(content_info). */
+
+ /*!< Use these */
+ LAUNCH_BY_PACKAGE = 0x00000000, /*!< Launch the package using given pakcage name. */
+ LAUNCH_BY_URI = 0x00000001, /*!< Launch the related package with given data(URI). */
+
+ LIVEBOX_TYPE_DEFAULT = 0x10000000,
+ LIVEBOX_TYPE_1x1 = 0x10010000,
+ LIVEBOX_TYPE_2x1 = 0x10020000,
+ LIVEBOX_TYPE_2x2 = 0x10040000,
+ LIVEBOX_TYPE_4x1 = 0x10080000,
+ LIVEBOX_TYPE_4x2 = 0x10100000,
+ LIVEBOX_TYPE_4x3 = 0x10200000,
+ LIVEBOX_TYPE_4x4 = 0x10400000,
+ LIVEBOX_TYPE_UNKNOWN = 0x1FFF0000,
+};
+
+#define ADD_TO_HOME_IS_LIVEBOX(type) (!!((type) & 0x10000000))
+
+/**
+ * @fn int shortcut_set_request_cb(request_cb_t request_cb, void *data)
+ *
+ * @brief Homescreen should use this function to service the shortcut creating request.
+ *
+ * @par Sync (or) Async:
+ * This is an asynchronous API.
+ *
+ * @par Important Notes:
+ * - Should be used from the homescreen.
+ * - Should check the return value of this function
+ *
+ * @param[in] request_cb Callback function pointer which will be invoked when add_to_home is requested.
+ * @param[in] data Callback data to deliver to the callback function.
+ *
+ * @return Return Type (int)
+ * - 0 - callback function is successfully registered
+ * - < 0 - Failed to register the callback function for request.
+ *
+ * @see request_cb_t
+ *
+ * @pre - You have to prepare a callback function
+ *
+ * @post - If a request is sent from the application, the registered callback will be invoked.
+ *
+ * @remarks - None
+ *
+ * @par Prospective Clients:
+ * Homescreen
+ *
+ * @par Example
+ * @code
+ * #include <shortcut.h>
+ *
+ * static int request_cb(const char *appid, const char *name, int type, const char *content_info, const char *icon, int pid, void *data)
+ * {
+ * printf("Package name: %s\n", appid);
+ * printf("Name: %s\n", name);
+ * printf("Type: %d\n", type);
+ * printf("Content: %s\n", content_info);
+ * printf("Icon: %s\n", icon);
+ * printf("Requested from: %d\n", pid);
+ * printf("CBDATA: %p\n", data);
+ * return 0; // returns success.
+ * }
+ *
+ * static int app_create(void *data)
+ * {
+ * shortcut_set_request_cb(request_cb, NULL);
+ * return 0;
+ * }
+ *
+ * int main(int argc, char *argv[])
+ * {
+ * appcore....
+ * }
+ *
+ * @endcode
+ */
+extern int shortcut_set_request_cb(request_cb_t request_cb, void *data);
+
+/**
+ * @fn int add_to_home_shortcut(const char *appid, const char *name, int type, const char *content_info, const char *icon, result_cb_t result_cb, void *data)
+ *
+ * @brief The application, which supporting the add_to_home feature, should invoke this.
+ *
+ * @par Sync (or) Async:
+ * This is an asynchronous API.
+ *
+ * @par Important Notes:
+ * - Application should check the return value of this function.
+ * - Application should check the return status from the callback function
+ * - Application should set the callback function to get the result of this request.
+ *
+ * @param[in] appid Package name of owner of this shortcut.
+ * @param[in] name Name for created shortcut icon.
+ * @param[in] type 3 kinds of types are defined.
+ * @param[in] content_info Specific information for delivering to the creating shortcut.
+ * @param[in] icon Absolute path of an icon file
+ * @param[in] result_cb Callback function pointer which will be invoked after add_to_home request.
+ * @param[in] data Callback data to deliver to the callback function.
+ *
+ * @return Return Type (int)
+ * - 0 - Succeed to send the request
+ * - <0 - Failed to send the request
+ *
+ * @see result_cb_t
+ *
+ * @pre - You have to prepare the callback function
+ *
+ * @post - You have to check the return status from callback function which is passed by argument.
+ *
+ * @remarks - If a homescreen does not support this feature, you will get proper error code.
+ *
+ * @par Prospective Clients:
+ * Inhouse Apps.
+ *
+ * @par Example
+ * @code
+ *
+ * #include <stdio.h>
+ * #include <shortcut.h>
+ *
+ * static int result_cb(int ret, int pid, void *data)
+ * {
+ * if (ret < 0)
+ * printf("Failed to add a shortcut: %s\n", perror(ret));
+ *
+ * printf("Processed by the %d\n", pid);
+ * return 0;
+ * }
+ *
+ * static int app_create(void *data)
+ * {
+ * add_to_home_shortcut("org.tizen.gallery", "With friends",
+ * SHORTCUT_DATA, "gallery:0000-0000",
+ * "/opt/media/Pictures/Friends.jpg", result_cb, NULL);
+ * return 0;
+ * }
+ *
+ * int main(int argc, char *argv[])
+ * {
+ * appcore....
+ * }
+ *
+ * @endcode
+ */
+extern int shortcut_get_list(const char *appid, int (*cb)(const char *appid, const char *icon, const char *name, const char *extra_key, const char *extra_data, void *data), void *data);
+
+extern int add_to_home_shortcut(const char *appid, const char *name, int type, const char *content_info, const char *icon, result_cb_t result_cb, void *data);
+
+extern int add_to_home_livebox(const char *appid, const char *name, int type, const char *content, const char *icon, double period, result_cb_t result_cb, void *data);
+
+
+/*!
+ * \brief Number of preview images for homescreen
+ */
+extern int homescreen_get_image_count(const char *appid);
+/*!
+ * \return string allocated in the heap - Path of image
+ */
+extern char *homescreen_get_image(const char *appid, int idx);
+
+/*!
+ * \brief Description of the homescreen (based on i18n)
+ */
+extern int homescreen_get_description(const char *appid, void (*cb)(const char *appid, const char *icon, const char *name, const char *desc, void *data), void *data);
+
+/*!
+ * \note
+ * These two functions are deprecated now.
+ *
+ * Please replace the "shortcut_add_to_home" with "add_to_home_shortcut"
+ * Please replace the "shortcut_add_to_home_with_period" with "add_to_home_livebox"
+ */
+extern int shortcut_add_to_home(const char *appid, const char *name, int type, const char *content, const char *icon, result_cb_t result_cb, void *data) __attribute__ ((deprecated));
+
+extern int shortcut_add_to_home_with_period(const char *appid, const char *name, int type, const char *content, const char *icon, double period, result_cb_t result_cb, void *data) __attribute__ ((deprecated));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+/* @}
+ * End of a file
+ */
diff --git a/lib/include/shortcut_PG.h b/lib/include/shortcut_PG.h
new file mode 100644
index 0000000..c3bd6c2
--- /dev/null
+++ b/lib/include/shortcut_PG.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2000 - 2011 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.
+ *
+*/
+
+/**
+ * @ingroup SLP_PG
+ * @defgroup SHORTCUT_PG Add to home (shortcut)
+ * @{
+
+ <h1 class="pg">Introduction</h1>
+ Shortcut is a communication interfaces for homescreen and applications. To enable the add_to_home feature. Shortcut(libshortcut) uses socket for IPC.
+
+ @image html SLP_Shortcut_PG_image01.png
+
+ <h2 class="pg">Properties</h2>
+- Types of shortcut
+- Header File : shortcut.h
+
+<h1 class="pg">Programming Guide</h1>
+
+<h2 class="pg">Types of shortcut</h1>
+Shortcut defines 3 kinds of types.
+
+<h3 class="pg">1. SHORTCUT_PACKAGE</h1>
+We can use this for adding a package shortcut with additional information. <br/>
+@code
+@endcode
+
+<h3 class="pg">2. SHORTCUT_DATA</h1>
+@code
+@endcode
+
+<h3 class="pg">3. SHORTCUT_FILE</h1>
+@code
+@endcode
+
+<h2 class="pg">Error code</h1>
+<h3 class="pg">1. -EINVAL</h1>
+<h3 class="pg">1. -EFAULT</h1>
+@code
+@endcode
+*/
+
+/**
+@}
+*/
diff --git a/lib/shortcut.pc.in b/lib/shortcut.pc.in
new file mode 100644
index 0000000..8daf96d
--- /dev/null
+++ b/lib/shortcut.pc.in
@@ -0,0 +1,10 @@
+prefix=@PREFIX@
+exec_prefix=@EXEC_PREFIX@
+libdir=@LIBDIR@
+includedir=@INCLUDEDIR@
+
+Name: shortcut
+Description: shortcut server platform library
+Version: @VERSION@
+Libs: -L${libdir} -lshortcut
+Cflags: -I${includedir}
diff --git a/lib/src/main.c b/lib/src/main.c
new file mode 100644
index 0000000..89871f0
--- /dev/null
+++ b/lib/src/main.c
@@ -0,0 +1,776 @@
+/*
+ * Copyright (c) 2000 - 2011 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 <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <libgen.h>
+
+#include <dlog.h>
+#include <glib.h>
+#include <db-util.h>
+#include <vconf.h>
+#include <vconf-keys.h>
+
+#include <packet.h>
+#include <com-core.h>
+#include <com-core_packet.h>
+
+#include "shortcut.h"
+
+#if !defined(FLOG)
+#define DbgPrint(format, arg...) LOGD("[%s/%s:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg)
+#define ErrPrint(format, arg...) LOGE("[%s/%s:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg)
+#else
+extern FILE *__file_log_fp;
+#define DbgPrint(format, arg...) do { fprintf(__file_log_fp, "[LOG] [%s/%s:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg); fflush(__file_log_fp); } while (0)
+
+#define ErrPrint(format, arg...) do { fprintf(__file_log_fp, "[ERR] [%s/%s:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg); fflush(__file_log_fp); } while (0)
+#endif
+
+#define EAPI __attribute__((visibility("default")))
+
+int errno;
+
+
+
+static struct info {
+ const char *dbfile;
+ sqlite3 *handle;
+ int server_fd;
+ int client_fd;
+ const char *socket_file;
+ struct {
+ int (*request_cb)(const char *appid, const char *name, int type, const char *content, const char *icon, pid_t pid, double period, void *data);
+ void *data;
+ } server_cb;
+ int initialized;
+ int db_opened;
+} s_info = {
+ .server_fd = -1,
+ .client_fd = -1,
+ .socket_file = "/tmp/.shortcut",
+ .dbfile = "/opt/dbspace/.shortcut_service.db",
+ .handle = NULL,
+ .initialized = 0,
+ .db_opened = 0,
+};
+
+
+
+static struct packet *add_shortcut_handler(pid_t pid, int handle, const struct packet *packet)
+{
+ const char *appid;
+ const char *name;
+ int type;
+ const char *content;
+ const char *icon;
+ int ret;
+
+ if (!packet)
+ return NULL;
+
+ if (packet_get(packet, "ssiss", &appid, &name, &type, &content, &icon) != 5) {
+ ErrPrint("Invalid packet\n");
+ return NULL;
+ }
+
+ DbgPrint("appid[%s], name[%s], type[0x%x], content[%s], icon[%s]\n", appid, name, type, content, icon);
+
+ if (s_info.server_cb.request_cb)
+ ret = s_info.server_cb.request_cb(appid, name, type, content, icon, pid, -1.0f, s_info.server_cb.data);
+ else
+ ret = 0;
+
+ return packet_create_reply(packet, "i", ret);
+}
+
+
+
+static struct packet *add_livebox_handler(pid_t pid, int handle, const struct packet *packet)
+{
+ const char *appid;
+ const char *name;
+ int type;
+ const char *content;
+ const char *icon;
+ double period;
+ int ret;
+
+ if (!packet)
+ return NULL;
+
+ if (packet_get(packet, "ssissd", &appid, &name, &type, &content, &icon, &period) != 6) {
+ ErrPrint("Invalid packet\n");
+ return NULL;
+ }
+
+ DbgPrint("appid[%s], name[%s], type[0x%x], content[%s], icon[%s], period[%lf]\n", appid, name, type, content, icon, period);
+
+ if (s_info.server_cb.request_cb)
+ ret = s_info.server_cb.request_cb(appid, name, type, content, icon, pid, period, s_info.server_cb.data);
+ else
+ ret = 0;
+
+ return packet_create_reply(packet, "i", ret);
+}
+
+
+
+EAPI int shortcut_set_request_cb(request_cb_t request_cb, void *data)
+{
+ s_info.server_cb.request_cb = request_cb;
+ s_info.server_cb.data = data;
+
+ if (s_info.server_fd < 0) {
+ static struct method service_table[] = {
+ {
+ .cmd = "add_shortcut",
+ .handler = add_shortcut_handler,
+ },
+ {
+ .cmd = "add_livebox",
+ .handler = add_livebox_handler,
+ },
+ {
+ .cmd = NULL,
+ .handler = NULL,
+ },
+ };
+
+ unlink(s_info.socket_file); /* Delete previous socket file for creating a new server socket */
+ s_info.server_fd = com_core_packet_server_init(s_info.socket_file, service_table);
+ }
+
+ DbgPrint("Server FD: %d\n", s_info.server_fd);
+
+ return s_info.server_fd > 0 ? 0 : s_info.server_fd;
+}
+
+
+
+struct result_cb_item {
+ result_cb_t result_cb;
+ void *data;
+};
+
+
+
+static int shortcut_send_cb(pid_t pid, int handle, const struct packet *packet, void *data)
+{
+ struct result_cb_item *item = data;
+ int ret;
+
+ if (!packet) {
+ ErrPrint("Packet is not valid\n");
+ ret = -EFAULT;
+ } else if (packet_get(packet, "i", &ret) != 1) {
+ ErrPrint("Packet is not valid\n");
+ ret = -EINVAL;
+ }
+
+ if (item->result_cb)
+ ret = item->result_cb(ret, pid, item->data);
+ else
+ ret = 0;
+ free(item);
+ return ret;
+}
+
+
+
+static int livebox_send_cb(pid_t pid, int handle, const struct packet *packet, void *data)
+{
+ struct result_cb_item *item = data;
+ int ret;
+
+ if (!packet) {
+ ErrPrint("Packet is not valid\n");
+ ret = -EFAULT;
+ } else if (packet_get(packet, "i", &ret) != 1) {
+ ErrPrint("Packet is not valid\n");
+ ret = -EINVAL;
+ }
+
+ if (item->result_cb)
+ ret = item->result_cb(ret, pid, item->data);
+ else
+ ret = 0;
+ free(item);
+ return ret;
+}
+
+
+
+static int disconnected_cb(int handle, void *data)
+{
+ if (s_info.client_fd != handle) {
+ /*!< This is not my favor */
+ return 0;
+ }
+
+ s_info.client_fd = -EINVAL;
+ return 0;
+}
+
+
+
+EAPI int add_to_home_shortcut(const char *appid, const char *name, int type, const char *content, const char *icon, result_cb_t result_cb, void *data)
+{
+ struct packet *packet;
+ struct result_cb_item *item;
+ int ret;
+
+ if (!s_info.initialized) {
+ s_info.initialized = 1;
+ com_core_add_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
+ }
+
+ if (s_info.client_fd < 0) {
+ static struct method service_table[] = {
+ {
+ .cmd = NULL,
+ .handler = NULL,
+ },
+ };
+
+ s_info.client_fd = com_core_packet_client_init(s_info.socket_file, 0, service_table);
+ if (s_info.client_fd < 0) {
+ ErrPrint("Failed to make connection\n");
+ return s_info.client_fd;
+ }
+ }
+
+ item = malloc(sizeof(*item));
+ if (!item) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ return -ENOMEM;
+ }
+
+ item->result_cb = result_cb;
+ item->data = data;
+
+ if (!appid)
+ appid = "";
+
+ if (!name)
+ name = "";
+
+ if (!content)
+ content = "";
+
+ if (!icon)
+ icon = "";
+
+ packet = packet_create("add_shortcut", "ssiss", appid, name, type, content, icon);
+ if (!packet) {
+ ErrPrint("Failed to build a packet\n");
+ free(item);
+ return -EFAULT;
+ }
+
+ ret = com_core_packet_async_send(s_info.client_fd, packet, 0.0f, shortcut_send_cb, item);
+ if (ret < 0) {
+ packet_destroy(packet);
+ free(item);
+ com_core_packet_client_fini(s_info.client_fd);
+ s_info.client_fd = -1;
+ }
+
+ return ret;
+}
+
+
+
+EAPI int add_to_home_livebox(const char *appid, const char *name, int type, const char *content, const char *icon, double period, result_cb_t result_cb, void *data)
+{
+ struct packet *packet;
+ struct result_cb_item *item;
+ int ret;
+
+ if (!s_info.initialized) {
+ s_info.initialized = 1;
+ com_core_add_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
+ }
+
+ if (s_info.client_fd < 0) {
+ static struct method service_table[] = {
+ {
+ .cmd = NULL,
+ .handler = NULL,
+ },
+ };
+
+ s_info.client_fd = com_core_packet_client_init(s_info.socket_file, 0, service_table);
+ if (s_info.client_fd < 0)
+ return s_info.client_fd;
+ }
+
+ item = malloc(sizeof(*item));
+ if (!item) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ return -ENOMEM;
+ }
+
+ item->result_cb = result_cb;
+ item->data = data;
+
+ packet = packet_create("add_livebox", "ssissd", appid, name, type, content, icon, period);
+ if (!packet) {
+ ErrPrint("Failed to build a packet\n");
+ free(item);
+ return -EFAULT;
+ }
+
+ ret = com_core_packet_async_send(s_info.client_fd, packet, 0.0f, livebox_send_cb, item);
+ if (ret < 0) {
+ packet_destroy(packet);
+ free(item);
+ com_core_packet_client_fini(s_info.client_fd);
+ s_info.client_fd = -1;
+ }
+
+ return ret;
+}
+
+
+EAPI int shortcut_add_to_home_with_period(const char *appid, const char *name, int type, const char *content, const char *icon, double period, result_cb_t result_cb, void *data)
+{
+ return add_to_home_livebox(appid, name, type, content, icon, period, result_cb, data);
+}
+
+EAPI int shortcut_add_to_home(const char *appid, const char *name, int type, const char *content, const char *icon, result_cb_t result_cb, void *data)
+{
+ return add_to_home_shortcut(appid, name, type, content, icon, result_cb, data);
+}
+
+static inline int open_db(void)
+{
+ int ret;
+
+ ret = db_util_open(s_info.dbfile, &s_info.handle, DB_UTIL_REGISTER_HOOK_METHOD);
+ if (ret != SQLITE_OK) {
+ DbgPrint("Failed to open a %s\n", s_info.dbfile);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+
+
+/*!
+ * \note this function will returns allocated(heap) string
+ */
+static inline char *get_i18n_name(const char *lang, int id)
+{
+ sqlite3_stmt *stmt;
+ static const char *query = "SELECT name FROM shortcut_name WHERE id = ? AND lang = ? COLLATE NOCASE";
+ const unsigned char *name;
+ char *ret;
+ int status;
+
+ status = sqlite3_prepare_v2(s_info.handle, query, -1, &stmt, NULL);
+ if (status != SQLITE_OK) {
+ ErrPrint("Failed to prepare stmt: %s\n", sqlite3_errmsg(s_info.handle));
+ return NULL;
+ }
+
+ status = sqlite3_bind_int(stmt, 1, id);
+ if (status != SQLITE_OK) {
+ ErrPrint("Failed to bind id: %s\n", sqlite3_errmsg(s_info.handle));
+ ret = NULL;
+ goto out;
+ }
+
+ status = sqlite3_bind_text(stmt, 2, lang, -1, NULL);
+ if (status != SQLITE_OK) {
+ ErrPrint("Failed to bind lang: %s\n", sqlite3_errmsg(s_info.handle));
+ ret = NULL;
+ goto out;
+ }
+
+ DbgPrint("id: %d, lang: %s\n", id, lang);
+ if (SQLITE_ROW != sqlite3_step(stmt)) {
+ ErrPrint("Failed to do step: %s\n", sqlite3_errmsg(s_info.handle));
+ ret = NULL;
+ goto out;
+ }
+
+ name = sqlite3_column_text(stmt, 0);
+ ret = name ? strdup((const char *)name) : NULL;
+
+out:
+ sqlite3_reset(stmt);
+ sqlite3_clear_bindings(stmt);
+ sqlite3_finalize(stmt);
+ return ret;
+}
+
+
+
+static inline int homescreen_get_i18n(const char *appid, const char *lang, char **name, char **desc)
+{
+ sqlite3_stmt *stmt;
+ static const char *query = "SELECT name, desc FROM desc WHERE appid = ? AND lang = ?";
+ const unsigned char *_name;
+ const unsigned char *_desc;
+ int status;
+
+ status = sqlite3_prepare_v2(s_info.handle, query, -1, &stmt, NULL);
+ if (status != SQLITE_OK) {
+ ErrPrint("Failed to prepare stmt: %s\n", sqlite3_errmsg(s_info.handle));
+ return -EIO;
+ }
+
+ status = sqlite3_bind_text(stmt, 1, appid, -1, NULL);
+ if (status != SQLITE_OK) {
+ ErrPrint("Failed to bind appid: %s\n", sqlite3_errmsg(s_info.handle));
+ status = -EIO;
+ goto out;
+ }
+
+ status = sqlite3_bind_text(stmt, 2, lang, -1, NULL);
+ if (status != SQLITE_OK) {
+ ErrPrint("Failed to bind lang: %s\n", sqlite3_errmsg(s_info.handle));
+ status = -EIO;
+ goto out;
+ }
+
+ if (SQLITE_ROW != sqlite3_step(stmt)) {
+ ErrPrint("Failed to do step: %s\n", sqlite3_errmsg(s_info.handle));
+ status = -EIO;
+ goto out;
+ }
+
+ if (name) {
+ _name = sqlite3_column_text(stmt, 0);
+ *name = _name ? strdup((const char *)_name) : NULL;
+ }
+
+ if (desc) {
+ _desc = sqlite3_column_text(stmt, 1);
+ *desc = _desc ? strdup((const char *)_desc) : NULL;
+ }
+
+out:
+ sqlite3_reset(stmt);
+ sqlite3_clear_bindings(stmt);
+ sqlite3_finalize(stmt);
+ return status;
+}
+
+
+
+/*!
+ * cb: SYNC callback
+ */
+EAPI int homescreen_get_description(const char *appid, void (*cb)(const char *appid, const char *icon, const char *name, const char *desc, void *data), void *data)
+{
+ sqlite3_stmt *stmt;
+ static const char *query = "SELECT icon, name, desc FROM homescreen WHERE appid = ?";
+ char *i18n_name;
+ char *i18n_desc;
+ const unsigned char *desc;
+ const unsigned char *name;
+ const unsigned char *icon;
+ int ret;
+
+ ret = sqlite3_prepare_v2(s_info.handle, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ ErrPrint("Prepare failed: %s\n", sqlite3_errmsg(s_info.handle));
+ ret = -EIO;
+ goto out;
+ }
+
+ ret = sqlite3_bind_text(stmt, 1, appid, -1, NULL);
+ if (ret != SQLITE_OK) {
+ ErrPrint("Prepare failed: %s\n", sqlite3_errmsg(s_info.handle));
+ ret = -EIO;
+ goto out;
+ }
+
+ if (SQLITE_ROW != sqlite3_step(stmt)) {
+ ErrPrint("Step failed: %s\n", sqlite3_errmsg(s_info.handle));
+ ret = -EIO;
+ goto out;
+ }
+
+ icon = sqlite3_column_text(stmt, 0);
+ name = sqlite3_column_text(stmt, 1);
+ desc = sqlite3_column_text(stmt, 2);
+
+ /*!
+ * \todo
+ * Get the i18n name and desc
+ */
+ if (homescreen_get_i18n(appid, "en-us", &i18n_name, &i18n_desc) < 0) {
+ i18n_name = NULL;
+ i18n_desc = NULL;
+ }
+
+ cb(appid, (const char *)icon, i18n_name ? i18n_name : (const char *)name, i18n_desc ? i18n_desc : (const char *)desc, data);
+
+ free(i18n_name);
+ free(i18n_desc);
+
+out:
+ sqlite3_reset(stmt);
+ sqlite3_clear_bindings(stmt);
+ sqlite3_finalize(stmt);
+ return ret;
+}
+
+
+
+EAPI char *homescreen_get_image(const char *appid, int idx)
+{
+ static const char *query = "SELECT path FROM image WHERE appid = ? AND id = ?";
+ sqlite3_stmt *stmt;
+ int ret;
+ const unsigned char *path;
+ char *ret_path = NULL;
+
+ ret = sqlite3_prepare_v2(s_info.handle, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ ErrPrint("Prepare failed: %s\n", sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ ret = sqlite3_bind_text(stmt, 1, appid, -1, NULL);
+ if (ret != SQLITE_OK) {
+ ErrPrint("bind failed: %s\n", sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ ret = sqlite3_bind_int(stmt, 2, idx);
+ if (ret != SQLITE_OK) {
+ ErrPrint("bind failed: %s\n", sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ if (SQLITE_ROW != sqlite3_step(stmt)) {
+ ErrPrint("Step failed: %s\n", sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ path = sqlite3_column_text(stmt, 0);
+ if (!path) {
+ ErrPrint("Get result: %s\n", sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ ret_path = strdup((const char *)path);
+ if (!ret_path)
+ ErrPrint("Heap: %s\n", strerror(errno));
+
+out:
+ sqlite3_reset(stmt);
+ sqlite3_clear_bindings(stmt);
+ sqlite3_finalize(stmt);
+ return ret_path;
+}
+
+
+
+EAPI int homescreen_get_image_count(const char *appid)
+{
+ static const char *query = "SELECT COUNT(id) FROM image WHERE appid = ?";
+ sqlite3_stmt *stmt;
+ int ret;
+
+ ret = sqlite3_prepare_v2(s_info.handle, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ ErrPrint("bind failed: %s\n", sqlite3_errmsg(s_info.handle));
+ ret = -EIO;
+ goto out;
+ }
+
+ ret = sqlite3_bind_text(stmt, 1, appid, -1, NULL);
+ if (ret != SQLITE_OK) {
+ ErrPrint("bind failed: %s\n", sqlite3_errmsg(s_info.handle));
+ ret = -EIO;
+ goto out;
+ }
+
+ if (SQLITE_ROW != sqlite3_step(stmt)) {
+ ErrPrint("step failed: %s\n", sqlite3_errmsg(s_info.handle));
+ ret = -EIO;
+ goto out;
+ }
+
+ ret = sqlite3_column_int(stmt, 0);
+
+out:
+ sqlite3_reset(stmt);
+ sqlite3_clear_bindings(stmt);
+ sqlite3_finalize(stmt);
+ return ret;
+}
+
+
+
+static inline char *cur_locale(void)
+{
+ char *language;
+ language = vconf_get_str(VCONFKEY_LANGSET);
+ if (language) {
+ char *ptr;
+
+ ptr = language;
+ while (*ptr) {
+ if (*ptr == '.') {
+ *ptr = '\0';
+ break;
+ }
+
+ if (*ptr == '_')
+ *ptr = '-';
+
+ ptr++;
+ }
+ } else {
+ language = strdup("en-us");
+ if (!language)
+ ErrPrint("Heap: %s\n", strerror(errno));
+ }
+
+ return language;
+}
+
+
+
+/*!
+ * \note READ ONLY DB
+ */
+EAPI int shortcut_get_list(const char *appid, int (*cb)(const char *appid, const char *icon, const char *name, const char *extra_key, const char *extra_data, void *data), void *data)
+{
+ sqlite3_stmt *stmt;
+ const char *query;
+ const unsigned char *name;
+ char *i18n_name;
+ const unsigned char *extra_data;
+ const unsigned char *extra_key;
+ const unsigned char *icon;
+ int id;
+ int ret;
+ int cnt;
+ char *language;
+
+ if (!s_info.db_opened)
+ s_info.db_opened = (open_db() == 0);
+
+ if (!s_info.db_opened) {
+ ErrPrint("Failed to open a DB\n");
+ return -EIO;
+ }
+
+ language = cur_locale();
+ if (!language) {
+ ErrPrint("Locale is not valid\n");
+ return -EINVAL;
+ }
+
+ if (appid) {
+ query = "SELECT id, appid, name, extra_key, extra_data, icon FROM shortcut_service WHERE appid = ?";
+ ret = sqlite3_prepare_v2(s_info.handle, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ ErrPrint("prepare: %s\n", sqlite3_errmsg(s_info.handle));
+ free(language);
+ return -EIO;
+ }
+
+ ret = sqlite3_bind_text(stmt, 1, appid, -1, NULL);
+ if (ret != SQLITE_OK) {
+ ErrPrint("bind text: %s\n", sqlite3_errmsg(s_info.handle));
+ sqlite3_finalize(stmt);
+ free(language);
+ return -EIO;
+ }
+ } else {
+ query = "SELECT id, appid, name, extra_key, extra_data, icon FROM shortcut_service";
+ ret = sqlite3_prepare_v2(s_info.handle, query, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ ErrPrint("prepare: %s\n", sqlite3_errmsg(s_info.handle));
+ free(language);
+ return -EIO;
+ }
+ }
+
+ cnt = 0;
+ while (SQLITE_ROW == sqlite3_step(stmt)) {
+ id = sqlite3_column_int(stmt, 0);
+
+ appid = (const char *)sqlite3_column_text(stmt, 1);
+ if (!appid) {
+ LOGE("Failed to get package name\n");
+ continue;
+ }
+
+ name = sqlite3_column_text(stmt, 2);
+ if (!name) {
+ LOGE("Failed to get name\n");
+ continue;
+ }
+
+ extra_key = sqlite3_column_text(stmt, 3);
+ if (!extra_key) {
+ LOGE("Failed to get service\n");
+ continue;
+ }
+
+ extra_data = sqlite3_column_text(stmt, 4);
+ if (!extra_data) {
+ LOGE("Failed to get service\n");
+ continue;
+ }
+
+ icon = sqlite3_column_text(stmt, 5);
+ if (!icon) {
+ LOGE("Failed to get icon\n");
+ continue;
+ }
+
+ /*!
+ * \todo
+ * Implement the "GET LOCALE" code
+ */
+ i18n_name = get_i18n_name(language, id);
+
+ cnt++;
+ if (cb(appid, (char *)icon, (i18n_name != NULL ? i18n_name : (char *)name), (char *)extra_key, (char *)extra_data, data) < 0) {
+ free(i18n_name);
+ break;
+ }
+
+ free(i18n_name);
+ }
+
+ sqlite3_reset(stmt);
+ sqlite3_clear_bindings(stmt);
+ sqlite3_finalize(stmt);
+ free(language);
+ return cnt;
+}
+
+
+
+/* End of a file */
diff --git a/libshortcut.manifest b/libshortcut.manifest
new file mode 100644
index 0000000..f1055e7
--- /dev/null
+++ b/libshortcut.manifest
@@ -0,0 +1,22 @@
+<manifest>
+ <!-- Shortcut service -->
+ <define>
+ <domain name="shortcut-service" policy="restricted" />
+ <provide>
+ <label name="shortcut-service::db" />
+ </provide>
+ </define>
+ <request>
+ <domain name="_" />
+ </request>
+
+ <assign>
+ <!-- Executable file -->
+ <filesystem path="/usr/lib/libshortcut.so.0.0.1" label="_" />
+ <filesystem path="/usr/etc/package-manager/parserlib/libshortcut-list.so" label="_" />
+
+ <!-- Database file -->
+ <filesystem path="/opt/dbspace/.shortcut_service.db" label="shortcut-service::db" />
+ <filesystem path="/opt/dbspace/.shortcut_service.db-journal" label="shortcut-service::db" />
+ </assign>
+</manifest>
diff --git a/packaging/libshortcut.spec b/packaging/libshortcut.spec
new file mode 100644
index 0000000..73eaf59
--- /dev/null
+++ b/packaging/libshortcut.spec
@@ -0,0 +1,66 @@
+Name: libshortcut
+Summary: Shortcut add feature supporting library
+Version: 0.3.17
+Release: 0
+Group: main/devel
+License: Apache License
+Source0: %{name}-%{version}.tar.gz
+
+Requires(post): /sbin/ldconfig
+Requires(postun): /sbin/ldconfig
+
+BuildRequires: cmake, gettext-tools, coreutils
+BuildRequires: pkgconfig(glib-2.0)
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(db-util)
+BuildRequires: pkgconfig(sqlite3)
+BuildRequires: pkgconfig(com-core)
+BuildRequires: pkgconfig(libxml-2.0)
+BuildRequires: pkgconfig(vconf)
+
+%description
+[Shortcut] AddToHome feature supporting library for menu/home screen developers.
+
+%package devel
+Summary: AddToHome feature supporting library development files
+Group: Development/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description devel
+[Shortcut] AddToHome feature supporting library for menu/home screen developers
+(dev).
+
+%prep
+%setup -q
+
+%build
+cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix}
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+%make_install
+mkdir -p %{buildroot}/opt/dbspace
+touch %{buildroot}/opt/dbspace/.shortcut_service.db
+touch %{buildroot}/opt/dbspace/.shortcut_service.db-journal
+
+%post
+
+%postun
+
+%files -n libshortcut
+%manifest libshortcut.manifest
+%defattr(-,root,root,-)
+%{_libdir}/*.so*
+%{_prefix}/etc/package-manager/parserlib/*
+%{_datarootdir}/license/*
+%attr(640,root,app) /opt/dbspace/.shortcut_service.db
+%attr(640,root,app) /opt/dbspace/.shortcut_service.db-journal
+
+%files devel
+%defattr(-,root,root,-)
+%{_includedir}/shortcut/shortcut_PG.h
+%{_includedir}/shortcut/shortcut.h
+%{_libdir}/pkgconfig/shortcut.pc
+
+# End of a file
diff --git a/pkgmgr_shortcut/CMakeLists.txt b/pkgmgr_shortcut/CMakeLists.txt
new file mode 100644
index 0000000..0a4abc7
--- /dev/null
+++ b/pkgmgr_shortcut/CMakeLists.txt
@@ -0,0 +1,31 @@
+PROJECT(shortcut-list C)
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/pkgmgr_shortcut/include)
+
+INCLUDE(FindPkgConfig)
+pkg_check_modules(bin_pkgs REQUIRED
+ dlog
+ sqlite3
+ libxml-2.0
+ db-util
+)
+
+FOREACH(flag ${bin_pkgs_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -g -Wall -Werror")
+
+ADD_DEFINITIONS("-DPREFIX=\"${PREFIX}\"")
+ADD_DEFINITIONS("-DLOG_TAG=\"PKGMGR_SHORTCUT\"")
+
+ADD_LIBRARY(${PROJECT_NAME} SHARED
+ src/service_register.c
+ src/dlist.c
+)
+
+TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${bin_pkgs_LDFLAGS})
+
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION "etc/package-manager/parserlib")
+
+# End of a file
diff --git a/pkgmgr_shortcut/include/dlist.h b/pkgmgr_shortcut/include/dlist.h
new file mode 100644
index 0000000..f840f92
--- /dev/null
+++ b/pkgmgr_shortcut/include/dlist.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2000 - 2011 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.
+ *
+*/
+
+#define dlist_remove_data(list, data) do { \
+ struct dlist *l; \
+ l = dlist_find_data(list, data); \
+ list = dlist_remove(list, l); \
+} while (0)
+
+#define dlist_foreach(list, l, data) \
+ for ((l) = (list); (l) && ((data) = dlist_data(l)); (l) = dlist_next(l))
+
+#define dlist_foreach_safe(list, l, n, data) \
+ for ((l) = (list), (n) = dlist_next(l); \
+ (l) && ((data) = dlist_data(l)); \
+ (l) = (n), (n) = dlist_next(l))
+
+struct dlist;
+
+extern struct dlist *dlist_append(struct dlist *list, void *data);
+extern struct dlist *dlist_prepend(struct dlist *list, void *data);
+extern struct dlist *dlist_remove(struct dlist *list, struct dlist *l);
+extern struct dlist *dlist_find_data(struct dlist *list, void *data);
+extern void *dlist_data(struct dlist *l);
+extern struct dlist *dlist_next(struct dlist *l);
+extern struct dlist *dlist_prev(struct dlist *l);
+extern int dlist_count(struct dlist *l);
+extern struct dlist *dlist_nth(struct dlist *l, int nth);
+
+/* End of a file */
diff --git a/pkgmgr_shortcut/src/dlist.c b/pkgmgr_shortcut/src/dlist.c
new file mode 100644
index 0000000..a212608
--- /dev/null
+++ b/pkgmgr_shortcut/src/dlist.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2000 - 2011 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 <assert.h>
+
+#include "dlist.h"
+
+/*!
+ * \brief
+ * This dlist is called Modified Doubly Linked List.
+ *
+ * Noramlly, The dobule linked list contains address of previous and next element.
+ * This dlist also contains them, but the tail element only contains prev address.
+ *
+ * The head element's prev pointer indicates the last element.
+ * But the last element's next pointer indicates NIL.
+ *
+ * So we can find the last element while crawling this DList
+ * But we have to remember the address of the head element.
+ */
+
+struct dlist {
+ struct dlist *next;
+ struct dlist *prev;
+ void *data;
+};
+
+struct dlist *dlist_append(struct dlist *list, void *data)
+{
+ struct dlist *item;
+
+ item = malloc(sizeof(*item));
+ if (!item)
+ return NULL;
+
+ item->next = NULL;
+ item->data = data;
+
+ if (!list) {
+ item->prev = item;
+
+ list = item;
+ } else {
+ item->prev = list->prev;
+ item->prev->next = item;
+ list->prev = item;
+ }
+
+ assert(!list->prev->next && "item NEXT");
+
+ return list;
+}
+
+struct dlist *dlist_prepend(struct dlist *list, void *data)
+{
+ struct dlist *item;
+
+ item = malloc(sizeof(*item));
+ if (!item)
+ return NULL;
+
+ item->data = data;
+
+ if (!list) {
+ item->prev = item;
+ item->next = NULL;
+ } else {
+ if (list->prev->next)
+ list->prev->next = item;
+
+ item->prev = list->prev;
+ item->next = list;
+
+ list->prev = item;
+
+ }
+
+ return item;
+}
+
+struct dlist *dlist_remove(struct dlist *list, struct dlist *l)
+{
+ if (!list || !l)
+ return NULL;
+
+ if (l == list)
+ list = l->next;
+ else
+ l->prev->next = l->next;
+
+ if (l->next)
+ l->next->prev = l->prev;
+ /*!
+ * \note
+ * If the removed entry 'l' has no next element, it is the last element.
+ * In this case, check the existence of the list first,
+ * and if the list is not empty, update the 'prev' of the list (which is a head element of the list)
+ *
+ * If we didn't care about this, the head element(list) can indicates the invalid element.
+ */
+ else if (list)
+ list->prev = l->prev;
+
+ free(l);
+ return list;
+}
+
+struct dlist *dlist_find_data(struct dlist *list, void *data)
+{
+ struct dlist *l;
+ void *_data;
+
+ dlist_foreach(list, l, _data) {
+ if (data == _data)
+ return l;
+ }
+
+ return NULL;
+}
+
+void *dlist_data(struct dlist *l)
+{
+ return l ? l->data : NULL;
+}
+
+struct dlist *dlist_next(struct dlist *l)
+{
+ return l ? l->next : NULL;
+}
+
+struct dlist *dlist_prev(struct dlist *l)
+{
+ return l ? l->prev : NULL;
+}
+
+int dlist_count(struct dlist *l)
+{
+ register int i;
+ struct dlist *n;
+ void *data;
+
+ i = 0;
+ dlist_foreach(l, n, data) {
+ i++;
+ }
+
+ return i;
+}
+
+struct dlist *dlist_nth(struct dlist *l, int nth)
+{
+ register int i;
+ struct dlist *n;
+
+ i = 0;
+ for (n = l; n; n = n->next) {
+ if (i == nth)
+ return n;
+ i++;
+ }
+
+ return NULL;
+}
+
+/* End of a file */
diff --git a/pkgmgr_shortcut/src/service_register.c b/pkgmgr_shortcut/src/service_register.c
new file mode 100644
index 0000000..6e8b618
--- /dev/null
+++ b/pkgmgr_shortcut/src/service_register.c
@@ -0,0 +1,776 @@
+/*
+ * Copyright (c) 2000 - 2011 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 <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <libgen.h>
+#include <string.h>
+
+#include <sqlite3.h>
+#include <db-util.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <dlog.h>
+
+#include "dlist.h"
+
+#if !defined(FLOG)
+#define DbgPrint(format, arg...) LOGD("[%s/%s:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg)
+#define ErrPrint(format, arg...) LOGE("[%s/%s:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg)
+#endif
+/* End of a file */
+
+/*!
+ * DB Table schema
+ *
+ * +----+-------+------+---------+-----------+------------+
+ * | id | appid | Icon | Name | extra_key | extra_data |
+ * +----+-------+------+---------+-----------+------------+
+ * | id | - | - | - | - | - |
+ * +----+-------+------+---------+-----------+------------+
+ *
+ * +----+------+------+
+ * | fk | lang | name |
+ * +----+------+------+
+ * | id | - | - |
+ * +----+------+------+
+ */
+
+#if !defined(LIBXML_TREE_ENABLED)
+ #error "LIBXML is not supporting the tree"
+#endif
+
+int errno;
+
+static struct {
+ const char *dbfile;
+ sqlite3 *handle;
+} s_info = {
+ .dbfile = "/opt/dbspace/.shortcut_service.db",
+ .handle = NULL,
+};
+
+static inline int begin_transaction(void)
+{
+ sqlite3_stmt *stmt;
+ int ret;
+
+ ret = sqlite3_prepare_v2(s_info.handle, "BEGIN TRANSACTION", -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
+ return EXIT_FAILURE;
+ }
+
+ if (sqlite3_step(stmt) != SQLITE_DONE) {
+ DbgPrint("Failed to do update (%s)\n",
+ sqlite3_errmsg(s_info.handle));
+ sqlite3_finalize(stmt);
+ return EXIT_FAILURE;
+ }
+
+ sqlite3_finalize(stmt);
+ return EXIT_SUCCESS;
+}
+
+static inline int rollback_transaction(void)
+{
+ int ret;
+ sqlite3_stmt *stmt;
+
+ ret = sqlite3_prepare_v2(s_info.handle, "ROLLBACK TRANSACTION", -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
+ return EXIT_FAILURE;
+ }
+
+ if (sqlite3_step(stmt) != SQLITE_DONE) {
+ DbgPrint("Failed to do update (%s)\n",
+ sqlite3_errmsg(s_info.handle));
+ sqlite3_finalize(stmt);
+ return EXIT_FAILURE;
+ }
+
+ sqlite3_finalize(stmt);
+ return EXIT_SUCCESS;
+}
+
+static inline int commit_transaction(void)
+{
+ sqlite3_stmt *stmt;
+ int ret;
+
+ ret = sqlite3_prepare_v2(s_info.handle, "COMMIT TRANSACTION", -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
+ return EXIT_FAILURE;
+ }
+
+ if (sqlite3_step(stmt) != SQLITE_DONE) {
+ DbgPrint("Failed to do update (%s)\n",
+ sqlite3_errmsg(s_info.handle));
+ sqlite3_finalize(stmt);
+ return EXIT_FAILURE;
+ }
+
+ sqlite3_finalize(stmt);
+ return EXIT_SUCCESS;
+}
+static inline void db_create_table(void)
+{
+ char *err;
+ static const char *ddl =
+ "CREATE TABLE shortcut_service ("
+ "id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "appid TEXT, "
+ "icon TEXT, "
+ "name TEXT, "
+ "extra_key TEXT, "
+ "extra_data TEXT)";
+
+ if (sqlite3_exec(s_info.handle, ddl, NULL, NULL, &err) != SQLITE_OK) {
+ ErrPrint("Failed to execute the DDL (%s)\n", err);
+ return;
+ }
+
+ if (sqlite3_changes(s_info.handle) == 0)
+ ErrPrint("No changes to DB\n");
+
+ ddl = "CREATE TABLE shortcut_name (id INTEGER, lang TEXT, name TEXT)";
+ if (sqlite3_exec(s_info.handle, ddl, NULL, NULL, &err) != SQLITE_OK) {
+ ErrPrint("Failed to execute the DDL (%s)\n", err);
+ return;
+ }
+
+ if (sqlite3_changes(s_info.handle) == 0)
+ ErrPrint("No changes to DB\n");
+}
+
+static inline int db_remove_record(const char *appid, const char *key, const char *data)
+{
+ static const char *dml = "DELETE FROM shortcut_service WHERE appid = ? AND extra_key = ? AND extra_data = ?";
+ sqlite3_stmt *stmt;
+ int ret;
+
+ if (!appid || !key || !data) {
+ ErrPrint("Invalid argument\n");
+ return -EINVAL;
+ }
+
+ ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ ErrPrint("Failed to prepare the initial DML(%s)\n", sqlite3_errmsg(s_info.handle));
+ return -EIO;
+ }
+
+ ret = -EIO;
+ if (sqlite3_bind_text(stmt, 1, appid, -1, NULL) != SQLITE_OK) {
+ ErrPrint("Failed to bind a appid(%s)\n", sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ if (sqlite3_bind_text(stmt, 2, key, -1, NULL) != SQLITE_OK) {
+ ErrPrint("Failed to bind a key(%s)\n", sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ if (sqlite3_bind_text(stmt, 3, data, -1, NULL) != SQLITE_OK) {
+ ErrPrint("Failed to bind a data(%s)\n", sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ ret = 0;
+ if (sqlite3_step(stmt) != SQLITE_DONE) {
+ ret = -EIO;
+ ErrPrint("Failed to execute the DML for %s - %s(%s)\n", appid, key, data);
+ }
+
+ if (sqlite3_changes(s_info.handle) == 0)
+ DbgPrint("No changes\n");
+
+out:
+ sqlite3_reset(stmt);
+ sqlite3_clear_bindings(stmt);
+ sqlite3_finalize(stmt);
+ return ret;
+}
+
+static inline int db_remove_name(int id)
+{
+ static const char *dml = "DELETE FROM shortcut_name WHERE id = ?";
+ sqlite3_stmt *stmt;
+ int ret;
+
+ if (id < 0) {
+ ErrPrint("Inavlid id\n");
+ return -EINVAL;
+ }
+
+ ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ ErrPrint("Failed to prepare the initial DML(%s)\n", sqlite3_errmsg(s_info.handle));
+ return -EIO;
+ }
+
+ if (sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) {
+ ErrPrint("Failed to bind id(%d)\n", id);
+ ret = -EIO;
+ goto out;
+ }
+
+ ret = 0;
+ if (sqlite3_step(stmt) != SQLITE_DONE) {
+ ret = -EIO;
+ ErrPrint("Failed to execute the DML for %d\n", id);
+ goto out;
+ }
+
+ if (sqlite3_changes(s_info.handle) == 0)
+ DbgPrint("No changes\n");
+
+out:
+ sqlite3_reset(stmt);
+ sqlite3_clear_bindings(stmt);
+ sqlite3_finalize(stmt);
+ return ret;
+}
+
+static inline int db_insert_record(const char *appid, const char *icon, const char *name, const char *key, const char *data)
+{
+ static const char *dml = "INSERT INTO shortcut_service (appid, icon, name, extra_key, extra_data) VALUES (?, ?, ?, ?, ?)";
+ sqlite3_stmt *stmt;
+ int ret;
+
+ if (!appid) {
+ ErrPrint("Failed to get appid\n");
+ return -EINVAL;
+ }
+
+ if (!name) {
+ ErrPrint("Failed to get name\n");
+ return -EINVAL;
+ }
+
+ if (!key) {
+ ErrPrint("Failed to get key\n");
+ return -EINVAL;
+ }
+
+ if (!data) {
+ ErrPrint("Faield to get key\n");
+ return -EINVAL;
+ }
+
+ icon = icon ? icon : "";
+
+ ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ ErrPrint("Failed to prepare the initial DML(%s)\n", sqlite3_errmsg(s_info.handle));
+ return -EIO;
+ }
+
+ ret = -EIO;
+ if (sqlite3_bind_text(stmt, 1, appid, -1, NULL) != SQLITE_OK) {
+ ErrPrint("Failed to bind a appid(%s)\n", sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ if (sqlite3_bind_text(stmt, 2, icon, -1, NULL) != SQLITE_OK) {
+ ErrPrint("Failed to bind a icon(%s)\n", sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ if (sqlite3_bind_text(stmt, 3, name, -1, NULL) != SQLITE_OK) {
+ ErrPrint("Failed to bind a name(%s)\n", sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ if (sqlite3_bind_text(stmt, 4, key, -1, NULL) != SQLITE_OK) {
+ ErrPrint("Failed to bind a service(%s)\n", sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ if (sqlite3_bind_text(stmt, 5, data, -1, NULL) != SQLITE_OK) {
+ ErrPrint("Failed to bind a service(%s)\n", sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ ret = 0;
+ if (sqlite3_step(stmt) != SQLITE_DONE) {
+ ErrPrint("Failed to execute the DML for %s - %s\n", appid, name);
+ ret = -EIO;
+ }
+
+out:
+ sqlite3_reset(stmt);
+ sqlite3_clear_bindings(stmt);
+ sqlite3_finalize(stmt);
+ return ret;
+}
+
+static inline int db_insert_name(int id, const char *lang, const char *name)
+{
+ static const char *dml = "INSERT INTO shortcut_name (id, lang, name) VALUES (?, ?, ?)";
+ sqlite3_stmt *stmt;
+ int ret;
+
+ if (id < 0 || !lang || !name) {
+ ErrPrint("Invalid parameters\n");
+ return -EINVAL;
+ }
+
+ ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ ErrPrint("Failed to prepare the initial DML(%s)\n", sqlite3_errmsg(s_info.handle));
+ return -EIO;
+ }
+
+ if (sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) {
+ ErrPrint("Failed to bind a id(%s)\n", sqlite3_errmsg(s_info.handle));
+ ret = -EIO;
+ goto out;
+ }
+
+ if (sqlite3_bind_text(stmt, 2, lang, -1, NULL) != SQLITE_OK) {
+ ErrPrint("Failed to bind a id(%s)\n", sqlite3_errmsg(s_info.handle));
+ ret = -EIO;
+ goto out;
+ }
+
+ if (sqlite3_bind_text(stmt, 3, name, -1, NULL) != SQLITE_OK) {
+ ErrPrint("Failed to bind a id(%s)\n", sqlite3_errmsg(s_info.handle));
+ ret = -EIO;
+ goto out;
+ }
+
+ ret = 0;
+ if (sqlite3_step(stmt) != SQLITE_DONE) {
+ ErrPrint("Failed to execute the DML for %d %s %s\n", id, lang, name);
+ ret = -EIO;
+ }
+
+out:
+ sqlite3_reset(stmt);
+ sqlite3_clear_bindings(stmt);
+ sqlite3_finalize(stmt);
+ return ret;
+}
+
+static inline int db_get_id(const char *appid, const char *key, const char *data)
+{
+ static const char *dml = "SELECT id FROM shortcut_service WHERE appid = ? AND extra_key = ? AND extra_data = ?";
+ sqlite3_stmt *stmt;
+ int ret;
+
+ if (!appid || !key || !data) {
+ ErrPrint("Invalid argument\n");
+ return -EINVAL;
+ }
+
+ ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ ErrPrint("Failed to prepare the initial DML(%s)\n", sqlite3_errmsg(s_info.handle));
+ return -EIO;
+ }
+
+ ret = -EIO;
+ if (sqlite3_bind_text(stmt, 1, appid, -1, NULL) != SQLITE_OK) {
+ ErrPrint("Failed to bind a appid(%s) - %s\n", appid, sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ if (sqlite3_bind_text(stmt, 2, key, -1, NULL) != SQLITE_OK) {
+ ErrPrint("Failed to bind a key(%s) - %s\n", key, sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ if (sqlite3_bind_text(stmt, 3, data, -1, NULL) != SQLITE_OK) {
+ ErrPrint("Failed to bind a data(%s) - %s\n", data, sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ if (sqlite3_step(stmt) != SQLITE_ROW) {
+ ErrPrint("Failed to execute the DML for %s - %s, %s\n", appid, key, data);
+ ret = -EIO;
+ goto out;
+ }
+
+ ret = sqlite3_column_int(stmt, 0);
+
+out:
+ sqlite3_reset(stmt);
+ sqlite3_clear_bindings(stmt);
+ sqlite3_finalize(stmt);
+ return ret;
+}
+
+static inline int db_init(void)
+{
+ int ret;
+ struct stat stat;
+
+ ret = db_util_open(s_info.dbfile, &s_info.handle, DB_UTIL_REGISTER_HOOK_METHOD);
+ if (ret != SQLITE_OK) {
+ ErrPrint("Failed to open a DB\n");
+ return -EIO;
+ }
+
+ if (lstat(s_info.dbfile, &stat) < 0) {
+ ErrPrint("%s\n", strerror(errno));
+ db_util_close(s_info.handle);
+ s_info.handle = NULL;
+ return -EIO;
+ }
+
+ if (!S_ISREG(stat.st_mode)) {
+ ErrPrint("Invalid file\n");
+ db_util_close(s_info.handle);
+ s_info.handle = NULL;
+ return -EINVAL;
+ }
+
+ if (!stat.st_size)
+ db_create_table();
+
+ return 0;
+}
+
+static inline int db_fini(void)
+{
+ if (!s_info.handle)
+ return 0;
+
+ db_util_close(s_info.handle);
+ s_info.handle = NULL;
+
+ return 0;
+}
+
+int PKGMGR_PARSER_PLUGIN_UPGRADE(xmlDocPtr docPtr, const char *appid)
+{
+ xmlNodePtr root;
+
+ root = xmlDocGetRootElement(docPtr);
+ if (!root) {
+ ErrPrint("Invalid node ptr\n");
+ return -EINVAL;
+ }
+
+ if (!s_info.handle) {
+ if (db_init() < 0)
+ return -EIO;
+ }
+
+ for (root = root->children; root; root = root->next) {
+ if (!xmlStrcasecmp(root->name, (const xmlChar *)"shortcut-list"))
+ break;
+ }
+
+ if (!root) {
+ ErrPrint("Root has no shortcut-list\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int PKGMGR_PARSER_PLUGIN_UNINSTALL(xmlDocPtr docPtr, const char *_appid)
+{
+ xmlNodePtr node = NULL;
+ xmlChar *key;
+ xmlChar *data;
+ xmlChar *appid;
+ xmlNodePtr root;
+ int id;
+
+ root = xmlDocGetRootElement(docPtr);
+ if (!root) {
+ ErrPrint("Invalid node ptr\n");
+ return -EINVAL;
+ }
+
+ if (!s_info.handle) {
+ if (db_init() < 0)
+ return -EIO;
+ }
+
+ for (root = root->children; root; root = root->next) {
+ if (!xmlStrcasecmp(root->name, (const xmlChar *)"shortcut-list"))
+ break;
+ }
+
+ if (!root) {
+ ErrPrint("Root has no shortcut-list\n");
+ return -EINVAL;
+ }
+
+ DbgPrint("AppID: %s\n", _appid);
+ root = root->children;
+ for (node = root; node; node = node->next) {
+ if (node->type == XML_ELEMENT_NODE)
+ DbgPrint("Element %s\n", node->name);
+
+ if (xmlStrcasecmp(node->name, (const xmlChar *)"shortcut"))
+ continue;
+
+ if (!xmlHasProp(node, (xmlChar *)"extra_data")
+ || !xmlHasProp(node, (xmlChar *)"extra_key")
+ || !xmlHasProp(node, (xmlChar *)"appid"))
+ {
+ DbgPrint("Invalid element %s\n", node->name);
+ continue;
+ }
+
+ appid = xmlGetProp(node, (xmlChar *)"appid");
+ key = xmlGetProp(node, (xmlChar *)"extra_key");
+ data = xmlGetProp(node, (xmlChar *)"extra_data");
+
+ DbgPrint("appid: %s\n", appid);
+ DbgPrint("key: %s\n", key);
+ DbgPrint("data: %s\n", data);
+
+ id = db_get_id((char *)appid, (char *)key, (char *)data);
+ if (id < 0) {
+ ErrPrint("No records found\n");
+ xmlFree(appid);
+ xmlFree(key);
+ xmlFree(data);
+ continue;
+ }
+
+ begin_transaction();
+ if (db_remove_record((char *)appid, (char *)key, (char *)data) < 0) {
+ ErrPrint("Failed to remove a record\n");
+ rollback_transaction();
+ xmlFree(appid);
+ xmlFree(key);
+ xmlFree(data);
+ continue;
+ }
+
+ if (db_remove_name(id) < 0) {
+ ErrPrint("Failed to remove name records\n");
+ rollback_transaction();
+ xmlFree(appid);
+ xmlFree(key);
+ xmlFree(data);
+ continue;
+ }
+ commit_transaction();
+ xmlFree(appid);
+ xmlFree(key);
+ xmlFree(data);
+
+ /*!
+ * \note
+ * if (node->children)
+ * DbgPrint("Skip this node's children\n");
+ */
+ }
+
+ return 0;
+}
+
+int PKGMGR_PARSER_PLUGIN_INSTALL(xmlDocPtr docPtr, const char *appid)
+{
+ xmlNodePtr node = NULL;
+ xmlNodePtr child = NULL;
+ xmlChar *key;
+ xmlChar *data;
+ xmlChar *name;
+ xmlChar *icon;
+ xmlChar *shortcut_appid;
+ xmlNodePtr root;
+ struct i18n_name {
+ xmlChar *name;
+ xmlChar *lang;
+ } *i18n;
+ struct dlist *i18n_list = NULL;
+ struct dlist *l;
+ struct dlist *n;
+ int id;
+
+ root = xmlDocGetRootElement(docPtr);
+ if (!root) {
+ ErrPrint("Invalid node ptr\n");
+ return -EINVAL;
+ }
+
+ if (!s_info.handle) {
+ if (db_init() < 0)
+ return -EIO;
+ }
+
+ for (root = root->children; root; root = root->next) {
+ if (!xmlStrcasecmp(root->name, (const xmlChar *)"shortcut-list"))
+ break;
+ }
+
+ if (!root) {
+ ErrPrint("Root has no children\n");
+ return -EINVAL;
+ }
+
+ DbgPrint("AppID: %s\n", appid);
+
+ root = root->children; /* Jump to children node */
+ for (node = root; node; node = node->next) {
+ if (node->type == XML_ELEMENT_NODE)
+ DbgPrint("Element %s\n", node->name);
+
+ if (xmlStrcasecmp(node->name, (const xmlChar *)"shortcut"))
+ continue;
+
+ if (!xmlHasProp(node, (xmlChar *)"extra_key") || !xmlHasProp(node, (xmlChar *)"extra_data")) {
+ DbgPrint("Invalid element %s\n", node->name);
+ continue;
+ }
+
+ key = xmlGetProp(node, (xmlChar *)"extra_key");
+ data = xmlGetProp(node, (xmlChar *)"extra_data");
+ shortcut_appid = xmlGetProp(node, (xmlChar *)"appid");
+
+ icon = NULL;
+ name = NULL;
+ for (child = node->children; child; child = child->next) {
+ if (!xmlStrcasecmp(child->name, (const xmlChar *)"icon")) {
+ if (icon) {
+ DbgPrint("Icon is duplicated\n");
+ continue;
+ }
+
+ icon = xmlNodeGetContent(child);
+ continue;
+ }
+
+ if (!xmlStrcasecmp(child->name, (const xmlChar *)"label")) {
+ xmlChar *lang;
+ lang = xmlNodeGetLang(child);
+ if (!lang) {
+ if (name) {
+ DbgPrint("Default name is duplicated\n");
+ } else {
+ name = xmlNodeGetContent(child);
+ DbgPrint("Default name is %s\n", name);
+ }
+
+ continue;
+ }
+
+ i18n = malloc(sizeof(*i18n));
+ if (!i18n) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ break;
+ }
+
+ i18n->lang = lang;
+ i18n->name = xmlNodeGetContent(child);
+ i18n_list = dlist_append(i18n_list, i18n);
+ continue;
+ }
+ }
+
+ DbgPrint("appid: %s\n", appid);
+ DbgPrint("shortcut appid: %s\n", shortcut_appid);
+ DbgPrint("key: %s\n", key);
+ DbgPrint("data: %s\n", data);
+ DbgPrint("icon: %s\n", icon);
+ DbgPrint("Default name: %s\n", name);
+
+ if (!shortcut_appid) {
+ shortcut_appid = xmlStrdup((xmlChar *)appid);
+ DbgPrint("Use the default appid\n");
+ }
+
+ begin_transaction();
+ if (db_insert_record((char *)shortcut_appid, (char *)icon, (char *)name, (char *)key, (char *)data) < 0) {
+ ErrPrint("Failed to insert a new record\n");
+ rollback_transaction();
+
+ dlist_foreach_safe(i18n_list, l, n, i18n) {
+ i18n_list = dlist_remove(i18n_list, l);
+ xmlFree(i18n->lang);
+ xmlFree(i18n->name);
+ free(i18n);
+ }
+ } else {
+ id = db_get_id((char *)shortcut_appid, (char *)key, (char *)data);
+ if (id < 0) {
+ ErrPrint("Failed to insert a new record\n");
+ rollback_transaction();
+
+ dlist_foreach_safe(i18n_list, l, n, i18n) {
+ i18n_list = dlist_remove(i18n_list, l);
+ xmlFree(i18n->lang);
+ xmlFree(i18n->name);
+ free(i18n);
+ }
+ } else {
+ dlist_foreach_safe(i18n_list, l, n, i18n) {
+ i18n_list = dlist_remove(i18n_list, l);
+ if (db_insert_name(id, (char *)i18n->lang, (char *)i18n->name) < 0)
+ ErrPrint("Failed to add i18n name: %s(%s)\n", i18n->name, i18n->lang);
+ xmlFree(i18n->lang);
+ xmlFree(i18n->name);
+ free(i18n);
+ }
+ commit_transaction();
+ }
+ }
+
+ xmlFree(key);
+ xmlFree(data);
+ xmlFree(icon);
+ xmlFree(name);
+ xmlFree(shortcut_appid);
+ }
+
+ return 0;
+}
+
+/*
+int main(int argc, char *argv[])
+{
+ xmlDoc *doc;
+ xmlNode *root;
+
+ if (argc != 2) {
+ ErrPRint("Invalid argument: %s XML_FILENAME\n", argv[0]);
+ return -EINVAL;
+ }
+
+ doc = xmlReadFile(argv[1], NULL, 0);
+ if (!doc) {
+ ErrPrint("Failed to parse %s\n", argv[1]);
+ return -EIO;
+ }
+
+ root = xmlDocGetRootElement(doc);
+
+ db_init();
+ install_shortcut("", root);
+ db_fini();
+
+ xmlFreeDoc(doc);
+ xmlCleanupParser();
+ return 0;
+}
+*/
+
+/* End of a file */
diff --git a/sample.xml b/sample.xml
new file mode 100644
index 0000000..0e471a0
--- /dev/null
+++ b/sample.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<manifest xmlns="http://tizen.org/ns/packages" package="org.tizen.myapp" version="0.3.5" install-location="auto">
+<shortcut-list test="a">
+ <shortcut appid="org.tizen.myapp" extra_key="key" extra_data="SERVICE INFORMATION 1">
+ <icon>/opt/usr/apps/org.tizen.myapp/res/icon/myapp_shortcut01.png</icon>
+ <label>Default Name</label>
+ <label xml:lang="en-us">Name en</label>
+ <label xml:lang="nl-nl">Name nl</label>
+ <label xml:lang="de-de">Name de</label>
+ <label xml:lang="zh-hk">Name hk</label>
+ <label xml:lang="zh-cn">Name cn</label>
+ <label xml:lang="ru-ru">Name ru</label>
+ <label xml:lang="zh-tw">Name tw</label>
+ <label xml:lang="ja-jp">Name jp</label>
+ <label xml:lang="es-es">Name es</label>
+ <label xml:lang="el-gr">Name gr</label>
+ <label xml:lang="it-it">Name it</label>
+ <label xml:lang="tr-tr">Name tr</label>
+ <label xml:lang="pt-pt">Name pt</label>
+ <label xml:lang="fr-fr">Name fr</label>
+ <label xml:lang="kor-kr">Name kr</label>
+ </shortcut>
+ <shortcut appid="org.tizen.myapp-gadget" extra_key="key" extra_data="SERVICE INFORMATION 2">
+ <icon>/opt/usr/apps/org.tizen.myapp/res/icon/gadget_shortcut01.png</icon>
+ <label>Default Name 02</label>
+ <label xml:lang="en-us">Name en</label>
+ <label xml:lang="nl-nl">Name nl</label>
+ <label xml:lang="de-de">Name de</label>
+ <label xml:lang="zh-hk">Name hk</label>
+ <label xml:lang="zh-cn">Name cn</label>
+ <label xml:lang="ru-ru">Name ru</label>
+ <label xml:lang="zh-tw">Name tw</label>
+ <label xml:lang="ja-jp">Name jp</label>
+ <label xml:lang="es-es">Name es</label>
+ <label xml:lang="el-gr">Name gr</label>
+ <label xml:lang="it-it">Name it</label>
+ <label xml:lang="tr-tr">Name tr</label>
+ <label xml:lang="pt-pt">Name pt</label>
+ <label xml:lang="fr-fr">Name fr</label>
+ <label xml:lang="kor-kr">Name kr</label>
+ </shortcut>
+ <shortcut appid="org.tizen.myapp" extra_key="key" extra_data="SERVICE INFORMATION 3">
+ <icon>/opt/usr/apps/org.tizen.myapp/res/icon/mayapp_shortcut02.png</icon>
+ <label>Default Name 03</label>
+ <label xml:lang="en-us">Name en</label>
+ <label xml:lang="nl-nl">Name nl</label>
+ <label xml:lang="de-de">Name de</label>
+ <label xml:lang="zh-hk">Name hk</label>
+ <label xml:lang="zh-cn">Name cn</label>
+ <label xml:lang="ru-ru">Name ru</label>
+ <label xml:lang="zh-tw">Name tw</label>
+ <label xml:lang="ja-jp">Name jp</label>
+ <label xml:lang="es-es">Name es</label>
+ <label xml:lang="el-gr">Name gr</label>
+ <label xml:lang="it-it">Name it</label>
+ <label xml:lang="tr-tr">Name tr</label>
+ <label xml:lang="pt-pt">Name pt</label>
+ <label xml:lang="fr-fr">Name fr</label>
+ <label xml:lang="kor-kr">Name kr</label>
+ </shortcut>
+</shortcut-list>
+</manifest>
diff --git a/test/Makefile b/test/Makefile
new file mode 100644
index 0000000..abe5c1b
--- /dev/null
+++ b/test/Makefile
@@ -0,0 +1,4 @@
+all:
+ @gcc homescreen.c -Wall -o homescreen `pkg-config ecore elementary shortcut --cflags --libs`
+ @gcc application.c -Wall -o application `pkg-config ecore elementary shortcut --cflags --libs`
+ @gcc shortcut.c -Wall -o shortcut `pkg-config ecore elementary shortcut --cflags --libs`
diff --git a/test/application.c b/test/application.c
new file mode 100644
index 0000000..563273e
--- /dev/null
+++ b/test/application.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2000 - 2011 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 <Elementary.h>
+#include <shortcut.h>
+
+static int result_cb(int ret, int pid, void *data)
+{
+ printf("Client: Return %d (%d)\n", ret, pid);
+ //elm_exit();
+ return 0;
+}
+
+static Eina_Bool shortcut_add_cb(void *data)
+{
+ int ret;
+
+ ret = add_to_home_shortcut("pkgname", "MyName", 0, "/usr/bin/true", "/opt/share/image/what.png", result_cb, NULL);
+ printf("Client: shortcut_add_to_home returns: %d\n", ret);
+
+ ret = add_to_home_livebox("pkgname", "MyName", 0, "/usr/bin/true", "/opt/share/image/what.png", 1.0f, result_cb, NULL);
+ printf("Client: shortcut_add_to_home_with_period returns: %d\n", ret);
+
+ return ECORE_CALLBACK_RENEW;
+}
+
+int elm_main(int argc, char *argv[])
+{
+ Ecore_Timer *timer;
+
+ timer = ecore_timer_add(3.0f, shortcut_add_cb, NULL);
+ if (!timer) {
+ printf("Failed to add a timer\n");
+ }
+
+ elm_run();
+ elm_shutdown();
+
+ return 0;
+}
+
+ELM_MAIN()
+/* End of a file */
diff --git a/test/homescreen.c b/test/homescreen.c
new file mode 100644
index 0000000..68a221b
--- /dev/null
+++ b/test/homescreen.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2000 - 2011 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 <Elementary.h>
+#include <shortcut.h>
+
+int shortcut_request_cb(const char *pkgname, const char *name, int type, const char *exec, const char *icon, int pid, double period, void *data)
+{
+ printf("SERVER: name: %s, type: %d, exec: %s, icon: %s, pid: %d, data: %p, period: %lf\n",
+ name, type, exec, icon, pid, data, period);
+ return 0;
+}
+
+int elm_main(int argc, char *argv[])
+{
+ shortcut_set_request_cb(shortcut_request_cb, NULL);
+
+ elm_run();
+ elm_shutdown();
+
+ return 0;
+}
+
+ELM_MAIN()
+/* End of a file */
+
diff --git a/test/shortcut.c b/test/shortcut.c
new file mode 100644
index 0000000..d6c7012
--- /dev/null
+++ b/test/shortcut.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2000 - 2011 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 <Elementary.h>
+#include <shortcut.h>
+
+static int shortcut_list_cb(const char *appid, const char *icon, const char *name, const char *extra_key, const char *extra_data, void *data)
+{
+ printf("appid[%s] icon[%s], name[%s] extra_key[%s], extra_ata[%s]\n", appid, icon, name, extra_key, extra_data);
+ return 0;
+}
+
+int elm_main(int argc, char *argv[])
+{
+ int ret;
+ ret = shortcut_get_list(NULL, shortcut_list_cb, NULL);
+ if (ret < 0)
+ printf("Error: %d\n", ret);
+
+ elm_run();
+ elm_shutdown();
+
+ return 0;
+}
+
+ELM_MAIN()
+/* End of a file */
diff --git a/test_db_builder.sh b/test_db_builder.sh
new file mode 100755
index 0000000..bf9ede4
--- /dev/null
+++ b/test_db_builder.sh
@@ -0,0 +1,80 @@
+#!/bin/sh
+#/*
+# * Copyright (c) 2000 - 2011 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.
+# *
+#*/
+
+DBFILE="/opt/dbspace/.shortcut_service.db"
+
+APPID=(
+"org.tizen.facebook"
+"org.tizen.facebook"
+"org.tizen.facebook"
+"org.tizen.facebook"
+"org.tizen.facebook"
+)
+
+ICON=(
+""
+""
+""
+""
+""
+)
+
+NAME=(
+"Friend's wall"
+"Groups"
+"Update status"
+"Like by me"
+"My wall"
+)
+
+KEY=(
+"livebox_shortcut_type"
+"livebox_shortcut_type"
+"livebox_shortcut_type"
+"livebox_shortcut_type"
+"livebox_shortcut_type"
+)
+
+VALUE=(
+"shortcut_friends"
+"shortcut_groups"
+"shortcut_post"
+"shortcut_like"
+"shortcut_me"
+)
+
+CNT=0
+ERR=0
+MAX=5
+
+sqlite3 $DBFILE "CREATE TABLE shortcut_service (id INTEGER PRIMARY KEY AUTOINCREMENT, appid TEXT, icon TEXT, name TEXT, extra_key TEXT, extra_data TEXT)"
+sqlite3 $DBFILE "CREATE TABLE shortcut_name (id INTEGER, lang TEXT, name TEXT)"
+while [ $CNT -lt $MAX ]
+do
+ echo "Insert a new record ('${APPID[$CNT]}', '${ICON[$CNT]}', '${NAME[$CNT]}', \"${KEY[$CNT]}\", \"${VALUE[$CNT]}\")"
+ sqlite3 $DBFILE "INSERT INTO shortcut_service (appid, icon, name, extra_key, extra_data) VALUES ('${APPID[$CNT]}', '${ICON[$CNT]}', \"${NAME[$CNT]}\", \"${KEY[$CNT]}\", \"${VALUE[$CNT]}\")" 2>/dev/null
+ if [ $? -ne 0 ]; then
+ let ERR=$ERR+1
+ fi
+ ID=`sqlite3 $DBFILE "SELECT id FROM shortcut_service WHERE appid = \"${APPID[$CNT]}\" AND extra_key = \"${KEY[$CNT]}\" AND extra_data = \"${VALUE[$CNT]}\""`
+ echo "Insert a name: \"${NAME[$CNT]}\""
+ sqlite3 $DBFILE "INSERT INTO shortcut_name (id, lang, name) VALUES ('$ID', 'en-us', \"${NAME[CNT]}\")"
+ let CNT=$CNT+1
+done
+
+echo "Error/Total: $ERR/$CNT"