2 * Copyright (c) 2011 - 2017 Samsung Electronics Co., Ltd. All rights reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
22 #include <shortcut_private.h>
23 #include <shortcut_db.h>
25 #include <vconf-keys.h>
26 #include <tzplatform_config.h>
28 #include "shortcut_error.h"
30 #define QUERY_CREATE_SHORTCUT_TABLE \
31 "PRAGMA journal_mode = PERSIST;" \
32 "CREATE TABLE IF NOT EXISTS shortcut_service (\n" \
33 " id INTEGER PRIMARY KEY AUTOINCREMENT,\n" \
38 " extra_key TEXT,\n" \
39 " extra_data TEXT);\n" \
40 "CREATE TABLE IF NOT EXISTS shortcut_name (\n" \
46 "CREATE TABLE IF NOT EXISTS version (\n" \
49 static bool is_db_corrupted = false;
51 static const char* _db_path = DB_PATH;
53 int shortcut_set_db_path(const char *db_path)
60 static int __check_integrity_cb(void *pid, int argc, char **argv, char **notUsed)
62 if (strcmp(argv[0], "ok") != 0) {
63 SHORTCUT_ERR("db integrity result : %s", argv[0]);
64 is_db_corrupted = true;
68 SHORTCUT_INFO("db integrity result : %s", argv[0]);
74 static int __recover_corrupted_db(sqlite3 *db)
76 int ret = SHORTCUT_ERROR_NONE;
80 SHORTCUT_INFO("DB is corrupted, start to recover corrupted db");
85 sql_ret = sqlite3_open_v2(_db_path, &db,
86 SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE,
88 if (sql_ret != SQLITE_OK) {
89 SHORTCUT_ERR("Failed to open db[%d]", sql_ret);
91 ret = SHORTCUT_ERROR_IO_ERROR;
95 sql_ret = sqlite3_exec(db, QUERY_CREATE_SHORTCUT_TABLE, NULL, NULL, &errmsg);
96 if (sql_ret != SQLITE_OK) {
97 SHORTCUT_ERR("Failed to exec query[%d][%s]", sql_ret, errmsg);
98 ret = SHORTCUT_ERROR_IO_ERROR;
103 sqlite3_free(errmsg);
109 /* LCOV_EXCL_START */
110 EAPI int shortcut_db_init(void)
112 int ret = SHORTCUT_ERROR_NONE;
117 sql_ret = sqlite3_open_v2(_db_path, &db,
118 SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
119 if (sql_ret != SQLITE_OK) {
120 SHORTCUT_ERR("Failed to open db[%d]", sql_ret);
121 ret = SHORTCUT_ERROR_IO_ERROR;
125 sql_ret = sqlite3_exec(db, QUERY_CREATE_SHORTCUT_TABLE,
126 NULL, NULL, &errmsg);
127 if (sql_ret != SQLITE_OK) {
128 SHORTCUT_ERR("Failed to exec query [%d][%s]", sql_ret, errmsg);
129 ret = SHORTCUT_ERROR_IO_ERROR;
133 sql_ret = sqlite3_exec(db, "PRAGMA integrity_check",
134 __check_integrity_cb, NULL, &errmsg);
135 if (sql_ret != SQLITE_OK || is_db_corrupted) {
136 SHORTCUT_ERR("Failed to exec query[%d][%s]", sql_ret, errmsg);
137 ret = SHORTCUT_ERROR_IO_ERROR;
141 if (sql_ret == SQLITE_CORRUPT || sql_ret == SQLITE_NOTADB || is_db_corrupted)
142 ret = __recover_corrupted_db(db);
144 sqlite3_free(errmsg);
152 static sqlite3 *_open_db(void)
155 const char *dbfile = _db_path;
158 ret = db_util_open(dbfile, &db, 0);
159 if (ret != SQLITE_OK) {
160 /* LCOV_EXCL_START */
161 SHORTCUT_DBG("Failed to open a %s\n", dbfile);
169 static int _close_db(sqlite3 **db)
173 if (db == NULL || *db == NULL)
174 return SHORTCUT_ERROR_INVALID_PARAMETER;
176 ret = db_util_close(*db);
177 if (ret != SQLITE_OK) {
178 /* LCOV_EXCL_START */
179 SHORTCUT_DBG("DB close error(%d)", ret);
180 return SHORTCUT_ERROR_IO_ERROR;
186 return SHORTCUT_ERROR_NONE;
189 /* LCOV_EXCL_START */
191 * \note this function will returns allocated(heap) string
193 static inline int _get_i18n_name(sqlite3 *handle, const char *lang, int id, char **name, char **icon)
196 static const char *query = "SELECT name, icon FROM shortcut_name WHERE id = ? AND lang = ? COLLATE NOCASE";
197 const unsigned char *_name;
198 const unsigned char *_icon;
202 status = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL);
203 if (status != SQLITE_OK) {
204 SHORTCUT_ERR("Failed to prepare stmt: %s\n", sqlite3_errmsg(handle));
208 status = sqlite3_bind_int(stmt, 1, id);
209 if (status != SQLITE_OK) {
210 SHORTCUT_ERR("Failed to bind id: %s\n", sqlite3_errmsg(handle));
215 status = sqlite3_bind_text(stmt, 2, lang, -1, SQLITE_TRANSIENT);
216 if (status != SQLITE_OK) {
217 SHORTCUT_ERR("Failed to bind lang: %s\n", sqlite3_errmsg(handle));
222 SHORTCUT_DBG("id: %d, lang: %s\n", id, lang);
223 if (SQLITE_ROW != sqlite3_step(stmt)) {
224 SHORTCUT_ERR("Failed to do step: %s\n", sqlite3_errmsg(handle));
229 _name = sqlite3_column_text(stmt, 0);
231 if (_name && strlen((const char *)_name)) {
232 *name = strdup((const char *)_name);
234 SHORTCUT_ERR("strdup: %d\n", errno);
243 _icon = sqlite3_column_text(stmt, 1);
245 if (_icon && strlen((const char *)_icon)) {
246 *icon = strdup((const char *)_icon);
248 SHORTCUT_ERR("strdup: %d\n", errno);
264 sqlite3_clear_bindings(stmt);
265 sqlite3_finalize(stmt);
270 static inline char *_cur_locale(void)
275 language = vconf_get_str(VCONFKEY_LANGSET);
290 language = strdup("en-us");
292 SHORTCUT_ERR("Heap: %d\n", errno);
298 EAPI int shortcut_db_get_list(const char *package_name, GList **shortcut_list)
301 sqlite3 *handle = NULL;
303 const unsigned char *name;
304 char *i18n_name = NULL;
305 char *i18n_icon = NULL;
306 const unsigned char *extra_data;
307 const unsigned char *extra_key;
308 const unsigned char *icon;
309 shortcut_info_s *shortcut;
317 /* LCOV_EXCL_START */
318 SHORTCUT_ERR("Failed to open a DB\n");
319 return SHORTCUT_ERROR_IO_ERROR;
323 language = _cur_locale();
325 /* LCOV_EXCL_START */
326 SHORTCUT_ERR("Locale is not valid\n");
328 return SHORTCUT_ERROR_FAULT;
333 query = "SELECT id, appid, name, extra_key, extra_data, icon FROM shortcut_service WHERE appid = ?";
334 ret = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL);
335 if (ret != SQLITE_OK) {
336 /* LCOV_EXCL_START */
337 SHORTCUT_ERR("prepare: %s\n", sqlite3_errmsg(handle));
340 return SHORTCUT_ERROR_IO_ERROR;
344 ret = sqlite3_bind_text(stmt, 1, package_name, -1, SQLITE_TRANSIENT);
345 if (ret != SQLITE_OK) {
346 /* LCOV_EXCL_START */
347 SHORTCUT_ERR("bind text: %s\n", sqlite3_errmsg(handle));
348 sqlite3_finalize(stmt);
351 return SHORTCUT_ERROR_IO_ERROR;
355 query = "SELECT id, appid, name, extra_key, extra_data, icon FROM shortcut_service";
356 ret = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL);
357 if (ret != SQLITE_OK) {
358 /* LCOV_EXCL_START */
359 SHORTCUT_ERR("prepare: %s\n", sqlite3_errmsg(handle));
362 return SHORTCUT_ERROR_IO_ERROR;
368 *shortcut_list = NULL;
369 while (SQLITE_ROW == sqlite3_step(stmt)) {
370 /* LCOV_EXCL_START */
371 id = sqlite3_column_int(stmt, 0);
373 package_name = (const char *)sqlite3_column_text(stmt, 1);
375 LOGE("Failed to get package name\n");
379 name = sqlite3_column_text(stmt, 2);
381 LOGE("Failed to get name\n");
385 extra_key = sqlite3_column_text(stmt, 3);
387 LOGE("Failed to get service\n");
391 extra_data = sqlite3_column_text(stmt, 4);
393 LOGE("Failed to get service\n");
397 icon = sqlite3_column_text(stmt, 5);
399 LOGE("Failed to get icon\n");
405 * Implement the "GET LOCALE" code
407 /* if (get_i18n_name(language, id, &i18n_name, &i18n_icon) < 0) { */
408 /* Okay, we can't manage this. just use the fallback string */
410 _get_i18n_name(handle, language, id, &i18n_name, &i18n_icon);
413 shortcut = (shortcut_info_s *)calloc(sizeof(shortcut_info_s), 1);
414 if (shortcut == NULL) {
419 shortcut->package_name = strdup(package_name);
420 shortcut->icon = strdup((i18n_icon != NULL ? i18n_icon : (char *)icon));
421 shortcut->name = strdup((i18n_name != NULL ? i18n_name : (char *)name));
422 shortcut->extra_key = strdup((char *)extra_key);
423 shortcut->extra_data = strdup((char *)extra_data);
424 *shortcut_list = g_list_append(*shortcut_list, shortcut);
439 sqlite3_clear_bindings(stmt);
440 sqlite3_finalize(stmt);