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