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