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