Tizen 2.0 Release
[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
254         return AIL_ERROR_OK;
255 }
256
257
258 EXPORT_API ail_error_e ail_package_get_appinfo(const char *package, ail_appinfo_h *ai)
259 {
260         return ail_get_appinfo(package, ai);
261 }
262
263
264 EXPORT_API ail_error_e ail_get_appinfo(const char *appid, ail_appinfo_h *ai)
265 {
266         ail_error_e ret;
267         char query[AIL_SQL_QUERY_MAX_LEN];
268         sqlite3_stmt *stmt = NULL;
269         char w[AIL_SQL_QUERY_MAX_LEN];
270
271         retv_if(!appid, AIL_ERROR_INVALID_PARAMETER);
272         retv_if(!ai, AIL_ERROR_INVALID_PARAMETER);
273
274         *ai = appinfo_create();
275         retv_if(!*ai, AIL_ERROR_OUT_OF_MEMORY);
276
277         snprintf(w, sizeof(w), sql_get_filter(E_AIL_PROP_X_SLP_APPID_STR), appid);
278
279         snprintf(query, sizeof(query), "SELECT %s FROM %s WHERE %s",SQL_FLD_APP_INFO, SQL_TBL_APP_INFO, w);
280
281         do {
282                 ret = db_open(DB_OPEN_RO);
283                 if (ret < 0) break;
284
285                 ret = db_prepare(query, &stmt);
286                 if (ret < 0) break;
287
288                 ret = db_step(stmt);
289                 if (ret < 0) {
290                         db_finalize(stmt);
291                         break;
292                 }
293
294                 (*ai)->stmt = stmt;
295
296                 ret = _retrieve_all_column(*ai);
297                 if (ret < 0) {
298                         db_finalize((*ai)->stmt);
299                         break;
300                 }
301
302                 ret = db_finalize((*ai)->stmt);
303                 if (ret < 0) break;
304                 (*ai)->stmt = NULL;
305
306                 return AIL_ERROR_OK;
307         } while(0);
308
309         appinfo_destroy(*ai);
310
311         return ret;
312 }
313
314
315 EXPORT_API ail_error_e ail_appinfo_get_bool(const ail_appinfo_h ai, const char *property, bool *value)
316 {
317         ail_prop_bool_e prop;
318         int val;
319
320         retv_if(!ai, AIL_ERROR_INVALID_PARAMETER);
321         retv_if(!property, AIL_ERROR_INVALID_PARAMETER);
322         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
323
324         prop = _ail_convert_to_prop_bool(property);
325
326         if (prop < E_AIL_PROP_BOOL_MIN || prop > E_AIL_PROP_BOOL_MAX)
327                 return AIL_ERROR_INVALID_PARAMETER;
328         
329         if (ai->stmt) {
330                 int index;
331                 index = sql_get_app_info_idx(prop);
332                 if (db_column_bool(ai->stmt, index, value) < 0)
333                         return AIL_ERROR_DB_FAILED;
334         } else {
335                 val = atoi(ai->values[prop]);
336                 *value = (val == 0? false : true);
337         }
338         return AIL_ERROR_OK;
339 }
340
341
342
343 EXPORT_API ail_error_e ail_appinfo_get_int(const ail_appinfo_h ai, const char *property, int *value)
344 {
345         ail_prop_int_e prop;
346
347         retv_if(!ai, AIL_ERROR_INVALID_PARAMETER);
348         retv_if(!property, AIL_ERROR_INVALID_PARAMETER);
349         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
350
351         prop = _ail_convert_to_prop_int(property);
352
353         if (prop < E_AIL_PROP_INT_MIN || prop > E_AIL_PROP_INT_MAX)
354                 return AIL_ERROR_INVALID_PARAMETER;
355
356         if (ai->stmt) {
357                 int index; 
358                 index = sql_get_app_info_idx(prop);
359                 if (db_column_int(ai->stmt, index, value) < 0)
360                         return AIL_ERROR_DB_FAILED;
361         } else
362                 *value = atoi(ai->values[prop]);
363
364         return AIL_ERROR_OK;
365 }
366
367 #define QUERY_GET_LOCALNAME "select name from localname where package='%s' and locale='%s'"
368
369 char *appinfo_get_localname(const char *package, char *locale)
370 {
371         db_open(DB_OPEN_RO);
372         sqlite3_stmt *stmt;
373         char *str = NULL;
374         char *localname;
375         char query[512];
376         
377         snprintf(query, sizeof(query), QUERY_GET_LOCALNAME, package, locale);
378
379         _D("Query = %s",query);
380         retv_if (db_prepare(query, &stmt) < 0, NULL);
381
382         do {
383                 if (db_step(stmt) < 0)
384                         break;
385                 if (db_column_str(stmt, 0, &str) < 0)
386                         break;
387                 if (str)
388                         localname = strdup(str);
389                 else
390                         localname = NULL;
391
392                 db_finalize(stmt);
393
394                 return localname;
395         } while(0);
396
397         db_finalize(stmt);
398         return NULL;
399 }
400
401
402 EXPORT_API ail_error_e ail_appinfo_get_str(const ail_appinfo_h ai, const char *property, char **str)
403 {
404         int index;
405         char *value;
406         char *pkg;
407         char *pkg_type;
408         char *locale, *localname;
409         ail_prop_str_e prop;
410         char *locale_new;
411
412         retv_if(!ai, AIL_ERROR_INVALID_PARAMETER);
413         retv_if(!property, AIL_ERROR_INVALID_PARAMETER);
414         retv_if(!str, AIL_ERROR_INVALID_PARAMETER);
415
416         prop = _ail_convert_to_prop_str(property);
417
418         if (prop < E_AIL_PROP_STR_MIN || prop > E_AIL_PROP_STR_MAX)
419                 return AIL_ERROR_INVALID_PARAMETER;
420
421         localname = NULL;
422
423         if (E_AIL_PROP_NAME_STR == prop) {
424                 if (ai->stmt) {
425                         if (db_column_str(ai->stmt, E_AIL_PROP_X_SLP_PACKAGETYPE_STR, &pkg_type) < 0)
426                                 return AIL_ERROR_DB_FAILED;
427                         if(pkg_type && (strcasecmp(pkg_type, "tpk") ==0))
428                         {
429                                 locale = sql_get_locale();
430                                 retv_if (NULL == locale, AIL_ERROR_FAIL);
431
432                                 if (db_column_str(ai->stmt, E_AIL_PROP_PACKAGE_STR, &pkg) < 0){
433                                         free(locale);
434                                         return AIL_ERROR_DB_FAILED;
435                                 }
436                                 if (pkg == NULL){
437                                         free(locale);
438                                         return AIL_ERROR_DB_FAILED;
439                                 }
440
441                                 locale_new = __get_app_locale_by_fallback(pkg, locale);
442                                 localname = (char *)appinfo_get_localname(pkg,locale_new);
443                                 free(locale);
444                                 free(locale_new);
445                         } else {
446                                 if (db_column_str(ai->stmt, SQL_LOCALNAME_IDX, &localname) < 0)
447                                         return AIL_ERROR_DB_FAILED;
448                         }
449                 } else {
450                         pkg_type = ai->values[E_AIL_PROP_X_SLP_PACKAGETYPE_STR];
451                         pkg = ai->values[E_AIL_PROP_PACKAGE_STR];
452                         retv_if (NULL == pkg, AIL_ERROR_FAIL);
453
454                         locale = sql_get_locale();
455                         retv_if (NULL == locale, AIL_ERROR_FAIL);
456
457                         if(pkg_type && (strcasecmp(pkg_type, "tpk") ==0))
458                         {
459                                 locale_new = __get_app_locale_by_fallback(pkg, locale);
460                                 localname = (char *)appinfo_get_localname(pkg,locale_new);
461                                 free(locale);
462                                 free(locale_new);
463                         } else {
464                                 localname = (char *)appinfo_get_localname(pkg,locale);
465                                 free(locale);
466                         }
467                 }
468
469                 if (localname) {
470                         if (!ai->stmt) {
471                                 if (ai->values) {
472                                         if (ai->values[prop])
473                                                 free(ai->values[prop]);
474                                         ai->values[prop] = localname;
475                                 }
476                         }
477                         *str = localname;
478                         return AIL_ERROR_OK;
479                 }
480         }
481
482         if (ai->stmt) {
483                 index = sql_get_app_info_idx(prop);
484                 if (db_column_str(ai->stmt, index, &value) < 0){
485                         return AIL_ERROR_DB_FAILED;
486                 }
487                 *str = value;
488         } else
489                 *str = ai->values[prop];
490
491         return AIL_ERROR_OK;
492 }
493
494
495 // End of file