Remove setuid bit
[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 <ctype.h>
27 #include <assert.h>
28 #include <unistd.h>
29 #include <db-util.h>
30 #include <tzplatform_config.h>
31 #include <vconf.h>
32
33 #include "ail.h"
34 #include "ail_private.h"
35 #include "ail_convert.h"
36 #include "ail_db.h"
37 #include "ail_sql.h"
38 #include "ail_package.h"
39
40 #define LANGUAGE_LENGTH 2
41 #define DEFAULT_LOCALE          "No Locale"
42 #define MAX_QUERY_LEN   4096
43 #define PKG_SD_PATH tzplatform_mkpath(TZ_SYS_STORAGE, "sdcard/app2sd/")
44 #define QUERY_GET_LOCALNAME "select name from localname where package='%s' and locale='%s'"
45
46 struct ail_appinfo {
47         char **values;
48         sqlite3_stmt *stmt;
49 };
50
51 typedef struct _pkgmgr_locale_x {
52         char *locale;
53 } pkgmgr_locale_x;
54
55 /* get the first locale value*/
56 static int __fallback_locale_cb(void *data, int ncols, char **coltxt, char **colname)
57 {
58         pkgmgr_locale_x *info = (pkgmgr_locale_x *)data;
59
60         if (ncols >= 1)
61                 info->locale = strdup(coltxt[0]);
62         else
63                 info->locale = NULL;
64
65         return 0;
66 }
67
68 static int __check_validation_of_query_cb(void *data, int ncols, char **coltxt, char **colname)
69 {
70         int *p = (int *)data;
71         *p = atoi(coltxt[0]);
72         return 0;
73 }
74
75 static int __check_app_locale_from_app_localized_info_by_exact(const char *appid, const char *locale)
76 {
77         int result_query = -1;
78         char query[MAX_QUERY_LEN];
79
80         snprintf(query, MAX_QUERY_LEN, "select exists(select locale from localname where package='%s' and locale='%s')", appid, locale);
81         db_exec_sqlite_query(query, __check_validation_of_query_cb, (void *)&result_query);
82
83         return result_query;
84 }
85
86 static int __check_app_locale_from_app_localized_info_by_fallback(const char *appid, const char *locale)
87 {
88         int result_query = -1;
89         char wildcard[2] = {'%', '\0'};
90         char query[MAX_QUERY_LEN];
91         char lang[3] = {'\0'};
92         strncpy(lang, locale, LANGUAGE_LENGTH);
93
94         snprintf(query, MAX_QUERY_LEN, "select exists(select locale from localname where package='%s' and locale like '%s%s')", appid, lang, wildcard);
95         db_exec_sqlite_query(query, __check_validation_of_query_cb, (void *)&result_query);
96
97         return result_query;
98 }
99
100 static char* __get_app_locale_from_app_localized_info_by_fallback(const char *appid, const char *locale)
101 {
102         char wildcard[2] = {'%', '\0'};
103         char lang[3] = {'\0'};
104         char query[MAX_QUERY_LEN];
105         char *locale_new = NULL;
106         pkgmgr_locale_x *info = NULL;
107
108         info = (pkgmgr_locale_x *)malloc(sizeof(pkgmgr_locale_x));
109         if (info == NULL) {
110                 _E("Out of Memory!!!\n");
111                 return NULL;
112         }
113         memset(info, 0x00, sizeof(*info));
114
115         strncpy(lang, locale, 2);
116         snprintf(query, MAX_QUERY_LEN, "select locale from localname where package='%s' and locale like '%s%s'", appid, lang, wildcard);
117         db_exec_sqlite_query(query, __fallback_locale_cb, (void *)info);
118         locale_new = info->locale;
119         free(info);
120
121         return locale_new;
122 }
123
124 static char* __convert_syslocale_to_manifest_locale(const char *syslocale)
125 {
126         char *locale = malloc(6);
127         if (!locale) {
128                 _E("Malloc Failed\n");
129                 return NULL;
130         }
131
132         snprintf(locale, 6, "%c%c_%c%c", syslocale[0], syslocale[1], toupper(syslocale[3]), toupper(syslocale[4]));
133         return locale;
134 }
135
136 static char* __get_app_locale_by_fallback(const char *appid, const char *syslocale)
137 {
138         assert(appid);
139         assert(syslocale);
140
141         char *locale = NULL;
142         char *locale_new = NULL;
143         int check_result = 0;
144
145         locale = __convert_syslocale_to_manifest_locale(syslocale);
146
147         /*check exact matching */
148         check_result = __check_app_locale_from_app_localized_info_by_exact(appid, locale);
149
150         /* Exact found */
151         if (check_result == 1) {
152                 _D("%s find exact locale(%s)\n", appid, locale);
153                 return locale;
154         }
155
156         /* fallback matching */
157         check_result = __check_app_locale_from_app_localized_info_by_fallback(appid, locale);
158         if (check_result == 1) {
159                    locale_new = __get_app_locale_from_app_localized_info_by_fallback(appid, locale);
160                    _D("%s found (%s) language-locale in DB by fallback!\n", appid, locale_new);
161                    free(locale);
162                    if (locale_new == NULL)
163                            locale_new =  strdup(DEFAULT_LOCALE);
164                    return locale_new;
165         }
166
167         /* default locale */
168         free(locale);
169         _D("%s DEFAULT_LOCALE)\n", appid);
170         return  strdup(DEFAULT_LOCALE);
171 }
172
173 static ail_error_e __retrieve_all_column(ail_appinfo_h ai)
174 {
175         int i, j;
176         ail_error_e err;
177         char *col;
178
179         retv_if(!ai, AIL_ERROR_INVALID_PARAMETER);
180         retv_if(!ai->stmt, AIL_ERROR_INVALID_PARAMETER);
181
182         ai->values = calloc(NUM_OF_PROP, sizeof(char *));
183         retv_if(!ai->values, AIL_ERROR_OUT_OF_MEMORY);
184
185         for (i = 0; i < NUM_OF_PROP; i++) {
186                 err = db_column_str(ai->stmt, i, &col);
187                 if (AIL_ERROR_OK != err)
188                         break;
189
190                 if (!col) {
191                         ai->values[i] = NULL;
192                 } else {
193                         ai->values[i] = strdup(col);
194                         if (!ai->values[i]) {
195                                 err = AIL_ERROR_OUT_OF_MEMORY;
196                                 break;
197                         }
198                 }
199         }
200
201         if (err < 0) {
202                 for (j = 0; j < i; ++j) {
203                         if (ai->values[j])
204                                 free(ai->values[j]);
205                 }
206                 if (ai->values)
207                         free(ai->values);
208                 return err;
209         } else
210                 return AIL_ERROR_OK;
211 }
212
213 int _appinfo_check_installed_storage(ail_appinfo_h ai)
214 {
215         int index = 0;
216         ail_prop_str_e prop = -1;
217         char *pkgid = NULL;
218         char *installed_storage = NULL;
219         char buf[AIL_SQL_QUERY_MAX_LEN] = {'\0'};
220
221         retv_if(!ai, AIL_ERROR_OK);
222
223         if (ai->stmt) {
224                 prop = _ail_convert_to_prop_str(AIL_PROP_X_SLP_INSTALLEDSTORAGE_STR);
225                 index = sql_get_app_info_idx(prop);
226                 if (db_column_str(ai->stmt, index, &installed_storage) < 0)
227                         return AIL_ERROR_OK;
228
229                 prop = _ail_convert_to_prop_str(AIL_PROP_X_SLP_PKGID_STR);
230                 index = sql_get_app_info_idx(prop);
231                 if (db_column_str(ai->stmt, index, &pkgid) < 0)
232                         return AIL_ERROR_OK;
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(ai == NULL, 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         free(ai->values);
291         free(ai);
292         db_close();
293
294         return AIL_ERROR_OK;
295 }
296
297 EXPORT_API ail_error_e ail_package_get_appinfo(const char *package, ail_appinfo_h *ai)
298 {
299         return ail_get_appinfo(package, ai);
300 }
301
302 EXPORT_API ail_error_e ail_package_get_usr_appinfo(const char *package, uid_t uid, ail_appinfo_h *ai)
303 {
304         return ail_get_usr_appinfo(package, uid, ai);
305 }
306
307 EXPORT_API ail_error_e ail_get_appinfo(const char *appid, ail_appinfo_h *ai)
308 {
309         ail_error_e ret;
310         char query[AIL_SQL_QUERY_MAX_LEN];
311         sqlite3_stmt *stmt = NULL;
312         char w[AIL_SQL_QUERY_MAX_LEN];
313         const char *filter;
314
315         retv_if(!appid, AIL_ERROR_INVALID_PARAMETER);
316         retv_if(!ai, AIL_ERROR_INVALID_PARAMETER);
317
318         *ai = appinfo_create();
319         retv_if(!*ai, AIL_ERROR_OUT_OF_MEMORY);
320
321         filter = sql_get_filter(E_AIL_PROP_X_SLP_APPID_STR);
322         if (filter == NULL) {
323                 appinfo_destroy(*ai);
324                 return AIL_ERROR_FAIL;
325         }
326
327         snprintf(w, sizeof(w), filter, appid);
328         snprintf(query, sizeof(query), "SELECT %s FROM %s WHERE %s",
329                                         SQL_FLD_APP_INFO, SQL_TBL_APP_INFO, w);
330
331         do {
332                 ret = db_open(DB_OPEN_RO, GLOBAL_USER);
333                 if (ret < 0)
334                         break;
335
336                 /* is_admin */
337                 ret = db_prepare_globalro(query, &stmt);
338                 if (ret < 0)
339                         break;
340
341                 ret = db_step(stmt);
342                 if (ret < 0) {
343                         db_finalize(stmt);
344                         break;
345                 }
346
347                 (*ai)->stmt = stmt;
348
349                 ret = _appinfo_check_installed_storage(*ai);
350                 if (ret < 0) {
351                         db_finalize((*ai)->stmt);
352                         break;
353                 }
354
355                 ret = __retrieve_all_column(*ai);
356                 if (ret < 0) {
357                         db_finalize((*ai)->stmt);
358                         break;
359                 }
360
361                 ret = db_finalize((*ai)->stmt);
362                 if (ret < 0)
363                         break;
364
365                 (*ai)->stmt = NULL;
366
367                 return AIL_ERROR_OK;
368         } while (0);
369
370         appinfo_destroy(*ai);
371
372         return ret;
373 }
374
375 EXPORT_API ail_error_e ail_get_usr_appinfo(const char *appid, uid_t uid, ail_appinfo_h *ai)
376 {
377         ail_error_e ret;
378         char query[AIL_SQL_QUERY_MAX_LEN];
379         sqlite3_stmt *stmt = NULL;
380         char w[AIL_SQL_QUERY_MAX_LEN];
381         const char *filter;
382
383         retv_if(!appid, AIL_ERROR_INVALID_PARAMETER);
384         retv_if(!ai, AIL_ERROR_INVALID_PARAMETER);
385
386         *ai = appinfo_create();
387         retv_if(!*ai, AIL_ERROR_OUT_OF_MEMORY);
388
389         filter = sql_get_filter(E_AIL_PROP_X_SLP_APPID_STR);
390         if (filter == NULL) {
391                 appinfo_destroy(*ai);
392                 return AIL_ERROR_FAIL;
393         }
394
395         snprintf(w, sizeof(w), filter, appid);
396         snprintf(query, sizeof(query), "SELECT %s FROM %s WHERE %s",
397                                         SQL_FLD_APP_INFO, SQL_TBL_APP_INFO, w);
398
399         do {
400                 ret = db_open(DB_OPEN_RO, uid);
401                 if (ret < 0)
402                         break;
403
404                 /* is_admin */
405                 ret = db_prepare(query, &stmt);
406                 if (ret < 0)
407                         break;
408
409                 ret = db_step(stmt);
410                 if (ret < 0) {
411                         db_finalize(stmt);
412                         break;
413                 }
414
415                 (*ai)->stmt = stmt;
416
417                 ret = _appinfo_check_installed_storage(*ai);
418                 if (ret < 0) {
419                         db_finalize((*ai)->stmt);
420                         break;
421                 }
422
423                 ret = __retrieve_all_column(*ai);
424                 if (ret < 0) {
425                         db_finalize((*ai)->stmt);
426                         break;
427                 }
428
429                 ret = db_finalize((*ai)->stmt);
430                 if (ret < 0)
431                         break;
432
433                 (*ai)->stmt = NULL;
434
435                 return AIL_ERROR_OK;
436         } while (0);
437
438         appinfo_destroy(*ai);
439
440         return ret;
441 }
442
443 EXPORT_API ail_error_e ail_appinfo_get_bool(const ail_appinfo_h ai, const char *property, bool *value)
444 {
445         ail_prop_bool_e prop;
446         int val;
447
448         retv_if(!ai, AIL_ERROR_INVALID_PARAMETER);
449         retv_if(!property, AIL_ERROR_INVALID_PARAMETER);
450         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
451
452         prop = _ail_convert_to_prop_bool(property);
453
454         if (prop < E_AIL_PROP_BOOL_MIN || prop > E_AIL_PROP_BOOL_MAX)
455                 return AIL_ERROR_INVALID_PARAMETER;
456
457         if (ai->stmt) {
458                 int index;
459                 index = sql_get_app_info_idx(prop);
460                 if (db_column_bool(ai->stmt, index, value) < 0)
461                         return AIL_ERROR_DB_FAILED;
462         } else {
463                 val = atoi(ai->values[prop]);
464                 *value = (val == 0) ? false : true;
465         }
466         return AIL_ERROR_OK;
467 }
468
469 EXPORT_API ail_error_e ail_appinfo_get_int(const ail_appinfo_h ai, const char *property, int *value)
470 {
471         ail_prop_int_e prop;
472
473         retv_if(!ai, AIL_ERROR_INVALID_PARAMETER);
474         retv_if(!property, AIL_ERROR_INVALID_PARAMETER);
475         retv_if(!value, AIL_ERROR_INVALID_PARAMETER);
476
477         prop = _ail_convert_to_prop_int(property);
478
479         if (prop < E_AIL_PROP_INT_MIN || prop > E_AIL_PROP_INT_MAX)
480                 return AIL_ERROR_INVALID_PARAMETER;
481
482         if (ai->stmt) {
483                 int index;
484                 index = sql_get_app_info_idx(prop);
485                 if (db_column_int(ai->stmt, index, value) < 0)
486                         return AIL_ERROR_DB_FAILED;
487         } else
488                 *value = atoi(ai->values[prop]);
489
490         return AIL_ERROR_OK;
491 }
492
493 char *appinfo_get_localname(const char *package, char *locale, uid_t uid)
494 {
495         db_open(DB_OPEN_RO, uid);
496         sqlite3_stmt *stmt;
497         char *str = NULL;
498         char *localname;
499         char query[512];
500
501         snprintf(query, sizeof(query), QUERY_GET_LOCALNAME, package, locale);
502
503         if (uid != GLOBAL_USER)
504                 retv_if(db_prepare(query, &stmt) < 0, NULL);
505         else
506                 retv_if(db_prepare_globalro(query, &stmt) < 0, NULL);
507
508         do {
509                 if (db_step(stmt) < 0)
510                         break;
511                 if (db_column_str(stmt, 0, &str) < 0)
512                         break;
513                 if (str)
514                         localname = strdup(str);
515                 else
516                         localname = NULL;
517
518                 db_finalize(stmt);
519
520                 return localname;
521         } while (0);
522
523         db_finalize(stmt);
524         return NULL;
525 }
526
527 EXPORT_API ail_error_e ail_appinfo_get_str(const ail_appinfo_h ai, const char *property, char **str)
528 {
529         int index;
530         char *value;
531         char *pkg;
532         char *pkg_type;
533         char *locale, *localname;
534         ail_prop_str_e prop;
535         char *locale_new;
536
537         retv_if(!ai, AIL_ERROR_INVALID_PARAMETER);
538         retv_if(!property, AIL_ERROR_INVALID_PARAMETER);
539         retv_if(!str, AIL_ERROR_INVALID_PARAMETER);
540
541         prop = _ail_convert_to_prop_str(property);
542
543         if (prop < E_AIL_PROP_STR_MIN || prop > E_AIL_PROP_STR_MAX)
544                 return AIL_ERROR_INVALID_PARAMETER;
545
546         localname = NULL;
547
548         if (E_AIL_PROP_NAME_STR == prop) {
549                 if (ai->stmt) {
550                         if (db_column_str(ai->stmt, E_AIL_PROP_X_SLP_PACKAGETYPE_STR, &pkg_type) < 0)
551                                 return AIL_ERROR_DB_FAILED;
552                         if (pkg_type && (strcasecmp(pkg_type, "tpk") == 0)) {
553                                 locale = sql_get_locale();
554                                 retv_if(locale == NULL, AIL_ERROR_FAIL);
555
556                                 if (db_column_str(ai->stmt, E_AIL_PROP_PACKAGE_STR, &pkg) < 0) {
557                                         free(locale);
558                                         return AIL_ERROR_DB_FAILED;
559                                 }
560                                 if (pkg == NULL) {
561                                         free(locale);
562                                         return AIL_ERROR_DB_FAILED;
563                                 }
564
565                                 locale_new = __get_app_locale_by_fallback(pkg, locale);
566                                 localname = (char *)appinfo_get_localname(pkg, locale_new, GLOBAL_USER);
567                                 free(locale);
568                                 free(locale_new);
569                         } else {
570                                 if (db_column_str(ai->stmt, SQL_LOCALNAME_IDX, &localname) < 0)
571                                         return AIL_ERROR_DB_FAILED;
572                         }
573                 } else {
574                         pkg_type = ai->values[E_AIL_PROP_X_SLP_PACKAGETYPE_STR];
575                         pkg = ai->values[E_AIL_PROP_PACKAGE_STR];
576                         retv_if(pkg == NULL, AIL_ERROR_FAIL);
577
578                         locale = sql_get_locale();
579                         retv_if(locale == NULL, AIL_ERROR_FAIL);
580
581                         if (pkg_type && (strcasecmp(pkg_type, "tpk") == 0)) {
582                                 locale_new = __get_app_locale_by_fallback(pkg, locale);
583                                 localname = (char *)appinfo_get_localname(pkg, locale_new, GLOBAL_USER);
584                                 free(locale);
585                                 free(locale_new);
586                         } else {
587                                 localname = (char *)appinfo_get_localname(pkg, locale, GLOBAL_USER);
588                                 free(locale);
589                         }
590                 }
591
592                 if (localname) {
593                         if (!ai->stmt) {
594                                 if (ai->values) {
595                                         if (ai->values[prop])
596                                                 free(ai->values[prop]);
597                                         ai->values[prop] = localname;
598                                 }
599                         }
600                         *str = localname;
601                         return AIL_ERROR_OK;
602                 }
603         }
604
605         if (ai->stmt) {
606                 index = sql_get_app_info_idx(prop);
607                 if (db_column_str(ai->stmt, index, &value) < 0)
608                         return AIL_ERROR_DB_FAILED;
609
610                 *str = value;
611         } else
612                 *str = ai->values[prop];
613
614         return AIL_ERROR_OK;
615 }
616
617 EXPORT_API ail_error_e ail_appinfo_get_usr_str(const ail_appinfo_h ai, const char *property, uid_t uid, char **str)
618 {
619         int index;
620         char *value;
621         char *pkg;
622         char *pkg_type;
623         char *locale, *localname;
624         ail_prop_str_e prop;
625         char *locale_new;
626
627         retv_if(!ai, AIL_ERROR_INVALID_PARAMETER);
628         retv_if(!property, AIL_ERROR_INVALID_PARAMETER);
629         retv_if(!str, AIL_ERROR_INVALID_PARAMETER);
630
631         prop = _ail_convert_to_prop_str(property);
632
633         if (prop < E_AIL_PROP_STR_MIN || prop > E_AIL_PROP_STR_MAX)
634                 return AIL_ERROR_INVALID_PARAMETER;
635
636         localname = NULL;
637
638         if (E_AIL_PROP_NAME_STR == prop) {
639                 if (ai->stmt) {
640                         if (db_column_str(ai->stmt, E_AIL_PROP_X_SLP_PACKAGETYPE_STR, &pkg_type) < 0)
641                                 return AIL_ERROR_DB_FAILED;
642                         if (pkg_type && (strcasecmp(pkg_type, "tpk") == 0)) {
643                                 locale = sql_get_locale();
644                                 retv_if(locale == NULL, AIL_ERROR_FAIL);
645
646                                 if (db_column_str(ai->stmt, E_AIL_PROP_PACKAGE_STR, &pkg) < 0) {
647                                         free(locale);
648                                         return AIL_ERROR_DB_FAILED;
649                                 }
650                                 if (pkg == NULL) {
651                                         free(locale);
652                                         return AIL_ERROR_DB_FAILED;
653                                 }
654
655                                 locale_new = __get_app_locale_by_fallback(pkg, locale);
656                                 localname = (char *)appinfo_get_localname(pkg, locale_new, uid);
657                                 free(locale);
658                                 free(locale_new);
659                         } else {
660                                 if (db_column_str(ai->stmt, SQL_LOCALNAME_IDX, &localname) < 0)
661                                         return AIL_ERROR_DB_FAILED;
662                         }
663                 } else {
664                         pkg_type = ai->values[E_AIL_PROP_X_SLP_PACKAGETYPE_STR];
665                         pkg = ai->values[E_AIL_PROP_PACKAGE_STR];
666                         retv_if(pkg == NULL, AIL_ERROR_FAIL);
667
668                         locale = sql_get_locale();
669                         retv_if(locale == NULL, AIL_ERROR_FAIL);
670
671                         if (pkg_type && (strcasecmp(pkg_type, "tpk") == 0)) {
672                                 locale_new = __get_app_locale_by_fallback(pkg, locale);
673                                 localname = (char *)appinfo_get_localname(pkg, locale_new, uid);
674                                 free(locale);
675                                 free(locale_new);
676                         } else {
677                                 localname = (char *)appinfo_get_localname(pkg, locale, uid);
678                                 free(locale);
679                         }
680                 }
681
682                 if (localname) {
683                         if (!ai->stmt) {
684                                 if (ai->values) {
685                                         if (ai->values[prop])
686                                                 free(ai->values[prop]);
687                                         ai->values[prop] = localname;
688                                 }
689                         }
690                         *str = localname;
691                         return AIL_ERROR_OK;
692                 }
693         }
694
695         if (ai->stmt) {
696                 index = sql_get_app_info_idx(prop);
697                 if (db_column_str(ai->stmt, index, &value) < 0)
698                         return AIL_ERROR_DB_FAILED;
699
700                 *str = value;
701         } else
702                 *str = ai->values[prop];
703
704         return AIL_ERROR_OK;
705 }
706
707 EXPORT_API ail_error_e ail_close_appinfo_db(void)
708 {
709         return db_close();
710 }