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