Fix QueryParcelable 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().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().empty() || result.back().empty())
272       return PMINFO_R_ERROR;
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     break;
288   }
289
290   return PMINFO_R_OK;
291 }
292
293 extern "C" EXPORT_API int _appinfo_get_datacontrol_appid(
294     const char* providerid, uid_t uid, char** appid) {
295   std::shared_ptr<pcp::AbstractParcelable> parcelable(
296       new pcp::QueryParcelable(uid,
297           { QUERY_INDEX_APPINFO_GET_DATACONTROL_APPID, { providerid } },
298           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
299           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
300
301   pkgmgr_client::PkgInfoClient client(parcelable, uid,
302       pkgmgr_common::ReqType::QUERY);
303   if (!client.SendRequest())
304     return PMINFO_R_ERROR;
305
306   auto ptr = client.GetResultParcel();
307   if (ptr == nullptr) {
308     LOG(ERROR) << "Fail to get return parcelable";
309     return PMINFO_R_ERROR;
310   }
311
312   if (ptr->GetRequestResult() != PMINFO_R_OK) {
313     LOG(ERROR) << "Request fail";
314     return ptr->GetRequestResult();
315   }
316
317   if (ptr->GetType() != pcp::ParcelableType::Result) {
318     LOG(ERROR) << "Invalid parcelable type";
319     return PMINFO_R_ERROR;
320   }
321
322   std::shared_ptr<pcp::ResultParcelable> return_parcel(
323       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
324
325   // result_list is vector of string vector
326   auto result_list = return_parcel->GetResult();
327   if (result_list.size() == 0)
328     return PMINFO_R_ENOENT;
329   for (auto& result : result_list) {
330     if (result.size() != 1 || result.front().empty())
331       return PMINFO_R_ERROR;
332     *appid = strdup(result.front().c_str());
333     if (*appid == nullptr) {
334       LOG(ERROR) << "Out of memory";
335       return PMINFO_R_ERROR;
336     }
337   }
338
339   return PMINFO_R_OK;
340 }
341
342 extern "C" EXPORT_API int _appinfo_get_datacontrol_trusted_info(
343     const char* providerid, const char* type, uid_t uid,
344     char** appid, char** trusted) {
345   std::shared_ptr<pcp::AbstractParcelable> parcelable(
346       new pcp::QueryParcelable(uid,
347           { QUERY_INDEX_APPINFO_GET_DATACONTROL_TRUSTED_INFO,
348               { providerid, type } },
349           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
350           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
351
352   pkgmgr_client::PkgInfoClient client(parcelable, uid,
353       pkgmgr_common::ReqType::QUERY);
354   if (!client.SendRequest())
355     return PMINFO_R_ERROR;
356
357   auto ptr = client.GetResultParcel();
358   if (ptr == nullptr) {
359     LOG(ERROR) << "Fail to get return parcelable";
360     return PMINFO_R_ERROR;
361   }
362
363   if (ptr->GetRequestResult() != PMINFO_R_OK) {
364     LOG(ERROR) << "Request fail";
365     return ptr->GetRequestResult();
366   }
367
368   if (ptr->GetType() != pcp::ParcelableType::Result) {
369     LOG(ERROR) << "Invalid parcelable type";
370     return PMINFO_R_ERROR;
371   }
372
373   std::shared_ptr<pcp::ResultParcelable> return_parcel(
374       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
375
376   // result_list is vector of string vector
377   auto result_list = return_parcel->GetResult();
378   if (result_list.size() == 0)
379     return PMINFO_R_ENOENT;
380   for (auto& result : result_list) {
381     if (result.size() != 2 || result.front().empty() || result.back().empty())
382       return PMINFO_R_ERROR;
383
384     char* tmp_appid = strdup(result.front().c_str());
385     if (tmp_appid == nullptr) {
386       LOG(ERROR) << "Out of memory";
387       return PMINFO_R_ERROR;
388     }
389     char* tmp_trusted = strdup(result.back().c_str());
390     if (tmp_trusted == nullptr) {
391       LOG(ERROR) << "Out of memory";
392       free(tmp_appid);
393       return PMINFO_R_ERROR;
394     }
395     *appid = tmp_appid;
396     *trusted = tmp_trusted;
397     break;
398   }
399
400   return PMINFO_R_OK;
401 }
402
403 extern "C" EXPORT_API int _appinfo_get_datacontrol_privileges(
404     const char* providerid, const char* type, uid_t uid, GList** privileges) {
405   std::shared_ptr<pcp::AbstractParcelable> parcelable(
406       new pcp::QueryParcelable(uid,
407           { QUERY_INDEX_APPINFO_GET_DATACONTROL_PRIVILEGES,
408               { providerid, type } },
409           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
410           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
411
412   pkgmgr_client::PkgInfoClient client(parcelable, uid,
413       pkgmgr_common::ReqType::QUERY);
414   if (!client.SendRequest())
415     return PMINFO_R_ERROR;
416
417   auto ptr = client.GetResultParcel();
418   if (ptr == nullptr) {
419     LOG(ERROR) << "Fail to get return parcelable";
420     return PMINFO_R_ERROR;
421   }
422
423   if (ptr->GetRequestResult() != PMINFO_R_OK) {
424     LOG(ERROR) << "Request fail";
425     return ptr->GetRequestResult();
426   }
427
428   if (ptr->GetType() != pcp::ParcelableType::Result) {
429     LOG(ERROR) << "Invalid parcelable type";
430     return PMINFO_R_ERROR;
431   }
432
433   std::shared_ptr<pcp::ResultParcelable> return_parcel(
434       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
435
436   // result_list is vector of string vector
437   auto result_list = return_parcel->GetResult();
438   if (result_list.size() == 0)
439     return PMINFO_R_ENOENT;
440
441   for (auto& result : result_list) {
442     if (result.size() != 1 || result.front().empty())
443       return PMINFO_R_ERROR;
444     char* privilege = strdup(result.front().c_str());
445     if (privilege == nullptr) {
446       LOG(ERROR) << "Out of memory";
447       return PMINFO_R_ERROR;
448     }
449     *privileges = g_list_append(*privileges, privilege);
450   }
451
452   return PMINFO_R_OK;
453 }
454
455 extern "C" EXPORT_API int _appinfo_get_appcontrol_privileges(
456     const char* appid, const char* operation, uid_t uid, GList** privileges) {
457   std::shared_ptr<pcp::AbstractParcelable> parcelable(
458       new pcp::QueryParcelable(uid,
459           { QUERY_INDEX_APPINFO_GET_APPCONTROL_PRIVILEGES, { appid } },
460           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
461           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
462
463   pkgmgr_client::PkgInfoClient client(parcelable, uid,
464       pkgmgr_common::ReqType::QUERY);
465   if (!client.SendRequest())
466     return PMINFO_R_ERROR;
467
468   auto ptr = client.GetResultParcel();
469   if (ptr == nullptr) {
470     LOG(ERROR) << "Fail to get return parcelable";
471     return PMINFO_R_ERROR;
472   }
473
474   if (ptr->GetRequestResult() != PMINFO_R_OK) {
475     LOG(ERROR) << "Request fail";
476     return ptr->GetRequestResult();
477   }
478
479   if (ptr->GetType() != pcp::ParcelableType::Result) {
480     LOG(ERROR) << "Invalid parcelable type";
481     return PMINFO_R_ERROR;
482   }
483
484   std::shared_ptr<pcp::ResultParcelable> return_parcel(
485       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
486
487   // result_list is vector of string vector
488   auto result_list = return_parcel->GetResult();
489   if (result_list.size() == 0)
490     return PMINFO_R_ENOENT;
491
492   for (auto& result : result_list) {
493     if (result.size() != 2 || result.front().empty() || result.back().empty())
494       return PMINFO_R_ERROR;
495     std::stringstream ss(result.front());
496     std::string token;
497     while (std::getline(ss, token, '|')) {
498       if (token.compare(std::string(operation))) {
499         char* privilege = strdup(result.back().c_str());
500         if (privilege == nullptr) {
501           LOG(ERROR) << "Out of memory";
502           return PMINFO_R_ERROR;
503         }
504         *privileges = g_list_append(*privileges, privilege);
505       }
506     }
507   }
508   return PMINFO_R_OK;
509 }
510
511 extern "C" EXPORT_API int _plugininfo_get_appids(
512     const char* pkgid, const char* plugin_type,
513     const char* plugin_name, GList** list) {
514   if (!pkgid || !plugin_type || !plugin_name || !list) {
515     LOG(ERROR) << "Invalid parameter";
516     return PMINFO_R_EINVAL;
517   }
518
519   std::shared_ptr<pcp::AbstractParcelable> parcelable(
520       new pcp::QueryParcelable(_getuid(),
521           { QUERY_INDEX_PLUGININFO_GET_APPIDS,
522               { pkgid, plugin_type, plugin_name } },
523           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
524           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
525
526   pkgmgr_client::PkgInfoClient client(parcelable, _getuid(),
527       pkgmgr_common::ReqType::QUERY);
528   if (!client.SendRequest())
529     return PMINFO_R_ERROR;
530
531   auto ptr = client.GetResultParcel();
532   if (ptr == nullptr) {
533     LOG(ERROR) << "Fail to get return parcelable";
534     return PMINFO_R_ERROR;
535   }
536
537   if (ptr->GetRequestResult() != PMINFO_R_OK) {
538     LOG(ERROR) << "Request fail";
539     return ptr->GetRequestResult();
540   }
541
542   if (ptr->GetType() != pcp::ParcelableType::Result) {
543     LOG(ERROR) << "Invalid parcelable type";
544     return PMINFO_R_ERROR;
545   }
546
547   std::shared_ptr<pcp::ResultParcelable> return_parcel(
548       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
549
550   if (return_parcel->GetCol() != 1) {
551     LOG(ERROR) << "Invalid result";
552     return PMINFO_R_ERROR;
553   }
554   // result_list is vector of string vector
555   auto &result_list = return_parcel->GetResult();
556   if (result_list.size() == 0)
557     return PMINFO_R_ENOENT;
558
559   for (auto& result : result_list) {
560     if (result.size() != 1) {
561       LOG(ERROR) << "Invalid result";
562       g_list_free_full(*list, free);
563       return PMINFO_R_ERROR;
564     }
565     *list = g_list_append(*list, strdup(result[0].c_str()));
566   }
567
568   return PMINFO_R_OK;
569 }
570
571 static int __convert_update_type(const char* type,
572     pkgmgrinfo_updateinfo_update_type* convert_type) {
573   if (strncasecmp(type, PMINFO_UPDATEINFO_TYPE_NONE,
574       strlen(PMINFO_UPDATEINFO_TYPE_NONE)) == 0)
575     *convert_type = PMINFO_UPDATEINFO_NONE;
576   else if (strncasecmp(type, PMINFO_UPDATEINFO_TYPE_FORCE,
577       strlen(PMINFO_UPDATEINFO_TYPE_FORCE)) == 0)
578     *convert_type = PMINFO_UPDATEINFO_FORCE;
579   else if (strncasecmp(type, PMINFO_UPDATEINFO_TYPE_OPTIONAL,
580       strlen(PMINFO_UPDATEINFO_TYPE_OPTIONAL)) == 0)
581     *convert_type = PMINFO_UPDATEINFO_OPTIONAL;
582   else
583     return -1;
584   return 0;
585 }
586
587 static void __free_update_info(gpointer data) {
588   updateinfo_x* update_info = reinterpret_cast<updateinfo_x*>(data);
589   if (update_info == nullptr)
590     return;
591
592   if (update_info->pkgid)
593     free(reinterpret_cast<void*>(update_info->pkgid));
594   if (update_info->version)
595     free(reinterpret_cast<void*>(update_info->version));
596   free(reinterpret_cast<void*>(update_info));
597 }
598
599 extern "C" EXPORT_API int _get_pkg_updateinfo(const char* pkgid,
600     GSList** update_info_list, uid_t uid) {
601   int ret;
602
603   std::pair<int, std::vector<const char*>> info;
604
605   if (pkgid == nullptr) {
606     info = std::pair<int, std::vector<const char*>>(
607               QUERY_INDEX_GET_PKG_UPDATEINFO_1, {});
608   } else {
609     info = std::pair<int, std::vector<const char*>>(
610               QUERY_INDEX_GET_PKG_UPDATEINFO_2, { pkgid });
611   }
612
613   std::shared_ptr<pcp::AbstractParcelable> parcelable(
614       new pcp::QueryParcelable(uid, std::move(info),
615           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
616           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
617
618   pkgmgr_client::PkgInfoClient client(parcelable, uid,
619       pkgmgr_common::ReqType::QUERY);
620   if (!client.SendRequest())
621     return PMINFO_R_ERROR;
622
623   auto ptr = client.GetResultParcel();
624   if (ptr == nullptr) {
625     LOG(ERROR) << "Fail to get return parcelable";
626     return PMINFO_R_ERROR;
627   }
628
629   if (ptr->GetRequestResult() != PMINFO_R_OK) {
630     LOG(ERROR) << "Request fail";
631     return ptr->GetRequestResult();
632   }
633
634   if (ptr->GetType() != pcp::ParcelableType::Result) {
635     LOG(ERROR) << "Invalid parcelable type";
636     return PMINFO_R_ERROR;
637   }
638
639   std::shared_ptr<pcp::ResultParcelable> return_parcel(
640       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
641
642   if (return_parcel->GetCol() != 3) {
643     LOG(ERROR) << "Invalid result";
644     return PMINFO_R_ERROR;
645   }
646
647   auto result_list = return_parcel->GetResult();
648   if (result_list.size() == 0)
649     return PMINFO_R_ENOENT;
650
651   GSList* tmp_list = nullptr;
652   for (auto& result : result_list) {
653     if (result.size() != 3) {
654       LOG(ERROR) << "Invalid result";
655       g_slist_free_full(tmp_list, __free_update_info);
656       return PMINFO_R_ERROR;
657     }
658     updateinfo_x* update_info = reinterpret_cast<updateinfo_x*>(
659         calloc(1, sizeof(updateinfo_x)));
660     if (update_info == nullptr) {
661       LOG(ERROR) << "Out of memory";
662       g_slist_free_full(tmp_list, __free_update_info);
663       return PMINFO_R_ERROR;
664     }
665     update_info->pkgid = strdup(result[0].c_str());
666     update_info->version = strdup(result[1].c_str());
667     pkgmgrinfo_updateinfo_update_type convert_type;
668     ret = __convert_update_type(result[2].c_str(), &convert_type);
669     if (ret != 0) {
670       __free_update_info(update_info);
671       g_slist_free_full(tmp_list, __free_update_info);
672       return PMINFO_R_ERROR;
673     }
674     update_info->type = static_cast<int>(convert_type);
675     tmp_list = g_slist_prepend(tmp_list, update_info);
676   }
677
678   *update_info_list = tmp_list;
679   return PMINFO_R_OK;
680 }
681
682 extern "C" EXPORT_API int _pkginfo_set_usr_installed_storage(const char* pkgid,
683     INSTALL_LOCATION location, const char* external_pkg_path, uid_t uid) {
684   const char* location_str;
685
686   if (location == INSTALL_INTERNAL)
687     location_str = "installed_internal";
688   else if (location == INSTALL_EXTERNAL)
689     location_str = "installed_external";
690   else
691     location_str = "installed_extended";
692
693   std::shared_ptr<pcp::AbstractParcelable> parcelable(
694       new pcp::QueryParcelable(uid, { {
695               QUERY_INDEX_PKGINFO_SET_USR_INSTALLED_STORAGE_1, {
696                 location_str,
697                 external_pkg_path,
698                 pkgid
699               }
700             }, {
701               QUERY_INDEX_PKGINFO_SET_USR_INSTALLED_STORAGE_2, {
702                 location_str,
703                 external_pkg_path,
704                 pkgid
705               }
706             },
707           },
708           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
709           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_WRITE));
710
711   pkgmgr_client::PkgInfoClient client(parcelable, uid,
712       pkgmgr_common::ReqType::QUERY);
713   if (!client.SendRequest())
714     return PMINFO_R_ERROR;
715
716   auto ptr = client.GetResultParcel();
717   if (ptr == nullptr) {
718     LOG(ERROR) << "Fail to get return parcelable";
719     return PMINFO_R_ERROR;
720   }
721
722   if (ptr->GetRequestResult() != PMINFO_R_OK) {
723     LOG(ERROR) << "Request fail";
724     return ptr->GetRequestResult();
725   }
726
727   if (ptr->GetType() != pcp::ParcelableType::Result) {
728     LOG(ERROR) << "Invalid parcelable type";
729     return PMINFO_R_ERROR;
730   }
731
732   return PMINFO_R_OK;
733 }
734
735 extern "C" EXPORT_API int _certinfo_compare_pkg_certinfo(const char* l_pkgid,
736     const char* r_pkgid, pkgmgrinfo_cert_compare_result_type_e* result) {
737   std::shared_ptr<pcp::AbstractParcelable> parcelable(
738       new pcp::QueryParcelable(0,
739           { QUERY_INDEX_CERTINFO_COMPARE_PKG_CERTINFO, { l_pkgid, r_pkgid } },
740           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_CERTDB,
741           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
742   pkgmgr_client::PkgInfoClient client(parcelable, 0,
743       pkgmgr_common::ReqType::QUERY);
744   if (!client.SendRequest())
745     return PMINFO_R_ERROR;
746
747   auto ptr = client.GetResultParcel();
748   if (ptr == nullptr) {
749     LOG(ERROR) << "Fail to get return parcelable";
750     return PMINFO_R_ERROR;
751   }
752
753   if (ptr->GetRequestResult() != PMINFO_R_OK) {
754     LOG(ERROR) << "Request fail";
755     return ptr->GetRequestResult();
756   }
757
758   if (ptr->GetType() != pcp::ParcelableType::Result) {
759     LOG(ERROR) << "Invalid parcelable type";
760     return PMINFO_R_ERROR;
761   }
762
763   std::shared_ptr<pcp::ResultParcelable> return_parcel(
764       std::static_pointer_cast<pcp::ResultParcelable>(
765           ptr));
766
767   auto certinfo_list = return_parcel->GetResult();
768
769   std::map<std::string, std::string> result_map;
770   result_map.insert(make_pair(std::string(l_pkgid), "-1"));
771   result_map.insert(make_pair(std::string(r_pkgid), "-1"));
772
773   for (auto& certinfo : certinfo_list)
774     result_map[certinfo.front()] = certinfo.back();
775
776   auto l_iter = result_map.find(l_pkgid);
777   auto r_iter = result_map.find(r_pkgid);
778   if (l_iter->second == "-1" && r_iter->second == "-1")
779     *result = PMINFO_CERT_COMPARE_BOTH_NO_CERT;
780   else if (l_iter->second == "-1")
781     *result = PMINFO_CERT_COMPARE_LHS_NO_CERT;
782   else if (r_iter->second == "-1")
783     *result = PMINFO_CERT_COMPARE_RHS_NO_CERT;
784   else if (l_iter->second == r_iter->second)
785     *result = PMINFO_CERT_COMPARE_MATCH;
786   else
787     *result = PMINFO_CERT_COMPARE_MISMATCH;
788
789   return PMINFO_R_OK;
790 }
791
792 extern "C" EXPORT_API int _certinfo_compare_app_certinfo(uid_t uid,
793     const char* l_appid, const char* r_appid,
794     pkgmgrinfo_cert_compare_result_type_e* result) {
795   std::shared_ptr<pcp::AbstractParcelable> parcelable(
796       new pcp::QueryParcelable(uid,
797           { QUERY_INDEX_CERTINFO_COMPARE_APP_CERTINFO, { l_appid, r_appid } },
798           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
799           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_READ));
800   pkgmgr_client::PkgInfoClient client(parcelable, uid,
801       pkgmgr_common::ReqType::QUERY);
802   if (!client.SendRequest())
803     return PMINFO_R_ERROR;
804
805   auto ptr = client.GetResultParcel();
806   if (ptr == nullptr) {
807     LOG(ERROR) << "Fail to get return parcelable";
808     return PMINFO_R_ERROR;
809   }
810
811   if (ptr->GetRequestResult() != PMINFO_R_OK) {
812     LOG(ERROR) << "Request fail";
813     return ptr->GetRequestResult();
814   }
815
816   if (ptr->GetType() != pcp::ParcelableType::Result) {
817     LOG(ERROR) << "Invalid parcelable type";
818     return PMINFO_R_ERROR;
819   }
820
821   std::shared_ptr<pcp::ResultParcelable> return_parcel(
822       std::static_pointer_cast<pcp::ResultParcelable>(ptr));
823
824   auto pkgid_list = return_parcel->GetResult();
825   std::map<std::string, std::string> result_map;
826   for (auto& pkgid : pkgid_list)
827     result_map.insert(make_pair(pkgid.front(), pkgid.back()));
828
829   auto l_iter = result_map.find(l_appid);
830   if (l_iter == result_map.end()) {
831     LOG(ERROR) << "Cannot find pkgid of app " << l_appid
832         << " for uid " << uid;
833     return PMINFO_R_ENOENT;
834   }
835   auto r_iter = result_map.find(r_appid);
836   if (r_iter == result_map.end()) {
837     LOG(ERROR) << "Cannot find pkgid of app " << r_appid
838         << " for uid " << uid;
839     return PMINFO_R_ENOENT;
840   }
841
842   const char* l_pkgid = l_iter->second.c_str();
843   const char* r_pkgid = r_iter->second.c_str();
844
845   return _certinfo_compare_pkg_certinfo(l_pkgid, r_pkgid, result);
846 }
847
848 extern "C" EXPORT_API int _parser_execute_write_query(
849     int query_index, const char** query_args, unsigned int arg_cnt, uid_t uid) {
850   std::vector<const char*> args;
851
852   for (unsigned int i = 0; i < arg_cnt; i++)
853     args.push_back(query_args[i]);
854
855   std::shared_ptr<pcp::AbstractParcelable> parcelable(
856       new pcp::QueryParcelable(uid, { query_index, std::move(args) },
857           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
858           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_WRITE));
859
860   pkgmgr_client::PkgInfoClient client(parcelable, uid,
861                                       pkgmgr_common::ReqType::QUERY);
862   if (!client.SendRequest())
863     return -1;
864
865   auto ptr = client.GetResultParcel();
866   if (ptr == nullptr) {
867     LOG(ERROR) << "Fail to get return parcelable";
868     return -1;
869   }
870
871   if (ptr->GetRequestResult() != PMINFO_R_OK) {
872     LOG(ERROR) << "Request fail";
873     return -1;
874   }
875
876   if (ptr->GetType() != pcp::ParcelableType::Result) {
877     LOG(ERROR) << "Invalid parcelable type";
878     return -1;
879   }
880   return 0;
881 }
882
883 extern "C" EXPORT_API int _parser_execute_write_queries(
884     int query_index, const char*** query_args, unsigned int arg_cnt,
885     unsigned int query_cnt, uid_t uid) {
886   std::vector<std::pair<int, std::vector<const char*>>> queries;
887
888   for (unsigned int i = 0; i < query_cnt; i++) {
889     std::vector<const char*> args;
890     for (unsigned int j = 0; j < arg_cnt; j++)
891       args.push_back(query_args[i][j]);
892     queries.push_back({ query_index, std::move(args) });
893   }
894
895   std::shared_ptr<pcp::AbstractParcelable> parcelable(
896       new pcp::QueryParcelable(uid, std::move(queries),
897           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_PKGDB,
898           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_WRITE));
899
900   pkgmgr_client::PkgInfoClient client(parcelable, uid,
901       pkgmgr_common::ReqType::QUERY);
902   if (!client.SendRequest())
903     return -1;
904
905   auto ptr = client.GetResultParcel();
906   if (ptr == nullptr) {
907     LOG(ERROR) << "Fail to get return parcelable";
908     return -1;
909   }
910
911   if (ptr->GetRequestResult() != PMINFO_R_OK) {
912     LOG(ERROR) << "Request fail";
913     return -1;
914   }
915
916   if (ptr->GetType() != pcp::ParcelableType::Result) {
917     LOG(ERROR) << "Invalid parcelable type";
918     return -1;
919   }
920
921   return 0;
922 }
923
924 extern "C" EXPORT_API int _parser_insert_manifest_info(
925     manifest_x* mfx, uid_t uid) {
926   auto parcelable =
927       std::make_shared<pcp::PkgInfoParcelable>(uid,
928           std::vector<package_x*>{mfx}, WriteType::Insert, false);
929
930   pkgmgr_client::PkgInfoClient client(parcelable, uid,
931       pkgmgr_common::ReqType::SET_PKG_INFO);
932   if (!client.SendRequest())
933     return -1;
934
935   auto ptr = client.GetResultParcel();
936   if (ptr == nullptr) {
937     LOG(ERROR) << "Fail to get return parcelable";
938     return -1;
939   }
940
941   if (ptr->GetRequestResult() != PMINFO_R_OK) {
942     LOG(ERROR) << "Request fail";
943     return -1;
944   }
945
946   if (ptr->GetType() != pcp::ParcelableType::Result) {
947     LOG(ERROR) << "Invalid parcelable type";
948     return -1;
949   }
950
951   return 0;
952 }
953
954 extern "C" EXPORT_API int _parser_update_manifest_info(
955     manifest_x* mfx, uid_t uid) {
956   auto parcelable =
957       std::make_shared<pcp::PkgInfoParcelable>(uid,
958           std::vector<package_x*>{mfx}, WriteType::Update, false);
959
960   pkgmgr_client::PkgInfoClient client(parcelable, uid,
961       pkgmgr_common::ReqType::SET_PKG_INFO);
962   if (!client.SendRequest())
963     return -1;
964
965   auto ptr = client.GetResultParcel();
966   if (ptr == nullptr) {
967     LOG(ERROR) << "Fail to get return parcelable";
968     return -1;
969   }
970
971   if (ptr->GetRequestResult() != PMINFO_R_OK) {
972     LOG(ERROR) << "Request fail";
973     return -1;
974   }
975
976   if (ptr->GetType() != pcp::ParcelableType::Result) {
977     LOG(ERROR) << "Invalid parcelable type";
978     return -1;
979   }
980
981   return 0;
982 }
983
984 extern "C" EXPORT_API int _parser_delete_manifest_info(
985     manifest_x* mfx, uid_t uid) {
986   auto parcelable =
987       std::make_shared<pcp::PkgInfoParcelable>(uid,
988           std::vector<package_x*>{mfx}, WriteType::Delete, false);
989
990   pkgmgr_client::PkgInfoClient client(parcelable, uid,
991       pkgmgr_common::ReqType::SET_PKG_INFO);
992   if (!client.SendRequest())
993     return -1;
994
995   auto ptr = client.GetResultParcel();
996   if (ptr == nullptr) {
997     LOG(ERROR) << "Fail to get return parcelable";
998     return -1;
999   }
1000
1001   if (ptr->GetRequestResult() != PMINFO_R_OK) {
1002     LOG(ERROR) << "Request fail";
1003     return -1;
1004   }
1005
1006   if (ptr->GetType() != pcp::ParcelableType::Result) {
1007     LOG(ERROR) << "Invalid parcelable type";
1008     return -1;
1009   }
1010
1011   return 0;
1012 }
1013
1014 extern "C" EXPORT_API int _pkginfo_insert_certinfo(const char* pkgid,
1015     pkgmgr_certinfo_x* cert, uid_t uid) {
1016   std::shared_ptr<pcp::AbstractParcelable> parcelable(
1017       new pcp::CertInfoParcelable(uid, cert, false));
1018   pkgmgr_client::PkgInfoClient client(parcelable, uid,
1019       pkgmgr_common::ReqType::SET_CERT_INFO);
1020
1021   if (!client.SendRequest())
1022     return PMINFO_R_ERROR;
1023
1024   auto ptr = client.GetResultParcel();
1025   if (ptr == nullptr) {
1026     LOG(ERROR) << "Fail to get return parcelable";
1027     return PMINFO_R_ERROR;
1028   }
1029
1030   if (ptr->GetRequestResult() != PMINFO_R_OK) {
1031     LOG(ERROR) << "Request fail";
1032     return ptr->GetRequestResult();
1033   }
1034
1035   if (ptr->GetType() != pcp::ParcelableType::Result) {
1036     LOG(ERROR) << "Invalid parcelable type";
1037     return PMINFO_R_ERROR;
1038   }
1039
1040   return PMINFO_R_OK;
1041 }
1042
1043 extern "C" EXPORT_API int _pkginfo_get_certinfo(const char* pkgid,
1044     pkgmgr_certinfo_x* cert, uid_t uid) {
1045   std::shared_ptr<pcp::AbstractParcelable> parcelable(
1046       new pcp::CertInfoParcelable(uid,
1047           std::string(pkgid)));
1048
1049   pkgmgr_client::PkgInfoClient client(parcelable, uid,
1050                                       pkgmgr_common::ReqType::GET_CERT_INFO);
1051   if (!client.SendRequest())
1052     return PMINFO_R_ERROR;
1053
1054   auto ptr = client.GetResultParcel();
1055   if (ptr == nullptr) {
1056     LOG(ERROR) << "Fail to get return parcelable";
1057     return PMINFO_R_ERROR;
1058   }
1059
1060   if (ptr->GetRequestResult() != PMINFO_R_OK) {
1061     LOG(ERROR) << "Request fail";
1062     return ptr->GetRequestResult();
1063   }
1064
1065   if (ptr->GetType() != pcp::ParcelableType::CertInfo) {
1066     LOG(ERROR) << "Invalid parcelable type";
1067     return PMINFO_R_ERROR;
1068   }
1069
1070   std::shared_ptr<pcp::CertInfoParcelable> return_parcel(
1071       std::static_pointer_cast<pcp::CertInfoParcelable>(ptr));
1072
1073   pkgmgr_certinfo_x* certinfo = return_parcel->ExtractCertInfo();
1074   if (certinfo == nullptr)
1075     return PMINFO_R_ERROR;
1076
1077   cert->for_all_users = certinfo->for_all_users;
1078   cert->pkgid = certinfo->pkgid;
1079   certinfo->pkgid = nullptr;
1080   cert->cert_value = certinfo->cert_value;
1081   certinfo->cert_value = nullptr;
1082   for (int i = 0; i < MAX_CERT_TYPE; i++) {
1083     cert->cert_info[i] = certinfo->cert_info[i];
1084     certinfo->cert_info[i] = nullptr;
1085   }
1086   for (int i = 0; i < MAX_CERT_TYPE; i++)
1087     cert->cert_id[i] = certinfo->cert_id[i];
1088
1089   free(certinfo);
1090
1091   return PMINFO_R_OK;
1092 }
1093
1094 extern "C" EXPORT_API int _pkginfo_delete_certinfo(const char* pkgid) {
1095   std::shared_ptr<pcp::AbstractParcelable> parcelable(
1096       new pcp::QueryParcelable(0,
1097           { QUERY_INDEX_PKGINFO_DELETE_CERTINFO, { pkgid } },
1098           pcd::AbstractDBHandler::DBType::DB_TYPE_FILE_CERTDB,
1099           pcd::AbstractDBHandler::OperationType::OPERATION_TYPE_WRITE));
1100
1101   pkgmgr_client::PkgInfoClient client(parcelable, 0,
1102                                       pkgmgr_common::ReqType::QUERY);
1103   if (!client.SendRequest())
1104     return PMINFO_R_ERROR;
1105
1106   auto ptr = client.GetResultParcel();
1107   if (ptr == nullptr) {
1108     LOG(ERROR) << "Fail to get return parcelable";
1109     return PMINFO_R_ERROR;
1110   }
1111
1112   if (ptr->GetRequestResult() != PMINFO_R_OK) {
1113     LOG(ERROR) << "Request fail";
1114     return PMINFO_R_ERROR;
1115   }
1116
1117   if (ptr->GetType() != pcp::ParcelableType::Result) {
1118     LOG(ERROR) << "Invalid parcelable type";
1119     return PMINFO_R_ERROR;
1120   }
1121
1122   return PMINFO_R_OK;
1123 }
1124
1125 extern "C" EXPORT_API int _parser_clear_cache_memory_db(uid_t uid) {
1126   std::shared_ptr<pcp::AbstractParcelable> parcelable(
1127       new pcp::CommandParcelable(uid, CommandType::RemoveCache));
1128
1129   pkgmgr_client::PkgInfoClient client(parcelable, uid,
1130                                       pkgmgr_common::ReqType::COMMAND);
1131
1132   if (!client.SendRequest())
1133     return PMINFO_R_ERROR;
1134
1135   auto ptr = client.GetResultParcel();
1136   if (ptr == nullptr) {
1137     LOG(ERROR) << "Fail to get return parcelable";
1138     return PMINFO_R_ERROR;
1139   }
1140
1141   if (ptr->GetRequestResult() != PMINFO_R_OK) {
1142     LOG(ERROR) << "Request fail";
1143     return PMINFO_R_ERROR;
1144   }
1145
1146   if (ptr->GetType() != pcp::ParcelableType::Result) {
1147     LOG(ERROR) << "Invalid parcelable type";
1148     return PMINFO_R_ERROR;
1149   }
1150
1151   return PMINFO_R_OK;
1152 }