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