3dd0eda7a2175c1d33f5cb7f0620271cb8f4a2fb
[platform/core/appfw/pkgmgr-info.git] / parser / src / pkgmgr_parser_db.c
1 /*
2  * Copyright (c) 2000 - 2017 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */
17
18 #include <fcntl.h>
19 #include <stdio.h>
20 #include <stdbool.h>
21 #include <string.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <sys/smack.h>
25 #include <sys/sysmacros.h>
26 #include <linux/limits.h>
27 #include <unistd.h>
28 #include <pwd.h>
29
30 #include <glib.h>
31 #include <gio/gio.h>
32 #include <sqlite3.h>
33
34 #include <tzplatform_config.h>
35 #include <system_info.h>
36
37 #include "pkgmgr-info.h"
38 #include "pkgmgrinfo_basic.h"
39 #include "pkgmgr_parser.h"
40 #include "pkgmgr_parser_db_queries.h"
41 #include "pkgmgr_parser_debug.h"
42 #include "pkgmgr_parser_internal.h"
43
44 #ifndef OWNER_ROOT
45 #define OWNER_ROOT 0
46 #endif
47 #ifndef GLOBAL_USER
48 #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
49 #endif
50 #ifndef APPFW_USER
51 #define APPFW_USER "app_fw"
52 #endif
53
54 #define BUFSIZE 4096
55
56 #define LDPI "ldpi"
57 #define MDPI "mdpi"
58 #define HDPI "hdpi"
59 #define XHDPI "xhdpi"
60 #define XXHDPI "xxhdpi"
61
62 #define LDPI_MIN 0
63 #define LDPI_MAX 240
64 #define MDPI_MIN 241
65 #define MDPI_MAX 300
66 #define HDPI_MIN 301
67 #define HDPI_MAX 380
68 #define XHDPI_MIN 381
69 #define XHDPI_MAX 480
70 #define XXHDPI_MIN 481
71 #define XXHDPI_MAX 600
72
73 /* app background category value */
74 #define APP_BG_CATEGORY_USER_DISABLE_FALSE_VAL 0x00000
75 #define APP_BG_CATEGORY_USER_DISABLE_TRUE_VAL  0x00001
76 #define APP_BG_CATEGORY_MEDIA_VAL              0x00002
77 #define APP_BG_CATEGORY_DOWNLOAD_VAL           0x00004
78 #define APP_BG_CATEGORY_BGNETWORK_VAL          0x00008
79 #define APP_BG_CATEGORY_LOCATION_VAL           0x00010
80 #define APP_BG_CATEGORY_SENSOR_VAL             0x00020
81 #define APP_BG_CATEGORY_IOTCOMM_VAL            0x00040
82 #define APP_BG_CATEGORY_SYSTEM_VAL             0x00080
83
84 #define APP_BG_CATEGORY_USER_DISABLE_FALSE_STR "enable"
85 #define APP_BG_CATEGORY_USER_DISABLE_TRUE_STR  "disable"
86 #define APP_BG_CATEGORY_MEDIA_STR              "media"
87 #define APP_BG_CATEGORY_DOWNLOAD_STR           "download"
88 #define APP_BG_CATEGORY_BGNETWORK_STR          "background-network"
89 #define APP_BG_CATEGORY_LOCATION_STR           "location"
90 #define APP_BG_CATEGORY_SENSOR_STR             "sensor"
91 #define APP_BG_CATEGORY_IOTCOMM_STR            "iot-communication"
92 #define APP_BG_CATEGORY_SYSTEM                 "system"
93
94 #define REGULAR_USER 5000
95 static inline uid_t __getuid(void)
96 {
97         uid_t uid = getuid();
98
99         if (uid < REGULAR_USER)
100                 return tzplatform_getuid(TZ_SYS_GLOBALAPP_USER);
101         else
102                 return uid;
103 }
104
105 static const char *__get_bool(char *value, bool is_true)
106 {
107         if (value != NULL) {
108                 if (!strcmp(value, ""))
109                         return (is_true) ? "true" : "false";
110                 return value;
111         }
112
113         return (is_true) ? "true" : "false";
114 }
115
116 #define __BEGIN_TRANSACTION(db)                                                \
117 do {                                                                           \
118         if (sqlite3_exec(db, "BEGIN DEFERRED", NULL, NULL, NULL) !=           \
119                         SQLITE_OK) {                                           \
120                 _LOGE("begin transaction failed: %s", sqlite3_errmsg(db));     \
121                 return PM_PARSER_R_ERROR;                                      \
122         }                                                                      \
123 } while (0)                                                                    \
124
125 #define __DO_TRANSACTION(db, func)                                             \
126 do {                                                                           \
127         if (func) {                                                            \
128                 _LOGE("transaction failed: %s, rollback", sqlite3_errmsg(db)); \
129                 if (sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL) !=          \
130                                 SQLITE_OK)                                     \
131                         _LOGE("roll back transaction failed: %s",              \
132                                         sqlite3_errmsg(db));                   \
133                 return PM_PARSER_R_ERROR;                                      \
134         }                                                                      \
135 } while (0)                                                                    \
136
137 #define __END_TRANSACTION(db)                                                  \
138 do {                                                                           \
139         if (sqlite3_exec(db, "COMMIT", NULL, NULL, NULL) !=                    \
140                         SQLITE_OK) {                                           \
141                 _LOGE("commit failed: %s, rollback", sqlite3_errmsg(db));      \
142                 if (sqlite3_exec(db, "ROLLBACK", NULL, NULL, NULL) !=          \
143                                 SQLITE_OK)                                     \
144                         _LOGE("roll back transaction failed: %s",              \
145                                         sqlite3_errmsg(db));                   \
146                 return PM_PARSER_R_ERROR;                                      \
147         }                                                                      \
148 } while (0)                                                                    \
149
150 #define __BIND_TEXT(db, stmt, i, text)                                         \
151 do {                                                                           \
152         if (sqlite3_bind_text(stmt, i, text, -1, SQLITE_STATIC) != SQLITE_OK) {\
153                 _LOGE("bind error(index %d): %s", i, sqlite3_errmsg(db));      \
154                 sqlite3_finalize(stmt);                                        \
155                 return -1;                                                     \
156         }                                                                      \
157 } while (0)
158
159 #define __BIND_INT(db, stmt, i, int)                                           \
160 do {                                                                           \
161         if (sqlite3_bind_int(stmt, i, int) != SQLITE_OK) {                     \
162                 _LOGE("bind error(index %d): %s", i, sqlite3_errmsg(db));      \
163                 sqlite3_finalize(stmt);                                        \
164                 return -1;                                                     \
165         }                                                                      \
166 } while (0)
167
168 static const char *__get_parser_db_path(uid_t uid)
169 {
170         char buf[PATH_MAX];
171         const char *path;
172
173         if (uid == GLOBAL_USER || uid == OWNER_ROOT) {
174                 path = tzplatform_mkpath(TZ_SYS_DB, ".pkgmgr_parser.db");
175         } else {
176                 snprintf(buf, sizeof(buf), "user/%d/.pkgmgr_parser.db", uid);
177                 path = tzplatform_mkpath(TZ_SYS_DB, buf);
178         }
179
180         return path;
181 }
182
183 static const char *__get_cert_db_path(void)
184 {
185         return tzplatform_mkpath(TZ_SYS_DB, ".pkgmgr_cert.db");
186 }
187
188 #define DB_VERSION_PATH SYSCONFDIR "/package-manager/pkg_db_version.txt"
189 static int __set_db_version(sqlite3 *db)
190 {
191         int ret;
192         FILE *fp = NULL;
193         char version[PKG_STRING_LEN_MAX] = { 0 };
194         char *query = NULL;
195
196         fp = fopen(DB_VERSION_PATH, "r");
197         retvm_if(fp == NULL, -1, "Failed to open db version file");
198         if (fgets(version, sizeof(version), fp) == NULL) {
199                 _LOGE("Failed to get version information");
200                 fclose(fp);
201                 return -1;
202         }
203         fclose(fp);
204
205         query = sqlite3_mprintf("PRAGMA user_version=%Q", version);
206         if (!query) {
207                 _LOGE("Out of memory");
208                 return -1;
209         }
210
211         ret = sqlite3_exec(db, query, NULL, NULL, NULL);
212         if (ret != SQLITE_OK) {
213                 _LOGE("exec failed: %s", sqlite3_errmsg(db));
214                 sqlite3_free(query);
215                 return -1;
216         }
217         sqlite3_free(query);
218
219         return 0;
220 }
221
222 /* TODO: Do not labeling directly */
223 #define DB_LABEL "User::Home"
224 #define SET_SMACK_LABEL(x)                                                     \
225 do {                                                                           \
226         if (smack_setlabel((x), DB_LABEL, SMACK_LABEL_ACCESS))                 \
227                 _LOGE("failed chsmack -a %s %s", DB_LABEL, x);                 \
228         else                                                                   \
229                 _LOGD("chsmack -a %s %s", DB_LABEL, x);                        \
230 } while (0)
231
232 static int __set_db_permission(const char *path, uid_t uid)
233 {
234         int fd;
235         const char *files[2];
236         char journal_file[BUFSIZE];
237         struct stat sb;
238         mode_t mode;
239         struct passwd pwd;
240         struct passwd *result;
241         char buf[BUFSIZE];
242         int ret;
243         int i;
244
245         if (getuid() != OWNER_ROOT)
246                 return 0;
247
248         if (uid == OWNER_ROOT || uid == GLOBAL_USER) {
249                 ret = getpwnam_r(APPFW_USER, &pwd, buf, sizeof(buf), &result);
250                 if (result == NULL) {
251                         if (ret == 0)
252                                 _LOGE("no such user: %d", uid);
253                         else
254                                 _LOGE("getpwuid_r failed: %d", errno);
255                         return -1;
256                 }
257                 uid = pwd.pw_uid;
258         }
259
260         snprintf(journal_file, sizeof(journal_file), "%s-journal", path);
261         files[0] = path;
262         files[1] = journal_file;
263
264         ret = getpwuid_r(uid, &pwd, buf, sizeof(buf), &result);
265         if (result == NULL) {
266                 if (ret == 0)
267                         _LOGE("no such user: %d", uid);
268                 else
269                         _LOGE("getpwuid_r failed: %d", errno);
270                 return -1;
271         }
272
273         for (i = 0; i < 2; i++) {
274                 fd = open(files[i], O_RDONLY);
275                 if (fd == -1) {
276                         _LOGE("open %s failed: %d", files[i], errno);
277                         return -1;
278                 }
279                 ret = fstat(fd, &sb);
280                 if (ret == -1) {
281                         _LOGE("stat %s failed: %d", files[i], errno);
282                         close(fd);
283                         return -1;
284                 }
285                 if (S_ISLNK(sb.st_mode)) {
286                         _LOGE("%s is symlink!", files[i]);
287                         close(fd);
288                         return -1;
289                 }
290                 ret = fchown(fd, uid, pwd.pw_gid);
291                 if (ret == -1) {
292                         _LOGE("fchown %s failed: %d", files[i], errno);
293                         close(fd);
294                         return -1;
295                 }
296
297                 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
298                 if (!strcmp(path, __get_cert_db_path()))
299                         mode |= S_IWOTH;
300                 ret = fchmod(fd, mode);
301                 if (ret == -1) {
302                         _LOGD("fchmod %s failed: %d", files[i], errno);
303                         close(fd);
304                         return -1;
305                 }
306                 close(fd);
307                 SET_SMACK_LABEL(files[i]);
308         }
309
310         return 0;
311 }
312
313 static int __create_tables(sqlite3 *db, const char **queries)
314 {
315         int ret;
316         int i;
317         for (i = 0; queries[i] != NULL; i++) {
318                 ret = sqlite3_exec(db, queries[i], NULL, NULL, NULL);
319                 if (ret != SQLITE_OK) {
320                         _LOGE("exec failed: %s", sqlite3_errmsg(db));
321                         return -1;
322                 }
323         }
324         return 0;
325 }
326
327 static int __initialize_db(sqlite3 *db, const char *dbpath, uid_t uid)
328 {
329         const char **queries;
330
331         if (__set_db_version(db))
332                 return -1;
333
334         if (strstr(dbpath, ".pkgmgr_parser.db")) {
335                 queries = PARSER_INIT_QUERIES;
336         } else if (strstr(dbpath, ".pkgmgr_cert.db")) {
337                 queries = CERT_INIT_QUERIES;
338         } else {
339                 _LOGE("unexpected dbpath: %s", dbpath);
340                 return -1;
341         }
342
343         __BEGIN_TRANSACTION(db);
344         __DO_TRANSACTION(db, __create_tables(db, queries));
345         __END_TRANSACTION(db);
346
347         if (__set_db_permission(dbpath, uid))
348                 _LOGE("failed to set db permission");
349
350         return 0;
351 }
352
353 #define RESOURCED_BUS_NAME "org.tizen.resourced"
354 #define RESOURCED_PROC_PATH "/Org/Tizen/ResourceD/Process"
355 #define RESOURCED_PROC_INTERFACE "org.tizen.resourced.process"
356 #define RESOURCED_PROC_METHOD "ProcExclude"
357 static void __send_wakeup_signal_to_resourced(pid_t pid)
358 {
359         GError *error = NULL;
360         GDBusConnection *conn;
361         GDBusProxy *proxy;
362         GVariant *reply;
363
364         conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
365         if (conn == NULL) {
366                 _LOGE("Failed to connect to dbus: %s", error->message);
367                 g_error_free(error);
368                 return;
369         }
370
371         proxy = g_dbus_proxy_new_sync(conn,
372                         G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
373                         NULL, RESOURCED_BUS_NAME,
374                         RESOURCED_PROC_PATH, RESOURCED_PROC_INTERFACE,
375                         NULL, &error);
376         if (proxy == NULL) {
377                 _LOGE("failed to get proxy object: %s", error->message);
378                 g_error_free(error);
379                 g_object_unref(conn);
380                 return;
381         }
382
383         reply = g_dbus_proxy_call_sync(proxy, RESOURCED_PROC_METHOD,
384                         g_variant_new("(si)", "wakeup", pid),
385                         G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
386         if (reply == NULL)
387                 _LOGE("failed to get reply from resourced");
388         if (error) {
389                 _LOGE("failed to send request: %s", error->message);
390                 g_error_free(error);
391         }
392
393         g_object_unref(proxy);
394         g_object_unref(conn);
395 }
396
397 static void __check_db_lock(const char *dbpath)
398 {
399         FILE *fp;
400         FILE *fp_cmdline;
401         struct stat sb;
402         char type[BUFSIZE];
403         int pid;
404         unsigned int maj;
405         unsigned int min;
406         unsigned long long ino;
407         char cmdline[BUFSIZE];
408         char name[BUFSIZE];
409         size_t len;
410
411         if (stat(dbpath, &sb) == -1) {
412                 _LOGE("get db file(%s) status failed: %d", dbpath, errno);
413                 return;
414         }
415
416         fp = fopen("/proc/locks", "r");
417         if (fp == NULL) {
418                 _LOGE("Failed to open lock info: %d", errno);
419                 return;
420         }
421
422         while (fscanf(fp, "%*s %*s %*s %5s %d %x:%x:%llu %*s %*s",
423                                 type, &pid, &maj, &min, &ino) != EOF) {
424                 if (maj != major(sb.st_dev) || min != minor(sb.st_dev) ||
425                                 ino != sb.st_ino || pid == getpid() ||
426                                 strcasecmp(type, "WRITE"))
427                         continue;
428
429                 snprintf(cmdline, sizeof(cmdline), "/proc/%d/cmdline", pid);
430                 fp_cmdline = fopen(cmdline, "r");
431                 name[0] = '\0';
432                 if (fp_cmdline != NULL) {
433                         len = fread(name, sizeof(char), sizeof(name) - 1,
434                                         fp_cmdline);
435                         if (len > 0) {
436                                 if (name[len - 1] == '\n')
437                                         name[len - 1] = '\0';
438                                 else
439                                         name[len] = '\0';
440                         }
441                         fclose(fp_cmdline);
442                 }
443
444                 _LOGE("%s (%d) has lock on pkgmgr db(%s)!", name, pid, dbpath);
445                 __send_wakeup_signal_to_resourced(pid);
446         }
447
448         fclose(fp);
449 }
450
451 #define BUSY_WAITING_USEC (1000000 / 10 / 2) /* 0.05 sec */
452 #define BUSY_WAITING_MAX 100 /* wait for max 5 sec */
453 static int __db_busy_handler(void *data, int count)
454 {
455         if (count < (BUSY_WAITING_MAX / 2)) {
456                 usleep(BUSY_WAITING_USEC);
457                 return 1;
458         } else if (count == (BUSY_WAITING_MAX / 2)) {
459                 __check_db_lock((const char *)data);
460                 usleep(BUSY_WAITING_USEC);
461                 return 1;
462         } else if (count < BUSY_WAITING_MAX) {
463                 usleep(BUSY_WAITING_USEC);
464                 return 1;
465         } else {
466                 /* sqlite3_prepare_v2 will return SQLITE_BUSY */
467                 return 0;
468         }
469 }
470
471 API int pkgmgr_parser_initialize_parser_db(uid_t uid)
472 {
473         int ret;
474         const char *dbpath;
475         sqlite3 *db;
476
477         dbpath = __get_parser_db_path(uid);
478         if (access(dbpath, F_OK) != -1) {
479                 _LOGE("Manifest db for user %d is already exists", uid);
480                 return PM_PARSER_R_ERROR;
481         }
482
483         ret = sqlite3_open_v2(dbpath, &db,
484                         SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
485         if (ret != SQLITE_OK) {
486                 _LOGE("open db failed: %d", ret);
487                 sqlite3_close_v2(db);
488                 return PM_PARSER_R_ERROR;
489         }
490
491         ret = sqlite3_busy_handler(db, __db_busy_handler, NULL);
492         if (ret != SQLITE_OK) {
493                 _LOGE("failed to register busy handler: %s",
494                                 sqlite3_errmsg(db));
495                 sqlite3_close_v2(db);
496                 return ret;
497         }
498
499         if (__initialize_db(db, dbpath, uid)) {
500                 sqlite3_close_v2(db);
501                 return PM_PARSER_R_ERROR;
502         }
503         sqlite3_close_v2(db);
504
505         return PM_PARSER_R_OK;
506 }
507
508 API int pkgmgr_parser_initialize_cert_db(void)
509 {
510         int ret;
511         const char *dbpath;
512         sqlite3 *db;
513
514         dbpath = __get_cert_db_path();
515         if (access(dbpath, F_OK) != -1) {
516                 _LOGE("Cert db is already exists");
517                 return PM_PARSER_R_ERROR;
518         }
519
520         ret = sqlite3_open_v2(dbpath, &db,
521                         SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL);
522         if (ret != SQLITE_OK) {
523                 _LOGE("open db failed: %d", ret);
524                 sqlite3_close_v2(db);
525                 return PM_PARSER_R_ERROR;
526         }
527
528         ret = sqlite3_busy_handler(db, __db_busy_handler, NULL);
529         if (ret != SQLITE_OK) {
530                 _LOGE("failed to register busy handler: %s",
531                                 sqlite3_errmsg(db));
532                 sqlite3_close_v2(db);
533                 return ret;
534         }
535
536         if (__initialize_db(db, dbpath, GLOBAL_USER)) {
537                 sqlite3_close_v2(db);
538                 return PM_PARSER_R_ERROR;
539         }
540         sqlite3_close_v2(db);
541
542         return PM_PARSER_R_OK;
543 }
544
545 API int pkgmgr_parser_create_and_initialize_db(uid_t uid)
546 {
547         int ret;
548         struct passwd pwd;
549         struct passwd *result;
550         char buf[BUFSIZE];
551
552         ret = getpwnam_r(APPFW_USER, &pwd, buf, sizeof(buf), &result);
553         if (result == NULL) {
554                 if (ret == 0)
555                         _LOGE("no such user: %s", APPFW_USER);
556                 else
557                         _LOGE("getpwnam_r failed: %d", errno);
558                 return PM_PARSER_R_ERROR;
559         }
560
561         if (getuid() != OWNER_ROOT && getuid() != pwd.pw_uid) {
562                 _LOGE("Only root or app_fw user is allowed");
563                 return PM_PARSER_R_EINVAL;
564         }
565
566         if (pkgmgr_parser_initialize_parser_db(uid))
567                 return PM_PARSER_R_ERROR;
568
569         if (uid == OWNER_ROOT || uid == GLOBAL_USER)
570                 if (pkgmgr_parser_initialize_cert_db())
571                         return PM_PARSER_R_ERROR;
572
573         return PM_PARSER_R_OK;
574 }
575
576 static int __convert_background_category(GList *category_list)
577 {
578         int ret = 0;
579         GList *tmp;
580         char *category_data;
581
582         if (category_list == NULL)
583                 return 0;
584
585         for (tmp = category_list; tmp; tmp = tmp->next) {
586                 category_data = (char *)tmp->data;
587                 if (category_data == NULL)
588                         continue;
589                 if (!strcmp(category_data, APP_BG_CATEGORY_MEDIA_STR))
590                         ret |= APP_BG_CATEGORY_MEDIA_VAL;
591                 else if (!strcmp(category_data, APP_BG_CATEGORY_DOWNLOAD_STR))
592                         ret |= APP_BG_CATEGORY_DOWNLOAD_VAL;
593                 else if (!strcmp(category_data, APP_BG_CATEGORY_BGNETWORK_STR))
594                         ret |= APP_BG_CATEGORY_BGNETWORK_VAL;
595                 else if (!strcmp(category_data, APP_BG_CATEGORY_LOCATION_STR))
596                         ret |= APP_BG_CATEGORY_LOCATION_VAL;
597                 else if (!strcmp(category_data, APP_BG_CATEGORY_SENSOR_STR))
598                         ret |= APP_BG_CATEGORY_SENSOR_VAL;
599                 else if (!strcmp(category_data, APP_BG_CATEGORY_IOTCOMM_STR))
600                         ret |= APP_BG_CATEGORY_IOTCOMM_VAL;
601                 else if (!strcmp(category_data, APP_BG_CATEGORY_SYSTEM))
602                         ret |= APP_BG_CATEGORY_SYSTEM_VAL;
603                 else
604                         _LOGE("Unidentified category [%s]", category_data);
605         }
606
607         return ret;
608 }
609
610 #define EFFECTIVE_APPID_KEY "http://tizen.org/metadata/effective-appid"
611 static const char *__find_effective_appid(GList *metadata_list)
612 {
613         GList *tmp;
614         metadata_x *md;
615
616         for (tmp = metadata_list; tmp; tmp = tmp->next) {
617                 md = (metadata_x *)tmp->data;
618                 if (md == NULL || md->key == NULL)
619                         continue;
620
621                 if (strcmp(md->key, EFFECTIVE_APPID_KEY) == 0) {
622                         if (md->value)
623                                 return md->value;
624                 }
625         }
626
627         return NULL;
628 }
629
630 static int __insert_appcontrol_privilege_info(sqlite3 *db, const char *appid,
631                 appcontrol_x *ac)
632 {
633         static const char query[] =
634                 "INSERT INTO package_app_app_control_privilege (app_id,"
635                 "  app_control, privilege) VALUES (?, ?, ?)";
636         int ret;
637         sqlite3_stmt *stmt;
638         int idx;
639         char app_control[BUFSIZE];
640         GList *tmp;
641         char *privilege;
642
643         if (ac == NULL)
644                 return 0;
645
646         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
647         if (ret != SQLITE_OK) {
648                 _LOGE("prepare failed: %s", sqlite3_errmsg(db));
649                 return -1;
650         }
651
652         for (tmp = ac->privileges; tmp; tmp = tmp->next) {
653                 privilege = (char *)tmp->data;
654                 if (privilege == NULL || !strlen(privilege))
655                         continue;
656
657                 idx = 1;
658                 snprintf(app_control, sizeof(app_control), "%s|%s|%s",
659                                 ac->operation ? (strlen(ac->operation) > 0 ?
660                                         ac->operation : "NULL") : "NULL",
661                                 ac->uri ? (strlen(ac->uri) > 0 ?
662                                         ac->uri : "NULL") : "NULL",
663                                 ac->mime ? (strlen(ac->mime) > 0 ?
664                                         ac->mime : "NULL") : "NULL");
665                 __BIND_TEXT(db, stmt, idx++, appid);
666                 __BIND_TEXT(db, stmt, idx++, app_control);
667                 __BIND_TEXT(db, stmt, idx++, privilege);
668
669                 ret = sqlite3_step(stmt);
670                 if (ret != SQLITE_DONE) {
671                         _LOGE("step failed: %s", sqlite3_errmsg(db));
672                         sqlite3_finalize(stmt);
673                         return -1;
674                 }
675
676                 sqlite3_reset(stmt);
677         }
678
679         sqlite3_finalize(stmt);
680
681         return 0;
682 }
683
684 static int __insert_appcontrol_info(sqlite3 *db, application_x *app)
685 {
686         static const char query[] =
687                 "INSERT INTO package_app_app_control (app_id, app_control,"
688                 "  visibility, app_control_id) "
689                 "VALUES (?, ?, ?, ?)";
690         int ret;
691         sqlite3_stmt *stmt;
692         int idx;
693         char app_control[BUFSIZE];
694         GList *tmp;
695         appcontrol_x *ac;
696
697         if (app->appcontrol == NULL)
698                 return 0;
699
700         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
701         if (ret != SQLITE_OK) {
702                 _LOGE("prepare failed: %s", sqlite3_errmsg(db));
703                 return -1;
704         }
705
706         for (tmp = app->appcontrol; tmp; tmp = tmp->next) {
707                 ac = (appcontrol_x *)tmp->data;
708                 if (ac == NULL)
709                         continue;
710                 idx = 1;
711                 snprintf(app_control, sizeof(app_control), "%s|%s|%s",
712                                 ac->operation ? (strlen(ac->operation) > 0 ?
713                                         ac->operation : "NULL") : "NULL",
714                                 ac->uri ? (strlen(ac->uri) > 0 ?
715                                         ac->uri : "NULL") : "NULL",
716                                 ac->mime ? (strlen(ac->mime) > 0 ?
717                                         ac->mime : "NULL") : "NULL");
718                 __BIND_TEXT(db, stmt, idx++, app->appid);
719                 __BIND_TEXT(db, stmt, idx++, app_control);
720                 __BIND_TEXT(db, stmt, idx++, ac->visibility);
721                 __BIND_TEXT(db, stmt, idx++, ac->id);
722
723                 ret = sqlite3_step(stmt);
724                 if (ret != SQLITE_DONE) {
725                         _LOGE("step failed: %s", sqlite3_errmsg(db));
726                         sqlite3_finalize(stmt);
727                         return -1;
728                 }
729
730                 if (__insert_appcontrol_privilege_info(db, app->appid, ac)) {
731                         sqlite3_finalize(stmt);
732                         return -1;
733                 }
734
735                 sqlite3_reset(stmt);
736         }
737
738         sqlite3_finalize(stmt);
739
740         return 0;
741 }
742
743 static int __insert_category_info(sqlite3 *db, application_x *app)
744 {
745         static const char query[] =
746                 "INSERT INTO package_app_app_category (app_id, category) "
747                 "VALUES (?, ?)";
748         int ret;
749         sqlite3_stmt *stmt;
750         int idx;
751         GList *tmp;
752         const char *category;
753
754         if (app->category == NULL)
755                 return 0;
756
757         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
758         if (ret != SQLITE_OK) {
759                 _LOGE("prepare failed: %s", sqlite3_errmsg(db));
760                 return -1;
761         }
762
763         for (tmp = app->category; tmp; tmp = tmp->next) {
764                 category = (const char *)tmp->data;
765                 if (category == NULL)
766                         continue;
767                 idx = 1;
768                 __BIND_TEXT(db, stmt, idx++, app->appid);
769                 __BIND_TEXT(db, stmt, idx++, category);
770
771                 ret = sqlite3_step(stmt);
772                 if (ret != SQLITE_DONE) {
773                         _LOGE("step failed: %s", sqlite3_errmsg(db));
774                         sqlite3_finalize(stmt);
775                         return -1;
776                 }
777
778                 sqlite3_reset(stmt);
779         }
780
781         sqlite3_finalize(stmt);
782
783         return 0;
784 }
785
786 static int __insert_metadata_info(sqlite3 *db, application_x *app)
787 {
788         static const char query[] =
789                 "INSERT INTO package_app_app_metadata (app_id,"
790                 "  md_key, md_value) VALUES (?, ?, ?)";
791         int ret;
792         sqlite3_stmt *stmt;
793         int idx;
794         GList *tmp;
795         metadata_x *md;
796
797         if (app->metadata == NULL)
798                 return 0;
799
800         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
801         if (ret != SQLITE_OK) {
802                 _LOGE("prepare failed: %s", sqlite3_errmsg(db));
803                 return -1;
804         }
805
806         for (tmp = app->metadata; tmp; tmp = tmp->next) {
807                 md = (metadata_x *)tmp->data;
808                 if (md == NULL)
809                         continue;
810                 idx = 1;
811                 __BIND_TEXT(db, stmt, idx++, app->appid);
812                 __BIND_TEXT(db, stmt, idx++, md->key);
813                 __BIND_TEXT(db, stmt, idx++, md->value);
814
815                 ret = sqlite3_step(stmt);
816                 if (ret != SQLITE_DONE) {
817                         _LOGE("step failed: %s", sqlite3_errmsg(db));
818                         sqlite3_finalize(stmt);
819                         return -1;
820                 }
821
822                 sqlite3_reset(stmt);
823         }
824
825         sqlite3_finalize(stmt);
826
827         return 0;
828 }
829
830 static int __insert_app_data_control_privilege_info(sqlite3 *db,
831                 datacontrol_x *datacontrol)
832 {
833         static const char query[] =
834                 "INSERT INTO package_app_data_control_privilege (providerid,"
835                 "  privilege, type) VALUES (?, ?, ?)";
836
837         int ret;
838         sqlite3_stmt *stmt;
839         int idx;
840         GList *privileges;
841         char *priv;
842
843         if (datacontrol == NULL)
844                 return 0;
845
846         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
847         if (ret != SQLITE_OK) {
848                 _LOGE("prepare failed: %s", sqlite3_errmsg(db));
849                 return -1;
850         }
851
852         for (privileges = datacontrol->privileges; privileges;
853                         privileges = privileges->next) {
854                 priv = (char *)privileges->data;
855                 if (priv == NULL)
856                         continue;
857
858                 idx = 1;
859                 __BIND_TEXT(db, stmt, idx++, datacontrol->providerid);
860                 __BIND_TEXT(db, stmt, idx++, priv);
861                 __BIND_TEXT(db, stmt, idx++, datacontrol->type);
862
863                 ret = sqlite3_step(stmt);
864                 if (ret != SQLITE_DONE) {
865                         _LOGE("step failed: %s", sqlite3_errmsg(db));
866                         sqlite3_finalize(stmt);
867                         return -1;
868                 }
869
870                 sqlite3_reset(stmt);
871         }
872
873         sqlite3_finalize(stmt);
874         return 0;
875 }
876
877 static int __insert_datacontrol_info(sqlite3 *db, application_x *app)
878 {
879         static const char query[] =
880                 "INSERT INTO package_app_data_control (app_id, providerid,"
881                 "  access, type, trusted) VALUES (?, ?, ?, ?, ?)";
882         int ret;
883         sqlite3_stmt *stmt;
884         int idx;
885         GList *tmp;
886         datacontrol_x *dc;
887
888         if (app->datacontrol == NULL)
889                 return 0;
890
891         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
892         if (ret != SQLITE_OK) {
893                 _LOGE("prepare failed: %s", sqlite3_errmsg(db));
894                 return -1;
895         }
896
897         for (tmp = app->datacontrol; tmp; tmp = tmp->next) {
898                 dc = (datacontrol_x *)tmp->data;
899                 if (dc == NULL)
900                         continue;
901                 idx = 1;
902                 __BIND_TEXT(db, stmt, idx++, app->appid);
903                 __BIND_TEXT(db, stmt, idx++, dc->providerid);
904                 __BIND_TEXT(db, stmt, idx++, dc->access);
905                 __BIND_TEXT(db, stmt, idx++, dc->type);
906                 __BIND_TEXT(db, stmt, idx++, dc->trusted);
907
908                 ret = sqlite3_step(stmt);
909                 if (ret != SQLITE_DONE) {
910                         _LOGE("step failed: %s", sqlite3_errmsg(db));
911                         sqlite3_finalize(stmt);
912                         return -1;
913                 }
914
915                 if (dc->privileges &&
916                                 __insert_app_data_control_privilege_info(db, dc)) {
917                         sqlite3_finalize(stmt);
918                         return -1;
919                 }
920
921                 sqlite3_reset(stmt);
922         }
923
924         sqlite3_finalize(stmt);
925
926         return 0;
927 }
928
929 /* TODO: move to installer */
930 static int __check_dpi(const char *dpi_char, int dpi_int)
931 {
932         if (dpi_char == NULL)
933                 return -1;
934
935         if (strcasecmp(dpi_char, LDPI) == 0) {
936                 if (dpi_int >= LDPI_MIN && dpi_int <= LDPI_MAX)
937                         return 0;
938                 else
939                         return -1;
940         } else if (strcasecmp(dpi_char, MDPI) == 0) {
941                 if (dpi_int >= MDPI_MIN && dpi_int <= MDPI_MAX)
942                         return 0;
943                 else
944                         return -1;
945         } else if (strcasecmp(dpi_char, HDPI) == 0) {
946                 if (dpi_int >= HDPI_MIN && dpi_int <= HDPI_MAX)
947                         return 0;
948                 else
949                         return -1;
950         } else if (strcasecmp(dpi_char, XHDPI) == 0) {
951                 if (dpi_int >= XHDPI_MIN && dpi_int <= XHDPI_MAX)
952                         return 0;
953                 else
954                         return -1;
955         } else if (strcasecmp(dpi_char, XXHDPI) == 0) {
956                 if (dpi_int >= XXHDPI_MIN && dpi_int <= XXHDPI_MAX)
957                         return 0;
958                 else
959                         return -1;
960         } else
961                 return -1;
962 }
963
964 static gint __compare_splashscreen_with_orientation_dpi(gconstpointer a,
965                 gconstpointer b)
966 {
967         splashscreen_x *ss = (splashscreen_x *)a;
968         const char *orientation = (const char *)b;
969         int dpi = -1;
970         int ret;
971
972         if (ss->operation || ss->dpi == NULL)
973                 return -1;
974
975         ret = system_info_get_platform_int(
976                         "http://tizen.org/feature/screen.dpi", &dpi);
977         if (ret != SYSTEM_INFO_ERROR_NONE)
978                 return -1;
979
980         if (strcasecmp(ss->orientation, orientation) == 0 &&
981                         __check_dpi(ss->dpi, dpi) == 0)
982                 return 0;
983
984         return -1;
985 }
986
987 static gint __compare_splashscreen_with_orientation(gconstpointer a,
988                 gconstpointer b)
989 {
990         splashscreen_x *ss = (splashscreen_x *)a;
991         const char *orientation = (const char *)b;
992
993         if (ss->operation || ss->dpi)
994                 return -1;
995
996         if (strcasecmp(ss->orientation, orientation) == 0)
997                 return 0;
998
999         return -1;
1000 }
1001
1002 static splashscreen_x *__find_default_splashscreen(GList *splashscreens,
1003                 const char *orientation)
1004 {
1005         GList *tmp;
1006
1007         tmp = g_list_find_custom(splashscreens, orientation,
1008                         (GCompareFunc)
1009                         __compare_splashscreen_with_orientation_dpi);
1010         if (tmp)
1011                 return (splashscreen_x *)tmp->data;
1012
1013         tmp = g_list_find_custom(splashscreens, orientation,
1014                         (GCompareFunc)__compare_splashscreen_with_orientation);
1015         if (tmp)
1016                 return (splashscreen_x *)tmp->data;
1017
1018         return NULL;
1019 }
1020
1021 static void __find_appcontrol_splashscreen_with_dpi(gpointer data,
1022                 gpointer user_data)
1023 {
1024         splashscreen_x *ss = (splashscreen_x *)data;
1025         GList **list = (GList **)user_data;
1026         int dpi = -1;
1027         int ret;
1028
1029         if (ss->operation == NULL || ss->dpi == NULL)
1030                 return;
1031
1032         ret = system_info_get_platform_int(
1033                         "http://tizen.org/feature/screen.dpi", &dpi);
1034         if (ret != SYSTEM_INFO_ERROR_NONE)
1035                 return;
1036
1037         if (__check_dpi(ss->dpi, dpi) != 0)
1038                 return;
1039
1040         *list = g_list_prepend(*list, ss);
1041 }
1042
1043 static void __find_appcontrol_splashscreen(gpointer data, gpointer user_data)
1044 {
1045         splashscreen_x *ss = (splashscreen_x *)data;
1046         GList **list = (GList **)user_data;
1047         splashscreen_x *ss_tmp;
1048         GList *tmp;
1049
1050         if (ss->operation == NULL || ss->dpi)
1051                 return;
1052
1053         for (tmp = *list; tmp; tmp = tmp->next) {
1054                 ss_tmp = (splashscreen_x *)tmp->data;
1055                 if (ss_tmp->operation
1056                         && strcmp(ss_tmp->operation, ss->operation) == 0
1057                         && strcmp(ss_tmp->orientation, ss->orientation) == 0)
1058                         return;
1059         }
1060
1061         *list = g_list_prepend(*list, ss);
1062 }
1063
1064 static GList *__find_splashscreens(GList *splashscreens)
1065 {
1066         GList *list = NULL;
1067         splashscreen_x *ss;
1068
1069         if (splashscreens == NULL)
1070                 return NULL;
1071
1072         g_list_foreach(splashscreens,
1073                         __find_appcontrol_splashscreen_with_dpi, &list);
1074         g_list_foreach(splashscreens,
1075                         __find_appcontrol_splashscreen, &list);
1076
1077         ss = __find_default_splashscreen(splashscreens, "portrait");
1078         if (ss)
1079                 list = g_list_prepend(list, ss);
1080         ss = __find_default_splashscreen(splashscreens, "landscape");
1081         if (ss)
1082                 list = g_list_prepend(list, ss);
1083
1084         return list;
1085 }
1086
1087 static int __insert_splashscreen_info(sqlite3 *db, application_x *app,
1088                 GList *ss_list)
1089 {
1090         static const char query[] =
1091                 "INSERT INTO package_app_splash_screen (app_id, src, type,"
1092                 "  orientation, indicatordisplay, operation, color_depth) "
1093                 "VALUES (?, ?, ?, ?, ?, ?, ?)";
1094         int ret;
1095         sqlite3_stmt *stmt;
1096         int idx;
1097         GList *tmp;
1098         splashscreen_x *ss;
1099
1100         if (app->splashscreens == NULL)
1101                 return 0;
1102
1103         if (ss_list == NULL)
1104                 return 0;
1105
1106         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
1107         if (ret != SQLITE_OK) {
1108                 _LOGE("prepare failed: %s", sqlite3_errmsg(db));
1109                 return -1;
1110         }
1111
1112         for (tmp = ss_list; tmp; tmp = tmp->next) {
1113                 ss = (splashscreen_x *)tmp->data;
1114                 if (ss == NULL)
1115                         continue;
1116                 idx = 1;
1117                 __BIND_TEXT(db, stmt, idx++, app->appid);
1118                 __BIND_TEXT(db, stmt, idx++, ss->src);
1119                 __BIND_TEXT(db, stmt, idx++, ss->type);
1120                 __BIND_TEXT(db, stmt, idx++, ss->orientation);
1121                 __BIND_TEXT(db, stmt, idx++, ss->indicatordisplay);
1122                 __BIND_TEXT(db, stmt, idx++, ss->operation);
1123                 __BIND_TEXT(db, stmt, idx++, ss->color_depth);
1124
1125                 ret = sqlite3_step(stmt);
1126                 if (ret != SQLITE_DONE) {
1127                         _LOGE("step failed: %s", sqlite3_errmsg(db));
1128                         sqlite3_finalize(stmt);
1129                         return -1;
1130                 }
1131
1132                 sqlite3_reset(stmt);
1133         }
1134
1135         sqlite3_finalize(stmt);
1136
1137         return 0;
1138 }
1139
1140 static void __trimfunc(GList *trim_list)
1141 {
1142         char *trim_data;
1143         char *prev = NULL;
1144         GList *list = g_list_first(trim_list);
1145
1146         while (list) {
1147                 trim_data = (char *)list->data;
1148                 if (trim_data) {
1149                         if (prev) {
1150                                 if (strcmp(trim_data, prev) == 0) {
1151                                         trim_list = g_list_remove(trim_list,
1152                                                         trim_data);
1153                                         list = g_list_first(trim_list);
1154                                         prev = NULL;
1155                                         continue;
1156                                 } else
1157                                         prev = trim_data;
1158                         } else {
1159                                 prev = trim_data;
1160                         }
1161                 }
1162                 list = g_list_next(list);
1163         }
1164 }
1165
1166 static gint __comparefunc(gconstpointer a, gconstpointer b, gpointer userdata)
1167 {
1168         if (a == NULL || b == NULL)
1169                 return 0;
1170         if (strcmp((char *)a, (char *)b) == 0)
1171                 return 0;
1172         if (strcmp((char *)a, (char *)b) < 0)
1173                 return -1;
1174         if (strcmp((char *)a, (char *)b) > 0)
1175                 return 1;
1176         return 0;
1177 }
1178
1179 /* TODO: refactor inserting localized info */
1180 static GList *__create_locale_list(GList *lbls, GList *lcns, GList *icns,
1181                 GList *dcns, GList *aths)
1182 {
1183         GList *locale = NULL;
1184         GList *tmp;
1185         label_x *lbl;
1186         license_x *lcn;
1187         icon_x *icn;
1188         description_x *dcn;
1189         author_x *ath;
1190
1191         for (tmp = lbls; tmp; tmp = tmp->next) {
1192                 lbl = (label_x *)tmp->data;
1193                 if (lbl == NULL)
1194                         continue;
1195                 if (lbl->lang)
1196                         locale = g_list_insert_sorted_with_data(
1197                                         locale, (gpointer)lbl->lang,
1198                                         __comparefunc, NULL);
1199         }
1200         for (tmp = lcns; tmp; tmp = tmp->next) {
1201                 lcn = (license_x *)tmp->data;
1202                 if (lcn == NULL)
1203                         continue;
1204                 if (lcn->lang)
1205                         locale = g_list_insert_sorted_with_data(
1206                                         locale, (gpointer)lcn->lang,
1207                                         __comparefunc, NULL);
1208         }
1209         for (tmp = icns; tmp; tmp = tmp->next) {
1210                 icn = (icon_x *)tmp->data;
1211                 if (icn == NULL)
1212                         continue;
1213                 if (icn->lang)
1214                         locale = g_list_insert_sorted_with_data(
1215                                         locale, (gpointer)icn->lang,
1216                                         __comparefunc, NULL);
1217         }
1218         for (tmp = dcns; tmp; tmp = tmp->next) {
1219                 dcn = (description_x *)tmp->data;
1220                 if (dcn == NULL)
1221                         continue;
1222                 if (dcn->lang)
1223                         locale = g_list_insert_sorted_with_data(
1224                                         locale, (gpointer)dcn->lang,
1225                                         __comparefunc, NULL);
1226         }
1227         for (tmp = aths; tmp; tmp = tmp->next) {
1228                 ath = (author_x *)tmp->data;
1229                 if (ath == NULL)
1230                         continue;
1231                 if (ath->lang)
1232                         locale = g_list_insert_sorted_with_data(
1233                                         locale, (gpointer)ath->lang,
1234                                         __comparefunc, NULL);
1235         }
1236         __trimfunc(locale);
1237         return locale;
1238 }
1239
1240 static gint __check_icon_resolution(const char *orig_icon_path,
1241                 char **new_icon_path)
1242 {
1243         int ret;
1244         char *dpi_path[2];
1245         char *icon_filename;
1246         char modified_iconpath[BUFSIZE];
1247         char icon_path[BUFSIZE];
1248         int i;
1249         int dpi = -1;
1250
1251         if (orig_icon_path == NULL)
1252                 return -1;
1253
1254         ret = system_info_get_platform_int(
1255                         "http://tizen.org/feature/screen.dpi", &dpi);
1256         if (ret != SYSTEM_INFO_ERROR_NONE)
1257                 return -1;
1258
1259         if (dpi >= LDPI_MIN && dpi <= LDPI_MAX) {
1260                 dpi_path[0] = "LDPI";
1261                 dpi_path[1] = "ldpi";
1262         } else if (dpi >= MDPI_MIN && dpi <= MDPI_MAX) {
1263                 dpi_path[0] = "MDPI";
1264                 dpi_path[1] = "mdpi";
1265         } else if (dpi >= HDPI_MIN && dpi <= HDPI_MAX) {
1266                 dpi_path[0] = "HDPI";
1267                 dpi_path[1] = "hdpi";
1268         } else if (dpi >= XHDPI_MIN && dpi <= XHDPI_MAX) {
1269                 dpi_path[0] = "XHDPI";
1270                 dpi_path[1] = "xhdpi";
1271         } else if (dpi >= XXHDPI_MIN && dpi <= XXHDPI_MAX) {
1272                 dpi_path[0] = "XXHDPI";
1273                 dpi_path[1] = "xxhdpi";
1274         } else {
1275                 _LOGE("Unidentified dpi[%d]", dpi);
1276                 return -1;
1277         }
1278
1279         icon_filename = strrchr(orig_icon_path, '/');
1280         if (icon_filename == NULL)
1281                 return -1;
1282
1283         snprintf(icon_path,
1284                         strlen(orig_icon_path) - (strlen(icon_filename) - 1),
1285                         "%s", orig_icon_path);
1286         for (i = 0; i < 2; i++) {
1287                 ret = snprintf(modified_iconpath, BUFSIZE - 1, "%s/%s%s",
1288                                 icon_path, dpi_path[i], icon_filename);
1289                 if (ret < 0 || ret > BUFSIZE -1) {
1290                         _LOGE("snprintf fail");
1291                         return -1;
1292                 }
1293                 if (access(modified_iconpath, F_OK) != -1) {
1294                         /* if exists, return modified icon path */
1295                         *new_icon_path = strdup(modified_iconpath);
1296                         return 0;
1297                 }
1298         }
1299
1300         return -1;
1301 }
1302
1303 static gint __compare_icon(gconstpointer a, gconstpointer b)
1304 {
1305         icon_x *icon = (icon_x *)a;
1306         char *icon_path;
1307
1308         if (icon->lang != NULL && strcasecmp(icon->lang, DEFAULT_LOCALE) != 0)
1309                 return -1;
1310
1311         if (icon->dpi != NULL)
1312                 return -1;
1313
1314         if (__check_icon_resolution(icon->text, &icon_path) == 0) {
1315                 free(icon->text);
1316                 icon->text = icon_path;
1317         }
1318
1319         return 0;
1320 }
1321
1322 static gint __compare_icon_with_dpi(gconstpointer a, gconstpointer b)
1323 {
1324         icon_x *icon = (icon_x *)a;
1325         int dpi = GPOINTER_TO_INT(b);
1326
1327         if (icon->lang != NULL && strcasecmp(icon->lang, DEFAULT_LOCALE) != 0)
1328                 return -1;
1329
1330         if (icon->dpi == NULL)
1331                 return -1;
1332
1333         if (__check_dpi(icon->dpi, dpi) == 0)
1334                 return 0;
1335
1336         return -1;
1337 }
1338
1339 static gint __compare_icon_with_lang(gconstpointer a, gconstpointer b)
1340 {
1341         icon_x *icon = (icon_x *)a;
1342         char *lang = (char *)b;
1343         char *icon_path;
1344
1345         if (icon->dpi != NULL)
1346                 return -1;
1347
1348         if (strcasecmp(icon->lang, lang) == 0) {
1349                 if (strcasecmp(icon->lang, DEFAULT_LOCALE) == 0) {
1350                         /* icon for no locale. check existance of
1351                          * folder-hierachied default icons
1352                          */
1353                         if (__check_icon_resolution(icon->text,
1354                                                 &icon_path) == 0) {
1355                                 free(icon->text);
1356                                 icon->text = icon_path;
1357                         }
1358                 }
1359                 return 0;
1360         }
1361
1362         return -1;
1363 }
1364
1365 static gint __compare_icon_with_lang_dpi(gconstpointer a, gconstpointer b)
1366 {
1367         int ret;
1368         icon_x *icon = (icon_x *)a;
1369         char *lang = (char *)b;
1370         int dpi = -1;
1371
1372         ret = system_info_get_platform_int(
1373                         "http://tizen.org/feature/screen.dpi", &dpi);
1374         if (ret != SYSTEM_INFO_ERROR_NONE)
1375                 return -1;
1376
1377         if (strcasecmp(icon->lang, lang) == 0 &&
1378                         __check_dpi(icon->dpi, dpi) == 0)
1379                 return 0;
1380
1381         return -1;
1382 }
1383
1384 static char *__find_icon(GList *icons, const char *lang)
1385 {
1386         GList *tmp;
1387         icon_x *icon;
1388         int dpi = 0;
1389         int ret;
1390
1391         /* first, find icon whose locale and dpi with given lang and
1392          * system's dpi has matched
1393          */
1394         tmp = g_list_find_custom(icons, lang,
1395                         (GCompareFunc)__compare_icon_with_lang_dpi);
1396         if (tmp != NULL) {
1397                 icon = (icon_x *)tmp->data;
1398                 return (char *)icon->text;
1399         }
1400
1401         /* if first has failed, find icon whose locale has matched */
1402         tmp = g_list_find_custom(icons, lang,
1403                         (GCompareFunc)__compare_icon_with_lang);
1404         if (tmp != NULL) {
1405                 icon = (icon_x *)tmp->data;
1406                 return (char *)icon->text;
1407         }
1408
1409         /* if second has failed, find icon whose dpi has matched with
1410          * system's dpi
1411          */
1412         ret = system_info_get_platform_int(
1413                         "http://tizen.org/feature/screen.dpi", &dpi);
1414         if (ret == SYSTEM_INFO_ERROR_NONE) {
1415                 tmp = g_list_find_custom(icons, GINT_TO_POINTER(dpi),
1416                                 (GCompareFunc)__compare_icon_with_dpi);
1417                 if (tmp != NULL) {
1418                         icon = (icon_x *)tmp->data;
1419                         return (char *)icon->text;
1420                 }
1421         }
1422
1423         /* last, find default icon marked as "No Locale" */
1424         tmp = g_list_find_custom(icons, NULL, (GCompareFunc)__compare_icon);
1425         if (tmp != NULL) {
1426                 icon = (icon_x *)tmp->data;
1427                 return (char *)icon->text;
1428         }
1429
1430         return NULL;
1431 }
1432
1433 static void __extract_data(const char *locale, GList *lbls, GList *lcns,
1434                 GList *icns, GList *dcns, GList *aths, char **label,
1435                 char **license, char **icon, char **description, char **author)
1436 {
1437         GList *tmp;
1438         label_x *lbl;
1439         license_x *lcn;
1440         description_x *dcn;
1441         author_x *ath;
1442
1443         for (tmp = lbls; tmp; tmp = tmp->next) {
1444                 lbl = (label_x *)tmp->data;
1445                 if (lbl == NULL)
1446                         continue;
1447                 if (lbl->lang) {
1448                         if (strcmp(lbl->lang, locale) == 0) {
1449                                 *label = (char *)lbl->text;
1450                                 break;
1451                         }
1452                 }
1453         }
1454         for (tmp = lcns; tmp; tmp = tmp->next) {
1455                 lcn = (license_x *)tmp->data;
1456                 if (lcn == NULL)
1457                         continue;
1458                 if (lcn->lang) {
1459                         if (strcmp(lcn->lang, locale) == 0) {
1460                                 *license = (char *)lcn->text;
1461                                 break;
1462                         }
1463                 }
1464         }
1465
1466         *icon = __find_icon(icns, locale);
1467
1468         for (tmp = dcns; tmp; tmp = tmp->next) {
1469                 dcn = (description_x *)tmp->data;
1470                 if (dcn == NULL)
1471                         continue;
1472                 if (dcn->lang) {
1473                         if (strcmp(dcn->lang, locale) == 0) {
1474                                 *description = (char *)dcn->text;
1475                                 break;
1476                         }
1477                 }
1478         }
1479         for (tmp = aths; tmp; tmp = tmp->next) {
1480                 ath = (author_x *)tmp->data;
1481                 if (ath == NULL)
1482                         continue;
1483                 if (ath->lang) {
1484                         if (strcmp(ath->lang, locale) == 0) {
1485                                 *author = (char *)ath->text;
1486                                 break;
1487                         }
1488                 }
1489         }
1490 }
1491
1492 static int __insert_mainapp_localized_info(sqlite3 *db, application_x *app,
1493                 const char *locale, const char *label, const char *icon)
1494 {
1495         static const char query[] =
1496                 "INSERT OR REPLACE INTO package_localized_info ("
1497                 "  package, package_locale, package_label, package_icon,"
1498                 "  package_description, package_license, package_author) "
1499                 "VALUES (?, ?,"
1500                 "  COALESCE((SELECT package_label FROM package_localized_info"
1501                 "            WHERE package=? AND package_locale=?), ?),"
1502                 "  COALESCE((SELECT package_icon FROM package_localized_info"
1503                 "            WHERE package=? AND package_icon=?), ?),"
1504                 "  (SELECT package_description FROM package_localized_info"
1505                 "   WHERE package=? AND package_locale=?),"
1506                 "  (SELECT package_description FROM package_localized_info"
1507                 "   WHERE package=? AND package_locale=?),"
1508                 "  (SELECT package_description FROM package_localized_info"
1509                 "   WHERE package=? AND package_locale=?))";
1510         int ret;
1511         sqlite3_stmt *stmt;
1512         int idx = 1;
1513
1514         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
1515         if (ret != SQLITE_OK) {
1516                 _LOGE("prepare failed: %s", sqlite3_errmsg(db));
1517                 return -1;
1518         }
1519
1520         __BIND_TEXT(db, stmt, idx++, app->package);
1521         __BIND_TEXT(db, stmt, idx++, locale);
1522         __BIND_TEXT(db, stmt, idx++, app->package);
1523         __BIND_TEXT(db, stmt, idx++, locale);
1524         __BIND_TEXT(db, stmt, idx++, label);
1525         __BIND_TEXT(db, stmt, idx++, app->package);
1526         __BIND_TEXT(db, stmt, idx++, locale);
1527         __BIND_TEXT(db, stmt, idx++, icon);
1528         __BIND_TEXT(db, stmt, idx++, app->package);
1529         __BIND_TEXT(db, stmt, idx++, locale);
1530         __BIND_TEXT(db, stmt, idx++, app->package);
1531         __BIND_TEXT(db, stmt, idx++, locale);
1532         __BIND_TEXT(db, stmt, idx++, app->package);
1533         __BIND_TEXT(db, stmt, idx++, locale);
1534
1535         ret = sqlite3_step(stmt);
1536         if (ret != SQLITE_DONE) {
1537                 _LOGE("step failed: %s", sqlite3_errmsg(db));
1538                 sqlite3_finalize(stmt);
1539                 return -1;
1540         }
1541
1542         sqlite3_finalize(stmt);
1543
1544         return 0;
1545 }
1546
1547 static int __insert_app_localized_info(sqlite3 *db, application_x *app)
1548 {
1549         static const char query[] =
1550                 "INSERT INTO package_app_localized_info (app_id, app_locale,"
1551                 "  app_label, app_icon) "
1552                 "VALUES (?, ?, ?, ?)";
1553         int ret;
1554         sqlite3_stmt *stmt;
1555         int idx;
1556         GList *tmp;
1557         GList *locales;
1558         const char *locale;
1559         char *label;
1560         char *icon;
1561
1562         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
1563         if (ret != SQLITE_OK) {
1564                 _LOGE("prepare failed: %s", sqlite3_errmsg(db));
1565                 return -1;
1566         }
1567
1568         locales = __create_locale_list(app->label, NULL, app->icon, NULL, NULL);
1569         for (tmp = locales; tmp; tmp = tmp->next) {
1570                 locale = (const char *)tmp->data;
1571                 label = NULL;
1572                 icon = NULL;
1573                 __extract_data(locale, app->label, NULL, app->icon, NULL, NULL,
1574                                 &label, NULL, &icon, NULL, NULL);
1575                 if (!label && !icon)
1576                         continue;
1577
1578                 idx = 1;
1579                 __BIND_TEXT(db, stmt, idx++, app->appid);
1580                 __BIND_TEXT(db, stmt, idx++, locale);
1581                 __BIND_TEXT(db, stmt, idx++, label);
1582                 __BIND_TEXT(db, stmt, idx++, icon);
1583
1584                 ret = sqlite3_step(stmt);
1585                 if (ret != SQLITE_DONE) {
1586                         _LOGE("step failed: %s", sqlite3_errmsg(db));
1587                         g_list_free(locales);
1588                         sqlite3_finalize(stmt);
1589                         return -1;
1590                 }
1591
1592                 sqlite3_reset(stmt);
1593
1594                 if (strcasecmp(app->mainapp, "true") == 0) {
1595                         if (__insert_mainapp_localized_info(db, app, locale,
1596                                                 label, icon))
1597                                 _LOGE("insert mainapp localized info failed");
1598                 }
1599         }
1600
1601         g_list_free(locales);
1602         sqlite3_finalize(stmt);
1603
1604         return 0;
1605 }
1606
1607 static int __insert_package_privilege_info(sqlite3 *db, manifest_x *mfx)
1608 {
1609         static const char query[] =
1610                 "INSERT INTO package_privilege_info (package, privilege, type) "
1611                 "VALUES (?, ?, ?)";
1612         int ret;
1613         sqlite3_stmt *stmt;
1614         int idx;
1615         GList *tmp;
1616         privilege_x *priv;
1617
1618         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
1619         if (ret != SQLITE_OK) {
1620                 _LOGE("prepare failed: %s", sqlite3_errmsg(db));
1621                 return -1;
1622         }
1623
1624         for (tmp = mfx->privileges; tmp; tmp = tmp->next) {
1625                 priv = (privilege_x *)tmp->data;
1626                 if (priv == NULL)
1627                         continue;
1628
1629                 idx = 1;
1630                 __BIND_TEXT(db, stmt, idx++, mfx->package);
1631                 __BIND_TEXT(db, stmt, idx++, priv->value);
1632                 __BIND_TEXT(db, stmt, idx++, priv->type);
1633
1634                 ret = sqlite3_step(stmt);
1635                 if (ret != SQLITE_DONE) {
1636                         _LOGE("step failed: %s", sqlite3_errmsg(db));
1637                         sqlite3_finalize(stmt);
1638                         return -1;
1639                 }
1640                 sqlite3_reset(stmt);
1641         }
1642
1643         sqlite3_finalize(stmt);
1644
1645         return 0;
1646 }
1647
1648 static int __insert_package_plugin_execution_info(
1649                 manifest_x *mfx, uid_t uid)
1650 {
1651         char *query = NULL;
1652         GList *tmp;
1653         plugin_x *plugin;
1654
1655         if (!mfx->plugin)
1656                 return PM_PARSER_R_OK;
1657
1658         for (tmp = mfx->plugin; tmp; tmp = tmp->next) {
1659                 plugin = (plugin_x *)tmp->data;
1660                 if (plugin == NULL)
1661                         continue;
1662
1663                 query = sqlite3_mprintf("INSERT INTO package_plugin_info "
1664                                 "(pkgid, appid, plugin_type, plugin_name) "
1665                                 "VALUES (%Q, %Q, %Q, %Q)",
1666                                 plugin->pkgid, plugin->appid,
1667                                 plugin->plugin_type, plugin->plugin_name);
1668                 if (query == NULL) {
1669                         _LOGE("Out of memory");
1670                         return PM_PARSER_R_ERROR;
1671                 }
1672
1673                 // TODO: send query to server
1674                 sqlite3_free(query);
1675                 query = NULL;
1676         }
1677         return PM_PARSER_R_OK;
1678 }
1679
1680 static int __delete_package_plugin_execution_info(const char *pkgid, uid_t uid)
1681 {
1682         char *query = NULL;
1683
1684         query = sqlite3_mprintf(
1685                         "DELETE FROM package_plugin_info WHERE pkgid=%Q", pkgid);
1686         if (query == NULL) {
1687                 _LOGE("Out of memory");
1688                 return PM_PARSER_R_ERROR;
1689         }
1690
1691         // TODO: send query to server
1692         sqlite3_free(query);
1693
1694         return PM_PARSER_R_OK;
1695 }
1696
1697 static int __insert_package_appdefined_privilege_info(sqlite3 *db,
1698                 manifest_x *mfx)
1699 {
1700         static const char query[] =
1701                 "INSERT INTO package_appdefined_privilege_info "
1702                 "(package, privilege, license, type) "
1703                 "VALUES (?, ?, ?, ?)";
1704         int ret;
1705         sqlite3_stmt *stmt;
1706         int idx;
1707         GList *tmp;
1708         appdefined_privilege_x *priv;
1709
1710         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
1711         if (ret != SQLITE_OK) {
1712                 _LOGE("prepare failed: %s", sqlite3_errmsg(db));
1713                 return -1;
1714         }
1715
1716         for (tmp = mfx->appdefined_privileges; tmp; tmp = tmp->next) {
1717                 priv = (appdefined_privilege_x *)tmp->data;
1718                 if (priv == NULL)
1719                         continue;
1720
1721                 idx = 1;
1722                 __BIND_TEXT(db, stmt, idx++, mfx->package);
1723                 __BIND_TEXT(db, stmt, idx++, priv->value);
1724                 __BIND_TEXT(db, stmt, idx++, priv->license);
1725                 __BIND_TEXT(db, stmt, idx++, priv->type);
1726
1727                 ret = sqlite3_step(stmt);
1728                 if (ret != SQLITE_DONE) {
1729                         _LOGE("step failed: %s", sqlite3_errmsg(db));
1730                         sqlite3_finalize(stmt);
1731                         return -1;
1732                 }
1733                 sqlite3_reset(stmt);
1734         }
1735
1736         sqlite3_finalize(stmt);
1737
1738         return 0;
1739 }
1740
1741 static int __insert_package_dependency_info(sqlite3 *db, manifest_x *mfx)
1742 {
1743         static const char query[] =
1744                 "INSERT INTO package_dependency_info"
1745                 "  (package, depends_on, type, required_version) "
1746                 "VALUES (?, ?, ?, ?)";
1747         int ret;
1748         sqlite3_stmt *stmt;
1749         int idx;
1750         GList *tmp;
1751         dependency_x *dep;
1752
1753         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
1754         if (ret != SQLITE_OK) {
1755                 _LOGE("prepare failed: %s", sqlite3_errmsg(db));
1756                 return -1;
1757         }
1758
1759         for (tmp = mfx->dependencies; tmp; tmp = tmp->next) {
1760                 dep = (dependency_x *)tmp->data;
1761                 if (dep == NULL)
1762                         continue;
1763
1764                 idx = 1;
1765                 __BIND_TEXT(db, stmt, idx++, mfx->package);
1766                 __BIND_TEXT(db, stmt, idx++, dep->depends_on);
1767                 __BIND_TEXT(db, stmt, idx++, dep->type);
1768                 __BIND_TEXT(db, stmt, idx++, dep->required_version);
1769
1770                 ret = sqlite3_step(stmt);
1771                 if (ret != SQLITE_DONE) {
1772                         _LOGE("step failed: %s", sqlite3_errmsg(db));
1773                         sqlite3_finalize(stmt);
1774                         return -1;
1775                 }
1776                 sqlite3_reset(stmt);
1777         }
1778
1779         sqlite3_finalize(stmt);
1780
1781         return 0;
1782 }
1783
1784 /* _PRODUCT_LAUNCHING_ENHANCED_
1785  *  app->indicatordisplay, app->portraitimg, app->landscapeimg,
1786  *  app->guestmode_appstatus
1787  */
1788 static int __insert_application_info(sqlite3 *db, manifest_x *mfx)
1789 {
1790         static const char query[] =
1791                 "INSERT INTO package_app_info (app_id, app_component,"
1792                 "  app_exec, app_nodisplay, app_type, app_onboot, app_multiple,"
1793                 "  app_autorestart, app_taskmanage, app_hwacceleration,"
1794                 "  app_screenreader, app_mainapp, app_recentimage,"
1795                 "  app_launchcondition, app_indicatordisplay, app_portraitimg,"
1796                 "  app_landscapeimg, app_guestmodevisibility,"
1797                 "  app_permissiontype, app_preload, app_submode,"
1798                 "  app_submode_mainid, app_installed_storage, app_process_pool,"
1799                 "  app_launch_mode, app_ui_gadget, app_support_mode,"
1800                 "  app_support_disable, component_type, package, app_tep_name,"
1801                 "  app_zip_mount_file, app_background_category,"
1802                 "  app_package_type, app_root_path, app_api_version,"
1803                 "  app_effective_appid, app_splash_screen_display,"
1804                 "  app_package_system, app_removable,"
1805                 "  app_package_installed_time, app_support_ambient,"
1806                 "  app_external_path, app_setup_appid) "
1807                 "VALUES (?, ?, "
1808                 "  ?, LOWER(?), ?, LOWER(?), LOWER(?),"
1809                 "  LOWER(?), LOWER(?), ?,"
1810                 "  ?, LOWER(?), ?,"
1811                 "  ?, LOWER(?), ?,"
1812                 "  ?, LOWER(?),"
1813                 "  ?, LOWER(?), LOWER(?),"
1814                 "  ?, ?, LOWER(?),"
1815                 "  COALESCE(?, 'single'), LOWER(?), ?,"
1816                 "  LOWER(?), ?, ?, ?,"
1817                 "  ?, ?,"
1818                 "  ?, ?, ?,"
1819                 "  ?, LOWER(?),"
1820                 "  LOWER(?), LOWER(?),"
1821                 "  ?, LOWER(?),"
1822                 "  ?, ?)";
1823         int ret;
1824         sqlite3_stmt *stmt;
1825         int idx;
1826         GList *tmp;
1827         application_x *app;
1828         int bg_category;
1829         const char *effective_appid;
1830         GList *ss_list;
1831
1832         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
1833         if (ret != SQLITE_OK) {
1834                 _LOGE("prepare failed: %s", sqlite3_errmsg(db));
1835                 return -1;
1836         }
1837
1838         for (tmp = mfx->application; tmp; tmp = tmp->next) {
1839                 app = (application_x *)tmp->data;
1840                 if (app == NULL)
1841                         continue;
1842
1843                 bg_category = __convert_background_category(
1844                                 app->background_category);
1845                 effective_appid = __find_effective_appid(app->metadata);
1846
1847                 idx = 1;
1848                 __BIND_TEXT(db, stmt, idx++, app->appid);
1849                 __BIND_TEXT(db, stmt, idx++, app->component_type);
1850                 __BIND_TEXT(db, stmt, idx++, app->exec);
1851                 __BIND_TEXT(db, stmt, idx++, __get_bool(app->nodisplay, false));
1852                 __BIND_TEXT(db, stmt, idx++, app->type);
1853                 __BIND_TEXT(db, stmt, idx++, __get_bool(app->onboot, false));
1854                 __BIND_TEXT(db, stmt, idx++, __get_bool(app->multiple, false));
1855                 __BIND_TEXT(db, stmt, idx++,
1856                                 __get_bool(app->autorestart, false));
1857                 __BIND_TEXT(db, stmt, idx++,
1858                                 __get_bool(app->taskmanage, false));
1859                 __BIND_TEXT(db, stmt, idx++, app->hwacceleration);
1860                 __BIND_TEXT(db, stmt, idx++, app->screenreader);
1861                 __BIND_TEXT(db, stmt, idx++, __get_bool(app->mainapp, false));
1862                 __BIND_TEXT(db, stmt, idx++, app->recentimage);
1863                 __BIND_TEXT(db, stmt, idx++, app->launchcondition);
1864                 __BIND_TEXT(db, stmt, idx++,
1865                                 __get_bool(app->indicatordisplay, true));
1866                 __BIND_TEXT(db, stmt, idx++, app->portraitimg);
1867                 __BIND_TEXT(db, stmt, idx++, app->landscapeimg);
1868                 __BIND_TEXT(db, stmt, idx++,
1869                                 __get_bool(app->guestmode_visibility, true));
1870                 __BIND_TEXT(db, stmt, idx++, app->permission_type);
1871                 __BIND_TEXT(db, stmt, idx++, __get_bool(mfx->preload, false));
1872                 __BIND_TEXT(db, stmt, idx++, __get_bool(app->submode, false));
1873                 __BIND_TEXT(db, stmt, idx++, app->submode_mainid);
1874                 __BIND_TEXT(db, stmt, idx++, mfx->installed_storage);
1875                 __BIND_TEXT(db, stmt, idx++,
1876                                 __get_bool(app->process_pool, false));
1877                 __BIND_TEXT(db, stmt, idx++, app->launch_mode);
1878                 __BIND_TEXT(db, stmt, idx++, __get_bool(app->ui_gadget, false));
1879                 __BIND_TEXT(db, stmt, idx++,
1880                                 app->support_mode ? app->support_mode : "0");
1881                 __BIND_TEXT(db, stmt, idx++,
1882                                 __get_bool(mfx->support_disable, false));
1883                 __BIND_TEXT(db, stmt, idx++, app->component_type);
1884                 __BIND_TEXT(db, stmt, idx++, mfx->package);
1885                 __BIND_TEXT(db, stmt, idx++, mfx->tep_name);
1886                 __BIND_TEXT(db, stmt, idx++, mfx->zip_mount_file);
1887                 __BIND_INT(db, stmt, idx++, bg_category);
1888                 __BIND_TEXT(db, stmt, idx++, mfx->type ? mfx->type : "tpk");
1889                 __BIND_TEXT(db, stmt, idx++, mfx->root_path);
1890                 __BIND_TEXT(db, stmt, idx++, app->api_version);
1891                 __BIND_TEXT(db, stmt, idx++, effective_appid);
1892                 __BIND_TEXT(db, stmt, idx++,
1893                                 __get_bool(app->splash_screen_display, true));
1894                 __BIND_TEXT(db, stmt, idx++, __get_bool(mfx->system, false));
1895                 __BIND_TEXT(db, stmt, idx++, __get_bool(mfx->removable, false));
1896                 __BIND_TEXT(db, stmt, idx++, mfx->installed_time);
1897                 __BIND_TEXT(db, stmt, idx++,
1898                                 __get_bool(app->support_ambient, false));
1899                 __BIND_TEXT(db, stmt, idx++, mfx->external_path);
1900                 __BIND_TEXT(db, stmt, idx++, app->setup_appid);
1901
1902                 ret = sqlite3_step(stmt);
1903                 if (ret != SQLITE_DONE) {
1904                         _LOGE("step failed: %s", sqlite3_errmsg(db));
1905                         sqlite3_finalize(stmt);
1906                         return -1;
1907                 }
1908
1909                 sqlite3_reset(stmt);
1910
1911                 if (__insert_appcontrol_info(db, app)) {
1912                         sqlite3_finalize(stmt);
1913                         return -1;
1914                 }
1915                 if (__insert_category_info(db, app)) {
1916                         sqlite3_finalize(stmt);
1917                         return -1;
1918                 }
1919                 if (__insert_metadata_info(db, app)) {
1920                         sqlite3_finalize(stmt);
1921                         return -1;
1922                 }
1923                 if (__insert_datacontrol_info(db, app)) {
1924                         sqlite3_finalize(stmt);
1925                         return -1;
1926                 }
1927                 ss_list = __find_splashscreens(app->splashscreens);
1928                 if (__insert_splashscreen_info(db, app, ss_list)) {
1929                         g_list_free(ss_list);
1930                         sqlite3_finalize(stmt);
1931                         return -1;
1932                 }
1933                 g_list_free(ss_list);
1934                 if (__insert_app_localized_info(db, app)) {
1935                         sqlite3_finalize(stmt);
1936                         return -1;
1937                 }
1938         }
1939
1940         sqlite3_finalize(stmt);
1941
1942         return 0;
1943 }
1944
1945 static int __insert_package_update_info(sqlite3 *db, manifest_x *mfx)
1946 {
1947         static const char query[] =
1948                 "INSERT INTO package_update_info (package, update_version) "
1949                 "VALUES (?, ?)";
1950         int ret;
1951         int idx;
1952         sqlite3_stmt *stmt;
1953
1954         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
1955         if (ret != SQLITE_OK) {
1956                 _LOGE("prepare failed: %s", sqlite3_errmsg(db));
1957                 return -1;
1958         }
1959
1960         idx = 1;
1961         __BIND_TEXT(db, stmt, idx++, mfx->package);
1962         __BIND_TEXT(db, stmt, idx, mfx->version);
1963         ret = sqlite3_step(stmt);
1964         if (ret != SQLITE_DONE) {
1965                 _LOGE("step failed: %s", sqlite3_errmsg(db));
1966                 sqlite3_finalize(stmt);
1967                 return -1;
1968         }
1969         sqlite3_finalize(stmt);
1970
1971         return 0;
1972 }
1973
1974 static int __insert_package_localized_info(sqlite3 *db, manifest_x *mfx)
1975 {
1976         static const char query[] =
1977                 "INSERT INTO package_localized_info (package, package_locale,"
1978                 "  package_label, package_icon, package_description,"
1979                 "  package_license, package_author) "
1980                 "VALUES (?, ?, ?, ?, ?, ?, ?)";
1981         int ret;
1982         sqlite3_stmt *stmt;
1983         int idx;
1984         GList *tmp;
1985         GList *locales;
1986         const char *locale;
1987         char *label;
1988         char *icon;
1989         char *description;
1990         char *license;
1991         char *author;
1992
1993         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
1994         if (ret != SQLITE_OK) {
1995                 _LOGE("prepare failed: %s", sqlite3_errmsg(db));
1996                 return -1;
1997         }
1998
1999         locales = __create_locale_list(mfx->label, mfx->license, mfx->icon,
2000                         mfx->description, mfx->author);
2001         for (tmp = locales; tmp; tmp = tmp->next) {
2002                 locale = (const char *)tmp->data;
2003                 label = NULL;
2004                 icon = NULL;
2005                 description = NULL;
2006                 license = NULL;
2007                 author = NULL;
2008                 __extract_data(locale, mfx->label, mfx->license, mfx->icon,
2009                                 mfx->description, mfx->author,
2010                                 &label, &license, &icon, &description, &author);
2011                 if (!label && !license && !icon && !description && !author)
2012                         continue;
2013
2014                 idx = 1;
2015                 __BIND_TEXT(db, stmt, idx++, mfx->package);
2016                 __BIND_TEXT(db, stmt, idx++, locale);
2017                 __BIND_TEXT(db, stmt, idx++, label);
2018                 __BIND_TEXT(db, stmt, idx++, icon);
2019                 __BIND_TEXT(db, stmt, idx++, description);
2020                 __BIND_TEXT(db, stmt, idx++, license);
2021                 __BIND_TEXT(db, stmt, idx++, author);
2022
2023                 ret = sqlite3_step(stmt);
2024                 if (ret != SQLITE_DONE) {
2025                         _LOGE("step failed: %s", sqlite3_errmsg(db));
2026                         g_list_free(locales);
2027                         sqlite3_finalize(stmt);
2028                         return -1;
2029                 }
2030
2031                 sqlite3_reset(stmt);
2032         }
2033
2034         g_list_free(locales);
2035         sqlite3_finalize(stmt);
2036
2037         return 0;
2038 }
2039
2040 static int __insert_package_info(sqlite3 *db, manifest_x *mfx)
2041 {
2042         static const char query[] =
2043                 "INSERT INTO package_info (package, package_type,"
2044                 "  package_version, package_api_version, package_tep_name,"
2045                 "  package_zip_mount_file, install_location, package_size,"
2046                 "  package_removable, package_preload, package_readonly,"
2047                 "  package_update, package_appsetting, package_nodisplay,"
2048                 "  package_system, author_name, author_email, author_href,"
2049                 "  installed_time, installed_storage, storeclient_id,"
2050                 "  mainapp_id, package_url, root_path, external_path,"
2051                 "  csc_path, package_support_mode, package_support_disable) "
2052                 "VALUES (?, ?,"
2053                 "  ?, ?, ?,"
2054                 "  ?, ?, ?,"
2055                 "  LOWER(?), LOWER(?), LOWER(?),"
2056                 "  LOWER(?), LOWER(?), LOWER(?),"
2057                 "  LOWER(?), ?, ?, ?,"
2058                 "  ?, ?, ?,"
2059                 "  ?, ?, ?, ?,"
2060                 "  ?, ?, LOWER(?))";
2061         int ret;
2062         sqlite3_stmt *stmt;
2063         int idx = 1;
2064         const char *author_name = NULL;
2065         const char *author_email = NULL;
2066         const char *author_href = NULL;
2067
2068         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
2069         if (ret != SQLITE_OK) {
2070                 _LOGE("prepare failed: %s", sqlite3_errmsg(db));
2071                 return -1;
2072         }
2073
2074         if (mfx->author && mfx->author->data) {
2075                 author_name = ((author_x *)mfx->author->data)->text;
2076                 author_email = ((author_x *)mfx->author->data)->email;
2077                 author_href = ((author_x *)mfx->author->data)->href;
2078         }
2079
2080         __BIND_TEXT(db, stmt, idx++, mfx->package);
2081         __BIND_TEXT(db, stmt, idx++, mfx->type);
2082         __BIND_TEXT(db, stmt, idx++, mfx->version);
2083         __BIND_TEXT(db, stmt, idx++, mfx->api_version);
2084         __BIND_TEXT(db, stmt, idx++, mfx->tep_name);
2085         __BIND_TEXT(db, stmt, idx++, mfx->zip_mount_file);
2086         __BIND_TEXT(db, stmt, idx++, mfx->installlocation);
2087         __BIND_TEXT(db, stmt, idx++, mfx->package_size);
2088         __BIND_TEXT(db, stmt, idx++, __get_bool(mfx->removable, true));
2089         __BIND_TEXT(db, stmt, idx++, __get_bool(mfx->preload, false));
2090         __BIND_TEXT(db, stmt, idx++, __get_bool(mfx->readonly, false));
2091         __BIND_TEXT(db, stmt, idx++, __get_bool(mfx->update, false));
2092         __BIND_TEXT(db, stmt, idx++, __get_bool(mfx->appsetting, false));
2093         __BIND_TEXT(db, stmt, idx++, __get_bool(mfx->nodisplay_setting, false));
2094         __BIND_TEXT(db, stmt, idx++, __get_bool(mfx->system, false));
2095         __BIND_TEXT(db, stmt, idx++, author_name);
2096         __BIND_TEXT(db, stmt, idx++, author_email);
2097         __BIND_TEXT(db, stmt, idx++, author_href);
2098         __BIND_TEXT(db, stmt, idx++, mfx->installed_time);
2099         __BIND_TEXT(db, stmt, idx++, mfx->installed_storage);
2100         __BIND_TEXT(db, stmt, idx++, mfx->storeclient_id);
2101         __BIND_TEXT(db, stmt, idx++, mfx->mainapp_id);
2102         __BIND_TEXT(db, stmt, idx++, mfx->package_url);
2103         __BIND_TEXT(db, stmt, idx++, mfx->root_path);
2104         __BIND_TEXT(db, stmt, idx++, mfx->external_path);
2105         __BIND_TEXT(db, stmt, idx++, mfx->csc_path);
2106         __BIND_TEXT(db, stmt, idx++,
2107                         mfx->support_mode ? mfx->support_mode : "0");
2108         __BIND_TEXT(db, stmt, idx++, __get_bool(mfx->support_disable, false));
2109
2110         ret = sqlite3_step(stmt);
2111         if (ret != SQLITE_DONE) {
2112                 _LOGE("step failed: %s", sqlite3_errmsg(db));
2113                 sqlite3_finalize(stmt);
2114                 return -1;
2115         }
2116
2117         sqlite3_finalize(stmt);
2118
2119         if (__insert_package_update_info(db, mfx))
2120                 return -1;
2121         if (__insert_package_localized_info(db, mfx))
2122                 return -1;
2123         if (__insert_application_info(db, mfx))
2124                 return -1;
2125         if (__insert_package_privilege_info(db, mfx))
2126                 return -1;
2127         if (__insert_package_appdefined_privilege_info(db, mfx))
2128                 return -1;
2129         if (__insert_package_dependency_info(db, mfx))
2130                 return -1;
2131
2132         return 0;
2133 }
2134
2135 static int __open_db(uid_t uid, const char *path, sqlite3 **db, int flags)
2136 {
2137         int ret;
2138
2139         ret = sqlite3_open_v2(path, db, flags, NULL);
2140         if (ret != SQLITE_OK) {
2141                 sqlite3_close_v2(*db);
2142                 return ret;
2143         }
2144
2145         ret = sqlite3_busy_handler(*db, __db_busy_handler, (void *)path);
2146         if (ret != SQLITE_OK) {
2147                 _LOGE("failed to register busy handler: %s",
2148                                 sqlite3_errmsg(*db));
2149                 sqlite3_close_v2(*db);
2150                 return ret;
2151         }
2152
2153         ret = sqlite3_exec(*db, "PRAGMA foreign_keys=ON", NULL, NULL, NULL);
2154         if (ret != SQLITE_OK) {
2155                 _LOGE("failed to enable foreign key support: %s",
2156                                 sqlite3_errmsg(*db));
2157                 sqlite3_close_v2(*db);
2158                 return ret;
2159         }
2160
2161         return ret;
2162 }
2163
2164 static int __delete_package_info(sqlite3 *db, const char *pkgid)
2165 {
2166         static const char query[] =
2167                 "DELETE FROM package_info WHERE package=?";
2168         int ret;
2169         sqlite3_stmt *stmt;
2170
2171         ret = sqlite3_prepare_v2(db, query, strlen(query), &stmt, NULL);
2172         if (ret != SQLITE_OK) {
2173                 _LOGE("prepare failed: %s", sqlite3_errmsg(db));
2174                 return -1;
2175         }
2176
2177         __BIND_TEXT(db, stmt, 1, pkgid);
2178
2179         ret = sqlite3_step(stmt);
2180         if (ret != SQLITE_DONE) {
2181                 _LOGE("step failed: %s", sqlite3_errmsg(db));
2182                 sqlite3_finalize(stmt);
2183                 return -1;
2184         }
2185
2186         sqlite3_finalize(stmt);
2187
2188         return 0;
2189 }
2190
2191 API int pkgmgr_parser_insert_pkg_info(manifest_x *mfx, uid_t uid)
2192 {
2193         int ret;
2194         const char *dbpath;
2195         sqlite3 *db;
2196
2197         if (mfx == NULL) {
2198                 _LOGE("invalid parameter");
2199                 return PM_PARSER_R_EINVAL;
2200         }
2201
2202         dbpath = __get_parser_db_path(uid);
2203
2204         ret = __open_db(uid, dbpath, &db, SQLITE_OPEN_READWRITE);
2205         if (ret != SQLITE_OK) {
2206                 _LOGE("open db failed: %d", ret);
2207                 return PM_PARSER_R_ERROR;
2208         }
2209
2210         __BEGIN_TRANSACTION(db);
2211         __DO_TRANSACTION(db, __delete_package_info(db, mfx->package));
2212         __DO_TRANSACTION(db, __insert_package_info(db, mfx));
2213         __END_TRANSACTION(db);
2214
2215         sqlite3_close_v2(db);
2216
2217         return PM_PARSER_R_OK;
2218 }
2219
2220 API int pkgmgr_parser_insert_manifest_info_in_usr_db(manifest_x *mfx, uid_t uid)
2221 {
2222         // TODO: use pkginfo-client APIs to send manifest_x to server
2223         return 0;
2224 }
2225
2226 API int pkgmgr_parser_insert_manifest_info_in_db(manifest_x *mfx)
2227 {
2228         return pkgmgr_parser_insert_manifest_info_in_usr_db(mfx, __getuid());
2229 }
2230
2231 API int pkgmgr_parser_delete_pkg_info(const char *package, uid_t uid)
2232 {
2233         int ret;
2234         const char *dbpath;
2235         sqlite3 *db;
2236
2237         if (package == NULL) {
2238                 _LOGE("invalid parameter");
2239                 return PM_PARSER_R_EINVAL;
2240         }
2241
2242         dbpath = __get_parser_db_path(uid);
2243
2244         ret = __open_db(uid, dbpath, &db, SQLITE_OPEN_READWRITE);
2245         if (ret != SQLITE_OK) {
2246                 _LOGE("open db failed: %d", ret);
2247                 return PM_PARSER_R_ERROR;
2248         }
2249
2250         __BEGIN_TRANSACTION(db);
2251         __DO_TRANSACTION(db, __delete_package_info(db, package));
2252         __END_TRANSACTION(db);
2253
2254         return PM_PARSER_R_OK;
2255 }
2256
2257 API int pkgmgr_parser_delete_manifest_info_from_usr_db(manifest_x *mfx,
2258         uid_t uid)
2259 {
2260         // TODO: use pkginfo-client APIs to send package id to server
2261         return 0;
2262 }
2263
2264 API int pkgmgr_parser_delete_manifest_info_from_db(manifest_x *mfx)
2265 {
2266         return pkgmgr_parser_delete_manifest_info_from_usr_db(mfx, __getuid());
2267 }
2268
2269 API int pkgmgr_parser_update_manifest_info_in_usr_db(manifest_x *mfx, uid_t uid)
2270 {
2271         return pkgmgr_parser_insert_manifest_info_in_usr_db(mfx, uid);
2272 }
2273
2274 API int pkgmgr_parser_update_manifest_info_in_db(manifest_x *mfx)
2275 {
2276         return pkgmgr_parser_update_manifest_info_in_usr_db(mfx, __getuid());
2277 }
2278
2279 API int pkgmgr_parser_update_global_app_disable_for_uid_info_in_db(
2280                 const char *appid, uid_t uid, int is_disable)
2281 {
2282         // TODO: construct query at here and send it to server
2283         char *query = NULL;
2284
2285         query = sqlite3_mprintf("INSERT OR REPLACE INTO package_app_info_for_uid ("
2286                         "  app_id, uid, is_disabled, is_splash_screen_enabled) "
2287                         "VALUES (%Q, %Q, %Q,"
2288                         "  (SELECT app_splash_screen_display FROM package_app_info"
2289                         "   WHERE app_id=%Q))", appid, uid,
2290                         (is_disable ? "true" : "false"), appid);
2291         if (query == NULL) {
2292                 _LOGE("Out of memory");
2293                 return PM_PARSER_R_ERROR;
2294         }
2295
2296         // TODO: send query to server
2297         sqlite3_free(query);
2298
2299         return PM_PARSER_R_OK;
2300 }
2301
2302 API int pkgmgr_parser_update_app_disable_info_in_usr_db(const char *appid,
2303                 uid_t uid, int is_disable)
2304 {
2305         char *query = NULL;
2306
2307         query = sqlite3_mprintf("UPDATE package_app_info SET app_disable=%Q "
2308                 "WHERE app_id=%Q", (is_disable ? "true" : "false"), appid);
2309         if (query == NULL) {
2310                 _LOGE("Out of memory");
2311                 return PM_PARSER_R_ERROR;
2312         }
2313
2314         // TODO: construct query and send it to server
2315         sqlite3_free(query);
2316
2317         return PM_PARSER_R_OK;
2318 }
2319
2320 API int pkgmgr_parser_update_app_disable_info_in_db(const char *appid,
2321                 int is_disable)
2322 {
2323         return pkgmgr_parser_update_app_disable_info_in_usr_db(appid,
2324                         __getuid(), is_disable);
2325 }
2326
2327 API int pkgmgr_parser_update_pkg_disable_info_in_usr_db(const char *pkgid,
2328                 uid_t uid, int is_disable)
2329 {
2330         char *query = NULL;
2331
2332         query = sqlite3_mprintf("UPDATE package_info SET package_disable=%Q "
2333                         "WHERE package=%Q", (is_disable ? "true" : "false"), pkgid);
2334         if (query == NULL) {
2335                 _LOGE("Out of memory");
2336                 return PM_PARSER_R_ERROR;
2337         }
2338
2339         // TODO: construct query and send it to server
2340         sqlite3_free(query);
2341
2342         return PM_PARSER_R_OK;
2343 }
2344
2345 API int pkgmgr_parser_update_pkg_disable_info_in_db(const char *pkgid,
2346                 int is_disable)
2347 {
2348         return pkgmgr_parser_update_pkg_disable_info_in_usr_db(pkgid,
2349                         __getuid(), is_disable);
2350 }
2351
2352 API int pkgmgr_parser_update_global_app_splash_screen_display_info_in_usr_db(
2353                 const char *appid, uid_t uid, int flag)
2354 {
2355         char *query = NULL;
2356
2357         query = sqlite3_mprintf("INSERT OR REPLACE INTO package_app_info_for_uid("
2358                 "  appid, uid, is_splash_screen_enabled) "
2359                 "VALUES (%Q, %Q, Q%)", appid, uid, (flag == 1 ? "true" : "false"));
2360         if (query == NULL) {
2361                 _LOGE("Out of memory");
2362                 return PM_PARSER_R_ERROR;
2363         }
2364
2365         // TODO: construct query and send it to server
2366         sqlite3_free(query);
2367
2368         return PM_PARSER_R_OK;
2369 }
2370
2371 API int pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
2372                 const char *appid, uid_t uid, int flag)
2373 {
2374         char *query = NULL;
2375
2376         query = sqlite3_mprintf("UPDATE package_app_info SET app_splash_screen_display=%Q "
2377                 "WHERE app_id=%Q", (flag == 1 ? "true" : "false"), appid);
2378         if (query == NULL) {
2379                 _LOGE("Out of memory");
2380                 return PM_PARSER_R_ERROR;
2381         }
2382
2383         // TODO: construct query and send it to server
2384         sqlite3_free(query);
2385
2386         return PM_PARSER_R_OK;
2387 }
2388
2389 API int pkgmgr_parser_update_app_splash_screen_display_info_in_db(
2390                 const char *appid, int flag)
2391 {
2392         return pkgmgr_parser_update_app_splash_screen_display_info_in_usr_db(
2393                         appid, __getuid(), flag);
2394 }
2395
2396 API int pkgmgr_parser_update_app_label_info_in_usr_db(const char *appid,
2397                 uid_t uid, const char *label)
2398 {
2399         char *query = NULL;
2400
2401         query = sqlite3_mprintf("UPDATE package_app_localized_info SET app_label=%Q "
2402                 "WHERE app_id=%Q AND app_label IS NOT NULL", label, appid);
2403         if (query == NULL) {
2404                 _LOGE("Out of memory");
2405                 return PM_PARSER_R_ERROR;
2406         }
2407
2408         // TODO: construct query and send it to server
2409         sqlite3_free(query);
2410
2411         return PM_PARSER_R_OK;
2412 }
2413
2414 API int pkgmgr_parser_update_app_label_info_in_db(const char *appid,
2415                 const char *label)
2416 {
2417         return pkgmgr_parser_update_app_label_info_in_usr_db(appid, __getuid(),
2418                         label);
2419 }
2420
2421 API int pkgmgr_parser_update_app_icon_info_in_usr_db(const char *appid,
2422                 uid_t uid, const char *icon_path)
2423 {
2424         char *query = NULL;
2425
2426         query = sqlite3_mprintf("UPDATE package_app_localized_info SET app_icon=%Q "
2427                 "WHERE app_id=TQ AND app_icon IS NOT NULL", icon_path, appid);
2428         if (query == NULL) {
2429                 _LOGE("Out of memory");
2430                 return PM_PARSER_R_ERROR;
2431         }
2432
2433         // TODO: construct query and send it to server
2434         sqlite3_free(query);
2435
2436         return PM_PARSER_R_OK;
2437 }
2438
2439 API int pkgmgr_parser_update_app_icon_info_in_db(const char *appid,
2440                 const char *icon_path)
2441 {
2442         return pkgmgr_parser_update_app_icon_info_in_usr_db(appid, __getuid(),
2443                         icon_path);
2444 }
2445
2446 API int pkgmgr_parser_update_tep_info_in_usr_db(const char *pkgid,
2447                 const char *tep_path, uid_t uid)
2448 {
2449         char *query = NULL;
2450
2451         query = sqlite3_mprintf("UPDATE package_info SET package_tep_name=%Q "
2452                 "WHERE package=%Q", tep_path, pkgid);
2453         if (query == NULL) {
2454                 _LOGE("Out of memory");
2455                 return PM_PARSER_R_ERROR;
2456         }
2457
2458         // TODO: construct query and send it to server
2459         sqlite3_free(query);
2460
2461         return PM_PARSER_R_OK;
2462 }
2463
2464 API int pkgmgr_parser_update_tep_info_in_db(const char *pkgid,
2465                 const char *tep_path)
2466 {
2467         return pkgmgr_parser_update_tep_info_in_usr_db(pkgid, tep_path,
2468                         __getuid());
2469 }
2470
2471 static int __convert_update_type(pkgmgrinfo_updateinfo_update_type type,
2472                 const char **update_type)
2473 {
2474         if (type == PMINFO_UPDATEINFO_NONE)
2475                 *update_type = PMINFO_UPDATEINFO_TYPE_NONE;
2476         else if (type == PMINFO_UPDATEINFO_FORCE)
2477                 *update_type = PMINFO_UPDATEINFO_TYPE_FORCE;
2478         else if (type == PMINFO_UPDATEINFO_OPTIONAL)
2479                 *update_type = PMINFO_UPDATEINFO_TYPE_OPTIONAL;
2480         else
2481                 return -1;
2482         return 0;
2483 }
2484
2485 static int __register_pkg_update_info(updateinfo_x *info,
2486                 const char *update_type)
2487 {
2488         char *query = NULL;
2489
2490         query = sqlite3_mprintf("UPDATE package_update_info "
2491                 "SET update_version=%Q, update_type=%Q "
2492                 "WHERE package=%Q", info->version, update_type, info->pkgid);
2493         if (query == NULL) {
2494                 _LOGE("Out of memory");
2495                 return PM_PARSER_R_ERROR;
2496         }
2497
2498         // TODO: send query to server
2499         sqlite3_free(query);
2500
2501         return PM_PARSER_R_OK;
2502 }
2503
2504 API int pkgmgr_parser_register_pkg_update_info_in_usr_db(
2505                 pkgmgrinfo_updateinfo_h handle, uid_t uid)
2506 {
2507         int ret;
2508         updateinfo_x *update_info;
2509         updateinfo_x *prev_update_info;
2510         pkgmgrinfo_updateinfo_h prev_update_handle;
2511         pkgmgrinfo_pkginfo_h pkginfo;
2512         pkgmgrinfo_version_compare_type compare_result;
2513         bool is_global_pkg;
2514         const char *update_type;
2515
2516         if (handle == NULL) {
2517                 _LOGE("invalid parameter");
2518                 return PM_PARSER_R_EINVAL;
2519         }
2520
2521         update_info = (updateinfo_x *)handle;
2522         if (update_info->pkgid == NULL || update_info->version == NULL)
2523                 return PM_PARSER_R_EINVAL;
2524         if (__convert_update_type(update_info->type, &update_type) != 0)
2525                 return PM_PARSER_R_EINVAL;
2526
2527         ret = pkgmgrinfo_updateinfo_get_usr_updateinfo(update_info->pkgid,
2528                         &prev_update_handle, uid);
2529         if (ret != PMINFO_R_OK)
2530                 return PM_PARSER_R_ERROR;
2531
2532         prev_update_info = (updateinfo_x *)prev_update_handle;
2533         ret = pkgmgrinfo_compare_package_version(update_info->version,
2534                         prev_update_info->version, &compare_result);
2535         if (ret != PMINFO_R_OK) {
2536                 pkgmgrinfo_updateinfo_destroy(prev_update_handle);
2537                 return PM_PARSER_R_ERROR;
2538         }
2539
2540         if (compare_result == PMINFO_VERSION_SAME &&
2541                         prev_update_info->type == PMINFO_UPDATEINFO_NONE) {
2542                 _LOGI("Given update info version[%s] of pkgid[%s] "
2543                                 "will be ignored",
2544                                 update_info->version, update_info->pkgid);
2545                 pkgmgrinfo_updateinfo_destroy(prev_update_handle);
2546                 return PM_PARSER_R_OK;
2547         }
2548         pkgmgrinfo_updateinfo_destroy(prev_update_handle);
2549
2550         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(update_info->pkgid, uid,
2551                         &pkginfo);
2552         if (ret != PMINFO_R_OK)
2553                 return PM_PARSER_R_ERROR;
2554
2555         ret = pkgmgrinfo_pkginfo_is_global(pkginfo, &is_global_pkg);
2556         if (ret != PMINFO_R_OK) {
2557                 pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
2558                 return PM_PARSER_R_ERROR;
2559         }
2560         pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
2561
2562         return __register_pkg_update_info(update_info, update_type);
2563 }
2564
2565 API int pkgmgr_parser_register_pkg_update_info_in_db(
2566                 pkgmgrinfo_updateinfo_h handle)
2567 {
2568         return pkgmgr_parser_register_pkg_update_info_in_usr_db(handle,
2569                         __getuid());
2570 }
2571
2572 static int __unregister_pkg_update_info(const char *pkgid, uid_t uid)
2573 {
2574         char *query = NULL;
2575
2576         query = sqlite3_mprintf("UPDATE package_update_info "
2577                 "SET update_type='none' WHERE package=%Q", pkgid);
2578         if (query == NULL) {
2579                 _LOGE("Out of memory");
2580                 return PM_PARSER_R_ERROR;
2581         }
2582
2583         // TODO: send query to server
2584         sqlite3_free(query);
2585
2586         return PM_PARSER_R_OK;
2587 }
2588
2589 API int pkgmgr_parser_unregister_pkg_update_info_in_usr_db(const char *pkgid,
2590                 uid_t uid)
2591 {
2592         int ret;
2593         pkgmgrinfo_pkginfo_h pkginfo;
2594         bool is_global_pkg;
2595         uid_t target_uid;
2596
2597         if (pkgid == NULL) {
2598                 _LOGE("invalid parameter");
2599                 return PM_PARSER_R_EINVAL;
2600         }
2601
2602         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, uid, &pkginfo);
2603         if (ret != PMINFO_R_OK)
2604                 return PM_PARSER_R_EINVAL;
2605
2606         ret = pkgmgrinfo_pkginfo_is_global(pkginfo, &is_global_pkg);
2607         pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo);
2608         if (ret != PMINFO_R_OK)
2609                 return PM_PARSER_R_ERROR;
2610
2611         target_uid = is_global_pkg ? GLOBAL_USER : uid;
2612
2613         // TODO: what we do with is_global_pkg?
2614         return __unregister_pkg_update_info(pkgid, target_uid);
2615 }
2616
2617 API int pkgmgr_parser_unregister_pkg_update_info_in_db(const char *pkgid)
2618 {
2619         return pkgmgr_parser_unregister_pkg_update_info_in_usr_db(pkgid,
2620                         __getuid());
2621 }
2622
2623 API int pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(uid_t uid)
2624 {
2625         char *query = NULL;
2626
2627         query = sqlite3_mprintf("UPDATE package_update_info "
2628                         "SET update_type='none'");
2629         if (query == NULL) {
2630                 _LOGE("Out of memory");
2631                 return PM_PARSER_R_ERROR;
2632         }
2633
2634         // TODO: send query to server
2635         sqlite3_free(query);
2636
2637         return PM_PARSER_R_OK;
2638 }
2639
2640 API int pkgmgr_parser_unregister_all_pkg_update_info_in_db(void)
2641 {
2642         return pkgmgr_parser_unregister_all_pkg_update_info_in_usr_db(
2643                         __getuid());
2644 }
2645
2646 API int pkgmgr_parser_register_pkg_plugin_info_in_usr_db(
2647                 manifest_x *mfx, uid_t uid)
2648 {
2649         return __insert_package_plugin_execution_info(mfx, uid);
2650 }
2651
2652 API int pkgmgr_parser_register_pkg_plugin_info_in_db(manifest_x *mfx)
2653 {
2654         return pkgmgr_parser_register_pkg_plugin_info_in_usr_db(mfx, __getuid());
2655 }
2656
2657 API int pkgmgr_parser_update_pkg_plugin_info_in_usr_db(
2658                 manifest_x *mfx, uid_t uid)
2659 {
2660         // TODO: construct query and send to server
2661         int ret;
2662
2663         ret = __delete_package_plugin_execution_info(mfx->package, uid);
2664         if (ret != PM_PARSER_R_OK)
2665                 return ret;
2666         ret = __insert_package_plugin_execution_info(mfx, uid);
2667         if (ret != PM_PARSER_R_OK)
2668                 return ret;
2669
2670         return PM_PARSER_R_OK;
2671 }
2672
2673 API int pkgmgr_parser_update_pkg_plugin_info_in_db(manifest_x *mfx)
2674 {
2675         return pkgmgr_parser_update_pkg_plugin_info_in_usr_db(mfx, __getuid());
2676 }
2677
2678 API int pkgmgr_parser_unregister_pkg_plugin_info_in_usr_db(
2679                 const char *pkgid, uid_t uid)
2680 {
2681         return __delete_package_plugin_execution_info(pkgid, uid);
2682 }
2683
2684 API int pkgmgr_parser_unregister_pkg_plugin_info_in_db(const char *pkgid)
2685 {
2686         return pkgmgr_parser_unregister_pkg_plugin_info_in_usr_db(pkgid, __getuid());
2687 }