Modified to create the DB tables when sticker daemon was not launched
[platform/core/uifw/capi-ui-sticker.git] / sticker-parser / sticker-parser.c
1 /*
2  * Copyright (c) 2019 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 #include <unistd.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <dlog.h>
22 #include <glib.h>
23 #include <json-glib/json-glib.h>
24 #include <pkgmgr-info.h>
25 #include <sqlite3.h>
26 #include <tzplatform_config.h>
27 #include <package_manager.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <errno.h>
31 #include <dirent.h>
32 #include <fcntl.h>
33
34 #ifndef EXPORT_API
35 #define EXPORT_API __attribute__((visibility("default")))
36 #endif
37
38 #ifdef LOG_TAG
39 #undef LOG_TAG
40 #endif
41 #define LOG_TAG "STICKER_PARSER"
42
43 #define STICKER_DIRECTORY tzplatform_mkpath(TZ_SYS_SHARE, "sticker-data")
44 #define STICKER_INFO_CREATE_TABLE "CREATE TABLE IF NOT EXISTS sticker_info(sticker_info_id INTEGER PRIMARY KEY AUTOINCREMENT, app_id TEXT NOT NULL, type INTEGER NOT NULL, uri TEXT NOT NULL, thumbnail TEXT, description TEXT, group_name TEXT NOT NULL, date TEXT NOT NULL);"
45 #define STICKER_KEYWORD_INFO_CREATE_TABLE "CREATE TABLE IF NOT EXISTS sticker_keyword_info(keyword_id INTEGER PRIMARY KEY AUTOINCREMENT, sticker_info_id INTEGER, keyword TEXT NOT NULL, FOREIGN KEY (sticker_info_id) REFERENCES sticker_info(sticker_info_id) ON DELETE CASCADE)"
46 #define UIFW_ID           502
47 #define APPFW_ID          301
48 #define MAX_ERROR_BUFFER  256
49
50 static char error_buffer[MAX_ERROR_BUFFER];
51 static gboolean is_corrupted = FALSE;
52
53 typedef struct metadata {
54     const char *key;
55     const char *value;
56 } metadata;
57
58 static char* __get_string_from_object(JsonObject *object, const char *key)
59 {
60     if (json_object_has_member(object, key) == false)
61         return NULL;
62
63     const char *str = json_object_get_string_member(object, key);
64     if (str != NULL)
65         return strdup(str);
66     else
67         return NULL;
68 }
69
70 static int __get_int_from_object(JsonObject *object, const char *key)
71 {
72     if (json_object_has_member(object, key) == false)
73         return -1;
74
75     int type = json_object_get_int_member(object, key);
76
77     return type;
78 }
79
80 static void __recover_db()
81 {
82     int ret;
83     sqlite3 *db = NULL;
84     char *err = NULL;
85     const char *db_path = tzplatform_mkpath(TZ_SYS_DB, ".sticker_info.db");
86
87     LOGD("Start to recover sticker db");
88     if (unlink(db_path) == -1)
89         LOGE("Failed to remove db file");
90
91     ret = sqlite3_open_v2(db_path, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
92     if (ret != SQLITE_OK) {
93         LOGE("Failed to open db : %s", sqlite3_errmsg(db));
94         if (unlink(db_path) == -1)
95             LOGE("Failed to remove db file");
96         goto cleanup;
97     }
98
99     ret = sqlite3_exec(db, STICKER_INFO_CREATE_TABLE, NULL, NULL, &err);
100     if (ret != SQLITE_OK) {
101         LOGE("Failed to create sticker_info table : %s" , err);
102         goto cleanup;
103     }
104
105     ret = sqlite3_exec(db, STICKER_KEYWORD_INFO_CREATE_TABLE, NULL, NULL, &err);
106     if (ret != SQLITE_OK) {
107         LOGE("Failed to create sticker_keyword_info table : %s", err);
108         goto cleanup;
109     }
110
111     is_corrupted = FALSE;
112
113 cleanup:
114     if (err)
115         sqlite3_free(err);
116
117     if (db)
118         sqlite3_close(db);
119 }
120
121 static int __integrity_check_cb(void *pid, int argc, char **argv, char **notUsed)
122 {
123     if (strcmp(argv[0], "ok") != 0) {
124         LOGE("DB integrity check failed : %s", argv[0]);
125         is_corrupted = TRUE;
126         return -1;
127     }
128
129     LOGD("Result integrity : %s", argv[0]);
130     return 0;
131 }
132
133 static void __db_init()
134 {
135     int ret;
136     sqlite3 *db = NULL;
137     char *err = NULL;
138     const char *db_path = tzplatform_mkpath(TZ_SYS_DB, ".sticker_info.db");
139
140     ret = sqlite3_open_v2(db_path, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
141     if (ret != SQLITE_OK) {
142         LOGE("Failed to open db : %s", sqlite3_errmsg(db));
143         goto cleanup;
144     }
145
146     ret = sqlite3_exec(db, STICKER_INFO_CREATE_TABLE, NULL, NULL, &err);
147     if (ret != SQLITE_OK) {
148         LOGE("Failed to create sticker_info table : %s" , err);
149         goto cleanup;
150     }
151
152     ret = sqlite3_exec(db, STICKER_KEYWORD_INFO_CREATE_TABLE, NULL, NULL, &err);
153     if (ret != SQLITE_OK) {
154         LOGE("Failed to create sticker_keyword_info table : %s", err);
155         goto cleanup;
156     }
157
158     ret = sqlite3_exec(db, "PRAGMA journal_mode = WAL", NULL, NULL, &err);
159     if (ret != SQLITE_OK) {
160         LOGE("Failed to set journal_mode : %s", err);
161         goto cleanup;
162     }
163
164     ret = sqlite3_exec(db, "PRAGMA integrity_check", __integrity_check_cb, NULL, &err);
165     if (ret != SQLITE_OK)
166         LOGE("Failed to check integrity : %s", err);
167
168 cleanup:
169     if (err)
170         sqlite3_free(err);
171
172     if (db)
173         sqlite3_close(db);
174
175     if (ret == SQLITE_CORRUPT || ret == SQLITE_NOTADB || is_corrupted)
176         __recover_db();
177 }
178
179 static sqlite3 *__db_open(const char *path)
180 {
181     int ret;
182     sqlite3 *db = NULL;
183     char *err = NULL;
184
185     ret = sqlite3_open(path, &db);
186     if (ret != SQLITE_OK) {
187         LOGE("Failed to open db : %s", sqlite3_errmsg(db));
188         return NULL;
189     }
190
191     ret = sqlite3_exec(db, "PRAGMA foreign_keys = ON", NULL, NULL, &err);
192     if (ret != SQLITE_OK) {
193         LOGE("Failed to turn on foreign keys : %s", err);
194     }
195
196     if (err)
197         sqlite3_free(err);
198
199     return db;
200 }
201
202 static int __change_ownership(const char *path, int user, int group)
203 {
204     int ret;
205     uid_t uid = (uid_t)user;
206     gid_t gid = (gid_t)group;
207
208     ret = chown(path, uid, gid);
209     if (ret != 0) {
210         strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
211         LOGE("chown() failed : %s", error_buffer);
212     }
213
214     return ret;
215 }
216
217 static int __remove_app_path(char *uri, const char *app_path)
218 {
219     int n = 0;
220     int k = 0;
221     for (int i = 0; uri[i] != '\0'; i++) {
222         if (uri[i] == app_path[n]) {
223             k = i;
224             while (uri[i] == app_path[n]) {
225                 if (app_path[++n] == '\0') {
226                     for(; uri[k + n] != '\0'; k++) {
227                         uri[k] = uri[k + n];
228                     }
229                     uri[k] = '\0';
230                     return 1;
231                 }
232                 i++;
233             }
234             n = 0;
235             i--;
236         }
237     }
238     return 0;
239 }
240
241 static int __mkdirs(const char *path, mode_t mode)
242 {
243     int len = 0;
244     char prev_path[2048];
245     const char *tmp = path;
246
247     if (!path || strlen(path) > 2048)
248         return -1;
249
250     memset(prev_path, '\0', 2048);
251     while ((tmp = strchr(tmp, '/')) != NULL) {
252         len = tmp - path;
253         tmp++;
254
255         if (len == 0)
256             continue;
257
258         strncpy(prev_path, path, len);
259         prev_path[len] = 0x00;
260
261         if (mkdir(prev_path, mode) == -1) {
262             if (errno != EEXIST) {
263                 strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
264                 LOGE("directory create error : %s", error_buffer);
265                 return -1;
266             }
267         } else {
268             if (__change_ownership(prev_path, UIFW_ID, UIFW_ID) != 0)
269                 LOGE("failed to change ownership");
270         }
271     }
272
273     if (mkdir(prev_path, mode) == -1) {
274         if (errno != EEXIST) {
275             strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
276             LOGE("directory create error : %s", error_buffer);
277             return -1;
278         }
279     } else {
280         if (__change_ownership(prev_path, UIFW_ID, UIFW_ID) != 0)
281             LOGE("failed to change ownership");
282     }
283     return 0;
284 }
285
286 static int __file_copy(const char *src, const char *dest)
287 {
288     int ret = 0;
289     int fd = -1, n_fd = -1;
290     char buf[4096];
291     int tmp_err = 0;
292     int size;
293
294     memset(buf, '\0', 4096);
295     fd = open(src, O_RDONLY);
296     n_fd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0755);
297
298     if (fd == -1 || n_fd == -1) {
299         tmp_err = errno;
300         ret = -1;
301         goto cleanup;
302     }
303
304     while((size = read(fd, buf, 4096))) {
305         if (size == -1) {
306             if(errno == EINTR)
307                 continue;
308
309             tmp_err = errno;
310             ret = -1;
311             goto cleanup;
312         }
313
314         while(write(n_fd, buf, size) == -1) {
315             if(errno == EINTR) {
316                 continue;
317             } else {
318                 tmp_err = errno;
319                 goto cleanup;
320             }
321         }
322     }
323
324 cleanup:
325     if (fd != -1)
326         close(fd);
327
328     if (n_fd != -1)
329         close(n_fd);
330
331     errno = tmp_err;
332     return ret;
333 }
334
335 static char* __convert_sticker_uri(const char *uri, const char *appid, const char *app_path)
336 {
337     int ret;
338     char *rel_path = strdup(uri);
339
340     __remove_app_path(rel_path, app_path);
341     int len = strlen(STICKER_DIRECTORY) + strlen(appid) + strlen(rel_path) + 2;
342     char *new_path = (char *)calloc(len, sizeof(char));
343     if (new_path == NULL) {
344         free(rel_path);
345         rel_path = NULL;
346         return NULL;
347     }
348
349     snprintf(new_path, len, "%s/%s%s",STICKER_DIRECTORY, appid, rel_path);
350
351     if (access(new_path, F_OK) == 0) {
352         LOGE("sticker file already exists");
353         ret = -1;
354         goto cleanup;
355     }
356
357     ret = __mkdirs(new_path, 0755);
358     if (ret != 0) {
359         LOGE("directory create error");
360         goto cleanup;
361     }
362
363     if (__file_copy(uri, new_path) == -1) {
364         strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
365         LOGE("failed to copy sticker file : %s", error_buffer);
366         ret = -1;
367         goto cleanup;
368     }
369
370     ret = unlink(uri);
371     if (ret != 0) {
372         strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
373         LOGE("failed to remove sticker file : %s", error_buffer);
374     }
375
376     if (__change_ownership(new_path, UIFW_ID, UIFW_ID) != 0)
377         LOGE("failed to change ownership");
378
379 cleanup:
380     free(rel_path);
381     rel_path = NULL;
382
383     if (ret == 0) {
384         return new_path;
385     } else {
386         free(new_path);
387         new_path = NULL;
388         return NULL;
389     }
390 }
391
392 static void __insert_sticker_info(const char *app_id, int type, const char *uri, const char *group, const char *thumbnail, const char *description)
393 {
394     int ret;
395     sqlite3 *db = NULL;
396     sqlite3_stmt *stmt = NULL;
397     const char *db_path;
398
399     db_path = tzplatform_mkpath(TZ_SYS_DB, ".sticker_info.db");
400     db = __db_open(db_path);
401     if (!db)
402         return;
403
404     ret = sqlite3_prepare_v2(db, "INSERT INTO sticker_info (app_id, type, uri, thumbnail, description, group_name, date) VALUES (?, ?, ?, ?, ?, ?, DateTime('now','localtime'))",-1, &stmt, NULL);
405     if (ret == SQLITE_OK) {
406         sqlite3_bind_text(stmt, 1, app_id, -1, SQLITE_TRANSIENT);
407         sqlite3_bind_int(stmt, 2, type);
408         sqlite3_bind_text(stmt, 3, uri, -1, SQLITE_TRANSIENT);
409         sqlite3_bind_text(stmt, 4, thumbnail, -1, SQLITE_TRANSIENT);
410         sqlite3_bind_text(stmt, 5, description, -1, SQLITE_TRANSIENT);
411         sqlite3_bind_text(stmt, 6, group, -1, SQLITE_TRANSIENT);
412
413         ret = sqlite3_step(stmt);
414         if (ret != SQLITE_OK && ret != SQLITE_DONE)
415             LOGE("sqlite3_step() failed : ret(%d)", ret);
416
417         if (sqlite3_changes(db) == 0)
418             LOGE("No changes to DB");
419
420         sqlite3_finalize(stmt);
421         sqlite3_close(db);
422     } else {
423         LOGE("failed to insert sticker information : %s", sqlite3_errmsg(db));
424         sqlite3_finalize(stmt);
425         sqlite3_close(db);
426     }
427
428     return;
429 }
430
431 static void __insert_sticker_keyword_info(const char *keyword)
432 {
433     int ret;
434     int record_id;
435     sqlite3 *db = NULL;
436     sqlite3_stmt *stmt = NULL;
437     const char *db_path;
438
439     db_path = tzplatform_mkpath(TZ_SYS_DB, ".sticker_info.db");
440     db = __db_open(db_path);
441     if (!db)
442         return;
443
444     ret = sqlite3_prepare_v2(db, "SELECT sticker_info_id FROM sticker_info ORDER BY sticker_info_id DESC LIMIT 1", -1, &stmt, NULL);
445     if (ret == SQLITE_OK) {
446         ret = sqlite3_step(stmt);
447         if (ret == SQLITE_ERROR) {
448             LOGE("sqlite3_step() failed : ret(%d)", ret);
449             sqlite3_finalize(stmt);
450             sqlite3_close(db);
451         } else {
452             record_id = sqlite3_column_int(stmt, 0);
453
454             sqlite3_finalize(stmt);
455             stmt = NULL;
456
457             ret = sqlite3_prepare_v2(db, "INSERT INTO sticker_keyword_info (sticker_info_id, keyword) VALUES (?, ?)", -1, &stmt, NULL);
458             if (ret == SQLITE_OK) {
459                 sqlite3_bind_int(stmt, 1, record_id);
460                 sqlite3_bind_text(stmt, 2, keyword, -1, SQLITE_TRANSIENT);
461
462                 ret = sqlite3_step(stmt);
463                 if (ret != SQLITE_OK && ret != SQLITE_DONE)
464                     LOGE("sqlite3_step() failed : ret(%d)", ret);
465
466                 if (sqlite3_changes(db) == 0)
467                     LOGE("No changes to DB");
468
469                 sqlite3_finalize(stmt);
470                 sqlite3_close(db);
471             } else {
472                 LOGE("fail to insert sticker keyword : %s", sqlite3_errmsg(db));
473                 sqlite3_finalize(stmt);
474                 sqlite3_close(db);
475             }
476         }
477     } else {
478         LOGE("fail to insert sticker information : %s", sqlite3_errmsg(db));
479         sqlite3_finalize(stmt);
480         sqlite3_close(db);
481     }
482
483     return;
484 }
485
486 static int __get_sticker_info_from_json(const char *appid, const char *file_path, const char *app_path)
487 {
488     int ret = 1;
489     JsonParser* parser = NULL;
490     GError* err_msg = NULL;
491     char *uri = NULL;
492     char *group = NULL;
493     char *description = NULL;
494     char *thumbnail = NULL;
495     char *uri_path = NULL;
496
497     parser = json_parser_new();
498     json_parser_load_from_file(parser, file_path, &err_msg);
499     if (err_msg) {
500         LOGE("failed to load json file. error message: %s", err_msg->message);
501         ret = 0;
502         goto cleanup;
503     }
504
505     JsonNode *root = json_parser_get_root(parser);
506     if (root == NULL) {
507         LOGE("failed to get root");
508         ret = 0;
509         goto cleanup;
510     }
511
512     JsonObject *root_obj = json_node_get_object(root);
513     if (root_obj == NULL) {
514         LOGE("failed to get object");
515         ret = 0;
516         goto cleanup;
517     }
518
519     JsonArray *sticker_arr = json_object_get_array_member(root_obj, "sticker");
520     if (sticker_arr == NULL) {
521         LOGE("failed to get array member");
522         ret = 0;
523         goto cleanup;
524     }
525
526     int arr_len = json_array_get_length(sticker_arr);
527     for (int i = 0; i < arr_len; i++) {
528         JsonObject *info_object = json_array_get_object_element(sticker_arr, i);
529         if (info_object != NULL) {
530             int type = __get_int_from_object(info_object, "type");
531             if (type < 1)
532                 continue;
533
534             uri = __get_string_from_object(info_object, "uri");
535             if (!uri)
536                 goto free_memory;
537
538             group = __get_string_from_object(info_object, "group");
539             if (!group)
540                 goto free_memory;
541
542             thumbnail = __get_string_from_object(info_object, "thumbnail");
543             description = __get_string_from_object(info_object, "description");
544
545             JsonArray *keyword_arr = json_object_get_array_member(info_object, "keyword");
546             int keyword_arr_len = json_array_get_length(keyword_arr);
547             if (keyword_arr_len < 1)
548                 goto free_memory;
549
550             if (type == 1) {
551                 if (access(uri, F_OK) == 0) {
552                     char *new_uri = __convert_sticker_uri(uri, appid, app_path);
553                     if (!new_uri)
554                         goto free_memory;
555                     __insert_sticker_info(appid, type, new_uri, group, thumbnail, description);
556
557                     if (new_uri) {
558                         free(new_uri);
559                         new_uri = NULL;
560                     }
561                 } else {
562                     int path_len = strlen(app_path) + strlen(uri) + 2;
563                     uri_path = (char *)calloc(path_len, sizeof(char));
564                     if (!uri_path) {
565                         LOGE("failed to alloc memory");
566                         goto free_memory;
567                     }
568
569                     if (uri[0] == '/')
570                         snprintf(uri_path, path_len, "%s%s",app_path, uri);
571                     else
572                         snprintf(uri_path, path_len, "%s%s%s",app_path, "/", uri);
573
574                     if (access(uri_path, F_OK) == 0) {
575                         char *new_uri = __convert_sticker_uri(uri_path, appid, app_path);
576                         if (!new_uri) {
577                             free(uri_path);
578                             uri_path = NULL;
579                             goto free_memory;
580                         }
581                         __insert_sticker_info(appid, type, new_uri, group, thumbnail, description);
582
583                         free(new_uri);
584                         new_uri = NULL;
585
586                         free(uri_path);
587                         uri_path = NULL;
588                     } else {
589                         LOGE("%s does not exist", uri_path);
590                         free(uri_path);
591                         uri_path = NULL;
592                         goto free_memory;
593                     }
594                 }
595             } else {
596                 __insert_sticker_info(appid, type, uri, group, thumbnail, description);
597             }
598
599             for (int j = 0; j < keyword_arr_len; j++) {
600                 __insert_sticker_keyword_info(json_array_get_string_element(keyword_arr, j));
601             }
602
603 free_memory:
604             if (uri) {
605                 free(uri);
606                 uri = NULL;
607             }
608
609             if (group) {
610                 free(group);
611                 group = NULL;
612             }
613
614             if (thumbnail) {
615                 free(thumbnail);
616                 thumbnail = NULL;
617             }
618
619             if (description) {
620                 free(description);
621                 description = NULL;
622             }
623         }
624     }
625
626 cleanup:
627     if (err_msg)
628         g_error_free(err_msg);
629
630     if (parser)
631         g_object_unref(parser);
632
633     return ret;
634 }
635
636 static void __delete_sticker_info(const char *db_path, int record_id)
637 {
638     int ret;
639     sqlite3 *db = NULL;
640     sqlite3_stmt *stmt = NULL;
641
642     db = __db_open(db_path);
643         if (!db)
644             return;
645
646     ret = sqlite3_prepare_v2(db, "DELETE FROM sticker_info WHERE sticker_info_id = ?", -1, &stmt, NULL);
647     if (ret != SQLITE_OK) {
648         LOGE("failed to delete sticker information : %s", sqlite3_errmsg(db));
649         sqlite3_finalize(stmt);
650         sqlite3_close(db);
651         goto cleanup;
652     }
653
654     sqlite3_bind_int(stmt, 1, record_id);
655
656     ret = sqlite3_step(stmt);
657     if (ret != SQLITE_OK && ret != SQLITE_DONE) {
658         LOGE("sqlite3_step() failed : ret(%d)", ret);
659         goto cleanup;
660     }
661
662     if (sqlite3_changes(db) == 0) {
663         LOGE("No changes to DB");
664         goto cleanup;
665     }
666
667     sqlite3_finalize(stmt);
668     sqlite3_close(db);
669     return;
670
671 cleanup:
672     sqlite3_finalize(stmt);
673     sqlite3_close(db);
674     return;
675 }
676
677 static int __remove_directory(const char *path, int is_error_stop)
678 {
679     DIR *dir_ptr = NULL;
680     struct dirent *file = NULL;
681     struct stat buf;
682     char filename[1024];
683
684     memset(filename, '\0', 1024);
685
686     if (__change_ownership(path, APPFW_ID, APPFW_ID) != 0)
687         LOGE("failed to change ownership");
688
689     dir_ptr = opendir(path);
690     if (dir_ptr == NULL)
691         return unlink(path);
692
693     while ((file = readdir(dir_ptr)) != NULL) {
694         if (strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0)
695             continue;
696
697         snprintf(filename, strlen(path) + strlen(file->d_name) + 2, "%s/%s", path, file->d_name);
698
699         if (lstat(filename, &buf) == -1)
700             continue;
701
702         if (S_ISDIR(buf.st_mode)) {
703             if (__remove_directory(filename, is_error_stop) == -1 && is_error_stop) {
704                 closedir(dir_ptr);
705                 return -1;
706             }
707         } else if (S_ISREG(buf.st_mode) || S_ISLNK(buf.st_mode)) {
708             if (unlink(filename) == -1 && is_error_stop) {
709                 closedir(dir_ptr);
710                 return -1;
711             }
712         }
713     }
714
715     closedir(dir_ptr);
716     return rmdir(path);
717 }
718
719 EXPORT_API
720 int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgid, const char *appid, GList *list)
721 {
722     LOGD("METADATA INSTALL");
723     LOGD("pkgid: %s, appid: %s", pkgid, appid);
724
725     metadata *md = NULL;
726     GList *md_list = NULL;
727     package_info_h package_info = NULL;
728     char *app_path = NULL;
729     char *file_path = NULL;
730     int ret = 0;
731
732     __db_init();
733
734     ret = package_info_create(pkgid, &package_info);
735     if (ret != PACKAGE_MANAGER_ERROR_NONE || package_info == NULL) {
736         LOGE("failed to create package_info. ret: %d", ret);
737         goto cleanup;
738     }
739
740     ret = package_info_get_root_path(package_info, &app_path);
741     if (ret != PACKAGE_MANAGER_ERROR_NONE || app_path == NULL) {
742         LOGE("failed to create package_info. ret: %d", ret);
743         goto cleanup;
744     }
745
746     for(md_list = g_list_first(list); md_list != NULL; md_list = md_list->next) {
747         md = (metadata *)md_list->data;
748         int path_len = strlen(app_path) + strlen((char *)md->value) + 2;
749         file_path = (char *)calloc(path_len, sizeof(char));
750         if (!file_path) {
751             LOGE("failed to alloc memory");
752             continue;
753         }
754
755         if ((char)md->value[0] == '/')
756             snprintf(file_path, path_len, "%s%s",app_path, (char *)md->value);
757         else
758             snprintf(file_path, path_len, "%s%s%s",app_path, "/", (char *)md->value);
759
760         if (__get_sticker_info_from_json(appid, file_path, app_path) == 0)
761             LOGE("failed to get sticker information [path : %s]", file_path);
762
763         free(file_path);
764         file_path = NULL;
765     }
766
767 cleanup:
768     if (package_info)
769         package_info_destroy(package_info);
770
771     if (app_path) {
772         free(app_path);
773         app_path = NULL;
774     }
775
776     return 0;
777 }
778
779 EXPORT_API
780 int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgid, const char *appid, GList *list)
781 {
782     LOGD("METADATA UNINSTALL");
783     LOGD("pkgid: %s, appid: %s", pkgid, appid);
784
785     int ret;
786     int del_id;
787     sqlite3 *db = NULL;
788     sqlite3_stmt *stmt = NULL;
789     const char *db_path;
790     GList *id_list = NULL;
791
792     db_path = tzplatform_mkpath(TZ_SYS_DB, ".sticker_info.db");
793     db = __db_open(db_path);
794     if (!db)
795         return 0;
796
797     ret = sqlite3_prepare_v2(db, "SELECT sticker_info_id from sticker_info WHERE app_id = ?", -1, &stmt, NULL);
798     if (ret == SQLITE_OK) {
799         sqlite3_bind_text(stmt, 1, appid, -1, SQLITE_TRANSIENT);
800         while (sqlite3_step(stmt) == SQLITE_ROW) {
801             const unsigned char *record_id = sqlite3_column_text(stmt, 0);
802             if (record_id)
803                 id_list = g_list_append(id_list, strdup((const char *)record_id));
804         }
805
806         sqlite3_finalize(stmt);
807         sqlite3_close(db);
808
809         for(GList *tmp = g_list_first(id_list); tmp != NULL; tmp = tmp->next) {
810             del_id = atoi((const char*)tmp->data);
811             __delete_sticker_info(db_path, del_id);
812         }
813
814         if (id_list)
815             g_list_free_full(id_list, free);
816     } else {
817         LOGE("failed to get sticker id");
818         sqlite3_finalize(stmt);
819         sqlite3_close(db);
820     }
821
822     return 0;
823 }
824
825 EXPORT_API
826 int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgid, const char *appid, GList *list)
827 {
828     LOGD("METADATA UPGRADE");
829     LOGD("pkgid: %s, appid: %s", pkgid, appid);
830
831     PKGMGR_MDPARSER_PLUGIN_UNINSTALL(pkgid, appid, list);
832     PKGMGR_MDPARSER_PLUGIN_INSTALL(pkgid, appid, list);
833     return 0;
834 }
835
836 EXPORT_API
837 int PKGMGR_CATEGORY_PARSER_PLUGIN_INSTALL(const char *pkgid, const char *appid, GList *list)
838 {
839     LOGD("STICKER CATEGORY INSTALL");
840     LOGD("pkgid: %s, appid: %s", pkgid, appid);
841
842     int len = strlen(STICKER_DIRECTORY) + strlen(appid) + 2;
843     char *dir_path = (char *)calloc(len, sizeof(char));
844
845     if (dir_path != NULL) {
846         snprintf(dir_path, len, "%s%s%s", STICKER_DIRECTORY, "/", appid);
847         LOGD("directory path : %s", dir_path);
848
849         if (mkdir(dir_path, 0755) == -1 && errno != EEXIST) {
850             strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
851             LOGE("directory create error : %s", error_buffer);
852         } else {
853             if (__change_ownership(dir_path, UIFW_ID, UIFW_ID) != 0)
854                 LOGE("failed to change ownership");
855         }
856
857         free(dir_path);
858         dir_path = NULL;
859     }
860
861     return 0;
862 }
863
864 EXPORT_API
865 int PKGMGR_CATEGORY_PARSER_PLUGIN_UNINSTALL(const char *pkgid, const char *appid, GList *list)
866 {
867     LOGD("STICKER CATEGORY UNINSTALL");
868     LOGD("pkgid: %s, appid: %s", pkgid, appid);
869
870     int len = strlen(STICKER_DIRECTORY) + strlen(appid) + 2;
871     char * dir_path = (char *)calloc(len, sizeof(char));
872
873     if (dir_path != NULL) {
874         snprintf(dir_path, len, "%s%s%s", STICKER_DIRECTORY, "/", appid);
875         LOGD("directory path : %s", dir_path);
876
877         if (__remove_directory(dir_path, 0) < 0) {
878             strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
879             LOGE("directory remove error : %s", error_buffer);
880         }
881
882         free(dir_path);
883         dir_path = NULL;
884     }
885
886     return 0;
887 }
888
889 EXPORT_API
890 int PKGMGR_CATEGORY_PARSER_PLUGIN_UPGRADE(const char *pkgid, const char *appid, GList *list)
891 {
892     LOGD("STICKER CATEGORY UPGRADE");
893     LOGD("pkgid: %s, appid: %s", pkgid, appid);
894
895     PKGMGR_CATEGORY_PARSER_PLUGIN_UNINSTALL(pkgid, appid, list);
896     PKGMGR_CATEGORY_PARSER_PLUGIN_INSTALL(pkgid, appid, list);
897
898     return 0;
899 }