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