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()
76 int ret = SHORTCUT_ERROR_NONE;
81 SHORTCUT_INFO("DB is corrupted, start to recover corrupted db");
84 sql_ret = sqlite3_open_v2(_db_path, &db,
85 SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE,
87 if (sql_ret != SQLITE_OK) {
88 SHORTCUT_ERR("Failed to open db[%d]", sql_ret);
90 ret = SHORTCUT_ERROR_IO_ERROR;
94 sql_ret = sqlite3_exec(db, QUERY_CREATE_SHORTCUT_TABLE, NULL, NULL, &errmsg);
95 if (sql_ret != SQLITE_OK) {
96 SHORTCUT_ERR("Failed to exec query[%d][%s]", sql_ret, errmsg);
97 ret = SHORTCUT_ERROR_IO_ERROR;
102 sqlite3_free(errmsg);
104 sqlite3_close_v2(db);
110 /* LCOV_EXCL_START */
111 EAPI int shortcut_db_init(void)
113 int ret = SHORTCUT_ERROR_NONE;
118 sql_ret = sqlite3_open_v2(_db_path, &db,
119 SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
120 if (sql_ret != SQLITE_OK) {
121 SHORTCUT_ERR("Failed to open db[%d]", sql_ret);
122 ret = SHORTCUT_ERROR_IO_ERROR;
126 sql_ret = sqlite3_exec(db, QUERY_CREATE_SHORTCUT_TABLE,
127 NULL, NULL, &errmsg);
128 if (sql_ret != SQLITE_OK) {
129 SHORTCUT_ERR("Failed to exec query [%d][%s]", sql_ret, errmsg);
130 ret = SHORTCUT_ERROR_IO_ERROR;
134 sql_ret = sqlite3_exec(db, "PRAGMA integrity_check",
135 __check_integrity_cb, NULL, &errmsg);
136 if (sql_ret != SQLITE_OK || is_db_corrupted) {
137 SHORTCUT_ERR("Failed to exec query[%d][%s]", sql_ret, errmsg);
138 ret = SHORTCUT_ERROR_IO_ERROR;
143 sqlite3_free(errmsg);
145 sqlite3_close_v2(db);
146 if (sql_ret == SQLITE_CORRUPT || sql_ret == SQLITE_NOTADB || is_db_corrupted)
147 ret = __recover_corrupted_db();
153 static sqlite3 *_open_db(void)
156 const char *dbfile = _db_path;
159 ret = db_util_open(dbfile, &db, 0);
160 if (ret != SQLITE_OK) {
161 /* LCOV_EXCL_START */
162 SHORTCUT_DBG("Failed to open a %s\n", dbfile);
170 static int _close_db(sqlite3 **db)
174 if (db == NULL || *db == NULL)
175 return SHORTCUT_ERROR_INVALID_PARAMETER;
177 ret = db_util_close(*db);
178 if (ret != SQLITE_OK) {
179 /* LCOV_EXCL_START */
180 SHORTCUT_DBG("DB close error(%d)", ret);
181 return SHORTCUT_ERROR_IO_ERROR;
187 return SHORTCUT_ERROR_NONE;
190 /* LCOV_EXCL_START */
192 * \note this function will returns allocated(heap) string
194 static inline int _get_i18n_name(sqlite3 *handle, const char *lang, int id, char **name, char **icon)
197 static const char *query = "SELECT name, icon FROM shortcut_name WHERE id = ? AND lang = ? COLLATE NOCASE";
198 const unsigned char *_name;
199 const unsigned char *_icon;
203 status = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL);
204 if (status != SQLITE_OK) {
205 SHORTCUT_ERR("Failed to prepare stmt: %s\n", sqlite3_errmsg(handle));
209 status = sqlite3_bind_int(stmt, 1, id);
210 if (status != SQLITE_OK) {
211 SHORTCUT_ERR("Failed to bind id: %s\n", sqlite3_errmsg(handle));
216 status = sqlite3_bind_text(stmt, 2, lang, -1, SQLITE_TRANSIENT);
217 if (status != SQLITE_OK) {
218 SHORTCUT_ERR("Failed to bind lang: %s\n", sqlite3_errmsg(handle));
223 SHORTCUT_DBG("id: %d, lang: %s\n", id, lang);
224 if (SQLITE_ROW != sqlite3_step(stmt)) {
225 SHORTCUT_ERR("Failed to do step: %s\n", sqlite3_errmsg(handle));
230 _name = sqlite3_column_text(stmt, 0);
232 if (_name && strlen((const char *)_name)) {
233 *name = strdup((const char *)_name);
235 SHORTCUT_ERR("strdup: %d\n", errno);
244 _icon = sqlite3_column_text(stmt, 1);
246 if (_icon && strlen((const char *)_icon)) {
247 *icon = strdup((const char *)_icon);
249 SHORTCUT_ERR("strdup: %d\n", errno);
265 sqlite3_clear_bindings(stmt);
266 sqlite3_finalize(stmt);
271 static inline char *_cur_locale(void)
276 language = vconf_get_str(VCONFKEY_LANGSET);
291 language = strdup("en-us");
293 SHORTCUT_ERR("Heap: %d\n", errno);
299 EAPI int shortcut_db_get_list(const char *package_name, GList **shortcut_list)
302 sqlite3 *handle = NULL;
304 const unsigned char *name;
305 char *i18n_name = NULL;
306 char *i18n_icon = NULL;
307 const unsigned char *extra_data;
308 const unsigned char *extra_key;
309 const unsigned char *icon;
310 shortcut_info_s *shortcut;
318 /* LCOV_EXCL_START */
319 SHORTCUT_ERR("Failed to open a DB\n");
320 return SHORTCUT_ERROR_IO_ERROR;
324 language = _cur_locale();
326 /* LCOV_EXCL_START */
327 SHORTCUT_ERR("Locale is not valid\n");
329 return SHORTCUT_ERROR_FAULT;
334 query = "SELECT id, appid, name, extra_key, extra_data, icon FROM shortcut_service WHERE appid = ?";
335 ret = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL);
336 if (ret != SQLITE_OK) {
337 /* LCOV_EXCL_START */
338 SHORTCUT_ERR("prepare: %s\n", sqlite3_errmsg(handle));
341 return SHORTCUT_ERROR_IO_ERROR;
345 ret = sqlite3_bind_text(stmt, 1, package_name, -1, SQLITE_TRANSIENT);
346 if (ret != SQLITE_OK) {
347 /* LCOV_EXCL_START */
348 SHORTCUT_ERR("bind text: %s\n", sqlite3_errmsg(handle));
349 sqlite3_finalize(stmt);
352 return SHORTCUT_ERROR_IO_ERROR;
356 query = "SELECT id, appid, name, extra_key, extra_data, icon FROM shortcut_service";
357 ret = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL);
358 if (ret != SQLITE_OK) {
359 /* LCOV_EXCL_START */
360 SHORTCUT_ERR("prepare: %s\n", sqlite3_errmsg(handle));
363 return SHORTCUT_ERROR_IO_ERROR;
369 *shortcut_list = NULL;
370 while (SQLITE_ROW == sqlite3_step(stmt)) {
371 /* LCOV_EXCL_START */
372 id = sqlite3_column_int(stmt, 0);
374 package_name = (const char *)sqlite3_column_text(stmt, 1);
376 LOGE("Failed to get package name\n");
380 name = sqlite3_column_text(stmt, 2);
382 LOGE("Failed to get name\n");
386 extra_key = sqlite3_column_text(stmt, 3);
388 LOGE("Failed to get service\n");
392 extra_data = sqlite3_column_text(stmt, 4);
394 LOGE("Failed to get service\n");
398 icon = sqlite3_column_text(stmt, 5);
400 LOGE("Failed to get icon\n");
406 * Implement the "GET LOCALE" code
408 /* if (get_i18n_name(language, id, &i18n_name, &i18n_icon) < 0) { */
409 /* Okay, we can't manage this. just use the fallback string */
411 _get_i18n_name(handle, language, id, &i18n_name, &i18n_icon);
414 shortcut = (shortcut_info_s *)calloc(sizeof(shortcut_info_s), 1);
415 if (shortcut == NULL) {
420 shortcut->package_name = strdup(package_name);
421 shortcut->icon = strdup((i18n_icon != NULL ? i18n_icon : (char *)icon));
422 shortcut->name = strdup((i18n_name != NULL ? i18n_name : (char *)name));
423 shortcut->extra_key = strdup((char *)extra_key);
424 shortcut->extra_data = strdup((char *)extra_data);
425 *shortcut_list = g_list_append(*shortcut_list, shortcut);
440 sqlite3_clear_bindings(stmt);
441 sqlite3_finalize(stmt);