summaryrefslogtreecommitdiff
path: root/pkgmgr_shortcut/src/service_register.c
diff options
context:
space:
mode:
Diffstat (limited to 'pkgmgr_shortcut/src/service_register.c')
-rw-r--r--pkgmgr_shortcut/src/service_register.c1244
1 files changed, 1244 insertions, 0 deletions
diff --git a/pkgmgr_shortcut/src/service_register.c b/pkgmgr_shortcut/src/service_register.c
new file mode 100644
index 0000000..c4c1a7f
--- /dev/null
+++ b/pkgmgr_shortcut/src/service_register.c
@@ -0,0 +1,1244 @@
+/*
+ * Copyright (c) 2000 - 2013 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...) SECURE_LOGD("[%s/%s:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg)
+#define ErrPrint(format, arg...) SECURE_LOGE("[%s/%s:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg)
+#endif
+/* End of a file */
+
+/*!
+ * DB Table schema
+ *
+ * +----+-------+-------+------+---------+-----------+------------+
+ * | id | pkgid | appid | Icon | Name | extra_key | extra_data |
+ * +----+-------+-------+------+---------+-----------+------------+
+ * | id | - | - | - | - | - | - |
+ * +----+-------+-------+------+---------+-----------+------------+
+ *
+ * +----+-------+------+------+------+
+ * | fk | pkgid | lang | name | icon |
+ * +----+-------+------+------+------+
+ * | id | - | - | | - |
+ * +----+-------+------+------+------+
+ */
+
+#if !defined(LIBXML_TREE_ENABLED)
+ #error "LIBXML is not supporting the tree"
+#endif
+
+int errno;
+
+struct i18n_name {
+ xmlChar *icon;
+ xmlChar *name;
+ xmlChar *lang;
+};
+
+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 void db_create_version(void)
+{
+ static const char *ddl = "CREATE TABLE version (version INTEGER)";
+ char *err;
+
+ 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 int set_version(int version)
+{
+ static const char *dml = "INSERT INTO version (version) VALUES (?)";
+ sqlite3_stmt *stmt;
+ int ret;
+
+ 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, version) != SQLITE_OK) {
+ ErrPrint("Failed to bind a id(%s)\n", sqlite3_errmsg(s_info.handle));
+ ret = -EIO;
+ goto out;
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ ErrPrint("Failed to execute the DML for version: %d\n", ret);
+ ret = -EIO;
+ } else {
+ ret = 0;
+ }
+
+out:
+ sqlite3_reset(stmt);
+ sqlite3_clear_bindings(stmt);
+ sqlite3_finalize(stmt);
+ return ret;
+}
+
+static int update_version(int version)
+{
+ static const char *dml = "UPDATE version SET version = ?";
+ sqlite3_stmt *stmt;
+ int ret;
+
+ 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, version) != SQLITE_OK) {
+ ErrPrint("Failed to bind a version: %s\n", sqlite3_errmsg(s_info.handle));
+ ret = -EIO;
+ goto out;
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ ErrPrint("Failed to execute DML: %d\n", ret);
+ ret = -EIO;
+ } else {
+ ret = 0;
+ }
+
+out:
+ sqlite3_reset(stmt);
+ sqlite3_clear_bindings(stmt);
+ sqlite3_finalize(stmt);
+ return ret;
+}
+
+static int get_version(void)
+{
+ static const char *dml = "SELECT version FROM version";
+ sqlite3_stmt *stmt;
+ int ret;
+
+ ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ return -ENOSYS;
+ }
+
+ if (sqlite3_step(stmt) != SQLITE_ROW) {
+ ret = -ENOENT;
+ } else {
+ ret = sqlite3_column_int(stmt, 0);
+ }
+
+ sqlite3_reset(stmt);
+ sqlite3_clear_bindings(stmt);
+ sqlite3_finalize(stmt);
+ return ret;
+}
+
+static void db_create_table(void)
+{
+ char *err;
+ static const char *ddl =
+ "CREATE TABLE shortcut_service ("
+ "id INTEGER PRIMARY KEY AUTOINCREMENT, "
+ "pkgid TEXT, "
+ "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, pkgid TEXT, lang TEXT, name TEXT, icon 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");
+ }
+
+ db_create_version();
+}
+
+static void alter_shortcut_icon(void)
+{
+ char *err;
+ static const char *ddl = "ALTER TABLE shortcut_name ADD icon 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 void alter_shortcut_name(void)
+{
+ char *err;
+ static const char *ddl = "ALTER TABLE shortcut_name ADD pkgid 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 void alter_shortcut_service(void)
+{
+ char *err;
+ static const char *ddl = "ALTER TABLE shortcut_service ADD pkgid 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 int db_remove_by_pkgid(const char *pkgid)
+{
+ static const char *dml = "DELETE FROM shortcut_service WHERE pkgid = ?";
+ sqlite3_stmt *stmt;
+ int ret;
+
+ if (!pkgid) {
+ 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, pkgid, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
+ ErrPrint("Failed to bind a pkgid(%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\n", pkgid);
+ } else {
+ if (sqlite3_changes(s_info.handle) == 0) {
+ DbgPrint("No changed\n");
+ }
+ }
+
+out:
+ sqlite3_reset(stmt);
+ sqlite3_clear_bindings(stmt);
+ sqlite3_finalize(stmt);
+ return ret;
+}
+
+static void do_upgrade_db_schema(void)
+{
+ int version;
+
+ version = get_version();
+
+ switch (version) {
+ case -ENOSYS:
+ db_create_version();
+ /* Need to create version table */
+ case -ENOENT:
+ if (set_version(1) < 0) {
+ ErrPrint("Failed to set version\n");
+ }
+ /* Need to set version */
+ alter_shortcut_name();
+ alter_shortcut_service();
+ case 1:
+ alter_shortcut_icon();
+ if (update_version(2) < 0) {
+ ErrPrint("Failed to update version\n");
+ }
+ case 2:
+ break;
+ default:
+ /* Need to update version */
+ DbgPrint("Old version: %d\n", version);
+ if (update_version(2) < 0) {
+ ErrPrint("Failed to update version\n");
+ }
+
+ alter_shortcut_name();
+ alter_shortcut_service();
+ /* 2 */
+ alter_shortcut_icon();
+ break;
+ }
+}
+
+static int db_remove_record(const char *pkgid, 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 = ? AND pkgid = ?";
+ 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, SQLITE_TRANSIENT) != 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, SQLITE_TRANSIENT) != 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, SQLITE_TRANSIENT) != SQLITE_OK) {
+ ErrPrint("Failed to bind a data(%s)\n", sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ if (sqlite3_bind_text(stmt, 4, pkgid, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
+ ErrPrint("Failed to bind a pkgid(%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 int db_remove_name_by_pkgid(const char *pkgid)
+{
+ static const char *dml = "DELETE FROM shortcut_name WHERE pkgid = ?";
+ sqlite3_stmt *stmt;
+ int ret;
+
+ if (!pkgid) {
+ ErrPrint("Invalid 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_text(stmt, 1, pkgid, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
+ ErrPrint("Failed to bind pkgid(%s)\n", pkgid);
+ return -EIO;
+ }
+
+ ret = 0;
+ if (sqlite3_step(stmt) != SQLITE_DONE) {
+ ret = -EIO;
+ ErrPrint("Failed to execute the DML for %s\n", pkgid);
+ goto out;
+ }
+
+ if (sqlite3_changes(s_info.handle) == 0) {
+ DbgPrint("No chnages\n");
+ }
+
+out:
+ sqlite3_reset(stmt);
+ sqlite3_clear_bindings(stmt);
+ sqlite3_finalize(stmt);
+ return ret;
+}
+
+static 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 int db_insert_record(const char *pkgid, const char *appid, const char *icon, const char *name, const char *key, const char *data)
+{
+ static const char *dml = "INSERT INTO shortcut_service (pkgid, appid, icon, name, extra_key, extra_data) VALUES (?, ?, ?, ?, ?, ?)";
+ sqlite3_stmt *stmt;
+ int ret;
+
+ if (!pkgid) {
+ ErrPrint("Failed to get pkgid\n");
+ return -EINVAL;
+ }
+
+ 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;
+ }
+
+ 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, pkgid, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
+ ErrPrint("Failed to bind a pkgid(%s)\n", sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ if (sqlite3_bind_text(stmt, 2, appid, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
+ ErrPrint("Failed to bind a appid(%s)\n", sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ if (sqlite3_bind_text(stmt, 3, icon, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
+ ErrPrint("Failed to bind a icon(%s)\n", sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ if (sqlite3_bind_text(stmt, 4, name, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
+ ErrPrint("Failed to bind a name(%s)\n", sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ if (sqlite3_bind_text(stmt, 5, key, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
+ ErrPrint("Failed to bind a service(%s)\n", sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ if (sqlite3_bind_text(stmt, 6, data, -1, SQLITE_TRANSIENT) != 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 int db_insert_name(int id, const char *pkgid, const char *lang, const char *name, const char *icon)
+{
+ static const char *dml = "INSERT INTO shortcut_name (id, pkgid, lang, name, icon) VALUES (?, ?, ?, ?, ?)";
+ sqlite3_stmt *stmt;
+ int ret;
+
+ if (id < 0 || !lang) {
+ 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, pkgid, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
+ ErrPrint("Failed to bind a pkgid(%s)\n", sqlite3_errmsg(s_info.handle));
+ ret = -EIO;
+ goto out;
+ }
+
+ if (sqlite3_bind_text(stmt, 3, lang, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
+ ErrPrint("Failed to bind a id(%s)\n", sqlite3_errmsg(s_info.handle));
+ ret = -EIO;
+ goto out;
+ }
+
+ if (sqlite3_bind_text(stmt, 4, name, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
+ ErrPrint("Failed to bind a id(%s)\n", sqlite3_errmsg(s_info.handle));
+ ret = -EIO;
+ goto out;
+ }
+
+ if (sqlite3_bind_text(stmt, 5, icon, -1, SQLITE_TRANSIENT) != 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 int db_get_id(const char *pkgid, const char *appid, const char *key, const char *data)
+{
+ static const char *dml = "SELECT id FROM shortcut_service WHERE pkgid = ? AND 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, pkgid, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
+ ErrPrint("Failed to bind a pkgid(%s) - %s\n", pkgid, sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ if (sqlite3_bind_text(stmt, 2, appid, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
+ ErrPrint("Failed to bind a appid(%s) - %s\n", appid, sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ if (sqlite3_bind_text(stmt, 3, key, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
+ ErrPrint("Failed to bind a key(%s) - %s\n", key, sqlite3_errmsg(s_info.handle));
+ goto out;
+ }
+
+ if (sqlite3_bind_text(stmt, 4, data, -1, SQLITE_TRANSIENT) != 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 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 int db_fini(void)
+{
+ if (!s_info.handle) {
+ return 0;
+ }
+
+ db_util_close(s_info.handle);
+ s_info.handle = NULL;
+
+ return 0;
+}
+
+static int do_uninstall(const char *appid)
+{
+ int ret;
+
+ ret = db_remove_by_pkgid(appid);
+ if (ret < 0) {
+ ErrPrint("Failed to remove a record: %s\n", appid);
+ return ret;
+ }
+
+ ret = db_remove_name_by_pkgid(appid);
+ if (ret < 0) {
+ ErrPrint("Failed to remove name records: %s\n", appid);
+ return ret;
+ }
+
+ return 0;
+}
+
+static inline struct i18n_name *find_i18n_name(struct dlist *i18n_list, xmlChar *lang)
+{
+ struct dlist *l;
+ struct i18n_name *i18n;
+
+ dlist_foreach(i18n_list, l, i18n) {
+ if (!xmlStrcasecmp(i18n->lang, lang)) {
+ return i18n;
+ }
+ }
+
+ return NULL;
+}
+
+static inline struct i18n_name *create_i18n_name(xmlChar *lang, xmlChar *name, xmlChar *icon)
+{
+ struct i18n_name *i18n;
+
+ i18n = malloc(sizeof(*i18n));
+ if (!i18n) {
+ ErrPrint("Heap: %s\n", strerror(errno));
+ return NULL;
+ }
+
+ i18n->lang = lang;
+ i18n->name = name;
+ i18n->icon = icon;
+
+ return i18n;
+}
+
+static inline void destroy_i18n_name(struct i18n_name *i18n)
+{
+ xmlFree(i18n->lang);
+ xmlFree(i18n->name);
+ xmlFree(i18n->icon);
+ free(i18n);
+}
+
+static int do_install(xmlDocPtr docPtr, const char *appid)
+{
+ xmlNodePtr node = NULL;
+ xmlNodePtr child = NULL;
+ xmlChar *key;
+ xmlChar *data;
+ xmlChar *name;
+ xmlChar *icon;
+ xmlChar *lang;
+ xmlChar *shortcut_appid;
+ xmlNodePtr root;
+ struct i18n_name *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;
+ }
+
+ 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")) {
+ lang = xmlNodeGetLang(child);
+ if (!lang) {
+ if (icon) {
+ DbgPrint("Default icon is duplicated\n");
+ } else {
+ icon = xmlNodeGetContent(child);
+ DbgPrint("Default icon is %s\n", icon);
+ }
+
+ continue;
+ }
+
+ i18n = find_i18n_name(i18n_list, lang);
+ if (i18n) {
+ xmlFree(lang);
+
+ if (i18n->icon) {
+ DbgPrint("%s is duplicated\n", i18n->icon);
+ continue;
+ }
+
+ i18n->icon = xmlNodeGetContent(child);
+ } else {
+ i18n = create_i18n_name(lang, NULL, xmlNodeGetContent(child));
+ if (!i18n) {
+ ErrPrint("Failed to create a new i18n_name\n");
+ continue;
+ }
+ i18n_list = dlist_append(i18n_list, i18n);
+ }
+
+ continue;
+ }
+
+ if (!xmlStrcasecmp(child->name, (const xmlChar *)"label")) {
+ 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 = find_i18n_name(i18n_list, lang);
+ if (i18n) {
+ xmlFree(lang);
+
+ if (i18n->name) {
+ DbgPrint("%s is duplicated\n", i18n->name);
+ continue;
+ }
+
+ i18n->name = xmlNodeGetContent(child);
+ } else {
+ i18n = create_i18n_name(lang, xmlNodeGetContent(child), NULL);
+ if (!i18n) {
+ ErrPrint("Failed to create a new i18n_name\n");
+ continue;
+ }
+ 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(appid, (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);
+ destroy_i18n_name(i18n);
+ }
+ } else {
+ id = db_get_id((char *)appid, (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);
+ destroy_i18n_name(i18n);
+ }
+ } else {
+ dlist_foreach_safe(i18n_list, l, n, i18n) {
+ i18n_list = dlist_remove(i18n_list, l);
+ if (db_insert_name(id, appid, (char *)i18n->lang, (char *)i18n->name, (char *)i18n->icon) < 0) {
+ ErrPrint("Failed to add i18n name: %s(%s)\n", i18n->name, i18n->lang);
+ }
+ destroy_i18n_name(i18n);
+ }
+ commit_transaction();
+ }
+ }
+
+ xmlFree(key);
+ xmlFree(data);
+ xmlFree(icon);
+ xmlFree(name);
+ xmlFree(shortcut_appid);
+ }
+
+ return 0;
+}
+
+int PKGMGR_PARSER_PLUGIN_PRE_UNINSTALL(const char *appid)
+{
+ if (!s_info.handle) {
+ if (db_init() < 0) {
+ return -EIO;
+ }
+ }
+
+ do_upgrade_db_schema();
+ return 0;
+}
+
+int PKGMGR_PARSER_PLUGIN_POST_UNINSTALL(const char *appid)
+{
+ int ret;
+
+ begin_transaction();
+ ret = do_uninstall(appid);
+ if (ret < 0) {
+ rollback_transaction();
+ return ret;
+ }
+ commit_transaction();
+
+ db_fini();
+ 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;
+
+ if (!docPtr) {
+ DbgPrint("Package manager doesn't support the docPtr (%s)\n", _appid);
+ return 0;
+ }
+
+ root = xmlDocGetRootElement(docPtr);
+ if (!root) {
+ ErrPrint("Invalid node ptr\n");
+ return -EINVAL;
+ }
+
+ 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(NULL, (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(NULL, (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_PRE_INSTALL(const char *appid)
+{
+ int ret;
+
+ if (!s_info.handle) {
+ if (db_init() < 0) {
+ return -EIO;
+ }
+ }
+
+ do_upgrade_db_schema();
+
+ begin_transaction();
+ ret = do_uninstall(appid);
+ if (ret < 0) {
+ ErrPrint("Failed to remove record: %s\n", appid);
+ /* Keep going */
+ }
+ commit_transaction();
+ return 0;
+}
+
+int PKGMGR_PARSER_PLUGIN_POST_INSTALL(const char *appid)
+{
+ db_fini();
+ return 0;
+}
+
+int PKGMGR_PARSER_PLUGIN_INSTALL(xmlDocPtr docPtr, const char *appid)
+{
+ return do_install(docPtr, appid);
+}
+
+int PKGMGR_PARSER_PLUGIN_PRE_UPGRADE(const char *appid)
+{
+ int ret;
+
+ if (!s_info.handle) {
+ if (db_init() < 0) {
+ return -EIO;
+ }
+ }
+
+ do_upgrade_db_schema();
+
+ begin_transaction();
+ ret = do_uninstall(appid);
+ if (ret < 0) {
+ ErrPrint("Failed to remove a record: %s\n", appid);
+ /* Keep going */
+ }
+ commit_transaction();
+ return 0;
+}
+
+int PKGMGR_PARSER_PLUGIN_POST_UPGRADE(const char *appid)
+{
+ db_fini();
+ return 0;
+}
+
+int PKGMGR_PARSER_PLUGIN_UPGRADE(xmlDocPtr docPtr, const char *appid)
+{
+ /* So... ugly */
+ return do_install(docPtr, appid);
+}
+
+/*
+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 */