063aa87611c5c8e3b9014fbab9e647bb2f7074be
[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 && rel_thumbnail[0] != '\0') {
624                 if (access(rel_thumbnail, F_OK) == 0) {
625                     thumbnail_path = __convert_sticker_uri(rel_thumbnail, appid, app_path);
626                 } else {
627                     int len = strlen(app_path) + strlen(rel_thumbnail) + 2;
628                     char *new_thumbnail_path = (char *)calloc(len, sizeof(char));
629                     if (new_thumbnail_path) {
630                         if (rel_thumbnail[0] == '/')
631                             snprintf(new_thumbnail_path, len, "%s%s",app_path, rel_thumbnail);
632                         else
633                             snprintf(new_thumbnail_path, len, "%s%s%s",app_path, "/", rel_thumbnail);
634
635                         if (access(new_thumbnail_path, F_OK) == 0)
636                             thumbnail_path = __convert_sticker_uri(new_thumbnail_path, appid, app_path);
637
638                         free(new_thumbnail_path);
639                         new_thumbnail_path = NULL;
640                     }
641                 }
642                 free(rel_thumbnail);
643             }
644
645             description = __get_string_from_object(info_object, "description");
646             int disp_type = __get_int_from_object(info_object, "display_type");
647
648             JsonArray *keyword_arr = json_object_get_array_member(info_object, "keyword");
649             int keyword_arr_len = json_array_get_length(keyword_arr);
650             if (keyword_arr_len < 1)
651                 goto free_memory;
652
653             if (type == 1) {
654                 if (access(uri, F_OK) == 0) {
655                     char *new_uri = __convert_sticker_uri(uri, appid, app_path);
656                     if (!new_uri)
657                         goto free_memory;
658                     __insert_sticker_info(appid, type, new_uri, group, thumbnail_path, description, disp_type);
659
660                     if (new_uri) {
661                         free(new_uri);
662                         new_uri = NULL;
663                     }
664                 } else {
665                     int path_len = strlen(app_path) + strlen(uri) + 2;
666                     uri_path = (char *)calloc(path_len, sizeof(char));
667                     if (!uri_path) {
668                         LOGE("failed to alloc memory");
669                         goto free_memory;
670                     }
671
672                     if (uri[0] == '/')
673                         snprintf(uri_path, path_len, "%s%s",app_path, uri);
674                     else
675                         snprintf(uri_path, path_len, "%s%s%s",app_path, "/", uri);
676
677                     if (access(uri_path, F_OK) == 0) {
678                         char *new_uri = __convert_sticker_uri(uri_path, appid, app_path);
679                         if (!new_uri) {
680                             free(uri_path);
681                             uri_path = NULL;
682                             goto free_memory;
683                         }
684                         __insert_sticker_info(appid, type, new_uri, group, thumbnail_path, description, disp_type);
685
686                         free(new_uri);
687                         new_uri = NULL;
688
689                         free(uri_path);
690                         uri_path = NULL;
691                     } else {
692                         LOGE("%s does not exist", uri_path);
693                         free(uri_path);
694                         uri_path = NULL;
695                         goto free_memory;
696                     }
697                 }
698             } else {
699                 __insert_sticker_info(appid, type, uri, group, thumbnail_path, description, disp_type);
700             }
701
702             for (int j = 0; j < keyword_arr_len; j++) {
703                 __insert_sticker_keyword_info(json_array_get_string_element(keyword_arr, j));
704             }
705
706 free_memory:
707             if (uri) {
708                 free(uri);
709                 uri = NULL;
710             }
711
712             if (group) {
713                 free(group);
714                 group = NULL;
715             }
716
717             if (thumbnail_path) {
718                 free(thumbnail_path);
719                 thumbnail_path = NULL;
720             }
721
722             if (description) {
723                 free(description);
724                 description = NULL;
725             }
726         }
727     }
728
729 cleanup:
730     if (err_msg)
731         g_error_free(err_msg);
732
733     if (parser)
734         g_object_unref(parser);
735
736     return ret;
737 }
738
739 static void __delete_sticker_allowlist(const char *db_path, const char *app_id)
740 {
741     int ret;
742     sqlite3 *db = NULL;
743     sqlite3_stmt *stmt = NULL;
744
745     db = __db_open(db_path);
746     if (!db)
747         return;
748
749     ret = sqlite3_prepare_v2(db, "DELETE FROM sticker_whitelist_info WHERE provider_id = ?", -1, &stmt, NULL);
750     if (ret != SQLITE_OK) {
751         LOGE("failed to delete sticker allowlist : %s", sqlite3_errmsg(db));
752         sqlite3_finalize(stmt);
753         sqlite3_close(db);
754         goto cleanup;
755     }
756
757     sqlite3_bind_text(stmt, 1, app_id, -1, SQLITE_TRANSIENT);
758
759     ret = sqlite3_step(stmt);
760     if (ret != SQLITE_OK && ret != SQLITE_DONE) {
761         LOGE("sqlite3_step() failed : ret(%d)", ret);
762         goto cleanup;
763     }
764
765     if (sqlite3_changes(db) == 0) {
766         LOGE("No changes to DB");
767         goto cleanup;
768     }
769
770     sqlite3_finalize(stmt);
771     sqlite3_close(db);
772     return;
773
774 cleanup:
775     sqlite3_finalize(stmt);
776     sqlite3_close(db);
777     return;
778 }
779
780 static void __delete_sticker_info(const char *db_path, int record_id)
781 {
782     int ret;
783     sqlite3 *db = NULL;
784     sqlite3_stmt *stmt = NULL;
785
786     db = __db_open(db_path);
787         if (!db)
788             return;
789
790     ret = sqlite3_prepare_v2(db, "DELETE FROM sticker_info WHERE sticker_info_id = ?", -1, &stmt, NULL);
791     if (ret != SQLITE_OK) {
792         LOGE("failed to delete sticker information : %s", sqlite3_errmsg(db));
793         sqlite3_finalize(stmt);
794         sqlite3_close(db);
795         goto cleanup;
796     }
797
798     sqlite3_bind_int(stmt, 1, record_id);
799
800     ret = sqlite3_step(stmt);
801     if (ret != SQLITE_OK && ret != SQLITE_DONE) {
802         LOGE("sqlite3_step() failed : ret(%d)", ret);
803         goto cleanup;
804     }
805
806     if (sqlite3_changes(db) == 0) {
807         LOGE("No changes to DB");
808         goto cleanup;
809     }
810
811     sqlite3_finalize(stmt);
812     sqlite3_close(db);
813     return;
814
815 cleanup:
816     sqlite3_finalize(stmt);
817     sqlite3_close(db);
818     return;
819 }
820
821 static int __remove_directory(const char *path, int is_error_stop)
822 {
823     DIR *dir_ptr = NULL;
824     struct dirent *file = NULL;
825     struct stat buf;
826     char filename[1024];
827
828     memset(filename, '\0', 1024);
829
830     if (__change_ownership(path, APPFW_ID, APPFW_ID) != 0)
831         LOGE("failed to change ownership");
832
833     dir_ptr = opendir(path);
834     if (dir_ptr == NULL)
835         return unlink(path);
836
837     while ((file = readdir(dir_ptr)) != NULL) {
838         if (strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0)
839             continue;
840
841         snprintf(filename, strlen(path) + strlen(file->d_name) + 2, "%s/%s", path, file->d_name);
842
843         if (lstat(filename, &buf) == -1)
844             continue;
845
846         if (S_ISDIR(buf.st_mode)) {
847             if (__remove_directory(filename, is_error_stop) == -1 && is_error_stop) {
848                 closedir(dir_ptr);
849                 return -1;
850             }
851         } else if (S_ISREG(buf.st_mode) || S_ISLNK(buf.st_mode)) {
852             if (unlink(filename) == -1 && is_error_stop) {
853                 closedir(dir_ptr);
854                 return -1;
855             }
856         }
857     }
858
859     closedir(dir_ptr);
860     return rmdir(path);
861 }
862
863 EXPORT_API
864 int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgid, const char *appid, GList *list)
865 {
866     LOGD("METADATA INSTALL");
867     LOGD("pkgid: %s, appid: %s", pkgid, appid);
868
869     metadata *md = (metadata *)list->data;
870     package_info_h package_info = NULL;
871     char *app_path = NULL;
872     char *file_path = NULL;
873     int ret = 0;
874
875     __db_init();
876
877     ret = package_info_create(pkgid, &package_info);
878     if (ret != PACKAGE_MANAGER_ERROR_NONE || package_info == NULL) {
879         LOGE("failed to create package_info. ret: %d", ret);
880         goto cleanup;
881     }
882
883     ret = package_info_get_root_path(package_info, &app_path);
884     if (ret != PACKAGE_MANAGER_ERROR_NONE || app_path == NULL) {
885         LOGE("failed to create package_info. ret: %d", ret);
886         goto cleanup;
887     }
888
889     int path_len = strlen(app_path) + strlen((char *)md->value) + 2;
890     file_path = (char *)calloc(path_len, sizeof(char));
891     if (!file_path) {
892         LOGE("failed to alloc memory");
893         goto cleanup;
894     }
895
896     if ((char)md->value[0] == '/')
897         snprintf(file_path, path_len, "%s%s",app_path, (char *)md->value);
898     else
899         snprintf(file_path, path_len, "%s%s%s",app_path, "/", (char *)md->value);
900
901     if (__get_sticker_info_from_json(appid, file_path, app_path) == 0)
902             LOGE("failed to get sticker information [path : %s]", file_path);
903
904 cleanup:
905     if (package_info)
906         package_info_destroy(package_info);
907
908     if (app_path) {
909         free(app_path);
910         app_path = NULL;
911     }
912
913     if (file_path) {
914         free(file_path);
915         file_path = NULL;
916     }
917
918     return 0;
919 }
920
921 EXPORT_API
922 int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgid, const char *appid, GList *list)
923 {
924     LOGD("METADATA UNINSTALL");
925     LOGD("pkgid: %s, appid: %s", pkgid, appid);
926
927     int ret;
928     int del_id;
929     sqlite3 *db = NULL;
930     sqlite3_stmt *stmt = NULL;
931     const char *db_path;
932     GList *id_list = NULL;
933
934     db_path = tzplatform_mkpath(TZ_SYS_DB, ".sticker_info.db");
935     db = __db_open(db_path);
936     if (!db)
937         return 0;
938
939     ret = sqlite3_prepare_v2(db, "SELECT sticker_info_id from sticker_info WHERE app_id = ?", -1, &stmt, NULL);
940     if (ret == SQLITE_OK) {
941         sqlite3_bind_text(stmt, 1, appid, -1, SQLITE_TRANSIENT);
942         while (sqlite3_step(stmt) == SQLITE_ROW) {
943             const unsigned char *record_id = sqlite3_column_text(stmt, 0);
944             if (record_id)
945                 id_list = g_list_append(id_list, strdup((const char *)record_id));
946         }
947
948         sqlite3_finalize(stmt);
949         sqlite3_close(db);
950
951         for(GList *tmp = g_list_first(id_list); tmp != NULL; tmp = tmp->next) {
952             del_id = atoi((const char*)tmp->data);
953             __delete_sticker_info(db_path, del_id);
954         }
955
956         if (id_list)
957             g_list_free_full(id_list, free);
958     } else {
959         LOGE("failed to get sticker id");
960         sqlite3_finalize(stmt);
961         sqlite3_close(db);
962     }
963
964     __delete_sticker_allowlist(db_path, appid);
965
966     return 0;
967 }
968
969 EXPORT_API
970 int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgid, const char *appid, GList *list)
971 {
972     LOGD("METADATA UPGRADE");
973     LOGD("pkgid: %s, appid: %s", pkgid, appid);
974
975     PKGMGR_MDPARSER_PLUGIN_UNINSTALL(pkgid, appid, list);
976     PKGMGR_MDPARSER_PLUGIN_INSTALL(pkgid, appid, list);
977     return 0;
978 }
979
980 EXPORT_API
981 int PKGMGR_CATEGORY_PARSER_PLUGIN_INSTALL(const char *pkgid, const char *appid, GList *list)
982 {
983     LOGD("STICKER CATEGORY INSTALL");
984     LOGD("pkgid: %s, appid: %s", pkgid, appid);
985
986     int len = strlen(STICKER_DIRECTORY) + strlen(appid) + 2;
987     char *dir_path = (char *)calloc(len, sizeof(char));
988
989     if (dir_path != NULL) {
990         snprintf(dir_path, len, "%s%s%s", STICKER_DIRECTORY, "/", appid);
991         LOGD("directory path : %s", dir_path);
992
993         if (mkdir(dir_path, 0755) == -1 && errno != EEXIST) {
994             strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
995             LOGE("directory create error : %s", error_buffer);
996         } else {
997             if (__change_ownership(dir_path, UIFW_ID, UIFW_ID) != 0)
998                 LOGE("failed to change ownership");
999         }
1000
1001         free(dir_path);
1002         dir_path = NULL;
1003     }
1004
1005     return 0;
1006 }
1007
1008 EXPORT_API
1009 int PKGMGR_CATEGORY_PARSER_PLUGIN_UNINSTALL(const char *pkgid, const char *appid, GList *list)
1010 {
1011     LOGD("STICKER CATEGORY UNINSTALL");
1012     LOGD("pkgid: %s, appid: %s", pkgid, appid);
1013
1014     int len = strlen(STICKER_DIRECTORY) + strlen(appid) + 2;
1015     char * dir_path = (char *)calloc(len, sizeof(char));
1016
1017     if (dir_path != NULL) {
1018         snprintf(dir_path, len, "%s%s%s", STICKER_DIRECTORY, "/", appid);
1019         LOGD("directory path : %s", dir_path);
1020
1021         if (__remove_directory(dir_path, 0) < 0) {
1022             strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
1023             LOGE("directory remove error : %s", error_buffer);
1024         }
1025
1026         free(dir_path);
1027         dir_path = NULL;
1028     }
1029
1030     return 0;
1031 }
1032
1033 EXPORT_API
1034 int PKGMGR_CATEGORY_PARSER_PLUGIN_UPGRADE(const char *pkgid, const char *appid, GList *list)
1035 {
1036     LOGD("STICKER CATEGORY UPGRADE");
1037     LOGD("pkgid: %s, appid: %s", pkgid, appid);
1038
1039     PKGMGR_CATEGORY_PARSER_PLUGIN_UNINSTALL(pkgid, appid, list);
1040     PKGMGR_CATEGORY_PARSER_PLUGIN_INSTALL(pkgid, appid, list);
1041
1042     return 0;
1043 }