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