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