Merge remote-tracking branch 'origin/master' into implement_api2
[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 <string>
22
23 #include "sqlite3.h"
24 #include "glib.h"
25
26 #include "pkgmgrinfo_private.h"
27
28 #include "logging.hh"
29 #include "common/parcel/appinfo_parcelable.hh"
30 #include "common/parcel/filter_parcelable.hh"
31 #include "common/parcel/pkginfo_parcelable.hh"
32 #include "common/parcel/query_parcelable.hh"
33 #include "common/parcel/result_parcelable.hh"
34
35 #include "client/pkginfo_client.hh"
36
37 #include <parcel.hh>
38
39 #ifdef LOG_TAG
40 #undef LOG_TAG
41 #endif
42 #define LOG_TAG "PKGMGR_INFO"
43
44 #ifdef EXPORT_API
45 #undef EXPORT_API
46 #endif
47 #define EXPORT_API __attribute__((visibility("default")))
48
49 extern "C" EXPORT_API int _pkginfo_get_packages(uid_t uid,
50             pkgmgrinfo_filter_x *filter, int flag, GHashTable *packages) { 
51         std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcelable(
52                         new pkgmgr_common::parcel::FilterParcelable(uid,
53                                         static_cast<pkgmgrinfo_filter_x*>(filter), flag));
54
55         pkgmgr_client::PkgInfoClient client(parcelable, uid, 
56                         pkgmgr_common::ReqType::GET_PKG_INFO);
57         if (!client.SendRequest())
58       return PMINFO_R_ERROR;
59
60         std::shared_ptr<pkgmgr_common::parcel::PkgInfoParcelable> return_parcel(
61                         std::static_pointer_cast<pkgmgr_common::parcel::PkgInfoParcelable>(
62                                         client.GetResultParcel()));
63
64         tizen_base::Parcel parcel;
65         parcel.ReadParcelable(return_parcel.get());
66
67         auto result_list = return_parcel->GetPkgInfo();
68         // TODO: check noentry error has returned if size of result_list is 0
69         for (auto& pkginfo : result_list) {
70                 g_hash_table_insert(packages, (gpointer)pkginfo->package, (gpointer)pkginfo);
71                 // TODO: remove element from list. is this work?
72                 pkginfo = nullptr;      
73         }
74
75         return PMINFO_R_OK;
76 }
77
78 // TODO: Need to add target db uid to identify which database to be searched
79 extern "C" EXPORT_API int _appinfo_get_applications(uid_t db_uid, uid_t uid,
80                 pkgmgrinfo_filter_x *filter, int flag, GHashTable *packages) {
81         std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcelable(
82                         new pkgmgr_common::parcel::FilterParcelable(uid,
83                                         static_cast<pkgmgrinfo_filter_x*>(filter), flag));
84
85         pkgmgr_client::PkgInfoClient client(parcelable, uid, pkgmgr_common::ReqType::GET_APP_INFO);
86         if (!client.SendRequest())
87       return PMINFO_R_ERROR;
88
89         std::shared_ptr<pkgmgr_common::parcel::AppInfoParcelable> return_parcel(
90                         std::static_pointer_cast<pkgmgr_common::parcel::AppInfoParcelable>(
91                                         client.GetResultParcel()));
92
93         tizen_base::Parcel parcel;
94         parcel.ReadParcelable(return_parcel.get());
95         auto result_list = return_parcel->GetAppInfo();
96         for (auto& appinfo : result_list) {
97                 g_hash_table_insert(packages, (gpointer)appinfo->appid, (gpointer)appinfo);
98                 // TODO: remove element from list. is this work?
99                 appinfo = nullptr;      
100         }
101
102         return PMINFO_R_OK;
103 }
104
105 extern "C" EXPORT_API char *_appinfo_get_localed_label(
106                 const char *appid, const char *locale, uid_t uid) {
107         char *query = nullptr;
108     query = sqlite3_mprintf(
109                         "SELECT COALESCE((SELECT app_label FROM package_app_localized_info "
110                         "WHERE app_id=%Q AND app_locale=%Q),"
111                         "(SELECT app_label FROM package_app_localized_info WHERE "
112                         "app_id=%Q AND app_locale='No Locale'))", appid, locale, appid);
113         if (query == nullptr) {
114                 LOG(ERROR) << "Out of memory";
115                 return nullptr;
116         }
117
118         std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcelable(
119                         new pkgmgr_common::parcel::QueryParcelable(uid, std::string(query)));
120
121         pkgmgr_client::PkgInfoClient client(parcelable, uid, 
122                         pkgmgr_common::ReqType::QUERY);
123         if (!client.SendRequest())
124                 return nullptr;
125         sqlite3_free(query);
126         std::shared_ptr<pkgmgr_common::parcel::ResultParcelable> return_parcel(
127                                 std::static_pointer_cast<pkgmgr_common::parcel::ResultParcelable>(
128                                                 client.GetResultParcel()));
129         tizen_base::Parcel parcel;
130         parcel.ReadParcelable(return_parcel.get());
131         
132         // result_list is vector of string vector
133         char *label;
134         auto result_list = return_parcel->GetResult();
135         for (auto result : result_list) {
136                 // result is string vector
137                 // it only has one string or not.
138                 if (result.front().empty() || result.front().length() == 0)
139                         return nullptr;
140                 label = strdup(result.front().c_str());
141                 if (label == nullptr) {
142                         LOG(ERROR) << "Out of memory";
143                         return nullptr;
144                 }
145         }
146
147         return label;
148 }
149
150 extern "C" EXPORT_API int _appinfo_get_datacontrol_info(
151                 const char *providerid, const char *type, uid_t uid, 
152                 char **appid, char **access) {
153         char *query = nullptr;
154         query = sqlite3_mprintf("SELECT app_id, access FROM "
155                         "package_app_data_control WHERE "
156                         "providerid=%Q AND type=%Q", providerid, type);
157         if (query == nullptr) {
158                 LOG(ERROR) << "Out of memory";
159                 return PMINFO_R_ERROR;
160         }
161
162         std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcelable(
163                         new pkgmgr_common::parcel::QueryParcelable(uid, std::string(query)));
164
165         pkgmgr_client::PkgInfoClient client(parcelable, uid,
166                         pkgmgr_common::ReqType::QUERY);
167         if (!client.SendRequest())
168                 return PMINFO_R_ERROR;
169         // TODO: deliver rawdata to reqhandler directly if server is not working
170
171         std::shared_ptr<pkgmgr_common::parcel::ResultParcelable> return_parcel(
172                         std::static_pointer_cast<pkgmgr_common::parcel::ResultParcelable>(
173                                         client.GetResultParcel()));
174         tizen_base::Parcel parcel;
175         parcel.ReadParcelable(return_parcel.get());
176         sqlite3_free(query);
177         // result_list is vector of string vector
178         auto result_list = return_parcel->GetResult();
179         if (result_list.size() == 0)
180                 return PMINFO_R_ENOENT;
181         for (auto result : result_list) {
182                 if (result.size() != 2)
183                         return PMINFO_R_ERROR;
184                 if (result.front().empty() || result.front().size() == 0 ||
185                                 result.back().empty() || result.back().size() == 0)
186                         return PMINFO_R_ERROR;
187                 *appid = strdup(result.front().c_str());
188                 *access = strdup(result.back().c_str());
189                 if (*appid == nullptr || *access == nullptr) {
190                         LOG(ERROR) << "Out of memory";
191                         return PMINFO_R_ERROR;
192                 }
193         }
194
195         return PMINFO_R_OK;
196 }
197
198 extern "C" EXPORT_API int _appinfo_get_datacontrol_appid(
199                 const char *providerid, uid_t uid, char **appid) {
200         char *query = nullptr;
201
202         query = sqlite3_mprintf("SELECT app_id FROM package_app_data_control "
203                 "WHERE providerid=%Q", providerid);
204         if (query == NULL) {
205                 LOGE("Out of memory");
206                 return PMINFO_R_ERROR;
207         }
208         std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcelable(
209                         new pkgmgr_common::parcel::QueryParcelable(uid, std::string(query)));
210
211         pkgmgr_client::PkgInfoClient client(parcelable, uid,
212                         pkgmgr_common::ReqType::QUERY);
213         if (!client.SendRequest())
214                 return PMINFO_R_ERROR;
215         // TODO: deliver rawdata to reqhandler directly if server is not working
216
217         std::shared_ptr<pkgmgr_common::parcel::ResultParcelable> return_parcel(
218                         std::static_pointer_cast<pkgmgr_common::parcel::ResultParcelable>(
219                                         client.GetResultParcel()));
220         tizen_base::Parcel parcel;
221         parcel.ReadParcelable(return_parcel.get());
222         sqlite3_free(query);
223
224         // result_list is vector of string vector
225         auto result_list = return_parcel->GetResult();
226         if (result_list.size() == 0)
227                 return PMINFO_R_ENOENT;
228         for (auto result : result_list) {
229                 if (result.size() != 1)
230                         return PMINFO_R_ERROR;
231                 if (result.front().empty() || result.front().size() == 0)
232                         return PMINFO_R_ERROR;
233                 *appid = strdup(result.front().c_str());
234                 if (*appid == nullptr) {
235                         LOG(ERROR) << "Out of memory";
236                         return PMINFO_R_ERROR;
237                 }
238         }
239
240         return PMINFO_R_OK;
241 }
242
243 extern "C" EXPORT_API int _appinfo_get_datacontrol_trusted_info(
244                 const char *providerid, const char *type, uid_t uid, 
245                 char **appid, char **trusted) {
246         char *query = nullptr;
247         query = sqlite3_mprintf(
248                         "SELECT app_id, trusted FROM package_app_data_control "
249                         "WHERE providerid=%Q AND type=%Q", providerid, type);
250         if (query == NULL) {
251                 LOGE("Out of memory");
252                 return PMINFO_R_ERROR;
253         }
254
255         std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcelable(
256                         new pkgmgr_common::parcel::QueryParcelable(uid, std::string(query)));
257
258         pkgmgr_client::PkgInfoClient client(parcelable, uid,
259                         pkgmgr_common::ReqType::QUERY);
260         if (!client.SendRequest())
261                 return PMINFO_R_ERROR;
262         // TODO: deliver rawdata to reqhandler directly if server is not working
263
264         std::shared_ptr<pkgmgr_common::parcel::ResultParcelable> return_parcel(
265                         std::static_pointer_cast<pkgmgr_common::parcel::ResultParcelable>(
266                                         client.GetResultParcel()));
267         tizen_base::Parcel parcel;
268         parcel.ReadParcelable(return_parcel.get());
269         sqlite3_free(query);
270         // result_list is vector of string vector
271         auto result_list = return_parcel->GetResult();
272         if (result_list.size() == 0)
273                 return PMINFO_R_ENOENT;
274         for (auto result : result_list) {
275                 if (result.size() != 2)
276                         return PMINFO_R_ERROR;
277                 if (result.front().empty() || result.front().size() == 0 ||
278                                 result.back().empty() || result.back().size() == 0)
279                         return PMINFO_R_ERROR;
280                 *appid = strdup(result.front().c_str());
281                 *trusted = strdup(result.back().c_str());
282                 if (*appid == nullptr || *trusted == nullptr) {
283                         LOG(ERROR) << "Out of memory";
284                         return PMINFO_R_ERROR;
285                 }
286         }
287
288         return PMINFO_R_OK;
289 }
290
291 extern "C" EXPORT_API int _appinfo_get_datacontrol_privileges(
292                 const char *providerid, const char *type, uid_t uid, 
293                 GList **privileges) {
294         char *query = nullptr;
295         query = sqlite3_mprintf(
296                         "SELECT privilege FROM package_app_data_control_privilege "
297                         "WHERE providerid=%Q AND type=%Q", providerid, type);
298         if (query == NULL) {
299                 LOGE("Out of memory");
300                 return PMINFO_R_ERROR;
301         }       
302
303         std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcelable(
304                         new pkgmgr_common::parcel::QueryParcelable(uid, std::string(query)));
305
306         pkgmgr_client::PkgInfoClient client(parcelable, uid,
307                         pkgmgr_common::ReqType::QUERY);
308         if (!client.SendRequest())
309                 return PMINFO_R_ERROR;
310         // TODO: deliver rawdata to reqhandler directly if server is not working
311
312         std::shared_ptr<pkgmgr_common::parcel::ResultParcelable> return_parcel(
313                         std::static_pointer_cast<pkgmgr_common::parcel::ResultParcelable>(
314                                         client.GetResultParcel()));
315         tizen_base::Parcel parcel;
316         parcel.ReadParcelable(return_parcel.get());
317         sqlite3_free(query);
318         // result_list is vector of string vector
319         auto result_list = return_parcel->GetResult();
320         if (result_list.size() == 0)
321                 return PMINFO_R_ENOENT;
322         
323         for (auto result : result_list) {
324                 if (result.size() != 1)
325                         return PMINFO_R_ERROR;
326                 if (result.front().empty() || result.front().size() == 0)
327                         return PMINFO_R_ERROR;
328                 char *privilege = strdup(result.front().c_str());
329                 if (privilege == nullptr) {
330                         LOG(ERROR) << "Out of memory";
331                         return PMINFO_R_ERROR;
332                 }
333                 *privileges = g_list_append(*privileges, privilege);
334         }
335
336         return PMINFO_R_OK;
337 }
338
339 extern "C" EXPORT_API int _appinfo_get_appcontrol_privileges(
340                 const char *appid, const char *operation, uid_t uid, GList **privileges) {
341         char *query = nullptr;
342         query = sqlite3_mprintf(
343                 "SELECT app_control, privilege FROM package_app_app_control_privilege "
344                 "WHERE app_id=%Q", appid);
345         if (query == NULL) {
346                 LOG(ERROR) << "Out of memory";
347                 return PMINFO_R_ERROR;
348         }       
349
350         std::shared_ptr<pkgmgr_common::parcel::AbstractParcelable> parcelable(
351                         new pkgmgr_common::parcel::QueryParcelable(uid, std::string(query)));
352
353         pkgmgr_client::PkgInfoClient client(parcelable, uid,
354                         pkgmgr_common::ReqType::QUERY);
355         if (!client.SendRequest())
356                 return PMINFO_R_ERROR;
357         // TODO: deliver rawdata to reqhandler directly if server is not working
358
359         std::shared_ptr<pkgmgr_common::parcel::ResultParcelable> return_parcel(
360                         std::static_pointer_cast<pkgmgr_common::parcel::ResultParcelable>(
361                                         client.GetResultParcel()));
362         tizen_base::Parcel parcel;
363         parcel.ReadParcelable(return_parcel.get());
364         sqlite3_free(query);
365         // result_list is vector of string vector
366         auto result_list = return_parcel->GetResult();
367         if (result_list.size() == 0)
368                 return PMINFO_R_ENOENT;
369         
370         for (auto result : result_list) {
371                 if (result.size() != 2)
372                         return PMINFO_R_ERROR;
373                 if (result.front().empty() || result.front().size() == 0 ||
374                                 result.back().empty() || result.back().size() == 0)
375                         return PMINFO_R_ERROR;
376                 std::string app_control = result.front();
377                 std::stringstream ss(app_control);
378                 std::string token;
379                 while (std::getline(ss, token, '|')) {
380                         if (token.compare(std::string(operation))) {
381                                 char *privilege = strdup(result.back().c_str());
382                                 if (privilege == nullptr) {
383                                         LOG(ERROR) << "Out of memory";
384                                         return PMINFO_R_ERROR;
385                                 }
386                                 *privileges = g_list_append(*privileges, privilege);
387                         }
388                 }
389         }
390         return PMINFO_R_OK;
391 }