00816e258c1e66d834aed862f69a04d79c890bf2
[platform/core/appfw/pkgmgr-info.git] / src / server / pkginfo_internal.cc
1 /*
2 * Copyright (c) 2023 Samsung Electronics Co., Ltd All Rights Reserved
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <stdbool.h>
21 #include <unistd.h>
22 #include <ctype.h>
23 #include <sys/smack.h>
24 #include <linux/limits.h>
25 #include <sys/stat.h>
26
27 #include <sqlite3.h>
28 #include <glib.h>
29 #include <system_info.h>
30
31 #include <queue>
32 #include <set>
33 #include <string>
34 #include <string_view>
35
36 #include "pkgmgr_parser.h"
37 #include "pkgmgrinfo_basic.h"
38 #include "pkgmgrinfo_internal.h"
39 #include "pkgmgrinfo_private.h"
40 #include "pkgmgrinfo_debug.h"
41 #include "pkgmgr-info.h"
42
43 namespace {
44
45 constexpr const char LDPI[] = "ldpi";
46 constexpr const char MDPI[] = "mdpi";
47 constexpr const char HDPI[] = "hdpi";
48 constexpr const char XHDPI[] = "xhdpi";
49 constexpr const char XXHDPI[] = "xxhdpi";
50
51 constexpr const int LDPI_MIN = 0;
52 constexpr const int LDPI_MAX = 240;
53 constexpr const int MDPI_MIN = 241;
54 constexpr const int MDPI_MAX = 300;
55 constexpr const int HDPI_MIN = 301;
56 constexpr const int HDPI_MAX = 380;
57 constexpr const int XHDPI_MIN = 381;
58 constexpr const int XHDPI_MAX = 480;
59 constexpr const int XXHDPI_MIN = 481;
60 constexpr const int XXHDPI_MAX = 600;
61
62 constexpr const char join_localized_info[] =
63   " LEFT OUTER JOIN package_localized_info"
64   "  ON pi.package=package_localized_info.package"
65   "  AND package_localized_info.package_locale=?";
66 constexpr const char join_privilege_info[] =
67   " LEFT OUTER JOIN package_privilege_info"
68   "  ON pi.package=package_privilege_info.package";
69 constexpr const char join_res_info[] =
70   " LEFT OUTER JOIN package_res_info"
71   "  ON pi.package=package_res_info.package";
72 constexpr const char join_metadata[] =
73   " LEFT OUTER JOIN package_metadata"
74   "  ON pi.package=package_metadata.package";
75
76 char* GetCString(int idx, const tizen_base::Database::Result::Record& rec) {
77   std::optional<std::string> str = rec.GetString(idx);
78   if (!str)
79     return nullptr;
80
81   return strdup(str->c_str());
82 }
83
84 int _pkginfo_add_description_info_into_list(const char *locale,
85     char *record, GList **description) {
86   description_x *info;
87
88   info = reinterpret_cast<description_x*>(calloc(1, sizeof(description_x)));
89   if (info == NULL) {
90     LOGE("out of memory");
91     return PMINFO_R_ERROR;
92   }
93   info->lang = strdup(locale);
94   info->text = record;
95   *description = g_list_prepend(*description, info);
96
97   return PMINFO_R_OK;
98 }
99
100 int GetPluginExecutionInfo(const tizen_base::Database& db,
101     const char* pkgid, GList** plugins) {
102   auto q = tizen_base::Database::Sql(
103       "SELECT appid, plugin_type, plugin_name FROM package_plugin_info "
104       "WHERE pkgid=?")
105       .Bind(pkgid);
106
107   auto r = db.Exec(q);
108   if (!r) {
109     LOGE("db.Exec failed : %s", static_cast<const char*>(r));
110     return PMINFO_R_ERROR;
111   }
112
113   for (const auto& rec : r) {
114     plugin_x* plugin = reinterpret_cast<plugin_x*>(
115         calloc(1, sizeof(plugin_x)));
116     if (!plugin) {
117       LOGE("out of memory");
118       return PMINFO_R_ERROR;
119     }
120
121     plugin->pkgid = strdup(pkgid);
122     plugin->appid = GetCString(0, rec);
123     plugin->plugin_type = GetCString(1, rec);
124     plugin->plugin_name = GetCString(2, rec);
125     *plugins = g_list_prepend(*plugins, (gpointer)plugin);
126   }
127
128   return PMINFO_R_OK;
129 }
130
131 int GetPrivilege(const tizen_base::Database& db, const char* pkgid,
132     GList** privileges) {
133   auto q = tizen_base::Database::Sql(
134       "SELECT DISTINCT privilege, type FROM package_privilege_info "
135       "WHERE package=?")
136       .Bind(pkgid);
137   auto r = db.Exec(q);
138   if (!r) {
139     LOGE("db.Exec failed : %s", static_cast<const char*>(r));
140     return PMINFO_R_ERROR;
141   }
142
143   for (const auto& rec : r) {
144     privilege_x* privilege = reinterpret_cast<privilege_x*>(
145         calloc(1, sizeof(privilege_x)));
146     if (!privilege) {
147       LOGE("failed to alloc memory");
148       return PMINFO_R_ERROR;
149     }
150
151     privilege->value = GetCString(0, rec);
152     privilege->type = GetCString(1, rec);
153     *privileges = g_list_prepend(*privileges, (gpointer)privilege);
154   }
155
156   return PMINFO_R_OK;
157 }
158
159 int GetAppdefinedPrivilege(const tizen_base::Database& db,
160     const char* pkgid, GList** privileges) {
161   auto q = tizen_base::Database::Sql(
162       "SELECT DISTINCT privilege, license, type FROM "
163       "package_appdefined_privilege_info WHERE package=?")
164       .Bind(pkgid);
165   auto r = db.Exec(q);
166   if (!r) {
167     LOGE("db.Exec failed : %s", static_cast<const char*>(r));
168     return PMINFO_R_ERROR;
169   }
170
171   for (const auto& rec : r) {
172     appdefined_privilege_x* privilege = reinterpret_cast<
173         appdefined_privilege_x*>(calloc(1, sizeof(appdefined_privilege_x)));
174     if (!privilege) {
175       LOGE("failed to alloc memory");
176       return PMINFO_R_ERROR;
177     }
178
179     privilege->value = GetCString(0, rec);
180     privilege->license = GetCString(1, rec);
181     privilege->type = GetCString(2, rec);
182     *privileges = g_list_prepend(*privileges, (gpointer)privilege);
183   }
184
185   return PMINFO_R_OK;
186 }
187
188 int GetDependency(const tizen_base::Database& db, const char* pkgid,
189     GList** dependencies) {
190   auto q = tizen_base::Database::Sql(
191       "SELECT DISTINCT depends_on, type, required_version "
192       "FROM package_dependency_info WHERE package=?")
193       .Bind(pkgid);
194   auto r = db.Exec(q);
195   if (!r) {
196     LOGE("db.Exec failed : %s", static_cast<const char*>(r));
197     return PMINFO_R_ERROR;
198   }
199
200   for (const auto& rec : r) {
201     dependency_x* dependency = reinterpret_cast<
202         dependency_x*>(calloc(1, sizeof(dependency_x)));
203     if (!dependency) {
204       LOGE("failed to alloc memory");
205       return PMINFO_R_ERROR;
206     }
207
208     dependency->depends_on = GetCString(0, rec);
209     dependency->type = GetCString(1, rec);
210     dependency->required_version = GetCString(2, rec);
211     *dependencies = g_list_prepend(*dependencies, (gpointer)dependency);
212   }
213
214   return PMINFO_R_OK;
215 }
216
217 int GetResAllowedPackages(const tizen_base::Database& db, const char* pkgid,
218     GList** allowed_packages) {
219   auto q = tizen_base::Database::Sql(
220       "SELECT DISTINCT allowed_package, required_privilege "
221       "FROM package_res_allowed_package WHERE package=?")
222       .Bind(pkgid);
223   auto r = db.Exec(q);
224   if (!r) {
225     LOGE("db.Exec failed : %s", static_cast<const char*>(r));
226     return PMINFO_R_ERROR;
227   }
228
229   for (const auto& rec : r) {
230     res_allowed_package_x* allowed_package_x = nullptr;
231     char* package = nullptr;
232     char* privilege = nullptr;
233
234     package = GetCString(0, rec);
235     if (!package)
236       continue;
237
238     for (GList* l = *allowed_packages; l; l = l->next) {
239       allowed_package_x = (res_allowed_package_x *)l->data;
240       if (!strcmp(package, allowed_package_x->allowed_package))
241         break;
242       allowed_package_x = nullptr;
243     }
244
245     if (allowed_package_x) {
246       free(package);
247     } else {
248       allowed_package_x = reinterpret_cast<res_allowed_package_x*>(calloc(1,
249           sizeof(res_allowed_package_x)));
250       if (allowed_package_x == nullptr) {
251         LOGE("failed to alloc memory");
252         free(package);
253         return PMINFO_R_ERROR;
254       }
255       allowed_package_x->allowed_package = package;
256       *allowed_packages = g_list_prepend(*allowed_packages,
257           (gpointer)allowed_package_x);
258     }
259
260     privilege = GetCString(1, rec);
261     if (!privilege)
262       continue;
263
264     allowed_package_x->required_privileges = g_list_prepend(
265         allowed_package_x->required_privileges,
266         privilege);
267   }
268
269   return PMINFO_R_OK;
270 }
271
272 int GetResInfo(const tizen_base::Database& db, const char* pkgid,
273     char** res_type, char** res_version, char** lib,
274     GList** res_allowed_packages) {
275   auto q = tizen_base::Database::Sql(
276       "SELECT DISTINCT res_type, res_version, lib "
277       "FROM package_res_info WHERE package=?")
278       .Bind(pkgid);
279   auto r = db.Exec(q);
280   if (!r) {
281     LOGE("db.Exec() failed : %s", static_cast<const char*>(r));
282     return PMINFO_R_ERROR;
283   }
284
285   auto rec = r.GetFirstRecord();
286   if (!rec)
287     return PMINFO_R_OK;
288
289   if (GetResAllowedPackages(db, pkgid, res_allowed_packages) != PMINFO_R_OK)
290     return PMINFO_R_ERROR;
291
292   *res_type = GetCString(0, *rec);
293   *res_version = GetCString(1, *rec);
294   *lib = GetCString(2, *rec);
295
296   return PMINFO_R_OK;
297 }
298
299 int GetPackageMetadata(const tizen_base::Database& db,
300     const char* pkgid, GList** metadata) {
301   auto q = tizen_base::Database::Sql(
302       "SELECT md_key, md_value "
303       "FROM package_metadata WHERE package=?")
304       .Bind(pkgid);
305
306   auto r = db.Exec(q);
307   if (!r) {
308     _LOGE("db.Exec() failed: %s", static_cast<const char*>(r));
309     return PMINFO_R_ERROR;
310   }
311
312   for (const auto& rec : r) {
313     metadata_x* info = static_cast<metadata_x*>(
314         calloc(1, sizeof(metadata_x)));
315     if (info == nullptr) {
316       LOGE("out of memory");
317       return PMINFO_R_ERROR;
318     }
319
320     int idx = 0;
321     info->key = GetCString(idx++, rec);
322     info->value = GetCString(idx++, rec);
323     *metadata = g_list_prepend(*metadata, info);
324   }
325
326   return PMINFO_R_OK;
327 }
328
329 int _get_filtered_query(pkgmgrinfo_filter_x *filter,
330     const std::string& locale, uid_t uid,
331     std::string& query, std::vector<std::string>& bind_params) {
332   if (!filter)
333     return PMINFO_R_OK;
334
335   int joined = 0;
336   if (filter->cache_flag) {
337     joined = E_PMINFO_PKGINFO_JOIN_LOCALIZED_INFO |
338       E_PMINFO_PKGINFO_JOIN_PRIVILEGE_INFO |
339       E_PMINFO_PKGINFO_JOIN_RES_INFO |
340       E_PMINFO_PKGINFO_JOIN_METADATA;
341   }
342
343   std::string buf = " WHERE 1=1 ";
344   GList *tmp_params = nullptr;
345   for (GSList* list = filter->list; list; list = list->next) {
346     char* condition = nullptr;
347     joined |= __get_filter_condition(list->data, uid, &condition,
348         &tmp_params);
349     if (condition == nullptr)
350       continue;
351
352     buf += " AND ";
353     buf += condition;
354     free(condition);
355   }
356
357   if (filter->list_pkg_metadata)
358     buf += " AND (";
359   for (GSList* list = filter->list_pkg_metadata; list; list = list->next) {
360     char* condition = nullptr;
361     joined |= __get_pkg_metadata_filter_condition(list->data,
362         &condition, &tmp_params);
363     if (condition == nullptr)
364       continue;
365     buf += condition;
366     free(condition);
367     buf += " OR ";
368   }
369   if (filter->list_pkg_metadata)
370     buf += " 1=0)";
371
372   std::string buf2;
373   if (joined & E_PMINFO_PKGINFO_JOIN_LOCALIZED_INFO) {
374     buf2 += join_localized_info;
375     bind_params.push_back(locale);
376   }
377
378   if (joined & E_PMINFO_PKGINFO_JOIN_PRIVILEGE_INFO)
379     buf2 += join_privilege_info;
380   if (joined & E_PMINFO_PKGINFO_JOIN_RES_INFO)
381     buf2 += join_res_info;
382   if (joined & E_PMINFO_PKGINFO_JOIN_METADATA)
383     buf2 += join_metadata;
384
385   for (GList* l = tmp_params; l != nullptr; l = l->next)
386     bind_params.push_back(reinterpret_cast<const char*>(l->data));
387
388   query = buf2 + buf;
389   g_list_free_full(tmp_params, free);
390
391   return PMINFO_R_OK;
392 }
393
394 bool CheckPackageStorageStatus(pkgmgrinfo_filter_x* tmp_filter) {
395   GSList* tmp_list = nullptr;
396   pkgmgrinfo_node_x* tmp_node = nullptr;
397   int property = -1;
398
399   if (tmp_filter->cache_flag)
400     return false;
401
402   property = _pminfo_pkginfo_convert_to_prop_bool(
403         PMINFO_PKGINFO_PROP_PACKAGE_CHECK_STORAGE);
404   for (tmp_list = tmp_filter->list; tmp_list != nullptr;
405       tmp_list = g_slist_next(tmp_list)) {
406     tmp_node = reinterpret_cast<pkgmgrinfo_node_x*>(tmp_list->data);
407     if (property == tmp_node->prop) {
408       if (strcmp(tmp_node->value, "true") == 0)
409         return true;
410       else
411         return false;
412     }
413   }
414   return true;
415 }
416
417 bool CheckPackageDisableFilter(const pkgmgrinfo_filter_x* filter,
418     const package_x* pkg_info) {
419   GSList* tmp_list = nullptr;
420   pkgmgrinfo_node_x* tmp_node = nullptr;
421   int property = -1;
422
423   property = _pminfo_pkginfo_convert_to_prop_bool(
424         PMINFO_PKGINFO_PROP_PACKAGE_DISABLE);
425   for (tmp_list = filter->list; tmp_list != nullptr;
426       tmp_list = g_slist_next(tmp_list)) {
427     tmp_node = reinterpret_cast<pkgmgrinfo_node_x*>(tmp_list->data);
428     if (property != tmp_node->prop)
429       continue;
430
431     if (strcasecmp(tmp_node->value, pkg_info->is_disabled) == 0)
432       return true;
433
434     if (strcasecmp(pkg_info->is_disabled, "true") == 0)
435       LOGW("The package [%s] is disabled", pkg_info->package);
436
437     return false;
438   }
439   return true;
440 }
441
442 int DoGetPkgInfo(const tizen_base::Database& db, uid_t uid,
443     const std::string& locale, pkgmgrinfo_filter_x* filter, int flag,
444     std::map<std::string, std::shared_ptr<package_x>>& packages) {
445   static const char query_raw[] =
446     "SELECT DISTINCT pi.package, pi.installed_storage, pi.external_path, "
447     "pi.package_disable";
448   static const char query_basic[] =
449     ", pi.package_version, pi.install_location, "
450     "pi.package_removable, pi.package_preload, pi.package_readonly, "
451     "pi.package_update, pi.package_appsetting, pi.package_system, "
452     "pi.package_type, pi.package_size, pi.installed_time, "
453     "pi.storeclient_id, pi.mainapp_id, pi.package_url, pi.root_path, "
454     "pi.csc_path, pi.package_nodisplay, pi.package_api_version, "
455     "pi.package_support_disable, pi.package_tep_name, "
456     "pi.package_zip_mount_file, pi.package_support_mode, "
457     "pi.light_user_switch_mode";
458   static const char query_author[] =
459     ", pi.author_name, pi.author_email, pi.author_href";
460   static const char query_label[] =
461     ", COALESCE("
462     "(SELECT package_label FROM package_localized_info WHERE pi.package=package AND package_locale=?), "
463     "(SELECT package_label FROM package_localized_info WHERE pi.package=package AND package_locale='No Locale'))";
464   static const char query_icon[] =
465     ", COALESCE("
466     "(SELECT package_icon FROM package_localized_info WHERE pi.package=package AND package_locale=?), "
467     "(SELECT package_icon FROM package_localized_info WHERE pi.package=package AND package_locale='No Locale'))";
468   static const char query_description[] =
469     ", COALESCE("
470     "(SELECT package_description FROM package_localized_info WHERE pi.package=package AND package_locale=?), "
471     "(SELECT package_description FROM package_localized_info WHERE pi.package=package AND package_locale='No Locale'))";
472   static const char query_res_type[] =
473     ", (SELECT res_type FROM package_res_info WHERE pi.package=package)";
474   static const char query_res_version[] =
475     ", (SELECT res_version FROM package_res_info WHERE pi.package=package)";
476   static const char query_res_lib[] =
477     ", (SELECT lib FROM package_res_info WHERE pi.package=package)";
478   static const char query_from_clause[] = " FROM package_info as pi";
479   int ret = PMINFO_R_ERROR;
480   char* tmp_record = nullptr;
481   std::vector<std::string> bind_params;
482   bool is_check_storage = true;
483   const uid_t global_user_uid = GLOBAL_USER;
484
485   if (!static_cast<bool>(db) || locale.empty() || filter == nullptr) {
486     LOGE("Invalid parameter");
487     return PMINFO_R_EINVAL;
488   }
489
490   is_check_storage = CheckPackageStorageStatus(filter);
491   std::string query = query_raw;
492   if (flag & PMINFO_APPINFO_GET_BASICINFO)
493     query += query_basic;
494   if (flag & PMINFO_PKGINFO_GET_AUTHOR)
495     query += query_author;
496   if (flag & PMINFO_PKGINFO_GET_LABEL) {
497     query += query_label;
498     bind_params.push_back(locale);
499   }
500
501   if (flag & PMINFO_PKGINFO_GET_ICON) {
502     query += query_icon;
503     bind_params.push_back(locale);
504   }
505
506   if (flag & PMINFO_PKGINFO_GET_DESCRIPTION) {
507     query += query_description;
508     bind_params.push_back(locale);
509   }
510
511   if (flag & PMINFO_PKGINFO_GET_RES_INFO) {
512     query += query_res_type;
513     query += query_res_version;
514     query += query_res_lib;
515   }
516
517   query += query_from_clause;
518   std::string constraints;
519   ret = _get_filtered_query(filter, locale, uid,
520       constraints, bind_params);
521   if (ret != PMINFO_R_OK) {
522     LOGE("Failed to get WHERE clause");
523     return PMINFO_R_EINVAL;
524   }
525
526   if (!constraints.empty())
527     query += constraints;
528
529   auto q = tizen_base::Database::Sql(query);
530   for (auto& i : bind_params)
531     q.Bind(i);
532
533   auto r = db.Exec(q);
534   if (!r) {
535     LOGE("db.Exec failed : %s", static_cast<const char*>(r));
536     return PMINFO_R_ERROR;
537   }
538
539   for (const auto& rec : r) {
540     package_x* info = reinterpret_cast<package_x*>(calloc(1, sizeof(package_x)));
541     if (info == nullptr) {
542       LOGE("out of memory");
543       return PMINFO_R_ERROR;
544     }
545
546     std::shared_ptr<package_x> pkg(info, pkgmgrinfo_basic_free_package);
547     info->locale = strdup(locale.c_str());
548     if (info->locale == nullptr) {
549       LOGE("Out of memory");
550       return PMINFO_R_ERROR;
551     }
552
553     int idx = 0;
554     // Temp impl
555     info->package = GetCString(idx++, rec);
556     info->installed_storage = GetCString(idx++, rec);
557     info->external_path = GetCString(idx++, rec);
558     info->is_disabled = GetCString(idx++, rec);
559     if (flag & PMINFO_APPINFO_GET_BASICINFO) {
560       info->version = GetCString(idx++, rec);
561       info->installlocation = GetCString(idx++, rec);
562       info->removable = GetCString(idx++, rec);
563       info->preload = GetCString(idx++, rec);
564       info->readonly = GetCString(idx++, rec);
565       info->update = GetCString(idx++, rec);
566       info->appsetting = GetCString(idx++, rec);
567       info->system = GetCString(idx++, rec);
568       info->type = GetCString(idx++, rec);
569       info->package_size = GetCString(idx++, rec);
570       info->installed_time = GetCString(idx++, rec);
571       info->storeclient_id = GetCString(idx++, rec);
572       info->mainapp_id = GetCString(idx++, rec);
573       info->package_url = GetCString(idx++, rec);
574       info->root_path = GetCString(idx++, rec);
575       info->csc_path = GetCString(idx++, rec);
576       info->nodisplay_setting = GetCString(idx++, rec);
577       info->api_version = GetCString(idx++, rec);
578       info->support_disable = GetCString(idx++, rec);
579       info->tep_name = GetCString(idx++, rec);
580       info->zip_mount_file = GetCString(idx++, rec);
581       info->support_mode = GetCString(idx++, rec);
582       info->light_user_switch_mode = GetCString(idx++, rec);
583     }
584
585     info->for_all_users =
586       strdup((uid != global_user_uid) ? "false" : "true");
587
588     if (GetPluginExecutionInfo(db, info->package, &info->plugin))
589       return PMINFO_R_ERROR;
590
591     if (flag & PMINFO_PKGINFO_GET_AUTHOR) {
592       author_x* author = reinterpret_cast<author_x*>(calloc(1, sizeof(author_x)));
593       if (author == nullptr) {
594         return PMINFO_R_ERROR;
595       }
596       author->text = GetCString(idx++, rec);
597       author->email = GetCString(idx++, rec);
598       author->href = GetCString(idx++, rec);
599       info->author = g_list_prepend(info->author, author);
600     }
601
602     if (flag & PMINFO_PKGINFO_GET_LABEL) {
603       tmp_record = GetCString(idx++, rec);
604       if (_add_label_info_into_list(locale.c_str(),
605           tmp_record, &info->label)) {
606         return PMINFO_R_ERROR;
607       }
608     }
609
610     if (flag & PMINFO_PKGINFO_GET_ICON) {
611       tmp_record = GetCString(idx++, rec);
612       if (_add_icon_info_into_list(locale.c_str(),
613           tmp_record, &info->icon)) {
614         return PMINFO_R_ERROR;
615       }
616     }
617
618     if (flag & PMINFO_PKGINFO_GET_DESCRIPTION) {
619       tmp_record = GetCString(idx++, rec);
620       if (_pkginfo_add_description_info_into_list(locale.c_str(),
621           tmp_record, &info->description)) {
622         return PMINFO_R_ERROR;
623       }
624     }
625
626     if (flag & PMINFO_PKGINFO_GET_PRIVILEGE) {
627       if (GetPrivilege(db, info->package, &info->privileges))
628         return PMINFO_R_ERROR;
629     }
630
631     if (flag & PMINFO_PKGINFO_GET_APPDEFINED_PRIVILEGE) {
632       if (GetAppdefinedPrivilege(db, info->package,
633             &info->appdefined_privileges)) {
634         return PMINFO_R_ERROR;
635       }
636     }
637
638     if (flag & PMINFO_PKGINFO_GET_DEPENDENCY) {
639       if (GetDependency(db, info->package, &info->dependencies))
640         return PMINFO_R_ERROR;
641     }
642
643     if (flag & PMINFO_PKGINFO_GET_RES_INFO) {
644       if (GetResInfo(db, info->package, &info->res_type,
645           &info->res_version, &info->lib, &info->res_allowed_packages) < 0) {
646         return PMINFO_R_ERROR;
647       }
648     }
649
650     if (flag & PMINFO_PKGINFO_GET_METADATA) {
651       if (GetPackageMetadata(db, info->package, &info->metadata) < 0)
652         return PMINFO_R_ERROR;
653     }
654
655     if (is_check_storage && __pkginfo_check_installed_storage(info) !=
656             PMINFO_R_OK)
657       continue;
658
659     if (!CheckPackageDisableFilter(filter, info))
660       continue;
661
662     if (!(flag & PMINFO_APPINFO_GET_BASICINFO) && info->is_disabled) {
663       free(info->is_disabled);
664       info->is_disabled = nullptr;
665     }
666
667     packages[info->package] = std::move(pkg);
668   }
669
670   return PMINFO_R_OK;
671 }
672
673 int DoGetDependsOn(const tizen_base::Database& db, const std::string& pkgid,
674     std::queue<std::string>& queue, std::set<std::string>& dup_checker,
675     std::vector<dependency_x*>& dep_list) {
676   if (dup_checker.find(pkgid) != dup_checker.end())
677     return PMINFO_R_OK;
678   dup_checker.insert(pkgid);
679
680   auto q = tizen_base::Database::Sql(
681       "SELECT package, depends_on, type, required_version "
682       "FROM package_dependency_info WHERE depends_on=?")
683       .Bind(pkgid);
684   auto r = db.Exec(q);
685
686   if (!r) {
687     LOGE("db.Exec() failed : %s", static_cast<const char*>(r));
688     return PMINFO_R_ERROR;
689   }
690
691   for (const auto& rec : r) {
692     auto* req = reinterpret_cast<dependency_x*>(calloc(1, sizeof(dependency_x)));
693     if (req == nullptr) {
694       LOGE("out of memory");
695       return PMINFO_R_ERROR;
696     }
697
698     req->pkgid = GetCString(0, rec);
699     req->depends_on = GetCString(1, rec);
700     req->type = GetCString(2, rec);
701     req->required_version = GetCString(3, rec);
702
703     dep_list.push_back(req);
704     queue.push(req->pkgid);
705   }
706
707   return PMINFO_R_OK;
708 }
709
710 void __free_depends_on(dependency_x* dep) {
711   free(dep->pkgid);
712   free(dep->depends_on);
713   free(dep->type);
714   free(dep->required_version);
715   free(dep);
716 }
717
718 int DoExecuteQuery(const tizen_base::Database& db, const std::string& query,
719     const std::vector<std::optional<std::string>>& param) {
720   auto q = tizen_base::Database::Sql(query);
721   for (auto& p : param) {
722     if (p)
723       q.Bind(*p);
724     else
725       q.Bind(std::nullopt);
726   }
727
728   auto r = db.Exec(q);
729   if (!r) {
730     LOGE("db.Exec() failed : %s", static_cast<const char*>(r));
731     return PMINFO_R_ERROR;
732   }
733
734   return PMINFO_R_OK;
735 }
736
737 int __check_dpi(const char *dpi_char, int dpi_int) {
738   if (dpi_char == NULL)
739     return -1;
740
741   if (strcasecmp(dpi_char, LDPI) == 0) {
742     if (dpi_int >= LDPI_MIN && dpi_int <= LDPI_MAX)
743       return 0;
744     else
745       return -1;
746   } else if (strcasecmp(dpi_char, MDPI) == 0) {
747     if (dpi_int >= MDPI_MIN && dpi_int <= MDPI_MAX)
748       return 0;
749     else
750       return -1;
751   } else if (strcasecmp(dpi_char, HDPI) == 0) {
752     if (dpi_int >= HDPI_MIN && dpi_int <= HDPI_MAX)
753       return 0;
754     else
755       return -1;
756   } else if (strcasecmp(dpi_char, XHDPI) == 0) {
757     if (dpi_int >= XHDPI_MIN && dpi_int <= XHDPI_MAX)
758       return 0;
759     else
760       return -1;
761   } else if (strcasecmp(dpi_char, XXHDPI) == 0) {
762     if (dpi_int >= XXHDPI_MIN && dpi_int <= XXHDPI_MAX)
763       return 0;
764     else
765       return -1;
766   } else
767     return -1;
768 }
769
770 void __find_appcontrol_splashscreen_with_dpi(gpointer data,
771     gpointer user_data) {
772   splashscreen_x *ss = (splashscreen_x *)data;
773   GList **list = (GList **)user_data;
774   int dpi = -1;
775   int ret;
776
777   if (ss->operation == NULL || ss->dpi == NULL)
778     return;
779
780   ret = system_info_get_platform_int(
781       "http://tizen.org/feature/screen.dpi", &dpi);
782   if (ret != SYSTEM_INFO_ERROR_NONE)
783     return;
784
785   if (__check_dpi(ss->dpi, dpi) != 0)
786     return;
787
788   *list = g_list_prepend(*list, ss);
789 }
790
791 void __find_appcontrol_splashscreen(gpointer data, gpointer user_data) {
792   splashscreen_x *ss = (splashscreen_x *)data;
793   GList **list = (GList **)user_data;
794   splashscreen_x *ss_tmp;
795   GList *tmp;
796
797   if (ss->operation == NULL || ss->dpi)
798     return;
799
800   for (tmp = *list; tmp; tmp = tmp->next) {
801     ss_tmp = (splashscreen_x *)tmp->data;
802     if (ss_tmp->operation
803       && strcmp(ss_tmp->operation, ss->operation) == 0
804       && strcmp(ss_tmp->orientation, ss->orientation) == 0)
805       return;
806   }
807
808   *list = g_list_prepend(*list, ss);
809 }
810
811 gint __compare_splashscreen_with_orientation_dpi(gconstpointer a,
812     gconstpointer b) {
813   splashscreen_x *ss = (splashscreen_x *)a;
814   const char *orientation = (const char *)b;
815   int dpi = -1;
816   int ret;
817
818   if (ss->operation || ss->dpi == NULL)
819     return -1;
820
821   ret = system_info_get_platform_int(
822       "http://tizen.org/feature/screen.dpi", &dpi);
823   if (ret != SYSTEM_INFO_ERROR_NONE)
824     return -1;
825
826   if (strcasecmp(ss->orientation, orientation) == 0 &&
827       __check_dpi(ss->dpi, dpi) == 0)
828     return 0;
829
830   return -1;
831 }
832
833 gint __compare_splashscreen_with_orientation(gconstpointer a,
834     gconstpointer b) {
835   splashscreen_x *ss = (splashscreen_x *)a;
836   const char *orientation = (const char *)b;
837
838   if (ss->operation || ss->dpi)
839     return -1;
840
841   if (strcasecmp(ss->orientation, orientation) == 0)
842     return 0;
843
844   return -1;
845 }
846
847 splashscreen_x *__find_default_splashscreen(GList *splashscreens,
848     const char *orientation) {
849   GList *tmp;
850
851   tmp = g_list_find_custom(splashscreens, orientation,
852       (GCompareFunc)
853       __compare_splashscreen_with_orientation_dpi);
854   if (tmp)
855     return (splashscreen_x *)tmp->data;
856
857   tmp = g_list_find_custom(splashscreens, orientation,
858       (GCompareFunc)__compare_splashscreen_with_orientation);
859   if (tmp)
860     return (splashscreen_x *)tmp->data;
861
862   return NULL;
863 }
864
865 GList *__find_splashscreens(GList *splashscreens) {
866   GList *list = NULL;
867   splashscreen_x *ss;
868
869   if (splashscreens == NULL)
870     return NULL;
871
872   g_list_foreach(splashscreens,
873       __find_appcontrol_splashscreen_with_dpi, &list);
874   g_list_foreach(splashscreens,
875       __find_appcontrol_splashscreen, &list);
876
877   ss = __find_default_splashscreen(splashscreens, "portrait");
878   if (ss)
879     list = g_list_prepend(list, ss);
880   ss = __find_default_splashscreen(splashscreens, "landscape");
881   if (ss)
882     list = g_list_prepend(list, ss);
883
884   return list;
885 }
886
887 int InsertSplashscreenInfo(const tizen_base::Database& db,
888     application_x *app, GList *ss_list) {
889   if (app->splashscreens == nullptr)
890     return 0;
891
892   if (ss_list == nullptr)
893     return 0;
894
895   auto q = tizen_base::Database::Sql(
896       "INSERT INTO package_app_splash_screen (app_id, src, type,"
897       "  orientation, indicatordisplay, operation, color_depth) "
898       "VALUES (?, ?, ?, ?, ?, ?, ?)");
899   auto r = db.Prepare(q);
900   if (!r) {
901     _LOGE("db.Prepare() failed: %s", static_cast<const char*>(r));
902     return -1;
903   }
904
905   for (GList* tmp = ss_list; tmp; tmp = tmp->next) {
906     splashscreen_x* ss = reinterpret_cast<splashscreen_x*>(tmp->data);
907     if (ss == nullptr)
908       continue;
909     q.Reset()
910         .Bind(app->appid)
911         .Bind(ss->src)
912         .Bind(ss->type)
913         .Bind(ss->orientation)
914         .Bind(ss->indicatordisplay)
915         .Bind(ss->operation)
916         .Bind(ss->color_depth);
917     if (!db.Exec(q, r)) {
918       _LOGE("db.Exec() failed : %s", static_cast<const char*>(r));
919       return -1;
920     }
921   }
922
923   return 0;
924 }
925
926 void __trimfunc(GList *trim_list) {
927   char *trim_data;
928   char *prev = NULL;
929   GList *list = g_list_first(trim_list);
930
931   while (list) {
932     trim_data = (char *)list->data;
933     if (trim_data) {
934       if (prev) {
935         if (strcmp(trim_data, prev) == 0) {
936           trim_list = g_list_remove(trim_list,
937               trim_data);
938           list = g_list_first(trim_list);
939           prev = NULL;
940           continue;
941         } else
942           prev = trim_data;
943       } else {
944         prev = trim_data;
945       }
946     }
947     list = g_list_next(list);
948   }
949 }
950
951 int InsertPackageAppdefinedPrivilegeInfo(const tizen_base::Database& db,
952     manifest_x* mfx) {
953   auto q = tizen_base::Database::Sql(
954       "INSERT INTO package_appdefined_privilege_info "
955       "(package, privilege, license, type) "
956       "VALUES (?, ?, ?, ?)");
957   auto r = db.Prepare(q);
958   if (!r) {
959     _LOGE("db.Prepare() failed: %s", static_cast<const char*>(r));
960     return -1;
961   }
962
963   for (GList* tmp = mfx->appdefined_privileges; tmp; tmp = tmp->next) {
964     appdefined_privilege_x* priv =
965         reinterpret_cast<appdefined_privilege_x*>(tmp->data);
966     if (priv == nullptr)
967       continue;
968
969     q.Reset()
970         .Bind(mfx->package)
971         .Bind(priv->value)
972         .Bind(priv->license)
973         .Bind(priv->type);
974     if (!db.Exec(q, r)) {
975       _LOGE("db.Exec() failed : %s", static_cast<const char*>(r));
976       return -1;
977     }
978   }
979
980   return 0;
981 }
982
983 int InsertPackageDependencyInfo(const tizen_base::Database& db,
984     manifest_x *mfx) {
985   auto q = tizen_base::Database::Sql(
986       "INSERT INTO package_dependency_info"
987       "  (package, depends_on, type, required_version) "
988       "VALUES (?, ?, ?, ?)");
989   auto r = db.Prepare(q);
990   if (!r) {
991     _LOGE("db.Prepare() failed: %s", static_cast<const char*>(r));
992     return -1;
993   }
994
995   for (GList* tmp = mfx->dependencies; tmp; tmp = tmp->next) {
996     dependency_x* dep = reinterpret_cast<dependency_x*>(tmp->data);
997     if (dep == nullptr)
998       continue;
999
1000     q.Reset()
1001         .Bind(mfx->package)
1002         .Bind(dep->depends_on)
1003         .Bind(dep->type)
1004         .Bind(dep->required_version);
1005
1006     if (!db.Exec(q, r)) {
1007       _LOGE("db.Exec() failed : %s", static_cast<const char*>(r));
1008       return -1;
1009     }
1010   }
1011
1012   return 0;
1013 }
1014
1015 int InsertMainappLocalizedInfo(const tizen_base::Database& db,
1016     application_x* app, const char* locale, const char* label,
1017     const char* icon) {
1018   auto q = tizen_base::Database::Sql(
1019       "INSERT OR REPLACE INTO package_localized_info ("
1020       "  package, package_locale, package_label, package_icon,"
1021       "  package_description, package_license, package_author) "
1022       "VALUES (?, ?,"
1023       "  COALESCE((SELECT package_label FROM package_localized_info"
1024       "            WHERE package=? AND package_locale=?), ?),"
1025       "  COALESCE((SELECT package_icon FROM package_localized_info"
1026       "            WHERE package=? AND package_icon=?), ?),"
1027       "  (SELECT package_description FROM package_localized_info"
1028       "   WHERE package=? AND package_locale=?),"
1029       "  (SELECT package_description FROM package_localized_info"
1030       "   WHERE package=? AND package_locale=?),"
1031       "  (SELECT package_description FROM package_localized_info"
1032       "   WHERE package=? AND package_locale=?))")
1033       .Bind(app->package)
1034       .Bind(locale)
1035       .Bind(app->package)
1036       .Bind(locale)
1037       .Bind(label)
1038       .Bind(app->package)
1039       .Bind(locale)
1040       .Bind(icon)
1041       .Bind(app->package)
1042       .Bind(locale)
1043       .Bind(app->package)
1044       .Bind(locale)
1045       .Bind(app->package)
1046       .Bind(locale);
1047   auto r = db.Exec(q);
1048   if (!r) {
1049     _LOGE("db.Exec() failed: %s", static_cast<const char*>(r));
1050     return -1;
1051   }
1052
1053   return 0;
1054 }
1055
1056 gint __comparefunc(gconstpointer a, gconstpointer b, gpointer userdata) {
1057   if (a == NULL || b == NULL)
1058     return 0;
1059   if (strcmp((char *)a, (char *)b) == 0)
1060     return 0;
1061   if (strcmp((char *)a, (char *)b) < 0)
1062     return -1;
1063   if (strcmp((char *)a, (char *)b) > 0)
1064     return 1;
1065   return 0;
1066 }
1067
1068 GList *__create_locale_list(GList *lbls, GList *lcns, GList *icns,
1069     GList *dcns, GList *aths) {
1070   GList *locale = NULL;
1071   GList *tmp;
1072   label_x *lbl;
1073   license_x *lcn;
1074   icon_x *icn;
1075   description_x *dcn;
1076   author_x *ath;
1077
1078   for (tmp = lbls; tmp; tmp = tmp->next) {
1079     lbl = (label_x *)tmp->data;
1080     if (lbl == NULL)
1081       continue;
1082     if (lbl->lang)
1083       locale = g_list_insert_sorted_with_data(
1084           locale, (gpointer)lbl->lang,
1085           __comparefunc, NULL);
1086   }
1087   for (tmp = lcns; tmp; tmp = tmp->next) {
1088     lcn = (license_x *)tmp->data;
1089     if (lcn == NULL)
1090       continue;
1091     if (lcn->lang)
1092       locale = g_list_insert_sorted_with_data(
1093           locale, (gpointer)lcn->lang,
1094           __comparefunc, NULL);
1095   }
1096   for (tmp = icns; tmp; tmp = tmp->next) {
1097     icn = (icon_x *)tmp->data;
1098     if (icn == NULL)
1099       continue;
1100     if (icn->lang)
1101       locale = g_list_insert_sorted_with_data(
1102           locale, (gpointer)icn->lang,
1103           __comparefunc, NULL);
1104   }
1105   for (tmp = dcns; tmp; tmp = tmp->next) {
1106     dcn = (description_x *)tmp->data;
1107     if (dcn == NULL)
1108       continue;
1109     if (dcn->lang)
1110       locale = g_list_insert_sorted_with_data(
1111           locale, (gpointer)dcn->lang,
1112           __comparefunc, NULL);
1113   }
1114   for (tmp = aths; tmp; tmp = tmp->next) {
1115     ath = (author_x *)tmp->data;
1116     if (ath == NULL)
1117       continue;
1118     if (ath->lang)
1119       locale = g_list_insert_sorted_with_data(
1120           locale, (gpointer)ath->lang,
1121           __comparefunc, NULL);
1122   }
1123   __trimfunc(locale);
1124   return locale;
1125 }
1126
1127 gint __check_icon_resolution(std::string_view orig_icon_path,
1128     char **new_icon_path) {
1129   const char* dpi_path[2];
1130   std::string modified_iconpath;
1131   if (orig_icon_path.empty())
1132     return -1;
1133
1134   int dpi = -1;
1135   int ret = system_info_get_platform_int(
1136       "http://tizen.org/feature/screen.dpi", &dpi);
1137   if (ret != SYSTEM_INFO_ERROR_NONE)
1138     return -1;
1139
1140   if (dpi >= LDPI_MIN && dpi <= LDPI_MAX) {
1141     dpi_path[0] = "LDPI";
1142     dpi_path[1] = "ldpi";
1143   } else if (dpi >= MDPI_MIN && dpi <= MDPI_MAX) {
1144     dpi_path[0] = "MDPI";
1145     dpi_path[1] = "mdpi";
1146   } else if (dpi >= HDPI_MIN && dpi <= HDPI_MAX) {
1147     dpi_path[0] = "HDPI";
1148     dpi_path[1] = "hdpi";
1149   } else if (dpi >= XHDPI_MIN && dpi <= XHDPI_MAX) {
1150     dpi_path[0] = "XHDPI";
1151     dpi_path[1] = "xhdpi";
1152   } else if (dpi >= XXHDPI_MIN && dpi <= XXHDPI_MAX) {
1153     dpi_path[0] = "XXHDPI";
1154     dpi_path[1] = "xxhdpi";
1155   } else {
1156     _LOGE("Unidentified dpi[%d]", dpi);
1157     return -1;
1158   }
1159
1160   auto pos = orig_icon_path.rfind('/');
1161   if (pos == std::string::npos)
1162     return -1;
1163   std::string_view icon_filename = orig_icon_path.substr(pos);
1164
1165   for (int i = 0; i < 2; i++) {
1166     modified_iconpath = std::string(orig_icon_path) +
1167         "/" + dpi_path[i] + std::string(icon_filename);
1168     if (access(modified_iconpath.c_str(), F_OK) != -1) {
1169       *new_icon_path = strdup(modified_iconpath.c_str());
1170       return 0;
1171     }
1172   }
1173
1174   return -1;
1175 }
1176
1177 gint __compare_icon(gconstpointer a, gconstpointer b) {
1178   icon_x *icon = (icon_x *)a;
1179   char *icon_path;
1180
1181   if (icon->lang != NULL && strcasecmp(icon->lang, DEFAULT_LOCALE) != 0)
1182     return -1;
1183
1184   if (icon->dpi != NULL)
1185     return -1;
1186
1187   if (__check_icon_resolution(icon->text, &icon_path) == 0) {
1188     free(icon->text);
1189     icon->text = icon_path;
1190   }
1191
1192   return 0;
1193 }
1194
1195 gint __compare_icon_with_lang(gconstpointer a, gconstpointer b) {
1196   icon_x *icon = (icon_x *)a;
1197   char *lang = (char *)b;
1198   char *icon_path;
1199
1200   if (icon->dpi != NULL)
1201     return -1;
1202
1203   if (strcasecmp(icon->lang, lang) == 0) {
1204     if (strcasecmp(icon->lang, DEFAULT_LOCALE) == 0) {
1205       /* icon for no locale. check existance of
1206       * folder-hierachied default icons
1207       */
1208       if (__check_icon_resolution(icon->text,
1209             &icon_path) == 0) {
1210         free(icon->text);
1211         icon->text = icon_path;
1212       }
1213     }
1214     return 0;
1215   }
1216
1217   return -1;
1218 }
1219
1220 gint __compare_icon_with_dpi(gconstpointer a, gconstpointer b) {
1221   icon_x *icon = (icon_x *)a;
1222   int dpi = GPOINTER_TO_INT(b);
1223
1224   if (icon->lang != NULL && strcasecmp(icon->lang, DEFAULT_LOCALE) != 0)
1225     return -1;
1226
1227   if (icon->dpi == NULL)
1228     return -1;
1229
1230   if (__check_dpi(icon->dpi, dpi) == 0)
1231     return 0;
1232
1233   return -1;
1234 }
1235
1236 gint __compare_icon_with_lang_dpi(gconstpointer a, gconstpointer b) {
1237   int ret;
1238   icon_x *icon = (icon_x *)a;
1239   char *lang = (char *)b;
1240   int dpi = -1;
1241
1242   ret = system_info_get_platform_int(
1243       "http://tizen.org/feature/screen.dpi", &dpi);
1244   if (ret != SYSTEM_INFO_ERROR_NONE)
1245     return -1;
1246
1247   if (strcasecmp(icon->lang, lang) == 0 &&
1248       __check_dpi(icon->dpi, dpi) == 0)
1249     return 0;
1250
1251   return -1;
1252 }
1253
1254 char *__find_icon(GList *icons, const char *lang) {
1255   GList *tmp;
1256   icon_x *icon;
1257   int dpi = 0;
1258   int ret;
1259
1260   /* first, find icon whose locale and dpi with given lang and
1261   * system's dpi has matched
1262   */
1263   tmp = g_list_find_custom(icons, lang,
1264       (GCompareFunc)__compare_icon_with_lang_dpi);
1265   if (tmp != NULL) {
1266     icon = (icon_x *)tmp->data;
1267     return (char *)icon->text;
1268   }
1269
1270   /* if first has failed, find icon whose locale has matched */
1271   tmp = g_list_find_custom(icons, lang,
1272       (GCompareFunc)__compare_icon_with_lang);
1273   if (tmp != NULL) {
1274     icon = (icon_x *)tmp->data;
1275     return (char *)icon->text;
1276   }
1277
1278   /* if second has failed, find icon whose dpi has matched with
1279   * system's dpi
1280   */
1281   ret = system_info_get_platform_int(
1282       "http://tizen.org/feature/screen.dpi", &dpi);
1283   if (ret == SYSTEM_INFO_ERROR_NONE) {
1284     tmp = g_list_find_custom(icons, GINT_TO_POINTER(dpi),
1285         (GCompareFunc)__compare_icon_with_dpi);
1286     if (tmp != NULL) {
1287       icon = (icon_x *)tmp->data;
1288       return (char *)icon->text;
1289     }
1290   }
1291
1292   /* last, find default icon marked as "No Locale" */
1293   tmp = g_list_find_custom(icons, NULL, (GCompareFunc)__compare_icon);
1294   if (tmp != NULL) {
1295     icon = (icon_x *)tmp->data;
1296     return (char *)icon->text;
1297   }
1298
1299   return NULL;
1300 }
1301
1302 void __extract_data(const char *locale, GList *lbls, GList *lcns,
1303     GList *icns, GList *dcns, GList *aths, char **label,
1304     char **license, char **icon, char **description, char **author) {
1305   GList *tmp;
1306   label_x *lbl;
1307   license_x *lcn;
1308   description_x *dcn;
1309   author_x *ath;
1310
1311   for (tmp = lbls; tmp; tmp = tmp->next) {
1312     lbl = (label_x *)tmp->data;
1313     if (lbl == NULL)
1314       continue;
1315     if (lbl->lang) {
1316       if (strcmp(lbl->lang, locale) == 0) {
1317         *label = (char *)lbl->text;
1318         break;
1319       }
1320     }
1321   }
1322   for (tmp = lcns; tmp; tmp = tmp->next) {
1323     lcn = (license_x *)tmp->data;
1324     if (lcn == NULL)
1325       continue;
1326     if (lcn->lang) {
1327       if (strcmp(lcn->lang, locale) == 0) {
1328         *license = (char *)lcn->text;
1329         break;
1330       }
1331     }
1332   }
1333
1334   *icon = __find_icon(icns, locale);
1335
1336   for (tmp = dcns; tmp; tmp = tmp->next) {
1337     dcn = (description_x *)tmp->data;
1338     if (dcn == NULL)
1339       continue;
1340     if (dcn->lang) {
1341       if (strcmp(dcn->lang, locale) == 0) {
1342         *description = (char *)dcn->text;
1343         break;
1344       }
1345     }
1346   }
1347   for (tmp = aths; tmp; tmp = tmp->next) {
1348     ath = (author_x *)tmp->data;
1349     if (ath == NULL)
1350       continue;
1351     if (ath->lang) {
1352       if (strcmp(ath->lang, locale) == 0) {
1353         *author = (char *)ath->text;
1354         break;
1355       }
1356     }
1357   }
1358 }
1359
1360 int InsertAppLocalizedInfo(const tizen_base::Database& db,
1361     application_x* app) {
1362   auto q = tizen_base::Database::Sql(
1363       "INSERT INTO package_app_localized_info (app_id, app_locale,"
1364       "  app_label, app_icon) "
1365       "VALUES (?, ?, ?, ?)");
1366   auto r = db.Prepare(q);
1367   if (!r) {
1368     _LOGE("db.Prepare() failed: %s", static_cast<const char*>(r));
1369     return -1;
1370   }
1371
1372   std::unique_ptr<GList, decltype(g_list_free)*> locales(
1373       __create_locale_list(app->label, nullptr, app->icon, nullptr, nullptr),
1374       g_list_free);
1375   for (GList* tmp = locales.get(); tmp; tmp = tmp->next) {
1376     const char* locale = reinterpret_cast<char*>(tmp->data);
1377     char* label = nullptr;
1378     char* icon = nullptr;
1379     __extract_data(locale, app->label, nullptr, app->icon, nullptr, nullptr,
1380         &label, nullptr, &icon, nullptr, nullptr);
1381     if (!label && !icon)
1382       continue;
1383
1384     q.Reset()
1385         .Bind(app->appid)
1386         .Bind(locale)
1387         .Bind(label)
1388         .Bind(icon);
1389     if (!db.Exec(q, r)) {
1390       _LOGE("db.Exec() failed : %s", static_cast<const char*>(r));
1391       return -1;
1392     }
1393
1394     if (strcasecmp(app->mainapp, "true") == 0) {
1395       if (InsertMainappLocalizedInfo(db, app, locale, label, icon))
1396         _LOGE("insert mainapp localized info failed");
1397     }
1398   }
1399
1400   return 0;
1401 }
1402
1403 int InsertAppResControl(const tizen_base::Database& db,
1404     application_x *app) {
1405   if (app->res_control == nullptr)
1406     return 0;
1407
1408   auto q = tizen_base::Database::Sql(
1409       "INSERT INTO package_app_res_control (app_id, res_type,"
1410       "  min_res_version, max_res_version, auto_close) "
1411       "VALUES (?, ?, ?, ?, ?)");
1412   auto r = db.Prepare(q);
1413   if (!r) {
1414     _LOGE("db.Prepare() failed: %s", static_cast<const char*>(r));
1415     return -1;
1416   }
1417
1418   for (GList* tmp = app->res_control; tmp; tmp = tmp->next) {
1419     res_control_x* rc = reinterpret_cast<res_control_x*>(tmp->data);
1420     if (rc == nullptr)
1421       continue;
1422
1423     q.Reset()
1424         .Bind(app->appid)
1425         .Bind(rc->res_type)
1426         .Bind(rc->min_res_version)
1427         .Bind(rc->max_res_version)
1428         .Bind(rc->auto_close);
1429     if (!db.Exec(q, r)) {
1430       _LOGE("db.Exec() failed : %s", static_cast<const char*>(r));
1431       return -1;
1432     }
1433   }
1434
1435   return 0;
1436 }
1437
1438 int InsertPackagePrivilegeInfo(const tizen_base::Database& db, manifest_x* mfx) {
1439   auto q = tizen_base::Database::Sql(
1440       "INSERT INTO package_privilege_info (package, privilege, type) "
1441       "VALUES (?, ?, ?)");
1442   auto r = db.Prepare(q);
1443   if (!r) {
1444     _LOGE("db.Prepare() failed: %s", static_cast<const char*>(r));
1445     return -1;
1446   }
1447
1448   for (GList* tmp = mfx->privileges; tmp; tmp = tmp->next) {
1449     privilege_x* priv = reinterpret_cast<privilege_x*>(tmp->data);
1450     if (priv == nullptr)
1451       continue;
1452
1453     q.Reset()
1454         .Bind(mfx->package)
1455         .Bind(priv->value)
1456         .Bind(priv->type);
1457     if (!db.Exec(q, r)) {
1458       _LOGE("db.Exec() failed : %s", static_cast<const char*>(r));
1459       return -1;
1460     }
1461   }
1462
1463   return 0;
1464 }
1465
1466 int InsertAppDataControlPrivilegeInfo(const tizen_base::Database& db,
1467     datacontrol_x* datacontrol) {
1468   if (datacontrol == nullptr)
1469     return 0;
1470
1471   auto q = tizen_base::Database::Sql(
1472     "INSERT INTO package_app_data_control_privilege (providerid,"
1473     "  privilege, type) VALUES (?, ?, ?)");
1474
1475   auto r = db.Prepare(q);
1476   if (!r) {
1477     _LOGE("db.Prepare() failed: %s", static_cast<const char*>(r));
1478     return -1;
1479   }
1480
1481   for (GList* privileges = datacontrol->privileges; privileges;
1482       privileges = privileges->next) {
1483     char* priv = reinterpret_cast<char*>(privileges->data);
1484     if (priv == nullptr)
1485       continue;
1486
1487     q.Reset()
1488         .Bind(datacontrol->providerid)
1489         .Bind(priv)
1490         .Bind(datacontrol->type);
1491     if (!db.Exec(q, r)) {
1492       _LOGE("db.Exec() failed : %s", static_cast<const char*>(r));
1493       return -1;
1494     }
1495   }
1496
1497   return 0;
1498 }
1499
1500 int InsertDatacontrolInfo(const tizen_base::Database& db, application_x* app) {
1501   if (app->datacontrol == nullptr)
1502     return 0;
1503
1504   auto q = tizen_base::Database::Sql(
1505       "INSERT INTO package_app_data_control (app_id, providerid,"
1506       "  access, type, trusted) VALUES (?, ?, ?, ?, ?)");
1507   auto r = db.Prepare(q);
1508   if (!r) {
1509     _LOGE("db.Prepare() failed: %s", static_cast<const char*>(r));
1510     return -1;
1511   }
1512
1513   for (GList* tmp = app->datacontrol; tmp; tmp = tmp->next) {
1514     datacontrol_x* dc = reinterpret_cast<datacontrol_x*>(tmp->data);
1515     if (dc == nullptr)
1516       continue;
1517     q.Reset()
1518         .Bind(app->appid)
1519         .Bind(dc->providerid)
1520         .Bind(dc->access)
1521         .Bind(dc->type)
1522         .Bind(dc->trusted);
1523
1524     if (!db.Exec(q, r)) {
1525       _LOGE("db.Exec() failed: %s", static_cast<const char*>(r));
1526       return -1;
1527     }
1528
1529     if (dc->privileges && InsertAppDataControlPrivilegeInfo(db, dc))
1530       return -1;
1531   }
1532
1533   return 0;
1534 }
1535
1536 int InsertCategoryInfo(const tizen_base::Database& db, application_x* app) {
1537   if (app->category == nullptr)
1538     return 0;
1539
1540   auto q = tizen_base::Database::Sql(
1541       "INSERT INTO package_app_app_category (app_id, category) "
1542       "VALUES (?, ?)");
1543   auto r = db.Prepare(q);
1544   if (!r) {
1545     _LOGE("db.Prepare() failed: %s", static_cast<const char*>(r));
1546     return -1;
1547   }
1548
1549   for (GList* tmp = app->category; tmp; tmp = tmp->next) {
1550     const char* category = reinterpret_cast<const char*>(tmp->data);
1551     if (category == nullptr)
1552       continue;
1553     q.Reset()
1554         .Bind(app->appid)
1555         .Bind(category);
1556
1557     if (!db.Exec(q, r)) {
1558       _LOGE("db.Exec() failed : %s", static_cast<const char*>(r));
1559       return -1;
1560     }
1561   }
1562
1563   return 0;
1564 }
1565
1566 int InsertMetadataInfo(const tizen_base::Database& db, application_x* app) {
1567   if (app->metadata == nullptr)
1568     return 0;
1569
1570   auto q = tizen_base::Database::Sql(
1571       "INSERT INTO package_app_app_metadata (app_id,"
1572       "  md_key, md_value) VALUES (?, ?, ?)");
1573   auto r = db.Prepare(q);
1574   if (!r) {
1575     _LOGE("db.Prepare() failed: %s", static_cast<const char*>(r));
1576     return -1;
1577   }
1578
1579   for (GList* tmp = app->metadata; tmp; tmp = tmp->next) {
1580     metadata_x* md = reinterpret_cast<metadata_x*>(tmp->data);
1581     if (md == nullptr)
1582       continue;
1583     q.Reset()
1584         .Bind(app->appid)
1585         .Bind(md->key)
1586         .Bind(md->value);
1587
1588     if (!db.Exec(q, r)) {
1589       _LOGE("db.Exec() failed: %s", static_cast<const char*>(r));
1590       return -1;
1591     }
1592   }
1593
1594   return 0;
1595 }
1596
1597 int InsertAppcontrolPrivilegeInfo(const tizen_base::Database& db,
1598     const char *appid, appcontrol_x* ac) {
1599   if (ac == nullptr)
1600     return 0;
1601
1602   auto q = tizen_base::Database::Sql(
1603       "INSERT INTO package_app_app_control_privilege (app_id,"
1604       "  app_control, privilege) VALUES (?, ?, ?)");
1605   auto r = db.Prepare(q);
1606   if (!r) {
1607     _LOGE("db.Prepare() failed: %s", static_cast<const char*>(r));
1608     return -1;
1609   }
1610
1611   char app_control[BUFSIZE];
1612   for (GList* tmp = ac->privileges; tmp; tmp = tmp->next) {
1613     char* privilege = reinterpret_cast<char*>(tmp->data);
1614     if (privilege == nullptr || !strlen(privilege))
1615       continue;
1616
1617     snprintf(app_control, sizeof(app_control), "%s|%s|%s",
1618         ac->operation ? (strlen(ac->operation) > 0 ?
1619           ac->operation : "NULL") : "NULL",
1620         ac->uri ? (strlen(ac->uri) > 0 ?
1621           ac->uri : "NULL") : "NULL",
1622         ac->mime ? (strlen(ac->mime) > 0 ?
1623           ac->mime : "NULL") : "NULL");
1624     q.Reset()
1625       .Bind(appid)
1626       .Bind(app_control)
1627       .Bind(privilege);
1628     if (!db.Exec(q,r)) {
1629       _LOGE("db.Exec() failed: %s", static_cast<const char*>(r));
1630       return -1;
1631     }
1632   }
1633
1634   return 0;
1635 }
1636
1637 int InsertAppcontrolInfo(const tizen_base::Database& db, application_x* app) {
1638   if (app->appcontrol == nullptr)
1639     return 0;
1640
1641   auto q = tizen_base::Database::Sql(
1642       "INSERT INTO package_app_app_control (app_id, app_control,"
1643       "  visibility, app_control_id) "
1644       "VALUES (?, ?, ?, ?)");
1645   auto r = db.Prepare(q);
1646   if (!r) {
1647     _LOGE("db.Prepare() failed: %s", static_cast<const char*>(r));
1648     return -1;
1649   }
1650
1651   for (GList* tmp = app->appcontrol; tmp; tmp = tmp->next) {
1652     appcontrol_x* ac = reinterpret_cast<appcontrol_x*>(tmp->data);
1653     if (ac == nullptr)
1654       continue;
1655     std::string op = ac->operation ? (strlen(ac->operation) > 0 ?
1656           ac->operation : "NULL") : "NULL";
1657     std::string uri = ac->uri ? (strlen(ac->uri) > 0 ?
1658           ac->uri : "NULL") : "NULL";
1659     std::string mime = ac->mime ? (strlen(ac->mime) > 0 ?
1660           ac->mime : "NULL") : "NULL";
1661     std::string app_control = std::move(op) + "|" + std::move(uri)
1662         + "|" + std::move(mime);
1663     q.Reset()
1664         .Bind(app->appid)
1665         .Bind(std::move(app_control))
1666         .Bind(ac->visibility)
1667         .Bind(ac->id);
1668     if (!db.Exec(q, r)) {
1669       _LOGE("db.Exec() failed : %s", static_cast<const char*>(r));
1670       return -1;
1671     }
1672
1673     if (InsertAppcontrolPrivilegeInfo(db, app->appid, ac))
1674       return -1;
1675   }
1676
1677   return 0;
1678 }
1679
1680 const char *__get_bool(char *value, bool is_true) {
1681   if (value != NULL) {
1682     if (!strcmp(value, ""))
1683       return (is_true) ? "true" : "false";
1684     return value;
1685   }
1686
1687   return (is_true) ? "true" : "false";
1688 }
1689
1690 const char *__find_effective_appid(GList *metadata_list) {
1691   constexpr const char EFFECTIVE_APPID_KEY[] =
1692       "http://tizen.org/metadata/effective-appid";
1693
1694   GList *tmp;
1695   metadata_x *md;
1696
1697   for (tmp = metadata_list; tmp; tmp = tmp->next) {
1698     md = (metadata_x *)tmp->data;
1699     if (md == NULL || md->key == NULL)
1700       continue;
1701
1702     if (strcmp(md->key, EFFECTIVE_APPID_KEY) == 0) {
1703       if (md->value)
1704         return md->value;
1705     }
1706   }
1707
1708   return NULL;
1709 }
1710
1711 int __convert_background_category(GList *category_list) {
1712   int ret = 0;
1713   GList *tmp;
1714   char *category_data;
1715
1716   if (category_list == NULL)
1717     return 0;
1718
1719   for (tmp = category_list; tmp; tmp = tmp->next) {
1720     category_data = (char *)tmp->data;
1721     if (category_data == NULL)
1722       continue;
1723     if (!strcmp(category_data, APP_BG_CATEGORY_MEDIA_STR))
1724       ret |= APP_BG_CATEGORY_MEDIA_VAL;
1725     else if (!strcmp(category_data, APP_BG_CATEGORY_DOWNLOAD_STR))
1726       ret |= APP_BG_CATEGORY_DOWNLOAD_VAL;
1727     else if (!strcmp(category_data, APP_BG_CATEGORY_BGNETWORK_STR))
1728       ret |= APP_BG_CATEGORY_BGNETWORK_VAL;
1729     else if (!strcmp(category_data, APP_BG_CATEGORY_LOCATION_STR))
1730       ret |= APP_BG_CATEGORY_LOCATION_VAL;
1731     else if (!strcmp(category_data, APP_BG_CATEGORY_SENSOR_STR))
1732       ret |= APP_BG_CATEGORY_SENSOR_VAL;
1733     else if (!strcmp(category_data, APP_BG_CATEGORY_IOTCOMM_STR))
1734       ret |= APP_BG_CATEGORY_IOTCOMM_VAL;
1735     else if (!strcmp(category_data, APP_BG_CATEGORY_SYSTEM))
1736       ret |= APP_BG_CATEGORY_SYSTEM_VAL;
1737     else
1738       _LOGE("Unidentified category [%s]", category_data);
1739   }
1740
1741   return ret;
1742 }
1743
1744 int InsertPackageResInfoAllowedPackage(const tizen_base::Database& db,
1745     const char* pkgid, GList* rap_list) {
1746   if (rap_list == nullptr)
1747     return 0;
1748
1749   auto q = tizen_base::Database::Sql(
1750       "INSERT INTO package_res_allowed_package (package,"
1751       "  allowed_package, required_privilege) VALUES (?, ?, ?)");
1752   auto r = db.Prepare(q);
1753   if (!r) {
1754     _LOGE("db.Prepare() failed: %s", static_cast<const char*>(r));
1755     return -1;
1756   }
1757
1758   for (GList* tmp = rap_list; tmp; tmp = tmp->next) {
1759     res_allowed_package_x* rap =
1760         reinterpret_cast<res_allowed_package_x*>(tmp->data);
1761     if (rap == nullptr)
1762       continue;
1763
1764     if (!rap->required_privileges) {
1765       q.Reset()
1766           .Bind(pkgid)
1767           .Bind(rap->allowed_package)
1768           .Bind(nullptr);
1769
1770       if (!db.Exec(q, r)) {
1771         _LOGE("db.Exec() failed : %s", static_cast<const char*>(r));
1772         return -1;
1773       }
1774
1775       continue;
1776     }
1777
1778     for (GList* priv_list = rap->required_privileges; priv_list;
1779         priv_list = priv_list->next) {
1780       q.Reset()
1781           .Bind(pkgid)
1782           .Bind(rap->allowed_package)
1783           .Bind(reinterpret_cast<char*>(priv_list->data));
1784
1785       if (!db.Exec(q, r)) {
1786         _LOGE("db.Exec() failed : %s", static_cast<const char*>(r));
1787         return -1;
1788       }
1789     }
1790   }
1791
1792   return 0;
1793 }
1794
1795 int InsertPackageResInfo(const tizen_base::Database& db, manifest_x* mfx) {
1796   if (mfx->res_type == nullptr || mfx->res_version == nullptr)
1797     return 0;
1798
1799   if (mfx->lib == nullptr)
1800     mfx->lib = strdup("false");
1801
1802   auto q = tizen_base::Database::Sql(
1803       "INSERT INTO package_res_info (package, res_type,"
1804       "  res_version, lib) VALUES (?, ?, ?, ?)")
1805       .Bind(mfx->package)
1806       .Bind(mfx->res_type)
1807       .Bind(mfx->res_version)
1808       .Bind(mfx->lib);
1809
1810   auto r = db.Exec(q);
1811   if (!r) {
1812     _LOGE("db.Exec() failed: %s", static_cast<const char*>(r));
1813     return -1;
1814   }
1815
1816   if (InsertPackageResInfoAllowedPackage(db, mfx->package,
1817       mfx->res_allowed_packages) < 0) {
1818     return -1;
1819   }
1820
1821   return 0;
1822 }
1823
1824 int InsertPackageMetadataInfo(const tizen_base::Database& db, manifest_x* mfx) {
1825   if (mfx->metadata == nullptr)
1826     return 0;
1827
1828   auto q = tizen_base::Database::Sql(
1829       "INSERT INTO package_metadata (package,"
1830       "  md_key, md_value) VALUES (?, ?, ?)");
1831   auto r = db.Prepare(q);
1832   if (!r) {
1833     _LOGE("db.Prepare() failed: %s", static_cast<const char*>(r));
1834     return -1;
1835   }
1836
1837   for (GList* tmp = mfx->metadata; tmp; tmp = tmp->next) {
1838     metadata_x* md = reinterpret_cast<metadata_x*>(tmp->data);
1839     if (md == nullptr)
1840       continue;
1841     q.Reset()
1842         .Bind(mfx->package)
1843         .Bind(md->key)
1844         .Bind(md->value);
1845
1846     if (!db.Exec(q, r)) {
1847       _LOGE("db.Exec() failed: %s", static_cast<const char*>(r));
1848       return -1;
1849     }
1850   }
1851
1852   return 0;
1853 }
1854
1855 int InsertApplicationInfo(const tizen_base::Database& db, manifest_x *mfx) {
1856   auto q = tizen_base::Database::Sql(
1857       "INSERT INTO package_app_info (app_id, app_component,"
1858       "  app_exec, app_nodisplay, app_type, app_onboot, app_multiple,"
1859       "  app_autorestart, app_taskmanage, app_hwacceleration,"
1860       "  app_screenreader, app_mainapp, app_recentimage,"
1861       "  app_launchcondition, app_indicatordisplay, app_portraitimg,"
1862       "  app_landscapeimg, app_guestmodevisibility,"
1863       "  app_permissiontype, app_preload, app_submode,"
1864       "  app_submode_mainid, app_installed_storage, app_process_pool,"
1865       "  app_launch_mode, app_ui_gadget, app_support_mode,"
1866       "  app_support_disable, component_type, package, app_tep_name,"
1867       "  app_zip_mount_file, app_background_category,"
1868       "  app_package_type, app_root_path, app_api_version,"
1869       "  app_effective_appid, app_splash_screen_display,"
1870       "  app_package_system, app_removable,"
1871       "  app_package_installed_time, app_support_ambient,"
1872       "  app_external_path, app_setup_appid, light_user_switch_mode) "
1873       "VALUES (?, ?, "
1874       "  ?, LOWER(?), ?, LOWER(?), LOWER(?),"
1875       "  LOWER(?), LOWER(?), ?,"
1876       "  ?, LOWER(?), ?,"
1877       "  ?, LOWER(?), ?,"
1878       "  ?, LOWER(?),"
1879       "  ?, LOWER(?), LOWER(?),"
1880       "  ?, ?, LOWER(?),"
1881       "  COALESCE(?, 'single'), LOWER(?), ?,"
1882       "  LOWER(?), ?, ?, ?,"
1883       "  ?, ?,"
1884       "  ?, ?, ?,"
1885       "  ?, LOWER(?),"
1886       "  LOWER(?), LOWER(?),"
1887       "  ?, LOWER(?),"
1888       "  ?, ?, ?)");
1889   auto r = db.Prepare(q);
1890   if (!r) {
1891     _LOGE("db.Prepare() failed: %s", static_cast<const char*>(r));
1892     return -1;
1893   }
1894
1895   for (GList* tmp = mfx->application; tmp; tmp = tmp->next) {
1896     application_x* app = reinterpret_cast<application_x*>(tmp->data);
1897     if (app == nullptr)
1898       continue;
1899
1900     int bg_category = __convert_background_category(
1901         app->background_category);
1902     const char* effective_appid = __find_effective_appid(app->metadata);
1903
1904     q.Reset()
1905         .Bind(app->appid)
1906         .Bind(app->component_type)
1907         .Bind(app->exec)
1908         .Bind(__get_bool(app->nodisplay, false))
1909         .Bind(app->type)
1910         .Bind(__get_bool(app->onboot, false))
1911         .Bind(__get_bool(app->multiple, false))
1912         .Bind(__get_bool(app->autorestart, false))
1913         .Bind(__get_bool(app->taskmanage, false))
1914         .Bind(app->hwacceleration)
1915         .Bind(app->screenreader)
1916         .Bind(__get_bool(app->mainapp, false))
1917         .Bind(app->recentimage)
1918         .Bind(app->launchcondition)
1919         .Bind(__get_bool(app->indicatordisplay, true))
1920         .Bind(app->portraitimg)
1921         .Bind(app->landscapeimg)
1922         .Bind(__get_bool(app->guestmode_visibility, true))
1923         .Bind(app->permission_type)
1924         .Bind(__get_bool(mfx->preload, false))
1925         .Bind(__get_bool(app->submode, false))
1926         .Bind(app->submode_mainid)
1927         .Bind(mfx->installed_storage)
1928         .Bind(__get_bool(app->process_pool, false))
1929         .Bind(app->launch_mode)
1930         .Bind(__get_bool(app->ui_gadget, false))
1931         .Bind(app->support_mode ? app->support_mode : "0")
1932         .Bind(__get_bool(mfx->support_disable, false))
1933         .Bind(app->component_type)
1934         .Bind(mfx->package)
1935         .Bind(mfx->tep_name)
1936         .Bind(mfx->zip_mount_file)
1937         .Bind(bg_category)
1938         .Bind(mfx->type ? mfx->type : "tpk")
1939         .Bind(mfx->root_path)
1940         .Bind(app->api_version)
1941         .Bind(effective_appid)
1942         .Bind(__get_bool(app->splash_screen_display, true))
1943         .Bind(__get_bool(mfx->system, false))
1944         .Bind(__get_bool(mfx->removable, false))
1945         .Bind(mfx->installed_time)
1946         .Bind(__get_bool(app->support_ambient, false))
1947         .Bind(mfx->external_path)
1948         .Bind(app->setup_appid)
1949         .Bind(mfx->light_user_switch_mode);
1950
1951     if (!db.Exec(q, r)) {
1952       _LOGE("db.Exec() failed : %s", static_cast<const char*>(r));
1953       return -1;
1954     }
1955
1956     if (InsertAppcontrolInfo(db, app))
1957       return -1;
1958     if (InsertCategoryInfo(db, app))
1959       return -1;
1960     if (InsertMetadataInfo(db, app))
1961       return -1;
1962     if (InsertDatacontrolInfo(db, app))
1963       return -1;
1964     GList* ss_list = __find_splashscreens(app->splashscreens);
1965     if (InsertSplashscreenInfo(db, app, ss_list)) {
1966       g_list_free(ss_list);
1967       return -1;
1968     }
1969     g_list_free(ss_list);
1970     if (InsertAppLocalizedInfo(db, app))
1971       return -1;
1972     if (InsertAppResControl(db, app))
1973       return -1;
1974   }
1975
1976   return 0;
1977 }
1978
1979 int InsertPackageUpdateInfo(const tizen_base::Database& db, manifest_x *mfx) {
1980   auto q = tizen_base::Database::Sql(
1981       "INSERT INTO package_update_info (package, update_version) "
1982       "VALUES (?, ?)")
1983       .Bind(mfx->package)
1984       .Bind(mfx->version);
1985
1986   auto r = db.Exec(q);
1987   if (!r) {
1988     _LOGE("db.Exec() failed : %s", static_cast<const char*>(r));
1989     return -1;
1990   }
1991
1992   return 0;
1993 }
1994
1995 int InsertPackageLocalizedInfo(const tizen_base::Database& db,
1996     manifest_x *mfx) {
1997   auto q = tizen_base::Database::Sql(
1998       "INSERT INTO package_localized_info (package, package_locale,"
1999       "  package_label, package_icon, package_description,"
2000       "  package_license, package_author) "
2001       "VALUES (?, ?, ?, ?, ?, ?, ?)");
2002   auto r = db.Prepare(q);
2003   if (!r) {
2004     _LOGE("db.Prepare() failed: %s", static_cast<const char*>(r));
2005     return -1;
2006   }
2007
2008   GList* locales = __create_locale_list(mfx->label, mfx->license, mfx->icon,
2009       mfx->description, mfx->author);
2010   for (GList* tmp = locales; tmp; tmp = tmp->next) {
2011     const char* locale = (const char *)tmp->data;
2012     char* label = nullptr;
2013     char* icon = nullptr;
2014     char* description = nullptr;
2015     char* license = nullptr;
2016     char* author = nullptr;
2017     __extract_data(locale, mfx->label, mfx->license, mfx->icon,
2018         mfx->description, mfx->author,
2019         &label, &license, &icon, &description, &author);
2020     if (!label && !license && !icon && !description && !author)
2021       continue;
2022
2023     q.Reset()
2024         .Bind(mfx->package)
2025         .Bind(locale)
2026         .Bind(label)
2027         .Bind(icon)
2028         .Bind(description)
2029         .Bind(license)
2030         .Bind(author);
2031
2032     if (!db.Exec(q, r)) {
2033       _LOGE("db.Exec() failed : %s", static_cast<const char*>(r));
2034       g_list_free(locales);
2035       return -1;
2036     }
2037   }
2038
2039   g_list_free(locales);
2040
2041   return 0;
2042 }
2043
2044 int DoInsertPackageInfo(const tizen_base::Database& db, manifest_x* mfx) {
2045   const char* author_name = nullptr;
2046   const char* author_email = nullptr;
2047   const char* author_href = nullptr;
2048
2049   if (mfx->author && mfx->author->data) {
2050     author_name = ((author_x *)mfx->author->data)->text;
2051     author_email = ((author_x *)mfx->author->data)->email;
2052     author_href = ((author_x *)mfx->author->data)->href;
2053   }
2054
2055   auto q = tizen_base::Database::Sql(
2056     "INSERT INTO package_info (package, package_type,"
2057     "  package_version, package_api_version, package_tep_name,"
2058     "  package_zip_mount_file, install_location, package_size,"
2059     "  package_removable, package_preload, package_readonly,"
2060     "  package_update, package_appsetting, package_nodisplay,"
2061     "  package_system, author_name, author_email, author_href,"
2062     "  installed_time, installed_storage, storeclient_id,"
2063     "  mainapp_id, package_url, root_path, external_path,"
2064     "  csc_path, package_support_mode, package_support_disable,"
2065     "  light_user_switch_mode)"
2066     "VALUES (?, ?,"
2067     "  ?, ?, ?,"
2068     "  ?, ?, ?,"
2069     "  LOWER(?), LOWER(?), LOWER(?),"
2070     "  LOWER(?), LOWER(?), LOWER(?),"
2071     "  LOWER(?), ?, ?, ?,"
2072     "  ?, ?, ?,"
2073     "  ?, ?, ?, ?,"
2074     "  ?, ?, LOWER(?), ?)")
2075     .Bind(mfx->package)
2076     .Bind(mfx->type)
2077     .Bind(mfx->version)
2078     .Bind(mfx->api_version)
2079     .Bind(mfx->tep_name)
2080     .Bind(mfx->zip_mount_file)
2081     .Bind(mfx->installlocation)
2082     .Bind(mfx->package_size)
2083     .Bind(__get_bool(mfx->removable, true))
2084     .Bind(__get_bool(mfx->preload, false))
2085     .Bind(__get_bool(mfx->readonly, false))
2086     .Bind(__get_bool(mfx->update, false))
2087     .Bind(__get_bool(mfx->appsetting, false))
2088     .Bind(__get_bool(mfx->nodisplay_setting, false))
2089     .Bind(__get_bool(mfx->system, false))
2090     .Bind(author_name)
2091     .Bind(author_email)
2092     .Bind(author_href)
2093     .Bind(mfx->installed_time)
2094     .Bind(mfx->installed_storage)
2095     .Bind(mfx->storeclient_id)
2096     .Bind(mfx->mainapp_id)
2097     .Bind(mfx->package_url)
2098     .Bind(mfx->root_path)
2099     .Bind(mfx->external_path)
2100     .Bind(mfx->csc_path)
2101     .Bind(mfx->support_mode ? mfx->support_mode : "0")
2102     .Bind(__get_bool(mfx->support_disable, false))
2103     .Bind(mfx->light_user_switch_mode);
2104
2105   auto r = db.Exec(q);
2106   if (!r) {
2107     _LOGE("db.Exec() failed: %s", static_cast<const char*>(r));
2108     return -1;
2109   }
2110
2111   if (InsertPackageUpdateInfo(db, mfx))
2112     return -1;
2113   if (InsertPackageLocalizedInfo(db, mfx))
2114     return -1;
2115   if (InsertApplicationInfo(db, mfx))
2116     return -1;
2117   if (InsertPackagePrivilegeInfo(db, mfx))
2118     return -1;
2119   if (InsertPackageAppdefinedPrivilegeInfo(db, mfx))
2120     return -1;
2121   if (InsertPackageDependencyInfo(db, mfx))
2122     return -1;
2123   if (InsertPackageResInfo(db, mfx))
2124     return -1;
2125   if (InsertPackageMetadataInfo(db, mfx))
2126     return -1;
2127
2128   return 0;
2129 }
2130
2131 int DoDeletePackageInfo(const tizen_base::Database& db, const char* pkgid) {
2132   auto q = tizen_base::Database::Sql(
2133       "DELETE FROM package_info WHERE package=?")
2134       .Bind(pkgid);
2135   auto r = db.Exec(q);
2136   if (!r) {
2137     _LOGE("db.Exec() failed: %s", static_cast<const char*>(r));
2138     return -1;
2139   }
2140
2141   return 0;
2142 }
2143
2144 }  // namesapce
2145
2146
2147 namespace pkgmgr_server::internal {
2148
2149 int DeletePkgInfo(const tizen_base::Database& db, const char* package,
2150     uid_t uid) {
2151   if (!static_cast<bool>(db) || package == nullptr) {
2152     _LOGE("invalid parameter");
2153     return PM_PARSER_R_EINVAL;
2154   }
2155
2156   auto guard = db.CreateTransactionGuard();
2157   if (DoDeletePackageInfo(db, package) != 0)
2158     return -1;
2159   guard.Commit();
2160
2161   return PM_PARSER_R_OK;
2162 }
2163
2164 int UpdatePkgInfo(const tizen_base::Database& db, manifest_x* mfx, uid_t uid) {
2165   if (!static_cast<bool>(db) || mfx == nullptr || mfx->package == nullptr) {
2166     _LOGE("invalid parameter");
2167     return PM_PARSER_R_EINVAL;
2168   }
2169
2170   auto guard = db.CreateTransactionGuard();
2171   if (DoDeletePackageInfo(db, mfx->package) != 0)
2172     return -1;
2173   if (DoInsertPackageInfo(db, mfx) != 0)
2174     return -1;
2175   guard.Commit();
2176
2177   return PM_PARSER_R_OK;
2178 }
2179
2180 int InsertPkgInfo(const tizen_base::Database& db, manifest_x* mfx, uid_t uid) {
2181   if (!static_cast<bool>(db) || mfx == nullptr) {
2182     _LOGE("invalid parameter");
2183     return PM_PARSER_R_EINVAL;
2184   }
2185
2186   auto guard = db.CreateTransactionGuard();
2187   if (DoInsertPackageInfo(db, mfx) != 0)
2188     return -1;
2189   guard.Commit();
2190
2191   return PM_PARSER_R_OK;
2192 }
2193
2194 bool CheckPackageStorageStatus(pkgmgrinfo_filter_x* tmp_filter) {
2195   return ::CheckPackageStorageStatus(tmp_filter);
2196 }
2197
2198 int ExecuteWriteQueries(const tizen_base::Database& db,
2199     const std::vector<std::string>& queries,
2200     const std::vector<std::vector<std::optional<std::string>>>& args_list) {
2201   if (!static_cast<bool>(db) || queries.empty()) {
2202     _LOGE("Invalid parameter");
2203     return PMINFO_R_EINVAL;
2204   }
2205
2206   auto guard = db.CreateTransactionGuard();
2207
2208   int idx = 0;
2209   for (const auto& i : queries) {
2210     if (DoExecuteQuery(db, i, args_list[idx++]) != 0)
2211       return -1;
2212   }
2213   guard.Commit();
2214
2215   return PMINFO_R_OK;
2216 }
2217
2218 int GetQueryResult(const tizen_base::Database& db,
2219     const std::string& query,
2220     const std::vector<std::optional<std::string>>& param,
2221     std::vector<std::vector<std::optional<std::string>>>& result) {
2222   if (!static_cast<bool>(db) || query.empty()) {
2223     LOGE("Invalid parameter");
2224     return PMINFO_R_EINVAL;
2225   }
2226
2227   auto q = tizen_base::Database::Sql(query);
2228   for (auto& p : param) {
2229     if (p)
2230       q.Bind(*p);
2231     else
2232       q.Bind(std::nullopt);
2233   }
2234
2235   auto r = db.Exec(q);
2236   if (!r) {
2237     LOGE("db.Exec() failed : %s", static_cast<const char*>(r));
2238     return PMINFO_R_ERROR;
2239   }
2240
2241   int col_cnt = r.GetColumnCount();
2242   for (const auto& row : r) {
2243     std::vector<std::optional<std::string>> rec;
2244     for (int i = 0; i < col_cnt; i++)
2245       rec.push_back(row.GetString(i));
2246
2247     result.push_back(std::move(rec));
2248   }
2249
2250   return PMINFO_R_OK;
2251 }
2252
2253 int GetPkgInfo(const tizen_base::Database& db,
2254     pkgmgrinfo_pkginfo_filter_h filter, uid_t uid,
2255     const std::string& locale,
2256     std::map<std::string, std::shared_ptr<package_x>>& pkginfo_list) {
2257   if (!static_cast<bool>(db) || filter == nullptr) {
2258     LOGE("Invalid argument");
2259     return PMINFO_R_EINVAL;
2260   }
2261
2262   int ret = DoGetPkgInfo(db, uid, locale, (pkgmgrinfo_filter_x*)filter,
2263       PMINFO_PKGINFO_GET_ALL, pkginfo_list);
2264   return ret;
2265 }
2266
2267 int GetDependsOn(const tizen_base::Database& db, const std::string& pkgid,
2268     std::vector<dependency_x*>& dep_list) {
2269   if (!static_cast<bool>(db) || pkgid.empty()) {
2270     LOGE("Invalid parameter");
2271     return PMINFO_R_EINVAL;
2272   }
2273
2274   std::queue<std::string> queue;
2275   std::set<std::string> dup_checker;
2276
2277   queue.push(pkgid);
2278   while (!queue.empty()) {
2279     auto item = queue.front();
2280     queue.pop();
2281     int ret = DoGetDependsOn(db, item, queue, dup_checker, dep_list);
2282     if (ret != PMINFO_R_OK) {
2283       LOGE("failed to get pkgs depends on %s", pkgid.c_str());
2284       for (auto i : dep_list)
2285         __free_depends_on(i);
2286       return PMINFO_R_ERROR;
2287     }
2288   }
2289
2290   return PMINFO_R_OK;
2291 }
2292
2293 }  // namespace pkgmgr_server::internal