Remove setuid bit
[platform/core/appfw/ail.git] / src / ail_filter.c
1 /*
2  * ail
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22
23
24 #include <stdlib.h>
25 #include <glib.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include "ail.h"
29 #include "ail_private.h"
30 #include "ail_convert.h"
31 #include "ail_sql.h"
32 #include "ail_package.h"
33 #include "ail_db.h"
34
35 char *_get_where_clause(ail_filter_h filter);
36
37 struct ail_filter {
38         GSList *list;
39 };
40
41 static inline void _add_cond_to_filter(ail_filter_h filter, struct element *cond)
42 {
43         filter->list = g_slist_append(filter->list, cond);
44 }
45
46 EXPORT_API ail_error_e ail_filter_new(ail_filter_h *filter)
47 {
48         struct ail_filter *f;
49
50         retv_if(filter == NULL, AIL_ERROR_INVALID_PARAMETER);
51
52         f = (struct ail_filter *)calloc(1, sizeof(struct ail_filter));
53         retv_if(f == NULL, AIL_ERROR_OUT_OF_MEMORY);
54
55         *filter = f;
56
57         return AIL_ERROR_OK;
58 }
59
60 static inline void _destroy_cond(gpointer data, gpointer user_data)
61 {
62         if (!data)
63                 return;
64
65         struct element *cond;
66         cond  = (struct element *)data;
67
68         int t;
69         ELEMENT_TYPE(cond, t);
70         if (VAL_TYPE_STR == t) {
71                 if (ELEMENT_STR(cond)->value)
72                         free(ELEMENT_STR(cond)->value);
73         }
74         free(cond);
75         return;
76 }
77
78
79 EXPORT_API ail_error_e ail_filter_destroy(ail_filter_h filter)
80 {
81         retv_if(filter == NULL, AIL_ERROR_INVALID_PARAMETER);
82
83         if (filter->list) {
84                 g_slist_foreach(filter->list, _destroy_cond, NULL);
85                 g_slist_free(filter->list);
86         }
87
88         free(filter);
89         db_close();
90
91         return AIL_ERROR_OK;
92 }
93
94 EXPORT_API ail_error_e ail_filter_add_bool(ail_filter_h filter, const char *property, bool value)
95 {
96         struct element *c;
97         ail_prop_bool_e prop;
98
99         retv_if(filter == NULL, AIL_ERROR_INVALID_PARAMETER);
100         retv_if(property == NULL, AIL_ERROR_INVALID_PARAMETER);
101
102         prop = _ail_convert_to_prop_bool(property);
103
104         if (prop < E_AIL_PROP_BOOL_MIN || prop > E_AIL_PROP_BOOL_MAX)
105                 return AIL_ERROR_INVALID_PARAMETER;
106
107         c = (struct element *)calloc(1, sizeof(struct element_bool));
108         retv_if(c == NULL, AIL_ERROR_OUT_OF_MEMORY);
109
110         ELEMENT_BOOL(c)->prop = (int)prop;
111         ELEMENT_BOOL(c)->value = value;
112
113         _add_cond_to_filter(filter, c);
114
115         return AIL_ERROR_OK;
116 }
117
118 EXPORT_API ail_error_e ail_filter_add_int(ail_filter_h filter, const char *property, int value)
119 {
120         struct element *c;
121         ail_prop_int_e prop;
122
123         retv_if(filter == NULL, AIL_ERROR_INVALID_PARAMETER);
124         retv_if(property == NULL, AIL_ERROR_INVALID_PARAMETER);
125
126         prop = _ail_convert_to_prop_int(property);
127
128         if (prop < E_AIL_PROP_INT_MIN || prop > E_AIL_PROP_INT_MAX)
129                 return AIL_ERROR_INVALID_PARAMETER;
130
131         c = (struct element *)calloc(1, sizeof(struct element_int));
132         retv_if(c == NULL, AIL_ERROR_OUT_OF_MEMORY);
133
134         ELEMENT_INT(c)->prop = (int)prop;
135         ELEMENT_INT(c)->value = value;
136
137         _add_cond_to_filter(filter, c);
138
139         return AIL_ERROR_OK;
140 }
141
142 EXPORT_API ail_error_e ail_filter_add_str(ail_filter_h filter, const char *property, const char *value)
143 {
144         struct element *c; /* condition */
145         ail_prop_str_e prop;
146
147         retv_if(filter == NULL, AIL_ERROR_INVALID_PARAMETER);
148         retv_if(property == NULL, AIL_ERROR_INVALID_PARAMETER);
149
150         prop = _ail_convert_to_prop_str(property);
151
152         if (prop < E_AIL_PROP_STR_MIN || prop > E_AIL_PROP_STR_MAX)
153                 return AIL_ERROR_INVALID_PARAMETER;
154
155         retv_if(value == NULL, AIL_ERROR_INVALID_PARAMETER);
156         retv_if(strlen(value) == 0, AIL_ERROR_INVALID_PARAMETER);
157
158         c = (struct element *)calloc(1, sizeof(struct element_str));
159         retv_if(c == NULL, AIL_ERROR_OUT_OF_MEMORY);
160
161         ELEMENT_STR(c)->prop = (int)prop;
162         ELEMENT_STR(c)->value = strdup(value);
163         if (!ELEMENT_STR(c)->value) {
164                 free(c);
165                 return AIL_ERROR_OUT_OF_MEMORY;
166         }
167
168         _add_cond_to_filter(filter, c);
169
170         return AIL_ERROR_OK;
171 }
172
173 static void _get_condition(gpointer data, char **condition)
174 {
175         struct element *e = (struct element *)data;
176         const char *f;
177         char buf[AIL_SQL_QUERY_MAX_LEN];
178         int t;
179
180         f =  sql_get_filter(e->prop);
181         if (f == NULL)
182                 return;
183
184         ELEMENT_TYPE(e, t);
185
186         switch (t) {
187         case VAL_TYPE_BOOL:
188                 snprintf(buf, sizeof(buf), f, ELEMENT_BOOL(e)->value);
189                 break;
190         case VAL_TYPE_INT:
191                 snprintf(buf, sizeof(buf), f, ELEMENT_INT(e)->value);
192                 break;
193         case VAL_TYPE_STR:
194                 if (E_AIL_PROP_NAME_STR == e->prop)
195                         snprintf(buf, sizeof(buf), f, ELEMENT_STR(e)->value, ELEMENT_STR(e)->value);
196                 else
197                         snprintf(buf, sizeof(buf), f, ELEMENT_STR(e)->value);
198                 break;
199         default:
200                 _E("Invalid property type");
201                 *condition = NULL;
202                 return;
203         }
204
205         *condition = strdup(buf);
206
207         return;
208 }
209
210 char *_get_where_clause(ail_filter_h filter)
211 {
212         char *c;
213         char w[AIL_SQL_QUERY_MAX_LEN] = {0,};
214         c = NULL;
215
216         GSList *l;
217
218         snprintf(w, AIL_SQL_QUERY_MAX_LEN, " WHERE ");
219
220         for (l = filter->list; l; l = g_slist_next(l)) {
221                 _get_condition(l->data, &c);
222                 if (!c)
223                         return NULL;
224                 if (*c == 0) {
225                         free(c);
226                         return NULL;
227                 }
228
229                 strncat(w, c, sizeof(w)-strlen(w)-1);
230                 w[sizeof(w) - 1] = '\0';
231                 if (c) {
232                         free(c);
233                         c = NULL;
234                 }
235
236                 if (g_slist_next(l)) {
237                         strncat(w, " and ", sizeof(w)-strlen(w)-1);
238                         w[sizeof(w) - 1] = '\0';
239                 }
240         }
241
242         return strdup(w);
243 }
244
245 EXPORT_API ail_error_e ail_filter_count_appinfo(ail_filter_h filter, int *cnt)
246 {
247         char q[AIL_SQL_QUERY_MAX_LEN];
248         char *w;
249         char *tmp_q;
250         char *l;
251         sqlite3_stmt *stmt;
252         ail_appinfo_h ai;
253         int filter_count = 0;
254
255         retv_if(!cnt, AIL_ERROR_INVALID_PARAMETER);
256
257         if (db_open(DB_OPEN_RO, GLOBAL_USER) != AIL_ERROR_OK)
258                 return AIL_ERROR_DB_FAILED;
259
260         snprintf(q, sizeof(q), "SELECT %s FROM %s", SQL_FLD_APP_INFO_WITH_LOCALNAME, SQL_TBL_APP_INFO_WITH_LOCALNAME);
261
262         tmp_q = strdup(q);
263         retv_if(tmp_q == NULL, AIL_ERROR_OUT_OF_MEMORY);
264         l = sql_get_locale();
265         if (l == NULL) {
266                 _E("Failed to get locale string");
267                 free(tmp_q);
268                 return AIL_ERROR_FAIL;
269         }
270         snprintf(q, sizeof(q), tmp_q, l);
271         free(l);
272         free(tmp_q);
273
274         if (filter && filter->list) {
275                 w = _get_where_clause(filter);
276                 retv_if(w == NULL, AIL_ERROR_FAIL);
277                 strncat(q, w, sizeof(q)-strlen(q)-1);
278                 q[sizeof(q)-1] = '\0';
279                 free(w);
280         } else {
281                 _D("No filter exists. All records are retreived");
282         }
283
284         /* is_admin */
285         if (db_prepare_globalro(q, &stmt) != AIL_ERROR_OK) {
286                 _E("db_prepare_globalro fail for query = %s", q);
287                 return AIL_ERROR_DB_FAILED;
288         }
289         ai = appinfo_create();
290         if (ai == NULL) {
291                 _E("out of memory");
292                 db_finalize(stmt);
293                 return AIL_ERROR_FAIL;
294         }
295
296         appinfo_set_stmt(ai, stmt);
297         while (db_step(stmt) == AIL_ERROR_OK) {
298
299                 if (_appinfo_check_installed_storage(ai) != AIL_ERROR_OK)
300                         continue;
301
302                 filter_count++;
303         }
304
305         db_finalize(stmt);
306
307         appinfo_destroy(ai);
308         *cnt = filter_count;
309
310         return AIL_ERROR_OK;
311 }
312
313 EXPORT_API ail_error_e ail_filter_count_usr_appinfo(ail_filter_h filter, int *cnt, uid_t uid)
314 {
315         char q[AIL_SQL_QUERY_MAX_LEN];
316         char *w;
317         char *tmp_q;
318         char *l;
319         sqlite3_stmt *stmt;
320         ail_appinfo_h ai;
321         int filter_count = 0;
322
323         retv_if(!cnt, AIL_ERROR_INVALID_PARAMETER);
324
325         /* is_admin ; redirect */
326         if (uid == GLOBAL_USER)
327                 return ail_filter_count_appinfo(filter, cnt);
328
329         if (db_open(DB_OPEN_RO, uid) != AIL_ERROR_OK)
330                 return AIL_ERROR_DB_FAILED;
331
332         snprintf(q, sizeof(q), "SELECT %s FROM %s", SQL_FLD_APP_INFO_WITH_LOCALNAME, SQL_TBL_APP_INFO_WITH_LOCALNAME);
333
334         tmp_q = strdup(q);
335         retv_if(tmp_q == NULL, AIL_ERROR_OUT_OF_MEMORY);
336         l = sql_get_locale();
337         if (NULL == l) {
338                 _E("Failed to get locale string");
339                 free(tmp_q);
340                 return AIL_ERROR_FAIL;
341         }
342         snprintf(q, sizeof(q), tmp_q, l);
343         free(l);
344         free(tmp_q);
345
346         if (filter && filter->list) {
347                 w = _get_where_clause(filter);
348                 retv_if(w == NULL, AIL_ERROR_FAIL);
349                 strncat(q, w, sizeof(q) - strlen(q) - 1);
350                 q[sizeof(q)-1] = '\0';
351                 free(w);
352         } else {
353                 _D("No filter exists. All records are retreived");
354         }
355
356         if (db_prepare(q, &stmt) != AIL_ERROR_OK) {
357                 _E("db_prepare fail for query = %s", q);
358                 return AIL_ERROR_DB_FAILED;
359         }
360
361         ai = appinfo_create();
362         if (ai == NULL) {
363                 _E("Failed to create appinfo");
364                 db_finalize(stmt);
365                 return AIL_ERROR_OUT_OF_MEMORY;
366         }
367
368         appinfo_set_stmt(ai, stmt);
369         while (db_step(stmt) == AIL_ERROR_OK) {
370                 if (_appinfo_check_installed_storage(ai) != AIL_ERROR_OK)
371                         continue;
372
373                 filter_count++;
374         }
375
376         db_finalize(stmt);
377
378         appinfo_destroy(ai);
379         *cnt = filter_count;
380
381         return AIL_ERROR_OK;
382 }
383
384
385 EXPORT_API ail_error_e ail_filter_list_appinfo_foreach(ail_filter_h filter, ail_list_appinfo_cb cb, void *user_data)
386 {
387         char q[AIL_SQL_QUERY_MAX_LEN];
388         char *tmp_q;
389         char *w;
390         char *l;
391         ail_cb_ret_e r;
392         sqlite3_stmt *stmt;
393         ail_appinfo_h ai;
394
395         retv_if(cb == NULL, AIL_ERROR_INVALID_PARAMETER);
396
397         if (db_open(DB_OPEN_RO, GLOBAL_USER) != AIL_ERROR_OK)
398                 return AIL_ERROR_DB_FAILED;
399
400         snprintf(q, sizeof(q), "SELECT %s FROM %s", SQL_FLD_APP_INFO_WITH_LOCALNAME, SQL_TBL_APP_INFO_WITH_LOCALNAME);
401
402         tmp_q = strdup(q);
403         retv_if(tmp_q == NULL, AIL_ERROR_OUT_OF_MEMORY);
404         l = sql_get_locale();
405         if (l == NULL) {
406                 _E("Failed to get locale string");
407                 free(tmp_q);
408                 return AIL_ERROR_FAIL;
409         }
410         snprintf(q, sizeof(q), tmp_q, l);
411         free(l);
412         free(tmp_q);
413
414         if (filter && filter->list) {
415                 w = _get_where_clause(filter);
416                 retv_if(w == NULL, AIL_ERROR_FAIL);
417                 strncat(q, w, sizeof(q)-strlen(q)-1);
418                 q[sizeof(q) - 1] = '\0';
419                 strncat(q, " order by app_info.package", sizeof(q) - strlen(q) - 1);
420                 q[sizeof(q) - 1] = '\0';
421                 free(w);
422         } else {
423                 _D("No filter exists. All records are retreived");
424         }
425
426         /* is_admin */
427         if (db_prepare_globalro(q, &stmt) != AIL_ERROR_OK) {
428                 _E("db_prepare fail for query = %s", q);
429                 return AIL_ERROR_DB_FAILED;
430         }
431         /* if (db_prepare_globalro(q, &stmt) != AIL_ERROR_OK) {
432                 _E("db_prepare fail for query = %s",q);
433                 return AIL_ERROR_DB_FAILED;
434         }*/
435         ai = appinfo_create();
436         if (ai == NULL) {
437                 _E("out of memory");
438                 db_finalize(stmt);
439                 return AIL_ERROR_FAIL;
440         }
441
442         appinfo_set_stmt(ai, stmt);
443         uint i = 0;
444         while ((i = db_step(stmt)) == AIL_ERROR_OK) {
445                 _E("------------------------dbstep : %u\n", i);
446                 if (_appinfo_check_installed_storage(ai) != AIL_ERROR_OK)
447                         continue;
448
449                 r = cb(ai, user_data, GLOBAL_USER);
450                 if (AIL_CB_RET_CANCEL == r)
451                         break;
452         }
453         appinfo_destroy(ai);
454
455         db_finalize(stmt);
456         return AIL_ERROR_OK;
457 }
458
459 EXPORT_API ail_error_e ail_filter_list_usr_appinfo_foreach(ail_filter_h filter, ail_list_appinfo_cb cb, void *user_data, uid_t uid)
460 {
461         char q[AIL_SQL_QUERY_MAX_LEN];
462         char *tmp_q;
463         char *w;
464         char *l;
465         ail_cb_ret_e r;
466         sqlite3_stmt *stmt;
467         ail_appinfo_h ai;
468
469         retv_if(cb == NULL, AIL_ERROR_INVALID_PARAMETER);
470
471         if (db_open(DB_OPEN_RO, uid) != AIL_ERROR_OK)
472                 return AIL_ERROR_DB_FAILED;
473
474         snprintf(q, sizeof(q), "SELECT %s FROM %s", SQL_FLD_APP_INFO_WITH_LOCALNAME, SQL_TBL_APP_INFO_WITH_LOCALNAME);
475
476         tmp_q = strdup(q);
477         retv_if(tmp_q == NULL, AIL_ERROR_OUT_OF_MEMORY);
478         l = sql_get_locale();
479         if (l == NULL) {
480                 _E("Failed to get locale string");
481                 free(tmp_q);
482                 return AIL_ERROR_FAIL;
483         }
484         snprintf(q, sizeof(q), tmp_q, l);
485         free(l);
486         free(tmp_q);
487
488         if (filter && filter->list) {
489                 w = _get_where_clause(filter);
490                 retv_if(w == NULL, AIL_ERROR_FAIL);
491                 strncat(q, w, sizeof(q) - strlen(q) - 1);
492                 q[sizeof(q) - 1] = '\0';
493                 strncat(q, " order by app_info.package", sizeof(q) - strlen(q) - 1);
494                 q[sizeof(q) - 1] = '\0';
495                 free(w);
496         } else {
497                 _D("No filter exists. All records are retreived");
498         }
499
500         /* is_admin */
501         if (db_prepare(q, &stmt) != AIL_ERROR_OK) {
502                 _E("db_prepare fail for query = %s", q);
503                 return AIL_ERROR_DB_FAILED;
504         }
505
506         ai = appinfo_create();
507         if (ai == NULL) {
508                 _E("Failed to create appinfo");
509                 db_finalize(stmt);
510                 return AIL_ERROR_DB_FAILED;
511         }
512
513         appinfo_set_stmt(ai, stmt);
514         uint i = 0;
515         while ((i = db_step(stmt)) == AIL_ERROR_OK) {
516                 if (_appinfo_check_installed_storage(ai) != AIL_ERROR_OK)
517                         continue;
518
519                 r = cb(ai, user_data, uid);
520                 if (AIL_CB_RET_CANCEL == r)
521                         break;
522         }
523
524         appinfo_destroy(ai);
525         db_finalize(stmt);
526
527         return AIL_ERROR_OK;
528 }