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" \
47 static bool is_db_corrupted = false;
49 static int __check_integrity_cb(void *pid, int argc, char **argv, char **notUsed)
51 if (strcmp(argv[0], "ok") != 0) {
52 SHORTCUT_ERR("db integrity result : %s" , argv[0]);
53 is_db_corrupted = true;
57 SHORTCUT_INFO("db integrity result : %s" , argv[0]);
61 static int __recover_corrupted_db(sqlite3 *db)
63 int ret = SHORTCUT_ERROR_NONE;
67 SHORTCUT_INFO("DB is corrupted, start to recover corrupted db");
72 sql_ret = sqlite3_open_v2(DB_PATH, &db,
73 SQLITE_OPEN_CREATE |SQLITE_OPEN_READWRITE,
75 if (sql_ret != SQLITE_OK) {
76 SHORTCUT_ERR("Failed to open db[%d]", sql_ret);
78 ret = SHORTCUT_ERROR_IO_ERROR;
82 sql_ret = sqlite3_exec(db, QUERY_CREATE_SHORTCUT_TABLE, NULL, NULL, &errmsg);
83 if (sql_ret != SQLITE_OK) {
84 SHORTCUT_ERR("Failed to exec query[%d][%s]", sql_ret, errmsg);
85 ret = SHORTCUT_ERROR_IO_ERROR;
95 EAPI int shortcut_db_init()
97 int ret = SHORTCUT_ERROR_NONE;
102 sql_ret = sqlite3_open_v2(DB_PATH, &db,
103 SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
104 if (sql_ret != SQLITE_OK) {
105 SHORTCUT_ERR("Failed to open db[%d]", sql_ret);
106 ret = SHORTCUT_ERROR_IO_ERROR;
110 sql_ret = sqlite3_exec(db, QUERY_CREATE_SHORTCUT_TABLE,
111 NULL, NULL, &errmsg);
112 if (sql_ret != SQLITE_OK) {
113 SHORTCUT_ERR("Failed to exec query [%d][%s]", sql_ret, errmsg);
114 ret = SHORTCUT_ERROR_IO_ERROR;
118 sql_ret = sqlite3_exec(db, "PRAGMA integrity_check",
119 __check_integrity_cb, NULL, &errmsg);
120 if (sql_ret != SQLITE_OK || is_db_corrupted) {
121 SHORTCUT_ERR("Failed to exec query[%d][%s]", sql_ret, errmsg);
122 ret = SHORTCUT_ERROR_IO_ERROR;
126 if (sql_ret == SQLITE_CORRUPT || sql_ret == SQLITE_NOTADB || is_db_corrupted)
127 ret = __recover_corrupted_db(db);
129 sqlite3_free(errmsg);
136 static sqlite3 *_open_db(void)
139 const char *dbfile = DB_PATH;
142 ret = db_util_open(dbfile, &db, 0);
143 if (ret != SQLITE_OK) {
144 /* LCOV_EXCL_START */
145 SHORTCUT_DBG("Failed to open a %s\n", dbfile);
153 static int _close_db(sqlite3 **db)
157 if (db == NULL || *db == NULL)
158 return SHORTCUT_ERROR_INVALID_PARAMETER;
160 ret = db_util_close(*db);
161 if (ret != SQLITE_OK) {
162 /* LCOV_EXCL_START */
163 SHORTCUT_DBG("DB close error(%d)", ret);
164 return SHORTCUT_ERROR_IO_ERROR;
170 return SHORTCUT_ERROR_NONE;
173 /* LCOV_EXCL_START */
175 * \note this function will returns allocated(heap) string
177 static inline int _get_i18n_name(sqlite3 *handle, const char *lang, int id, char **name, char **icon)
180 static const char *query = "SELECT name, icon FROM shortcut_name WHERE id = ? AND lang = ? COLLATE NOCASE";
181 const unsigned char *_name;
182 const unsigned char *_icon;
186 status = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL);
187 if (status != SQLITE_OK) {
188 SHORTCUT_ERR("Failed to prepare stmt: %s\n", sqlite3_errmsg(handle));
192 status = sqlite3_bind_int(stmt, 1, id);
193 if (status != SQLITE_OK) {
194 SHORTCUT_ERR("Failed to bind id: %s\n", sqlite3_errmsg(handle));
199 status = sqlite3_bind_text(stmt, 2, lang, -1, SQLITE_TRANSIENT);
200 if (status != SQLITE_OK) {
201 SHORTCUT_ERR("Failed to bind lang: %s\n", sqlite3_errmsg(handle));
206 SHORTCUT_DBG("id: %d, lang: %s\n", id, lang);
207 if (SQLITE_ROW != sqlite3_step(stmt)) {
208 SHORTCUT_ERR("Failed to do step: %s\n", sqlite3_errmsg(handle));
213 _name = sqlite3_column_text(stmt, 0);
215 if (_name && strlen((const char *)_name)) {
216 *name = strdup((const char *)_name);
218 SHORTCUT_ERR("strdup: %d\n", errno);
227 _icon = sqlite3_column_text(stmt, 1);
229 if (_icon && strlen((const char *)_icon)) {
230 *icon = strdup((const char *)_icon);
232 SHORTCUT_ERR("strdup: %d\n", errno);
246 sqlite3_clear_bindings(stmt);
247 sqlite3_finalize(stmt);
252 static inline char *_cur_locale(void)
257 language = vconf_get_str(VCONFKEY_LANGSET);
272 language = strdup("en-us");
274 SHORTCUT_ERR("Heap: %d\n", errno);
280 EAPI int shortcut_db_get_list(const char *package_name, GList **shortcut_list)
283 sqlite3 *handle = NULL;
285 const unsigned char *name;
286 char *i18n_name = NULL;
287 char *i18n_icon = NULL;
288 const unsigned char *extra_data;
289 const unsigned char *extra_key;
290 const unsigned char *icon;
291 shortcut_info_s *shortcut;
299 /* LCOV_EXCL_START */
300 SHORTCUT_ERR("Failed to open a DB\n");
301 return SHORTCUT_ERROR_IO_ERROR;
305 language = _cur_locale();
307 /* LCOV_EXCL_START */
308 SHORTCUT_ERR("Locale is not valid\n");
310 return SHORTCUT_ERROR_FAULT;
315 query = "SELECT id, appid, name, extra_key, extra_data, icon FROM shortcut_service WHERE appid = ?";
316 ret = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL);
317 if (ret != SQLITE_OK) {
318 /* LCOV_EXCL_START */
319 SHORTCUT_ERR("prepare: %s\n", sqlite3_errmsg(handle));
322 return SHORTCUT_ERROR_IO_ERROR;
326 ret = sqlite3_bind_text(stmt, 1, package_name, -1, SQLITE_TRANSIENT);
327 if (ret != SQLITE_OK) {
328 /* LCOV_EXCL_START */
329 SHORTCUT_ERR("bind text: %s\n", sqlite3_errmsg(handle));
330 sqlite3_finalize(stmt);
333 return SHORTCUT_ERROR_IO_ERROR;
337 query = "SELECT id, appid, name, extra_key, extra_data, icon FROM shortcut_service";
338 ret = sqlite3_prepare_v2(handle, query, -1, &stmt, NULL);
339 if (ret != SQLITE_OK) {
340 /* LCOV_EXCL_START */
341 SHORTCUT_ERR("prepare: %s\n", sqlite3_errmsg(handle));
344 return SHORTCUT_ERROR_IO_ERROR;
350 *shortcut_list = NULL;
351 while (SQLITE_ROW == sqlite3_step(stmt)) {
352 /* LCOV_EXCL_START */
353 id = sqlite3_column_int(stmt, 0);
355 package_name = (const char *)sqlite3_column_text(stmt, 1);
357 LOGE("Failed to get package name\n");
361 name = sqlite3_column_text(stmt, 2);
363 LOGE("Failed to get name\n");
367 extra_key = sqlite3_column_text(stmt, 3);
369 LOGE("Failed to get service\n");
373 extra_data = sqlite3_column_text(stmt, 4);
375 LOGE("Failed to get service\n");
379 icon = sqlite3_column_text(stmt, 5);
381 LOGE("Failed to get icon\n");
387 * Implement the "GET LOCALE" code
389 /* if (get_i18n_name(language, id, &i18n_name, &i18n_icon) < 0) { */
390 /* Okay, we can't manage this. just use the fallback string */
392 _get_i18n_name(handle, language, id, &i18n_name, &i18n_icon);
395 shortcut = (shortcut_info_s *)calloc(sizeof(shortcut_info_s), 1);
396 if (shortcut == NULL) {
401 shortcut->package_name = strdup(package_name);
402 shortcut->icon = strdup((i18n_icon != NULL ? i18n_icon : (char *)icon));
403 shortcut->name = strdup((i18n_name != NULL ? i18n_name : (char *)name));
404 shortcut->extra_key = strdup((char *)extra_key);
405 shortcut->extra_data = strdup((char *)extra_data);
406 *shortcut_list = g_list_append(*shortcut_list, shortcut);
417 sqlite3_clear_bindings(stmt);
418 sqlite3_finalize(stmt);