Update the project to the newest version.
[framework/appfw/shortcut.git] / pkgmgr_homescreen / 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  * homescreen
44  * +-------+------+------+------+
45  * | appid | icon | name | desc |
46  * +-------+------+------+------|
47  * |   -   |      |      |      |
48  * +-------+------+------+------+
49  * CREATE TABLE homescreen ( appid TEXT PRIMARY KEY NOT NULL, icon TEXT, name TEXT, desc TEXT )
50  *
51  * image list
52  * +-------+----+------------+
53  * | appid | ID | image path |
54  * +-------+----+------------+
55  * |   -   |  - |      -     |
56  * +-------+----+------------+
57  * CREATE TABLE image ( appid TEXT NOT NULL, id INTEGER, path TEXT NOT NULL, FOREIGN KEY(appid) REFERENCES homescreen(appid) )
58  *
59  * description list
60  * +-------+------+------+------+
61  * | appid | lang | desc | name |
62  * +-------+------+------+------+
63  * |   -   |   -  |  -   |      |
64  * +-------+------+------+------+
65  * CREATE TABLE desc ( appid TEXT NOT NULL, lang TEXT NOT NULL, desc NOT NULL, name NOT NULL, FOREIGN KEY(appid) REFERENCES homescreen(appid) )
66  *
67  */
68
69 #if !defined(LIBXML_TREE_ENABLED)
70         #error "LIBXML is not supporting the tree"
71 #endif
72
73 #if defined(LOG_TAG)
74 #undef LOG_TAG
75 #endif
76
77 #define LOG_TAG "pkgmgr_homescreen"
78
79 int errno;
80
81 static struct {
82         const char *dbfile;
83         sqlite3 *handle;
84 } s_info = {
85         .dbfile = "/opt/dbspace/.shortcut_service.db",
86         .handle = NULL,
87 };
88
89 static inline int begin_transaction(void)
90 {
91         sqlite3_stmt *stmt;
92         int ret;
93
94         ret = sqlite3_prepare_v2(s_info.handle, "BEGIN TRANSACTION", -1, &stmt, NULL);
95
96         if (ret != SQLITE_OK) {
97                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
98                 return EXIT_FAILURE;
99         }
100
101         if (sqlite3_step(stmt) != SQLITE_DONE) {
102                 ErrPrint("Failed to do update (%s)\n",
103                                         sqlite3_errmsg(s_info.handle));
104                 sqlite3_finalize(stmt);
105                 return EXIT_FAILURE;
106         }
107
108         sqlite3_finalize(stmt);
109         return EXIT_SUCCESS;
110 }
111
112 static inline int rollback_transaction(void)
113 {
114         int ret;
115         sqlite3_stmt *stmt;
116
117         ret = sqlite3_prepare_v2(s_info.handle, "ROLLBACK TRANSACTION", -1, &stmt, NULL);
118         if (ret != SQLITE_OK) {
119                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
120                 return EXIT_FAILURE;
121         }
122
123         if (sqlite3_step(stmt) != SQLITE_DONE) {
124                 ErrPrint("Failed to do update (%s)\n",
125                                 sqlite3_errmsg(s_info.handle));
126                 sqlite3_finalize(stmt);
127                 return EXIT_FAILURE;
128         }
129
130         sqlite3_finalize(stmt);
131         return EXIT_SUCCESS;
132 }
133
134 static inline int commit_transaction(void)
135 {
136         sqlite3_stmt *stmt;
137         int ret;
138
139         ret = sqlite3_prepare_v2(s_info.handle, "COMMIT TRANSACTION", -1, &stmt, NULL);
140         if (ret != SQLITE_OK) {
141                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
142                 return EXIT_FAILURE;
143         }
144
145         if (sqlite3_step(stmt) != SQLITE_DONE) {
146                 ErrPrint("Failed to do update (%s)\n",
147                                         sqlite3_errmsg(s_info.handle));
148                 sqlite3_finalize(stmt);
149                 return EXIT_FAILURE;
150         }
151
152         sqlite3_finalize(stmt);
153         return EXIT_SUCCESS;
154 }
155
156
157 static inline int db_create_homescreen(void)
158 {
159         int ret;
160         char *err;
161         static const char *ddl = "CREATE TABLE homescreen ( appid TEXT PRIMARY KEY NOT NULL, icon TEXT, name TEXT, desc TEXT )";
162
163         ret = sqlite3_exec(s_info.handle, ddl, NULL, NULL, &err);
164         if (ret != SQLITE_OK) {
165                 ErrPrint("Failed to execute the DDL(%s)\n", err);
166                 return -EIO;
167         }
168
169         if (sqlite3_changes(s_info.handle) == 0)
170                 ErrPrint("No changes to DB\n");
171
172         return 0;
173 }
174
175 static inline int db_insert_homescreen(const char *appid, const char *icon, const char *name, const char *desc)
176 {
177         int ret;
178         static const char *dml = "INSERT INTO homescreen (appid, icon, name, desc) VALUES (?, ?, ?, ?)";
179         sqlite3_stmt *stmt;
180
181         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
182         if (ret != SQLITE_OK) {
183                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
184                 return -EIO;
185         }
186
187         ret = sqlite3_bind_text(stmt, 1, appid, -1, NULL);
188         if (ret != SQLITE_OK) {
189                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
190                 ret = -EIO;
191                 goto out;
192         }
193
194         ret = sqlite3_bind_text(stmt, 2, icon, -1, NULL);
195         if (ret != SQLITE_OK) {
196                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
197                 ret = -EIO;
198                 goto out;
199         }
200
201         ret = sqlite3_bind_text(stmt, 3, name, -1, NULL);
202         if (ret != SQLITE_OK) {
203                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
204                 ret = -EIO;
205                 goto out;
206         }
207
208         ret = sqlite3_bind_text(stmt, 4, desc, -1, NULL);
209         if (ret != SQLITE_OK) {
210                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
211                 ret = -EIO;
212                 goto out;
213         }
214
215         ret = sqlite3_step(stmt);
216         if (ret != SQLITE_DONE) {
217                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
218                 ret = -EIO;
219         }
220
221 out:
222         sqlite3_reset(stmt);
223         sqlite3_clear_bindings(stmt);
224         sqlite3_finalize(stmt);
225         return ret;
226 }
227
228 static inline int db_remove_homescreen(const char *appid)
229 {
230         int ret;
231         static const char *dml = "DELETE FROM homescreen WHERE appid = ?";
232         sqlite3_stmt *stmt;
233
234         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
235         if (ret != SQLITE_OK) {
236                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
237                 ret = -EIO;
238                 return -EIO;
239         }
240
241         ret = sqlite3_bind_text(stmt, 1, appid, -1, NULL);
242         if (ret != SQLITE_OK) {
243                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
244                 ret = -EIO;
245                 goto out;
246         }
247
248         ret = sqlite3_step(stmt);
249         if (ret != SQLITE_OK) {
250                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
251                 ret = -EIO;
252                 goto out;
253         }
254
255         if (sqlite3_changes(s_info.handle) == 0)
256                 DbgPrint("DB has no changes\n");
257
258 out:
259         sqlite3_reset(stmt);
260         sqlite3_clear_bindings(stmt);
261         sqlite3_finalize(stmt);
262         return ret;
263 }
264
265 static inline int db_update_homescreen(const char *appid, const char *icon, const char *name, const char *desc)
266 {
267         int ret;
268         static const char *dml = "UPDATE homescreen SET icon = ?, name = ?, desc = ? WHERE appid = ?";
269         sqlite3_stmt *stmt;
270
271         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
272         if (ret != SQLITE_OK) {
273                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
274                 return -EIO;
275         }
276
277         ret = sqlite3_bind_text(stmt, 1, icon, -1, NULL);
278         if (ret != SQLITE_OK) {
279                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
280                 ret = -EIO;
281                 goto out;
282         }
283
284         ret = sqlite3_bind_text(stmt, 2, name, -1, NULL);
285         if (ret != SQLITE_OK) {
286                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
287                 ret = -EIO;
288                 goto out;
289         }
290
291         ret = sqlite3_bind_text(stmt, 3, desc, -1, NULL);
292         if (ret != SQLITE_OK) {
293                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
294                 ret = -EIO;
295                 goto out;
296         }
297
298         ret = sqlite3_bind_text(stmt, 4, appid, -1, NULL);
299         if (ret != SQLITE_OK) {
300                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
301                 ret = -EIO;
302                 goto out;
303         }
304
305         ret = sqlite3_step(stmt);
306         if (sqlite3_changes(s_info.handle) == 0)
307                 DbgPrint("DB has no changes\n");
308
309 out:
310         sqlite3_reset(stmt);
311         sqlite3_clear_bindings(stmt);
312         sqlite3_finalize(stmt);
313         return ret;
314 }
315
316 static inline int db_create_image(void)
317 {
318         int ret;
319         char *err;
320         static const char *ddl = "CREATE TABLE image ( appid TEXT NOT NULL, id INTEGER, path TEXT NOT NULL, FOREIGN KEY(appid) REFERENCES homescreen(appid) )";
321
322         ret = sqlite3_exec(s_info.handle, ddl, NULL, NULL, &err);
323         if (ret != SQLITE_OK) {
324                 ErrPrint("Failed to execute the DDL(%s)\n", err);
325                 return -EIO;
326         }
327
328         if (sqlite3_changes(s_info.handle) == 0)
329                 ErrPrint("No changes to DB\n");
330
331         return 0;
332 }
333
334 static inline int db_insert_image(const char *appid, int id, const char *path)
335 {
336         int ret;
337         static const char *dml = "INSERT INTO image (appid, id, path) VALUES (?, ?, ?)";
338         sqlite3_stmt *stmt;
339
340         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
341         if (ret != SQLITE_OK) {
342                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
343                 return -EIO;
344         }
345
346         ret = sqlite3_bind_text(stmt, 1, appid, -1, NULL);
347         if (ret != SQLITE_OK) {
348                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
349                 ret = -EIO;
350                 goto out;
351         }
352
353         ret = sqlite3_bind_int(stmt, 2, id);
354         if (ret != SQLITE_OK) {
355                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
356                 ret = -EIO;
357                 goto out;
358         }
359
360         ret = sqlite3_bind_text(stmt, 3, path, -1, NULL);
361         if (ret != SQLITE_OK) {
362                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
363                 ret = -EIO;
364                 goto out;
365         }
366
367         ret = sqlite3_step(stmt);
368         if (ret != SQLITE_DONE) {
369                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
370                 ret = -EIO;
371         }
372
373 out:
374         sqlite3_reset(stmt);
375         sqlite3_clear_bindings(stmt);
376         sqlite3_finalize(stmt);
377         return ret;
378 }
379
380 static inline int db_remove_image(const char *appid)
381 {
382         int ret;
383         static const char *dml = "DELETE FROM image WHERE appid = ?";
384         sqlite3_stmt *stmt;
385
386         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
387         if (ret != SQLITE_OK) {
388                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
389                 ret = -EIO;
390                 goto out;
391         }
392
393         ret = sqlite3_bind_text(stmt, 1, appid, -1, NULL);
394         if (ret != SQLITE_OK) {
395                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
396                 ret = -EIO;
397                 goto out;
398         }
399
400         ret = sqlite3_step(stmt);
401         if (ret != SQLITE_DONE) {
402                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
403                 ret = -EIO;
404         }
405
406         if (sqlite3_changes(s_info.handle) == 0)
407                 DbgPrint("DB has no changes\n");
408
409 out:
410         sqlite3_reset(stmt);
411         sqlite3_clear_bindings(stmt);
412         sqlite3_finalize(stmt);
413         return ret;
414 }
415
416 static inline int db_update_image(const char *appid, int id, const char *path)
417 {
418         int ret;
419         static const char *dml = "UPDATE image SET path = ? WHERE appid = ? AND id = ?";
420         sqlite3_stmt *stmt;
421
422         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
423         if (ret != SQLITE_OK) {
424                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
425                 ret = -EIO;
426                 goto out;
427         }
428
429         ret = sqlite3_bind_text(stmt, 1, path, -1, NULL);
430         if (ret != SQLITE_OK) {
431                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
432                 ret = -EIO;
433                 goto out;
434         }
435
436         ret = sqlite3_bind_text(stmt, 2, appid, -1, NULL);
437         if (ret != SQLITE_OK) {
438                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
439                 ret = -EIO;
440                 goto out;
441         }
442
443         ret = sqlite3_bind_int(stmt, 3, id);
444         if (ret != SQLITE_OK) {
445                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
446                 ret = -EIO;
447                 goto out;
448         }
449
450         ret = sqlite3_step(stmt);
451         if (ret != SQLITE_DONE) {
452                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
453                 ret = -EIO;
454         }
455
456         if (sqlite3_changes(s_info.handle) == 0)
457                 DbgPrint("DB has no changes\n");
458
459 out:
460         sqlite3_reset(stmt);
461         sqlite3_clear_bindings(stmt);
462         sqlite3_finalize(stmt);
463         return ret;
464 }
465
466 static inline int db_create_desc(void)
467 {
468         int ret;
469         char *err;
470         static const char *ddl = "CREATE TABLE desc ( appid TEXT NOT NULL, lang TEXT NOT NULL, desc NOT NULL, name NOT NULL, FOREIGN KEY(appid) REFERENCES homescreen(appid) )";
471
472         ret = sqlite3_exec(s_info.handle, ddl, NULL, NULL, &err);
473         if (ret != SQLITE_OK) {
474                 ErrPrint("Failed to execute the DDL(%s)\n", err);
475                 return -EIO;
476         }
477
478         if (sqlite3_changes(s_info.handle) == 0)
479                 ErrPrint("No changes to DB\n");
480
481         return 0;
482 }
483
484 static inline int db_insert_desc(const char *appid, const char *lang, const char *desc, const char *name)
485 {
486         int ret;
487         static const char *dml = "INSERT INTO desc ( appid, lang, desc, name ) VALUES ( ?, ?, ?, ? )";
488         sqlite3_stmt *stmt;
489
490         if (!appid)
491                 return -EINVAL;
492
493         if (!lang)
494                 return -EINVAL;
495
496         if (!desc)
497                 desc = "";
498
499         if (!name)
500                 name = "";
501
502         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
503         if (ret != SQLITE_OK) {
504                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
505                 return -EIO;
506         }
507
508         ret = sqlite3_bind_text(stmt, 1, appid, -1, NULL);
509         if (ret != SQLITE_DONE) {
510                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
511                 ret = -EIO;
512                 goto out;
513         }
514
515         ret = sqlite3_bind_text(stmt, 2, lang, -1, NULL);
516         if (ret != SQLITE_DONE) {
517                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
518                 ret = -EIO;
519                 goto out;
520         }
521
522         ret = sqlite3_bind_text(stmt, 3, desc, -1, NULL);
523         if (ret != SQLITE_DONE) {
524                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
525                 ret = -EIO;
526                 goto out;
527         }
528
529         ret = sqlite3_bind_text(stmt, 4, name, -1, NULL);
530         if (ret != SQLITE_DONE) {
531                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
532                 ret = -EIO;
533                 goto out;
534         }
535
536         ret = sqlite3_step(stmt);
537         if (ret != SQLITE_DONE) {
538                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
539                 ret = -EIO;
540         }
541
542 out:
543         sqlite3_reset(stmt);
544         sqlite3_clear_bindings(stmt);
545         sqlite3_finalize(stmt);
546         return ret;
547 }
548
549 static inline int db_remove_desc(const char *appid)
550 {
551         int ret;
552         static const char *dml;
553         sqlite3_stmt *stmt;
554
555         if (!appid)
556                 return -EINVAL;
557
558         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
559         if (ret != SQLITE_OK) {
560                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
561                 return -EIO;
562         }
563
564         ret = sqlite3_bind_text(stmt, 1, appid, -1, NULL);
565         if (ret != SQLITE_OK) {
566                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
567                 ret = -EIO;
568                 goto out;
569         }
570
571         ret = 0;
572         if (sqlite3_step(stmt) != SQLITE_DONE) {
573                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
574                 ret = -EIO;
575         }
576
577         if (sqlite3_changes(s_info.handle) == 0)
578                 ErrPrint("DB has no changes\n");
579
580 out:
581         sqlite3_reset(stmt);
582         sqlite3_clear_bindings(stmt);
583         sqlite3_finalize(stmt);
584         return ret;
585 }
586
587 static inline int db_update_desc(const char *appid, const char *lang, const char *desc, const char *name)
588 {
589         int ret;
590         static const char *dml = "UPDATE desc SET desc = ?, name = ? WHERE appid = ? AND lang = ?";
591         sqlite3_stmt *stmt;
592
593         if (!appid)
594                 return -EINVAL;
595
596         if (!lang)
597                 return -EINVAL;
598
599         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
600         if (ret != SQLITE_OK) {
601                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
602                 return -EIO;
603         }
604
605         ret = sqlite3_bind_text(stmt, 1, desc, -1, NULL);
606         if (ret != SQLITE_OK) {
607                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
608                 ret = -EIO;
609                 goto out;
610         }
611
612         ret = sqlite3_bind_text(stmt, 2, name, -1, NULL);
613         if (ret != SQLITE_OK) {
614                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
615                 ret = -EIO;
616                 goto out;
617         }
618
619         ret = sqlite3_bind_text(stmt, 3, appid, -1, NULL);
620         if (ret != SQLITE_OK) {
621                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
622                 ret = -EIO;
623                 goto out;
624         }
625
626         ret = sqlite3_bind_text(stmt, 4, lang, -1, NULL);
627         if (ret != SQLITE_OK) {
628                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
629                 ret = -EIO;
630                 goto out;
631         }
632
633         ret = sqlite3_step(stmt);
634         if (ret != SQLITE_DONE) {
635                 ErrPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
636                 ret = -EIO;
637         }
638
639         if (sqlite3_changes(s_info.handle) == 0)
640                 ErrPrint("DB has no changes\n");
641
642 out:
643         sqlite3_reset(stmt);
644         sqlite3_clear_bindings(stmt);
645         sqlite3_finalize(stmt);
646         return ret;
647 }
648
649 static inline void db_create_table(void)
650 {
651         int ret;
652         begin_transaction();
653
654         ret = db_create_homescreen();
655         if (ret < 0) {
656                 rollback_transaction();
657                 return;
658         }
659                 
660         ret = db_create_image();
661         if (ret < 0) {
662                 rollback_transaction();
663                 return;
664         }
665
666         ret = db_create_desc();
667         if (ret < 0) {
668                 rollback_transaction();
669                 return;
670         }
671
672         commit_transaction();
673 }
674
675 static inline int db_init(void)
676 {
677         int ret;
678         struct stat stat;
679
680         ret = db_util_open(s_info.dbfile, &s_info.handle, DB_UTIL_REGISTER_HOOK_METHOD);
681         if (ret != SQLITE_OK) {
682                 ErrPrint("Failed to open a DB\n");
683                 return -EIO;
684         }
685
686         if (lstat(s_info.dbfile, &stat) < 0) {
687                 ErrPrint("%s\n", strerror(errno));
688                 db_util_close(s_info.handle);
689                 s_info.handle = NULL;
690                 return -EIO;
691         }
692
693         if (!S_ISREG(stat.st_mode)) {
694                 ErrPrint("Invalid file\n");
695                 db_util_close(s_info.handle);
696                 s_info.handle = NULL;
697                 return -EINVAL;
698         }
699
700         if (!stat.st_size)
701                 db_create_table();
702
703         return 0;
704 }
705
706 static inline int db_fini(void)
707 {
708         if (!s_info.handle)
709                 return 0;
710
711         db_util_close(s_info.handle);
712         s_info.handle = NULL;
713
714         return 0;
715 }
716
717 struct desc {
718         xmlChar *lang;
719         xmlChar *desc;
720         xmlChar *name;
721 };
722
723 struct image {
724         int id;
725         xmlChar *path;
726 };
727
728 struct homescreen {
729         char *appid;
730         xmlChar *icon;
731         xmlChar *name;
732         xmlChar *desc;
733         struct dlist *image_list;
734         struct dlist *desc_list;
735 };
736
737 static inline int homescreen_destroy(struct homescreen *homescreen)
738 {
739         struct dlist *l;
740         struct dlist *n;
741         struct desc *desc;
742         struct image *image;
743
744         free(homescreen->appid);
745         xmlFree(homescreen->icon);
746         xmlFree(homescreen->name);
747         xmlFree(homescreen->desc);
748
749         dlist_foreach_safe(homescreen->image_list, l, n, image) {
750                 homescreen->image_list = dlist_remove(homescreen->image_list, l);
751                 xmlFree(image->path);
752                 free(image);
753         }
754
755         dlist_foreach_safe(homescreen->desc_list, l, n, desc) {
756                 homescreen->desc_list = dlist_remove(homescreen->desc_list, l);
757                 xmlFree(desc->lang);
758                 xmlFree(desc->desc);
759                 xmlFree(desc->name);
760                 free(desc);
761         }
762
763         return 0;
764 }
765
766 static inline int db_insert_item(struct homescreen *homescreen)
767 {
768         return 0;
769 }
770
771 static inline int update_name(struct homescreen *homescreen, xmlNodePtr node)
772 {
773         xmlChar *name;
774         xmlChar *lang;
775         struct dlist *l;
776         struct desc *desc;
777
778         name = xmlNodeGetContent(node);
779         if (!name)
780                 return -EINVAL;
781
782         lang = xmlNodeGetLang(node);
783         if (!lang) {
784                 if (homescreen->name) {
785                         DbgPrint("Overwrite the name: %s\n", homescreen->name);
786                         xmlFree(homescreen->name);
787                 }
788
789                 homescreen->name = name;
790                 return 0;
791         }
792
793         dlist_foreach(homescreen->desc_list, l, desc) {
794                 if (!xmlStrcmp(desc->lang, lang)) {
795                         if (desc->name) {
796                                 DbgPrint("Overwrite the name: %s\n", desc->name);
797                                 xmlFree(desc->name);
798                         }
799
800                         desc->name = name;
801                         return 0;
802                 }
803         }
804
805         desc = calloc(1, sizeof(*desc));
806         if (!desc) {
807                 ErrPrint("Heap: %s\n", strerror(errno));
808                 xmlFree(name);
809                 xmlFree(lang);
810                 return -ENOMEM;
811         }
812
813         desc->name = name;
814         desc->lang = lang;
815         desc->desc = NULL;
816
817         homescreen->desc_list = dlist_append(homescreen->desc_list, desc);
818         return 0;
819 }
820
821 static inline int update_icon(struct homescreen *homescreen, xmlNodePtr node)
822 {
823         xmlChar *path;
824
825         path = xmlNodeGetContent(node);
826         if (!path)
827                 return -EINVAL;
828
829         if (homescreen->icon) {
830                 DbgPrint("Overwrite icon: %s\n", homescreen->icon);
831                 xmlFree(homescreen->icon);
832         }
833
834         homescreen->icon = path;
835         return 0;
836 }
837
838 static inline int update_image(struct homescreen *homescreen, xmlNodePtr node)
839 {
840         xmlChar *path;
841         xmlChar *id_str;
842         int id;
843         struct dlist *l;
844         struct image *image;
845
846         if (!xmlHasProp(node, (const xmlChar *)"src")) {
847                 DbgPrint("Has no source\n");
848                 return -EINVAL;
849         }
850
851         if (!xmlHasProp(node, (const xmlChar *)"id")) {
852                 DbgPrint("Has no id\n");
853                 return -EINVAL;
854         }
855
856         path = xmlGetProp(node, (const xmlChar *)"src");
857         if (!path) {
858                 ErrPrint("Invalid path\n");
859                 return -EINVAL;
860         }
861
862         id_str = xmlGetProp(node, (const xmlChar *)"id");
863         if (!id_str) {
864                 ErrPrint("Invalid id\n");
865                 xmlFree(path);
866                 return -EINVAL;
867         }
868
869         id = atoi((char *)id_str);
870         xmlFree(id_str);
871
872         dlist_foreach(homescreen->image_list, l, image) {
873                 if (image->id == id) {
874                         xmlFree(image->path);
875                         image->path = path;
876                         return 0;
877                 }
878         }
879
880         image = calloc(1, sizeof(*image));
881         if (!image) {
882                 ErrPrint("Heap: %s\n", strerror(errno));
883                 return -ENOMEM;
884         }
885
886         image->path = path;
887         image->id = id;
888
889         homescreen->image_list = dlist_append(homescreen->image_list, image);
890         return 0;
891 }
892
893 static inline int update_desc(struct homescreen *homescreen, xmlNodePtr node)
894 {
895         xmlChar *desc_str;
896         xmlChar *lang;
897         struct desc *desc;
898         struct dlist *l;
899
900         desc_str = xmlNodeGetContent(node);
901         if (!desc_str) {
902                 desc_str = xmlStrdup((const xmlChar *)"No description");
903                 if (!desc_str) {
904                         ErrPrint("Heap: %s\n", strerror(errno));
905                         return -ENOMEM;
906                 }
907         }
908
909         lang = xmlNodeGetLang(node);
910         if (!lang) {
911                 if (homescreen->desc) {
912                         DbgPrint("Overwrite desc: %s\n", homescreen->desc);
913                         xmlFree(homescreen->desc);
914                 }
915
916                 homescreen->desc = desc_str;
917                 return 0;
918         }
919
920         dlist_foreach(homescreen->desc_list, l, desc) {
921                 if (!xmlStrcmp(desc->lang, lang)) {
922                         if (desc->desc) {
923                                 DbgPrint("Overwrite desc: %s\n", desc->desc);
924                                 xmlFree(desc->desc);
925                         }
926
927                         desc->desc = desc_str;
928                         return 0;
929                 }
930         }
931
932         desc = calloc(1, sizeof(*desc));
933         if (!desc) {
934                 ErrPrint("Heap: %s\n", strerror(errno));
935                 return -ENOMEM;
936         }
937
938         desc->lang = lang;
939         desc->desc = desc_str;
940         desc->name = NULL;
941
942         homescreen->desc_list = dlist_append(homescreen->desc_list, desc);
943         return 0;
944 }
945
946 int PKGMGR_PARSER_PLUGIN_UPGRADE(xmlDocPtr docPtr, const char *appid)
947 {
948         xmlNodePtr node;
949
950         if (!s_info.handle) {
951                 if (db_init() < 0) {
952                         ErrPrint("Failed to init DB\n");
953                         return -EIO;
954                 }
955         }
956
957         node = xmlDocGetRootElement(docPtr);
958         if (!node) {
959                 ErrPrint("Invalid document\n");
960                 return -EINVAL;
961         }
962
963         for (node = node->children; node; node = node->next) {
964                 if (!xmlStrcasecmp(node->name, (const xmlChar *)"homescreen"))
965                         break;
966         }
967
968         if (!node) {
969                 ErrPrint("Root has no homescreen\n");
970                 return -EINVAL;
971         }
972
973         return 0;
974 }
975
976 int PKGMGR_PARSER_PLUGIN_INSTALL(xmlDocPtr docPtr, const char *pkgname)
977 {
978         xmlNodePtr node;
979         struct homescreen *homescreen;
980
981         if (!s_info.handle) {
982                 if (db_init() < 0) {
983                         ErrPrint("Failed to init DB\n");
984                         return -EIO;
985                 }
986         }
987
988         node = xmlDocGetRootElement(docPtr);
989         if (!node) {
990                 ErrPrint("Invalid document\n");
991                 return -EINVAL;
992         }
993
994         for (node = node->children; node; node = node->next) {
995                 if (!xmlStrcasecmp(node->name, (const xmlChar *)"homescreen"))
996                         break;
997         }
998
999         if (!node) {
1000                 ErrPrint("Root has no children\n");
1001                 return -EINVAL;
1002         }
1003
1004         homescreen = calloc(1, sizeof(*homescreen));
1005         if (!homescreen) {
1006                 ErrPrint("Heap: %s\n", strerror(errno));
1007                 return -ENOMEM;
1008         }
1009
1010         homescreen->appid = strdup(pkgname);
1011         if (!homescreen->appid) {
1012                 ErrPrint("Heap: %s\n", strerror(errno));
1013                 return -ENOMEM;
1014         }
1015
1016         for (node = node->children; node; node = node->next) {
1017                 if (!xmlStrcmp(node->name, (const xmlChar *)"text"))
1018                         continue;
1019
1020                 DbgPrint("Nodename: %s\n", node->name);
1021                 if (!xmlStrcasecmp(node->name, (const xmlChar *)"label"))
1022                         update_name(homescreen, node);
1023                 else if (!xmlStrcasecmp(node->name, (const xmlChar *)"icon"))
1024                         update_icon(homescreen, node);
1025                 else if (!xmlStrcasecmp(node->name, (const xmlChar *)"img"))
1026                         update_image(homescreen, node);
1027                 else if (!xmlStrcasecmp(node->name, (const xmlChar *)"desc"))
1028                         update_desc(homescreen, node);
1029                 else
1030                         ErrPrint("Unknown node: %s\n", node->name);
1031         }
1032
1033         return db_insert_item(homescreen);
1034 }
1035
1036 int PKGMGR_PARSER_PLUGIN_UNINSTALL(xmlDocPtr docPtr, const char *pkgname)
1037 {
1038         xmlNodePtr node;
1039         int ret;
1040
1041         if (!s_info.handle) {
1042                 if (db_init() < 0) {
1043                         ErrPrint("Failed to init DB\n");
1044                         return -EIO;
1045                 }
1046         }
1047
1048         node = xmlDocGetRootElement(docPtr);
1049         if (!node) {
1050                 ErrPrint("Invalid document\n");
1051                 return -EINVAL;
1052         }
1053
1054         for (node = node->children; node; node = node->next) {
1055                 if (!xmlStrcasecmp(node->name, (const xmlChar *)"homescreen"))
1056                         break;
1057         }
1058
1059         if (!node) {
1060                 ErrPrint("Root has no children\n");
1061                 return -EINVAL;
1062         }
1063
1064         begin_transaction();
1065         ret = db_remove_image(pkgname);
1066         if (ret < 0) {
1067                 rollback_transaction();
1068                 return ret;
1069         }
1070
1071         ret = db_remove_desc(pkgname);
1072         if (ret < 0) {
1073                 rollback_transaction();
1074                 return ret;
1075         }
1076
1077         ret = db_remove_homescreen(pkgname);
1078         if (ret < 0) {
1079                 rollback_transaction();
1080                 return ret;
1081         }
1082
1083         commit_transaction();
1084         return 0;
1085 }
1086
1087 /*
1088 int main(int argc, char *argv[])
1089 {
1090         xmlDoc *doc;
1091         xmlNode *root;
1092
1093         if (argc != 2) {
1094                 ErrPRint("Invalid argument: %s XML_FILENAME\n", argv[0]);
1095                 return -EINVAL;
1096         }
1097
1098         doc = xmlReadFile(argv[1], NULL, 0);
1099         if (!doc) {
1100                 ErrPrint("Failed to parse %s\n", argv[1]);
1101                 return -EIO;
1102         }
1103
1104         root = xmlDocGetRootElement(doc);
1105
1106         db_init();
1107         install_shortcut("", root);
1108         db_fini();
1109
1110         xmlFreeDoc(doc);
1111         xmlCleanupParser();
1112         return 0;
1113 }
1114 */
1115
1116 /* End of a file */