096b28a8ac5a61dcc8ead64856c73dc4df3fc1a9
[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 (NULL == filter, AIL_ERROR_INVALID_PARAMETER);
51
52         f = (struct ail_filter *)calloc(1, sizeof(struct ail_filter));
53         retv_if (NULL == f, 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 (NULL == filter, 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 (NULL == filter, AIL_ERROR_INVALID_PARAMETER);
100         retv_if (NULL == property, 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 (NULL == c, 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 (NULL == filter, AIL_ERROR_INVALID_PARAMETER);
124         retv_if (NULL == property, 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 (NULL == c, 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 (NULL == filter, AIL_ERROR_INVALID_PARAMETER);
148         retv_if (NULL == property, 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 (NULL == value, 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
160         retv_if (NULL == c, AIL_ERROR_OUT_OF_MEMORY);
161
162         ELEMENT_STR(c)->prop = (int)prop;
163         ELEMENT_STR(c)->value = strdup(value);
164         if (!ELEMENT_STR(c)->value) {
165                 free(c);
166                 return AIL_ERROR_OUT_OF_MEMORY;
167         }
168
169         _add_cond_to_filter(filter, c);
170
171         return AIL_ERROR_OK;
172 }
173
174 static void _get_condition(gpointer data, char **condition)
175 {
176         struct element *e = (struct element *)data;
177         const char *f;
178         char buf[AIL_SQL_QUERY_MAX_LEN];
179         int t;
180
181         f =  sql_get_filter(e->prop);
182         if (f == NULL)
183                 return;
184
185         ELEMENT_TYPE(e, t);
186
187         switch (t) {
188                 case VAL_TYPE_BOOL:
189                         snprintf(buf, sizeof(buf), f, ELEMENT_BOOL(e)->value);
190                         break;
191                 case VAL_TYPE_INT:
192                         snprintf(buf, sizeof(buf), f, ELEMENT_INT(e)->value);
193                         break;
194                 case VAL_TYPE_STR:
195                         if (E_AIL_PROP_NAME_STR == e->prop) {
196                                 snprintf(buf, sizeof(buf), f, ELEMENT_STR(e)->value, ELEMENT_STR(e)->value);
197                         } else {
198                                 snprintf(buf, sizeof(buf), f, ELEMENT_STR(e)->value);
199                         }
200                         break;
201                 default:
202                         _E("Invalid property type");
203                         *condition = NULL;
204                         return;
205         }
206
207         *condition = strdup(buf);
208
209         return;
210 }
211
212 char *_get_where_clause(ail_filter_h filter)
213 {
214         char *c;
215         char w[AIL_SQL_QUERY_MAX_LEN] = {0,};
216         c = NULL;
217
218         GSList *l;
219
220         snprintf(w, AIL_SQL_QUERY_MAX_LEN, " WHERE ");
221
222         for (l = filter->list; l; l = g_slist_next(l)) {
223                 _get_condition(l->data, &c);
224                 if (!c) return NULL;
225                 if (*c == 0) {
226                         free(c);
227                         return NULL;
228                 }
229
230                 strncat(w, c, sizeof(w)-strlen(w)-1);
231                 w[sizeof(w)-1] = '\0';
232                 if(c) free(c);
233
234                 if (g_slist_next(l)) {
235                         strncat(w, " and ", sizeof(w)-strlen(w)-1);
236                         w[sizeof(w)-1] = '\0';
237                 }
238         }
239
240 //      _D("where = %s", w);
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         ail_cb_ret_e r;
252         sqlite3_stmt *stmt;
253         ail_appinfo_h ai;
254         int filter_count = 0;
255
256         retv_if(!cnt, AIL_ERROR_INVALID_PARAMETER);
257
258         if (db_open(DB_OPEN_RO, GLOBAL_USER) != AIL_ERROR_OK)
259                 return AIL_ERROR_DB_FAILED;
260
261         snprintf(q, sizeof(q), "SELECT %s FROM %s", SQL_FLD_APP_INFO_WITH_LOCALNAME, SQL_TBL_APP_INFO_WITH_LOCALNAME);
262
263         tmp_q = strdup(q);
264         retv_if (NULL == tmp_q, AIL_ERROR_OUT_OF_MEMORY);
265         l = sql_get_locale();
266         if (NULL == l) {
267                 _E("Failed to get locale string");
268                 free(tmp_q);
269                 return AIL_ERROR_FAIL;
270         }
271         snprintf(q, sizeof(q), tmp_q, l);
272         free(l);
273         free(tmp_q);
274
275         if (filter && filter->list) {
276                 w = _get_where_clause(filter);
277                 retv_if (NULL == w, AIL_ERROR_FAIL);
278                 strncat(q, w, sizeof(q)-strlen(q)-1);
279                 q[sizeof(q)-1] = '\0';
280                 free(w);
281         }
282         else
283                 _D("No filter exists. All records are retreived");
284
285 //is_admin
286         if (db_prepare_globalro(q, &stmt) != AIL_ERROR_OK) {
287                 _E("db_prepare_globalro fail for query = %s",q);
288                 return AIL_ERROR_DB_FAILED;
289         }
290         ai = appinfo_create();
291         if (ai == NULL) {
292                 _E("out of memory");
293                 db_finalize(stmt);
294                 return AIL_ERROR_FAIL;
295         }
296
297         appinfo_set_stmt(ai, stmt);
298         while (db_step(stmt) == AIL_ERROR_OK) {
299
300                 if(_appinfo_check_installed_storage(ai) != AIL_ERROR_OK)
301                         continue;
302
303                 filter_count++;
304         }
305
306         db_finalize(stmt);
307
308         appinfo_destroy(ai);
309         *cnt = filter_count;
310
311         return AIL_ERROR_OK;
312 }
313
314 EXPORT_API ail_error_e ail_filter_count_usr_appinfo(ail_filter_h filter, int *cnt, uid_t uid)
315 {
316         char q[AIL_SQL_QUERY_MAX_LEN];
317         char *w;
318         char *tmp_q;
319         char *l;
320         ail_cb_ret_e r;
321         sqlite3_stmt *stmt;
322         ail_appinfo_h ai;
323         int filter_count = 0;
324
325         retv_if(!cnt, AIL_ERROR_INVALID_PARAMETER);
326
327 //is_admin ; redirect
328         if (uid == GLOBAL_USER)
329                 return ail_filter_count_appinfo(filter, cnt);
330
331         if (db_open(DB_OPEN_RO, uid) != AIL_ERROR_OK)
332                 return AIL_ERROR_DB_FAILED;
333
334         snprintf(q, sizeof(q), "SELECT %s FROM %s", SQL_FLD_APP_INFO_WITH_LOCALNAME, SQL_TBL_APP_INFO_WITH_LOCALNAME);
335
336         tmp_q = strdup(q);
337         retv_if (NULL == tmp_q, AIL_ERROR_OUT_OF_MEMORY);
338         l = sql_get_locale();
339         if (NULL == l) {
340                 _E("Failed to get locale string");
341                 free(tmp_q);
342                 return AIL_ERROR_FAIL;
343         }
344         snprintf(q, sizeof(q), tmp_q, l);
345         free(l);
346         free(tmp_q);
347
348         if (filter && filter->list) {
349                 w = _get_where_clause(filter);
350                 retv_if (NULL == w, AIL_ERROR_FAIL);
351                 strncat(q, w, sizeof(q)-strlen(q)-1);
352                 q[sizeof(q)-1] = '\0';
353                 free(w);
354         }
355         else
356                 _D("No filter exists. All records are retreived");
357
358         if (db_prepare(q, &stmt) != AIL_ERROR_OK) {
359                 _E("db_prepare fail for query = %s",q);
360                 return AIL_ERROR_DB_FAILED;
361         }
362
363         ai = appinfo_create();
364         if (ai == NULL) {
365                 _E("Failed to create appinfo");
366                 db_finalize(stmt);
367                 return AIL_ERROR_OUT_OF_MEMORY;
368         }
369
370         appinfo_set_stmt(ai, stmt);
371         while (db_step(stmt) == AIL_ERROR_OK) {
372
373                 if(_appinfo_check_installed_storage(ai) != AIL_ERROR_OK)
374                         continue;
375
376                 filter_count++;
377         }
378
379         db_finalize(stmt);
380
381         appinfo_destroy(ai);
382         *cnt = filter_count;
383
384         return AIL_ERROR_OK;
385 }
386
387
388 EXPORT_API ail_error_e ail_filter_list_appinfo_foreach(ail_filter_h filter, ail_list_appinfo_cb cb, void *user_data)
389 {
390         char q[AIL_SQL_QUERY_MAX_LEN];
391         char *tmp_q;
392         char *w;
393         char *l;
394         ail_cb_ret_e r;
395         sqlite3_stmt *stmt;
396         ail_appinfo_h ai;
397
398         retv_if (NULL == cb, AIL_ERROR_INVALID_PARAMETER);
399
400         if (db_open(DB_OPEN_RO, GLOBAL_USER) != AIL_ERROR_OK)
401                 return AIL_ERROR_DB_FAILED;
402
403         snprintf(q, sizeof(q), "SELECT %s FROM %s", SQL_FLD_APP_INFO_WITH_LOCALNAME, SQL_TBL_APP_INFO_WITH_LOCALNAME);
404
405         tmp_q = strdup(q);
406         retv_if (NULL == tmp_q, AIL_ERROR_OUT_OF_MEMORY);
407         l = sql_get_locale();
408         if (NULL == l) {
409                 _E("Failed to get locale string");
410                 free(tmp_q);
411                 return AIL_ERROR_FAIL;
412         }
413         snprintf(q, sizeof(q), tmp_q, l);
414         free(l);
415         free(tmp_q);
416
417         if (filter && filter->list) {
418                 w = _get_where_clause(filter);
419                 retv_if (NULL == w, AIL_ERROR_FAIL);
420                 strncat(q, w, sizeof(q)-strlen(q)-1);
421                 q[sizeof(q)-1] = '\0';
422                 strncat(q, " order by app_info.package", sizeof(q)-strlen(q)-1);
423                 q[sizeof(q)-1] = '\0';
424                 free(w);
425         }
426         else
427                 _D("No filter exists. All records are retreived");
428
429 //      _D("Query = %s",q);
430 //is_admin
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         /*if (db_prepare_globalro(q, &stmt) != AIL_ERROR_OK) {
436                 _E("db_prepare fail for query = %s",q);
437                 return AIL_ERROR_DB_FAILED;
438         }*/
439         ai = appinfo_create();
440         if (ai == NULL) {
441                 _E("out of memory");
442                 db_finalize(stmt);
443                 return AIL_ERROR_FAIL;
444         }
445
446         appinfo_set_stmt(ai, stmt);
447         uint i = 0;
448         while (i = db_step(stmt) == AIL_ERROR_OK) {
449                 _E("------------------------dbstep : %u\n", i);
450                 if(_appinfo_check_installed_storage(ai) != AIL_ERROR_OK)
451                         continue;
452
453                 r = cb(ai, user_data,GLOBAL_USER);
454                 if (AIL_CB_RET_CANCEL == r)
455                         break;
456         }
457         appinfo_destroy(ai);
458
459         db_finalize(stmt);
460         return AIL_ERROR_OK;
461 }
462
463 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)
464 {
465         char q[AIL_SQL_QUERY_MAX_LEN];
466         char *tmp_q;
467         char *w;
468         char *l;
469         ail_cb_ret_e r;
470         sqlite3_stmt *stmt;
471         ail_appinfo_h ai;
472
473         retv_if (NULL == cb, AIL_ERROR_INVALID_PARAMETER);
474
475         if (db_open(DB_OPEN_RO, uid) != AIL_ERROR_OK)
476                 return AIL_ERROR_DB_FAILED;
477
478         snprintf(q, sizeof(q), "SELECT %s FROM %s", SQL_FLD_APP_INFO_WITH_LOCALNAME, SQL_TBL_APP_INFO_WITH_LOCALNAME);
479
480         tmp_q = strdup(q);
481         retv_if (NULL == tmp_q, AIL_ERROR_OUT_OF_MEMORY);
482         l = sql_get_locale();
483         if (NULL == l) {
484                 _E("Failed to get locale string");
485                 free(tmp_q);
486                 return AIL_ERROR_FAIL;
487         }
488         snprintf(q, sizeof(q), tmp_q, l);
489         free(l);
490         free(tmp_q);
491
492         if (filter && filter->list) {
493                 w = _get_where_clause(filter);
494                 retv_if (NULL == w, AIL_ERROR_FAIL);
495                 strncat(q, w, sizeof(q)-strlen(q)-1);
496                 q[sizeof(q)-1] = '\0';
497                 strncat(q, " order by app_info.package", sizeof(q)-strlen(q)-1);
498                 q[sizeof(q)-1] = '\0';
499                 free(w);
500         }
501         else
502                 _D("No filter exists. All records are retreived");
503
504 //is_admin
505         if (db_prepare(q, &stmt) != AIL_ERROR_OK) {
506                 _E("db_prepare fail for query = %s",q);
507                 return AIL_ERROR_DB_FAILED;
508         }
509
510         ai = appinfo_create();
511         if (ai == NULL) {
512                 _E("Failed to create appinfo");
513                 db_finalize(stmt);
514                 return AIL_ERROR_DB_FAILED;
515         }
516
517         appinfo_set_stmt(ai, stmt);
518         uint i = 0;
519         while (i = db_step(stmt) == AIL_ERROR_OK) {
520                 if(_appinfo_check_installed_storage(ai) != AIL_ERROR_OK)
521                         continue;
522
523                 r = cb(ai, user_data,uid);
524                 if (AIL_CB_RET_CANCEL == r)
525                         break;
526         }
527
528         appinfo_destroy(ai);
529         db_finalize(stmt);
530
531         return AIL_ERROR_OK;
532 }