2 * Copyright (c) 2021 Samsung Electronics Co., Ltd.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "manager/pkginfo_manager.h"
19 #include <sys/types.h>
26 #include "pkgmgrinfo_private.h"
29 #include "common/parcel/appinfo_parcelable.hh"
30 #include "common/parcel/filter_parcelable.hh"
31 #include "common/parcel/pkginfo_parcelable.hh"
32 #include "common/parcel/query_parcelable.hh"
33 #include "common/parcel/result_parcelable.hh"
35 #include "client/pkginfo_client.hh"
42 #define LOG_TAG "PKGMGR_INFO"
47 #define EXPORT_API __attribute__((visibility("default")))
49 extern "C" EXPORT_API int _pkginfo_get_packages(uid_t uid,
50 pkgmgrinfo_filter_x *filter, int flag, GHashTable *packages) {
51 std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcelable(
52 new pkgmgr_common::parcel::FilterParcelable(uid,
53 static_cast<pkgmgrinfo_filter_x*>(filter), flag));
55 pkgmgr_client::PkgInfoClient client(parcelable, uid,
56 pkgmgr_common::ReqType::GET_PKG_INFO);
57 if (!client.SendRequest())
58 return PMINFO_R_ERROR;
60 std::shared_ptr<pkgmgr_common::parcel::PkgInfoParcelable> return_parcel(
61 std::static_pointer_cast<pkgmgr_common::parcel::PkgInfoParcelable>(
62 client.GetResultParcel()));
64 tizen_base::Parcel parcel;
65 parcel.ReadParcelable(return_parcel.get());
67 auto result_list = return_parcel->GetPkgInfo();
68 // TODO: check noentry error has returned if size of result_list is 0
69 for (auto& pkginfo : result_list)
70 g_hash_table_insert(packages, (gpointer)pkginfo->package,
76 // TODO: Need to add target db uid to identify which database to be searched
77 extern "C" EXPORT_API int _appinfo_get_applications(uid_t db_uid, uid_t uid,
78 pkgmgrinfo_filter_x *filter, int flag, GHashTable *packages) {
79 std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcelable(
80 new pkgmgr_common::parcel::FilterParcelable(uid,
81 static_cast<pkgmgrinfo_filter_x*>(filter), flag));
83 pkgmgr_client::PkgInfoClient client(parcelable, uid, pkgmgr_common::ReqType::GET_APP_INFO);
84 if (!client.SendRequest())
85 return PMINFO_R_ERROR;
87 std::shared_ptr<pkgmgr_common::parcel::AppInfoParcelable> return_parcel(
88 std::static_pointer_cast<pkgmgr_common::parcel::AppInfoParcelable>(
89 client.GetResultParcel()));
91 tizen_base::Parcel parcel;
92 parcel.ReadParcelable(return_parcel.get());
93 auto result_list = return_parcel->GetAppInfo();
94 for (auto& appinfo : result_list)
95 g_hash_table_insert(packages, (gpointer)appinfo->appid,
101 extern "C" EXPORT_API char *_appinfo_get_localed_label(
102 const char *appid, const char *locale, uid_t uid) {
103 char *query = nullptr;
104 query = sqlite3_mprintf(
105 "SELECT COALESCE((SELECT app_label FROM package_app_localized_info "
106 "WHERE app_id=%Q AND app_locale=%Q),"
107 "(SELECT app_label FROM package_app_localized_info WHERE "
108 "app_id=%Q AND app_locale='No Locale'))", appid, locale, appid);
109 if (query == nullptr) {
110 LOG(ERROR) << "Out of memory";
114 std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcelable(
115 new pkgmgr_common::parcel::QueryParcelable(uid, std::string(query)));
117 pkgmgr_client::PkgInfoClient client(parcelable, uid,
118 pkgmgr_common::ReqType::QUERY);
119 if (!client.SendRequest()) {
124 std::shared_ptr<pkgmgr_common::parcel::ResultParcelable> return_parcel(
125 std::static_pointer_cast<pkgmgr_common::parcel::ResultParcelable>(
126 client.GetResultParcel()));
127 tizen_base::Parcel parcel;
128 parcel.ReadParcelable(return_parcel.get());
130 // result_list is vector of string vector
131 char *label = nullptr;
132 auto result_list = return_parcel->GetResult();
133 for (auto result : result_list) {
134 // result is string vector
135 // it only has one string or not.
136 if (result.front().empty() || result.front().length() == 0)
138 label = strdup(result.front().c_str());
139 if (label == nullptr) {
140 LOG(ERROR) << "Out of memory";
149 extern "C" EXPORT_API int _appinfo_get_datacontrol_info(
150 const char *providerid, const char *type, uid_t uid,
151 char **appid, char **access) {
152 char *query = nullptr;
153 query = sqlite3_mprintf("SELECT app_id, access FROM "
154 "package_app_data_control WHERE "
155 "providerid=%Q AND type=%Q", providerid, type);
156 if (query == nullptr) {
157 LOG(ERROR) << "Out of memory";
158 return PMINFO_R_ERROR;
161 std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcelable(
162 new pkgmgr_common::parcel::QueryParcelable(uid, std::string(query)));
164 pkgmgr_client::PkgInfoClient client(parcelable, uid,
165 pkgmgr_common::ReqType::QUERY);
166 if (!client.SendRequest()) {
168 return PMINFO_R_ERROR;
171 std::shared_ptr<pkgmgr_common::parcel::ResultParcelable> return_parcel(
172 std::static_pointer_cast<pkgmgr_common::parcel::ResultParcelable>(
173 client.GetResultParcel()));
174 tizen_base::Parcel parcel;
175 parcel.ReadParcelable(return_parcel.get());
177 // result_list is vector of string vector
178 auto result_list = return_parcel->GetResult();
179 if (result_list.size() == 0)
180 return PMINFO_R_ENOENT;
181 for (auto result : result_list) {
182 if (result.size() != 2)
183 return PMINFO_R_ERROR;
184 if (result.front().empty() || result.front().size() == 0 ||
185 result.back().empty() || result.back().size() == 0)
186 return PMINFO_R_ERROR;
187 *appid = strdup(result.front().c_str());
188 *access = strdup(result.back().c_str());
189 if (*appid == nullptr || *access == nullptr) {
190 LOG(ERROR) << "Out of memory";
191 return PMINFO_R_ERROR;
198 extern "C" EXPORT_API int _appinfo_get_datacontrol_appid(
199 const char *providerid, uid_t uid, char **appid) {
200 char *query = nullptr;
202 query = sqlite3_mprintf("SELECT app_id FROM package_app_data_control "
203 "WHERE providerid=%Q", providerid);
205 LOGE("Out of memory");
206 return PMINFO_R_ERROR;
208 std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcelable(
209 new pkgmgr_common::parcel::QueryParcelable(uid, std::string(query)));
211 pkgmgr_client::PkgInfoClient client(parcelable, uid,
212 pkgmgr_common::ReqType::QUERY);
213 if (!client.SendRequest()) {
215 return PMINFO_R_ERROR;
217 // TODO: deliver rawdata to reqhandler directly if server is not working
219 std::shared_ptr<pkgmgr_common::parcel::ResultParcelable> return_parcel(
220 std::static_pointer_cast<pkgmgr_common::parcel::ResultParcelable>(
221 client.GetResultParcel()));
222 tizen_base::Parcel parcel;
223 parcel.ReadParcelable(return_parcel.get());
226 // result_list is vector of string vector
227 auto result_list = return_parcel->GetResult();
228 if (result_list.size() == 0)
229 return PMINFO_R_ENOENT;
230 for (auto result : result_list) {
231 if (result.size() != 1)
232 return PMINFO_R_ERROR;
233 if (result.front().empty() || result.front().size() == 0)
234 return PMINFO_R_ERROR;
235 *appid = strdup(result.front().c_str());
236 if (*appid == nullptr) {
237 LOG(ERROR) << "Out of memory";
238 return PMINFO_R_ERROR;
245 extern "C" EXPORT_API int _appinfo_get_datacontrol_trusted_info(
246 const char *providerid, const char *type, uid_t uid,
247 char **appid, char **trusted) {
248 char *query = nullptr;
249 query = sqlite3_mprintf(
250 "SELECT app_id, trusted FROM package_app_data_control "
251 "WHERE providerid=%Q AND type=%Q", providerid, type);
253 LOGE("Out of memory");
254 return PMINFO_R_ERROR;
257 std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcelable(
258 new pkgmgr_common::parcel::QueryParcelable(uid, std::string(query)));
260 pkgmgr_client::PkgInfoClient client(parcelable, uid,
261 pkgmgr_common::ReqType::QUERY);
262 if (!client.SendRequest()) {
264 return PMINFO_R_ERROR;
266 // TODO: deliver rawdata to reqhandler directly if server is not working
268 std::shared_ptr<pkgmgr_common::parcel::ResultParcelable> return_parcel(
269 std::static_pointer_cast<pkgmgr_common::parcel::ResultParcelable>(
270 client.GetResultParcel()));
271 tizen_base::Parcel parcel;
272 parcel.ReadParcelable(return_parcel.get());
274 // result_list is vector of string vector
275 auto result_list = return_parcel->GetResult();
276 if (result_list.size() == 0)
277 return PMINFO_R_ENOENT;
278 for (auto result : result_list) {
279 if (result.size() != 2)
280 return PMINFO_R_ERROR;
281 if (result.front().empty() || result.front().size() == 0 ||
282 result.back().empty() || result.back().size() == 0)
283 return PMINFO_R_ERROR;
284 *appid = strdup(result.front().c_str());
285 *trusted = strdup(result.back().c_str());
286 if (*appid == nullptr || *trusted == nullptr) {
287 LOG(ERROR) << "Out of memory";
288 return PMINFO_R_ERROR;
295 extern "C" EXPORT_API int _appinfo_get_datacontrol_privileges(
296 const char *providerid, const char *type, uid_t uid,
297 GList **privileges) {
298 char *query = nullptr;
299 query = sqlite3_mprintf(
300 "SELECT privilege FROM package_app_data_control_privilege "
301 "WHERE providerid=%Q AND type=%Q", providerid, type);
303 LOGE("Out of memory");
304 return PMINFO_R_ERROR;
307 std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcelable(
308 new pkgmgr_common::parcel::QueryParcelable(uid, std::string(query)));
310 pkgmgr_client::PkgInfoClient client(parcelable, uid,
311 pkgmgr_common::ReqType::QUERY);
312 if (!client.SendRequest()) {
314 return PMINFO_R_ERROR;
316 // TODO: deliver rawdata to reqhandler directly if server is not working
318 std::shared_ptr<pkgmgr_common::parcel::ResultParcelable> return_parcel(
319 std::static_pointer_cast<pkgmgr_common::parcel::ResultParcelable>(
320 client.GetResultParcel()));
321 tizen_base::Parcel parcel;
322 parcel.ReadParcelable(return_parcel.get());
324 // result_list is vector of string vector
325 auto result_list = return_parcel->GetResult();
326 if (result_list.size() == 0)
327 return PMINFO_R_ENOENT;
329 for (auto result : result_list) {
330 if (result.size() != 1)
331 return PMINFO_R_ERROR;
332 if (result.front().empty() || result.front().size() == 0)
333 return PMINFO_R_ERROR;
334 char *privilege = strdup(result.front().c_str());
335 if (privilege == nullptr) {
336 LOG(ERROR) << "Out of memory";
337 return PMINFO_R_ERROR;
339 *privileges = g_list_append(*privileges, privilege);
345 extern "C" EXPORT_API int _appinfo_get_appcontrol_privileges(
346 const char *appid, const char *operation, uid_t uid, GList **privileges) {
347 char *query = nullptr;
348 query = sqlite3_mprintf(
349 "SELECT app_control, privilege FROM package_app_app_control_privilege "
350 "WHERE app_id=%Q", appid);
352 LOG(ERROR) << "Out of memory";
353 return PMINFO_R_ERROR;
356 std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcelable(
357 new pkgmgr_common::parcel::QueryParcelable(uid, std::string(query)));
359 pkgmgr_client::PkgInfoClient client(parcelable, uid,
360 pkgmgr_common::ReqType::QUERY);
361 if (!client.SendRequest()) {
363 return PMINFO_R_ERROR;
365 // TODO: deliver rawdata to reqhandler directly if server is not working
367 std::shared_ptr<pkgmgr_common::parcel::ResultParcelable> return_parcel(
368 std::static_pointer_cast<pkgmgr_common::parcel::ResultParcelable>(
369 client.GetResultParcel()));
370 tizen_base::Parcel parcel;
371 parcel.ReadParcelable(return_parcel.get());
373 // result_list is vector of string vector
374 auto result_list = return_parcel->GetResult();
375 if (result_list.size() == 0)
376 return PMINFO_R_ENOENT;
378 for (auto result : result_list) {
379 if (result.size() != 2)
380 return PMINFO_R_ERROR;
381 if (result.front().empty() || result.front().size() == 0 ||
382 result.back().empty() || result.back().size() == 0)
383 return PMINFO_R_ERROR;
384 std::string app_control = result.front();
385 std::stringstream ss(app_control);
387 while (std::getline(ss, token, '|')) {
388 if (token.compare(std::string(operation))) {
389 char *privilege = strdup(result.back().c_str());
390 if (privilege == nullptr) {
391 LOG(ERROR) << "Out of memory";
392 return PMINFO_R_ERROR;
394 *privileges = g_list_append(*privileges, privilege);
401 extern "C" EXPORT_API int _plugininfo_get_appids(
402 const char *pkgid, const char *plugin_type,
403 const char *plugin_name, GList **list) {
404 if (!pkgid || !plugin_type || !plugin_name || !list) {
405 LOG(ERROR) << "Invalid parameter";
406 return PMINFO_R_EINVAL;
409 char *query = nullptr;
410 query = sqlite3_mprintf(
412 "package_plugin_info WHERE pkgid=%Q AND "
413 "plugin_type=%Q AND plugin_name=%Q",
414 pkgid, plugin_type, plugin_name);
416 LOG(ERROR) << "Out of memory";
417 return PMINFO_R_ERROR;
420 std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcelable(
421 new pkgmgr_common::parcel::QueryParcelable(_getuid(), std::string(query)));
424 pkgmgr_client::PkgInfoClient client(parcelable, _getuid(),
425 pkgmgr_common::ReqType::QUERY);
426 if (!client.SendRequest()) {
427 return PMINFO_R_ERROR;
430 std::shared_ptr<pkgmgr_common::parcel::ResultParcelable> return_parcel(
431 std::static_pointer_cast<pkgmgr_common::parcel::ResultParcelable>(
432 client.GetResultParcel()));
433 if (return_parcel->GetCol() != 1) {
434 LOG(ERROR) << "Invalid result";
435 return PMINFO_R_ERROR;
437 // result_list is vector of string vector
438 auto result_list = return_parcel->GetResult();
439 if (result_list.size() == 0)
440 return PMINFO_R_ENOENT;
442 for (auto result : result_list) {
443 if (result.size() != 1) {
444 LOG(ERROR) << "Invalid result";
445 g_list_free_full(*list, free);
446 return PMINFO_R_ERROR;
448 *list = g_list_append(*list, strdup(result[0].c_str()));
454 static int __convert_update_type(const char *type, pkgmgrinfo_updateinfo_update_type *convert_type)
456 if (strncasecmp(type, PMINFO_UPDATEINFO_TYPE_NONE,
457 strlen(PMINFO_UPDATEINFO_TYPE_NONE)) == 0)
458 *convert_type = PMINFO_UPDATEINFO_NONE;
459 else if (strncasecmp(type, PMINFO_UPDATEINFO_TYPE_FORCE,
460 strlen(PMINFO_UPDATEINFO_TYPE_FORCE)) == 0)
461 *convert_type = PMINFO_UPDATEINFO_FORCE;
462 else if (strncasecmp(type, PMINFO_UPDATEINFO_TYPE_OPTIONAL,
463 strlen(PMINFO_UPDATEINFO_TYPE_OPTIONAL)) == 0)
464 *convert_type = PMINFO_UPDATEINFO_OPTIONAL;
470 static void __free_update_info(gpointer data)
472 updateinfo_x *update_info = (updateinfo_x *)data;
473 if (update_info == NULL)
476 if (update_info->pkgid)
477 free((void *)update_info->pkgid);
478 if (update_info->version)
479 free((void *)update_info->version);
480 free((void *)update_info);
484 extern "C" EXPORT_API int _get_pkg_updateinfo(const char *pkgid,
485 GSList **update_info_list, uid_t uid)
487 char *query = nullptr;
491 query = sqlite3_mprintf(
492 "SELECT package, update_version, update_type "
493 "FROM package_update_info");
495 query = sqlite3_mprintf(
496 "SELECT package, update_version, update_type "
497 "FROM package_update_info WHERE package=%Q",
500 LOG(ERROR) << "Out of memory";
501 return PMINFO_R_ERROR;
504 std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcelable(
505 new pkgmgr_common::parcel::QueryParcelable(uid, std::string(query)));
508 pkgmgr_client::PkgInfoClient client(parcelable, uid,
509 pkgmgr_common::ReqType::QUERY);
510 if (!client.SendRequest()) {
511 return PMINFO_R_ERROR;
514 std::shared_ptr<pkgmgr_common::parcel::ResultParcelable> return_parcel(
515 std::static_pointer_cast<pkgmgr_common::parcel::ResultParcelable>(
516 client.GetResultParcel()));
517 if (return_parcel->GetCol() != 3) {
518 LOG(ERROR) << "Invalid result";
519 return PMINFO_R_ERROR;
522 auto result_list = return_parcel->GetResult();
523 if (result_list.size() == 0)
524 return PMINFO_R_ENOENT;
526 for (auto result : result_list) {
527 if (result.size() != 3) {
528 LOG(ERROR) << "Invalid result";
529 g_slist_free_full(*update_info_list, __free_update_info);
530 return PMINFO_R_ERROR;
532 updateinfo_x *update_info = reinterpret_cast<updateinfo_x *>(calloc(1, sizeof(updateinfo_x)));
533 if (update_info == NULL) {
534 LOG(ERROR) << "Out of memory";
535 return PMINFO_R_ERROR;
537 update_info->pkgid = strdup(result[0].c_str());
538 update_info->version = strdup(result[1].c_str());
539 pkgmgrinfo_updateinfo_update_type convert_type;
540 ret = __convert_update_type(result[2].c_str(), &convert_type);
542 __free_update_info(update_info);
543 g_slist_free_full(*update_info_list, __free_update_info);
544 return PMINFO_R_ERROR;
546 update_info->type = static_cast<int>(convert_type);
547 *update_info_list = g_slist_prepend(*update_info_list,