Change the spec file, add mouse_event attribute.
[apps/livebox/data-provider-master.git] / pkgmgr_livebox / src / service_register.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
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 #include <stdio.h>
18 #include <errno.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <unistd.h>
22 #include <libgen.h>
23 #include <string.h>
24
25 #include <sqlite3.h>
26 #include <db-util.h>
27 #include <libxml/parser.h>
28 #include <libxml/tree.h>
29 #include <dlog.h>
30
31 #include "dlist.h"
32
33 #if !defined(FLOG)
34 #define DbgPrint(format, arg...)        LOGD("[\e[32m%s/%s\e[0m:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg)
35 #define ErrPrint(format, arg...)        LOGE("[\e[32m%s/%s\e[0m:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg)
36 #endif
37 /* End of a file */
38
39 /*!
40  * \note
41  * DB Table schema
42  *
43  * pkgmap
44  * +-------+-------+---------+
45  * | appid | pkgid | prime   |
46  * +-------+-------+---------+
47  * |   -   |   -   |         |
48  * +-------+-------+---------+
49  * CREATE TABLE pkgmap ( pkgid TEXT PRIMARY KEY NOT NULL, appid TEXT, prime INTEGER )
50  *
51  *
52  * provider
53  * +-------+---------+-----+---------+----------+---------+-----------+---------+--------+----------+---------+---------+--------+--------+-------+
54  * | pkgid | network | abi | secured | box_type | box_src | box_group | pd_type | pd_src | pd_group | libexec | timeout | period | script | pinup |
55  * +-------+---------+-----+---------+----------+---------+-----------+---------+--------+----------+---------+---------+--------+--------+-------+
56  * |   -   |    -    |  -  |    -    |     -    |    -    |     -     |    -    |    -   |     -    |     -   |    -    |    -   |    -   |   -   |
57  * +-------+---------+-----+---------+----------+---------+-----------+---------+--------+----------+---------+---------+--------+--------+-------+
58  * CREATE TABLE provider ( pkgid TEXT PRIMARY KEY NOT NULL, network INTEGER, abi TEXT, secured INTEGER, box_type INTEGER, box_src TEXT, box_group TEXT, pd_type TEXT, pd_src TEXT, pd_group TEXT, libexec TEXT, timeout INTEGER, period TEXT, script TEXT, pinup INTEGER, FOREIGN KEY(pkgid) REFERENCES pkgmap(pkgid))
59  *
60  * = box_type = { text | buffer | script | image }
61  * = pd_type = { text | buffer | script }
62  * = network = { 1 | 0 }
63  * = secured = { 1 | 0 }
64  *
65  *
66  * client
67  * +-------+------+---------+-------------+---------+---------+-----------+-------+-------------+
68  * | pkgid | Icon |  Name   | auto_launch | pd_size | content | nodisplay | setup | mouse_event |
69  * +-------+------+---------+-------------+---------+---------+-----------+-------+-------------+
70  * |   -   |   -  |    -    |      -      |    -    |    -    |     -     |   -   |      -      }
71  * +-------+------+---------+-------------+---------+---------+-----------+-------+-------------+
72  * CREATE TABLE client ( pkgid TEXT PRIMARY KEY NOT NULL, icon TEXT, name TEXT, auto_launch TEXT, pd_size TEXT, content TEXT DEFAULT "default", nodisplay INTEGER, setup TEXT, mouse_event INTEGER, FOREIGN KEY(pkgid) REFERENCES pkgmap(pkgid) )
73  *
74  * = auto_launch = UI-APPID
75  * = pd_size = WIDTHxHEIGHT
76  *
77  *
78  * i18n
79  * +-------+------+------+------+
80  * |   fk  | lang | name | icon |
81  * +-------+------+------+------+
82  * | pkgid |   -  |   -  |   -  |
83  * +-------+------+------+------+
84  * CREATE TABLE i18n ( pkgid TEXT NOT NULL, lang TEXT COLLATE NOCASE, name TEXT, icon TEXT, FOREIGN KEY(pkgid) REFERENCES pkgmap(pkgid) )
85  *
86  *
87  * box_size
88  * +-------+-----------+---------+
89  * | pkgid | size_type | preview |
90  * +-------+-----------+---------+
91  * |   -   |     -     |    -    |
92  * +-------+-----------+---------+
93  * CREATE TABLE box_size ( pkgid TEXT NOT NULL, size_type INTEGER, preview TEXT, FOREIGN KEY(pkgid) REFERENCES pkgmap(pkgid) )
94  *
95  * = box_size_list = { WIDTHxHEIGHT; WIDTHxHEIGHT; ... }
96  *
97  * groupinfo
98  * +----+---------+----------+-------+
99  * | id | cluster | category | pkgid |
100  * +----+---------+----------+-------+
101  * |  - |    -    |    -     |   -   |
102  * +----+---------+----------+-------|
103  * CREATE TABLE groupinfo ( id INTEGER PRIMARY KEY AUTOINCREMENT, cluster TEXT NOT NULL, category TEXT NOT NULL, appid TEXT NOT NULL, FOREIGN KEY(pkgid) REFERENCES pkgmap(pkgid) ))
104  *
105  * groupmap
106  * +-------+----+----------+-----------+
107  * | pkgid | id | ctx_item | option_id |
108  * +-------+----+----------+-----------+
109  * CREATE TABLE groupmap ( option_id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER, pkgid TEXT NOT NULL, ctx_item TEXT NOT NULL, FOREIGN KEY(id) REFERENCES groupinfo(id), FOREIGN KEY(pkgid) REFERENCES pkgmap(pkgid) )
110  *
111  *
112  * option
113  * +-------+-----------+-----+-------+
114  * | pkgid | option_id | key | value |
115  * +-------+-----------+-----+-------+
116  * CREATE TABLE option ( pkgid TEXT NOT NULL, option_id INTEGER, key TEXT NOT NULL, value TEXT NOT NULL, FOREIGN KEY(option_id) REFERENCES groupmap(option_id), FOREIGN KEY(pkgid) REFERENCES pkgmap(pkgid)  )
117  */
118
119 #if !defined(LIBXML_TREE_ENABLED)
120         #error "LIBXML is not supporting the tree"
121 #endif
122
123 #if defined(LOG_TAG)
124 #undef LOG_TAG
125 #endif
126
127 #define LOG_TAG "PKGMGR_LIVEBOX"
128
129 int errno;
130
131 struct i18n {
132         xmlChar *lang;
133         xmlChar *name;
134         xmlChar *icon;
135 };
136
137 enum lb_type {
138         LB_TYPE_NONE = 0x0,
139         LB_TYPE_SCRIPT,
140         LB_TYPE_FILE,
141         LB_TYPE_TEXT,
142         LB_TYPE_BUFFER,
143 };
144
145 enum pd_type {
146         PD_TYPE_NONE = 0x0,
147         PD_TYPE_SCRIPT,
148         PD_TYPE_TEXT,
149         PD_TYPE_BUFFER,
150 };
151
152 enum lb_size {
153         LB_SIZE_1x1 = 0x01,
154         LB_SIZE_2x1 = 0x02,
155         LB_SIZE_2x2 = 0x04,
156         LB_SIZE_4x1 = 0x08,
157         LB_SIZE_4x2 = 0x10,
158         LB_SIZE_4x3 = 0x20,
159         LB_SIZE_4x4 = 0x40,
160 };
161
162 struct livebox {
163         xmlChar *pkgid;
164         int secured;
165         int network;
166         xmlChar *auto_launch;
167         xmlChar *abi;
168         xmlChar *name; /* Default name */
169         xmlChar *icon; /* Default icon */
170         xmlChar *libexec; /* Path of the SO file */
171         xmlChar *timeout; /* INTEGER, timeout */
172         xmlChar *period; /* DOUBLE, update period */
173         xmlChar *script; /* Script engine */
174         xmlChar *content; /* Content information */
175         xmlChar *setup;
176
177         int pinup; /* Is this support the pinup feature? */
178         int primary; /* Is this primary livebox? */
179         int nodisplay;
180         int mouse_event; /* Mouse event processing option for livebox */
181
182         enum lb_type lb_type;
183         xmlChar *lb_src;
184         xmlChar *lb_group;
185         int size_list; /* 1x1, 2x1, 2x2, 4x1, 4x2, 4x3, 4x4 */
186
187         xmlChar *preview[7];
188
189         enum pd_type pd_type;
190         xmlChar *pd_src;
191         xmlChar *pd_group;
192         xmlChar *pd_size; /* Default PD size */
193
194         struct dlist *i18n_list;
195         struct dlist *group_list;
196 };
197
198 struct group {
199         xmlChar *cluster;
200         xmlChar *category;
201         xmlChar *ctx_item;
202         struct dlist *option_list;
203 };
204
205 struct option {
206         xmlChar *key;
207         xmlChar *value;
208 };
209
210 static struct {
211         const char *dbfile;
212         sqlite3 *handle;
213 } s_info = {
214         .dbfile = "/opt/dbspace/.livebox.db",
215         .handle = NULL,
216 };
217
218 static inline int begin_transaction(void)
219 {
220         sqlite3_stmt *stmt;
221         int ret;
222
223         ret = sqlite3_prepare_v2(s_info.handle, "BEGIN TRANSACTION", -1, &stmt, NULL);
224
225         if (ret != SQLITE_OK) {
226                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
227                 return EXIT_FAILURE;
228         }
229
230         if (sqlite3_step(stmt) != SQLITE_DONE) {
231                 DbgPrint("Failed to do update (%s)\n",
232                                         sqlite3_errmsg(s_info.handle));
233                 sqlite3_finalize(stmt);
234                 return EXIT_FAILURE;
235         }
236
237         sqlite3_finalize(stmt);
238         return EXIT_SUCCESS;
239 }
240
241 static inline int rollback_transaction(void)
242 {
243         int ret;
244         sqlite3_stmt *stmt;
245
246         ret = sqlite3_prepare_v2(s_info.handle, "ROLLBACK TRANSACTION", -1, &stmt, NULL);
247         if (ret != SQLITE_OK) {
248                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
249                 return EXIT_FAILURE;
250         }
251
252         if (sqlite3_step(stmt) != SQLITE_DONE) {
253                 DbgPrint("Failed to do update (%s)\n",
254                                 sqlite3_errmsg(s_info.handle));
255                 sqlite3_finalize(stmt);
256                 return EXIT_FAILURE;
257         }
258
259         sqlite3_finalize(stmt);
260         return EXIT_SUCCESS;
261 }
262
263 static inline int commit_transaction(void)
264 {
265         sqlite3_stmt *stmt;
266         int ret;
267
268         ret = sqlite3_prepare_v2(s_info.handle, "COMMIT TRANSACTION", -1, &stmt, NULL);
269         if (ret != SQLITE_OK) {
270                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
271                 return EXIT_FAILURE;
272         }
273
274         if (sqlite3_step(stmt) != SQLITE_DONE) {
275                 DbgPrint("Failed to do update (%s)\n",
276                                         sqlite3_errmsg(s_info.handle));
277                 sqlite3_finalize(stmt);
278                 return EXIT_FAILURE;
279         }
280
281         sqlite3_finalize(stmt);
282         return EXIT_SUCCESS;
283 }
284
285 static inline int db_create_pkgmap(void)
286 {
287         char *err;
288         static const char *ddl;
289
290         ddl = "CREATE TABLE pkgmap ( pkgid TEXT PRIMARY KEY NOT NULL, appid TEXT, prime INTEGER )";
291         if (sqlite3_exec(s_info.handle, ddl, NULL, NULL, &err) != SQLITE_OK) {
292                 ErrPrint("Failed to execute the DDL (%s)\n", err);
293                 return -EIO;
294         }
295
296         if (sqlite3_changes(s_info.handle) == 0)
297                 ErrPrint("No changes to DB\n");
298
299         return 0;
300 }
301
302 static inline int db_insert_pkgmap(const char *appid, const char *pkgid, int primary)
303 {
304         int ret;
305         static const char *dml;
306         sqlite3_stmt *stmt;
307
308         dml = "INSERT INTO pkgmap ( appid, pkgid, prime ) VALUES (? ,?, ?)";
309         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
310         if (ret != SQLITE_OK) {
311                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
312                 return -EIO;
313         }
314
315         ret = sqlite3_bind_text(stmt, 1, appid, -1, NULL);
316         if (ret != SQLITE_OK) {
317                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
318                 ret = -EIO;
319                 goto out;
320         }
321
322         ret = sqlite3_bind_text(stmt, 2, pkgid, -1, NULL);
323         if (ret != SQLITE_OK) {
324                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
325                 ret = -EIO;
326                 goto out;
327         }
328
329         ret = sqlite3_bind_int(stmt, 3, primary);
330         if (ret != SQLITE_OK) {
331                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
332                 ret = -EIO;
333                 goto out;
334         }
335
336         ret = 0;
337         if (sqlite3_step(stmt) != SQLITE_DONE) {
338                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
339                 ret = -EIO;
340         }
341
342 out:
343         sqlite3_reset(stmt);
344         sqlite3_clear_bindings(stmt);
345         sqlite3_finalize(stmt);
346         return ret;
347 }
348
349 static inline int db_remove_pkgmap(const char *pkgid)
350 {
351         int ret;
352         static const char *dml;
353         sqlite3_stmt *stmt;
354
355         dml = "DELETE FROM pkgmap WHERE pkgid = ?";
356         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
357         if (ret != SQLITE_OK) {
358                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
359                 return -EIO;
360         }
361
362         ret = sqlite3_bind_text(stmt, 1, pkgid, -1, NULL);
363         if (ret != SQLITE_OK) {
364                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
365                 ret = -EIO;
366                 goto out;
367         }
368
369         ret = 0;
370         if (sqlite3_step(stmt) != SQLITE_DONE) {
371                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
372                 ret = -EIO;
373         }
374
375 out:
376         sqlite3_reset(stmt);
377         sqlite3_clear_bindings(stmt);
378         sqlite3_finalize(stmt);
379         return ret;
380 }
381
382 static inline int db_create_provider(void)
383 {
384         char *err;
385         static const char *ddl;
386
387         ddl = "CREATE TABLE provider (" \
388                 "pkgid TEXT PRIMARY KEY NOT NULL, network INTEGER, " \
389                 "abi TEXT, secured INTEGER, box_type INTEGER, " \
390                 "box_src TEXT, box_group TEXT, pd_type INTEGER, " \
391                 "pd_src TEXT, pd_group TEXT, libexec TEXT, timeout INTEGER, period TEXT, script TEXT, pinup INTEGER, "\
392                 "FOREIGN KEY(pkgid) REFERENCES pkgmap(pkgid) ON DELETE CASCADE)";
393
394         if (sqlite3_exec(s_info.handle, ddl, NULL, NULL, &err) != SQLITE_OK) {
395                 ErrPrint("Failed to execute the DDL (%s)\n", err);
396                 return -EIO;
397         }
398
399         if (sqlite3_changes(s_info.handle) == 0)
400                 ErrPrint("No changes to DB\n");
401
402         return 0;
403 }
404
405 static inline int db_remove_provider(const char *pkgid)
406 {
407         static const char *dml;
408         int ret;
409         sqlite3_stmt *stmt;
410
411         dml = "DELETE FROM provider WHERE pkgid = ?";
412         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
413         if (ret != SQLITE_OK) {
414                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
415                 return -EIO;
416         }
417
418         ret = sqlite3_bind_text(stmt, 1, pkgid, -1, NULL);
419         if (ret != SQLITE_OK) {
420                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
421                 ret = -EIO;
422                 goto out;
423         }
424
425         ret = 0;
426         if (sqlite3_step(stmt) != SQLITE_DONE) {
427                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
428                 ret = -EIO;
429         }
430
431 out:
432         sqlite3_reset(stmt);
433         sqlite3_clear_bindings(stmt);
434         sqlite3_finalize(stmt);
435         return ret;
436 }
437 static inline int db_insert_provider(struct livebox *livebox)
438 {
439         static const char *dml;
440         int ret;
441         sqlite3_stmt *stmt;
442         char *abi = (char *)livebox->abi;
443         char *box_src = (char *)livebox->lb_src;
444         char *box_group = (char *)livebox->lb_group;
445         char *pd_src = (char *)livebox->pd_src;
446         char *pd_group = (char *)livebox->pd_group;
447         char *libexec = (char *)livebox->libexec;
448         char *timeout = (char *)livebox->timeout;
449         char *period = (char *)livebox->period;
450         char *script = (char *)livebox->script;
451
452         if (!abi)
453                 abi = "c";
454
455         if (!box_src)
456                 box_src = "";
457
458         if (!box_group)
459                 box_group = "";
460
461         if (!pd_src)
462                 pd_src = "";
463
464         if (!pd_group)
465                 pd_group = "";
466
467         if (!libexec)
468                 libexec = "";
469
470         if (!timeout)
471                 timeout = "10";
472
473         if (!period)
474                 period = "0.0";
475
476         if (!script)
477                 script = "edje";
478
479         dml = "INSERT INTO provider ( pkgid, network, abi, secured, box_type, box_src, box_group, pd_type, pd_src, pd_group, libexec, timeout, period, script, pinup ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
480         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
481         if (ret != SQLITE_OK) {
482                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
483                 return -EIO;
484         }
485
486         ret = sqlite3_bind_text(stmt, 1, (char *)livebox->pkgid, -1, NULL);
487         if (ret != SQLITE_OK) {
488                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
489                 ret = -EIO;
490                 goto out;
491         }
492
493
494         ret = sqlite3_bind_int(stmt, 2, livebox->network);
495         if (ret != SQLITE_OK) {
496                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
497                 ret = -EIO;
498                 goto out;
499         }
500
501         ret = sqlite3_bind_text(stmt, 3, abi, -1, NULL);
502         if (ret != SQLITE_OK) {
503                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
504                 ret = -EIO;
505                 goto out;
506         }
507         ret = sqlite3_bind_int(stmt, 4, livebox->secured);
508         if (ret != SQLITE_OK) {
509                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
510                 ret = -EIO;
511                 goto out;
512         }
513
514         ret = sqlite3_bind_int(stmt, 5, livebox->lb_type);
515         if (ret != SQLITE_OK) {
516                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
517                 ret = -EIO;
518                 goto out;
519         }
520
521         ret = sqlite3_bind_text(stmt, 6, box_src, -1, NULL);
522         if (ret != SQLITE_OK) {
523                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
524                 ret = -EIO;
525                 goto out;
526         }
527
528         ret = sqlite3_bind_text(stmt, 7, box_group, -1, NULL);
529         if (ret != SQLITE_OK) {
530                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
531                 ret = -EIO;
532                 goto out;
533         }
534
535         ret = sqlite3_bind_int(stmt, 8, livebox->pd_type);
536         if (ret != SQLITE_OK) {
537                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
538                 ret = -EIO;
539                 goto out;
540         }
541
542         ret = sqlite3_bind_text(stmt, 9, pd_src, -1, NULL);
543         if (ret != SQLITE_OK) {
544                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
545                 ret = -EIO;
546                 goto out;
547         }
548
549         ret = sqlite3_bind_text(stmt, 10, pd_group, -1, NULL);
550         if (ret != SQLITE_OK) {
551                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
552                 ret = -EIO;
553                 goto out;
554         }
555
556         ret = sqlite3_bind_text(stmt, 11, libexec, -1, NULL);
557         if (ret != SQLITE_OK) {
558                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
559                 ret = -EIO;
560                 goto out;
561         }
562
563         ret = sqlite3_bind_int(stmt, 12, atoi(timeout));
564         if (ret != SQLITE_OK) {
565                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
566                 ret = -EIO;
567                 goto out;
568         }
569
570         ret = sqlite3_bind_text(stmt, 13, period, -1, NULL);
571         if (ret != SQLITE_OK) {
572                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
573                 ret = -EIO;
574                 goto out;
575         }
576
577         ret = sqlite3_bind_text(stmt, 14, script, -1, NULL);
578         if (ret != SQLITE_OK) {
579                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
580                 ret = -EIO;
581                 goto out;
582         }
583
584         ret = sqlite3_bind_int(stmt, 15, livebox->pinup);
585         if (ret != SQLITE_OK) {
586                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
587                 ret = -EIO;
588                 goto out;
589         }
590
591         ret = 0;
592         if (sqlite3_step(stmt) != SQLITE_DONE) {
593                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
594                 ret = -EIO;
595         }
596
597 out:
598         sqlite3_reset(stmt);
599         sqlite3_clear_bindings(stmt);
600         sqlite3_finalize(stmt);
601         return ret;
602 }
603
604 static inline int db_create_client(void)
605 {
606         char *err;
607         static const char *ddl;
608
609         ddl = "CREATE TABLE client (" \
610                 "pkgid TEXT PRIMARY KEY NOT NULL, icon TEXT, name TEXT, " \
611                 "auto_launch TEXT, pd_size TEXT, content TEXT DEFAULT 'default', nodisplay INTEGER, setup TEXT, mouse_event INTEGER, FOREIGN KEY(pkgid) REFERENCES pkgmap(pkgid) ON DELETE CASCADE)";
612         if (sqlite3_exec(s_info.handle, ddl, NULL, NULL, &err) != SQLITE_OK) {
613                 ErrPrint("Failed to execute the DDL (%s)\n", err);
614                 return -EIO;
615         }
616
617         if (sqlite3_changes(s_info.handle) == 0)
618                 ErrPrint("No changes to DB\n");
619
620         return 0;
621 }
622
623 static inline int db_insert_client(struct livebox *livebox)
624 {
625         static const char *dml;
626         int ret;
627         sqlite3_stmt *stmt;
628
629         dml = "INSERT INTO client ( pkgid, icon, name, auto_launch, pd_size, content, nodisplay, setup, mouse_event ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
630         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
631         if (ret != SQLITE_OK) {
632                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
633                 return -EIO;
634         }
635
636         ret = sqlite3_bind_text(stmt, 1, (char *)livebox->pkgid, -1, NULL);
637         if (ret != SQLITE_OK) {
638                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
639                 ret = -EIO;
640                 goto out;
641         }
642
643         ret = sqlite3_bind_text(stmt, 2, (char *)livebox->icon, -1, NULL);
644         if (ret != SQLITE_OK) {
645                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
646                 ret = -EIO;
647                 goto out;
648         }
649
650         ret = sqlite3_bind_text(stmt, 3, (char *)livebox->name, -1, NULL);
651         if (ret != SQLITE_OK) {
652                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
653                 ret = -EIO;
654                 goto out;
655         }
656
657         ret = sqlite3_bind_text(stmt, 4, (char *)livebox->auto_launch, -1, NULL);
658         if (ret != SQLITE_OK) {
659                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
660                 ret = -EIO;
661                 goto out;
662         }
663
664         ret = sqlite3_bind_text(stmt, 5, (char *)livebox->pd_size, -1, NULL);
665         if (ret != SQLITE_OK) {
666                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
667                 ret = -EIO;
668                 goto out;
669         }
670
671         ret = sqlite3_bind_text(stmt, 6, livebox->content ? (char *)livebox->content : "default", -1, NULL);
672         if (ret != SQLITE_OK) {
673                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
674                 ret = -EIO;
675                 goto out;
676         }
677
678         ret = sqlite3_bind_int(stmt, 7, livebox->nodisplay);
679         if (ret != SQLITE_OK) {
680                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
681                 ret = -EIO;
682                 goto out;
683         }
684
685         ret = sqlite3_bind_text(stmt, 8, livebox->setup ? (char *)livebox->setup : "", -1, NULL);
686         if (ret != SQLITE_OK) {
687                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
688                 ret = -EIO;
689                 goto out;
690         }
691
692         ret = sqlite3_bind_int(stmt, 9, livebox->mouse_event);
693         if (ret != SQLITE_OK) {
694                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
695                 ret = -EIO;
696                 goto out;
697         }
698
699         ret = 0;
700         if (sqlite3_step(stmt) != SQLITE_DONE) {
701                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
702                 ret = -EIO;
703         }
704
705 out:
706         sqlite3_reset(stmt);
707         sqlite3_clear_bindings(stmt);
708         sqlite3_finalize(stmt);
709         return ret;
710 }
711
712 static inline int db_remove_client(const char *pkgid)
713 {
714         static const char *dml;
715         int ret;
716         sqlite3_stmt *stmt;
717
718         dml = "DELETE FROM client WHERE pkgid = ?";
719         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
720         if (ret != SQLITE_OK) {
721                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
722                 return -EIO;
723         }
724
725         ret = sqlite3_bind_text(stmt, 1, pkgid, -1, NULL);
726         if (ret != SQLITE_OK) {
727                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
728                 ret = -EIO;
729                 goto out;
730         }
731
732         ret = 0;
733         if (sqlite3_step(stmt) != SQLITE_DONE) {
734                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
735                 ret = -EIO;
736         }
737
738 out:
739         sqlite3_reset(stmt);
740         sqlite3_clear_bindings(stmt);
741         sqlite3_finalize(stmt);
742         return ret;
743 }
744
745 static inline int db_create_i18n(void)
746 {
747         char *err;
748         static const char *ddl;
749
750         ddl = "CREATE TABLE i18n ( pkgid TEXT NOT NULL, lang TEXT COLLATE NOCASE, name TEXT, " \
751                 "icon TEXT, FOREIGN KEY(pkgid) REFERENCES pkgmap(pkgid) ON DELETE CASCADE)";
752         if (sqlite3_exec(s_info.handle, ddl, NULL, NULL, &err) != SQLITE_OK) {
753                 ErrPrint("Failed to execute the DDL (%s)\n", err);
754                 return -EIO;
755         }
756
757         if (sqlite3_changes(s_info.handle) == 0)
758                 ErrPrint("No changes to DB\n");
759
760         return 0;
761 }
762
763 static inline int db_insert_i18n(const char *pkgid, const char *lang, const char *name, const char *icon)
764 {
765         static const char *dml;
766         int ret;
767         sqlite3_stmt *stmt;
768
769         DbgPrint("%s - lang[%s] name[%s] icon[%s]\n", pkgid, lang, name, icon);
770         dml = "INSERT INTO i18n ( pkgid, lang, name, icon ) VALUES (?, ?, ?, ?)";
771         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
772         if (ret != SQLITE_OK) {
773                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
774                 return -EIO;
775         }
776
777         ret = sqlite3_bind_text(stmt, 1, pkgid, -1, NULL);
778         if (ret != SQLITE_OK) {
779                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
780                 ret = -EIO;
781                 goto out;
782         }
783
784         ret = sqlite3_bind_text(stmt, 2, lang, -1, NULL);
785         if (ret != SQLITE_OK) {
786                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
787                 ret = -EIO;
788                 goto out;
789         }
790
791         ret = sqlite3_bind_text(stmt, 3, name, -1, NULL);
792         if (ret != SQLITE_OK) {
793                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
794                 ret = -EIO;
795                 goto out;
796         }
797
798         ret = sqlite3_bind_text(stmt, 4, icon, -1, NULL);
799         if (ret != SQLITE_OK) {
800                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
801                 ret = -EIO;
802                 goto out;
803         }
804
805         ret = 0;
806         if (sqlite3_step(stmt) != SQLITE_DONE) {
807                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
808                 ret = -EIO;
809         }
810
811 out:
812         sqlite3_reset(stmt);
813         sqlite3_clear_bindings(stmt);
814         sqlite3_finalize(stmt);
815         return ret;
816 }
817
818 static inline int db_remove_i18n(const char *pkgid)
819 {
820         static const char *dml;
821         int ret;
822         sqlite3_stmt *stmt;
823
824         dml = "DELETE FROM i18n WHERE pkgid = ?";
825         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
826         if (ret != SQLITE_OK) {
827                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
828                 return -EIO;
829         }
830
831         ret = sqlite3_bind_text(stmt, 1, pkgid, -1, NULL);
832         if (ret != SQLITE_OK) {
833                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
834                 ret = -EIO;
835                 goto out;
836         }
837
838         ret = 0;
839         if (sqlite3_step(stmt) != SQLITE_DONE) {
840                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
841                 ret = -EIO;
842         }
843
844         if (sqlite3_changes(s_info.handle) == 0)
845                 DbgPrint("No changes\n");
846
847 out:
848         sqlite3_reset(stmt);
849         sqlite3_clear_bindings(stmt);
850         sqlite3_finalize(stmt);
851         return ret;
852 }
853
854 static inline int db_create_group(void)
855 {
856         char *err;
857         static const char *ddl;
858
859         ddl = "CREATE TABLE groupinfo ( id INTEGER PRIMARY KEY AUTOINCREMENT, cluster TEXT NOT NULL, category TEXT NOT NULL, pkgid TEXT NOT NULL, FOREIGN KEY(pkgid) REFERENCES pkgmap(pkgid) ON DELETE CASCADE)";
860         if (sqlite3_exec(s_info.handle, ddl, NULL, NULL, &err) != SQLITE_OK) {
861                 ErrPrint("Failed to execute the DDL (%s)\n", err);
862                 return -EIO;
863         }
864
865         if (sqlite3_changes(s_info.handle) == 0)
866                 ErrPrint("No changes to DB\n");
867
868         return 0;
869 }
870
871 static inline int db_insert_group(const char *pkgid, const char *cluster, const char *category)
872 {
873         static const char *dml;
874         int ret;
875         sqlite3_stmt *stmt;
876
877         dml = "INSERT INTO groupinfo ( cluster, category, pkgid ) VALUES (?, ?, ?)";
878         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
879         if (ret != SQLITE_OK) {
880                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
881                 return -EIO;
882         }
883
884         ret = sqlite3_bind_text(stmt, 1, cluster, -1, NULL);
885         if (ret != SQLITE_OK) {
886                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
887                 ret = -EIO;
888                 goto out;
889         }
890
891         ret = sqlite3_bind_text(stmt, 2, category, -1, NULL);
892         if (ret != SQLITE_OK) {
893                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
894                 ret = -EIO;
895                 goto out;
896         }
897
898         ret = sqlite3_bind_text(stmt, 3, pkgid, -1, NULL);
899         if (ret != SQLITE_OK) {
900                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
901                 ret = -EIO;
902                 goto out;
903         }
904
905         ret = 0;
906         if (sqlite3_step(stmt) != SQLITE_DONE) {
907                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
908                 ret = -EIO;
909         }
910
911 out:
912         sqlite3_reset(stmt);
913         sqlite3_clear_bindings(stmt);
914         sqlite3_finalize(stmt);
915         return ret;
916 }
917
918 static inline int db_get_group_id(const char *cluster, const char *category)
919 {
920         static const char *dml = "SELECT id FROM groupinfo WHERE cluster = ? AND category = ?";
921         sqlite3_stmt *stmt;
922         int ret;
923
924         if (!cluster || !category) {
925                 ErrPrint("Invalid argument\n");
926                 return -EINVAL;
927         }
928
929         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
930         if (ret != SQLITE_OK) {
931                 ErrPrint("Failed to prepare the initial DML(%s)\n", sqlite3_errmsg(s_info.handle));
932                 return -EIO;
933         }
934
935         ret = -EIO;
936         if (sqlite3_bind_text(stmt, 1, cluster, -1, NULL) != SQLITE_OK) {
937                 ErrPrint("Failed to bind a cluster(%s) - %s\n", cluster, sqlite3_errmsg(s_info.handle));
938                 goto out;
939         }
940
941         if (sqlite3_bind_text(stmt, 2, category, -1, NULL) != SQLITE_OK) {
942                 ErrPrint("Failed to bind a category(%s) - %s\n", category, sqlite3_errmsg(s_info.handle));
943                 goto out;
944         }
945
946         if (sqlite3_step(stmt) != SQLITE_ROW) {
947                 ErrPrint("Failed to execute the DML for %s - %s\n", cluster, category);
948                 goto out;
949         }
950
951         ret = sqlite3_column_int(stmt, 0);
952
953 out:
954         sqlite3_reset(stmt);
955         sqlite3_clear_bindings(stmt);
956         sqlite3_finalize(stmt);
957         return ret;
958 }
959
960 static inline int db_remove_group(const char *pkgid)
961 {
962         static const char *dml;
963         int ret;
964         sqlite3_stmt *stmt;
965
966         dml = "DELETE FROM groupinfo WHERE pkgid = ?";
967         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
968         if (ret != SQLITE_OK) {
969                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
970                 return -EIO;
971         }
972
973         ret = sqlite3_bind_text(stmt, 1, pkgid, -1, NULL);
974         if (ret != SQLITE_OK) {
975                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
976                 ret = -EIO;
977                 goto out;
978         }
979
980         ret = 0;
981         if (sqlite3_step(stmt) != SQLITE_DONE) {
982                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
983                 ret = -EIO;
984         }
985
986         if (sqlite3_changes(s_info.handle) == 0)
987                 DbgPrint("No changes\n");
988
989 out:
990         sqlite3_reset(stmt);
991         sqlite3_clear_bindings(stmt);
992         sqlite3_finalize(stmt);
993         return ret;
994 }
995
996 static inline int db_create_groupmap(void)
997 {
998         char *err;
999         static const char *ddl;
1000
1001         ddl = "CREATE TABLE groupmap (option_id INTEGER PRIMARY KEY AUTOINCREMENT, id INTEGER, pkgid TEXT NOT NULL, ctx_item TEXT NOT NULL, FOREIGN KEY(id) REFERENCES groupinfo(id), FOREIGN KEY(pkgid) REFERENCES pkgmap(pkgid) ON DELETE CASCADE)";
1002         if (sqlite3_exec(s_info.handle, ddl, NULL, NULL, &err) != SQLITE_OK) {
1003                 ErrPrint("Failed to execute the DDL (%s)\n", err);
1004                 return -EIO;
1005         }
1006
1007         if (sqlite3_changes(s_info.handle) == 0)
1008                 ErrPrint("No changes to DB\n");
1009
1010         return 0;
1011 }
1012
1013 static inline int db_get_option_id(int id, const char *pkgid, const char *ctx_item)
1014 {
1015         static const char *dml;
1016         int ret;
1017         sqlite3_stmt *stmt;
1018
1019         dml = "SELECT option_id FROM groupmap WHERE id = ? AND pkgid = ? AND ctx_item = ?";
1020         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
1021         if (ret != SQLITE_OK) {
1022                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1023                 return -EIO;
1024         }
1025
1026         ret = sqlite3_bind_int(stmt, 1, id);
1027         if (ret != SQLITE_OK) {
1028                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1029                 ret = -EIO;
1030                 goto out;
1031         }
1032
1033         ret = sqlite3_bind_text(stmt, 2, pkgid, -1, NULL);
1034         if (ret != SQLITE_OK) {
1035                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1036                 ret = -EIO;
1037                 goto out;
1038         }
1039
1040         ret = sqlite3_bind_text(stmt, 3, ctx_item, -1, NULL);
1041         if (ret != SQLITE_OK) {
1042                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1043                 ret = -EIO;
1044                 goto out;
1045         }
1046
1047         ret = 0;
1048         if (sqlite3_step(stmt) != SQLITE_ROW) {
1049                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1050                 ret = -EIO;
1051                 goto out;
1052         }
1053
1054         ret = sqlite3_column_int(stmt, 0);
1055
1056 out:
1057         sqlite3_reset(stmt);
1058         sqlite3_clear_bindings(stmt);
1059         sqlite3_finalize(stmt);
1060         return ret;
1061 }
1062
1063 static inline int db_insert_groupmap(int id, const char *pkgid, const char *ctx_item)
1064 {
1065         static const char *dml;
1066         int ret;
1067         sqlite3_stmt *stmt;
1068
1069         DbgPrint("%d (%s) add to groupmap\n", id, pkgid);
1070
1071         dml = "INSERT INTO groupmap ( id, pkgid, ctx_item ) VALUES (?, ?, ?)";
1072         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
1073         if (ret != SQLITE_OK) {
1074                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1075                 return -EIO;
1076         }
1077
1078         ret = sqlite3_bind_int(stmt, 1, id);
1079         if (ret != SQLITE_OK) {
1080                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1081                 ret = -EIO;
1082                 goto out;
1083         }
1084
1085         ret = sqlite3_bind_text(stmt, 2, pkgid, -1, NULL);
1086         if (ret != SQLITE_OK) {
1087                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1088                 ret = -EIO;
1089                 goto out;
1090         }
1091
1092         ret = sqlite3_bind_text(stmt, 3, ctx_item, -1, NULL);
1093         if (ret != SQLITE_OK) {
1094                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1095                 ret = -EIO;
1096                 goto out;
1097         }
1098
1099         ret = 0;
1100         if (sqlite3_step(stmt) != SQLITE_DONE) {
1101                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1102                 ret = -EIO;
1103         }
1104
1105 out:
1106         sqlite3_reset(stmt);
1107         sqlite3_clear_bindings(stmt);
1108         sqlite3_finalize(stmt);
1109         return ret;
1110 }
1111
1112 static inline int db_remove_groupmap(const char *pkgid)
1113 {
1114         static const char *dml;
1115         int ret;
1116         sqlite3_stmt *stmt;
1117
1118         dml = "DELETE FROM groupmap WHERE pkgid = ?";
1119         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
1120         if (ret != SQLITE_OK) {
1121                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1122                 return -EIO;
1123         }
1124
1125         ret = sqlite3_bind_text(stmt, 1, pkgid, -1, NULL);
1126         if (ret != SQLITE_OK) {
1127                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1128                 ret = -EIO;
1129                 goto out;
1130         }
1131
1132         ret = 0;
1133         if (sqlite3_step(stmt) != SQLITE_DONE) {
1134                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1135                 ret = -EIO;
1136         }
1137
1138         if (sqlite3_changes(s_info.handle) == 0)
1139                 DbgPrint("No changes\n");
1140
1141 out:
1142         sqlite3_reset(stmt);
1143         sqlite3_clear_bindings(stmt);
1144         sqlite3_finalize(stmt);
1145         return ret;
1146 }
1147
1148 static inline int db_create_option(void)
1149 {
1150         char *err;
1151         static const char *ddl;
1152
1153         ddl = "CREATE TABLE option ( pkgid TEXT NOT NULL, option_id INTEGER, key TEXT NOT NULL, value TEXT NOT NULL, " \
1154                 "FOREIGN KEY(option_id) REFERENCES groupmap(option_id), " \
1155                 "FOREIGN KEY(pkgid) REFERENCES pkgmap(pkgid) ON DELETE CASCADE)";
1156         if (sqlite3_exec(s_info.handle, ddl, NULL, NULL, &err) != SQLITE_OK) {
1157                 ErrPrint("Failed to execute the DDL (%s)\n", err);
1158                 return -EIO;
1159         }
1160
1161         if (sqlite3_changes(s_info.handle) == 0)
1162                 ErrPrint("No changes to DB\n");
1163
1164         return 0;
1165 }
1166
1167 static inline int db_insert_option(const char *pkgid, int option_id, const char *key, const char *value)
1168 {
1169         static const char *dml;
1170         int ret;
1171         sqlite3_stmt *stmt;
1172
1173         dml = "INSERT INTO option (pkgid, option_id, key, value) VALUES (?, ?, ?, ?)";
1174         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
1175         if (ret != SQLITE_OK) {
1176                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1177                 return -EIO;
1178         }
1179
1180         ret = sqlite3_bind_text(stmt, 1, pkgid, -1, NULL);
1181         if (ret != SQLITE_OK) {
1182                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1183                 ret = -EIO;
1184                 goto out;
1185         }
1186
1187         ret = sqlite3_bind_int(stmt, 2, option_id);
1188         if (ret != SQLITE_OK) {
1189                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1190                 ret = -EIO;
1191                 goto out;
1192         }
1193
1194         ret = sqlite3_bind_text(stmt, 3, key, -1, NULL);
1195         if (ret != SQLITE_OK) {
1196                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1197                 ret = -EIO;
1198                 goto out;
1199         }
1200
1201         ret = sqlite3_bind_text(stmt, 4, value, -1, NULL);
1202         if (ret != SQLITE_OK) {
1203                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1204                 ret = -EIO;
1205                 goto out;
1206         }
1207
1208         ret = 0;
1209         if (sqlite3_step(stmt) != SQLITE_DONE) {
1210                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1211                 ret = -EIO;
1212         }
1213 out:
1214         sqlite3_reset(stmt);
1215         sqlite3_clear_bindings(stmt);
1216         sqlite3_finalize(stmt);
1217         return ret;
1218 }
1219
1220 static inline int db_remove_option(const char *pkgid)
1221 {
1222         static const char *dml;
1223         int ret;
1224         sqlite3_stmt *stmt;
1225
1226         dml = "DELETE FROM option WHERE pkgid = ?";
1227         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
1228         if (ret != SQLITE_OK) {
1229                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1230                 return -EIO;
1231         }
1232
1233         ret = sqlite3_bind_text(stmt, 1, pkgid, -1, NULL);
1234         if (ret != SQLITE_OK) {
1235                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1236                 ret = -EIO;
1237                 goto out;
1238         }
1239
1240         ret = 0;
1241         if (sqlite3_step(stmt) != SQLITE_DONE) {
1242                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1243                 ret = -EIO;
1244         }
1245
1246         if (sqlite3_changes(s_info.handle) == 0)
1247                 DbgPrint("No changes\n");
1248
1249 out:
1250         sqlite3_reset(stmt);
1251         sqlite3_clear_bindings(stmt);
1252         sqlite3_finalize(stmt);
1253         return ret;
1254 }
1255
1256 static inline int db_create_box_size(void)
1257 {
1258         char *err;
1259         static const char *ddl;
1260
1261         ddl = "CREATE TABLE box_size ( pkgid TEXT NOT NULL, size_type INTEGER, preview TEXT, " \
1262                 "FOREIGN KEY(pkgid) REFERENCES pkgmap(pkgid) ON DELETE CASCADE)";
1263         if (sqlite3_exec(s_info.handle, ddl, NULL, NULL, &err) != SQLITE_OK) {
1264                 ErrPrint("Failed to execute the DDL (%s)\n", err);
1265                 return -EIO;
1266         }
1267
1268         if (sqlite3_changes(s_info.handle) == 0)
1269                 ErrPrint("No changes to DB\n");
1270
1271         return 0;
1272 }
1273
1274 static inline int db_insert_box_size(const char *pkgid, int size_type, const char *preview)
1275 {
1276         static const char *dml;
1277         int ret;
1278         sqlite3_stmt *stmt;
1279
1280         DbgPrint("box size: %s - %d (%s) is added\n", pkgid, size_type, preview);
1281         dml = "INSERT INTO box_size ( pkgid, size_type, preview ) VALUES (?, ?, ?)";
1282         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
1283         if (ret != SQLITE_OK) {
1284                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1285                 return -EIO;
1286         }
1287
1288         ret = sqlite3_bind_text(stmt, 1, pkgid, -1, NULL);
1289         if (ret != SQLITE_OK) {
1290                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1291                 ret = -EIO;
1292                 goto out;
1293         }
1294
1295         ret = sqlite3_bind_int(stmt, 2, size_type);
1296         if (ret != SQLITE_OK) {
1297                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1298                 ret = -EIO;
1299                 goto out;
1300         }
1301
1302         ret = sqlite3_bind_text(stmt, 3, preview ? preview : "", -1, NULL);
1303         if (ret != SQLITE_OK) {
1304                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1305                 ret = -EIO;
1306                 goto out;
1307         }
1308
1309         ret = 0;
1310         if (sqlite3_step(stmt) != SQLITE_DONE) {
1311                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1312                 ret = -EIO;
1313         }
1314
1315 out:
1316         sqlite3_reset(stmt);
1317         sqlite3_clear_bindings(stmt);
1318         sqlite3_finalize(stmt);
1319         return ret;
1320 }
1321
1322 static inline int db_remove_box_size(const char *pkgid)
1323 {
1324         static const char *dml;
1325         int ret;
1326         sqlite3_stmt *stmt;
1327
1328         dml = "DELETE FROM box_size WHERE pkgid = ?";
1329         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
1330         if (ret != SQLITE_OK) {
1331                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1332                 return -EIO;
1333         }
1334
1335         ret = sqlite3_bind_text(stmt, 1, pkgid, -1, NULL);
1336         if (ret != SQLITE_OK) {
1337                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1338                 ret = -EIO;
1339                 goto out;
1340         }
1341
1342         ret = 0;
1343         if (sqlite3_step(stmt) != SQLITE_DONE) {
1344                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
1345                 ret = -EIO;
1346         }
1347
1348         if (sqlite3_changes(s_info.handle) == 0)
1349                 DbgPrint("No changes\n");
1350
1351 out:
1352         sqlite3_reset(stmt);
1353         sqlite3_clear_bindings(stmt);
1354         sqlite3_finalize(stmt);
1355         return ret;
1356 }
1357
1358 static inline void db_create_table(void)
1359 {
1360         int ret;
1361         begin_transaction();
1362
1363         ret = db_create_pkgmap();
1364         if (ret < 0) {
1365                 rollback_transaction();
1366                 return;
1367         }
1368
1369         ret = db_create_provider();
1370         if (ret < 0) {
1371                 rollback_transaction();
1372                 return;
1373         }
1374
1375         ret = db_create_client();
1376         if (ret < 0) {
1377                 rollback_transaction();
1378                 return;
1379         }
1380
1381         ret = db_create_i18n();
1382         if (ret < 0) {
1383                 rollback_transaction();
1384                 return;
1385         }
1386
1387         ret = db_create_box_size();
1388         if (ret < 0) {
1389                 rollback_transaction();
1390                 return;
1391         }
1392
1393         ret = db_create_group();
1394         if (ret < 0) {
1395                 rollback_transaction();
1396                 return;
1397         }
1398
1399         ret = db_create_option();
1400         if (ret < 0) {
1401                 rollback_transaction();
1402                 return;
1403         }
1404
1405         ret = db_create_groupmap();
1406         if (ret < 0) {
1407                 rollback_transaction();
1408                 return;
1409         }
1410
1411         commit_transaction();
1412 }
1413
1414 static inline int db_init(void)
1415 {
1416         int ret;
1417         struct stat stat;
1418
1419         ret = db_util_open(s_info.dbfile, &s_info.handle, DB_UTIL_REGISTER_HOOK_METHOD);
1420         if (ret != SQLITE_OK) {
1421                 ErrPrint("Failed to open a DB\n");
1422                 return -EIO;
1423         }
1424
1425         if (lstat(s_info.dbfile, &stat) < 0) {
1426                 ErrPrint("%s\n", strerror(errno));
1427                 db_util_close(s_info.handle);
1428                 s_info.handle = NULL;
1429                 return -EIO;
1430         }
1431
1432         if (!S_ISREG(stat.st_mode)) {
1433                 ErrPrint("Invalid file\n");
1434                 db_util_close(s_info.handle);
1435                 s_info.handle = NULL;
1436                 return -EINVAL;
1437         }
1438
1439         if (!stat.st_size)
1440                 db_create_table();
1441
1442         return 0;
1443 }
1444
1445 static inline int db_fini(void)
1446 {
1447         if (!s_info.handle)
1448                 return 0;
1449
1450         db_util_close(s_info.handle);
1451         s_info.handle = NULL;
1452
1453         return 0;
1454 }
1455
1456 static inline int validate_pkgid(const char *appid, const char *pkgid)
1457 {
1458         /* Just return 1 Always */
1459         return 1 || !strncmp(appid, pkgid, strlen(appid));
1460 }
1461
1462 static inline int livebox_destroy(struct livebox *livebox)
1463 {
1464         struct dlist *l;
1465         struct dlist *n;
1466         struct i18n *i18n;
1467         struct group *group;
1468         struct option *option;
1469         struct dlist *il;
1470         struct dlist *in;
1471
1472         xmlFree(livebox->auto_launch);
1473         xmlFree(livebox->pkgid);
1474         xmlFree(livebox->abi);
1475         xmlFree(livebox->name);
1476         xmlFree(livebox->icon);
1477         xmlFree(livebox->lb_src);
1478         xmlFree(livebox->lb_group);
1479         xmlFree(livebox->pd_src);
1480         xmlFree(livebox->pd_group);
1481         xmlFree(livebox->pd_size);
1482         xmlFree(livebox->libexec);
1483         xmlFree(livebox->script);
1484         xmlFree(livebox->period);
1485         xmlFree(livebox->content);
1486         xmlFree(livebox->setup);
1487         xmlFree(livebox->preview[0]); /* 1x1 */
1488         xmlFree(livebox->preview[1]); /* 2x1 */
1489         xmlFree(livebox->preview[2]); /* 2x2 */
1490         xmlFree(livebox->preview[3]); /* 4x1 */
1491         xmlFree(livebox->preview[4]); /* 4x2 */
1492         xmlFree(livebox->preview[5]); /* 4x3 */
1493         xmlFree(livebox->preview[6]); /* 4x4 */
1494
1495         dlist_foreach_safe(livebox->i18n_list, l, n, i18n) {
1496                 livebox->i18n_list = dlist_remove(livebox->i18n_list, l);
1497                 xmlFree(i18n->name);
1498                 xmlFree(i18n->icon);
1499                 xmlFree(i18n->lang);
1500                 free(i18n);
1501         }
1502
1503         dlist_foreach_safe(livebox->group_list, l, n, group) {
1504                 livebox->group_list = dlist_remove(livebox->group_list, l);
1505                 DbgPrint("Release %s/%s\n", group->cluster, group->category);
1506
1507                 if (group->ctx_item) {
1508                         dlist_foreach_safe(group->option_list, il, in, option) {
1509                                 group->option_list = dlist_remove(group->option_list, il);
1510                                 DbgPrint("Release option %s(%s)\n", option->key, option->value);
1511                                 xmlFree(option->key);
1512                                 xmlFree(option->value);
1513                                 free(option);
1514                         }
1515                         xmlFree(group->ctx_item);
1516                 }
1517
1518                 xmlFree(group->cluster);
1519                 xmlFree(group->category);
1520                 free(group);
1521         }
1522
1523         free(livebox);
1524         return 0;
1525 }
1526
1527 static inline void update_i18n_name(struct livebox *livebox, xmlNodePtr node)
1528 {
1529         struct i18n *i18n;
1530         struct dlist *l;
1531         xmlChar *lang;
1532         xmlChar *name;
1533
1534         name = xmlNodeGetContent(node);
1535         if (!name) {
1536                 ErrPrint("Invalid tag\n");
1537                 return;
1538         }
1539
1540         lang = xmlNodeGetLang(node);
1541         if (!lang) {
1542                 if (livebox->name) {
1543                         DbgPrint("Override default name: %s\n", livebox->name);
1544                         xmlFree(livebox->name);
1545                 }
1546
1547                 livebox->name = name;
1548                 return;
1549         }
1550
1551         dlist_foreach(livebox->i18n_list, l, i18n) {
1552                 if (!xmlStrcasecmp(i18n->lang, lang)) {
1553                         if (i18n->name) {
1554                                 DbgPrint("Override name: %s\n", i18n->name);
1555                                 xmlFree(i18n->name);
1556                         }
1557
1558                         i18n->name = name;
1559                         return;
1560                 }
1561         }
1562
1563         i18n = calloc(1, sizeof(*i18n));
1564         if (!i18n) {
1565                 ErrPrint("Heap: %s\n", strerror(errno));
1566                 xmlFree(name);
1567                 xmlFree(lang);
1568                 return;
1569         }
1570
1571         i18n->name = name;
1572         i18n->lang = lang;
1573         DbgPrint("Label[%s] - [%s] added\n", i18n->lang, i18n->name);
1574         livebox->i18n_list = dlist_append(livebox->i18n_list, i18n);
1575 }
1576
1577 static inline void update_i18n_icon(struct livebox *livebox, xmlNodePtr node)
1578 {
1579         struct i18n *i18n;
1580         struct dlist *l;
1581         xmlChar *lang;
1582         xmlChar *icon;
1583
1584         icon = xmlNodeGetContent(node);
1585         if (!icon) {
1586                 ErrPrint("Invalid tag\n");
1587                 return;
1588         }
1589
1590         lang = xmlNodeGetLang(node);
1591         if (!lang) {
1592                 if (livebox->icon) {
1593                         DbgPrint("Override default icon: %s\n", livebox->icon);
1594                         xmlFree(livebox->icon);
1595                 }
1596
1597                 livebox->icon = icon;
1598                 return;
1599         }
1600
1601         dlist_foreach(livebox->i18n_list, l, i18n) {
1602                 if (!xmlStrcasecmp(i18n->lang, lang)) {
1603                         if (i18n->icon) {
1604                                 DbgPrint("Override icon %s for %s\n", i18n->icon, i18n->name);
1605                                 xmlFree(i18n->icon);
1606                         }
1607
1608                         i18n->icon = icon;
1609                         return;
1610                 }
1611         }
1612
1613         i18n = calloc(1, sizeof(*i18n));
1614         if (!i18n) {
1615                 ErrPrint("Heap: %s\n", strerror(errno));
1616                 xmlFree(icon);
1617                 xmlFree(lang);
1618                 return;
1619         }
1620
1621         i18n->icon = icon;
1622         i18n->lang = lang;
1623         DbgPrint("Icon[%s] - [%s] added\n", i18n->lang, i18n->icon);
1624         livebox->i18n_list = dlist_append(livebox->i18n_list, i18n);
1625 }
1626
1627 static inline void update_launch(struct livebox *livebox, xmlNodePtr node)
1628 {
1629         xmlChar *launch;
1630         launch = xmlNodeGetContent(node);
1631         if (!launch) {
1632                 DbgPrint("Has no launch\n");
1633                 return;
1634         }
1635
1636         livebox->auto_launch = xmlStrdup(launch);
1637         if (!livebox->auto_launch) {
1638                 ErrPrint("Failed to duplicate string: %s\n", (char *)launch);
1639                 return;
1640         }
1641 }
1642
1643 static inline void update_setup(struct livebox *livebox, xmlNodePtr node)
1644 {
1645         xmlChar *setup;
1646         setup = xmlNodeGetContent(node);
1647         if (!setup) {
1648                 DbgPrint("Has no setup\n");
1649                 return;
1650         }
1651
1652         livebox->setup = xmlStrdup(setup);
1653         if (!livebox->setup) {
1654                 ErrPrint("Failed to duplicate string: %s\n", (char *)setup);
1655                 return;
1656         }
1657 }
1658
1659 static inline void update_content(struct livebox *livebox, xmlNodePtr node)
1660 {
1661         xmlChar *content;
1662         content = xmlNodeGetContent(node);
1663         if (!content) {
1664                 DbgPrint("Has no content\n");
1665                 return;
1666         }
1667
1668         livebox->content = xmlStrdup(content);
1669         if (!livebox->content) {
1670                 ErrPrint("Failed to duplicate string: %s\n", (char *)content);
1671                 return;
1672         }
1673 }
1674
1675 static inline void update_box(struct livebox *livebox, xmlNodePtr node)
1676 {
1677         if (!xmlHasProp(node, (const xmlChar *)"type")) {
1678                 livebox->lb_type = LB_TYPE_FILE;
1679         } else {
1680                 xmlChar *type;
1681
1682                 type = xmlGetProp(node, (const xmlChar *)"type");
1683                 if (!type) {
1684                         ErrPrint("Type is NIL\n");
1685                         livebox->lb_type = LB_TYPE_FILE;
1686                 } else {
1687                         if (!xmlStrcasecmp(type, (const xmlChar *)"text"))
1688                                 livebox->lb_type = LB_TYPE_TEXT;
1689                         else if (!xmlStrcasecmp(type, (const xmlChar *)"buffer"))
1690                                 livebox->lb_type = LB_TYPE_BUFFER;
1691                         else if (!xmlStrcasecmp(type, (const xmlChar *)"script"))
1692                                 livebox->lb_type = LB_TYPE_SCRIPT;
1693                         else /* Default */
1694                                 livebox->lb_type = LB_TYPE_FILE;
1695
1696                         xmlFree(type);
1697                 }
1698         }
1699
1700         if (!xmlHasProp(node, (const xmlChar *)"mouse_event")) {
1701                 livebox->mouse_event = 0;
1702         } else {
1703                 xmlChar *mouse_event;
1704
1705                 mouse_event = xmlGetProp(node, (const xmlChar *)"mouse_event");
1706                 if (!mouse_event) {
1707                         ErrPrint("mouse_event is NIL\n");
1708                         livebox->mouse_event = 0;
1709                 } else {
1710                         livebox->mouse_event = !xmlStrcasecmp(mouse_event, (const xmlChar *)"true");
1711                         xmlFree(mouse_event);
1712                 }
1713         }
1714
1715         for (node = node->children; node; node = node->next) {
1716                 if (!xmlStrcasecmp(node->name, (const xmlChar *)"size")) {
1717                         xmlChar *size;
1718
1719                         size = xmlNodeGetContent(node);
1720                         if (!size) {
1721                                 ErrPrint("Invalid size tag\n");
1722                                 continue;
1723                         }
1724
1725                         if (!xmlStrcasecmp(size, (const xmlChar *)"1x1")) {
1726                                 livebox->size_list |= LB_SIZE_1x1;
1727                                 if (xmlHasProp(node, (const xmlChar *)"preview")) {
1728                                         livebox->preview[0] = xmlGetProp(node, (const xmlChar *)"preview");
1729                                 }
1730                         } else if (!xmlStrcasecmp(size, (const xmlChar *)"2x1")) {
1731                                 livebox->size_list |= LB_SIZE_2x1;
1732                                 if (xmlHasProp(node, (const xmlChar *)"preview")) {
1733                                         livebox->preview[1] = xmlGetProp(node, (const xmlChar *)"preview");
1734                                 }
1735                         } else if (!xmlStrcasecmp(size, (const xmlChar *)"2x2")) {
1736                                 livebox->size_list |= LB_SIZE_2x2;
1737                                 if (xmlHasProp(node, (const xmlChar *)"preview")) {
1738                                         livebox->preview[2] = xmlGetProp(node, (const xmlChar *)"preview");
1739                                 }
1740                         } else if (!xmlStrcasecmp(size, (const xmlChar *)"4x1")) {
1741                                 livebox->size_list |= LB_SIZE_4x1;
1742                                 if (xmlHasProp(node, (const xmlChar *)"preview")) {
1743                                         livebox->preview[3] = xmlGetProp(node, (const xmlChar *)"preview");
1744                                 }
1745                         } else if (!xmlStrcasecmp(size, (const xmlChar *)"4x2")) {
1746                                 livebox->size_list |= LB_SIZE_4x2;
1747                                 if (xmlHasProp(node, (const xmlChar *)"preview")) {
1748                                         livebox->preview[4] = xmlGetProp(node, (const xmlChar *)"preview");
1749                                 }
1750                         } else if (!xmlStrcasecmp(size, (const xmlChar *)"4x3")) {
1751                                 livebox->size_list |= LB_SIZE_4x3;
1752                                 if (xmlHasProp(node, (const xmlChar *)"preview")) {
1753                                         livebox->preview[5] = xmlGetProp(node, (const xmlChar *)"preview");
1754                                 }
1755                         } else if (!xmlStrcasecmp(size, (const xmlChar *)"4x4")) {
1756                                 livebox->size_list |= LB_SIZE_4x4;
1757                                 if (xmlHasProp(node, (const xmlChar *)"preview")) {
1758                                         livebox->preview[6] = xmlGetProp(node, (const xmlChar *)"preview");
1759                                 }
1760                         } else {
1761                                 ErrPrint("Invalid size tag (%s)\n", size);
1762                         }
1763
1764                         xmlFree(size);
1765                 } else if (!xmlStrcasecmp(node->name, (const xmlChar *)"script")) {
1766                         xmlChar *src;
1767
1768                         if (!xmlHasProp(node, (const xmlChar *)"src")) {
1769                                 ErrPrint("Invalid script tag. has no src\n");
1770                                 continue;
1771                         }
1772
1773                         src = xmlGetProp(node, (const xmlChar *)"src");
1774                         if (!src) {
1775                                 ErrPrint("Invalid script tag. src is NIL\n");
1776                                 continue;
1777                         }
1778
1779                         if (livebox->lb_src) {
1780                                 DbgPrint("Override lb src: %s\n", livebox->lb_src);
1781                                 xmlFree(livebox->lb_src);
1782                         }
1783
1784                         livebox->lb_src = src;
1785
1786                         if (xmlHasProp(node, (const xmlChar *)"group")) {
1787                                 xmlChar *group;
1788                                 group = xmlGetProp(node, (const xmlChar *)"group");
1789                                 if (!group) {
1790                                         ErrPrint("Group is NIL\n");
1791                                 } else {
1792                                         if (livebox->lb_group) {
1793                                                 DbgPrint("Override lb group: %s\n", livebox->lb_group);
1794                                                 xmlFree(livebox->lb_group);
1795                                         }
1796
1797                                         livebox->lb_group = group;
1798                                 }
1799                         }
1800                 }
1801         }
1802 }
1803
1804 static inline void update_group(struct livebox *livebox, xmlNodePtr node)
1805 {
1806         xmlNodePtr cluster;
1807         xmlNodePtr category;
1808         xmlNodePtr option_item;
1809         xmlChar *cluster_name;
1810         xmlChar *category_name;
1811         xmlChar *ctx_item;
1812
1813         xmlChar *key;
1814         xmlChar *value;
1815
1816         struct group *group;
1817         struct option *option;
1818
1819         cluster = node;
1820         for (cluster = cluster->children; cluster; cluster = cluster->next) {
1821                 if (xmlStrcasecmp(cluster->name, (const xmlChar *)"cluster")) {
1822                         DbgPrint("Skip: %s\n", cluster->name);
1823                         continue;
1824                 }
1825
1826                 if (!xmlHasProp(cluster, (const xmlChar *)"name")) {
1827                         ErrPrint("Invalid cluster, has no name\n");
1828                         continue;
1829                 }
1830
1831                 cluster_name = xmlGetProp(cluster, (const xmlChar *)"name");
1832                 if (!cluster_name) {
1833                         ErrPrint("Invalid cluster name. NIL\n");
1834                         continue;
1835                 }
1836
1837                 for (category = cluster->children; category; category = category->next) {
1838                         if (xmlStrcasecmp(category->name, (const xmlChar *)"category")) {
1839                                 DbgPrint("Skip: %s\n", category->name);
1840                                 continue;
1841                         }
1842
1843                         if (!xmlHasProp(category, (const xmlChar *)"name")) {
1844                                 ErrPrint("Invalid category, has no name\n");
1845                                 continue;
1846                         }
1847
1848                         category_name = xmlGetProp(category, (const xmlChar *)"name");
1849                         if (!category_name) {
1850                                 ErrPrint("Invalid category name. NIL\n");
1851                                 continue;
1852                         }
1853
1854                         group = calloc(1, sizeof(*group));
1855                         if (!group) {
1856                                 ErrPrint("Heap: %s\n", strerror(errno));
1857                                 xmlFree(category_name);
1858                                 continue;
1859                         }
1860
1861                         group->cluster = xmlStrdup(cluster_name);
1862                         if (!group->cluster) {
1863                                 ErrPrint("Heap: %s\n", strerror(errno));
1864                                 xmlFree(category_name);
1865                                 free(group);
1866                                 continue;
1867                         }
1868
1869                         group->category = category_name;
1870                         livebox->group_list = dlist_append(livebox->group_list, group);
1871
1872                         if (!xmlHasProp(category, (const xmlChar *)"context")) {
1873                                 DbgPrint("%s, %s has no ctx info\n", group->cluster, group->category);
1874                                 continue;
1875                         }
1876
1877                         ctx_item = xmlGetProp(category, (const xmlChar *)"context");
1878                         if (!ctx_item) {
1879                                 ErrPrint("Failed to get context ID (%s, %s)\n", group->cluster, group->category);
1880                                 continue;
1881                         }
1882
1883                         group->ctx_item = ctx_item;
1884                         DbgPrint("Build group item: %s - %s - %s\n", group->cluster, group->category, group->ctx_item);
1885
1886                         for (option_item = category->children; option_item; option_item = option_item->next) {
1887                                 if (xmlStrcasecmp(option_item->name, (const xmlChar *)"option")) {
1888                                         DbgPrint("Skip: %s\n", option_item->name);
1889                                         continue;
1890                                 }
1891
1892                                 if (!xmlHasProp(option_item, (const xmlChar *)"key")) {
1893                                         ErrPrint("Invalid option, has no key\n");
1894                                         continue;
1895                                 }
1896
1897                                 if (!xmlHasProp(option_item, (const xmlChar *)"value")) {
1898                                         ErrPrint("Invalid option, has no value\n");
1899                                         continue;
1900                                 }
1901
1902                                 key = xmlGetProp(option_item, (const xmlChar *)"key");
1903                                 if (!key) {
1904                                         ErrPrint("Invalid key. NIL\n");
1905                                         continue;
1906                                 }
1907
1908                                 value = xmlGetProp(option_item, (const xmlChar *)"value");
1909                                 if (!value) {
1910                                         ErrPrint("Invalid valid. NIL\n");
1911                                         xmlFree(key);
1912                                         continue;
1913                                 }
1914
1915                                 option = calloc(1, sizeof(*option));
1916                                 if (!option) {
1917                                         ErrPrint("Heap: %s\n", strerror(errno));
1918                                         xmlFree(key);
1919                                         xmlFree(value);
1920                                         continue;
1921                                 }
1922
1923                                 option->key = key;
1924                                 option->value = value;
1925
1926                                 group->option_list = dlist_append(group->option_list, option);
1927                         }
1928                 }
1929
1930                 xmlFree(cluster_name);
1931         }
1932 }
1933
1934 static inline void update_pd(struct livebox *livebox, xmlNodePtr node)
1935 {
1936         if (!xmlHasProp(node, (const xmlChar *)"type")) {
1937                 livebox->pd_type = PD_TYPE_SCRIPT;
1938         } else {
1939                 xmlChar *type;
1940
1941                 type = xmlGetProp(node, (const xmlChar *)"type");
1942                 if (!type) {
1943                         ErrPrint("type is NIL\n");
1944                         return;
1945                 }
1946
1947                 if (!xmlStrcasecmp(type, (const xmlChar *)"text"))
1948                         livebox->pd_type = PD_TYPE_TEXT;
1949                 else if (!xmlStrcasecmp(type, (const xmlChar *)"buffer"))
1950                         livebox->pd_type = PD_TYPE_BUFFER;
1951                 else
1952                         livebox->pd_type = PD_TYPE_SCRIPT;
1953
1954                 xmlFree(type);
1955         }
1956
1957         for (node = node->children; node; node = node->next) {
1958                 if (!xmlStrcasecmp(node->name, (const xmlChar *)"size")) {
1959                         xmlChar *size;
1960
1961                         size = xmlNodeGetContent(node);
1962                         if (!size) {
1963                                 ErrPrint("Invalid size tag\n");
1964                                 continue;
1965                         }
1966
1967                         if (livebox->pd_size) {
1968                                 DbgPrint("Override pd size: %s\n", livebox->pd_size);
1969                                 xmlFree(livebox->pd_size);
1970                         }
1971                         livebox->pd_size = size;
1972                 } else if (!xmlStrcasecmp(node->name, (const xmlChar *)"script")) {
1973                         xmlChar *src;
1974
1975                         if (!xmlHasProp(node, (const xmlChar *)"src")) {
1976                                 ErrPrint("Invalid script tag, has no src\n");
1977                                 continue;
1978                         }
1979
1980                         src = xmlGetProp(node, (const xmlChar *)"src");
1981                         if (!src) {
1982                                 ErrPrint("src is NIL\n");
1983                                 continue;
1984                         }
1985
1986                         if (livebox->pd_src) {
1987                                 DbgPrint("Overide PD src: %s\n", livebox->pd_src);
1988                                 xmlFree(livebox->pd_src);
1989                         }
1990
1991                         livebox->pd_src = src;
1992
1993                         if (xmlHasProp(node, (const xmlChar *)"group")) {
1994                                 xmlChar *group;
1995                                 group = xmlGetProp(node, (const xmlChar *)"group");
1996                                 if (!group) {
1997                                         ErrPrint("Group is NIL\n");
1998                                 } else {
1999                                         if (livebox->pd_group) {
2000                                                 DbgPrint("Override PD group : %s\n", livebox->pd_group);
2001                                                 xmlFree(livebox->pd_group);
2002                                         }
2003
2004                                         livebox->pd_group = group;
2005                                 }
2006                         }
2007                 }
2008         }
2009 }
2010
2011 static inline int db_insert_livebox(struct livebox *livebox, const char *appid)
2012 {
2013         struct dlist *l;
2014         struct dlist *il;
2015         struct i18n *i18n;
2016         struct group *group;
2017         int ret;
2018         int id;
2019         struct option *option;
2020
2021         begin_transaction();
2022         ret = db_insert_pkgmap(appid, (char *)livebox->pkgid, livebox->primary);
2023         if (ret < 0)
2024                 goto errout;
2025
2026         ret = db_insert_provider(livebox);
2027         if (ret < 0)
2028                 goto errout;
2029
2030         ret = db_insert_client(livebox);
2031         if (ret < 0)
2032                 goto errout;
2033
2034         dlist_foreach(livebox->i18n_list, l, i18n) {
2035                 ret = db_insert_i18n((char *)livebox->pkgid, (char *)i18n->lang, (char *)i18n->name, (char *)i18n->icon);
2036                 if (ret < 0)
2037                         goto errout;
2038         }
2039
2040         if (livebox->size_list & LB_SIZE_1x1) {
2041                 ret = db_insert_box_size((char *)livebox->pkgid, LB_SIZE_1x1, (char *)livebox->preview[0]);
2042                 if (ret < 0)
2043                         goto errout;
2044         }
2045
2046         if (livebox->size_list & LB_SIZE_2x1) {
2047                 ret = db_insert_box_size((char *)livebox->pkgid, LB_SIZE_2x1, (char *)livebox->preview[1]);
2048                 if (ret < 0)
2049                         goto errout;
2050         }
2051
2052         if (livebox->size_list & LB_SIZE_2x2) {
2053                 ret = db_insert_box_size((char *)livebox->pkgid, LB_SIZE_2x2, (char *)livebox->preview[2]);
2054                 if (ret < 0)
2055                         goto errout;
2056         }
2057
2058         if (livebox->size_list & LB_SIZE_4x1) {
2059                 ret = db_insert_box_size((char *)livebox->pkgid, LB_SIZE_4x1, (char *)livebox->preview[3]);
2060                 if (ret < 0)
2061                         goto errout;
2062         }
2063
2064         if (livebox->size_list & LB_SIZE_4x2) {
2065                 ret = db_insert_box_size((char *)livebox->pkgid, LB_SIZE_4x2, (char *)livebox->preview[4]);
2066                 if (ret < 0)
2067                         goto errout;
2068         }
2069
2070         if (livebox->size_list & LB_SIZE_4x3) {
2071                 ret = db_insert_box_size((char *)livebox->pkgid, LB_SIZE_4x3, (char *)livebox->preview[5]);
2072                 if (ret < 0)
2073                         goto errout;
2074         }
2075
2076         if (livebox->size_list & LB_SIZE_4x4) {
2077                 ret = db_insert_box_size((char *)livebox->pkgid, LB_SIZE_4x4, (char *)livebox->preview[6]);
2078                 if (ret < 0)
2079                         goto errout;
2080         }
2081
2082         dlist_foreach(livebox->group_list, l, group) {
2083                 /* group ID "id" */
2084                 id = db_get_group_id((char *)group->cluster, (char *)group->category);
2085                 if (id < 0) {
2086                         int ret;
2087                         
2088                         ret = db_insert_group((char *)livebox->pkgid, (char *)group->cluster, (char *)group->category);
2089                         if (ret < 0) {
2090                                 ErrPrint("[%s]-[%s] is not exists\n", group->cluster, group->category);
2091                                 continue;
2092                         }
2093
2094                         DbgPrint("New group name is built - %s/%s\n", group->cluster, group->category);
2095                         id = db_get_group_id((char *)group->cluster, (char *)group->category);
2096                         if (id < 0) {
2097                                 ErrPrint("Failed to get group id for %s/%s\n", group->cluster, group->category);
2098                                 continue;
2099                         }
2100                 }
2101
2102                 if (!group->ctx_item) {
2103                         DbgPrint("%s, %s - has no ctx info\n", group->cluster, group->category);
2104                         continue;
2105                 }
2106
2107                 ret = db_insert_groupmap(id, (char *)livebox->pkgid, (char *)group->ctx_item);
2108                 if (ret < 0)
2109                         goto errout;
2110
2111                 /* REUSE "id" from here , option ID */
2112                 id = db_get_option_id(id, (char *)livebox->pkgid, (char *)group->ctx_item);
2113                 if (id < 0)
2114                         goto errout;
2115
2116                 dlist_foreach(group->option_list, il, option) {
2117                         ret = db_insert_option((char *)livebox->pkgid, id, (char *)option->key, (char *)option->value);
2118                         if (ret < 0)
2119                                 goto errout;
2120                 }
2121         }
2122
2123         commit_transaction();
2124         livebox_destroy(livebox);
2125         return 0;
2126
2127 errout:
2128         ErrPrint("ROLLBACK\n");
2129         rollback_transaction();
2130         livebox_destroy(livebox);
2131         return ret;
2132 }
2133
2134 static inline int do_install(xmlNodePtr node, const char *appid)
2135 {
2136         struct livebox *livebox;
2137         xmlChar *pkgid;
2138         xmlChar *tmp;
2139
2140         if (!xmlHasProp(node, (const xmlChar *)"appid")) {
2141                 ErrPrint("Missing appid\n");
2142                 return -EINVAL;
2143         }
2144
2145         pkgid = xmlGetProp(node, (const xmlChar *)"appid");
2146         if (!pkgid || !validate_pkgid(appid, (char *)pkgid)) {
2147                 ErrPrint("Invalid appid\n");
2148                 xmlFree(pkgid);
2149                 return -EINVAL;
2150         }
2151
2152         DbgPrint("appid: %s\n", (char *)pkgid);
2153
2154         livebox = calloc(1, sizeof(*livebox));
2155         if (!livebox) {
2156                 ErrPrint("Heap: %s\n", strerror(errno));
2157                 xmlFree(pkgid);
2158                 return -ENOMEM;
2159         }
2160
2161         livebox->pkgid = pkgid;
2162
2163         if (xmlHasProp(node, (const xmlChar *)"primary")) {
2164                 tmp = xmlGetProp(node, (const xmlChar *)"primary");
2165                 livebox->primary = !xmlStrcasecmp(tmp, (const xmlChar *)"true");
2166                 xmlFree(tmp);
2167         }
2168
2169         if (xmlHasProp(node, (const xmlChar *)"script")) {
2170                 livebox->script = xmlGetProp(node, (const xmlChar *)"script");
2171                 if (!livebox->script)
2172                         ErrPrint("script is NIL\n");
2173         }
2174
2175         if (xmlHasProp(node, (const xmlChar *)"nodisplay")) {
2176                 tmp = xmlGetProp(node, (const xmlChar *)"nodisplay");
2177                 livebox->nodisplay = tmp && !xmlStrcasecmp(tmp, (const xmlChar *)"true");
2178                 xmlFree(tmp);
2179         }
2180
2181         if (xmlHasProp(node, (const xmlChar *)"pinup")) {
2182                 tmp = xmlGetProp(node, (const xmlChar *)"pinup");
2183                 livebox->pinup = tmp && !xmlStrcasecmp(tmp, (const xmlChar *)"true");
2184                 xmlFree(tmp);
2185         }
2186
2187         if (xmlHasProp(node, (const xmlChar *)"period")) {
2188                 livebox->period = xmlGetProp(node, (const xmlChar *)"period");
2189                 if (!livebox->period)
2190                         ErrPrint("Period is NIL\n");
2191         }
2192
2193         if (xmlHasProp(node, (const xmlChar *)"timeout")) {
2194                 livebox->timeout = xmlGetProp(node, (const xmlChar *)"timeout");
2195                 if (!livebox->timeout)
2196                         ErrPrint("Timeout is NIL\n");
2197         }
2198
2199         if (xmlHasProp(node, (const xmlChar *)"secured")) {
2200                 tmp = xmlGetProp(node, (const xmlChar *)"secured");
2201                 livebox->secured = tmp && !xmlStrcasecmp(tmp, (const xmlChar *)"true");
2202                 xmlFree(tmp);
2203         }
2204
2205         if (xmlHasProp(node, (const xmlChar *)"network")) {
2206                 tmp = xmlGetProp(node, (const xmlChar *)"network");
2207                 livebox->network = tmp && !xmlStrcasecmp(tmp, (const xmlChar *)"true");
2208                 xmlFree(tmp);
2209         }
2210
2211         if (xmlHasProp(node, (const xmlChar *)"abi")) {
2212                 livebox->abi = xmlGetProp(node, (const xmlChar *)"abi");
2213                 if (!livebox->abi) {
2214                         ErrPrint("ABI is NIL\n");
2215                         livebox_destroy(livebox);
2216                         return -EFAULT;
2217                 }
2218         } else {
2219                 livebox->abi = xmlStrdup((const xmlChar *)"c");
2220                 if (!livebox->abi) {
2221                         ErrPrint("Heap: %s\n", strerror(errno));
2222                         livebox_destroy(livebox);
2223                         return -ENOMEM;
2224                 }
2225         }
2226
2227         if (xmlHasProp(node, (const xmlChar *)"libexec")) {
2228                 livebox->libexec = xmlGetProp(node, (const xmlChar *)"libexec");
2229                 if (!livebox->libexec) {
2230                         ErrPrint("libexec is NIL\n");
2231                         livebox_destroy(livebox);
2232                         return -EFAULT;
2233                 }
2234         } else if (!xmlStrcasecmp(livebox->abi, (const xmlChar *)"c") || !xmlStrcasecmp(livebox->abi, (const xmlChar *)"cpp")) {
2235                 char *filename;
2236                 int len;
2237
2238                 len = strlen((char *)livebox->pkgid) + strlen("/libexec/liblive-.so") + 1;
2239
2240                 filename = malloc(len);
2241                 if (!filename) {
2242                         livebox_destroy(livebox);
2243                         return -ENOMEM;
2244                 }
2245
2246                 snprintf(filename, len, "/libexec/liblive-%s.so", livebox->pkgid);
2247                 livebox->libexec = xmlStrdup((xmlChar *)filename);
2248                 DbgPrint("Use the default libexec: %s\n", filename);
2249                 free(filename);
2250
2251                 if (!livebox->libexec) {
2252                         livebox_destroy(livebox);
2253                         return -ENOMEM;
2254                 }
2255         }
2256
2257         for (node = node->children; node; node = node->next) {
2258                 if (!xmlStrcmp(node->name, (const xmlChar *)"text"))
2259                         continue;
2260
2261                 DbgPrint("Nodename: %s\n", node->name);
2262                 if (!xmlStrcasecmp(node->name, (const xmlChar *)"label")) {
2263                         update_i18n_name(livebox, node);
2264                         continue;
2265                 }
2266
2267                 if (!xmlStrcasecmp(node->name, (const xmlChar *)"icon")) {
2268                         update_i18n_icon(livebox, node);
2269                         continue;
2270                 }
2271
2272                 if (!xmlStrcasecmp(node->name, (const xmlChar *)"box")) {
2273                         update_box(livebox, node);
2274                         continue;
2275                 }
2276
2277                 if (!xmlStrcasecmp(node->name, (const xmlChar *)"pd")) {
2278                         update_pd(livebox, node);
2279                         continue;
2280                 }
2281
2282                 if (!xmlStrcasecmp(node->name, (const xmlChar *)"group")) {
2283                         update_group(livebox, node);
2284                         continue;
2285                 }
2286
2287                 if (!xmlStrcasecmp(node->name, (const xmlChar *)"content")) {
2288                         update_content(livebox, node);
2289                         continue;
2290                 }
2291
2292                 if (!xmlStrcasecmp(node->name, (const xmlChar *)"setup")) {
2293                         update_setup(livebox, node);
2294                         continue;
2295                 }
2296
2297                 if (!xmlStrcasecmp(node->name, (const xmlChar *)"launch")) {
2298                         update_launch(livebox, node);
2299                         continue;
2300                 }
2301         }
2302
2303         return db_insert_livebox(livebox, appid);
2304 }
2305
2306 int PKGMGR_PARSER_PLUGIN_INSTALL(xmlDocPtr docPtr, const char *appid)
2307 {
2308         xmlNodePtr node;
2309         int ret;
2310
2311         if (!s_info.handle) {
2312                 if (db_init() < 0) {
2313                         ErrPrint("Failed to init DB\n");
2314                         return -EIO;
2315                 }
2316         }
2317
2318         node = xmlDocGetRootElement(docPtr);
2319         if (!node) {
2320                 ErrPrint("Invalid document\n");
2321                 return -EINVAL;
2322         }
2323
2324         for (node = node->children; node; node = node->next) {
2325                 DbgPrint("node->name: %s\n", node->name);
2326                 if (!xmlStrcasecmp(node->name, (const xmlChar *)"livebox")) {
2327                         ret = do_install(node, appid);
2328                         DbgPrint("Returns: %d\n", ret);
2329                 }
2330         }
2331
2332         return 0;
2333 }
2334
2335 int PKGMGR_PARSER_PLUGIN_UPGRADE(xmlDocPtr docPtr, const char *appid)
2336 {
2337         xmlNodePtr node;
2338
2339         if (!s_info.handle) {
2340                 if (db_init() < 0) {
2341                         ErrPrint("Failed to init DB\n");
2342                         return -EIO;
2343                 }
2344         }
2345
2346         node = xmlDocGetRootElement(docPtr);
2347         if (!node) {
2348                 ErrPrint("Invalid document\n");
2349                 return -EINVAL;
2350         }
2351
2352         for (node = node->children; node; node = node->next) {
2353                 if (!xmlStrcasecmp(node->name, (const xmlChar *)"livebox"))
2354                         break;
2355         }
2356
2357         if (!node) {
2358                 ErrPrint("Root has no livebox\n");
2359                 return -EINVAL;
2360         }
2361
2362         return 0;
2363 }
2364
2365 static inline int do_uninstall(xmlNodePtr node, const char *appid)
2366 {
2367         xmlChar *pkgid;
2368         int ret;
2369
2370         if (!xmlHasProp(node, (const xmlChar *)"appid")) {
2371                 ErrPrint("Missing appid\n");
2372                 return -EINVAL;
2373         }
2374
2375         pkgid = xmlGetProp(node, (const xmlChar *)"appid");
2376         if (!validate_pkgid(appid, (char *)pkgid)) {
2377                 ErrPrint("Invalid package\n");
2378                 xmlFree(pkgid);
2379                 return -EINVAL;
2380         }
2381
2382         begin_transaction();
2383         ret = db_remove_box_size((char *)pkgid);
2384         if (ret < 0)
2385                 goto errout;
2386
2387         ret = db_remove_i18n((char *)pkgid);
2388         if (ret < 0)
2389                 goto errout;
2390
2391         ret = db_remove_client((char *)pkgid);
2392         if (ret < 0)
2393                 goto errout;
2394
2395         ret = db_remove_provider((char *)pkgid);
2396         if (ret < 0)
2397                 goto errout;
2398
2399         ret = db_remove_option((char *)pkgid);
2400         DbgPrint("Remove option: %d\n", ret);
2401
2402         ret = db_remove_groupmap((char *)pkgid);
2403         DbgPrint("Remove groupmap: %d\n", ret);
2404
2405         ret = db_remove_group((char *)pkgid);
2406         if (ret < 0)
2407                 goto errout;
2408
2409         ret = db_remove_pkgmap((char *)pkgid);
2410         if (ret < 0)
2411                 goto errout;
2412
2413         commit_transaction();
2414         xmlFree(pkgid);
2415
2416         return 0;
2417
2418 errout:
2419         rollback_transaction();
2420         xmlFree(pkgid);
2421         return ret;
2422 }
2423
2424 int PKGMGR_PARSER_PLUGIN_UNINSTALL(xmlDocPtr docPtr, const char *appid)
2425 {
2426         xmlNodePtr node;
2427         int ret;
2428
2429         if (!s_info.handle) {
2430                 if (db_init() < 0) {
2431                         ErrPrint("Failed to init DB\n");
2432                         return -EIO;
2433                 }
2434         }
2435
2436         node = xmlDocGetRootElement(docPtr);
2437         if (!node) {
2438                 ErrPrint("Invalid document\n");
2439                 return -EINVAL;
2440         }
2441
2442         for (node = node->children; node; node = node->next) {
2443                 if (!xmlStrcasecmp(node->name, (const xmlChar *)"livebox")) {
2444                         ret = do_uninstall(node, appid);
2445                         DbgPrint("Returns: %d\n", ret);
2446                 }
2447         }
2448
2449         return 0;
2450 }
2451
2452 /*
2453 int main(int argc, char *argv[])
2454 {
2455         xmlDoc *doc;
2456         xmlNode *root;
2457
2458         if (argc != 2) {
2459                 ErrPRint("Invalid argument: %s XML_FILENAME\n", argv[0]);
2460                 return -EINVAL;
2461         }
2462
2463         doc = xmlReadFile(argv[1], NULL, 0);
2464         if (!doc) {
2465                 ErrPrint("Failed to parse %s\n", argv[1]);
2466                 return -EIO;
2467         }
2468
2469         root = xmlDocGetRootElement(doc);
2470
2471         db_init();
2472         install_shortcut("", root);
2473         db_fini();
2474
2475         xmlFreeDoc(doc);
2476         xmlCleanupParser();
2477         return 0;
2478 }
2479 */
2480
2481 /* End of a file */