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