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