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