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