merge with master
[platform/core/appfw/shortcut.git] / pkgmgr_shortcut / src / service_register.c
1 /*
2  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16 */
17
18 #include <stdio.h>
19 #include <errno.h>
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <unistd.h>
23 #include <libgen.h>
24 #include <string.h>
25
26 #include <sqlite3.h>
27 #include <db-util.h>
28 #include <libxml/parser.h>
29 #include <libxml/tree.h>
30 #include <dlog.h>
31
32 #include "dlist.h"
33
34 #if !defined(FLOG)
35 #define DbgPrint(format, arg...)        LOGD("[\e[32m%s/%s\e[0m:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg)
36 #define ErrPrint(format, arg...)        LOGE("[\e[32m%s/%s\e[0m:%d] " format, basename(__FILE__), __func__, __LINE__, ##arg)
37 #endif
38 /* End of a file */
39
40 /*!
41  * DB Table schema
42  *
43  * +----+-------+------+---------+-----------+------------+
44  * | id | appid | Icon |  Name   | extra_key | extra_data |
45  * +----+-------+------+---------+-----------+------------+
46  * | id |   -   |   -  |    -    |     -     |     -      |
47  * +----+-------+------+---------+-----------+------------+
48  *
49  * +----+------+------+
50  * | fk | lang | name |
51  * +----+------+------+
52  * | id |   -  |   -  |
53  * +----+------+------+
54  */
55
56 #if !defined(LIBXML_TREE_ENABLED)
57         #error "LIBXML is not supporting the tree"
58 #endif
59
60 int errno;
61
62 static struct {
63         const char *dbfile;
64         sqlite3 *handle;
65 } s_info = {
66         .dbfile = "/opt/dbspace/.shortcut_service.db",
67         .handle = NULL,
68 };
69
70 static inline int begin_transaction(void)
71 {
72         sqlite3_stmt *stmt;
73         int ret;
74
75         ret = sqlite3_prepare_v2(s_info.handle, "BEGIN TRANSACTION", -1, &stmt, NULL);
76         if (ret != SQLITE_OK) {
77                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
78                 return EXIT_FAILURE;
79         }
80
81         if (sqlite3_step(stmt) != SQLITE_DONE) {
82                 DbgPrint("Failed to do update (%s)\n",
83                                         sqlite3_errmsg(s_info.handle));
84                 sqlite3_finalize(stmt);
85                 return EXIT_FAILURE;
86         }
87
88         sqlite3_finalize(stmt);
89         return EXIT_SUCCESS;
90 }
91
92 static inline int rollback_transaction(void)
93 {
94         int ret;
95         sqlite3_stmt *stmt;
96
97         ret = sqlite3_prepare_v2(s_info.handle, "ROLLBACK TRANSACTION", -1, &stmt, NULL);
98         if (ret != SQLITE_OK) {
99                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
100                 return EXIT_FAILURE;
101         }
102
103         if (sqlite3_step(stmt) != SQLITE_DONE) {
104                 DbgPrint("Failed to do update (%s)\n",
105                                 sqlite3_errmsg(s_info.handle));
106                 sqlite3_finalize(stmt);
107                 return EXIT_FAILURE;
108         }
109
110         sqlite3_finalize(stmt);
111         return EXIT_SUCCESS;
112 }
113
114 static inline int commit_transaction(void)
115 {
116         sqlite3_stmt *stmt;
117         int ret;
118
119         ret = sqlite3_prepare_v2(s_info.handle, "COMMIT TRANSACTION", -1, &stmt, NULL);
120         if (ret != SQLITE_OK) {
121                 DbgPrint("Error: %s\n", sqlite3_errmsg(s_info.handle));
122                 return EXIT_FAILURE;
123         }
124
125         if (sqlite3_step(stmt) != SQLITE_DONE) {
126                 DbgPrint("Failed to do update (%s)\n",
127                                         sqlite3_errmsg(s_info.handle));
128                 sqlite3_finalize(stmt);
129                 return EXIT_FAILURE;
130         }
131
132         sqlite3_finalize(stmt);
133         return EXIT_SUCCESS;
134 }
135 static inline void db_create_table(void)
136 {
137         char *err;
138         static const char *ddl =
139                 "CREATE TABLE shortcut_service ("
140                 "id INTEGER PRIMARY KEY AUTOINCREMENT, "
141                 "appid TEXT, "
142                 "icon TEXT, "
143                 "name TEXT, "
144                 "extra_key TEXT, "
145                 "extra_data TEXT)";
146
147         if (sqlite3_exec(s_info.handle, ddl, NULL, NULL, &err) != SQLITE_OK) {
148                 ErrPrint("Failed to execute the DDL (%s)\n", err);
149                 return;
150         }
151
152         if (sqlite3_changes(s_info.handle) == 0)
153                 ErrPrint("No changes to DB\n");
154
155         ddl = "CREATE TABLE shortcut_name (id INTEGER, lang TEXT, name TEXT)";
156         if (sqlite3_exec(s_info.handle, ddl, NULL, NULL, &err) != SQLITE_OK) {
157                 ErrPrint("Failed to execute the DDL (%s)\n", err);
158                 return;
159         }
160
161         if (sqlite3_changes(s_info.handle) == 0)
162                 ErrPrint("No changes to DB\n");
163 }
164
165 static inline int db_remove_record(const char *appid, const char *key, const char *data)
166 {
167         static const char *dml = "DELETE FROM shortcut_service WHERE appid = ? AND extra_key = ? AND extra_data = ?";
168         sqlite3_stmt *stmt;
169         int ret;
170
171         if (!appid || !key || !data) {
172                 ErrPrint("Invalid argument\n");
173                 return -EINVAL;
174         }
175
176         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
177         if (ret != SQLITE_OK) {
178                 ErrPrint("Failed to prepare the initial DML(%s)\n", sqlite3_errmsg(s_info.handle));
179                 return -EIO;
180         }
181
182         ret = -EIO;
183         if (sqlite3_bind_text(stmt, 1, appid, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
184                 ErrPrint("Failed to bind a appid(%s)\n", sqlite3_errmsg(s_info.handle));
185                 goto out;
186         }
187
188         if (sqlite3_bind_text(stmt, 2, key, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
189                 ErrPrint("Failed to bind a key(%s)\n", sqlite3_errmsg(s_info.handle));
190                 goto out;
191         }
192
193         if (sqlite3_bind_text(stmt, 3, data, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
194                 ErrPrint("Failed to bind a data(%s)\n", sqlite3_errmsg(s_info.handle));
195                 goto out;
196         }
197
198         ret = 0;
199         if (sqlite3_step(stmt) != SQLITE_DONE) {
200                 ret = -EIO;
201                 ErrPrint("Failed to execute the DML for %s - %s(%s)\n", appid, key, data);
202         }
203
204         if (sqlite3_changes(s_info.handle) == 0)
205                 DbgPrint("No changes\n");
206
207 out:
208         sqlite3_reset(stmt);
209         sqlite3_clear_bindings(stmt);
210         sqlite3_finalize(stmt);
211         return ret;
212 }
213
214 static inline int db_remove_name(int id)
215 {
216         static const char *dml = "DELETE FROM shortcut_name WHERE id = ?";
217         sqlite3_stmt *stmt;
218         int ret;
219
220         if (id < 0) {
221                 ErrPrint("Inavlid id\n");
222                 return -EINVAL;
223         }
224
225         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
226         if (ret != SQLITE_OK) {
227                 ErrPrint("Failed to prepare the initial DML(%s)\n", sqlite3_errmsg(s_info.handle));
228                 return -EIO;
229         }
230
231         if (sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) {
232                 ErrPrint("Failed to bind id(%d)\n", id);
233                 ret = -EIO;
234                 goto out;
235         }
236
237         ret = 0;
238         if (sqlite3_step(stmt) != SQLITE_DONE) {
239                 ret = -EIO;
240                 ErrPrint("Failed to execute the DML for %d\n", id);
241                 goto out;
242         }
243
244         if (sqlite3_changes(s_info.handle) == 0)
245                 DbgPrint("No changes\n");
246
247 out:
248         sqlite3_reset(stmt);
249         sqlite3_clear_bindings(stmt);
250         sqlite3_finalize(stmt);
251         return ret;
252 }
253
254 static inline int db_insert_record(const char *appid, const char *icon, const char *name, const char *key, const char *data)
255 {
256         static const char *dml = "INSERT INTO shortcut_service (appid, icon, name, extra_key, extra_data) VALUES (?, ?, ?, ?, ?)";
257         sqlite3_stmt *stmt;
258         int ret;
259
260         if (!appid) {
261                 ErrPrint("Failed to get appid\n");
262                 return -EINVAL;
263         }
264
265         if (!name) {
266                 ErrPrint("Failed to get name\n");
267                 return -EINVAL;
268         }
269
270         if (!key) {
271                 ErrPrint("Failed to get key\n");
272                 return -EINVAL;
273         }
274
275         if (!data) {
276                 ErrPrint("Faield to get key\n");
277                 return -EINVAL;
278         }
279
280         icon = icon ? icon : "";
281
282         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
283         if (ret != SQLITE_OK) {
284                 ErrPrint("Failed to prepare the initial DML(%s)\n", sqlite3_errmsg(s_info.handle));
285                 return -EIO;
286         }
287
288         ret = -EIO;
289         if (sqlite3_bind_text(stmt, 1, appid, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
290                 ErrPrint("Failed to bind a appid(%s)\n", sqlite3_errmsg(s_info.handle));
291                 goto out;
292         }
293
294         if (sqlite3_bind_text(stmt, 2, icon, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
295                 ErrPrint("Failed to bind a icon(%s)\n", sqlite3_errmsg(s_info.handle));
296                 goto out;
297         }
298
299         if (sqlite3_bind_text(stmt, 3, name, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
300                 ErrPrint("Failed to bind a name(%s)\n", sqlite3_errmsg(s_info.handle));
301                 goto out;
302         }
303
304         if (sqlite3_bind_text(stmt, 4, key, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
305                 ErrPrint("Failed to bind a service(%s)\n", sqlite3_errmsg(s_info.handle));
306                 goto out;
307         }
308
309         if (sqlite3_bind_text(stmt, 5, data, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
310                 ErrPrint("Failed to bind a service(%s)\n", sqlite3_errmsg(s_info.handle));
311                 goto out;
312         }
313
314         ret = 0;
315         if (sqlite3_step(stmt) != SQLITE_DONE) {
316                 ErrPrint("Failed to execute the DML for %s - %s\n", appid, name);
317                 ret = -EIO;
318         }
319
320 out:
321         sqlite3_reset(stmt);
322         sqlite3_clear_bindings(stmt);
323         sqlite3_finalize(stmt);
324         return ret;
325 }
326
327 static inline int db_insert_name(int id, const char *lang, const char *name)
328 {
329         static const char *dml = "INSERT INTO shortcut_name (id, lang, name) VALUES (?, ?, ?)";
330         sqlite3_stmt *stmt;
331         int ret;
332
333         if (id < 0 || !lang || !name) {
334                 ErrPrint("Invalid parameters\n");
335                 return -EINVAL;
336         }
337
338         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
339         if (ret != SQLITE_OK) {
340                 ErrPrint("Failed to prepare the initial DML(%s)\n", sqlite3_errmsg(s_info.handle));
341                 return -EIO;
342         }
343
344         if (sqlite3_bind_int(stmt, 1, id) != SQLITE_OK) {
345                 ErrPrint("Failed to bind a id(%s)\n", sqlite3_errmsg(s_info.handle));
346                 ret = -EIO;
347                 goto out;
348         }
349
350         if (sqlite3_bind_text(stmt, 2, lang, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
351                 ErrPrint("Failed to bind a id(%s)\n", sqlite3_errmsg(s_info.handle));
352                 ret = -EIO;
353                 goto out;
354         }
355
356         if (sqlite3_bind_text(stmt, 3, name, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
357                 ErrPrint("Failed to bind a id(%s)\n", sqlite3_errmsg(s_info.handle));
358                 ret = -EIO;
359                 goto out;
360         }
361
362         ret = 0;
363         if (sqlite3_step(stmt) != SQLITE_DONE) {
364                 ErrPrint("Failed to execute the DML for %d %s %s\n", id, lang, name);
365                 ret = -EIO;
366         }
367
368 out:
369         sqlite3_reset(stmt);
370         sqlite3_clear_bindings(stmt);
371         sqlite3_finalize(stmt);
372         return ret;
373 }
374
375 static inline int db_get_id(const char *appid, const char *key, const char *data)
376 {
377         static const char *dml = "SELECT id FROM shortcut_service WHERE appid = ? AND extra_key = ? AND extra_data = ?";
378         sqlite3_stmt *stmt;
379         int ret;
380
381         if (!appid || !key || !data) {
382                 ErrPrint("Invalid argument\n");
383                 return -EINVAL;
384         }
385
386         ret = sqlite3_prepare_v2(s_info.handle, dml, -1, &stmt, NULL);
387         if (ret != SQLITE_OK) {
388                 ErrPrint("Failed to prepare the initial DML(%s)\n", sqlite3_errmsg(s_info.handle));
389                 return -EIO;
390         }
391
392         ret = -EIO;
393         if (sqlite3_bind_text(stmt, 1, appid, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
394                 ErrPrint("Failed to bind a appid(%s) - %s\n", appid, sqlite3_errmsg(s_info.handle));
395                 goto out;
396         }
397
398         if (sqlite3_bind_text(stmt, 2, key, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
399                 ErrPrint("Failed to bind a key(%s) - %s\n", key, sqlite3_errmsg(s_info.handle));
400                 goto out;
401         }
402
403         if (sqlite3_bind_text(stmt, 3, data, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
404                 ErrPrint("Failed to bind a data(%s) - %s\n", data, sqlite3_errmsg(s_info.handle));
405                 goto out;
406         }
407
408         if (sqlite3_step(stmt) != SQLITE_ROW) {
409                 ErrPrint("Failed to execute the DML for %s - %s, %s\n", appid, key, data);
410                 ret = -EIO;
411                 goto out;
412         }
413
414         ret = sqlite3_column_int(stmt, 0);
415
416 out:
417         sqlite3_reset(stmt);
418         sqlite3_clear_bindings(stmt);
419         sqlite3_finalize(stmt);
420         return ret;
421 }
422
423 static inline int db_init(void)
424 {
425         int ret;
426         struct stat stat;
427
428         ret = db_util_open(s_info.dbfile, &s_info.handle, DB_UTIL_REGISTER_HOOK_METHOD);
429         if (ret != SQLITE_OK) {
430                 ErrPrint("Failed to open a DB\n");
431                 return -EIO;
432         }
433
434         if (lstat(s_info.dbfile, &stat) < 0) {
435                 ErrPrint("%s\n", strerror(errno));
436                 db_util_close(s_info.handle);
437                 s_info.handle = NULL;
438                 return -EIO;
439         }
440
441         if (!S_ISREG(stat.st_mode)) {
442                 ErrPrint("Invalid file\n");
443                 db_util_close(s_info.handle);
444                 s_info.handle = NULL;
445                 return -EINVAL;
446         }
447
448         if (!stat.st_size)
449                 db_create_table();
450
451         return 0;
452 }
453
454 static inline int db_fini(void)
455 {
456         if (!s_info.handle)
457                 return 0;
458
459         db_util_close(s_info.handle);
460         s_info.handle = NULL;
461
462         return 0;
463 }
464
465 int PKGMGR_PARSER_PLUGIN_UNINSTALL(xmlDocPtr docPtr, const char *_appid)
466 {
467         xmlNodePtr node = NULL;
468         xmlChar *key;
469         xmlChar *data;
470         xmlChar *appid;
471         xmlNodePtr root;
472         int id;
473
474         root = xmlDocGetRootElement(docPtr);
475         if (!root) {
476                 ErrPrint("Invalid node ptr\n");
477                 return -EINVAL;
478         }
479
480         if (!s_info.handle) {
481                 if (db_init() < 0)
482                         return -EIO;
483         }
484
485         for (root = root->children; root; root = root->next) {
486                 if (!xmlStrcasecmp(root->name, (const xmlChar *)"shortcut-list"))
487                         break;
488         }
489
490         if (!root) {
491                 ErrPrint("Root has no shortcut-list\n");
492                 return -EINVAL;
493         }
494
495         DbgPrint("AppID: %s\n", _appid);
496         root = root->children;
497         for (node = root; node; node = node->next) {
498                 if (node->type == XML_ELEMENT_NODE)
499                         DbgPrint("Element %s\n", node->name);
500
501                 if (xmlStrcasecmp(node->name, (const xmlChar *)"shortcut"))
502                         continue;
503
504                 if (!xmlHasProp(node, (xmlChar *)"extra_data")
505                         || !xmlHasProp(node, (xmlChar *)"extra_key")
506                         || !xmlHasProp(node, (xmlChar *)"appid"))
507                 {
508                         DbgPrint("Invalid element %s\n", node->name);
509                         continue;
510                 }
511
512                 appid = xmlGetProp(node, (xmlChar *)"appid");
513                 key = xmlGetProp(node, (xmlChar *)"extra_key");
514                 data = xmlGetProp(node, (xmlChar *)"extra_data");
515
516                 DbgPrint("appid: %s\n", appid);
517                 DbgPrint("key: %s\n", key);
518                 DbgPrint("data: %s\n", data);
519
520                 id = db_get_id((char *)appid, (char *)key, (char *)data);
521                 if (id < 0) {
522                         ErrPrint("No records found\n");
523                         xmlFree(appid);
524                         xmlFree(key);
525                         xmlFree(data);
526                         continue;
527                 }
528
529                 begin_transaction();
530                 if (db_remove_record((char *)appid, (char *)key, (char *)data) < 0) {
531                         ErrPrint("Failed to remove a record\n");
532                         rollback_transaction();
533                         xmlFree(appid);
534                         xmlFree(key);
535                         xmlFree(data);
536                         continue;
537                 }
538
539                 if (db_remove_name(id) < 0) {
540                         ErrPrint("Failed to remove name records\n");
541                         rollback_transaction();
542                         xmlFree(appid);
543                         xmlFree(key);
544                         xmlFree(data);
545                         continue;
546                 }
547                 commit_transaction();
548                 xmlFree(appid);
549                 xmlFree(key);
550                 xmlFree(data);
551
552                 /*!
553                  * \note
554                  * if (node->children)
555                  * DbgPrint("Skip this node's children\n");
556                  */
557         }
558
559         return 0;
560 }
561
562 int PKGMGR_PARSER_PLUGIN_INSTALL(xmlDocPtr docPtr, const char *appid)
563 {
564         xmlNodePtr node = NULL;
565         xmlNodePtr child = NULL;
566         xmlChar *key;
567         xmlChar *data;
568         xmlChar *name;
569         xmlChar *icon;
570         xmlChar *shortcut_appid;
571         xmlNodePtr root;
572         struct i18n_name {
573                 xmlChar *name;
574                 xmlChar *lang;
575         } *i18n;
576         struct dlist *i18n_list = NULL;
577         struct dlist *l;
578         struct dlist *n;
579         int id;
580
581         root = xmlDocGetRootElement(docPtr);
582         if (!root) {
583                 ErrPrint("Invalid node ptr\n");
584                 return -EINVAL;
585         }
586
587         if (!s_info.handle) {
588                 if (db_init() < 0)
589                         return -EIO;
590         }
591
592         for (root = root->children; root; root = root->next) {
593                 if (!xmlStrcasecmp(root->name, (const xmlChar *)"shortcut-list"))
594                         break;
595         }
596
597         if (!root) {
598                 ErrPrint("Root has no children\n");
599                 return -EINVAL;
600         }
601
602         DbgPrint("AppID: %s\n", appid);
603
604         root = root->children; /* Jump to children node */
605         for (node = root; node; node = node->next) {
606                 if (node->type == XML_ELEMENT_NODE)
607                         DbgPrint("Element %s\n", node->name);
608
609                 if (xmlStrcasecmp(node->name, (const xmlChar *)"shortcut"))
610                         continue;
611
612                 if (!xmlHasProp(node, (xmlChar *)"extra_key") || !xmlHasProp(node, (xmlChar *)"extra_data")) {
613                         DbgPrint("Invalid element %s\n", node->name);
614                         continue;
615                 }
616
617                 key = xmlGetProp(node, (xmlChar *)"extra_key");
618                 data = xmlGetProp(node, (xmlChar *)"extra_data");
619                 shortcut_appid = xmlGetProp(node, (xmlChar *)"appid");
620
621                 icon = NULL;
622                 name = NULL;
623                 for (child = node->children; child; child = child->next) {
624                         if (!xmlStrcasecmp(child->name, (const xmlChar *)"icon")) {
625                                 if (icon) {
626                                         DbgPrint("Icon is duplicated\n");
627                                         continue;
628                                 }
629
630                                 icon = xmlNodeGetContent(child);
631                                 continue;
632                         }
633
634                         if (!xmlStrcasecmp(child->name, (const xmlChar *)"label")) {
635                                 xmlChar *lang;
636                                 lang = xmlNodeGetLang(child);
637                                 if (!lang) {
638                                         if (name) {
639                                                 DbgPrint("Default name is duplicated\n");
640                                         } else {
641                                                 name = xmlNodeGetContent(child);
642                                                 DbgPrint("Default name is %s\n", name);
643                                         }
644
645                                         continue;
646                                 }
647
648                                 i18n = malloc(sizeof(*i18n));
649                                 if (!i18n) {
650                                         ErrPrint("Heap: %s\n", strerror(errno));
651                                         break;
652                                 }
653
654                                 i18n->lang = lang;
655                                 i18n->name = xmlNodeGetContent(child);
656                                 i18n_list = dlist_append(i18n_list, i18n);
657                                 continue;
658                         }
659                 }
660
661                 DbgPrint("appid: %s\n", appid);
662                 DbgPrint("shortcut appid: %s\n", shortcut_appid);
663                 DbgPrint("key: %s\n", key);
664                 DbgPrint("data: %s\n", data);
665                 DbgPrint("icon: %s\n", icon);
666                 DbgPrint("Default name: %s\n", name);
667
668                 if (!shortcut_appid) {
669                         shortcut_appid = xmlStrdup((xmlChar *)appid);
670                         DbgPrint("Use the default appid\n");
671                 }
672
673                 begin_transaction();
674                 if (db_insert_record((char *)shortcut_appid, (char *)icon, (char *)name, (char *)key, (char *)data) < 0) {
675                         ErrPrint("Failed to insert a new record\n");
676                         rollback_transaction();
677
678                         dlist_foreach_safe(i18n_list, l, n, i18n) {
679                                 i18n_list = dlist_remove(i18n_list, l);
680                                 xmlFree(i18n->lang);
681                                 xmlFree(i18n->name);
682                                 free(i18n);
683                         }
684                 } else {
685                         id = db_get_id((char *)shortcut_appid, (char *)key, (char *)data);
686                         if (id < 0) {
687                                 ErrPrint("Failed to insert a new record\n");
688                                 rollback_transaction();
689
690                                 dlist_foreach_safe(i18n_list, l, n, i18n) {
691                                         i18n_list = dlist_remove(i18n_list, l);
692                                         xmlFree(i18n->lang);
693                                         xmlFree(i18n->name);
694                                         free(i18n);
695                                 }
696                         } else {
697                                 dlist_foreach_safe(i18n_list, l, n, i18n) {
698                                         i18n_list = dlist_remove(i18n_list, l);
699                                         if (db_insert_name(id, (char *)i18n->lang, (char *)i18n->name) < 0)
700                                                 ErrPrint("Failed to add i18n name: %s(%s)\n", i18n->name, i18n->lang);
701                                         xmlFree(i18n->lang);
702                                         xmlFree(i18n->name);
703                                         free(i18n);
704                                 }
705                                 commit_transaction();
706                         }
707                 }
708
709                 xmlFree(key);
710                 xmlFree(data);
711                 xmlFree(icon);
712                 xmlFree(name);
713                 xmlFree(shortcut_appid);
714         }
715
716         return 0;
717 }
718
719 int PKGMGR_PARSER_PLUGIN_UPGRADE(xmlDocPtr docPtr, const char *appid)
720 {
721         /* So... ugly */
722         PKGMGR_PARSER_PLUGIN_UNINSTALL(docPtr, appid);
723         PKGMGR_PARSER_PLUGIN_INSTALL(docPtr, appid);
724         return 0;
725 }
726
727 /*
728 int main(int argc, char *argv[])
729 {
730         xmlDoc *doc;
731         xmlNode *root;
732
733         if (argc != 2) {
734                 ErrPRint("Invalid argument: %s XML_FILENAME\n", argv[0]);
735                 return -EINVAL;
736         }
737
738         doc = xmlReadFile(argv[1], NULL, 0);
739         if (!doc) {
740                 ErrPrint("Failed to parse %s\n", argv[1]);
741                 return -EIO;
742         }
743
744         root = xmlDocGetRootElement(doc);
745
746         db_init();
747         install_shortcut("", root);
748         db_fini();
749
750         xmlFreeDoc(doc);
751         xmlCleanupParser();
752         return 0;
753 }
754 */
755
756 /* End of a file */