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