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