Fix build error
[platform/core/appfw/pkgmgr-info.git] / src / pkginfo_internal.c
1 // copyright
2
3 #define _GNU_SOURCE
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <stdbool.h>
8 #include <unistd.h>
9 #include <ctype.h>
10 #include <sys/smack.h>
11 #include <linux/limits.h>
12 #include <libgen.h>
13 #include <sys/stat.h>
14
15 #include <sqlite3.h>
16 #include <glib.h>
17
18 #include "pkgmgrinfo_basic.h"
19 #include "pkgmgrinfo_private.h"
20 #include "pkgmgrinfo_debug.h"
21 #include "pkgmgr-info.h"
22
23 static void __free_packages(gpointer data)
24 {
25         pkgmgrinfo_basic_free_package((package_x *)data);
26 }
27
28 static const char join_localized_info[] =
29         " LEFT OUTER JOIN package_localized_info"
30         "  ON pi.package=package_localized_info.package"
31         "  AND package_localized_info.package_locale=?";
32 static const char join_privilege_info[] =
33         " LEFT OUTER JOIN package_privilege_info"
34         "  ON pi.package=package_privilege_info.package";
35
36 static int _get_filtered_query(pkgmgrinfo_filter_x *filter,
37                 const char *locale, uid_t uid, char **query, GList **bind_params)
38 {
39         int joined = 0;
40         int size;
41         char buf[MAX_QUERY_LEN] = { '\0' };
42         char buf2[MAX_QUERY_LEN] = { '\0' };
43         char *condition = NULL;
44         GSList *list = NULL;
45
46         if (filter == NULL)
47                 return PMINFO_R_OK;
48
49         snprintf(buf, sizeof(buf), "%s", " WHERE 1=1 ");
50         for (list = filter->list; list; list = list->next) {
51                 joined |= __get_filter_condition(list->data, uid, &condition,
52                                 bind_params);
53                 if (condition == NULL)
54                         continue;
55
56                 strncat(buf, " AND ", sizeof(buf) - strlen(buf) - 1);
57
58                 strncat(buf, condition, sizeof(buf) - strlen(buf) - 1);
59                 free(condition);
60                 condition = NULL;
61         }
62
63         if (joined & E_PMINFO_PKGINFO_JOIN_LOCALIZED_INFO) {
64                 strncat(buf2, join_localized_info, sizeof(buf2) - strlen(buf2) - 1);
65                 *bind_params = g_list_append(*bind_params, strdup(locale));
66         }
67         if (joined & E_PMINFO_PKGINFO_JOIN_PRIVILEGE_INFO)
68                 strncat(buf2, join_privilege_info, sizeof(buf2) - strlen(buf2) - 1);
69
70         size = strlen(buf2) + strlen(buf) + 1;
71         *query = (char *)calloc(1, size);
72         if (*query == NULL)
73                 return PMINFO_R_ERROR;
74         snprintf(*query, size, "%s%s", buf2, buf);
75
76         return PMINFO_R_OK;
77 }
78
79 static int __bind_params(sqlite3_stmt *stmt, GList *params)
80 {
81         GList *tmp_list = NULL;
82         int idx = 0;
83         int ret;
84
85         if (stmt == NULL || params == NULL)
86                 return PMINFO_R_EINVAL;
87
88         tmp_list = params;
89         while (tmp_list) {
90                 ret = sqlite3_bind_text(stmt, ++idx, (char *)tmp_list->data, -1, SQLITE_STATIC);
91                 if (ret != SQLITE_OK)
92                         return PMINFO_R_ERROR;
93                 tmp_list = tmp_list->next;
94         }
95
96         return PMINFO_R_OK;
97 }
98
99 static bool __check_package_storage_status(pkgmgrinfo_filter_x *tmp_filter)
100 {
101         GSList *tmp_list = NULL;
102         pkgmgrinfo_node_x *tmp_node = NULL;
103         int property = -1;
104
105         property = _pminfo_pkginfo_convert_to_prop_bool(PMINFO_PKGINFO_PROP_PACKAGE_CHECK_STORAGE);
106         for (tmp_list = tmp_filter->list; tmp_list != NULL;
107                         tmp_list = g_slist_next(tmp_list)) {
108                 tmp_node = (pkgmgrinfo_node_x *)tmp_list->data;
109                 if (property == tmp_node->prop) {
110                         if (strcmp(tmp_node->value, "true") == 0)
111                                 return true;
112                         else
113                                 return false;
114                 }
115         }
116         return true;
117 }
118
119 static int _pkginfo_add_description_info_into_list(const char *locale,
120                 char *record, GList **description)
121 {
122         description_x *info;
123
124         info = calloc(1, sizeof(description_x));
125         if (info == NULL) {
126                 LOGE("out of memory");
127                 return PMINFO_R_ERROR;
128         }
129         info->lang = strdup(locale);
130         info->text = record;
131         *description = g_list_prepend(*description, info);
132
133         return PMINFO_R_OK;
134 }
135
136 static int _pkginfo_get_plugin_execution_info(sqlite3 *db, const char *pkgid,
137                 GList **plugins)
138 {
139         static const char query_raw[] =
140                 "SELECT appid, plugin_type, plugin_name FROM package_plugin_info "
141                 "WHERE pkgid=%Q";
142         int ret;
143         char *query;
144         sqlite3_stmt *stmt;
145         plugin_x *plugin;
146
147         query = sqlite3_mprintf(query_raw, pkgid);
148         if (query == NULL) {
149                 LOGE("out of memory");
150                 return PMINFO_R_ERROR;
151         }
152
153         ret = sqlite3_prepare_v2(db, query, strlen(query),
154                         &stmt, NULL);
155         sqlite3_free(query);
156         if (ret != SQLITE_OK) {
157                 LOGE("prepare failed: %s", sqlite3_errmsg(db));
158                 return PMINFO_R_ERROR;
159         }
160
161         while (sqlite3_step(stmt) == SQLITE_ROW) {
162                 plugin = calloc(1, sizeof(plugin_x));
163                 if (!plugin) {
164                         LOGE("out of memory");
165                         sqlite3_finalize(stmt);
166                         return PMINFO_R_ERROR;
167                 }
168                 plugin->pkgid = strdup(pkgid);
169                 _save_column_str(stmt, 0, &plugin->appid);
170                 _save_column_str(stmt, 1, &plugin->plugin_type);
171                 _save_column_str(stmt, 2, &plugin->plugin_name);
172                 *plugins = g_list_prepend(*plugins,
173                                 (gpointer)plugin);
174         }
175
176         sqlite3_finalize(stmt);
177
178         return PMINFO_R_OK;
179 }
180
181 static int _pkginfo_get_privilege(sqlite3 *db, const char *pkgid,
182                 GList **privileges)
183 {
184         static const char query_raw[] =
185                 "SELECT DISTINCT privilege, type FROM package_privilege_info "
186                 "WHERE package=%Q";
187         int ret;
188         char *query;
189         sqlite3_stmt *stmt;
190         privilege_x *privilege;
191
192         query = sqlite3_mprintf(query_raw, pkgid);
193         if (query == NULL) {
194                 LOGE("out of memory");
195                 return PMINFO_R_ERROR;
196         }
197
198         ret = sqlite3_prepare_v2(db, query, strlen(query),
199                         &stmt, NULL);
200         sqlite3_free(query);
201         if (ret != SQLITE_OK) {
202                 LOGE("prepare failed: %s", sqlite3_errmsg(db));
203                 return PMINFO_R_ERROR;
204         }
205
206         while (sqlite3_step(stmt) == SQLITE_ROW) {
207                 privilege = calloc(1, sizeof(privilege_x));
208                 if (!privilege) {
209                         LOGE("failed to alloc memory");
210                         sqlite3_finalize(stmt);
211                         return PMINFO_R_ERROR;
212                 }
213                 _save_column_str(stmt, 0, &privilege->value);
214                 _save_column_str(stmt, 1, &privilege->type);
215                 *privileges = g_list_prepend(*privileges,
216                                 (gpointer)privilege);
217         }
218
219         sqlite3_finalize(stmt);
220
221         return PMINFO_R_OK;
222 }
223
224 static int _pkginfo_get_appdefined_privilege(sqlite3 *db, const char *pkgid,
225                 GList **privileges)
226 {
227         static const char query_raw[] =
228                 "SELECT DISTINCT privilege, license, type FROM "
229                 "package_appdefined_privilege_info WHERE package=%Q";
230         int ret;
231         char *query;
232         sqlite3_stmt *stmt;
233         appdefined_privilege_x *privilege;
234
235         query = sqlite3_mprintf(query_raw, pkgid);
236         if (query == NULL) {
237                 LOGE("out of memory");
238                 return PMINFO_R_ERROR;
239         }
240
241         ret = sqlite3_prepare_v2(db, query, strlen(query),
242                         &stmt, NULL);
243         sqlite3_free(query);
244         if (ret != SQLITE_OK) {
245                 LOGE("prepare failed: %s", sqlite3_errmsg(db));
246                 return PMINFO_R_ERROR;
247         }
248
249         while (sqlite3_step(stmt) == SQLITE_ROW) {
250                 privilege = calloc(1, sizeof(appdefined_privilege_x));
251                 if (!privilege) {
252                         LOGE("failed to alloc memory");
253                         sqlite3_finalize(stmt);
254                         return PMINFO_R_ERROR;
255                 }
256                 _save_column_str(stmt, 0, &privilege->value);
257                 _save_column_str(stmt, 1, &privilege->license);
258                 _save_column_str(stmt, 2, &privilege->type);
259                 *privileges = g_list_prepend(*privileges,
260                                 (gpointer)privilege);
261         }
262
263         sqlite3_finalize(stmt);
264
265         return PMINFO_R_OK;
266 }
267
268 static int _pkginfo_get_dependency(sqlite3 *db, const char *pkgid,
269                 GList **dependencies)
270 {
271         static const char query_raw[] =
272                 "SELECT DISTINCT depends_on, type, required_version "
273                 "FROM package_dependency_info WHERE package=%Q";
274         int ret;
275         char *query;
276         sqlite3_stmt *stmt;
277         dependency_x *dependency;
278
279         query = sqlite3_mprintf(query_raw, pkgid);
280         if (query == NULL) {
281                 LOGE("out of memory");
282                 return PMINFO_R_ERROR;
283         }
284
285         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
286         sqlite3_free(query);
287         if (ret != SQLITE_OK) {
288                 LOGE("prepare failed: %s", sqlite3_errmsg(db));
289                 return PMINFO_R_ERROR;
290         }
291
292         while (sqlite3_step(stmt) == SQLITE_ROW) {
293                 dependency = calloc(1, sizeof(dependency_x));
294                 if (!dependency) {
295                         LOGE("failed to alloc memory");
296                         sqlite3_finalize(stmt);
297                         return PMINFO_R_ERROR;
298                 }
299                 _save_column_str(stmt, 0, &dependency->depends_on);
300                 _save_column_str(stmt, 1, &dependency->type);
301                 _save_column_str(stmt, 2, &dependency->required_version);
302                 *dependencies = g_list_prepend(*dependencies,
303                                 (gpointer)dependency);
304         }
305
306         sqlite3_finalize(stmt);
307
308         return PMINFO_R_OK;
309 }
310
311 static int _pkginfo_get_packages(sqlite3 *db, uid_t uid, const char *locale,
312                 pkgmgrinfo_filter_x *filter, int flag, GHashTable *packages)
313 {
314         static const char query_raw[] =
315                 "SELECT DISTINCT pi.package, pi.installed_storage, pi.external_path";
316         static const char query_basic[] =
317                 ", pi.package_version, pi.install_location, "
318                 "pi.package_removable, pi.package_preload, pi.package_readonly, "
319                 "pi.package_update, pi.package_appsetting, pi.package_system, "
320                 "pi.package_type, pi.package_size, pi.installed_time, "
321                 "pi.storeclient_id, pi.mainapp_id, pi.package_url, pi.root_path, "
322                 "pi.csc_path, pi.package_nodisplay, pi.package_api_version, "
323                 "pi.package_support_disable, pi.package_tep_name, "
324                 "pi.package_zip_mount_file, pi.package_support_mode";
325         static const char query_author[] =
326                 ", pi.author_name, pi.author_email, pi.author_href";
327         static const char query_label[] =
328                 ", COALESCE("
329                 "(SELECT package_label FROM package_localized_info WHERE pi.package=package AND package_locale=?), "
330                 "(SELECT package_label FROM package_localized_info WHERE pi.package=package AND package_locale='No Locale'))";
331         static const char query_icon[] =
332                 ", COALESCE("
333                 "(SELECT package_icon FROM package_localized_info WHERE pi.package=package AND package_locale=?), "
334                 "(SELECT package_icon FROM package_localized_info WHERE pi.package=package AND package_locale='No Locale'))";
335         static const char query_description[] =
336                 ", COALESCE("
337                 "(SELECT package_description FROM package_localized_info WHERE pi.package=package AND package_locale=?), "
338                 "(SELECT package_description FROM package_localized_info WHERE pi.package=package AND package_locale='No Locale'))";
339         static const char query_from_clause[] = " FROM package_info as pi";
340         int ret = PMINFO_R_ERROR;
341         int idx = 0;
342         //char *dbpath;
343         char *tmp_record = NULL;
344         char *constraints = NULL;
345         char query[MAX_QUERY_LEN] = { '\0' };
346         package_x *info = NULL;
347         author_x *author = NULL;
348         GList *bind_params = NULL;
349         //sqlite3 *db;
350         sqlite3_stmt *stmt = NULL;
351         bool is_check_storage = true;
352         const uid_t global_user_uid = GLOBAL_USER;
353 #if 0
354         dbpath = getUserPkgParserDBPathUID(uid);
355         if (dbpath == NULL)
356                 return PMINFO_R_ERROR;
357
358         ret = __open_db(dbpath, &db, SQLITE_OPEN_READONLY);
359         if (ret != SQLITE_OK) {
360                 _LOGD("failed to open db(%s): %d", dbpath, ret);
361                 free(dbpath);
362                 return PMINFO_R_ERROR;
363         }
364         free(dbpath);
365 #endif
366         is_check_storage = __check_package_storage_status(filter);
367
368         snprintf(query, MAX_QUERY_LEN - 1, "%s", query_raw);
369         if (flag & PMINFO_APPINFO_GET_BASICINFO)
370                 strncat(query, query_basic, sizeof(query) - strlen(query) - 1);
371         if (flag & PMINFO_PKGINFO_GET_AUTHOR)
372                 strncat(query, query_author, sizeof(query) - strlen(query) - 1);
373         if (flag & PMINFO_PKGINFO_GET_LABEL) {
374                 strncat(query, query_label, sizeof(query) - strlen(query) - 1);
375                 bind_params = g_list_append(bind_params, strdup(locale));
376         }
377         if (flag & PMINFO_PKGINFO_GET_ICON) {
378                 strncat(query, query_icon, sizeof(query) - strlen(query) - 1);
379                 bind_params = g_list_append(bind_params, strdup(locale));
380         }
381         if (flag & PMINFO_PKGINFO_GET_DESCRIPTION) {
382                 strncat(query, query_description, sizeof(query) - strlen(query) - 1);
383                 bind_params = g_list_append(bind_params, strdup(locale));
384         }
385
386         strncat(query, query_from_clause, sizeof(query) - strlen(query) - 1);
387
388         ret = _get_filtered_query(filter, locale, uid, &constraints, &bind_params);
389         if (ret != PMINFO_R_OK) {
390                 LOGE("Failed to get WHERE clause");
391                 goto catch;
392         }
393
394         if (constraints)
395                 strncat(query, constraints, sizeof(query) - strlen(query) - 1);
396
397         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
398         if (ret != SQLITE_OK) {
399                 LOGE("prepare failed: %s", sqlite3_errmsg(db));
400                 ret = PMINFO_R_ERROR;
401                 goto catch;
402         }
403
404         ret = __bind_params(stmt, bind_params);
405         if (ret != SQLITE_OK) {
406                 LOGE("Failed to bind parameters");
407                 goto catch;
408         }
409
410         while (sqlite3_step(stmt) == SQLITE_ROW) {
411                 info = calloc(1, sizeof(package_x));
412                 if (info == NULL) {
413                         LOGE("out of memory");
414                         ret = PMINFO_R_ERROR;
415                         goto catch;
416                 }
417                 idx = 0;
418                 _save_column_str(stmt, idx++, &info->package);
419                 _save_column_str(stmt, idx++, &info->installed_storage);
420                 _save_column_str(stmt, idx++, &info->external_path);
421
422                 if (flag & PMINFO_APPINFO_GET_BASICINFO) {
423                         _save_column_str(stmt, idx++, &info->version);
424                         _save_column_str(stmt, idx++, &info->installlocation);
425                         _save_column_str(stmt, idx++, &info->removable);
426                         _save_column_str(stmt, idx++, &info->preload);
427                         _save_column_str(stmt, idx++, &info->readonly);
428                         _save_column_str(stmt, idx++, &info->update);
429                         _save_column_str(stmt, idx++, &info->appsetting);
430                         _save_column_str(stmt, idx++, &info->system);
431                         _save_column_str(stmt, idx++, &info->type);
432                         _save_column_str(stmt, idx++, &info->package_size);
433                         _save_column_str(stmt, idx++, &info->installed_time);
434                         _save_column_str(stmt, idx++, &info->storeclient_id);
435                         _save_column_str(stmt, idx++, &info->mainapp_id);
436                         _save_column_str(stmt, idx++, &info->package_url);
437                         _save_column_str(stmt, idx++, &info->root_path);
438                         _save_column_str(stmt, idx++, &info->csc_path);
439                         _save_column_str(stmt, idx++, &info->nodisplay_setting);
440                         _save_column_str(stmt, idx++, &info->api_version);
441                         _save_column_str(stmt, idx++, &info->support_disable);
442                         _save_column_str(stmt, idx++, &info->tep_name);
443                         _save_column_str(stmt, idx++, &info->zip_mount_file);
444                         _save_column_str(stmt, idx++, &info->support_mode);
445                 }
446
447                 info->for_all_users =
448                         strdup((uid != global_user_uid) ? "false" : "true");
449
450                 if (_pkginfo_get_plugin_execution_info(db, info->package, &info->plugin)) {
451                         ret = PMINFO_R_ERROR;
452                         goto catch;
453                 }
454
455                 if (flag & PMINFO_PKGINFO_GET_AUTHOR) {
456                         /* TODO : author should be retrieved at package_localized_info */
457                         author = calloc(1, sizeof(author_x));
458                         if (author == NULL) {
459                                 ret = PMINFO_R_ERROR;
460                                 goto catch;
461                         }
462                         _save_column_str(stmt, idx++, &author->text);
463                         _save_column_str(stmt, idx++, &author->email);
464                         _save_column_str(stmt, idx++, &author->href);
465                         info->author = g_list_prepend(info->author, author);
466                 }
467
468                 if (flag & PMINFO_PKGINFO_GET_LABEL) {
469                         tmp_record = NULL;
470                         _save_column_str(stmt, idx++, &tmp_record);
471
472                         if (_add_label_info_into_list(locale, tmp_record, &info->label)) {
473                                 ret = PMINFO_R_ERROR;
474                                 goto catch;
475                         }
476                 }
477
478                 if (flag & PMINFO_PKGINFO_GET_ICON) {
479                         tmp_record = NULL;
480                         _save_column_str(stmt, idx++, &tmp_record);
481                         if (_add_icon_info_into_list(locale, tmp_record, &info->icon)) {
482                                 ret = PMINFO_R_ERROR;
483                                 goto catch;
484                         }
485                 }
486
487                 if (flag & PMINFO_PKGINFO_GET_DESCRIPTION) {
488                         tmp_record = NULL;
489                         _save_column_str(stmt, idx++, &tmp_record);
490                         if (_pkginfo_add_description_info_into_list(locale, tmp_record,
491                                         &info->description)) {
492                                 ret = PMINFO_R_ERROR;
493                                 goto catch;
494                         }
495                 }
496
497                 if (flag & PMINFO_PKGINFO_GET_PRIVILEGE) {
498                         if (_pkginfo_get_privilege(db, info->package,
499                                                 &info->privileges)) {
500                                 ret = PMINFO_R_ERROR;
501                                 goto catch;
502                         }
503                 }
504
505                 if (flag & PMINFO_PKGINFO_GET_APPDEFINED_PRIVILEGE) {
506                         if (_pkginfo_get_appdefined_privilege(db, info->package,
507                                                 &info->appdefined_privileges)) {
508                                 ret = PMINFO_R_ERROR;
509                                 goto catch;
510                         }
511                 }
512
513                 if (flag & PMINFO_PKGINFO_GET_DEPENDENCY) {
514                         if (_pkginfo_get_dependency(db, info->package,
515                                                 &info->dependencies)) {
516                                 ret = PMINFO_R_ERROR;
517                                 goto catch;
518                         }
519                 }
520
521                 if (is_check_storage &&
522                                 __pkginfo_check_installed_storage(info) != PMINFO_R_OK) {
523                         ret = PMINFO_R_ERROR;
524                         pkgmgrinfo_basic_free_package(info);
525                         info = NULL;
526                         continue;
527                 }
528
529                 g_hash_table_insert(packages, (gpointer)info->package,
530                                 (gpointer)info);
531         }
532
533         ret = PMINFO_R_OK;
534
535 catch:
536         sqlite3_finalize(stmt);
537
538         if (constraints)
539                 free(constraints);
540
541         if (ret != PMINFO_R_OK && info != NULL)
542                 pkgmgrinfo_basic_free_package(info);
543
544         g_list_free_full(bind_params, free);
545
546         return ret;
547 }
548
549 API int pkginfo_internal_filter_get_list(
550                 sqlite3 *db, pkgmgrinfo_pkginfo_filter_h filter,
551                 uid_t uid, const char *locale, GHashTable **pkginfo_list) {
552         GHashTable *list;
553         int ret;
554
555         if (filter == NULL || pkginfo_list == NULL) {
556                 // TODO: print error log
557                 return PMINFO_R_EINVAL;
558         }
559
560         list = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
561                         __free_packages);
562         if (list == NULL)
563                 return PMINFO_R_ERROR;
564
565         ret = _pkginfo_get_packages(db, uid, locale, filter,
566                         PMINFO_PKGINFO_GET_ALL, list);
567         if (ret == PMINFO_R_OK && uid != GLOBAL_USER)
568                 ret = _pkginfo_get_packages(db, GLOBAL_USER, locale, filter,
569                                 PMINFO_PKGINFO_GET_ALL, list);
570
571         if (ret != PMINFO_R_OK) {
572                 g_hash_table_destroy(list);
573                 return PMINFO_R_ERROR;
574         }
575
576         *pkginfo_list = list;
577         return PMINFO_R_OK;
578 }