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