--- /dev/null
+ /*
+ * Copyright (c) 2021 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 <stdbool.h>
+ #include <string.h>
+ #include <ctype.h>
+ #include <unistd.h>
+ #include <sys/types.h>
+ #include <dlfcn.h>
+
+ #include <sqlite3.h>
+ #include <glib.h>
+
+ #include "pkgmgr-info.h"
+ #include "pkgmgrinfo_debug.h"
+ #include "pkgmgrinfo_private.h"
+ #include "pkgmgr_parser.h"
+ #include "pkgmgrinfo_internal.h"
+
+ static void __parse_appcontrol(GList **appcontrol,
+ char *appcontrol_str, char *visibility, char *id)
+ {
+ char *dup;
+ char *token;
+ char *ptr = NULL;
+ appcontrol_x *ac;
+
+ if (appcontrol_str == NULL)
+ return;
+
+ dup = strdup(appcontrol_str);
+ if (dup == NULL) {
+ _LOGE("out of memory");
+ return;
+ }
+
+ do {
+ ac = calloc(1, sizeof(appcontrol_x));
+ if (ac == NULL) {
+ _LOGE("out of memory");
+ break;
+ }
+ token = strtok_r(dup, "|", &ptr);
+ if (token && strcmp(token, "NULL"))
+ ac->operation = strdup(token);
+ token = strtok_r(NULL, "|", &ptr);
+ if (token && strcmp(token, "NULL"))
+ ac->uri = strdup(token);
+ token = strtok_r(NULL, "|", &ptr);
+ if (token && strcmp(token, "NULL"))
+ ac->mime = strdup(token);
+ ac->visibility = strdup(visibility);
+ ac->id = strdup(id);
+ *appcontrol = g_list_prepend(*appcontrol, ac);
+ } while ((token = strtok_r(NULL, ";", &ptr)));
+
+ free(dup);
+ }
+
+ static int _appinfo_get_splashscreens(sqlite3 *db,
+ const char *appid, GList **splashscreens)
+ {
+ static const char query_raw[] =
+ "SELECT src, type, orientation, indicatordisplay, "
+ "operation, color_depth "
+ "FROM package_app_splash_screen WHERE app_id=%Q";
+ int ret;
+ char *query;
+ sqlite3_stmt *stmt;
+ int idx;
+ splashscreen_x *info;
+
+ query = sqlite3_mprintf(query_raw, appid);
+ if (query == NULL) {
+ LOGE("out of memory");
+ return PMINFO_R_ERROR;
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ sqlite3_free(query);
+ if (ret != SQLITE_OK) {
+ LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return PMINFO_R_ERROR;
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ info = calloc(1, sizeof(splashscreen_x));
+ if (info == NULL) {
+ LOGE("out of memory");
+ sqlite3_finalize(stmt);
+ return PMINFO_R_ERROR;
+ }
+ idx = 0;
+ _save_column_str(stmt, idx++, &info->src);
+ _save_column_str(stmt, idx++, &info->type);
+ _save_column_str(stmt, idx++, &info->orientation);
+ _save_column_str(stmt, idx++, &info->indicatordisplay);
+ _save_column_str(stmt, idx++, &info->operation);
+ _save_column_str(stmt, idx++, &info->color_depth);
+ *splashscreens = g_list_prepend(*splashscreens, info);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return PMINFO_R_OK;
+ }
+
+ static int _appinfo_get_metadata(sqlite3 *db,
+ const char *appid, GList **metadata)
+ {
+ static const char query_raw[] =
+ "SELECT md_key, md_value "
+ "FROM package_app_app_metadata WHERE app_id=%Q";
+ int ret;
+ char *query;
+ sqlite3_stmt *stmt;
+ int idx;
+ metadata_x *info;
+
+ query = sqlite3_mprintf(query_raw, appid);
+ if (query == NULL) {
+ LOGE("out of memory");
+ return PMINFO_R_ERROR;
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ sqlite3_free(query);
+ if (ret != SQLITE_OK) {
+ LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return PMINFO_R_ERROR;
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ info = calloc(1, sizeof(metadata_x));
+ if (info == NULL) {
+ LOGE("out of memory");
+ sqlite3_finalize(stmt);
+ return PMINFO_R_ERROR;
+ }
+ idx = 0;
+ _save_column_str(stmt, idx++, &info->key);
+ _save_column_str(stmt, idx++, &info->value);
+ *metadata = g_list_prepend(*metadata, info);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return PMINFO_R_OK;
+ }
+
+ static int _appinfo_get_app_control(sqlite3 *db,
+ const char *appid, GList **appcontrol)
+ {
+ static const char query_raw[] =
+ "SELECT app_control, visibility, app_control_id "
+ "FROM package_app_app_control WHERE app_id=%Q";
+ int ret;
+ int idx;
+ char *query;
+ sqlite3_stmt *stmt;
+ char *str;
+ char *visibility;
+ char *id;
+
+ query = sqlite3_mprintf(query_raw, appid);
+ if (query == NULL) {
+ LOGE("out of memory");
+ return PMINFO_R_ERROR;
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ sqlite3_free(query);
+ if (ret != SQLITE_OK) {
+ LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return PMINFO_R_ERROR;
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ str = NULL;
+ visibility = NULL;
+ id = NULL;
+ idx = 0;
+ _save_column_str(stmt, idx++, &str);
+ _save_column_str(stmt, idx++, &visibility);
+ _save_column_str(stmt, idx++, &id);
+ /* TODO: revise */
+ __parse_appcontrol(appcontrol, str, visibility, id);
+ free(str);
+ free(visibility);
+ free(id);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return PMINFO_R_OK;
+ }
+
+ static int _appinfo_get_category(sqlite3 *db,
+ const char *appid, GList **category)
+ {
+ static const char query_raw[] =
+ "SELECT category "
+ "FROM package_app_app_category WHERE app_id=%Q";
+ int ret;
+ char *query;
+ sqlite3_stmt *stmt;
+ char *val;
+
+ query = sqlite3_mprintf(query_raw, appid);
+ if (query == NULL) {
+ LOGE("out of memory");
+ return PMINFO_R_ERROR;
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ sqlite3_free(query);
+ if (ret != SQLITE_OK) {
+ LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return PMINFO_R_ERROR;
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ val = NULL;
+ _save_column_str(stmt, 0, &val);
+ if (val)
+ *category = g_list_prepend(*category, (gpointer)val);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return PMINFO_R_OK;
+ }
+
++static int _appinfo_get_res_control(sqlite3 *db, const char *appid,
++ GList **res_control)
++{
++ static const char query_raw[] =
++ "SELECT res_type, min_res_version, max_res_version, auto_close "
++ "FROM package_app_res_control WHERE app_id=%Q";
++ int ret;
++ char *query;
++ sqlite3_stmt *stmt;
++ int idx;
++ res_control_x *info;
++
++ query = sqlite3_mprintf(query_raw, appid);
++ if (query == NULL) {
++ LOGE("out of memory");
++ return PMINFO_R_ERROR;
++ }
++
++ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
++ sqlite3_free(query);
++ if (ret != SQLITE_OK) {
++ LOGE("prepare failed: %s", sqlite3_errmsg(db));
++ return PMINFO_R_ERROR;
++ }
++
++ while (sqlite3_step(stmt) == SQLITE_ROW) {
++ info = calloc(1, sizeof(res_control_x));
++ if (info == NULL) {
++ LOGE("out of memory");
++ sqlite3_finalize(stmt);
++ return PMINFO_R_ERROR;
++ }
++ idx = 0;
++ _save_column_str(stmt, idx++, &info->res_type);
++ _save_column_str(stmt, idx++, &info->min_res_version);
++ _save_column_str(stmt, idx++, &info->max_res_version);
++ _save_column_str(stmt, idx++, &info->auto_close);
++ *res_control = g_list_prepend(*res_control, info);
++ }
++
++ sqlite3_finalize(stmt);
++
++ return PMINFO_R_OK;
++}
++
+ static GList *__get_background_category(const char *value)
+ {
+ GList *category_list = NULL;
+ int convert_value = 0;
+
+ if (!value || strlen(value) == 0)
+ return NULL;
+
+ convert_value = atoi(value);
+ if (convert_value < 0)
+ return NULL;
+
+ if (convert_value & APP_BG_CATEGORY_USER_DISABLE_TRUE_VAL)
+ category_list = g_list_prepend(category_list,
+ strdup(APP_BG_CATEGORY_USER_DISABLE_TRUE_STR));
+ else
+ category_list = g_list_prepend(category_list,
+ strdup(APP_BG_CATEGORY_USER_DISABLE_FALSE_STR));
+
+ if (convert_value & APP_BG_CATEGORY_MEDIA_VAL)
+ category_list = g_list_prepend(category_list,
+ strdup(APP_BG_CATEGORY_MEDIA_STR));
+
+ if (convert_value & APP_BG_CATEGORY_DOWNLOAD_VAL)
+ category_list = g_list_prepend(category_list,
+ strdup(APP_BG_CATEGORY_DOWNLOAD_STR));
+
+ if (convert_value & APP_BG_CATEGORY_BGNETWORK_VAL)
+ category_list = g_list_prepend(category_list,
+ strdup(APP_BG_CATEGORY_BGNETWORK_STR));
+
+ if (convert_value & APP_BG_CATEGORY_LOCATION_VAL)
+ category_list = g_list_prepend(category_list,
+ strdup(APP_BG_CATEGORY_LOCATION_STR));
+
+ if (convert_value & APP_BG_CATEGORY_SENSOR_VAL)
+ category_list = g_list_prepend(category_list,
+ strdup(APP_BG_CATEGORY_SENSOR_STR));
+
+ if (convert_value & APP_BG_CATEGORY_IOTCOMM_VAL)
+ category_list = g_list_prepend(category_list,
+ strdup(APP_BG_CATEGORY_IOTCOMM_STR));
+
+ if (convert_value & APP_BG_CATEGORY_SYSTEM_VAL)
+ category_list = g_list_prepend(category_list,
+ strdup(APP_BG_CATEGORY_SYSTEM));
+
+ return category_list;
+ }
+
+ static int __bind_params(sqlite3_stmt *stmt, GList *params)
+ {
+ GList *tmp_list = NULL;
+ int idx = 0;
+ int ret;
+
+ if (stmt == NULL || params == NULL)
+ return PMINFO_R_EINVAL;
+
+ tmp_list = params;
+ while (tmp_list) {
+ ret = sqlite3_bind_text(stmt, ++idx,
+ (char *)tmp_list->data, -1, SQLITE_STATIC);
+ if (ret != SQLITE_OK)
+ return PMINFO_R_ERROR;
+ tmp_list = tmp_list->next;
+ }
+
+ return PMINFO_R_OK;
+ }
+
+ static const char join_localized_info[] =
+ " LEFT OUTER JOIN package_app_localized_info"
+ " ON ai.app_id=package_app_localized_info.app_id"
+ " AND package_app_localized_info.app_locale=?";
+ static const char join_category[] =
+ " LEFT OUTER JOIN package_app_app_category"
+ " ON ai.app_id=package_app_app_category.app_id";
+ static const char join_app_control[] =
+ " LEFT OUTER JOIN package_app_app_control"
+ " ON ai.app_id=package_app_app_control.app_id";
+ static const char join_metadata[] =
+ " LEFT OUTER JOIN package_app_app_metadata"
+ " ON ai.app_id=package_app_app_metadata.app_id ";
+ static const char join_privilege[] =
+ " LEFT OUTER JOIN package_privilege_info"
+ " ON ai.package=package_privilege_info.package ";
+
+ static int _get_filtered_query(pkgmgrinfo_filter_x *filter, const char *locale,
+ uid_t uid, char **query, GList **bind_params)
+ {
+ int joined = 0;
+ int size;
+ char *condition = NULL;
+ char buf[MAX_QUERY_LEN] = {'\0'};
+ char tmp_query[MAX_QUERY_LEN] = {'\0'};
+ GSList *list;
+
+ if (!filter)
+ return PMINFO_R_OK;
+ strncat(buf, " WHERE 1=1", sizeof(buf) - strlen(buf) - 1);
+
+ for (list = filter->list; list; list = list->next) {
+ joined |= __get_filter_condition(list->data,
+ uid, &condition, bind_params);
+ if (condition == NULL)
+ continue;
+
+ strncat(buf, " AND ", sizeof(buf) - strlen(buf) - 1);
+
+ strncat(buf, condition, sizeof(buf) - strlen(buf) - 1);
+ free(condition);
+ condition = NULL;
+ }
+
+ if (filter->list_metadata)
+ strncat(buf, " AND (", sizeof(buf) - strlen(buf) - 1);
+ for (list = filter->list_metadata; list; list = list->next) {
+ joined |= __get_metadata_filter_condition(list->data,
+ &condition, bind_params);
+ if (condition == NULL)
+ continue;
+ strncat(buf, condition, sizeof(buf) - strlen(buf) - 1);
+ free(condition);
+ condition = NULL;
+
+ strncat(buf, " OR ", sizeof(buf) - strlen(buf) - 1);
+ }
+ if (filter->list_metadata)
+ strncat(buf, "1=0)", sizeof(buf) - strlen(buf) - 1);
+
+ if (joined & E_PMINFO_APPINFO_JOIN_LOCALIZED_INFO) {
+ strncat(tmp_query, join_localized_info,
+ sizeof(tmp_query) - strlen(tmp_query) - 1);
+ *bind_params = g_list_append(*bind_params, strdup(locale));
+ }
+ if (joined & E_PMINFO_APPINFO_JOIN_CATEGORY)
+ strncat(tmp_query, join_category,
+ sizeof(tmp_query) - strlen(tmp_query) - 1);
+ if (joined & E_PMINFO_APPINFO_JOIN_APP_CONTROL)
+ strncat(tmp_query, join_app_control,
+ sizeof(tmp_query) - strlen(tmp_query) - 1);
+ if (joined & E_PMINFO_APPINFO_JOIN_METADATA)
+ strncat(tmp_query, join_metadata,
+ sizeof(tmp_query) - strlen(tmp_query) - 1);
+ if (joined & E_PMINFO_APPINFO_JOIN_PRIVILEGE)
+ strncat(tmp_query, join_privilege,
+ sizeof(tmp_query) - strlen(tmp_query) - 1);
+
+ size = strlen(tmp_query) + strlen(buf) + 1;
+ *query = (char *)calloc(1, size);
+ if (*query == NULL)
+ return PMINFO_R_ERROR;
+ snprintf(*query, size, "%s%s", tmp_query, buf);
+
+ return PMINFO_R_OK;
+ }
+
+ static bool __check_app_storage_status(pkgmgrinfo_filter_x *tmp_filter)
+ {
+ GSList *tmp_list = NULL;
+ pkgmgrinfo_node_x *tmp_node = NULL;
+ int property = -1;
+
+ if (tmp_filter == NULL)
+ return true;
+
+ property = _pminfo_appinfo_convert_to_prop_bool(
+ PMINFO_APPINFO_PROP_APP_CHECK_STORAGE);
+ for (tmp_list = tmp_filter->list; tmp_list != NULL;
+ tmp_list = g_slist_next(tmp_list)) {
+ tmp_node = (pkgmgrinfo_node_x *)tmp_list->data;
+ if (property == tmp_node->prop) {
+ if (strcmp(tmp_node->value, "true") == 0)
+ return true;
+ else
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ static int _appinfo_get_applications(sqlite3 *db, uid_t db_uid, uid_t uid,
+ const char *locale, pkgmgrinfo_filter_x *filter, int flag,
+ GHashTable *applications)
+ {
+ static const char query_raw[] =
+ "SELECT DISTINCT ai.app_id, ai.app_installed_storage, "
+ "ai.app_external_path";
+ static const char query_basic[] =
+ ", ai.app_component, ai.app_exec, "
+ "ai.app_nodisplay, ai.app_type, ai.app_onboot, "
+ "ai.app_multiple, ai.app_autorestart, ai.app_taskmanage, "
+ "ai.app_hwacceleration, ai.app_screenreader, "
+ "ai.app_mainapp, ai.app_recentimage, ai.app_launchcondition, "
+ "ai.app_indicatordisplay, ai.app_portraitimg, "
+ "ai.app_landscapeimg, ai.app_guestmodevisibility, "
+ "ai.app_permissiontype, ai.app_preload, ai.app_submode, "
+ "ai.app_submode_mainid, ai.app_launch_mode, ai.app_ui_gadget, "
+ "ai.app_support_disable, ai.app_process_pool, "
+ "ai.app_background_category, ai.app_package_type, "
+ "ai.app_root_path, ai.app_api_version, ai.app_effective_appid, "
+ "ai.app_disable, ai.app_splash_screen_display, ai.app_tep_name, "
+ "ai.app_zip_mount_file, ai.component_type, ai.package, "
+ "ai.app_package_system, ai.app_removable, "
+ "ai.app_package_installed_time, ai.app_support_mode, "
+ "ai.app_support_ambient, ai.app_setup_appid";
+ static const char query_uid_info[] =
+ ", ui.is_disabled, ui.is_splash_screen_enabled";
+ static const char query_label[] =
+ ", COALESCE("
+ "(SELECT app_label FROM package_app_localized_info WHERE "
+ "ai.app_id=app_id AND app_locale=?), "
+ "(SELECT app_label FROM package_app_localized_info WHERE "
+ "ai.app_id=app_id AND app_locale='No Locale'))";
+ static const char query_icon[] =
+ ", COALESCE("
+ "(SELECT app_icon FROM package_app_localized_info WHERE ai.app_id=app_id "
+ "AND app_locale=?), "
+ "(SELECT app_icon FROM package_app_localized_info WHERE ai.app_id=app_id "
+ "AND app_locale='No Locale'))";
+ static const char query_from_clause[] = " FROM package_app_info as ai";
+ static const char query_uid_info_clause[] =
+ " LEFT OUTER JOIN package_app_info_for_uid AS ui "
+ "ON (ai.app_id=ui.app_id AND ui.uid=?)";
+ int ret = PMINFO_R_ERROR;
+ int idx;
+ char *bg_category_str = NULL;
+ char *constraint = NULL;
+ char *tmp_record = NULL;
+ char query[MAX_QUERY_LEN] = {'\0'};
+ char buf[BUFSIZE] = {'\0'};
+ application_x *info = NULL;
+ GList *bind_params = NULL;
+ sqlite3_stmt *stmt = NULL;
+ bool is_check_storage = true;
+ const uid_t global_user_uid = GLOBAL_USER;
+
+ snprintf(query, MAX_QUERY_LEN - 1, "%s", query_raw);
+
+ if (flag & PMINFO_APPINFO_GET_BASICINFO) {
+ strncat(query, query_basic, sizeof(query) - strlen(query) - 1);
+ strncat(query, query_uid_info,
+ sizeof(query) - strlen(query) - 1);
+ }
+ if (flag & PMINFO_APPINFO_GET_LABEL) {
+ strncat(query, query_label, sizeof(query) - strlen(query) - 1);
+ bind_params = g_list_append(bind_params, strdup(locale));
+ }
+ if (flag & PMINFO_APPINFO_GET_ICON) {
+ strncat(query, query_icon, sizeof(query) - strlen(query) - 1);
+ bind_params = g_list_append(bind_params, strdup(locale));
+ }
+
+ snprintf(buf, MAX_QUERY_LEN - 1, "%d", uid);
+ bind_params = g_list_append(bind_params, strdup(buf));
+
+ is_check_storage = __check_app_storage_status(filter);
+
+ ret = _get_filtered_query(filter, locale,
+ uid, &constraint, &bind_params);
+ if (ret != PMINFO_R_OK) {
+ LOGE("Failed to get WHERE clause");
+ goto catch;
+ }
+ strncat(query, query_from_clause, sizeof(query) - strlen(query) - 1);
+
+ strncat(query, query_uid_info_clause,
+ sizeof(query) - strlen(query) - 1);
+
+ if (constraint)
+ strncat(query, constraint, sizeof(query) - strlen(query) - 1);
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+
+ if (g_list_length(bind_params) != 0) {
+ ret = __bind_params(stmt, bind_params);
+ if (ret != SQLITE_OK) {
+ LOGE("Failed to bind parameters");
+ goto catch;
+ }
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ info = calloc(1, sizeof(application_x));
+ if (info == NULL) {
+ LOGE("out of memory");
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+ info->locale = strdup(locale);
+ if (info->locale == NULL) {
+ LOGE("Out of memory");
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+
+ idx = 0;
+ _save_column_str(stmt, idx++, &info->appid);
+ _save_column_str(stmt, idx++, &info->installed_storage);
+ _save_column_str(stmt, idx++, &info->external_path);
+
+ if (flag & PMINFO_APPINFO_GET_BASICINFO) {
+ _save_column_str(stmt, idx++, &info->component);
+ _save_column_str(stmt, idx++, &info->exec);
+ _save_column_str(stmt, idx++, &info->nodisplay);
+ _save_column_str(stmt, idx++, &info->type);
+ _save_column_str(stmt, idx++, &info->onboot);
+ _save_column_str(stmt, idx++, &info->multiple);
+ _save_column_str(stmt, idx++, &info->autorestart);
+ _save_column_str(stmt, idx++, &info->taskmanage);
+ _save_column_str(stmt, idx++, &info->hwacceleration);
+ _save_column_str(stmt, idx++, &info->screenreader);
+ _save_column_str(stmt, idx++, &info->mainapp);
+ _save_column_str(stmt, idx++, &info->recentimage);
+ _save_column_str(stmt, idx++, &info->launchcondition);
+ _save_column_str(stmt, idx++, &info->indicatordisplay);
+ _save_column_str(stmt, idx++, &info->portraitimg);
+ _save_column_str(stmt, idx++, &info->landscapeimg);
+ _save_column_str(stmt, idx++,
+ &info->guestmode_visibility);
+ _save_column_str(stmt, idx++, &info->permission_type);
+ _save_column_str(stmt, idx++, &info->preload);
+ _save_column_str(stmt, idx++, &info->submode);
+ _save_column_str(stmt, idx++, &info->submode_mainid);
+ _save_column_str(stmt, idx++, &info->launch_mode);
+ _save_column_str(stmt, idx++, &info->ui_gadget);
+ _save_column_str(stmt, idx++, &info->support_disable);
+ _save_column_str(stmt, idx++, &info->process_pool);
+ _save_column_str(stmt, idx++, &bg_category_str);
+ _save_column_str(stmt, idx++, &info->package_type);
+ _save_column_str(stmt, idx++, &info->root_path);
+ _save_column_str(stmt, idx++, &info->api_version);
+ _save_column_str(stmt, idx++, &info->effective_appid);
+ _save_column_str(stmt, idx++, &info->is_disabled);
+ _save_column_str(stmt, idx++,
+ &info->splash_screen_display);
+ _save_column_str(stmt, idx++, &info->tep_name);
+ _save_column_str(stmt, idx++, &info->zip_mount_file);
+ _save_column_str(stmt, idx++, &info->component_type);
+ _save_column_str(stmt, idx++, &info->package);
+ _save_column_str(stmt, idx++, &info->package_system);
+ _save_column_str(stmt, idx++, &info->removable);
+ _save_column_str(stmt, idx++,
+ &info->package_installed_time);
+ _save_column_str(stmt, idx++, &info->support_mode);
+ _save_column_str(stmt, idx++, &info->support_ambient);
+ _save_column_str(stmt, idx++, &info->setup_appid);
+ info->background_category = __get_background_category(
+ bg_category_str);
+ free(bg_category_str);
+ bg_category_str = NULL;
+ }
+
+ info->for_all_users =
+ strdup((db_uid != global_user_uid) ?
+ "false" : "true");
+
+ if (db_uid != global_user_uid) {
+ idx = idx + 2;
+ } else {
+ tmp_record = NULL;
+ _save_column_str(stmt, idx++, &tmp_record);
+ if (tmp_record != NULL) {
+ if (strcasecmp(info->is_disabled, "false") == 0 &&
+ strcasecmp(tmp_record, "false") == 0) {
+ free(info->is_disabled);
+ info->is_disabled = tmp_record;
+ } else {
+ free(tmp_record);
+ }
+ }
+ tmp_record = NULL;
+ _save_column_str(stmt, idx++, &tmp_record);
+ if (tmp_record != NULL) {
+ if (strcasecmp(info->splash_screen_display, "false") == 0 &&
+ strcasecmp(tmp_record, "false") == 0) {
+ free(info->splash_screen_display);
+ info->splash_screen_display = tmp_record;
+ } else {
+ free(tmp_record);
+ }
+ }
+ }
+
+ if (flag & PMINFO_APPINFO_GET_LABEL) {
+ tmp_record = NULL;
+ _save_column_str(stmt, idx++, &tmp_record);
+ if (_add_label_info_into_list(locale, tmp_record,
+ &info->label)) {
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+ }
+
+ if (flag & PMINFO_APPINFO_GET_ICON) {
+ tmp_record = NULL;
+ _save_column_str(stmt, idx++, &tmp_record);
+ if (_add_icon_info_into_list(locale, tmp_record,
+ &info->icon)) {
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+ }
+
+ if (flag & PMINFO_APPINFO_GET_CATEGORY) {
+ if (_appinfo_get_category(db, info->appid,
+ &info->category)) {
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+ }
+
+ if (flag & PMINFO_APPINFO_GET_APP_CONTROL) {
+ if (_appinfo_get_app_control(db, info->appid,
+ &info->appcontrol)) {
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+ }
+
+ if (flag & PMINFO_APPINFO_GET_METADATA) {
+ if (_appinfo_get_metadata(db, info->appid,
+ &info->metadata)) {
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+ }
+
+ if (flag & PMINFO_APPINFO_GET_SPLASH_SCREEN) {
+ if (_appinfo_get_splashscreens(db, info->appid,
+ &info->splashscreens)) {
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+ }
+
++ if (flag & PMINFO_APPINFO_GET_RES_CONTROL) {
++ if (_appinfo_get_res_control(db, info->appid,
++ &info->res_control)) {
++ ret = PMINFO_R_ERROR;
++ goto catch;
++ }
++ }
++
+ if (is_check_storage &&
+ __appinfo_check_installed_storage(info) !=
+ PMINFO_R_OK) {
+ ret = PMINFO_R_ERROR;
+ pkgmgrinfo_basic_free_application(info);
+ info = NULL;
+ continue;
+ }
+
+ g_hash_table_insert(applications, (gpointer)info->appid,
+ (gpointer)info);
+ }
+
+ ret = PMINFO_R_OK;
+
+ catch:
+ sqlite3_finalize(stmt);
+
+ if (constraint)
+ free(constraint);
+
+ if (ret != PMINFO_R_OK && info != NULL)
+ pkgmgrinfo_basic_free_application(info);
+
+ g_list_free_full(bind_params, free);
+
+ return ret;
+ }
+
+ API int appinfo_internal_filter_get_list(sqlite3 *db,
+ pkgmgrinfo_appinfo_filter_h filter, uid_t db_uid, uid_t uid,
+ const char *locale, GHashTable *appinfo_list)
+ {
+ int ret;
+
+ if (db == NULL || filter == NULL || appinfo_list == NULL) {
+ LOGE("Invalid argument");
+ return PMINFO_R_EINVAL;
+ }
+
+ ret = _appinfo_get_applications(db, db_uid, uid, locale, filter,
+ PMINFO_APPINFO_GET_ALL, appinfo_list);
+ return ret;
+ }
--- /dev/null
- __BIND_TEXT(db, stmt, idx++, app->component);
+ /*
+ * Copyright (c) 2021 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 _GNU_SOURCE
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+ #include <stdbool.h>
+ #include <unistd.h>
+ #include <ctype.h>
+ #include <sys/smack.h>
+ #include <linux/limits.h>
+ #include <libgen.h>
+ #include <sys/stat.h>
+
+ #include <sqlite3.h>
+ #include <glib.h>
+
+ #include <system_info.h>
+
+ #include "pkgmgr_parser.h"
+ #include "pkgmgrinfo_basic.h"
+ #include "pkgmgrinfo_internal.h"
+ #include "pkgmgrinfo_private.h"
+ #include "pkgmgrinfo_debug.h"
+ #include "pkgmgr-info.h"
+
+ #define LDPI "ldpi"
+ #define MDPI "mdpi"
+ #define HDPI "hdpi"
+ #define XHDPI "xhdpi"
+ #define XXHDPI "xxhdpi"
+
+ #define LDPI_MIN 0
+ #define LDPI_MAX 240
+ #define MDPI_MIN 241
+ #define MDPI_MAX 300
+ #define HDPI_MIN 301
+ #define HDPI_MAX 380
+ #define XHDPI_MIN 381
+ #define XHDPI_MAX 480
+ #define XXHDPI_MIN 481
+ #define XXHDPI_MAX 600
+
+ static const char join_localized_info[] =
+ " LEFT OUTER JOIN package_localized_info"
+ " ON pi.package=package_localized_info.package"
+ " AND package_localized_info.package_locale=?";
+ static const char join_privilege_info[] =
+ " LEFT OUTER JOIN package_privilege_info"
+ " ON pi.package=package_privilege_info.package";
++static const char join_res_info[] =
++ " LEFT OUTER JOIN package_res_info"
++ " ON pi.package=package_res_info.package";
+
+ static int _get_filtered_query(pkgmgrinfo_filter_x *filter,
+ const char *locale, uid_t uid,
+ char **query, GList **bind_params)
+ {
+ int joined = 0;
+ int size;
+ char buf[MAX_QUERY_LEN] = { '\0' };
+ char buf2[MAX_QUERY_LEN] = { '\0' };
+ char *condition = NULL;
+ GSList *list = NULL;
+
+ if (filter == NULL)
+ return PMINFO_R_OK;
+
+ snprintf(buf, sizeof(buf), "%s", " WHERE 1=1 ");
+ for (list = filter->list; list; list = list->next) {
+ joined |= __get_filter_condition(list->data, uid, &condition,
+ bind_params);
+ if (condition == NULL)
+ continue;
+
+ strncat(buf, " AND ", sizeof(buf) - strlen(buf) - 1);
+
+ strncat(buf, condition, sizeof(buf) - strlen(buf) - 1);
+ free(condition);
+ condition = NULL;
+ }
+
+ if (joined & E_PMINFO_PKGINFO_JOIN_LOCALIZED_INFO) {
+ strncat(buf2, join_localized_info,
+ sizeof(buf2) - strlen(buf2) - 1);
+ *bind_params = g_list_append(*bind_params, strdup(locale));
+ }
+ if (joined & E_PMINFO_PKGINFO_JOIN_PRIVILEGE_INFO)
+ strncat(buf2, join_privilege_info,
+ sizeof(buf2) - strlen(buf2) - 1);
++ if (joined & E_PMINFO_PKGINFO_JOIN_RES_INFO)
++ strncat(buf2, join_res_info,
++ sizeof(buf2) - strlen(buf2) - 1);
+
+ size = strlen(buf2) + strlen(buf) + 1;
+ *query = (char *)calloc(1, size);
+ if (*query == NULL)
+ return PMINFO_R_ERROR;
+ snprintf(*query, size, "%s%s", buf2, buf);
+
+ return PMINFO_R_OK;
+ }
+
+ static int __bind_params(sqlite3_stmt *stmt, GList *params)
+ {
+ GList *tmp_list = NULL;
+ int idx = 0;
+ int ret;
+
+ if (stmt == NULL || params == NULL)
+ return PMINFO_R_EINVAL;
+
+ tmp_list = params;
+ while (tmp_list) {
+ ret = sqlite3_bind_text(stmt, ++idx,
+ (char *)tmp_list->data, -1, SQLITE_STATIC);
+ if (ret != SQLITE_OK)
+ return PMINFO_R_ERROR;
+ tmp_list = tmp_list->next;
+ }
+
+ return PMINFO_R_OK;
+ }
+
+ static bool __check_package_storage_status(pkgmgrinfo_filter_x *tmp_filter)
+ {
+ GSList *tmp_list = NULL;
+ pkgmgrinfo_node_x *tmp_node = NULL;
+ int property = -1;
+
+ property = _pminfo_pkginfo_convert_to_prop_bool(
+ PMINFO_PKGINFO_PROP_PACKAGE_CHECK_STORAGE);
+ for (tmp_list = tmp_filter->list; tmp_list != NULL;
+ tmp_list = g_slist_next(tmp_list)) {
+ tmp_node = (pkgmgrinfo_node_x *)tmp_list->data;
+ if (property == tmp_node->prop) {
+ if (strcmp(tmp_node->value, "true") == 0)
+ return true;
+ else
+ return false;
+ }
+ }
+ return true;
+ }
+
+ static int _pkginfo_add_description_info_into_list(const char *locale,
+ char *record, GList **description)
+ {
+ description_x *info;
+
+ info = calloc(1, sizeof(description_x));
+ if (info == NULL) {
+ LOGE("out of memory");
+ return PMINFO_R_ERROR;
+ }
+ info->lang = strdup(locale);
+ info->text = record;
+ *description = g_list_prepend(*description, info);
+
+ return PMINFO_R_OK;
+ }
+
+ static int _pkginfo_get_plugin_execution_info(sqlite3 *db, const char *pkgid,
+ GList **plugins)
+ {
+ static const char query_raw[] =
+ "SELECT appid, plugin_type, plugin_name FROM package_plugin_info "
+ "WHERE pkgid=%Q";
+ int ret;
+ char *query;
+ sqlite3_stmt *stmt;
+ plugin_x *plugin;
+
+ query = sqlite3_mprintf(query_raw, pkgid);
+ if (query == NULL) {
+ LOGE("out of memory");
+ return PMINFO_R_ERROR;
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query),
+ &stmt, NULL);
+ sqlite3_free(query);
+ if (ret != SQLITE_OK) {
+ LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return PMINFO_R_ERROR;
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ plugin = calloc(1, sizeof(plugin_x));
+ if (!plugin) {
+ LOGE("out of memory");
+ sqlite3_finalize(stmt);
+ return PMINFO_R_ERROR;
+ }
+ plugin->pkgid = strdup(pkgid);
+ _save_column_str(stmt, 0, &plugin->appid);
+ _save_column_str(stmt, 1, &plugin->plugin_type);
+ _save_column_str(stmt, 2, &plugin->plugin_name);
+ *plugins = g_list_prepend(*plugins,
+ (gpointer)plugin);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return PMINFO_R_OK;
+ }
+
+ static int _pkginfo_get_privilege(sqlite3 *db, const char *pkgid,
+ GList **privileges)
+ {
+ static const char query_raw[] =
+ "SELECT DISTINCT privilege, type FROM package_privilege_info "
+ "WHERE package=%Q";
+ int ret;
+ char *query;
+ sqlite3_stmt *stmt;
+ privilege_x *privilege;
+
+ query = sqlite3_mprintf(query_raw, pkgid);
+ if (query == NULL) {
+ LOGE("out of memory");
+ return PMINFO_R_ERROR;
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query),
+ &stmt, NULL);
+ sqlite3_free(query);
+ if (ret != SQLITE_OK) {
+ LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return PMINFO_R_ERROR;
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ privilege = calloc(1, sizeof(privilege_x));
+ if (!privilege) {
+ LOGE("failed to alloc memory");
+ sqlite3_finalize(stmt);
+ return PMINFO_R_ERROR;
+ }
+ _save_column_str(stmt, 0, &privilege->value);
+ _save_column_str(stmt, 1, &privilege->type);
+ *privileges = g_list_prepend(*privileges,
+ (gpointer)privilege);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return PMINFO_R_OK;
+ }
+
+ static int _pkginfo_get_appdefined_privilege(sqlite3 *db, const char *pkgid,
+ GList **privileges)
+ {
+ static const char query_raw[] =
+ "SELECT DISTINCT privilege, license, type FROM "
+ "package_appdefined_privilege_info WHERE package=%Q";
+ int ret;
+ char *query;
+ sqlite3_stmt *stmt;
+ appdefined_privilege_x *privilege;
+
+ query = sqlite3_mprintf(query_raw, pkgid);
+ if (query == NULL) {
+ LOGE("out of memory");
+ return PMINFO_R_ERROR;
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query),
+ &stmt, NULL);
+ sqlite3_free(query);
+ if (ret != SQLITE_OK) {
+ LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return PMINFO_R_ERROR;
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ privilege = calloc(1, sizeof(appdefined_privilege_x));
+ if (!privilege) {
+ LOGE("failed to alloc memory");
+ sqlite3_finalize(stmt);
+ return PMINFO_R_ERROR;
+ }
+ _save_column_str(stmt, 0, &privilege->value);
+ _save_column_str(stmt, 1, &privilege->license);
+ _save_column_str(stmt, 2, &privilege->type);
+ *privileges = g_list_prepend(*privileges,
+ (gpointer)privilege);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return PMINFO_R_OK;
+ }
+
+ static int _pkginfo_get_dependency(sqlite3 *db, const char *pkgid,
+ GList **dependencies)
+ {
+ static const char query_raw[] =
+ "SELECT DISTINCT depends_on, type, required_version "
+ "FROM package_dependency_info WHERE package=%Q";
+ int ret;
+ char *query;
+ sqlite3_stmt *stmt;
+ dependency_x *dependency;
+
+ query = sqlite3_mprintf(query_raw, pkgid);
+ if (query == NULL) {
+ LOGE("out of memory");
+ return PMINFO_R_ERROR;
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ sqlite3_free(query);
+ if (ret != SQLITE_OK) {
+ LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return PMINFO_R_ERROR;
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ dependency = calloc(1, sizeof(dependency_x));
+ if (!dependency) {
+ LOGE("failed to alloc memory");
+ sqlite3_finalize(stmt);
+ return PMINFO_R_ERROR;
+ }
+ _save_column_str(stmt, 0, &dependency->depends_on);
+ _save_column_str(stmt, 1, &dependency->type);
+ _save_column_str(stmt, 2, &dependency->required_version);
+ *dependencies = g_list_prepend(*dependencies,
+ (gpointer)dependency);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return PMINFO_R_OK;
+ }
+
++static int _pkginfo_get_res_allowed_packages(sqlite3 *db, const char *pkgid,
++ GList **allowed_packages)
++{
++ static const char query_raw[] =
++ "SELECT DISTINCT allowed_package, required_privilege "
++ "FROM package_res_allowed_package WHERE package=%Q";
++ int ret;
++ char *query;
++ char *package;
++ char *privilege;
++ sqlite3_stmt *stmt;
++ res_allowed_package_x *allowed_package_x;
++ GList *l;
++
++ query = sqlite3_mprintf(query_raw, pkgid);
++ if (query == NULL) {
++ LOGE("out of memory");
++ return PMINFO_R_ERROR;
++ }
++
++ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
++ sqlite3_free(query);
++ if (ret != SQLITE_OK) {
++ LOGE("prepare failed: %s", sqlite3_errmsg(db));
++ return PMINFO_R_ERROR;
++ }
++
++ while (sqlite3_step(stmt) == SQLITE_ROW) {
++ allowed_package_x = NULL;
++ package = NULL;
++ privilege = NULL;
++
++ _save_column_str(stmt, 0, &package);
++ if (!package)
++ continue;
++
++ for (l = *allowed_packages; l; l = l->next) {
++ allowed_package_x = (res_allowed_package_x *)l->data;
++ if (!strcmp(package, (char *)l->data))
++ break;
++ allowed_package_x = NULL;
++ }
++
++ if (allowed_package_x) {
++ free(package);
++ } else {
++ allowed_package_x = calloc(1,
++ sizeof(res_allowed_package_x));
++ if (allowed_package_x == NULL) {
++ LOGE("failed to alloc memory");
++ sqlite3_finalize(stmt);
++ free(package);
++ return PMINFO_R_ERROR;
++ }
++ allowed_package_x->allowed_package = package;
++ *allowed_packages = g_list_prepend(*allowed_packages,
++ (gpointer)allowed_package_x);
++ }
++
++ _save_column_str(stmt, 1, &privilege);
++ if (!privilege)
++ continue;
++
++ allowed_package_x->required_privileges = g_list_prepend(
++ allowed_package_x->required_privileges,
++ privilege);
++ }
++
++ sqlite3_finalize(stmt);
++
++ return PMINFO_R_OK;
++}
++
++static int _pkginfo_get_res_info(sqlite3 *db, const char *pkgid,
++ char **res_type, char **res_version,
++ GList **res_allowed_packages)
++{
++ static const char query_raw[] =
++ "SELECT DISTINCT res_type, res_version "
++ "FROM package_res_info WHERE package=%Q";
++ int ret;
++ char *query;
++ sqlite3_stmt *stmt;
++
++ query = sqlite3_mprintf(query_raw, pkgid);
++ if (query == NULL) {
++ LOGE("out of memory");
++ return PMINFO_R_ERROR;
++ }
++
++ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
++ sqlite3_free(query);
++ if (ret != SQLITE_OK) {
++ LOGE("prepare failed: %s", sqlite3_errmsg(db));
++ return PMINFO_R_ERROR;
++ }
++
++ if (sqlite3_step(stmt) != SQLITE_ROW) {
++ sqlite3_finalize(stmt);
++ return PMINFO_R_OK;
++ }
++
++ _save_column_str(stmt, 0, res_type);
++ _save_column_str(stmt, 1, res_version);
++
++ if (_pkginfo_get_res_allowed_packages(db, pkgid,
++ res_allowed_packages) != PMINFO_R_OK) {
++ sqlite3_finalize(stmt);
++ return PMINFO_R_ERROR;
++ }
++
++ sqlite3_finalize(stmt);
++
++ return PMINFO_R_OK;
++}
++
+ static int _pkginfo_get_packages(sqlite3 *db, uid_t uid, const char *locale,
+ pkgmgrinfo_filter_x *filter, int flag, GHashTable *packages)
+ {
+ static const char query_raw[] =
+ "SELECT DISTINCT pi.package, pi.installed_storage, pi.external_path";
+ static const char query_basic[] =
+ ", pi.package_version, pi.install_location, "
+ "pi.package_removable, pi.package_preload, pi.package_readonly, "
+ "pi.package_update, pi.package_appsetting, pi.package_system, "
+ "pi.package_type, pi.package_size, pi.installed_time, "
+ "pi.storeclient_id, pi.mainapp_id, pi.package_url, pi.root_path, "
+ "pi.csc_path, pi.package_nodisplay, pi.package_api_version, "
+ "pi.package_support_disable, pi.package_tep_name, "
+ "pi.package_zip_mount_file, pi.package_support_mode";
+ static const char query_author[] =
+ ", pi.author_name, pi.author_email, pi.author_href";
+ static const char query_label[] =
+ ", COALESCE("
+ "(SELECT package_label FROM package_localized_info WHERE pi.package=package AND package_locale=?), "
+ "(SELECT package_label FROM package_localized_info WHERE pi.package=package AND package_locale='No Locale'))";
+ static const char query_icon[] =
+ ", COALESCE("
+ "(SELECT package_icon FROM package_localized_info WHERE pi.package=package AND package_locale=?), "
+ "(SELECT package_icon FROM package_localized_info WHERE pi.package=package AND package_locale='No Locale'))";
+ static const char query_description[] =
+ ", COALESCE("
+ "(SELECT package_description FROM package_localized_info WHERE pi.package=package AND package_locale=?), "
+ "(SELECT package_description FROM package_localized_info WHERE pi.package=package AND package_locale='No Locale'))";
++ static const char query_res_type[] =
++ ", (SELECT res_type FROM package_res_info WHERE pi.package=package)";
++ static const char query_res_version[] =
++ ", (SELECT res_version FROM package_res_info WHERE pi.package=package)";
+ static const char query_from_clause[] = " FROM package_info as pi";
+ int ret = PMINFO_R_ERROR;
+ int idx = 0;
+ char *tmp_record = NULL;
+ char *constraints = NULL;
+ char query[MAX_QUERY_LEN] = { '\0' };
+ package_x *info = NULL;
+ author_x *author = NULL;
+ GList *bind_params = NULL;
+ sqlite3_stmt *stmt = NULL;
+ bool is_check_storage = true;
+ const uid_t global_user_uid = GLOBAL_USER;
+
+ if (db == NULL || locale == NULL || filter == NULL) {
+ LOGE("Invalid parameter");
+ return PMINFO_R_EINVAL;
+ }
+
+ is_check_storage = __check_package_storage_status(filter);
+
+ snprintf(query, MAX_QUERY_LEN - 1, "%s", query_raw);
+ if (flag & PMINFO_APPINFO_GET_BASICINFO)
+ strncat(query, query_basic, sizeof(query) - strlen(query) - 1);
+ if (flag & PMINFO_PKGINFO_GET_AUTHOR)
+ strncat(query, query_author, sizeof(query) - strlen(query) - 1);
+ if (flag & PMINFO_PKGINFO_GET_LABEL) {
+ strncat(query, query_label, sizeof(query) - strlen(query) - 1);
+ bind_params = g_list_append(bind_params, strdup(locale));
+ }
+ if (flag & PMINFO_PKGINFO_GET_ICON) {
+ strncat(query, query_icon, sizeof(query) - strlen(query) - 1);
+ bind_params = g_list_append(bind_params, strdup(locale));
+ }
+ if (flag & PMINFO_PKGINFO_GET_DESCRIPTION) {
+ strncat(query, query_description,
+ sizeof(query) - strlen(query) - 1);
+ bind_params = g_list_append(bind_params, strdup(locale));
+ }
++ if (flag & PMINFO_PKGINFO_GET_RES_INFO) {
++ strncat(query, query_res_type,
++ sizeof(query) - strlen(query) - 1);
++ strncat(query, query_res_version,
++ sizeof(query) - strlen(query) - 1);
++ }
+
+ strncat(query, query_from_clause, sizeof(query) - strlen(query) - 1);
+
+ ret = _get_filtered_query(filter, locale, uid,
+ &constraints, &bind_params);
+ if (ret != PMINFO_R_OK) {
+ LOGE("Failed to get WHERE clause");
+ goto catch;
+ }
+
+ if (constraints)
+ strncat(query, constraints, sizeof(query) - strlen(query) - 1);
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+
+ ret = __bind_params(stmt, bind_params);
+ if (ret != SQLITE_OK) {
+ LOGE("Failed to bind parameters");
+ goto catch;
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ info = calloc(1, sizeof(package_x));
+ if (info == NULL) {
+ LOGE("out of memory");
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+ info->locale = strdup(locale);
+ if (info->locale == NULL) {
+ LOGE("Out of memory");
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+
+ idx = 0;
+ _save_column_str(stmt, idx++, &info->package);
+ _save_column_str(stmt, idx++, &info->installed_storage);
+ _save_column_str(stmt, idx++, &info->external_path);
+
+ if (flag & PMINFO_APPINFO_GET_BASICINFO) {
+ _save_column_str(stmt, idx++, &info->version);
+ _save_column_str(stmt, idx++, &info->installlocation);
+ _save_column_str(stmt, idx++, &info->removable);
+ _save_column_str(stmt, idx++, &info->preload);
+ _save_column_str(stmt, idx++, &info->readonly);
+ _save_column_str(stmt, idx++, &info->update);
+ _save_column_str(stmt, idx++, &info->appsetting);
+ _save_column_str(stmt, idx++, &info->system);
+ _save_column_str(stmt, idx++, &info->type);
+ _save_column_str(stmt, idx++, &info->package_size);
+ _save_column_str(stmt, idx++, &info->installed_time);
+ _save_column_str(stmt, idx++, &info->storeclient_id);
+ _save_column_str(stmt, idx++, &info->mainapp_id);
+ _save_column_str(stmt, idx++, &info->package_url);
+ _save_column_str(stmt, idx++, &info->root_path);
+ _save_column_str(stmt, idx++, &info->csc_path);
+ _save_column_str(stmt, idx++, &info->nodisplay_setting);
+ _save_column_str(stmt, idx++, &info->api_version);
+ _save_column_str(stmt, idx++, &info->support_disable);
+ _save_column_str(stmt, idx++, &info->tep_name);
+ _save_column_str(stmt, idx++, &info->zip_mount_file);
+ _save_column_str(stmt, idx++, &info->support_mode);
+ }
+
+ info->for_all_users =
+ strdup((uid != global_user_uid) ? "false" : "true");
+
+ if (_pkginfo_get_plugin_execution_info(db,
+ info->package, &info->plugin)) {
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+
+ if (flag & PMINFO_PKGINFO_GET_AUTHOR) {
+ /* TODO : author should be retrieved at package_localized_info */
+ author = calloc(1, sizeof(author_x));
+ if (author == NULL) {
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+ _save_column_str(stmt, idx++, &author->text);
+ _save_column_str(stmt, idx++, &author->email);
+ _save_column_str(stmt, idx++, &author->href);
+ info->author = g_list_prepend(info->author, author);
+ }
+
+ if (flag & PMINFO_PKGINFO_GET_LABEL) {
+ tmp_record = NULL;
+ _save_column_str(stmt, idx++, &tmp_record);
+
+ if (_add_label_info_into_list(locale,
+ tmp_record, &info->label)) {
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+ }
+
+ if (flag & PMINFO_PKGINFO_GET_ICON) {
+ tmp_record = NULL;
+ _save_column_str(stmt, idx++, &tmp_record);
+ if (_add_icon_info_into_list(locale,
+ tmp_record, &info->icon)) {
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+ }
+
+ if (flag & PMINFO_PKGINFO_GET_DESCRIPTION) {
+ tmp_record = NULL;
+ _save_column_str(stmt, idx++, &tmp_record);
+ if (_pkginfo_add_description_info_into_list(locale,
+ tmp_record, &info->description)) {
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+ }
+
+ if (flag & PMINFO_PKGINFO_GET_PRIVILEGE) {
+ if (_pkginfo_get_privilege(db, info->package,
+ &info->privileges)) {
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+ }
+
+ if (flag & PMINFO_PKGINFO_GET_APPDEFINED_PRIVILEGE) {
+ if (_pkginfo_get_appdefined_privilege(db, info->package,
+ &info->appdefined_privileges)) {
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+ }
+
+ if (flag & PMINFO_PKGINFO_GET_DEPENDENCY) {
+ if (_pkginfo_get_dependency(db, info->package,
+ &info->dependencies)) {
+ ret = PMINFO_R_ERROR;
+ goto catch;
+ }
+ }
+
++ if (flag & PMINFO_PKGINFO_GET_RES_INFO) {
++ if (_pkginfo_get_res_info(db, info->package,
++ &info->res_type,
++ &info->res_version,
++ &info->res_allowed_packages) < 0) {
++ ret = PMINFO_R_ERROR;
++ goto catch;
++ }
++ }
++
+ if (is_check_storage &&
+ __pkginfo_check_installed_storage(info) !=
+ PMINFO_R_OK) {
+ ret = PMINFO_R_ERROR;
+ pkgmgrinfo_basic_free_package(info);
+ info = NULL;
+ continue;
+ }
+
+ g_hash_table_insert(packages, (gpointer)info->package,
+ (gpointer)info);
+ }
+
+ ret = PMINFO_R_OK;
+
+ catch:
+ sqlite3_finalize(stmt);
+
+ if (constraints)
+ free(constraints);
+
+ if (ret != PMINFO_R_OK && info != NULL)
+ pkgmgrinfo_basic_free_package(info);
+
+ g_list_free_full(bind_params, free);
+
+ return ret;
+ }
+
+ API int pkginfo_internal_filter_get_list(
+ sqlite3 *db, pkgmgrinfo_pkginfo_filter_h filter,
+ uid_t uid, const char *locale, GHashTable *pkginfo_list)
+ {
+ int ret;
+
+ if (filter == NULL || pkginfo_list == NULL) {
+ LOGE("Invalid argument");
+ return PMINFO_R_EINVAL;
+ }
+
+ ret = _pkginfo_get_packages(db, uid, locale, filter,
+ PMINFO_PKGINFO_GET_ALL, pkginfo_list);
+ return ret;
+ }
+
+ API int get_query_result(sqlite3 *db, const char *query, GList *param,
+ GList **list, int *row, int *col)
+ {
+ int ret = 0;
+ int col_cnt = 0;
+ int row_cnt = 0;
+ int idx = 0;
+ sqlite3_stmt *stmt = NULL;
+ char *result = NULL;
+
+ if (db == NULL || query == NULL) {
+ LOGE("Invalid parameter");
+ return PMINFO_R_EINVAL;
+ }
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return PMINFO_R_ERROR;
+ }
+
+ if (g_list_length(param) != 0) {
+ ret = __bind_params(stmt, param);
+ if (ret != PMINFO_R_OK) {
+ LOGE("failed to bind parameters: %s", sqlite3_errmsg(db));
+ return ret;
+ }
+ }
+
+ col_cnt = sqlite3_column_count(stmt);
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ row_cnt++;
+ for (idx = 0; idx < col_cnt; ++idx) {
+ _save_column_str(stmt, idx, &result);
+ *list = g_list_append(*list, result);
+ result = NULL;
+ }
+ }
+
+ *row = row_cnt;
+ *col = col_cnt;
+
+ sqlite3_finalize(stmt);
+
+ return PMINFO_R_OK;
+ }
+
+ static int _get_depends_on(sqlite3 *db, const char *pkgid, GQueue **queue,
+ GHashTable **table, GList **pkg_list)
+ {
+ static const char query[] =
+ "SELECT package, depends_on, type, required_version "
+ "FROM package_dependency_info WHERE depends_on=?";
+ int ret;
+ sqlite3_stmt *stmt;
+ dependency_x *req;
+
+ /* already checked */
+ if (!g_hash_table_insert(*table, strdup(pkgid), GINT_TO_POINTER(1)))
+ return PMINFO_R_OK;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return PMINFO_R_ERROR;
+ }
+
+ ret = sqlite3_bind_text(stmt, 1, pkgid, -1, SQLITE_STATIC);
+ if (ret != SQLITE_OK) {
+ LOGE("bind failed: %s", sqlite3_errmsg(db));
+ sqlite3_finalize(stmt);
+ return PMINFO_R_ERROR;
+ }
+
+ while (sqlite3_step(stmt) == SQLITE_ROW) {
+ req = calloc(1, sizeof(dependency_x));
+ if (req == NULL) {
+ LOGE("out of memory");
+ sqlite3_finalize(stmt);
+ return PMINFO_R_ERROR;
+ }
+ _save_column_str(stmt, 0, &req->pkgid);
+ _save_column_str(stmt, 1, &req->depends_on);
+ _save_column_str(stmt, 2, &req->type);
+ _save_column_str(stmt, 3, &req->required_version);
+
+ *pkg_list = g_list_prepend(*pkg_list, req);
+ g_queue_push_tail(*queue, strdup(req->pkgid));
+ }
+
+ sqlite3_finalize(stmt);
+
+ return PMINFO_R_OK;
+ }
+
+ static void __free_depends_on(gpointer data)
+ {
+ struct dependency_x *dep = (struct dependency_x *)data;
+
+ free(dep->pkgid);
+ free(dep->depends_on);
+ free(dep->type);
+ free(dep->required_version);
+ free(dep);
+ }
+
+ API int pkginfo_internal_filter_get_depends_on(sqlite3 *db, const char *pkgid,
+ GList **list)
+ {
+ GQueue *queue;
+ GHashTable *table;
+ char *item;
+ int ret;
+
+ if (db == NULL || pkgid == NULL) {
+ LOGE("Invalid parameter");
+ return PMINFO_R_EINVAL;
+ }
+
+ queue = g_queue_new();
+ if (queue == NULL) {
+ LOGE("out of memory");
+ return PMINFO_R_ERROR;
+ }
+ table = g_hash_table_new_full(g_str_hash, g_str_equal, free, NULL);
+
+ g_queue_push_tail(queue, strdup(pkgid));
+ while (!g_queue_is_empty(queue)) {
+ item = g_queue_pop_head(queue);
+ ret = _get_depends_on(db, item, &queue, &table, list);
+ free(item);
+ if (ret != PMINFO_R_OK) {
+ LOGE("failed to get pkgs depends on %s", pkgid);
+ g_hash_table_destroy(table);
+ g_list_free_full(*list, __free_depends_on);
+ g_queue_free_full(queue, free);
+ return PMINFO_R_ERROR;
+ }
+ }
+
+ g_hash_table_destroy(table);
+ g_queue_free_full(queue, free);
+ return PMINFO_R_OK;
+ }
+
+ static int __execute_query(sqlite3 *db, const char *query, GList *param)
+ {
+ int ret = 0;
+ sqlite3_stmt *stmt = NULL;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+
+ if (g_list_length(param) != 0) {
+ ret = __bind_params(stmt, param);
+ if (ret != PMINFO_R_OK) {
+ LOGE("failed to bind parameters: %s", sqlite3_errmsg(db));
+ return ret;
+ }
+ }
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE && ret != SQLITE_OK) {
+ LOGE("step failed:%d %s", ret, sqlite3_errmsg(db));
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+
+ sqlite3_finalize(stmt);
+
+ return PMINFO_R_OK;
+ }
+
+ API int execute_write_queries(sqlite3 *db, GList *queries, GList *params_list)
+ {
+ int i;
+ query_args *tmp_ptr = NULL;
+
+ if (db == NULL || queries == NULL) {
+ _LOGE("Invalid parameter");
+ return PMINFO_R_EINVAL;
+ }
+
+ __BEGIN_TRANSACTION(db);
+ for (i = 0; i < g_list_length(queries); ++i) {
+ tmp_ptr = (query_args *)g_list_nth_data(params_list, i);
+ if (tmp_ptr == NULL) {
+ _LOGE("Failed to get parameter list");
+ sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL);
+ return PMINFO_R_ERROR;
+ }
+
+ __DO_TRANSACTION(db,
+ __execute_query(db, g_list_nth_data(queries, i),
+ tmp_ptr->argument));
+ }
+ __END_TRANSACTION(db);
+
+ return PMINFO_R_OK;
+ }
+
+ static int __check_dpi(const char *dpi_char, int dpi_int)
+ {
+ if (dpi_char == NULL)
+ return -1;
+
+ if (strcasecmp(dpi_char, LDPI) == 0) {
+ if (dpi_int >= LDPI_MIN && dpi_int <= LDPI_MAX)
+ return 0;
+ else
+ return -1;
+ } else if (strcasecmp(dpi_char, MDPI) == 0) {
+ if (dpi_int >= MDPI_MIN && dpi_int <= MDPI_MAX)
+ return 0;
+ else
+ return -1;
+ } else if (strcasecmp(dpi_char, HDPI) == 0) {
+ if (dpi_int >= HDPI_MIN && dpi_int <= HDPI_MAX)
+ return 0;
+ else
+ return -1;
+ } else if (strcasecmp(dpi_char, XHDPI) == 0) {
+ if (dpi_int >= XHDPI_MIN && dpi_int <= XHDPI_MAX)
+ return 0;
+ else
+ return -1;
+ } else if (strcasecmp(dpi_char, XXHDPI) == 0) {
+ if (dpi_int >= XXHDPI_MIN && dpi_int <= XXHDPI_MAX)
+ return 0;
+ else
+ return -1;
+ } else
+ return -1;
+ }
+
+ static void __find_appcontrol_splashscreen_with_dpi(gpointer data,
+ gpointer user_data)
+ {
+ splashscreen_x *ss = (splashscreen_x *)data;
+ GList **list = (GList **)user_data;
+ int dpi = -1;
+ int ret;
+
+ if (ss->operation == NULL || ss->dpi == NULL)
+ return;
+
+ ret = system_info_get_platform_int(
+ "http://tizen.org/feature/screen.dpi", &dpi);
+ if (ret != SYSTEM_INFO_ERROR_NONE)
+ return;
+
+ if (__check_dpi(ss->dpi, dpi) != 0)
+ return;
+
+ *list = g_list_prepend(*list, ss);
+ }
+
+ static void __find_appcontrol_splashscreen(gpointer data, gpointer user_data)
+ {
+ splashscreen_x *ss = (splashscreen_x *)data;
+ GList **list = (GList **)user_data;
+ splashscreen_x *ss_tmp;
+ GList *tmp;
+
+ if (ss->operation == NULL || ss->dpi)
+ return;
+
+ for (tmp = *list; tmp; tmp = tmp->next) {
+ ss_tmp = (splashscreen_x *)tmp->data;
+ if (ss_tmp->operation
+ && strcmp(ss_tmp->operation, ss->operation) == 0
+ && strcmp(ss_tmp->orientation, ss->orientation) == 0)
+ return;
+ }
+
+ *list = g_list_prepend(*list, ss);
+ }
+
+ static gint __compare_splashscreen_with_orientation_dpi(gconstpointer a,
+ gconstpointer b)
+ {
+ splashscreen_x *ss = (splashscreen_x *)a;
+ const char *orientation = (const char *)b;
+ int dpi = -1;
+ int ret;
+
+ if (ss->operation || ss->dpi == NULL)
+ return -1;
+
+ ret = system_info_get_platform_int(
+ "http://tizen.org/feature/screen.dpi", &dpi);
+ if (ret != SYSTEM_INFO_ERROR_NONE)
+ return -1;
+
+ if (strcasecmp(ss->orientation, orientation) == 0 &&
+ __check_dpi(ss->dpi, dpi) == 0)
+ return 0;
+
+ return -1;
+ }
+
+ static gint __compare_splashscreen_with_orientation(gconstpointer a,
+ gconstpointer b)
+ {
+ splashscreen_x *ss = (splashscreen_x *)a;
+ const char *orientation = (const char *)b;
+
+ if (ss->operation || ss->dpi)
+ return -1;
+
+ if (strcasecmp(ss->orientation, orientation) == 0)
+ return 0;
+
+ return -1;
+ }
+
+ static splashscreen_x *__find_default_splashscreen(GList *splashscreens,
+ const char *orientation)
+ {
+ GList *tmp;
+
+ tmp = g_list_find_custom(splashscreens, orientation,
+ (GCompareFunc)
+ __compare_splashscreen_with_orientation_dpi);
+ if (tmp)
+ return (splashscreen_x *)tmp->data;
+
+ tmp = g_list_find_custom(splashscreens, orientation,
+ (GCompareFunc)__compare_splashscreen_with_orientation);
+ if (tmp)
+ return (splashscreen_x *)tmp->data;
+
+ return NULL;
+ }
+
+ static GList *__find_splashscreens(GList *splashscreens)
+ {
+ GList *list = NULL;
+ splashscreen_x *ss;
+
+ if (splashscreens == NULL)
+ return NULL;
+
+ g_list_foreach(splashscreens,
+ __find_appcontrol_splashscreen_with_dpi, &list);
+ g_list_foreach(splashscreens,
+ __find_appcontrol_splashscreen, &list);
+
+ ss = __find_default_splashscreen(splashscreens, "portrait");
+ if (ss)
+ list = g_list_prepend(list, ss);
+ ss = __find_default_splashscreen(splashscreens, "landscape");
+ if (ss)
+ list = g_list_prepend(list, ss);
+
+ return list;
+ }
+
+ static int __insert_splashscreen_info(sqlite3 *db, application_x *app,
+ GList *ss_list)
+ {
+ static const char query[] =
+ "INSERT INTO package_app_splash_screen (app_id, src, type,"
+ " orientation, indicatordisplay, operation, color_depth) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?)";
+ int ret;
+ sqlite3_stmt *stmt;
+ int idx;
+ GList *tmp;
+ splashscreen_x *ss;
+
+ if (app->splashscreens == NULL)
+ return 0;
+
+ if (ss_list == NULL)
+ return 0;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+
+ for (tmp = ss_list; tmp; tmp = tmp->next) {
+ ss = (splashscreen_x *)tmp->data;
+ if (ss == NULL)
+ continue;
+ idx = 1;
+ __BIND_TEXT(db, stmt, idx++, app->appid);
+ __BIND_TEXT(db, stmt, idx++, ss->src);
+ __BIND_TEXT(db, stmt, idx++, ss->type);
+ __BIND_TEXT(db, stmt, idx++, ss->orientation);
+ __BIND_TEXT(db, stmt, idx++, ss->indicatordisplay);
+ __BIND_TEXT(db, stmt, idx++, ss->operation);
+ __BIND_TEXT(db, stmt, idx++, ss->color_depth);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ _LOGE("step failed: %s", sqlite3_errmsg(db));
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+
+ sqlite3_reset(stmt);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return 0;
+ }
+
+ static void __trimfunc(GList *trim_list)
+ {
+ char *trim_data;
+ char *prev = NULL;
+ GList *list = g_list_first(trim_list);
+
+ while (list) {
+ trim_data = (char *)list->data;
+ if (trim_data) {
+ if (prev) {
+ if (strcmp(trim_data, prev) == 0) {
+ trim_list = g_list_remove(trim_list,
+ trim_data);
+ list = g_list_first(trim_list);
+ prev = NULL;
+ continue;
+ } else
+ prev = trim_data;
+ } else {
+ prev = trim_data;
+ }
+ }
+ list = g_list_next(list);
+ }
+ }
+
+ static int __insert_package_appdefined_privilege_info(sqlite3 *db,
+ manifest_x *mfx)
+ {
+ static const char query[] =
+ "INSERT INTO package_appdefined_privilege_info "
+ "(package, privilege, license, type) "
+ "VALUES (?, ?, ?, ?)";
+ int ret;
+ sqlite3_stmt *stmt;
+ int idx;
+ GList *tmp;
+ appdefined_privilege_x *priv;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+
+ for (tmp = mfx->appdefined_privileges; tmp; tmp = tmp->next) {
+ priv = (appdefined_privilege_x *)tmp->data;
+ if (priv == NULL)
+ continue;
+
+ idx = 1;
+ __BIND_TEXT(db, stmt, idx++, mfx->package);
+ __BIND_TEXT(db, stmt, idx++, priv->value);
+ __BIND_TEXT(db, stmt, idx++, priv->license);
+ __BIND_TEXT(db, stmt, idx++, priv->type);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ _LOGE("step failed: %s", sqlite3_errmsg(db));
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+ sqlite3_reset(stmt);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return 0;
+ }
+
+ static int __insert_package_dependency_info(sqlite3 *db, manifest_x *mfx)
+ {
+ static const char query[] =
+ "INSERT INTO package_dependency_info"
+ " (package, depends_on, type, required_version) "
+ "VALUES (?, ?, ?, ?)";
+ int ret;
+ sqlite3_stmt *stmt;
+ int idx;
+ GList *tmp;
+ dependency_x *dep;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+
+ for (tmp = mfx->dependencies; tmp; tmp = tmp->next) {
+ dep = (dependency_x *)tmp->data;
+ if (dep == NULL)
+ continue;
+
+ idx = 1;
+ __BIND_TEXT(db, stmt, idx++, mfx->package);
+ __BIND_TEXT(db, stmt, idx++, dep->depends_on);
+ __BIND_TEXT(db, stmt, idx++, dep->type);
+ __BIND_TEXT(db, stmt, idx++, dep->required_version);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ _LOGE("step failed: %s", sqlite3_errmsg(db));
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+ sqlite3_reset(stmt);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return 0;
+ }
+
+ static int __insert_mainapp_localized_info(sqlite3 *db, application_x *app,
+ const char *locale, const char *label, const char *icon)
+ {
+ static const char query[] =
+ "INSERT OR REPLACE INTO package_localized_info ("
+ " package, package_locale, package_label, package_icon,"
+ " package_description, package_license, package_author) "
+ "VALUES (?, ?,"
+ " COALESCE((SELECT package_label FROM package_localized_info"
+ " WHERE package=? AND package_locale=?), ?),"
+ " COALESCE((SELECT package_icon FROM package_localized_info"
+ " WHERE package=? AND package_icon=?), ?),"
+ " (SELECT package_description FROM package_localized_info"
+ " WHERE package=? AND package_locale=?),"
+ " (SELECT package_description FROM package_localized_info"
+ " WHERE package=? AND package_locale=?),"
+ " (SELECT package_description FROM package_localized_info"
+ " WHERE package=? AND package_locale=?))";
+ int ret;
+ sqlite3_stmt *stmt;
+ int idx = 1;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+
+ __BIND_TEXT(db, stmt, idx++, app->package);
+ __BIND_TEXT(db, stmt, idx++, locale);
+ __BIND_TEXT(db, stmt, idx++, app->package);
+ __BIND_TEXT(db, stmt, idx++, locale);
+ __BIND_TEXT(db, stmt, idx++, label);
+ __BIND_TEXT(db, stmt, idx++, app->package);
+ __BIND_TEXT(db, stmt, idx++, locale);
+ __BIND_TEXT(db, stmt, idx++, icon);
+ __BIND_TEXT(db, stmt, idx++, app->package);
+ __BIND_TEXT(db, stmt, idx++, locale);
+ __BIND_TEXT(db, stmt, idx++, app->package);
+ __BIND_TEXT(db, stmt, idx++, locale);
+ __BIND_TEXT(db, stmt, idx++, app->package);
+ __BIND_TEXT(db, stmt, idx++, locale);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ _LOGE("step failed: %s", sqlite3_errmsg(db));
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+
+ sqlite3_finalize(stmt);
+
+ return 0;
+ }
+
+ static gint __comparefunc(gconstpointer a, gconstpointer b, gpointer userdata)
+ {
+ if (a == NULL || b == NULL)
+ return 0;
+ if (strcmp((char *)a, (char *)b) == 0)
+ return 0;
+ if (strcmp((char *)a, (char *)b) < 0)
+ return -1;
+ if (strcmp((char *)a, (char *)b) > 0)
+ return 1;
+ return 0;
+ }
+
+ static GList *__create_locale_list(GList *lbls, GList *lcns, GList *icns,
+ GList *dcns, GList *aths)
+ {
+ GList *locale = NULL;
+ GList *tmp;
+ label_x *lbl;
+ license_x *lcn;
+ icon_x *icn;
+ description_x *dcn;
+ author_x *ath;
+
+ for (tmp = lbls; tmp; tmp = tmp->next) {
+ lbl = (label_x *)tmp->data;
+ if (lbl == NULL)
+ continue;
+ if (lbl->lang)
+ locale = g_list_insert_sorted_with_data(
+ locale, (gpointer)lbl->lang,
+ __comparefunc, NULL);
+ }
+ for (tmp = lcns; tmp; tmp = tmp->next) {
+ lcn = (license_x *)tmp->data;
+ if (lcn == NULL)
+ continue;
+ if (lcn->lang)
+ locale = g_list_insert_sorted_with_data(
+ locale, (gpointer)lcn->lang,
+ __comparefunc, NULL);
+ }
+ for (tmp = icns; tmp; tmp = tmp->next) {
+ icn = (icon_x *)tmp->data;
+ if (icn == NULL)
+ continue;
+ if (icn->lang)
+ locale = g_list_insert_sorted_with_data(
+ locale, (gpointer)icn->lang,
+ __comparefunc, NULL);
+ }
+ for (tmp = dcns; tmp; tmp = tmp->next) {
+ dcn = (description_x *)tmp->data;
+ if (dcn == NULL)
+ continue;
+ if (dcn->lang)
+ locale = g_list_insert_sorted_with_data(
+ locale, (gpointer)dcn->lang,
+ __comparefunc, NULL);
+ }
+ for (tmp = aths; tmp; tmp = tmp->next) {
+ ath = (author_x *)tmp->data;
+ if (ath == NULL)
+ continue;
+ if (ath->lang)
+ locale = g_list_insert_sorted_with_data(
+ locale, (gpointer)ath->lang,
+ __comparefunc, NULL);
+ }
+ __trimfunc(locale);
+ return locale;
+ }
+
+ static gint __check_icon_resolution(const char *orig_icon_path,
+ char **new_icon_path)
+ {
+ int ret;
+ char *dpi_path[2];
+ char *icon_filename;
+ char modified_iconpath[BUFSIZE];
+ char icon_path[BUFSIZE];
+ int i;
+ int dpi = -1;
+
+ if (orig_icon_path == NULL)
+ return -1;
+
+ ret = system_info_get_platform_int(
+ "http://tizen.org/feature/screen.dpi", &dpi);
+ if (ret != SYSTEM_INFO_ERROR_NONE)
+ return -1;
+
+ if (dpi >= LDPI_MIN && dpi <= LDPI_MAX) {
+ dpi_path[0] = "LDPI";
+ dpi_path[1] = "ldpi";
+ } else if (dpi >= MDPI_MIN && dpi <= MDPI_MAX) {
+ dpi_path[0] = "MDPI";
+ dpi_path[1] = "mdpi";
+ } else if (dpi >= HDPI_MIN && dpi <= HDPI_MAX) {
+ dpi_path[0] = "HDPI";
+ dpi_path[1] = "hdpi";
+ } else if (dpi >= XHDPI_MIN && dpi <= XHDPI_MAX) {
+ dpi_path[0] = "XHDPI";
+ dpi_path[1] = "xhdpi";
+ } else if (dpi >= XXHDPI_MIN && dpi <= XXHDPI_MAX) {
+ dpi_path[0] = "XXHDPI";
+ dpi_path[1] = "xxhdpi";
+ } else {
+ _LOGE("Unidentified dpi[%d]", dpi);
+ return -1;
+ }
+
+ icon_filename = strrchr(orig_icon_path, '/');
+ if (icon_filename == NULL)
+ return -1;
+
+ snprintf(icon_path,
+ strlen(orig_icon_path) - (strlen(icon_filename) - 1),
+ "%s", orig_icon_path);
+ for (i = 0; i < 2; i++) {
+ ret = snprintf(modified_iconpath, BUFSIZE - 1, "%s/%s%s",
+ icon_path, dpi_path[i], icon_filename);
+ if (ret < 0 || ret > BUFSIZE - 1) {
+ _LOGE("snprintf fail");
+ return -1;
+ }
+ if (access(modified_iconpath, F_OK) != -1) {
+ /* if exists, return modified icon path */
+ *new_icon_path = strdup(modified_iconpath);
+ return 0;
+ }
+ }
+
+ return -1;
+ }
+
+ static gint __compare_icon(gconstpointer a, gconstpointer b)
+ {
+ icon_x *icon = (icon_x *)a;
+ char *icon_path;
+
+ if (icon->lang != NULL && strcasecmp(icon->lang, DEFAULT_LOCALE) != 0)
+ return -1;
+
+ if (icon->dpi != NULL)
+ return -1;
+
+ if (__check_icon_resolution(icon->text, &icon_path) == 0) {
+ free(icon->text);
+ icon->text = icon_path;
+ }
+
+ return 0;
+ }
+
+ static gint __compare_icon_with_lang(gconstpointer a, gconstpointer b)
+ {
+ icon_x *icon = (icon_x *)a;
+ char *lang = (char *)b;
+ char *icon_path;
+
+ if (icon->dpi != NULL)
+ return -1;
+
+ if (strcasecmp(icon->lang, lang) == 0) {
+ if (strcasecmp(icon->lang, DEFAULT_LOCALE) == 0) {
+ /* icon for no locale. check existance of
+ * folder-hierachied default icons
+ */
+ if (__check_icon_resolution(icon->text,
+ &icon_path) == 0) {
+ free(icon->text);
+ icon->text = icon_path;
+ }
+ }
+ return 0;
+ }
+
+ return -1;
+ }
+
+ static gint __compare_icon_with_dpi(gconstpointer a, gconstpointer b)
+ {
+ icon_x *icon = (icon_x *)a;
+ int dpi = GPOINTER_TO_INT(b);
+
+ if (icon->lang != NULL && strcasecmp(icon->lang, DEFAULT_LOCALE) != 0)
+ return -1;
+
+ if (icon->dpi == NULL)
+ return -1;
+
+ if (__check_dpi(icon->dpi, dpi) == 0)
+ return 0;
+
+ return -1;
+ }
+
+ static gint __compare_icon_with_lang_dpi(gconstpointer a, gconstpointer b)
+ {
+ int ret;
+ icon_x *icon = (icon_x *)a;
+ char *lang = (char *)b;
+ int dpi = -1;
+
+ ret = system_info_get_platform_int(
+ "http://tizen.org/feature/screen.dpi", &dpi);
+ if (ret != SYSTEM_INFO_ERROR_NONE)
+ return -1;
+
+ if (strcasecmp(icon->lang, lang) == 0 &&
+ __check_dpi(icon->dpi, dpi) == 0)
+ return 0;
+
+ return -1;
+ }
+
+ static char *__find_icon(GList *icons, const char *lang)
+ {
+ GList *tmp;
+ icon_x *icon;
+ int dpi = 0;
+ int ret;
+
+ /* first, find icon whose locale and dpi with given lang and
+ * system's dpi has matched
+ */
+ tmp = g_list_find_custom(icons, lang,
+ (GCompareFunc)__compare_icon_with_lang_dpi);
+ if (tmp != NULL) {
+ icon = (icon_x *)tmp->data;
+ return (char *)icon->text;
+ }
+
+ /* if first has failed, find icon whose locale has matched */
+ tmp = g_list_find_custom(icons, lang,
+ (GCompareFunc)__compare_icon_with_lang);
+ if (tmp != NULL) {
+ icon = (icon_x *)tmp->data;
+ return (char *)icon->text;
+ }
+
+ /* if second has failed, find icon whose dpi has matched with
+ * system's dpi
+ */
+ ret = system_info_get_platform_int(
+ "http://tizen.org/feature/screen.dpi", &dpi);
+ if (ret == SYSTEM_INFO_ERROR_NONE) {
+ tmp = g_list_find_custom(icons, GINT_TO_POINTER(dpi),
+ (GCompareFunc)__compare_icon_with_dpi);
+ if (tmp != NULL) {
+ icon = (icon_x *)tmp->data;
+ return (char *)icon->text;
+ }
+ }
+
+ /* last, find default icon marked as "No Locale" */
+ tmp = g_list_find_custom(icons, NULL, (GCompareFunc)__compare_icon);
+ if (tmp != NULL) {
+ icon = (icon_x *)tmp->data;
+ return (char *)icon->text;
+ }
+
+ return NULL;
+ }
+
+ static void __extract_data(const char *locale, GList *lbls, GList *lcns,
+ GList *icns, GList *dcns, GList *aths, char **label,
+ char **license, char **icon, char **description, char **author)
+ {
+ GList *tmp;
+ label_x *lbl;
+ license_x *lcn;
+ description_x *dcn;
+ author_x *ath;
+
+ for (tmp = lbls; tmp; tmp = tmp->next) {
+ lbl = (label_x *)tmp->data;
+ if (lbl == NULL)
+ continue;
+ if (lbl->lang) {
+ if (strcmp(lbl->lang, locale) == 0) {
+ *label = (char *)lbl->text;
+ break;
+ }
+ }
+ }
+ for (tmp = lcns; tmp; tmp = tmp->next) {
+ lcn = (license_x *)tmp->data;
+ if (lcn == NULL)
+ continue;
+ if (lcn->lang) {
+ if (strcmp(lcn->lang, locale) == 0) {
+ *license = (char *)lcn->text;
+ break;
+ }
+ }
+ }
+
+ *icon = __find_icon(icns, locale);
+
+ for (tmp = dcns; tmp; tmp = tmp->next) {
+ dcn = (description_x *)tmp->data;
+ if (dcn == NULL)
+ continue;
+ if (dcn->lang) {
+ if (strcmp(dcn->lang, locale) == 0) {
+ *description = (char *)dcn->text;
+ break;
+ }
+ }
+ }
+ for (tmp = aths; tmp; tmp = tmp->next) {
+ ath = (author_x *)tmp->data;
+ if (ath == NULL)
+ continue;
+ if (ath->lang) {
+ if (strcmp(ath->lang, locale) == 0) {
+ *author = (char *)ath->text;
+ break;
+ }
+ }
+ }
+ }
+
+ static int __insert_app_localized_info(sqlite3 *db, application_x *app)
+ {
+ static const char query[] =
+ "INSERT INTO package_app_localized_info (app_id, app_locale,"
+ " app_label, app_icon) "
+ "VALUES (?, ?, ?, ?)";
+ int ret;
+ sqlite3_stmt *stmt;
+ int idx;
+ GList *tmp;
+ GList *locales;
+ const char *locale;
+ char *label;
+ char *icon;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+
+ locales = __create_locale_list(app->label, NULL, app->icon, NULL, NULL);
+ for (tmp = locales; tmp; tmp = tmp->next) {
+ locale = (const char *)tmp->data;
+ label = NULL;
+ icon = NULL;
+ __extract_data(locale, app->label, NULL, app->icon, NULL, NULL,
+ &label, NULL, &icon, NULL, NULL);
+ if (!label && !icon)
+ continue;
+
+ idx = 1;
+ __BIND_TEXT(db, stmt, idx++, app->appid);
+ __BIND_TEXT(db, stmt, idx++, locale);
+ __BIND_TEXT(db, stmt, idx++, label);
+ __BIND_TEXT(db, stmt, idx++, icon);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ _LOGE("step failed: %s", sqlite3_errmsg(db));
+ g_list_free(locales);
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+
+ sqlite3_reset(stmt);
+
+ if (strcasecmp(app->mainapp, "true") == 0) {
+ if (__insert_mainapp_localized_info(db, app, locale,
+ label, icon))
+ _LOGE("insert mainapp localized info failed");
+ }
+ }
+
+ g_list_free(locales);
+ sqlite3_finalize(stmt);
+
+ return 0;
+ }
+
++static int __insert_app_res_control(sqlite3 *db, application_x *app)
++{
++ static const char query[] =
++ "INSERT INTO package_app_res_control (app_id, res_type,"
++ " min_res_version, max_res_version, auto_close) "
++ "VALUES (?, ?, ?, ?, ?)";
++ int ret;
++ sqlite3_stmt *stmt;
++ int idx;
++ GList *tmp;
++ res_control_x *rc;
++
++ if (app->res_control == NULL)
++ return 0;
++
++ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
++ if (ret != SQLITE_OK) {
++ _LOGE("prepare failed: %s", sqlite3_errmsg(db));
++ return -1;
++ }
++
++ for (tmp = app->res_control; tmp; tmp = tmp->next) {
++ rc = (res_control_x *)tmp->data;
++ if (rc == NULL)
++ continue;
++ idx = 1;
++ __BIND_TEXT(db, stmt, idx++, app->appid);
++ __BIND_TEXT(db, stmt, idx++, rc->res_type);
++ __BIND_TEXT(db, stmt, idx++, rc->min_res_version);
++ __BIND_TEXT(db, stmt, idx++, rc->max_res_version);
++ __BIND_TEXT(db, stmt, idx++, rc->auto_close);
++
++ ret = sqlite3_step(stmt);
++ if (ret != SQLITE_DONE) {
++ _LOGE("step failed: %s", sqlite3_errmsg(db));
++ sqlite3_finalize(stmt);
++ return -1;
++ }
++
++ sqlite3_reset(stmt);
++ }
++
++ sqlite3_finalize(stmt);
++
++ return 0;
++}
++
+ static int __insert_package_privilege_info(sqlite3 *db, manifest_x *mfx)
+ {
+ static const char query[] =
+ "INSERT INTO package_privilege_info (package, privilege, type) "
+ "VALUES (?, ?, ?)";
+ int ret;
+ sqlite3_stmt *stmt;
+ int idx;
+ GList *tmp;
+ privilege_x *priv;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+
+ for (tmp = mfx->privileges; tmp; tmp = tmp->next) {
+ priv = (privilege_x *)tmp->data;
+ if (priv == NULL)
+ continue;
+
+ idx = 1;
+ __BIND_TEXT(db, stmt, idx++, mfx->package);
+ __BIND_TEXT(db, stmt, idx++, priv->value);
+ __BIND_TEXT(db, stmt, idx++, priv->type);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ _LOGE("step failed: %s", sqlite3_errmsg(db));
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+ sqlite3_reset(stmt);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return 0;
+ }
+
+ static int __insert_app_data_control_privilege_info(sqlite3 *db,
+ datacontrol_x *datacontrol)
+ {
+ static const char query[] =
+ "INSERT INTO package_app_data_control_privilege (providerid,"
+ " privilege, type) VALUES (?, ?, ?)";
+
+ int ret;
+ sqlite3_stmt *stmt;
+ int idx;
+ GList *privileges;
+ char *priv;
+
+ if (datacontrol == NULL)
+ return 0;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+
+ for (privileges = datacontrol->privileges; privileges;
+ privileges = privileges->next) {
+ priv = (char *)privileges->data;
+ if (priv == NULL)
+ continue;
+
+ idx = 1;
+ __BIND_TEXT(db, stmt, idx++, datacontrol->providerid);
+ __BIND_TEXT(db, stmt, idx++, priv);
+ __BIND_TEXT(db, stmt, idx++, datacontrol->type);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ _LOGE("step failed: %s", sqlite3_errmsg(db));
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+
+ sqlite3_reset(stmt);
+ }
+
+ sqlite3_finalize(stmt);
+ return 0;
+ }
+
+ static int __insert_datacontrol_info(sqlite3 *db, application_x *app)
+ {
+ static const char query[] =
+ "INSERT INTO package_app_data_control (app_id, providerid,"
+ " access, type, trusted) VALUES (?, ?, ?, ?, ?)";
+ int ret;
+ sqlite3_stmt *stmt;
+ int idx;
+ GList *tmp;
+ datacontrol_x *dc;
+
+ if (app->datacontrol == NULL)
+ return 0;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+
+ for (tmp = app->datacontrol; tmp; tmp = tmp->next) {
+ dc = (datacontrol_x *)tmp->data;
+ if (dc == NULL)
+ continue;
+ idx = 1;
+ __BIND_TEXT(db, stmt, idx++, app->appid);
+ __BIND_TEXT(db, stmt, idx++, dc->providerid);
+ __BIND_TEXT(db, stmt, idx++, dc->access);
+ __BIND_TEXT(db, stmt, idx++, dc->type);
+ __BIND_TEXT(db, stmt, idx++, dc->trusted);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ _LOGE("step failed: %s", sqlite3_errmsg(db));
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+
+ if (dc->privileges &&
+ __insert_app_data_control_privilege_info(
+ db, dc)) {
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+
+ sqlite3_reset(stmt);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return 0;
+ }
+
+ static int __insert_category_info(sqlite3 *db, application_x *app)
+ {
+ static const char query[] =
+ "INSERT INTO package_app_app_category (app_id, category) "
+ "VALUES (?, ?)";
+ int ret;
+ sqlite3_stmt *stmt;
+ int idx;
+ GList *tmp;
+ const char *category;
+
+ if (app->category == NULL)
+ return 0;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+
+ for (tmp = app->category; tmp; tmp = tmp->next) {
+ category = (const char *)tmp->data;
+ if (category == NULL)
+ continue;
+ idx = 1;
+ __BIND_TEXT(db, stmt, idx++, app->appid);
+ __BIND_TEXT(db, stmt, idx++, category);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ _LOGE("step failed: %s", sqlite3_errmsg(db));
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+
+ sqlite3_reset(stmt);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return 0;
+ }
+
+ static int __insert_metadata_info(sqlite3 *db, application_x *app)
+ {
+ static const char query[] =
+ "INSERT INTO package_app_app_metadata (app_id,"
+ " md_key, md_value) VALUES (?, ?, ?)";
+ int ret;
+ sqlite3_stmt *stmt;
+ int idx;
+ GList *tmp;
+ metadata_x *md;
+
+ if (app->metadata == NULL)
+ return 0;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+
+ for (tmp = app->metadata; tmp; tmp = tmp->next) {
+ md = (metadata_x *)tmp->data;
+ if (md == NULL)
+ continue;
+ idx = 1;
+ __BIND_TEXT(db, stmt, idx++, app->appid);
+ __BIND_TEXT(db, stmt, idx++, md->key);
+ __BIND_TEXT(db, stmt, idx++, md->value);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ _LOGE("step failed: %s", sqlite3_errmsg(db));
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+
+ sqlite3_reset(stmt);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return 0;
+ }
+
+ static int __insert_appcontrol_privilege_info(sqlite3 *db, const char *appid,
+ appcontrol_x *ac)
+ {
+ static const char query[] =
+ "INSERT INTO package_app_app_control_privilege (app_id,"
+ " app_control, privilege) VALUES (?, ?, ?)";
+ int ret;
+ sqlite3_stmt *stmt;
+ int idx;
+ char app_control[BUFSIZE];
+ GList *tmp;
+ char *privilege;
+
+ if (ac == NULL)
+ return 0;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+
+ for (tmp = ac->privileges; tmp; tmp = tmp->next) {
+ privilege = (char *)tmp->data;
+ if (privilege == NULL || !strlen(privilege))
+ continue;
+
+ idx = 1;
+ snprintf(app_control, sizeof(app_control), "%s|%s|%s",
+ ac->operation ? (strlen(ac->operation) > 0 ?
+ ac->operation : "NULL") : "NULL",
+ ac->uri ? (strlen(ac->uri) > 0 ?
+ ac->uri : "NULL") : "NULL",
+ ac->mime ? (strlen(ac->mime) > 0 ?
+ ac->mime : "NULL") : "NULL");
+ __BIND_TEXT(db, stmt, idx++, appid);
+ __BIND_TEXT(db, stmt, idx++, app_control);
+ __BIND_TEXT(db, stmt, idx++, privilege);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ _LOGE("step failed: %s", sqlite3_errmsg(db));
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+
+ sqlite3_reset(stmt);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return 0;
+ }
+
+ static int __insert_appcontrol_info(sqlite3 *db, application_x *app)
+ {
+ static const char query[] =
+ "INSERT INTO package_app_app_control (app_id, app_control,"
+ " visibility, app_control_id) "
+ "VALUES (?, ?, ?, ?)";
+ int ret;
+ sqlite3_stmt *stmt;
+ int idx;
+ char app_control[BUFSIZE];
+ GList *tmp;
+ appcontrol_x *ac;
+
+ if (app->appcontrol == NULL)
+ return 0;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+
+ for (tmp = app->appcontrol; tmp; tmp = tmp->next) {
+ ac = (appcontrol_x *)tmp->data;
+ if (ac == NULL)
+ continue;
+ idx = 1;
+ snprintf(app_control, sizeof(app_control), "%s|%s|%s",
+ ac->operation ? (strlen(ac->operation) > 0 ?
+ ac->operation : "NULL") : "NULL",
+ ac->uri ? (strlen(ac->uri) > 0 ?
+ ac->uri : "NULL") : "NULL",
+ ac->mime ? (strlen(ac->mime) > 0 ?
+ ac->mime : "NULL") : "NULL");
+ __BIND_TEXT(db, stmt, idx++, app->appid);
+ __BIND_TEXT(db, stmt, idx++, app_control);
+ __BIND_TEXT(db, stmt, idx++, ac->visibility);
+ __BIND_TEXT(db, stmt, idx++, ac->id);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ _LOGE("step failed: %s", sqlite3_errmsg(db));
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+
+ if (__insert_appcontrol_privilege_info(db, app->appid, ac)) {
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+
+ sqlite3_reset(stmt);
+ }
+
+ sqlite3_finalize(stmt);
+
+ return 0;
+ }
+
+ static const char *__get_bool(char *value, bool is_true)
+ {
+ if (value != NULL) {
+ if (!strcmp(value, ""))
+ return (is_true) ? "true" : "false";
+ return value;
+ }
+
+ return (is_true) ? "true" : "false";
+ }
+
+ #define EFFECTIVE_APPID_KEY "http://tizen.org/metadata/effective-appid"
+ static const char *__find_effective_appid(GList *metadata_list)
+ {
+ GList *tmp;
+ metadata_x *md;
+
+ for (tmp = metadata_list; tmp; tmp = tmp->next) {
+ md = (metadata_x *)tmp->data;
+ if (md == NULL || md->key == NULL)
+ continue;
+
+ if (strcmp(md->key, EFFECTIVE_APPID_KEY) == 0) {
+ if (md->value)
+ return md->value;
+ }
+ }
+
+ return NULL;
+ }
+
+ static int __convert_background_category(GList *category_list)
+ {
+ int ret = 0;
+ GList *tmp;
+ char *category_data;
+
+ if (category_list == NULL)
+ return 0;
+
+ for (tmp = category_list; tmp; tmp = tmp->next) {
+ category_data = (char *)tmp->data;
+ if (category_data == NULL)
+ continue;
+ if (!strcmp(category_data, APP_BG_CATEGORY_MEDIA_STR))
+ ret |= APP_BG_CATEGORY_MEDIA_VAL;
+ else if (!strcmp(category_data, APP_BG_CATEGORY_DOWNLOAD_STR))
+ ret |= APP_BG_CATEGORY_DOWNLOAD_VAL;
+ else if (!strcmp(category_data, APP_BG_CATEGORY_BGNETWORK_STR))
+ ret |= APP_BG_CATEGORY_BGNETWORK_VAL;
+ else if (!strcmp(category_data, APP_BG_CATEGORY_LOCATION_STR))
+ ret |= APP_BG_CATEGORY_LOCATION_VAL;
+ else if (!strcmp(category_data, APP_BG_CATEGORY_SENSOR_STR))
+ ret |= APP_BG_CATEGORY_SENSOR_VAL;
+ else if (!strcmp(category_data, APP_BG_CATEGORY_IOTCOMM_STR))
+ ret |= APP_BG_CATEGORY_IOTCOMM_VAL;
+ else if (!strcmp(category_data, APP_BG_CATEGORY_SYSTEM))
+ ret |= APP_BG_CATEGORY_SYSTEM_VAL;
+ else
+ _LOGE("Unidentified category [%s]", category_data);
+ }
+
+ return ret;
+ }
+
++static int __insert_package_res_info_allowed_package(sqlite3 *db,
++ const char *pkgid, GList *rap_list)
++{
++ static const char query[] =
++ "INSERT INTO package_res_allowed_package (package,"
++ " allowed_package, required_privilege) VALUES (?, ?, ?)";
++ int ret;
++ int idx;
++ sqlite3_stmt *stmt;
++ GList *tmp;
++ GList *priv_list;
++ res_allowed_package_x *rap;
++
++ if (rap_list == NULL)
++ return 0;
++
++ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
++ if (ret != SQLITE_OK) {
++ _LOGE("prepare failed: %s", sqlite3_errmsg(db));
++ return -1;
++ }
++
++ for (tmp = rap_list; tmp; tmp = tmp->next) {
++ rap = (res_allowed_package_x *)tmp->data;
++ if (rap == NULL)
++ continue;
++
++ if (!rap->required_privileges) {
++ idx = 1;
++ __BIND_TEXT(db, stmt, idx++, pkgid);
++ __BIND_TEXT(db, stmt, idx++, rap->allowed_package);
++ __BIND_TEXT(db, stmt, idx++, NULL);
++
++ ret = sqlite3_step(stmt);
++ if (ret != SQLITE_DONE) {
++ _LOGE("step failed: %s", sqlite3_errmsg(db));
++ sqlite3_finalize(stmt);
++ return -1;
++ }
++
++ sqlite3_reset(stmt);
++ continue;
++ }
++
++ for (priv_list = rap->required_privileges; priv_list;
++ priv_list = priv_list->next) {
++ idx = 1;
++ __BIND_TEXT(db, stmt, idx++, pkgid);
++ __BIND_TEXT(db, stmt, idx++, rap->allowed_package);
++ __BIND_TEXT(db, stmt, idx++, (char *)priv_list->data);
++
++ ret = sqlite3_step(stmt);
++ if (ret != SQLITE_DONE) {
++ _LOGE("step failed: %s", sqlite3_errmsg(db));
++ sqlite3_finalize(stmt);
++ return -1;
++ }
++
++ sqlite3_reset(stmt);
++ }
++ }
++
++ sqlite3_finalize(stmt);
++
++ return 0;
++}
++
++static int __insert_package_res_info(sqlite3 *db, manifest_x *mfx)
++{
++ static const char query[] =
++ "INSERT INTO package_res_info (package, res_type,"
++ " res_version) VALUES (?, ?, ?)";
++ int ret;
++ sqlite3_stmt *stmt;
++ int idx;
++
++ if (mfx->res_type == NULL || mfx->res_version == NULL)
++ return 0;
++
++ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
++ if (ret != SQLITE_OK) {
++ _LOGE("prepare failed: %s", sqlite3_errmsg(db));
++ return -1;
++ }
++
++ idx = 1;
++ __BIND_TEXT(db, stmt, idx++, mfx->package);
++ __BIND_TEXT(db, stmt, idx++, mfx->res_type);
++ __BIND_TEXT(db, stmt, idx++, mfx->res_version);
++
++ ret = sqlite3_step(stmt);
++ if (ret != SQLITE_DONE) {
++ _LOGE("step failed: %s", sqlite3_errmsg(db));
++ sqlite3_finalize(stmt);
++ return -1;
++ }
++
++ if (__insert_package_res_info_allowed_package(db, mfx->package,
++ mfx->res_allowed_packages) < 0) {
++ sqlite3_finalize(stmt);
++ return -1;
++ }
++
++ sqlite3_finalize(stmt);
++
++ return 0;
++}
++
+ static int __insert_application_info(sqlite3 *db, manifest_x *mfx)
+ {
+ static const char query[] =
+ "INSERT INTO package_app_info (app_id, app_component,"
+ " app_exec, app_nodisplay, app_type, app_onboot, app_multiple,"
+ " app_autorestart, app_taskmanage, app_hwacceleration,"
+ " app_screenreader, app_mainapp, app_recentimage,"
+ " app_launchcondition, app_indicatordisplay, app_portraitimg,"
+ " app_landscapeimg, app_guestmodevisibility,"
+ " app_permissiontype, app_preload, app_submode,"
+ " app_submode_mainid, app_installed_storage, app_process_pool,"
+ " app_launch_mode, app_ui_gadget, app_support_mode,"
+ " app_support_disable, component_type, package, app_tep_name,"
+ " app_zip_mount_file, app_background_category,"
+ " app_package_type, app_root_path, app_api_version,"
+ " app_effective_appid, app_splash_screen_display,"
+ " app_package_system, app_removable,"
+ " app_package_installed_time, app_support_ambient,"
+ " app_external_path, app_setup_appid) "
+ "VALUES (?, ?, "
+ " ?, LOWER(?), ?, LOWER(?), LOWER(?),"
+ " LOWER(?), LOWER(?), ?,"
+ " ?, LOWER(?), ?,"
+ " ?, LOWER(?), ?,"
+ " ?, LOWER(?),"
+ " ?, LOWER(?), LOWER(?),"
+ " ?, ?, LOWER(?),"
+ " COALESCE(?, 'single'), LOWER(?), ?,"
+ " LOWER(?), ?, ?, ?,"
+ " ?, ?,"
+ " ?, ?, ?,"
+ " ?, LOWER(?),"
+ " LOWER(?), LOWER(?),"
+ " ?, LOWER(?),"
+ " ?, ?)";
+ int ret;
+ sqlite3_stmt *stmt;
+ int idx;
+ GList *tmp;
+ application_x *app;
+ int bg_category;
+ const char *effective_appid;
+ GList *ss_list;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+
+ for (tmp = mfx->application; tmp; tmp = tmp->next) {
+ app = (application_x *)tmp->data;
+ if (app == NULL)
+ continue;
+
+ bg_category = __convert_background_category(
+ app->background_category);
+ effective_appid = __find_effective_appid(app->metadata);
+
+ idx = 1;
+ __BIND_TEXT(db, stmt, idx++, app->appid);
++ __BIND_TEXT(db, stmt, idx++, app->component_type);
+ __BIND_TEXT(db, stmt, idx++, app->exec);
+ __BIND_TEXT(db, stmt, idx++, __get_bool(app->nodisplay, false));
+ __BIND_TEXT(db, stmt, idx++, app->type);
+ __BIND_TEXT(db, stmt, idx++, __get_bool(app->onboot, false));
+ __BIND_TEXT(db, stmt, idx++, __get_bool(app->multiple, false));
+ __BIND_TEXT(db, stmt, idx++,
+ __get_bool(app->autorestart, false));
+ __BIND_TEXT(db, stmt, idx++,
+ __get_bool(app->taskmanage, false));
+ __BIND_TEXT(db, stmt, idx++, app->hwacceleration);
+ __BIND_TEXT(db, stmt, idx++, app->screenreader);
+ __BIND_TEXT(db, stmt, idx++, __get_bool(app->mainapp, false));
+ __BIND_TEXT(db, stmt, idx++, app->recentimage);
+ __BIND_TEXT(db, stmt, idx++, app->launchcondition);
+ __BIND_TEXT(db, stmt, idx++,
+ __get_bool(app->indicatordisplay, true));
+ __BIND_TEXT(db, stmt, idx++, app->portraitimg);
+ __BIND_TEXT(db, stmt, idx++, app->landscapeimg);
+ __BIND_TEXT(db, stmt, idx++,
+ __get_bool(app->guestmode_visibility, true));
+ __BIND_TEXT(db, stmt, idx++, app->permission_type);
+ __BIND_TEXT(db, stmt, idx++, __get_bool(mfx->preload, false));
+ __BIND_TEXT(db, stmt, idx++, __get_bool(app->submode, false));
+ __BIND_TEXT(db, stmt, idx++, app->submode_mainid);
+ __BIND_TEXT(db, stmt, idx++, mfx->installed_storage);
+ __BIND_TEXT(db, stmt, idx++,
+ __get_bool(app->process_pool, false));
+ __BIND_TEXT(db, stmt, idx++, app->launch_mode);
+ __BIND_TEXT(db, stmt, idx++, __get_bool(app->ui_gadget, false));
+ __BIND_TEXT(db, stmt, idx++,
+ app->support_mode ? app->support_mode : "0");
+ __BIND_TEXT(db, stmt, idx++,
+ __get_bool(mfx->support_disable, false));
+ __BIND_TEXT(db, stmt, idx++, app->component_type);
+ __BIND_TEXT(db, stmt, idx++, mfx->package);
+ __BIND_TEXT(db, stmt, idx++, mfx->tep_name);
+ __BIND_TEXT(db, stmt, idx++, mfx->zip_mount_file);
+ __BIND_INT(db, stmt, idx++, bg_category);
+ __BIND_TEXT(db, stmt, idx++, mfx->type ? mfx->type : "tpk");
+ __BIND_TEXT(db, stmt, idx++, mfx->root_path);
+ __BIND_TEXT(db, stmt, idx++, app->api_version);
+ __BIND_TEXT(db, stmt, idx++, effective_appid);
+ __BIND_TEXT(db, stmt, idx++,
+ __get_bool(app->splash_screen_display, true));
+ __BIND_TEXT(db, stmt, idx++, __get_bool(mfx->system, false));
+ __BIND_TEXT(db, stmt, idx++, __get_bool(mfx->removable, false));
+ __BIND_TEXT(db, stmt, idx++, mfx->installed_time);
+ __BIND_TEXT(db, stmt, idx++,
+ __get_bool(app->support_ambient, false));
+ __BIND_TEXT(db, stmt, idx++, mfx->external_path);
+ __BIND_TEXT(db, stmt, idx++, app->setup_appid);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ _LOGE("step failed: %s", sqlite3_errmsg(db));
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+
+ sqlite3_reset(stmt);
+
+ if (__insert_appcontrol_info(db, app)) {
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+ if (__insert_category_info(db, app)) {
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+ if (__insert_metadata_info(db, app)) {
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+ if (__insert_datacontrol_info(db, app)) {
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+ ss_list = __find_splashscreens(app->splashscreens);
+ if (__insert_splashscreen_info(db, app, ss_list)) {
+ g_list_free(ss_list);
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+ g_list_free(ss_list);
+ if (__insert_app_localized_info(db, app)) {
+ sqlite3_finalize(stmt);
+ return -1;
+ }
++ if (__insert_app_res_control(db, app)) {
++ sqlite3_finalize(stmt);
++ return -1;
++ }
+ }
+
+ sqlite3_finalize(stmt);
+
+ return 0;
+ }
+
+ static int __insert_package_update_info(sqlite3 *db, manifest_x *mfx)
+ {
+ static const char query[] =
+ "INSERT INTO package_update_info (package, update_version) "
+ "VALUES (?, ?)";
+ int ret;
+ int idx;
+ sqlite3_stmt *stmt;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+
+ idx = 1;
+ __BIND_TEXT(db, stmt, idx++, mfx->package);
+ __BIND_TEXT(db, stmt, idx, mfx->version);
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ _LOGE("step failed: %s", sqlite3_errmsg(db));
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+ sqlite3_finalize(stmt);
+
+ return 0;
+ }
+
+ static int __insert_package_localized_info(sqlite3 *db, manifest_x *mfx)
+ {
+ static const char query[] =
+ "INSERT INTO package_localized_info (package, package_locale,"
+ " package_label, package_icon, package_description,"
+ " package_license, package_author) "
+ "VALUES (?, ?, ?, ?, ?, ?, ?)";
+ int ret;
+ sqlite3_stmt *stmt;
+ int idx;
+ GList *tmp;
+ GList *locales;
+ const char *locale;
+ char *label;
+ char *icon;
+ char *description;
+ char *license;
+ char *author;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+
+ locales = __create_locale_list(mfx->label, mfx->license, mfx->icon,
+ mfx->description, mfx->author);
+ for (tmp = locales; tmp; tmp = tmp->next) {
+ locale = (const char *)tmp->data;
+ label = NULL;
+ icon = NULL;
+ description = NULL;
+ license = NULL;
+ author = NULL;
+ __extract_data(locale, mfx->label, mfx->license, mfx->icon,
+ mfx->description, mfx->author,
+ &label, &license, &icon, &description, &author);
+ if (!label && !license && !icon && !description && !author)
+ continue;
+
+ idx = 1;
+ __BIND_TEXT(db, stmt, idx++, mfx->package);
+ __BIND_TEXT(db, stmt, idx++, locale);
+ __BIND_TEXT(db, stmt, idx++, label);
+ __BIND_TEXT(db, stmt, idx++, icon);
+ __BIND_TEXT(db, stmt, idx++, description);
+ __BIND_TEXT(db, stmt, idx++, license);
+ __BIND_TEXT(db, stmt, idx++, author);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ _LOGE("step failed: %s", sqlite3_errmsg(db));
+ g_list_free(locales);
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+
+ sqlite3_reset(stmt);
+ }
+
+ g_list_free(locales);
+ sqlite3_finalize(stmt);
+
+ return 0;
+ }
+
+ static int __insert_package_info(sqlite3 *db, manifest_x *mfx)
+ {
+ static const char query[] =
+ "INSERT INTO package_info (package, package_type,"
+ " package_version, package_api_version, package_tep_name,"
+ " package_zip_mount_file, install_location, package_size,"
+ " package_removable, package_preload, package_readonly,"
+ " package_update, package_appsetting, package_nodisplay,"
+ " package_system, author_name, author_email, author_href,"
+ " installed_time, installed_storage, storeclient_id,"
+ " mainapp_id, package_url, root_path, external_path,"
+ " csc_path, package_support_mode, package_support_disable) "
+ "VALUES (?, ?,"
+ " ?, ?, ?,"
+ " ?, ?, ?,"
+ " LOWER(?), LOWER(?), LOWER(?),"
+ " LOWER(?), LOWER(?), LOWER(?),"
+ " LOWER(?), ?, ?, ?,"
+ " ?, ?, ?,"
+ " ?, ?, ?, ?,"
+ " ?, ?, LOWER(?))";
+ int ret;
+ sqlite3_stmt *stmt;
+ int idx = 1;
+ const char *author_name = NULL;
+ const char *author_email = NULL;
+ const char *author_href = NULL;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+
+ if (mfx->author && mfx->author->data) {
+ author_name = ((author_x *)mfx->author->data)->text;
+ author_email = ((author_x *)mfx->author->data)->email;
+ author_href = ((author_x *)mfx->author->data)->href;
+ }
+
+ __BIND_TEXT(db, stmt, idx++, mfx->package);
+ __BIND_TEXT(db, stmt, idx++, mfx->type);
+ __BIND_TEXT(db, stmt, idx++, mfx->version);
+ __BIND_TEXT(db, stmt, idx++, mfx->api_version);
+ __BIND_TEXT(db, stmt, idx++, mfx->tep_name);
+ __BIND_TEXT(db, stmt, idx++, mfx->zip_mount_file);
+ __BIND_TEXT(db, stmt, idx++, mfx->installlocation);
+ __BIND_TEXT(db, stmt, idx++, mfx->package_size);
+ __BIND_TEXT(db, stmt, idx++, __get_bool(mfx->removable, true));
+ __BIND_TEXT(db, stmt, idx++, __get_bool(mfx->preload, false));
+ __BIND_TEXT(db, stmt, idx++, __get_bool(mfx->readonly, false));
+ __BIND_TEXT(db, stmt, idx++, __get_bool(mfx->update, false));
+ __BIND_TEXT(db, stmt, idx++, __get_bool(mfx->appsetting, false));
+ __BIND_TEXT(db, stmt, idx++, __get_bool(mfx->nodisplay_setting, false));
+ __BIND_TEXT(db, stmt, idx++, __get_bool(mfx->system, false));
+ __BIND_TEXT(db, stmt, idx++, author_name);
+ __BIND_TEXT(db, stmt, idx++, author_email);
+ __BIND_TEXT(db, stmt, idx++, author_href);
+ __BIND_TEXT(db, stmt, idx++, mfx->installed_time);
+ __BIND_TEXT(db, stmt, idx++, mfx->installed_storage);
+ __BIND_TEXT(db, stmt, idx++, mfx->storeclient_id);
+ __BIND_TEXT(db, stmt, idx++, mfx->mainapp_id);
+ __BIND_TEXT(db, stmt, idx++, mfx->package_url);
+ __BIND_TEXT(db, stmt, idx++, mfx->root_path);
+ __BIND_TEXT(db, stmt, idx++, mfx->external_path);
+ __BIND_TEXT(db, stmt, idx++, mfx->csc_path);
+ __BIND_TEXT(db, stmt, idx++,
+ mfx->support_mode ? mfx->support_mode : "0");
+ __BIND_TEXT(db, stmt, idx++, __get_bool(mfx->support_disable, false));
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ _LOGE("step failed: %s", sqlite3_errmsg(db));
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+
+ sqlite3_finalize(stmt);
+
+ if (__insert_package_update_info(db, mfx))
+ return -1;
+ if (__insert_package_localized_info(db, mfx))
+ return -1;
+ if (__insert_application_info(db, mfx))
+ return -1;
+ if (__insert_package_privilege_info(db, mfx))
+ return -1;
+ if (__insert_package_appdefined_privilege_info(db, mfx))
+ return -1;
+ if (__insert_package_dependency_info(db, mfx))
+ return -1;
++ if (__insert_package_res_info(db, mfx))
++ return -1;
+
+ return 0;
+ }
+
+ static int __delete_package_info(sqlite3 *db, const char *pkgid)
+ {
+ static const char query[] =
+ "DELETE FROM package_info WHERE package=?";
+ int ret;
+ sqlite3_stmt *stmt;
+
+ ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
+ if (ret != SQLITE_OK) {
+ _LOGE("prepare failed: %s", sqlite3_errmsg(db));
+ return -1;
+ }
+
+ __BIND_TEXT(db, stmt, 1, pkgid);
+
+ ret = sqlite3_step(stmt);
+ if (ret != SQLITE_DONE) {
+ _LOGE("step failed: %s", sqlite3_errmsg(db));
+ sqlite3_finalize(stmt);
+ return -1;
+ }
+
+ sqlite3_finalize(stmt);
+
+ return 0;
+ }
+
+ API int pkgmgr_parser_delete_pkg_info(sqlite3 *db,
+ const char *package, uid_t uid)
+ {
+ if (db == NULL || package == NULL) {
+ _LOGE("invalid parameter");
+ return PM_PARSER_R_EINVAL;
+ }
+
+ __BEGIN_TRANSACTION(db);
+ __DO_TRANSACTION(db, __delete_package_info(db, package));
+ __END_TRANSACTION(db);
+
+ return PM_PARSER_R_OK;
+ }
+
+ API int pkgmgr_parser_update_pkg_info(sqlite3 *db, manifest_x *mfx, uid_t uid)
+ {
+ if (db == NULL || mfx == NULL) {
+ _LOGE("invalid parameter");
+ return PM_PARSER_R_EINVAL;
+ }
+
+ __BEGIN_TRANSACTION(db);
+ __DO_TRANSACTION(db, __delete_package_info(db, mfx->package));
+ __DO_TRANSACTION(db, __insert_package_info(db, mfx));
+ __END_TRANSACTION(db);
+
+ return PM_PARSER_R_OK;
+ }
+
+ API int pkgmgr_parser_insert_pkg_info(sqlite3 *db, manifest_x *mfx, uid_t uid)
+ {
+ if (db == NULL || mfx == NULL) {
+ _LOGE("invalid parameter");
+ return PM_PARSER_R_EINVAL;
+ }
+
+ __BEGIN_TRANSACTION(db);
+ __DO_TRANSACTION(db, __insert_package_info(db, mfx));
+ __END_TRANSACTION(db);
+
+ return PM_PARSER_R_OK;
+ }
--- /dev/null
- std::vector<std::pair<int, std::vector<std::string>>>{
+ /*
+ * Copyright (c) 2021 Samsung Electronics Co., Ltd.
+ *
+ * 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 <gmock/gmock.h>
+
+ #include <gtest/gtest.h>
+
+ #include <cstdio>
+
+ #include "appinfo_db_handler.hh"
+ #include "create_db_handler.hh"
+ #include "depinfo_db_handler.hh"
+ #include "db_type.hh"
+ #include "parcel_utils.hh"
+ #include "pkg_get_db_handler.hh"
+ #include "pkg_set_db_handler.hh"
+ #include "query_handler.hh"
+
+ #include "mock/file_mock.h"
+ #include "mock/test_fixture.h"
+ #include "mock/system_info_mock.h"
+
+ #include "pkgmgr-info.h"
+ #include "pkgmgr_query_index.h"
+ #include "pkgmgrinfo_basic.h"
+
+ #define TEST_PARSER_DB "test.pkgmgr_parser.db"
+
+ namespace psd = pkgmgr_server::database;
+ namespace pc = pkgmgr_common;
+
+ class CreateParserDBHandlerMock : public psd::CreateDBHandler {
+ public:
+ CreateParserDBHandlerMock(uid_t uid, int pid)
+ : psd::CreateDBHandler(uid, pid) {}
+
+ MOCK_METHOD0(Connect, bool());
+ MOCK_METHOD0(GetConnection, std::vector<std::pair<sqlite3*, uid_t>>());
+ };
+
+ class PkgSetDBHandlerMock : public psd::PkgSetDBHandler {
+ public:
+ PkgSetDBHandlerMock(uid_t uid, int pid) : psd::PkgSetDBHandler(uid, pid) {}
+
+ MOCK_METHOD0(Connect, bool());
+ MOCK_METHOD0(GetConnection, std::vector<std::pair<sqlite3*, uid_t>>());
+ };
+
+ class PkgGetDBHandlerMock : public psd::PkgGetDBHandler {
+ public:
+ PkgGetDBHandlerMock(uid_t uid, int pid) : psd::PkgGetDBHandler(uid, pid) {}
+
+ MOCK_METHOD0(Connect, bool());
+ MOCK_METHOD0(GetConnection, std::vector<std::pair<sqlite3*, uid_t>>());
+ };
+
+ class AppInfoDBHandlerMock : public psd::AppInfoDBHandler {
+ public:
+ AppInfoDBHandlerMock(uid_t uid, int pid) : psd::AppInfoDBHandler(uid, pid) {}
+
+ MOCK_METHOD0(Connect, bool());
+ MOCK_METHOD0(GetConnection, std::vector<std::pair<sqlite3*, uid_t>>());
+ };
+
+ class DepInfoGetDBHandlerMock : public psd::DepInfoGetDBHandler {
+ public:
+ DepInfoGetDBHandlerMock(uid_t uid, int pid) :
+ psd::DepInfoGetDBHandler(uid, pid) {}
+
+ MOCK_METHOD0(Connect, bool());
+ MOCK_METHOD0(GetConnection, std::vector<std::pair<sqlite3*, uid_t>>());
+ };
+
+ class QueryHandlerMock : public psd::QueryHandler {
+ public:
+ QueryHandlerMock(uid_t uid, int pid) :
+ psd::QueryHandler(uid, pid) {}
+
+ MOCK_METHOD0(Connect, bool());
+ MOCK_METHOD0(GetConnection, std::vector<std::pair<sqlite3*, uid_t>>());
+ };
+
+ class Mocks : public ::testing::NiceMock<SystemInfoMock> {};
+
+ class ParserDBHandlerTest : public TestFixture {
+ public:
+ ParserDBHandlerTest() : TestFixture(std::make_unique<Mocks>()) {}
+ virtual ~ParserDBHandlerTest() {}
+
+ virtual void SetUp() {
+ sqlite3 *db;
+ ASSERT_EQ(sqlite3_open_v2(TEST_PARSER_DB, &db,
+ SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL), SQLITE_OK);
+
+ SetDBHandles(
+ std::vector<std::pair<sqlite3*, uid_t>> { std::make_pair(db, 0) });
+ CreateParserDBHandlerMock create_db_handler(0, 0);
+
+ EXPECT_CALL(create_db_handler, Connect())
+ .Times(2).WillRepeatedly(testing::Return(true));
+ EXPECT_CALL(create_db_handler, GetConnection())
+ .Times(2).WillRepeatedly(testing::Return(GetDBHandles()));
+ EXPECT_CALL(GetMock<SystemInfoMock>(),
+ system_info_get_platform_int(testing::_, testing::_))
+ .WillRepeatedly(testing::DoAll(
+ testing::SetArgPointee<1>(120), testing::Return(0)));
+ fopen_mock_setup(true);
+ ASSERT_EQ(create_db_handler.Execute(), 0);
+ fopen_mock_setup(false);
+ }
+
+ virtual void TearDown() {
+ for (auto& handle : db_handles_)
+ sqlite3_close_v2(handle.first);
+
+ ASSERT_EQ(remove(TEST_PARSER_DB), 0);
+ std::string journal_path(TEST_PARSER_DB);
+ journal_path += "-journal";
+ ASSERT_EQ(remove(journal_path.c_str()), 0);
+ }
+
+ const std::vector<std::pair<sqlite3*, uid_t>>& GetDBHandles() {
+ return db_handles_;
+ }
+
+ private:
+ void SetDBHandles(std::vector<std::pair<sqlite3*, uid_t>>&& db_handles) {
+ db_handles_ = db_handles;
+ }
+
+ std::vector<std::pair<sqlite3*, uid_t>> db_handles_;
+ };
+
+ TEST_F(ParserDBHandlerTest, PkgSetDBHandlerTest) {
+ PkgSetDBHandlerMock pkg_set_db_handler(0, 0);
+ pkg_set_db_handler.SetWriteType(pkgmgr_common::PkgWriteType::Insert);
+ std::unique_ptr<package_x, decltype(pkgmgrinfo_basic_free_package)*> ptr(
+ GetTestPackage("pkgA"), pkgmgrinfo_basic_free_package);
+ pkg_set_db_handler.SetPkgInfo(ptr.get());
+
+ EXPECT_CALL(pkg_set_db_handler, Connect()).WillOnce(testing::Return(true));
+ EXPECT_CALL(pkg_set_db_handler, GetConnection())
+ .WillOnce(testing::Return(GetDBHandles()));
+ ASSERT_EQ(pkg_set_db_handler.Execute(), 0);
+ }
+
+ TEST_F(ParserDBHandlerTest, PkgGetDBHandlerTest) {
+ std::string pkgid = "pkgA";
+ PkgSetDBHandlerMock pkg_set_db_handler(0, 0);
+ pkg_set_db_handler.SetWriteType(pkgmgr_common::PkgWriteType::Insert);
+ std::unique_ptr<package_x, decltype(pkgmgrinfo_basic_free_package)*> ptr(
+ GetTestPackage(pkgid), pkgmgrinfo_basic_free_package);
+ pkg_set_db_handler.SetPkgInfo(ptr.get());
+
+ EXPECT_CALL(pkg_set_db_handler, Connect()).WillOnce(testing::Return(true));
+ EXPECT_CALL(pkg_set_db_handler, GetConnection())
+ .WillOnce(testing::Return(GetDBHandles()));
+ ASSERT_EQ(pkg_set_db_handler.Execute(), 0);
+
+ pkgmgrinfo_pkginfo_filter_h filter;
+
+ ASSERT_EQ(pkgmgrinfo_pkginfo_filter_create(&filter), PMINFO_R_OK);
+ std::unique_ptr<pkgmgrinfo_filter_x, decltype(
+ pkgmgrinfo_pkginfo_filter_destroy)*> filter_ptr(
+ reinterpret_cast<pkgmgrinfo_filter_x *>(filter),
+ pkgmgrinfo_pkginfo_filter_destroy);
+ ASSERT_EQ(pkgmgrinfo_pkginfo_filter_add_string(filter,
+ PMINFO_PKGINFO_PROP_PACKAGE_ID, pkgid.c_str()), PMINFO_R_OK);
+ ASSERT_EQ(pkgmgrinfo_pkginfo_filter_add_bool(filter,
+ PMINFO_PKGINFO_PROP_PACKAGE_DISABLE, false), PMINFO_R_OK);
+
+ PkgGetDBHandlerMock pkg_get_db_handler(0, 0);
+ pkg_get_db_handler.SetFilter(filter_ptr.get());
+ pkg_get_db_handler.SetLocale("test_lang");
+
+ EXPECT_CALL(pkg_get_db_handler, Connect()).WillOnce(testing::Return(true));
+ EXPECT_CALL(pkg_get_db_handler, GetConnection())
+ .WillOnce(testing::Return(GetDBHandles()));
+ ASSERT_EQ(pkg_get_db_handler.Execute(), 0);
+
+ auto lpkginfo_list = pkg_get_db_handler.GetPkgHandle();
+ ASSERT_EQ(lpkginfo_list.size(), 1);
+
+ auto test_pkginfo = GetTestPackage(pkgid);
+ std::vector<package_x*> rpkginfo_list;
+ rpkginfo_list.emplace_back(test_pkginfo);
+
+ ASSERT_EQ(IsEqualPackagesInfo(lpkginfo_list, rpkginfo_list), true);
+ }
+
+ TEST_F(ParserDBHandlerTest, AppInfoDBHandlerTest) {
+ PkgSetDBHandlerMock pkg_set_db_handler(0, 0);
+ pkg_set_db_handler.SetWriteType(pkgmgr_common::PkgWriteType::Insert);
+ std::unique_ptr<package_x, decltype(pkgmgrinfo_basic_free_package)*> ptr(
+ GetTestPackage("test_package"), pkgmgrinfo_basic_free_package);
+ pkg_set_db_handler.SetPkgInfo(ptr.get());
+
+ EXPECT_CALL(pkg_set_db_handler, Connect()).WillOnce(testing::Return(true));
+ EXPECT_CALL(pkg_set_db_handler, GetConnection())
+ .WillOnce(testing::Return(GetDBHandles()));
+ ASSERT_EQ(pkg_set_db_handler.Execute(), 0);
+
+ pkgmgrinfo_appinfo_filter_h filter;
+ std::string appid = "test_app1";
+
+ ASSERT_EQ(pkgmgrinfo_appinfo_filter_create(&filter), PMINFO_R_OK);
+ std::unique_ptr<pkgmgrinfo_filter_x, decltype(
+ pkgmgrinfo_appinfo_filter_destroy)*> filter_ptr(
+ reinterpret_cast<pkgmgrinfo_filter_x *>(filter),
+ pkgmgrinfo_appinfo_filter_destroy);
+ ASSERT_EQ(pkgmgrinfo_appinfo_filter_add_string(filter,
+ PMINFO_APPINFO_PROP_APP_ID, appid.c_str()), PMINFO_R_OK);
+ ASSERT_EQ(pkgmgrinfo_appinfo_filter_add_bool(filter,
+ PMINFO_APPINFO_PROP_APP_DISABLE, false), PMINFO_R_OK);
+
+ AppInfoDBHandlerMock appinfo_db_handler(0, 0);
+ appinfo_db_handler.SetFilter(filter_ptr.get());
+
+ EXPECT_CALL(appinfo_db_handler, Connect()).WillOnce(testing::Return(true));
+ EXPECT_CALL(appinfo_db_handler, GetConnection())
+ .WillOnce(testing::Return(GetDBHandles()));
+ appinfo_db_handler.SetLocale("test_lang");
+ ASSERT_EQ(appinfo_db_handler.Execute(), 0);
+
+ auto lappinfo_list = appinfo_db_handler.GetAppHandle();
+ ASSERT_EQ(lappinfo_list.size(), 1);
+
+ auto test_appinfo = GetTestApplication(appid);
+ std::vector<application_x*> rappinfo_list;
+ rappinfo_list.emplace_back(test_appinfo);
+
+ ASSERT_EQ(IsEqualApplicationsInfo(lappinfo_list, rappinfo_list), true);
+ }
+
+ TEST_F(ParserDBHandlerTest, DepInfoDBHandlerTest) {
+ PkgSetDBHandlerMock pkg_set_db_handler(0, 0);
+ pkg_set_db_handler.SetWriteType(pkgmgr_common::PkgWriteType::Insert);
+ std::unique_ptr<package_x, decltype(pkgmgrinfo_basic_free_package)*> ptr(
+ GetTestPackage("test_package"), pkgmgrinfo_basic_free_package);
+ pkg_set_db_handler.SetPkgInfo(ptr.get());
+
+ EXPECT_CALL(pkg_set_db_handler, Connect()).WillOnce(testing::Return(true));
+ EXPECT_CALL(pkg_set_db_handler, GetConnection())
+ .WillOnce(testing::Return(GetDBHandles()));
+ ASSERT_EQ(pkg_set_db_handler.Execute(), 0);
+
+ DepInfoGetDBHandlerMock depinfo_get_db_handler(0, 0);
+ depinfo_get_db_handler.SetPkgID("depends_on_pkgid");
+ EXPECT_CALL(depinfo_get_db_handler,
+ Connect()).WillOnce(testing::Return(true));
+ EXPECT_CALL(depinfo_get_db_handler, GetConnection())
+ .WillOnce(testing::Return(GetDBHandles()));
+ ASSERT_EQ(depinfo_get_db_handler.Execute(), 0);
+
+ auto depinfo_from_db = depinfo_get_db_handler.GetDependencyList();
+ ASSERT_EQ(depinfo_from_db.size(), 1);
+
+ std::vector<dependency_x*> depinfo_list;
+ depinfo_list.emplace_back(GetTestDepInfo("test_package"));
+
+ EXPECT_TRUE(IsEqualDepInfo(depinfo_list, depinfo_from_db));
+ }
+
+ TEST_F(ParserDBHandlerTest, QueryDBHandler_PluginInfoTest) {
+ const std::string pkgid = "test_pkgid";
+ const std::string appid = "test_appid";
+ const std::string plugin_type = "test_plugin_type";
+ const std::string plugin_name = "test_plugin_name";
+
+ QueryHandlerMock set_query_handler(0, 0);
+ set_query_handler.SetQueryArgs(
- std::vector<std::string>{
++ std::vector<std::pair<int, std::vector<std::optional<std::string>>>>{
+ std::make_pair(
+ QUERY_INDEX_INSERT_PACKAGE_PLUGIN_EXECUTION_INFO,
- std::vector<std::pair<int, std::vector<std::string>>>{
++ std::vector<std::optional<std::string>>{
+ pkgid, appid, plugin_type, plugin_name})});
+ set_query_handler.SetDBType(pkgmgr_common::DBType::DB_TYPE_FILE_PKGDB);
+ set_query_handler.SetOpType(
+ pkgmgr_common::DBOperationType::OPERATION_TYPE_WRITE);
+
+ EXPECT_CALL(set_query_handler,
+ Connect()).WillOnce(testing::Return(true));
+ EXPECT_CALL(set_query_handler, GetConnection())
+ .WillOnce(testing::Return(GetDBHandles()));
+ ASSERT_EQ(set_query_handler.Execute(), 0);
+
+ QueryHandlerMock get_query_handler(0, 0);
+ get_query_handler.SetQueryArgs(
- std::vector<std::string>{pkgid, plugin_type, plugin_name})});
++ std::vector<std::pair<int, std::vector<std::optional<std::string>>>>{
+ std::make_pair(
+ QUERY_INDEX_PLUGININFO_GET_APPIDS,
- std::vector<std::pair<int, std::vector<std::string>>> query_args;
- std::vector<std::vector<std::string>> expected_label;
++ std::vector<std::optional<std::string>>{pkgid, plugin_type, plugin_name})});
+ get_query_handler.SetDBType(pkgmgr_common::DBType::DB_TYPE_FILE_PKGDB);
+ get_query_handler.SetOpType(
+ pkgmgr_common::DBOperationType::OPERATION_TYPE_READ);
+
+ EXPECT_CALL(get_query_handler,
+ Connect()).WillOnce(testing::Return(true));
+ EXPECT_CALL(get_query_handler, GetConnection())
+ .WillOnce(testing::Return(GetDBHandles()));
+ ASSERT_EQ(get_query_handler.Execute(), 0);
+ auto result = get_query_handler.GetResult();
+ ASSERT_EQ(result.size(), 1);
+ ASSERT_EQ(result[0].size(), 1);
+ ASSERT_EQ(appid, result[0][0]);
+ }
+
+ TEST_F(ParserDBHandlerTest, QueryDBHandler_GetLocaledLabelTest) {
+ PkgSetDBHandlerMock pkg_set_db_handler(0, 0);
+ pkg_set_db_handler.SetWriteType(pkgmgr_common::PkgWriteType::Insert);
+ std::unique_ptr<package_x, decltype(pkgmgrinfo_basic_free_package)*> ptr(
+ GetTestPackage("test_package"), pkgmgrinfo_basic_free_package);
+ pkg_set_db_handler.SetPkgInfo(ptr.get());
+
+ EXPECT_CALL(pkg_set_db_handler, Connect()).WillOnce(testing::Return(true));
+ EXPECT_CALL(pkg_set_db_handler, GetConnection())
+ .WillOnce(testing::Return(GetDBHandles()));
+ ASSERT_EQ(pkg_set_db_handler.Execute(), 0);
+
- std::vector<std::string>{app->appid, label->lang}));
- expected_label.emplace_back(std::vector<std::string>{label->text});
++ std::vector<std::pair<int, std::vector<std::optional<std::string>>>> query_args;
++ std::vector<std::vector<std::optional<std::string>>> expected_label;
+ for (GList* app_list = ptr.get()->application; app_list;
+ app_list = app_list->next) {
+ application_x* app = reinterpret_cast<application_x*>(app_list->data);
+ ASSERT_NE(app, nullptr);
+ ASSERT_NE(app->appid, nullptr);
+ ASSERT_NE(app->label, nullptr);
+
+ for (GList* label_list = app->label; label_list;
+ label_list = label_list->next) {
+ label_x* label = reinterpret_cast<label_x*>(label_list->data);
+ ASSERT_NE(label, nullptr);
+ ASSERT_NE(label->lang, nullptr);
+ ASSERT_NE(label->text, nullptr);
+ query_args.emplace_back(std::make_pair(
+ QUERY_INDEX_APPINFO_GET_LOCALED_LABEL,
- std::vector<std::pair<int, std::vector<std::string>>> query_args;
- std::vector<std::vector<std::string>> expected_label;
++ std::vector<std::optional<std::string>>{app->appid, label->lang}));
++ expected_label.emplace_back(std::vector<std::optional<std::string>>{label->text});
+ }
+ }
+
+ QueryHandlerMock query_handler(0, 0);
+ query_handler.SetQueryArgs(std::move(query_args));
+ query_handler.SetDBType(pc::DBType::DB_TYPE_FILE_PKGDB);
+ query_handler.SetOpType(pc::DBOperationType::OPERATION_TYPE_READ);
+
+ EXPECT_CALL(query_handler,
+ Connect()).WillOnce(testing::Return(true));
+ EXPECT_CALL(query_handler, GetConnection())
+ .WillOnce(testing::Return(GetDBHandles()));
+ ASSERT_EQ(query_handler.Execute(), 0);
+ auto result = query_handler.GetResult();
+ ASSERT_EQ(result, expected_label);
+ }
+
+ TEST_F(ParserDBHandlerTest, QueryDBHandler_GetDataControlTest) {
+ PkgSetDBHandlerMock pkg_set_db_handler(0, 0);
+ pkg_set_db_handler.SetWriteType(pkgmgr_common::PkgWriteType::Insert);
+ std::unique_ptr<package_x, decltype(pkgmgrinfo_basic_free_package)*> ptr(
+ GetTestPackage("test_package"), pkgmgrinfo_basic_free_package);
+ pkg_set_db_handler.SetPkgInfo(ptr.get());
+
+ EXPECT_CALL(pkg_set_db_handler, Connect()).WillOnce(testing::Return(true));
+ EXPECT_CALL(pkg_set_db_handler, GetConnection())
+ .WillOnce(testing::Return(GetDBHandles()));
+ ASSERT_EQ(pkg_set_db_handler.Execute(), 0);
+
- std::vector<std::string>{dc->providerid, dc->type}));
++ std::vector<std::pair<int, std::vector<std::optional<std::string>>>> query_args;
++ std::vector<std::vector<std::optional<std::string>>> expected_label;
+ for (GList* app_list = ptr.get()->application; app_list;
+ app_list = app_list->next) {
+ application_x* app = reinterpret_cast<application_x*>(app_list->data);
+ ASSERT_NE(app, nullptr);
+ ASSERT_NE(app->appid, nullptr);
+ ASSERT_NE(app->datacontrol, nullptr);
+
+ for (GList* dc_list = app->datacontrol; dc_list; dc_list = dc_list->next) {
+ datacontrol_x* dc = reinterpret_cast<datacontrol_x*>(dc_list->data);
+ ASSERT_NE(dc, nullptr);
+ ASSERT_NE(dc->providerid, nullptr);
+ ASSERT_NE(dc->type, nullptr);
+ ASSERT_NE(dc->access, nullptr);
+ query_args.emplace_back(std::make_pair(
+ QUERY_INDEX_APPINFO_GET_DATACONTROL_INFO,
- std::vector<std::string>{app->appid, dc->access});
++ std::vector<std::optional<std::string>>{dc->providerid, dc->type}));
+ expected_label.emplace_back(
- std::vector<std::pair<int, std::vector<std::string>>> query_args;
- std::vector<std::vector<std::string>> expected_appids;
- std::map<std::string, std::vector<std::string>> provider_map;
++ std::vector<std::optional<std::string>>{app->appid, dc->access});
+ }
+ }
+
+ QueryHandlerMock query_handler(0, 0);
+ query_handler.SetQueryArgs(std::move(query_args));
+ query_handler.SetDBType(pc::DBType::DB_TYPE_FILE_PKGDB);
+ query_handler.SetOpType(pc::DBOperationType::OPERATION_TYPE_READ);
+
+ EXPECT_CALL(query_handler,
+ Connect()).WillOnce(testing::Return(true));
+ EXPECT_CALL(query_handler, GetConnection())
+ .WillOnce(testing::Return(GetDBHandles()));
+ ASSERT_EQ(query_handler.Execute(), 0);
+ auto result = query_handler.GetResult();
+ ASSERT_EQ(result, expected_label);
+ }
+
+ TEST_F(ParserDBHandlerTest, QueryDBHandler_GetDataControlAppIdTest) {
+ PkgSetDBHandlerMock pkg_set_db_handler(0, 0);
+ pkg_set_db_handler.SetWriteType(pkgmgr_common::PkgWriteType::Insert);
+ std::unique_ptr<package_x, decltype(pkgmgrinfo_basic_free_package)*> ptr(
+ GetTestPackage("test_package"), pkgmgrinfo_basic_free_package);
+ pkg_set_db_handler.SetPkgInfo(ptr.get());
+
+ EXPECT_CALL(pkg_set_db_handler, Connect()).WillOnce(testing::Return(true));
+ EXPECT_CALL(pkg_set_db_handler, GetConnection())
+ .WillOnce(testing::Return(GetDBHandles()));
+ ASSERT_EQ(pkg_set_db_handler.Execute(), 0);
+
- std::vector<std::string>{std::move(it.first)}));
++ std::vector<std::pair<int, std::vector<std::optional<std::string>>>> query_args;
++ std::vector<std::vector<std::optional<std::string>>> expected_appids;
++ std::map<std::string, std::vector<std::optional<std::string>>> provider_map;
+ for (GList* app_list = ptr.get()->application; app_list;
+ app_list = app_list->next) {
+ application_x* app = reinterpret_cast<application_x*>(app_list->data);
+ ASSERT_NE(app, nullptr);
+ ASSERT_NE(app->appid, nullptr);
+ ASSERT_NE(app->datacontrol, nullptr);
+
+ for (GList* dc_list = app->datacontrol; dc_list; dc_list = dc_list->next) {
+ datacontrol_x* dc = reinterpret_cast<datacontrol_x*>(dc_list->data);
+ ASSERT_NE(dc, nullptr);
+ ASSERT_NE(dc->providerid, nullptr);
+ ASSERT_NE(dc->type, nullptr);
+ ASSERT_NE(dc->access, nullptr);
+ provider_map[dc->providerid].emplace_back(app->appid);
+ }
+ }
+
+ for (auto& it : provider_map) {
+ query_args.emplace_back(std::make_pair(
+ QUERY_INDEX_APPINFO_GET_DATACONTROL_APPID,
++ std::vector<std::optional<std::string>>{std::move(it.first)}));
+ expected_appids.emplace_back(std::move(it.second));
+ }
+
+ QueryHandlerMock query_handler(0, 0);
+ query_handler.SetQueryArgs(std::move(query_args));
+ query_handler.SetDBType(pc::DBType::DB_TYPE_FILE_PKGDB);
+ query_handler.SetOpType(pc::DBOperationType::OPERATION_TYPE_READ);
+
+ EXPECT_CALL(query_handler,
+ Connect()).WillOnce(testing::Return(true));
+ EXPECT_CALL(query_handler, GetConnection())
+ .WillOnce(testing::Return(GetDBHandles()));
+ ASSERT_EQ(query_handler.Execute(), 0);
+ auto result = query_handler.GetResult();
+ ASSERT_NE(result.size(), 0);
+ for (auto& it : result)
+ std::sort(it.begin(), it.end());
+ for (auto& it : expected_appids)
+ std::sort(it.begin(), it.end());
+ ASSERT_EQ(result, expected_appids);
+ }