Fix uid behavior on appinfo related functions
[platform/core/appfw/pkgmgr-info.git] / src / manager / pkginfo_manager.cc
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
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 "manager/pkginfo_manager.h"
18
19 #include <sys/types.h>
20
21 #include <sqlite3.h>
22 #include <glib.h>
23
24 #include <parcel.hh>
25
26 #include <map>
27 #include <string>
28 #include <vector>
29
30 #include "pkgmgr_parser.h"
31 #include "pkgmgrinfo_private.h"
32
33 #include "client/pkginfo_client.hh"
34 #include "common/database/abstract_db_handler.hh"
35 #include "common/database/pkg_set_db_handler.hh"
36 #include "common/parcel/appinfo_parcelable.hh"
37 #include "common/parcel/certinfo_parcelable.hh"
38 #include "common/parcel/command_parcelable.hh"
39 #include "common/parcel/depinfo_parcelable.hh"
40 #include "common/parcel/filter_parcelable.hh"
41 #include "common/parcel/pkginfo_parcelable.hh"
42 #include "common/parcel/query_parcelable.hh"
43 #include "common/parcel/result_parcelable.hh"
44 #include "logging.hh"
45
46
47 #ifdef LOG_TAG
48 #undef LOG_TAG
49 #endif
50 #define LOG_TAG "PKGMGR_INFO"
51
52 #ifdef EXPORT_API
53 #undef EXPORT_API
54 #endif
55 #define EXPORT_API __attribute__((visibility("default")))
56
57 namespace pcp = pkgmgr_common::parcel;
58 namespace pcd = pkgmgr_common::database;
59
60 extern "C" EXPORT_API int _pkginfo_get_packages(uid_t uid,
61     pkgmgrinfo_filter_x* filter, int flag, GHashTable* packages) {
62   std::shared_ptr<pcp::AbstractParcelable> parcelable(
63       new pcp::FilterParcelable(uid,
64           static_cast<pkgmgrinfo_filter_x*>(filter), flag, false));
65
66   pkgmgr_client::PkgInfoClient client(parcelable, uid,
67       pkgmgr_common::ReqType::GET_PKG_INFO);
68   if (!client.SendRequest())
69     return PMINFO_R_ERROR;
70
71   auto ptr = client.GetResultParcel();
72   if (ptr == nullptr) {
73     LOG(ERROR) << "Fail to get return parcelable";
74     return PMINFO_R_ERROR;
75   }
76
77   if (ptr->GetRequestResult() != PMINFO_R_OK) {
78     if (ptr->GetRequestResult() == PMINFO_R_ERROR)
79       LOG(ERROR) << "Request fail";
80     return ptr->GetRequestResult();
81   }
82
83   if (ptr->GetType() != pcp::ParcelableType::PkgInfo) {
84     LOG(ERROR) << "Invalid parcelable type";
85     return PMINFO_R_ERROR;
86   }
87
88   std::shared_ptr<pcp::PkgInfoParcelable> return_parcel(
89       std::static_pointer_cast<pcp::PkgInfoParcelable>(
90           ptr));
91
92   auto result_list = return_parcel->ExtractPkgInfo();
93   if (result_list.size() == 0) {
94     LOG(DEBUG) << "No packages meets given condition for user " << uid;
95     return PMINFO_R_ENOENT;
96   }
97   for (auto &pkginfo : result_list)
98     g_hash_table_insert(packages, (gpointer)pkginfo->package,
99                         (gpointer)pkginfo);
100
101   return PMINFO_R_OK;
102 }
103
104 extern "C" EXPORT_API int _pkginfo_get_depends_on(uid_t uid,
105     const char* pkgid, GList** dependencies) {
106   std::shared_ptr<pcp::AbstractParcelable> parcelable(
107       new pcp::DepInfoParcelable(std::string(pkgid)));
108
109   pkgmgr_client::PkgInfoClient client(parcelable, uid,
110       pkgmgr_common::ReqType::GET_PKG_DEP_INFO);
111   if (!client.SendRequest())
112     return PMINFO_R_ERROR;
113
114   auto ptr = client.GetResultParcel();
115   if (ptr == nullptr) {
116     LOG(ERROR) << "Fail to get return parcelable";
117     return PMINFO_R_ERROR;
118   }
119
120   if (ptr->GetRequestResult() != PMINFO_R_OK) {
121     LOG(ERROR) << "Request fail";
122     return ptr->GetRequestResult();
123   }
124
125   if (ptr->GetType() != pcp::ParcelableType::DepInfo) {
126     LOG(ERROR) << "Invalid parcelable type";
127     return PMINFO_R_ERROR;
128   }
129
130   std::shared_ptr<pcp::DepInfoParcelable> return_parcel(
131       std::static_pointer_cast<pcp::DepInfoParcelable>(ptr));
132
133   auto dependency_list = return_parcel->ExtractDependencyInfo();
134   for (auto &dependency : dependency_list)
135     *dependencies = g_list_prepend(*dependencies, dependency);
136   return PMINFO_R_OK;
137 }
138
139 extern "C" EXPORT_API int _appinfo_get_applications(uid_t uid,
140     pkgmgrinfo_filter_x* filter, int flag, GHashTable* packages) {
141   std::shared_ptr<pcp::AbstractParcelable> parcelable(
142       new pcp::FilterParcelable(uid,
143           static_cast<pkgmgrinfo_filter_x*>(filter), flag, false));
144
145   pkgmgr_client::PkgInfoClient client(
146       parcelable, uid, pkgmgr_common::ReqType::GET_APP_INFO);
147   if (!client.SendRequest())
148     return PMINFO_R_ERROR;
149
150   auto ptr = client.GetResultParcel();
151   if (ptr == nullptr) {
152     LOG(ERROR) << "Fail to get return parcelable";
153     return PMINFO_R_ERROR;
154   }
155
156   int ret = ptr->GetRequestResult();
157   if (ret != PMINFO_R_OK) {
158     if (ret == PMINFO_R_ENOENT)
159       LOG(DEBUG) << "No such application";
160     else
161       LOG(ERROR) << "Request fail";
162     return ret;
163   }
164
165   if (ptr->GetType() != pcp::ParcelableType::AppInfo) {
166     LOG(ERROR) << "Invalid parcelable type";
167     return PMINFO_R_ERROR;
168   }
169
170   std::shared_ptr<pcp::AppInfoParcelable> return_parcel(
171       std::static_pointer_cast<pcp::AppInfoParcelable>(ptr));
172
173   std::vector<application_x*> result_list = return_parcel->ExtractAppInfo();
174   for (application_x* app : result_list)
175     g_hash_table_insert(packages, (gpointer)app->appid,
176         (gpointer)app);
177
178   return PMINFO_R_OK;
179 }
180
181 extern "C" EXPORT_API char* _appinfo_get_localed_label(
182     const char* appid, const char* locale, uid_t uid) {
183   char* query = nullptr;
184   query = sqlite3_mprintf(
185       "SELECT COALESCE((SELECT app_label FROM package_app_localized_info "
186       "WHERE app_id=%Q AND app_locale=%Q),"
187       "(SELECT app_label FROM package_app_localized_info WHERE "
188       "app_id=%Q AND app_locale='No Locale'))",
189       appid, locale, appid);
190   if (query == nullptr) {
191     LOG(ERROR) << "Out of memory";
192     return nullptr;
193   }
194
195   std::shared_ptr<pcp::AbstractParcelable> parcelable(
196       new pcp::QueryParcelable(uid, std::string(query),
197           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
198           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
199   sqlite3_free(query);
200
201   pkgmgr_client::PkgInfoClient client(parcelable, uid,
202       pkgmgr_common::ReqType::QUERY);
203   if (!client.SendRequest())
204     return nullptr;
205   auto ptr = client.GetResultParcel();
206   if (ptr == nullptr) {
207     LOG(ERROR) << "Fail to get return parcelable";
208     return nullptr;
209   }
210
211   if (ptr->GetRequestResult() != PMINFO_R_OK) {
212     LOG(ERROR) << "Request fail";
213     return nullptr;
214   }
215
216   if (ptr->GetType() != pcp::ParcelableType::Result) {
217     LOG(ERROR) << "Invalid parcelable type";
218     return nullptr;
219   }
220
221   std::shared_ptr<pcp::ResultParcelable> return_parcel(
222       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
223
224   // result_list is vector of string vector
225   char* label = nullptr;
226   auto result_list = return_parcel->GetResult();
227   for (auto result : result_list) {
228     // result is string vector
229     // it only has one string or not.
230     if (result.front().empty() || result.front().length() == 0)
231       return nullptr;
232     label = strdup(result.front().c_str());
233     if (label == nullptr) {
234       LOG(ERROR) << "Out of memory";
235       return nullptr;
236     }
237     return label;
238   }
239
240   return label;
241 }
242
243 extern "C" EXPORT_API int _appinfo_get_datacontrol_info(
244     const char* providerid, const char* type, uid_t uid,
245     char** appid, char** access) {
246   char* query = nullptr;
247   query = sqlite3_mprintf("SELECT app_id, access FROM "
248     "package_app_data_control WHERE "
249     "providerid=%Q AND type=%Q",
250     providerid, type);
251   if (query == nullptr) {
252     LOG(ERROR) << "Out of memory";
253     return PMINFO_R_ERROR;
254   }
255
256   std::shared_ptr<pcp::AbstractParcelable> parcelable(
257       new pcp::QueryParcelable(uid, std::string(query),
258           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
259           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
260   sqlite3_free(query);
261
262   pkgmgr_client::PkgInfoClient client(parcelable, uid,
263       pkgmgr_common::ReqType::QUERY);
264   if (!client.SendRequest())
265     return PMINFO_R_ERROR;
266
267   auto ptr = client.GetResultParcel();
268   if (ptr == nullptr) {
269     LOG(ERROR) << "Fail to get return parcelable";
270     return PMINFO_R_ERROR;
271   }
272
273   if (ptr->GetRequestResult() != PMINFO_R_OK) {
274     LOG(ERROR) << "Request fail";
275     return ptr->GetRequestResult();
276   }
277
278   if (ptr->GetType() != pcp::ParcelableType::Result) {
279     LOG(ERROR) << "Invalid parcelable type";
280     return PMINFO_R_ERROR;
281   }
282
283   std::shared_ptr<pcp::ResultParcelable> return_parcel(
284       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
285
286   auto result_list = return_parcel->GetResult();
287   if (result_list.size() == 0)
288     return PMINFO_R_ENOENT;
289   for (auto result : result_list) {
290     if (result.size() != 2)
291       return PMINFO_R_ERROR;
292     if (result.front().empty() || result.front().size() == 0 ||
293         result.back().empty() || result.back().size() == 0)
294       return PMINFO_R_ERROR;
295     *appid = strdup(result.front().c_str());
296     *access = strdup(result.back().c_str());
297     if (*appid == nullptr || *access == nullptr) {
298       LOG(ERROR) << "Out of memory";
299       return PMINFO_R_ERROR;
300     }
301   }
302
303   return PMINFO_R_OK;
304 }
305
306 extern "C" EXPORT_API int _appinfo_get_datacontrol_appid(
307     const char* providerid, uid_t uid, char** appid) {
308   char* query = nullptr;
309
310   query = sqlite3_mprintf("SELECT app_id FROM package_app_data_control "
311                           "WHERE providerid=%Q",
312                           providerid);
313   if (query == nullptr) {
314     LOGE("Out of memory");
315     return PMINFO_R_ERROR;
316   }
317   std::shared_ptr<pcp::AbstractParcelable> parcelable(
318       new pcp::QueryParcelable(uid, std::string(query),
319           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
320           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
321   sqlite3_free(query);
322
323   pkgmgr_client::PkgInfoClient client(parcelable, uid,
324       pkgmgr_common::ReqType::QUERY);
325   if (!client.SendRequest())
326     return PMINFO_R_ERROR;
327
328   auto ptr = client.GetResultParcel();
329   if (ptr == nullptr) {
330     LOG(ERROR) << "Fail to get return parcelable";
331     return PMINFO_R_ERROR;
332   }
333
334   if (ptr->GetRequestResult() != PMINFO_R_OK) {
335     LOG(ERROR) << "Request fail";
336     return ptr->GetRequestResult();
337   }
338
339   if (ptr->GetType() != pcp::ParcelableType::Result) {
340     LOG(ERROR) << "Invalid parcelable type";
341     return PMINFO_R_ERROR;
342   }
343
344   std::shared_ptr<pcp::ResultParcelable> return_parcel(
345       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
346
347   // result_list is vector of string vector
348   auto result_list = return_parcel->GetResult();
349   if (result_list.size() == 0)
350     return PMINFO_R_ENOENT;
351   for (auto result : result_list) {
352     if (result.size() != 1)
353       return PMINFO_R_ERROR;
354     if (result.front().empty() || result.front().size() == 0)
355       return PMINFO_R_ERROR;
356     *appid = strdup(result.front().c_str());
357     if (*appid == nullptr) {
358       LOG(ERROR) << "Out of memory";
359       return PMINFO_R_ERROR;
360     }
361   }
362
363   return PMINFO_R_OK;
364 }
365
366 extern "C" EXPORT_API int _appinfo_get_datacontrol_trusted_info(
367     const char* providerid, const char* type, uid_t uid,
368     char** appid, char** trusted) {
369   char* query = nullptr;
370   query = sqlite3_mprintf(
371       "SELECT app_id, trusted FROM package_app_data_control "
372       "WHERE providerid=%Q AND type=%Q",
373       providerid, type);
374   if (query == nullptr) {
375     LOGE("Out of memory");
376     return PMINFO_R_ERROR;
377   }
378
379   std::shared_ptr<pcp::AbstractParcelable> parcelable(
380       new pcp::QueryParcelable(uid, std::string(query),
381           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
382           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
383   sqlite3_free(query);
384
385   pkgmgr_client::PkgInfoClient client(parcelable, uid,
386       pkgmgr_common::ReqType::QUERY);
387   if (!client.SendRequest())
388     return PMINFO_R_ERROR;
389
390   auto ptr = client.GetResultParcel();
391   if (ptr == nullptr) {
392     LOG(ERROR) << "Fail to get return parcelable";
393     return PMINFO_R_ERROR;
394   }
395
396   if (ptr->GetRequestResult() != PMINFO_R_OK) {
397     LOG(ERROR) << "Request fail";
398     return ptr->GetRequestResult();
399   }
400
401   if (ptr->GetType() != pcp::ParcelableType::Result) {
402     LOG(ERROR) << "Invalid parcelable type";
403     return PMINFO_R_ERROR;
404   }
405
406   std::shared_ptr<pcp::ResultParcelable> return_parcel(
407       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
408
409   // result_list is vector of string vector
410   auto result_list = return_parcel->GetResult();
411   if (result_list.size() == 0)
412     return PMINFO_R_ENOENT;
413   for (auto result : result_list) {
414     if (result.size() != 2)
415       return PMINFO_R_ERROR;
416     if (result.front().empty() || result.front().size() == 0 ||
417         result.back().empty() || result.back().size() == 0)
418       return PMINFO_R_ERROR;
419     *appid = strdup(result.front().c_str());
420     *trusted = strdup(result.back().c_str());
421     if (*appid == nullptr || *trusted == nullptr) {
422       LOG(ERROR) << "Out of memory";
423       return PMINFO_R_ERROR;
424     }
425   }
426
427   return PMINFO_R_OK;
428 }
429
430 extern "C" EXPORT_API int _appinfo_get_datacontrol_privileges(
431     const char* providerid, const char* type, uid_t uid, GList** privileges) {
432   char* query = nullptr;
433   query = sqlite3_mprintf(
434       "SELECT privilege FROM package_app_data_control_privilege "
435       "WHERE providerid=%Q AND type=%Q",
436       providerid, type);
437   if (query == nullptr) {
438     LOGE("Out of memory");
439     return PMINFO_R_ERROR;
440   }
441
442   std::shared_ptr<pcp::AbstractParcelable> parcelable(
443       new pcp::QueryParcelable(uid, std::string(query),
444           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
445           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
446   sqlite3_free(query);
447
448   pkgmgr_client::PkgInfoClient client(parcelable, uid,
449       pkgmgr_common::ReqType::QUERY);
450   if (!client.SendRequest())
451     return PMINFO_R_ERROR;
452
453   auto ptr = client.GetResultParcel();
454   if (ptr == nullptr) {
455     LOG(ERROR) << "Fail to get return parcelable";
456     return PMINFO_R_ERROR;
457   }
458
459   if (ptr->GetRequestResult() != PMINFO_R_OK) {
460     LOG(ERROR) << "Request fail";
461     return ptr->GetRequestResult();
462   }
463
464   if (ptr->GetType() != pcp::ParcelableType::Result) {
465     LOG(ERROR) << "Invalid parcelable type";
466     return PMINFO_R_ERROR;
467   }
468
469   std::shared_ptr<pcp::ResultParcelable> return_parcel(
470       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
471
472   // result_list is vector of string vector
473   auto result_list = return_parcel->GetResult();
474   if (result_list.size() == 0)
475     return PMINFO_R_ENOENT;
476
477   for (auto result : result_list) {
478     if (result.size() != 1)
479       return PMINFO_R_ERROR;
480     if (result.front().empty() || result.front().size() == 0)
481       return PMINFO_R_ERROR;
482     char* privilege = strdup(result.front().c_str());
483     if (privilege == nullptr) {
484       LOG(ERROR) << "Out of memory";
485       return PMINFO_R_ERROR;
486     }
487     *privileges = g_list_append(*privileges, privilege);
488   }
489
490   return PMINFO_R_OK;
491 }
492
493 extern "C" EXPORT_API int _appinfo_get_appcontrol_privileges(
494     const char* appid, const char* operation, uid_t uid, GList** privileges) {
495   char* query = nullptr;
496   query = sqlite3_mprintf(
497       "SELECT app_control, privilege FROM package_app_app_control_privilege "
498       "WHERE app_id=%Q", appid);
499   if (query == nullptr) {
500     LOG(ERROR) << "Out of memory";
501     return PMINFO_R_ERROR;
502   }
503
504   std::shared_ptr<pcp::AbstractParcelable> parcelable(
505       new pcp::QueryParcelable(uid, std::string(query),
506           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
507           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
508   sqlite3_free(query);
509
510   pkgmgr_client::PkgInfoClient client(parcelable, uid,
511       pkgmgr_common::ReqType::QUERY);
512   if (!client.SendRequest())
513     return PMINFO_R_ERROR;
514
515   auto ptr = client.GetResultParcel();
516   if (ptr == nullptr) {
517     LOG(ERROR) << "Fail to get return parcelable";
518     return PMINFO_R_ERROR;
519   }
520
521   if (ptr->GetRequestResult() != PMINFO_R_OK) {
522     LOG(ERROR) << "Request fail";
523     return ptr->GetRequestResult();
524   }
525
526   if (ptr->GetType() != pcp::ParcelableType::Result) {
527     LOG(ERROR) << "Invalid parcelable type";
528     return PMINFO_R_ERROR;
529   }
530
531   std::shared_ptr<pcp::ResultParcelable> return_parcel(
532       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
533
534   // result_list is vector of string vector
535   auto result_list = return_parcel->GetResult();
536   if (result_list.size() == 0)
537     return PMINFO_R_ENOENT;
538
539   for (auto result : result_list) {
540     if (result.size() != 2)
541       return PMINFO_R_ERROR;
542     if (result.front().empty() || result.front().size() == 0 ||
543         result.back().empty() || result.back().size() == 0)
544       return PMINFO_R_ERROR;
545     std::string app_control = result.front();
546     std::stringstream ss(app_control);
547     std::string token;
548     while (std::getline(ss, token, '|')) {
549       if (token.compare(std::string(operation))) {
550         char* privilege = strdup(result.back().c_str());
551         if (privilege == nullptr) {
552           LOG(ERROR) << "Out of memory";
553           return PMINFO_R_ERROR;
554         }
555         *privileges = g_list_append(*privileges, privilege);
556       }
557     }
558   }
559   return PMINFO_R_OK;
560 }
561
562 extern "C" EXPORT_API int _plugininfo_get_appids(
563     const char* pkgid, const char* plugin_type,
564     const char* plugin_name, GList** list) {
565   if (!pkgid || !plugin_type || !plugin_name || !list) {
566     LOG(ERROR) << "Invalid parameter";
567     return PMINFO_R_EINVAL;
568   }
569
570   char* query = nullptr;
571   query = sqlite3_mprintf(
572       "SELECT appid FROM "
573       "package_plugin_info WHERE pkgid=%Q AND "
574       "plugin_type=%Q AND plugin_name=%Q",
575       pkgid, plugin_type, plugin_name);
576   if (query == nullptr) {
577     LOG(ERROR) << "Out of memory";
578     return PMINFO_R_ERROR;
579   }
580
581   std::shared_ptr<pcp::AbstractParcelable> parcelable(
582       new pcp::QueryParcelable(_getuid(), std::string(query),
583           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
584           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
585   sqlite3_free(query);
586
587   pkgmgr_client::PkgInfoClient client(parcelable, _getuid(),
588       pkgmgr_common::ReqType::QUERY);
589   if (!client.SendRequest())
590     return PMINFO_R_ERROR;
591
592   auto ptr = client.GetResultParcel();
593   if (ptr == nullptr) {
594     LOG(ERROR) << "Fail to get return parcelable";
595     return PMINFO_R_ERROR;
596   }
597
598   if (ptr->GetRequestResult() != PMINFO_R_OK) {
599     LOG(ERROR) << "Request fail";
600     return ptr->GetRequestResult();
601   }
602
603   if (ptr->GetType() != pcp::ParcelableType::Result) {
604     LOG(ERROR) << "Invalid parcelable type";
605     return PMINFO_R_ERROR;
606   }
607
608   std::shared_ptr<pcp::ResultParcelable> return_parcel(
609       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
610
611   if (return_parcel->GetCol() != 1) {
612     LOG(ERROR) << "Invalid result";
613     return PMINFO_R_ERROR;
614   }
615   // result_list is vector of string vector
616   auto &result_list = return_parcel->GetResult();
617   if (result_list.size() == 0)
618     return PMINFO_R_ENOENT;
619
620   for (auto result : result_list) {
621     if (result.size() != 1) {
622       LOG(ERROR) << "Invalid result";
623       g_list_free_full(*list, free);
624       return PMINFO_R_ERROR;
625     }
626     *list = g_list_append(*list, strdup(result[0].c_str()));
627   }
628
629   return PMINFO_R_OK;
630 }
631
632 static int __convert_update_type(const char* type,
633     pkgmgrinfo_updateinfo_update_type* convert_type) {
634   if (strncasecmp(type, PMINFO_UPDATEINFO_TYPE_NONE,
635       strlen(PMINFO_UPDATEINFO_TYPE_NONE)) == 0)
636     *convert_type = PMINFO_UPDATEINFO_NONE;
637   else if (strncasecmp(type, PMINFO_UPDATEINFO_TYPE_FORCE,
638       strlen(PMINFO_UPDATEINFO_TYPE_FORCE)) == 0)
639     *convert_type = PMINFO_UPDATEINFO_FORCE;
640   else if (strncasecmp(type, PMINFO_UPDATEINFO_TYPE_OPTIONAL,
641       strlen(PMINFO_UPDATEINFO_TYPE_OPTIONAL)) == 0)
642     *convert_type = PMINFO_UPDATEINFO_OPTIONAL;
643   else
644     return -1;
645   return 0;
646 }
647
648 static void __free_update_info(gpointer data) {
649   updateinfo_x* update_info = reinterpret_cast<updateinfo_x*>(data);
650   if (update_info == nullptr)
651     return;
652
653   if (update_info->pkgid)
654     free(reinterpret_cast<void*>(update_info->pkgid));
655   if (update_info->version)
656     free(reinterpret_cast<void*>(update_info->version));
657   free(reinterpret_cast<void*>(update_info));
658 }
659
660 extern "C" EXPORT_API int _get_pkg_updateinfo(const char* pkgid,
661     GSList** update_info_list, uid_t uid) {
662   char* query = nullptr;
663   int ret;
664
665   if (pkgid == nullptr)
666     query = sqlite3_mprintf(
667         "SELECT package, update_version, update_type "
668         "FROM package_update_info");
669   else
670     query = sqlite3_mprintf(
671         "SELECT package, update_version, update_type "
672         "FROM package_update_info WHERE package=%Q",
673         pkgid);
674   if (query == nullptr) {
675     LOG(ERROR) << "Out of memory";
676     return PMINFO_R_ERROR;
677   }
678
679   std::shared_ptr<pcp::AbstractParcelable> parcelable(
680       new pcp::QueryParcelable(uid, std::string(query),
681           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
682           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
683   sqlite3_free(query);
684
685   pkgmgr_client::PkgInfoClient client(parcelable, uid,
686       pkgmgr_common::ReqType::QUERY);
687   if (!client.SendRequest())
688     return PMINFO_R_ERROR;
689
690   auto ptr = client.GetResultParcel();
691   if (ptr == nullptr) {
692     LOG(ERROR) << "Fail to get return parcelable";
693     return PMINFO_R_ERROR;
694   }
695
696   if (ptr->GetRequestResult() != PMINFO_R_OK) {
697     LOG(ERROR) << "Request fail";
698     return ptr->GetRequestResult();
699   }
700
701   if (ptr->GetType() != pcp::ParcelableType::Result) {
702     LOG(ERROR) << "Invalid parcelable type";
703     return PMINFO_R_ERROR;
704   }
705
706   std::shared_ptr<pcp::ResultParcelable> return_parcel(
707       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
708
709   if (return_parcel->GetCol() != 3) {
710     LOG(ERROR) << "Invalid result";
711     return PMINFO_R_ERROR;
712   }
713
714   auto result_list = return_parcel->GetResult();
715   if (result_list.size() == 0)
716     return PMINFO_R_ENOENT;
717
718   for (auto result : result_list) {
719     if (result.size() != 3) {
720       LOG(ERROR) << "Invalid result";
721       g_slist_free_full(*update_info_list, __free_update_info);
722       return PMINFO_R_ERROR;
723     }
724     updateinfo_x* update_info = reinterpret_cast<updateinfo_x*>(
725         calloc(1, sizeof(updateinfo_x)));
726     if (update_info == nullptr) {
727       LOG(ERROR) << "Out of memory";
728       return PMINFO_R_ERROR;
729     }
730     update_info->pkgid = strdup(result[0].c_str());
731     update_info->version = strdup(result[1].c_str());
732     pkgmgrinfo_updateinfo_update_type convert_type;
733     ret = __convert_update_type(result[2].c_str(), &convert_type);
734     if (ret != 0) {
735       __free_update_info(update_info);
736       g_slist_free_full(*update_info_list, __free_update_info);
737       return PMINFO_R_ERROR;
738     }
739     update_info->type = static_cast<int>(convert_type);
740     *update_info_list = g_slist_prepend(*update_info_list,
741         update_info);
742   }
743
744   return PMINFO_R_OK;
745 }
746
747 extern "C" EXPORT_API int _pkginfo_set_usr_installed_storage(const char* pkgid,
748     INSTALL_LOCATION location, const char* external_pkg_path, uid_t uid) {
749   char* query = nullptr;
750   const char* location_str;
751   std::vector<std::string> queries;
752
753   if (location == INSTALL_INTERNAL)
754     location_str = "installed_internal";
755   else if (location == INSTALL_EXTERNAL)
756     location_str = "installed_external";
757   else
758     location_str = "installed_extended";
759   /* pkgcakge_info table */
760   query = sqlite3_mprintf(
761       "UPDATE package_info SET installed_storage=%Q, external_path=%Q "
762       "WHERE package=%Q",
763       location_str, external_pkg_path, pkgid);
764   queries.emplace_back(query);
765   sqlite3_free(query);
766
767   /* package_app_info table */
768   query = sqlite3_mprintf(
769       "UPDATE package_app_info SET app_installed_storage=%Q, "
770       "app_external_path=%Q WHERE package=%Q",
771       location_str, external_pkg_path, pkgid);
772   queries.emplace_back(query);
773   sqlite3_free(query);
774
775   std::shared_ptr<pcp::AbstractParcelable> parcelable(
776       new pcp::QueryParcelable(uid, queries,
777           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
778           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_WRITE));
779
780   pkgmgr_client::PkgInfoClient client(parcelable, uid,
781       pkgmgr_common::ReqType::QUERY);
782   if (!client.SendRequest())
783     return PMINFO_R_ERROR;
784
785   auto ptr = client.GetResultParcel();
786   if (ptr == nullptr) {
787     LOG(ERROR) << "Fail to get return parcelable";
788     return PMINFO_R_ERROR;
789   }
790
791   if (ptr->GetRequestResult() != PMINFO_R_OK) {
792     LOG(ERROR) << "Request fail";
793     return ptr->GetRequestResult();
794   }
795
796   if (ptr->GetType() != pcp::ParcelableType::Result) {
797     LOG(ERROR) << "Invalid parcelable type";
798     return PMINFO_R_ERROR;
799   }
800
801   return PMINFO_R_OK;
802 }
803
804 extern "C" EXPORT_API int _certinfo_compare_pkg_certinfo(const char* l_pkgid,
805     const char* r_pkgid, pkgmgrinfo_cert_compare_result_type_e* result) {
806   char* query = sqlite3_mprintf("SELECT package, "
807       "COALESCE(author_signer_cert, -1) FROM package_cert_info WHERE "
808       "package IN (%Q, %Q)",
809       l_pkgid, r_pkgid);
810   if (query == nullptr) {
811     LOG(ERROR) << "Out of memory";
812     return PMINFO_R_ERROR;
813   }
814   std::vector<std::string> queries;
815   queries.emplace_back(query);
816   sqlite3_free(query);
817
818   std::shared_ptr<pcp::AbstractParcelable> parcelable(
819       new pcp::QueryParcelable(0, queries,
820           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_CERTDB,
821           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
822   pkgmgr_client::PkgInfoClient client(parcelable, 0,
823       pkgmgr_common::ReqType::QUERY);
824   if (!client.SendRequest())
825     return PMINFO_R_ERROR;
826
827   auto ptr = client.GetResultParcel();
828   if (ptr == nullptr) {
829     LOG(ERROR) << "Fail to get return parcelable";
830     return PMINFO_R_ERROR;
831   }
832
833   if (ptr->GetRequestResult() != PMINFO_R_OK) {
834     LOG(ERROR) << "Request fail";
835     return ptr->GetRequestResult();
836   }
837
838   if (ptr->GetType() != pcp::ParcelableType::Result) {
839     LOG(ERROR) << "Invalid parcelable type";
840     return PMINFO_R_ERROR;
841   }
842
843   std::shared_ptr<pcp::ResultParcelable> return_parcel(
844       std::static_pointer_cast<pcp::ResultParcelable>(
845           ptr));
846
847   auto certinfo_list = return_parcel->GetResult();
848
849   std::map<std::string, std::string> result_map;
850   result_map.insert(make_pair(std::string(l_pkgid), "-1"));
851   result_map.insert(make_pair(std::string(r_pkgid), "-1"));
852
853   for (auto &certinfo : certinfo_list)
854     result_map[certinfo.front()] = certinfo.back();
855
856   if (result_map.find(std::string(l_pkgid))->second == "-1" &&
857       result_map.find(std::string(r_pkgid))->second == "-1")
858     *result = PMINFO_CERT_COMPARE_BOTH_NO_CERT;
859   else if (result_map.find(std::string(l_pkgid))->second == "-1")
860     *result = PMINFO_CERT_COMPARE_LHS_NO_CERT;
861   else if (result_map.find(std::string(r_pkgid))->second == "-1")
862     *result = PMINFO_CERT_COMPARE_RHS_NO_CERT;
863   else if (result_map.find(std::string(l_pkgid))->second ==
864       result_map.find(std::string(r_pkgid))->second)
865     *result = PMINFO_CERT_COMPARE_MATCH;
866   else
867     *result = PMINFO_CERT_COMPARE_MISMATCH;
868
869   return PMINFO_R_OK;
870 }
871
872 extern "C" EXPORT_API int _certinfo_compare_app_certinfo(uid_t uid,
873     const char* l_appid, const char* r_appid,
874     pkgmgrinfo_cert_compare_result_type_e* result) {
875   char* query = sqlite3_mprintf("SELECT app_id, package FROM "
876                                 "package_app_info WHERE app_id IN (%Q, %Q)",
877                                 l_appid, r_appid);
878   if (query == nullptr) {
879     LOG(ERROR) << "Out of memory";
880     return PMINFO_R_ERROR;
881   }
882   std::vector<std::string> queries;
883   queries.emplace_back(query);
884   sqlite3_free(query);
885
886   std::shared_ptr<pcp::AbstractParcelable> parcelable(
887       new pcp::QueryParcelable(uid, queries,
888           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
889           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
890   pkgmgr_client::PkgInfoClient client(parcelable, uid,
891       pkgmgr_common::ReqType::QUERY);
892   if (!client.SendRequest())
893     return PMINFO_R_ERROR;
894
895   auto ptr = client.GetResultParcel();
896   if (ptr == nullptr) {
897     LOG(ERROR) << "Fail to get return parcelable";
898     return PMINFO_R_ERROR;
899   }
900
901   if (ptr->GetRequestResult() != PMINFO_R_OK) {
902     LOG(ERROR) << "Request fail";
903     return ptr->GetRequestResult();
904   }
905
906   if (ptr->GetType() != pcp::ParcelableType::Result) {
907     LOG(ERROR) << "Invalid parcelable type";
908     return PMINFO_R_ERROR;
909   }
910
911   std::shared_ptr<pcp::ResultParcelable> return_parcel(
912       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
913
914   auto pkgid_list = return_parcel->GetResult();
915   std::map<std::string, std::string> result_map;
916   for (auto &pkgid : pkgid_list)
917     result_map.insert(make_pair(pkgid.front(), pkgid.back()));
918
919   if (result_map.find(std::string(l_appid)) == result_map.end()) {
920     LOG(ERROR) << "Cannot find pkgid of app " << l_appid
921         << " for uid " << uid;
922     return PMINFO_R_ENOENT;
923   } else if (result_map.find(std::string(r_appid)) == result_map.end()) {
924     LOG(ERROR) << "Cannot find pkgid of app " << r_appid
925         << " for uid " << uid;
926     return PMINFO_R_ENOENT;
927   }
928
929   const char* l_pkgid = result_map.find(std::string(l_appid))->second.c_str();
930   const char* r_pkgid = result_map.find(std::string(r_appid))->second.c_str();
931
932   return _certinfo_compare_pkg_certinfo(l_pkgid, r_pkgid, result);
933 }
934
935 extern "C" EXPORT_API int _parser_execute_write_query(
936     const char* query, uid_t uid) {
937   std::shared_ptr<pcp::AbstractParcelable> parcelable(
938       new pcp::QueryParcelable(uid, query,
939           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
940           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_WRITE));
941
942   pkgmgr_client::PkgInfoClient client(parcelable, uid,
943                                       pkgmgr_common::ReqType::QUERY);
944   if (!client.SendRequest())
945     return -1;
946
947   auto ptr = client.GetResultParcel();
948   if (ptr == nullptr) {
949     LOG(ERROR) << "Fail to get return parcelable";
950     return -1;
951   }
952
953   if (ptr->GetRequestResult() != PMINFO_R_OK) {
954     LOG(ERROR) << "Request fail";
955     return -1;
956   }
957
958   if (ptr->GetType() != pcp::ParcelableType::Result) {
959     LOG(ERROR) << "Invalid parcelable type";
960     return -1;
961   }
962
963   return 0;
964 }
965
966 extern "C" EXPORT_API int _parser_execute_write_queries(
967     const char** queries, int len, uid_t uid) {
968   std::vector<std::string> query_vt;
969   for (int i = 0; i < len; ++i)
970     query_vt.emplace_back(queries[i]);
971
972   std::shared_ptr<pcp::AbstractParcelable> parcelable(
973       new pcp::QueryParcelable(uid, query_vt,
974           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
975           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_WRITE));
976
977   pkgmgr_client::PkgInfoClient client(parcelable, uid,
978       pkgmgr_common::ReqType::QUERY);
979   if (!client.SendRequest())
980     return -1;
981
982   auto ptr = client.GetResultParcel();
983   if (ptr == nullptr) {
984     LOG(ERROR) << "Fail to get return parcelable";
985     return -1;
986   }
987
988   if (ptr->GetRequestResult() != PMINFO_R_OK) {
989     LOG(ERROR) << "Request fail";
990     return -1;
991   }
992
993   if (ptr->GetType() != pcp::ParcelableType::Result) {
994     LOG(ERROR) << "Invalid parcelable type";
995     return -1;
996   }
997
998   return 0;
999 }
1000
1001 extern "C" EXPORT_API int _parser_insert_manifest_info(
1002     manifest_x* mfx, uid_t uid) {
1003   auto parcelable =
1004       std::make_shared<pcp::PkgInfoParcelable>(uid,
1005           std::vector<package_x*>{mfx}, WriteType::Insert, false);
1006
1007   pkgmgr_client::PkgInfoClient client(parcelable, uid,
1008       pkgmgr_common::ReqType::SET_PKG_INFO);
1009   if (!client.SendRequest())
1010     return -1;
1011
1012   auto ptr = client.GetResultParcel();
1013   if (ptr == nullptr) {
1014     LOG(ERROR) << "Fail to get return parcelable";
1015     return -1;
1016   }
1017
1018   if (ptr->GetRequestResult() != PMINFO_R_OK) {
1019     LOG(ERROR) << "Request fail";
1020     return -1;
1021   }
1022
1023   if (ptr->GetType() != pcp::ParcelableType::Result) {
1024     LOG(ERROR) << "Invalid parcelable type";
1025     return -1;
1026   }
1027
1028   return 0;
1029 }
1030
1031 extern "C" EXPORT_API int _parser_update_manifest_info(
1032     manifest_x* mfx, uid_t uid) {
1033   auto parcelable =
1034       std::make_shared<pcp::PkgInfoParcelable>(uid,
1035           std::vector<package_x*>{mfx}, WriteType::Update, false);
1036
1037   pkgmgr_client::PkgInfoClient client(parcelable, uid,
1038       pkgmgr_common::ReqType::SET_PKG_INFO);
1039   if (!client.SendRequest())
1040     return -1;
1041
1042   auto ptr = client.GetResultParcel();
1043   if (ptr == nullptr) {
1044     LOG(ERROR) << "Fail to get return parcelable";
1045     return -1;
1046   }
1047
1048   if (ptr->GetRequestResult() != PMINFO_R_OK) {
1049     LOG(ERROR) << "Request fail";
1050     return -1;
1051   }
1052
1053   if (ptr->GetType() != pcp::ParcelableType::Result) {
1054     LOG(ERROR) << "Invalid parcelable type";
1055     return -1;
1056   }
1057
1058   return 0;
1059 }
1060
1061 extern "C" EXPORT_API int _parser_delete_manifest_info(
1062     manifest_x* mfx, uid_t uid) {
1063   auto parcelable =
1064       std::make_shared<pcp::PkgInfoParcelable>(uid,
1065           std::vector<package_x*>{mfx}, WriteType::Delete, false);
1066
1067   pkgmgr_client::PkgInfoClient client(parcelable, uid,
1068       pkgmgr_common::ReqType::SET_PKG_INFO);
1069   if (!client.SendRequest())
1070     return -1;
1071
1072   auto ptr = client.GetResultParcel();
1073   if (ptr == nullptr) {
1074     LOG(ERROR) << "Fail to get return parcelable";
1075     return -1;
1076   }
1077
1078   if (ptr->GetRequestResult() != PMINFO_R_OK) {
1079     LOG(ERROR) << "Request fail";
1080     return -1;
1081   }
1082
1083   if (ptr->GetType() != pcp::ParcelableType::Result) {
1084     LOG(ERROR) << "Invalid parcelable type";
1085     return -1;
1086   }
1087
1088   return 0;
1089 }
1090
1091 extern "C" EXPORT_API int _pkginfo_insert_certinfo(const char* pkgid,
1092     pkgmgr_certinfo_x* cert, uid_t uid) {
1093   std::shared_ptr<pcp::AbstractParcelable> parcelable(
1094       new pcp::CertInfoParcelable(uid, cert, false));
1095   pkgmgr_client::PkgInfoClient client(parcelable, uid,
1096       pkgmgr_common::ReqType::SET_CERT_INFO);
1097
1098   if (!client.SendRequest())
1099     return PMINFO_R_ERROR;
1100
1101   auto ptr = client.GetResultParcel();
1102   if (ptr == nullptr) {
1103     LOG(ERROR) << "Fail to get return parcelable";
1104     return PMINFO_R_ERROR;
1105   }
1106
1107   if (ptr->GetRequestResult() != PMINFO_R_OK) {
1108     LOG(ERROR) << "Request fail";
1109     return ptr->GetRequestResult();
1110   }
1111
1112   if (ptr->GetType() != pcp::ParcelableType::Result) {
1113     LOG(ERROR) << "Invalid parcelable type";
1114     return PMINFO_R_ERROR;
1115   }
1116
1117   return PMINFO_R_OK;
1118 }
1119
1120 extern "C" EXPORT_API int _pkginfo_get_certinfo(const char* pkgid,
1121     pkgmgr_certinfo_x* cert, uid_t uid) {
1122   std::shared_ptr<pcp::AbstractParcelable> parcelable(
1123       new pcp::CertInfoParcelable(uid,
1124           std::string(pkgid)));
1125
1126   pkgmgr_client::PkgInfoClient client(parcelable, uid,
1127                                       pkgmgr_common::ReqType::GET_CERT_INFO);
1128   if (!client.SendRequest())
1129     return PMINFO_R_ERROR;
1130
1131   auto ptr = client.GetResultParcel();
1132   if (ptr == nullptr) {
1133     LOG(ERROR) << "Fail to get return parcelable";
1134     return PMINFO_R_ERROR;
1135   }
1136
1137   if (ptr->GetRequestResult() != PMINFO_R_OK) {
1138     LOG(ERROR) << "Request fail";
1139     return ptr->GetRequestResult();
1140   }
1141
1142   if (ptr->GetType() != pcp::ParcelableType::CertInfo) {
1143     LOG(ERROR) << "Invalid parcelable type";
1144     return PMINFO_R_ERROR;
1145   }
1146
1147   std::shared_ptr<pcp::CertInfoParcelable> return_parcel(
1148       std::static_pointer_cast<pcp::CertInfoParcelable>(ptr));
1149
1150   pkgmgr_certinfo_x* certinfo = return_parcel->ExtractCertInfo();
1151   if (certinfo == nullptr)
1152     return PMINFO_R_ERROR;
1153
1154   cert->for_all_users = certinfo->for_all_users;
1155   cert->pkgid = certinfo->pkgid;
1156   certinfo->pkgid = nullptr;
1157   cert->cert_value = certinfo->cert_value;
1158   certinfo->cert_value = nullptr;
1159   for (int i = 0; i < MAX_CERT_TYPE; i++) {
1160     cert->cert_info[i] = certinfo->cert_info[i];
1161     certinfo->cert_info[i] = nullptr;
1162   }
1163   for (int i = 0; i < MAX_CERT_TYPE; i++)
1164     cert->cert_id[i] = certinfo->cert_id[i];
1165
1166   free(certinfo);
1167
1168   return PMINFO_R_OK;
1169 }
1170
1171 extern "C" EXPORT_API int _pkginfo_delete_certinfo(const char* pkgid) {
1172   char* query = sqlite3_mprintf("UPDATE package_cert_info SET "
1173       "package_count = package_count - 1 WHERE package=%Q", pkgid);
1174   if (query == nullptr) {
1175     LOG(ERROR) << "Out of memory";
1176     return PMINFO_R_ERROR;
1177   }
1178
1179   std::vector<std::string> queries;
1180   queries.emplace_back(query);
1181   sqlite3_free(query);
1182
1183   std::shared_ptr<pcp::AbstractParcelable> parcelable(
1184       new pcp::QueryParcelable(0, queries,
1185           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_CERTDB,
1186           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_WRITE));
1187
1188   pkgmgr_client::PkgInfoClient client(parcelable, 0,
1189                                       pkgmgr_common::ReqType::QUERY);
1190   if (!client.SendRequest())
1191     return PMINFO_R_ERROR;
1192
1193   auto ptr = client.GetResultParcel();
1194   if (ptr == nullptr) {
1195     LOG(ERROR) << "Fail to get return parcelable";
1196     return PMINFO_R_ERROR;
1197   }
1198
1199   if (ptr->GetRequestResult() != PMINFO_R_OK) {
1200     LOG(ERROR) << "Request fail";
1201     return PMINFO_R_ERROR;
1202   }
1203
1204   if (ptr->GetType() != pcp::ParcelableType::Result) {
1205     LOG(ERROR) << "Invalid parcelable type";
1206     return PMINFO_R_ERROR;
1207   }
1208
1209   return PMINFO_R_OK;
1210 }
1211
1212 extern "C" EXPORT_API int _parser_clear_cache_memory_db(uid_t uid) {
1213   std::shared_ptr<pcp::AbstractParcelable> parcelable(
1214       new pcp::CommandParcelable(uid, CommandType::RemoveCache));
1215
1216   pkgmgr_client::PkgInfoClient client(parcelable, uid,
1217                                       pkgmgr_common::ReqType::COMMAND);
1218
1219   if (!client.SendRequest())
1220     return PMINFO_R_ERROR;
1221
1222   auto ptr = client.GetResultParcel();
1223   if (ptr == nullptr)   {
1224     LOG(ERROR) << "Fail to get return parcelable";
1225     return PMINFO_R_ERROR;
1226   }
1227
1228   if (ptr->GetRequestResult() != PMINFO_R_OK)   {
1229     LOG(ERROR) << "Request fail";
1230     return PMINFO_R_ERROR;
1231   }
1232
1233   if (ptr->GetType() != pcp::ParcelableType::Result)   {
1234     LOG(ERROR) << "Invalid parcelable type";
1235     return PMINFO_R_ERROR;
1236   }
1237
1238   return PMINFO_R_OK;
1239 }