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