appinfo db close when ail_destroy_appinfo is called
[platform/core/appfw/ail.git] / src / ail_package.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 <string.h>
25 #include <stdlib.h>
26 #include <db-util.h>
27 #include <vconf.h>
28 #include "ail.h"
29 #include "ail_private.h"
30 #include "ail_convert.h"
31 #include "ail_db.h"
32 #include "ail_sql.h"
33 #include "ail_package.h"
34 #include <assert.h>
35 #include <unistd.h>
36
37 #define LANGUAGE_LENGTH 2
38 #define DEFAULT_LOCALE          "No Locale"
39 #define MAX_QUERY_LEN   4096
40
41 struct ail_appinfo {
42         char **values;
43         sqlite3_stmt *stmt;
44 };
45
46 typedef struct _pkgmgr_locale_x {
47         char *locale;
48 } pkgmgr_locale_x;
49
50
51 /* get the first locale value*/
52 static int __fallback_locale_cb(void *data, int ncols, char **coltxt, char **colname)
53 {
54         pkgmgr_locale_x *info = (pkgmgr_locale_x *)data;
55
56         if (ncols >= 1)
57                 info->locale = strdup(coltxt[0]);
58         else
59                 info->locale = NULL;
60
61         return 0;
62 }
63
64 static int __check_validation_of_qurey_cb(void *data, int ncols, char **coltxt, char **colname)
65 {
66         int *p = (int*)data;
67         *p = atoi(coltxt[0]);
68         return 0;
69 }
70
71 static int __check_app_locale_from_app_localized_info_by_exact(const char *appid, const char *locale)
72 {
73         int result_query = -1;
74         char query[MAX_QUERY_LEN];
75
76         snprintf(query, MAX_QUERY_LEN, "select exists(select locale from localname where package='%s' and locale='%s')", appid, locale);
77         db_exec_sqlite_query(query, __check_validation_of_qurey_cb, (void *)&result_query);
78
79         return result_query;
80 }
81
82 static int __check_app_locale_from_app_localized_info_by_fallback(const char *appid, const char *locale)
83 {
84         int result_query = -1;
85         char wildcard[2] = {'%','\0'};
86         char query[MAX_QUERY_LEN];
87         char lang[3] = {'\0'};
88         strncpy(lang, locale, LANGUAGE_LENGTH);
89
90         snprintf(query, MAX_QUERY_LEN, "select exists(select locale from localname where package='%s' and locale like '%s%s')", appid, lang, wildcard);
91         db_exec_sqlite_query(query, __check_validation_of_qurey_cb, (void *)&result_query);
92
93         return result_query;
94 }
95
96 static char* __get_app_locale_from_app_localized_info_by_fallback(const char *appid, const char *locale)
97 {
98         char wildcard[2] = {'%','\0'};
99         char lang[3] = {'\0'};
100         char query[MAX_QUERY_LEN];
101         char *locale_new = NULL;
102         pkgmgr_locale_x *info = NULL;
103
104         info = (pkgmgr_locale_x *)malloc(sizeof(pkgmgr_locale_x));
105         if (info == NULL) {
106                 _E("Out of Memory!!!\n");
107                 return NULL;
108         }
109         memset(info, NULL, sizeof(*info));
110
111         strncpy(lang, locale, 2);
112         snprintf(query, MAX_QUERY_LEN, "select locale from localname where package='%s' and locale like '%s%s'", appid, lang, wildcard);
113         db_exec_sqlite_query(query, __fallback_locale_cb, (void *)info);
114         locale_new = info->locale;
115         free(info);
116
117         return locale_new;
118 }
119
120 static char* __convert_syslocale_to_manifest_locale(char *syslocale)
121 {
122         char *locale = malloc(6);
123         if (!locale) {
124                 _E("Malloc Failed\n");
125                 return NULL;
126         }
127
128         sprintf(locale, "%c%c_%c%c", syslocale[0], syslocale[1], toupper(syslocale[3]), toupper(syslocale[4]));
129         return locale;
130 }
131
132 static char* __get_app_locale_by_fallback(const char *appid, const char *syslocale)
133 {
134         assert(appid);
135         assert(syslocale);
136
137         char *locale = NULL;
138         char *locale_new = NULL;
139         int check_result = 0;
140
141         locale = __convert_syslocale_to_manifest_locale(syslocale);
142
143         /*check exact matching */
144         check_result = __check_app_locale_from_app_localized_info_by_exact(appid, locale);
145
146         /* Exact found */
147         if (check_result == 1) {
148                 _D("%s find exact locale(%s)\n", appid, locale);
149                 return locale;
150         }
151
152         /* fallback matching */
153         check_result = __check_app_locale_from_app_localized_info_by_fallback(appid, locale);
154         if(check_result == 1) {
155                    locale_new = __get_app_locale_from_app_localized_info_by_fallback(appid, locale);
156                    _D("%s found (%s) language-locale in DB by fallback!\n", appid, locale_new);
157                    free(locale);
158                    if (locale_new == NULL)
159                            locale_new =  strdup(DEFAULT_LOCALE);
160                    return locale_new;
161         }
162
163         /* default locale */
164         free(locale);
165         _D("%s DEFAULT_LOCALE)\n", appid);
166         return  strdup(DEFAULT_LOCALE);
167 }
168
169 void appinfo_set_stmt(ail_appinfo_h ai, sqlite3_stmt *stmt)
170 {
171         ai->stmt = stmt;
172 }
173
174 ail_appinfo_h appinfo_create(void)
175 {
176         ail_appinfo_h ai;
177         ai = calloc(1, sizeof(struct ail_appinfo));
178         retv_if (NULL == ai, NULL);
179         ai->stmt = NULL;
180
181         return ai;
182 }
183
184 void appinfo_destroy(ail_appinfo_h ai)
185 {
186         if (ai) 
187                 free(ai);
188 }
189
190
191
192 static ail_error_e _retrieve_all_column(ail_appinfo_h ai)
193 {
194         int i, j;
195         ail_error_e err;
196         char *col;
197
198         retv_if(!ai, AIL_ERROR_INVALID_PARAMETER);
199         retv_if(!ai->stmt, AIL_ERROR_INVALID_PARAMETER);
200
201         ai->values = calloc(NUM_OF_PROP, sizeof(char *));
202         retv_if(!ai->values, AIL_ERROR_OUT_OF_MEMORY);
203
204         for (i = 0; i < NUM_OF_PROP; i++) {
205                 err = db_column_str(ai->stmt, i, &col);
206                 if (AIL_ERROR_OK != err) 
207                         break;
208
209                 if (!col) {
210                         ai->values[i] = NULL;
211                 } else {
212                         ai->values[i] = strdup(col);
213                         if (!ai->values[i]) {
214                                 err = AIL_ERROR_OUT_OF_MEMORY;
215                                 break;
216                         }
217                 }
218         }
219
220         if (err < 0) {
221                 for (j = 0; j < i; ++j) {
222                         if (ai->values[j])
223                                 free(ai->values[j]);
224                 }
225                 if (ai->values)
226                         free(ai->values);
227                 return err;
228         } else
229                 return AIL_ERROR_OK;
230 }
231
232
233 EXPORT_API ail_error_e ail_package_destroy_appinfo(ail_appinfo_h ai)
234 {
235         return ail_destroy_appinfo(ai);
236 }
237
238 EXPORT_API ail_error_e ail_destroy_appinfo(ail_appinfo_h ai)
239 {
240         int i;
241
242         retv_if(!ai, AIL_ERROR_INVALID_PARAMETER);
243         retv_if(!ai->values, AIL_ERROR_INVALID_PARAMETER);
244
245         for (i = 0; i < NUM_OF_PROP; i++) {
246                 if (ai->values[i]) {
247                         free(ai->values[i]);
248                 }
249         }
250
251         free(ai->values);
252         free(ai);
253         db_close();
254
255         return AIL_ERROR_OK;
256 }
257
258
259 EXPORT_API ail_error_e ail_package_get_appinfo(const char *package, ail_appinfo_h *ai)
260 {
261         return ail_get_appinfo(package, ai);
262 }
263
264
265 EXPORT_API ail_error_e ail_get_appinfo(const char *appid, ail_appinfo_h *ai)
266 {
267         ail_error_e ret;
268         char query[AIL_SQL_QUERY_MAX_LEN];
269         sqlite3_stmt *stmt = NULL;
270         char w[AIL_SQL_QUERY_MAX_LEN];
271
272         retv_if(!appid, AIL_ERROR_INVALID_PARAMETER);
273         retv_if(!ai, AIL_ERROR_INVALID_PARAMETER);
274
275         *ai = appinfo_create();
276         retv_if(!*ai, AIL_ERROR_OUT_OF_MEMORY);
277
278         snprintf(w, sizeof(w), sql_get_filter(E_AIL_PROP_X_SLP_APPID_STR), appid);
279
280         snprintf(query, sizeof(query), "SELECT %s FROM %s WHERE %s",SQL_FLD_APP_INFO, SQL_TBL_APP_INFO, w);
281
282         do {
283                 ret = db_open(DB_OPEN_RO);
284                 if (ret < 0) break;
285
286                 ret = db_prepare(query, &stmt);
287                 if (ret < 0) break;
288
289                 ret = db_step(stmt);
290                 if (ret < 0) {
291                         db_finalize(stmt);
292                         break;
293                 }
294
295                 (*ai)->stmt = stmt;
296
297                 ret = _retrieve_all_column(*ai);
298                 if (ret < 0) {
299                         db_finalize((*ai)->stmt);
300                         break;
301                 }
302
303                 ret = db_finalize((*ai)->stmt);
304                 if (ret < 0) break;
305                 (*ai)->stmt = NULL;
306
307                 return AIL_ERROR_OK;
308         } while(0);
309
310         appinfo_destroy(*ai);
311
312         return ret;
313 }
314
315
316 EXPORT_API ail_error_e ail_appinfo_get_bool(const ail_appinfo_h ai, const char *property, bool *value)
317 {
318         ail_prop_bool_e prop;
319         int val;
320
321         retv_if(!ai, AIL_ERROR_INVALID_PARAMETER);
322         retv_if(!property, AIL_ERROR_INVALID_PARAMETER);
323         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
324
325         prop = _ail_convert_to_prop_bool(property);
326
327         if (prop < E_AIL_PROP_BOOL_MIN || prop > E_AIL_PROP_BOOL_MAX)
328                 return AIL_ERROR_INVALID_PARAMETER;
329         
330         if (ai->stmt) {
331                 int index;
332                 index = sql_get_app_info_idx(prop);
333                 if (db_column_bool(ai->stmt, index, value) < 0)
334                         return AIL_ERROR_DB_FAILED;
335         } else {
336                 val = atoi(ai->values[prop]);
337                 *value = (val == 0? false : true);
338         }
339         return AIL_ERROR_OK;
340 }
341
342
343
344 EXPORT_API ail_error_e ail_appinfo_get_int(const ail_appinfo_h ai, const char *property, int *value)
345 {
346         ail_prop_int_e prop;
347
348         retv_if(!ai, AIL_ERROR_INVALID_PARAMETER);
349         retv_if(!property, AIL_ERROR_INVALID_PARAMETER);
350         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
351
352         prop = _ail_convert_to_prop_int(property);
353
354         if (prop < E_AIL_PROP_INT_MIN || prop > E_AIL_PROP_INT_MAX)
355                 return AIL_ERROR_INVALID_PARAMETER;
356
357         if (ai->stmt) {
358                 int index; 
359                 index = sql_get_app_info_idx(prop);
360                 if (db_column_int(ai->stmt, index, value) < 0)
361                         return AIL_ERROR_DB_FAILED;
362         } else
363                 *value = atoi(ai->values[prop]);
364
365         return AIL_ERROR_OK;
366 }
367
368 #define QUERY_GET_LOCALNAME "select name from localname where package='%s' and locale='%s'"
369
370 char *appinfo_get_localname(const char *package, char *locale)
371 {
372         db_open(DB_OPEN_RO);
373         sqlite3_stmt *stmt;
374         char *str = NULL;
375         char *localname;
376         char query[512];
377         
378         snprintf(query, sizeof(query), QUERY_GET_LOCALNAME, package, locale);
379
380         _D("Query = %s",query);
381         retv_if (db_prepare(query, &stmt) < 0, NULL);
382
383         do {
384                 if (db_step(stmt) < 0)
385                         break;
386                 if (db_column_str(stmt, 0, &str) < 0)
387                         break;
388                 if (str)
389                         localname = strdup(str);
390                 else
391                         localname = NULL;
392
393                 db_finalize(stmt);
394
395                 return localname;
396         } while(0);
397
398         db_finalize(stmt);
399         return NULL;
400 }
401
402
403 EXPORT_API ail_error_e ail_appinfo_get_str(const ail_appinfo_h ai, const char *property, char **str)
404 {
405         int index;
406         char *value;
407         char *pkg;
408         char *pkg_type;
409         char *locale, *localname;
410         ail_prop_str_e prop;
411         char *locale_new;
412
413         retv_if(!ai, AIL_ERROR_INVALID_PARAMETER);
414         retv_if(!property, AIL_ERROR_INVALID_PARAMETER);
415         retv_if(!str, AIL_ERROR_INVALID_PARAMETER);
416
417         prop = _ail_convert_to_prop_str(property);
418
419         if (prop < E_AIL_PROP_STR_MIN || prop > E_AIL_PROP_STR_MAX)
420                 return AIL_ERROR_INVALID_PARAMETER;
421
422         localname = NULL;
423
424         if (E_AIL_PROP_NAME_STR == prop) {
425                 if (ai->stmt) {
426                         if (db_column_str(ai->stmt, E_AIL_PROP_X_SLP_PACKAGETYPE_STR, &pkg_type) < 0)
427                                 return AIL_ERROR_DB_FAILED;
428                         if(pkg_type && (strcasecmp(pkg_type, "tpk") ==0))
429                         {
430                                 locale = sql_get_locale();
431                                 retv_if (NULL == locale, AIL_ERROR_FAIL);
432
433                                 if (db_column_str(ai->stmt, E_AIL_PROP_PACKAGE_STR, &pkg) < 0){
434                                         free(locale);
435                                         return AIL_ERROR_DB_FAILED;
436                                 }
437                                 if (pkg == NULL){
438                                         free(locale);
439                                         return AIL_ERROR_DB_FAILED;
440                                 }
441
442                                 locale_new = __get_app_locale_by_fallback(pkg, locale);
443                                 localname = (char *)appinfo_get_localname(pkg,locale_new);
444                                 free(locale);
445                                 free(locale_new);
446                         } else {
447                                 if (db_column_str(ai->stmt, SQL_LOCALNAME_IDX, &localname) < 0)
448                                         return AIL_ERROR_DB_FAILED;
449                         }
450                 } else {
451                         pkg_type = ai->values[E_AIL_PROP_X_SLP_PACKAGETYPE_STR];
452                         pkg = ai->values[E_AIL_PROP_PACKAGE_STR];
453                         retv_if (NULL == pkg, AIL_ERROR_FAIL);
454
455                         locale = sql_get_locale();
456                         retv_if (NULL == locale, AIL_ERROR_FAIL);
457
458                         if(pkg_type && (strcasecmp(pkg_type, "tpk") ==0))
459                         {
460                                 locale_new = __get_app_locale_by_fallback(pkg, locale);
461                                 localname = (char *)appinfo_get_localname(pkg,locale_new);
462                                 free(locale);
463                                 free(locale_new);
464                         } else {
465                                 localname = (char *)appinfo_get_localname(pkg,locale);
466                                 free(locale);
467                         }
468                 }
469
470                 if (localname) {
471                         if (!ai->stmt) {
472                                 if (ai->values) {
473                                         if (ai->values[prop])
474                                                 free(ai->values[prop]);
475                                         ai->values[prop] = localname;
476                                 }
477                         }
478                         *str = localname;
479                         return AIL_ERROR_OK;
480                 }
481         }
482
483         if (ai->stmt) {
484                 index = sql_get_app_info_idx(prop);
485                 if (db_column_str(ai->stmt, index, &value) < 0){
486                         return AIL_ERROR_DB_FAILED;
487                 }
488                 *str = value;
489         } else
490                 *str = ai->values[prop];
491
492         return AIL_ERROR_OK;
493 }
494
495 EXPORT_API ail_error_e ail_close_appinfo_db(void)
496 {
497         return db_close();
498 }
499
500 // End of file