2 * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include <json-glib/json-glib.h>
24 #include <pkgmgr-info.h>
26 #include <tzplatform_config.h>
27 #include <package_manager.h>
29 #include <sys/types.h>
35 #define EXPORT_API __attribute__((visibility("default")))
41 #define LOG_TAG "STICKER_PARSER"
43 #define STICKER_DIRECTORY tzplatform_mkpath(TZ_SYS_SHARE, "sticker-data")
46 #define MAX_ERROR_BUFFER 256
48 static char error_buffer[MAX_ERROR_BUFFER];
50 typedef struct metadata {
55 static char* __get_string_from_object(JsonObject *object, const char *key)
57 if (json_object_has_member(object, key) == false)
60 const char *str = json_object_get_string_member(object, key);
67 static int __get_int_from_object(JsonObject *object, const char *key)
69 if (json_object_has_member(object, key) == false)
72 int type = json_object_get_int_member(object, key);
77 static sqlite3 *__db_open(const char *path)
83 ret = sqlite3_open(path, &db);
84 if (ret != SQLITE_OK) {
85 LOGE("Failed to open db : %s", sqlite3_errmsg(db));
89 ret = sqlite3_exec(db, "PRAGMA foreign_keys = ON", NULL, NULL, &err);
90 if (ret != SQLITE_OK) {
91 LOGE("Failed to turn on foreign keys : %s", err);
97 static int __change_ownership(const char *path, int user, int group)
100 uid_t uid = (uid_t)user;
101 gid_t gid = (gid_t)group;
103 ret = chown(path, uid, gid);
105 strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
106 LOGE("chown() failed : %s", error_buffer);
112 static int __remove_app_path(char *uri, const char *app_path)
116 for (int i = 0; uri[i] != '\0'; i++) {
117 if (uri[i] == app_path[n]) {
119 while (uri[i] == app_path[n]) {
120 if (app_path[++n] == '\0') {
121 for(; uri[k + n] != '\0'; k++) {
136 static int __mkdirs(const char *path, mode_t mode)
139 char prev_path[2048];
140 const char *tmp = path;
142 if (!path || strlen(path) > 2048)
145 memset(prev_path, '\0', 2048);
146 while ((tmp = strchr(tmp, '/')) != NULL) {
153 strncpy(prev_path, path, len);
154 prev_path[len] = 0x00;
156 if (mkdir(prev_path, mode) == -1) {
157 if (errno != EEXIST) {
158 strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
159 LOGE("directory create error : %s", error_buffer);
163 if (__change_ownership(prev_path, UIFW_ID, UIFW_ID) != 0)
164 LOGE("failed to change ownership");
168 if (mkdir(prev_path, mode) == -1) {
169 if (errno != EEXIST) {
170 strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
171 LOGE("directory create error : %s", error_buffer);
175 if (__change_ownership(prev_path, UIFW_ID, UIFW_ID) != 0)
176 LOGE("failed to change ownership");
181 static int __file_copy(const char *src, const char *dest)
184 int fd = -1, n_fd = -1;
189 memset(buf, '\0', 4096);
190 fd = open(src, O_RDONLY);
191 n_fd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0755);
193 if (fd == -1 || n_fd == -1) {
199 while((size = read(fd, buf, 4096))) {
209 while(write(n_fd, buf, size) == -1) {
230 static char* __convert_sticker_uri(const char *uri, const char *appid, const char *app_path)
233 char *rel_path = strdup(uri);
235 __remove_app_path(rel_path, app_path);
236 int len = strlen(STICKER_DIRECTORY) + strlen(appid) + strlen(rel_path) + 2;
237 char *new_path = (char *)calloc(len, sizeof(char));
238 if (new_path == NULL) {
244 snprintf(new_path, len, "%s/%s%s",STICKER_DIRECTORY, appid, rel_path);
246 if (access(new_path, F_OK) == 0) {
247 LOGE("sticker file already exists");
252 ret = __mkdirs(new_path, 0755);
254 LOGE("directory create error");
258 if (__file_copy(uri, new_path) == -1) {
259 strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
260 LOGE("failed to copy sticker file : %s", error_buffer);
267 strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
268 LOGE("failed to remove sticker file : %s", error_buffer);
271 if (__change_ownership(new_path, UIFW_ID, UIFW_ID) != 0)
272 LOGE("failed to change ownership");
287 static void __insert_sticker_info(const char *app_id, int type, const char *uri, const char *group, const char *thumbnail, const char *description)
291 sqlite3_stmt *stmt = NULL;
294 db_path = tzplatform_mkpath(TZ_SYS_DB, ".sticker_info.db");
295 db = __db_open(db_path);
299 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);
300 if (ret == SQLITE_OK) {
301 sqlite3_bind_text(stmt, 1, app_id, -1, SQLITE_TRANSIENT);
302 sqlite3_bind_int(stmt, 2, type);
303 sqlite3_bind_text(stmt, 3, uri, -1, SQLITE_TRANSIENT);
304 sqlite3_bind_text(stmt, 4, thumbnail, -1, SQLITE_TRANSIENT);
305 sqlite3_bind_text(stmt, 5, description, -1, SQLITE_TRANSIENT);
306 sqlite3_bind_text(stmt, 6, group, -1, SQLITE_TRANSIENT);
308 ret = sqlite3_step(stmt);
309 if (ret != SQLITE_OK && ret != SQLITE_DONE)
310 LOGE("sqlite3_step() failed : ret(%d)", ret);
312 if (sqlite3_changes(db) == 0)
313 LOGE("No changes to DB");
315 sqlite3_finalize(stmt);
318 LOGE("failed to insert sticker information : %s", sqlite3_errmsg(db));
319 sqlite3_finalize(stmt);
326 static void __insert_sticker_keyword_info(const char *keyword)
331 sqlite3_stmt *stmt = NULL;
334 db_path = tzplatform_mkpath(TZ_SYS_DB, ".sticker_info.db");
335 db = __db_open(db_path);
339 ret = sqlite3_prepare_v2(db, "SELECT sticker_info_id FROM sticker_info ORDER BY sticker_info_id DESC LIMIT 1", -1, &stmt, NULL);
340 if (ret == SQLITE_OK) {
341 ret = sqlite3_step(stmt);
342 if (ret == SQLITE_ERROR) {
343 LOGE("sqlite3_step() failed : ret(%d)", ret);
344 sqlite3_finalize(stmt);
347 record_id = sqlite3_column_int(stmt, 0);
349 sqlite3_finalize(stmt);
352 ret = sqlite3_prepare_v2(db, "INSERT INTO sticker_keyword_info (sticker_info_id, keyword) VALUES (?, ?)", -1, &stmt, NULL);
353 if (ret == SQLITE_OK) {
354 sqlite3_bind_int(stmt, 1, record_id);
355 sqlite3_bind_text(stmt, 2, keyword, -1, SQLITE_TRANSIENT);
357 ret = sqlite3_step(stmt);
358 if (ret != SQLITE_OK && ret != SQLITE_DONE)
359 LOGE("sqlite3_step() failed : ret(%d)", ret);
361 if (sqlite3_changes(db) == 0)
362 LOGE("No changes to DB");
364 sqlite3_finalize(stmt);
367 LOGE("fail to insert sticker keyword : %s", sqlite3_errmsg(db));
368 sqlite3_finalize(stmt);
373 LOGE("fail to insert sticker information : %s", sqlite3_errmsg(db));
374 sqlite3_finalize(stmt);
381 static int __get_sticker_info_from_json(const char *appid, const char *file_path, const char *app_path)
384 JsonParser* parser = NULL;
385 GError* err_msg = NULL;
388 char *description = NULL;
389 char *thumbnail = NULL;
390 char *uri_path = NULL;
392 parser = json_parser_new();
393 json_parser_load_from_file(parser, file_path, &err_msg);
395 LOGE("failed to load json file. error message: %s", err_msg->message);
400 JsonNode *root = json_parser_get_root(parser);
402 LOGE("failed to get root");
407 JsonObject *root_obj = json_node_get_object(root);
408 if (root_obj == NULL) {
409 LOGE("failed to get object");
414 JsonArray *sticker_arr = json_object_get_array_member(root_obj, "sticker");
415 if (sticker_arr == NULL) {
416 LOGE("failed to get array member");
421 int arr_len = json_array_get_length(sticker_arr);
422 for (int i = 0; i < arr_len; i++) {
423 JsonObject *info_object = json_array_get_object_element(sticker_arr, i);
424 if (info_object != NULL) {
425 int type = __get_int_from_object(info_object, "type");
429 uri = __get_string_from_object(info_object, "uri");
433 group = __get_string_from_object(info_object, "group");
437 thumbnail = __get_string_from_object(info_object, "thumbnail");
438 description = __get_string_from_object(info_object, "description");
440 JsonArray *keyword_arr = json_object_get_array_member(info_object, "keyword");
441 int keyword_arr_len = json_array_get_length(keyword_arr);
442 if (keyword_arr_len < 1)
446 if (access(uri, F_OK) == 0) {
447 char *new_uri = __convert_sticker_uri(uri, appid, app_path);
450 __insert_sticker_info(appid, type, new_uri, group, thumbnail, description);
457 int path_len = strlen(app_path) + strlen(uri) + 2;
458 uri_path = (char *)calloc(path_len, sizeof(char));
460 LOGE("failed to alloc memory");
465 snprintf(uri_path, path_len, "%s%s",app_path, uri);
467 snprintf(uri_path, path_len, "%s%s%s",app_path, "/", uri);
469 if (access(uri_path, F_OK) == 0) {
470 char *new_uri = __convert_sticker_uri(uri_path, appid, app_path);
476 __insert_sticker_info(appid, type, new_uri, group, thumbnail, description);
484 LOGE("%s does not exist", uri_path);
491 __insert_sticker_info(appid, type, uri, group, thumbnail, description);
494 for (int j = 0; j < keyword_arr_len; j++) {
495 __insert_sticker_keyword_info(json_array_get_string_element(keyword_arr, j));
523 g_error_free(err_msg);
526 g_object_unref(parser);
531 static void __delete_sticker_info(const char *db_path, int record_id)
535 sqlite3_stmt *stmt = NULL;
537 db = __db_open(db_path);
541 ret = sqlite3_prepare_v2(db, "DELETE FROM sticker_info WHERE sticker_info_id = ?", -1, &stmt, NULL);
542 if (ret != SQLITE_OK) {
543 LOGE("failed to delete sticker information : %s", sqlite3_errmsg(db));
544 sqlite3_finalize(stmt);
549 sqlite3_bind_int(stmt, 1, record_id);
551 ret = sqlite3_step(stmt);
552 if (ret != SQLITE_OK && ret != SQLITE_DONE) {
553 LOGE("sqlite3_step() failed : ret(%d)", ret);
557 if (sqlite3_changes(db) == 0) {
558 LOGE("No changes to DB");
562 sqlite3_finalize(stmt);
567 sqlite3_finalize(stmt);
572 static int __remove_directory(const char *path, int is_error_stop)
575 struct dirent *file = NULL;
579 memset(filename, '\0', 1024);
581 if (__change_ownership(path, APPFW_ID, APPFW_ID) != 0)
582 LOGE("failed to change ownership");
584 dir_ptr = opendir(path);
588 while ((file = readdir(dir_ptr)) != NULL) {
589 if (strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0)
592 snprintf(filename, strlen(path) + strlen(file->d_name) + 2, "%s/%s", path, file->d_name);
594 if (lstat(filename, &buf) == -1)
597 if (S_ISDIR(buf.st_mode)) {
598 if (__remove_directory(filename, is_error_stop) == -1 && is_error_stop) {
602 } else if (S_ISREG(buf.st_mode) || S_ISLNK(buf.st_mode)) {
603 if (unlink(filename) == -1 && is_error_stop) {
615 int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgid, const char *appid, GList *list)
617 LOGD("METADATA INSTALL");
618 LOGD("pkgid: %s, appid: %s", pkgid, appid);
621 GList *md_list = NULL;
622 package_info_h package_info = NULL;
623 char *app_path = NULL;
624 char *file_path = NULL;
627 ret = package_info_create(pkgid, &package_info);
628 if (ret != PACKAGE_MANAGER_ERROR_NONE || package_info == NULL) {
629 LOGE("faild to create package_info. ret: %d", ret);
633 ret = package_info_get_root_path(package_info, &app_path);
634 if (ret != PACKAGE_MANAGER_ERROR_NONE || app_path == NULL) {
635 LOGE("faild to create package_info. ret: %d", ret);
639 for(md_list = g_list_first(list); md_list != NULL; md_list = md_list->next) {
640 md = (metadata *)md_list->data;
641 int path_len = strlen(app_path) + strlen((char *)md->value) + 2;
642 file_path = (char *)calloc(path_len, sizeof(char));
644 LOGE("failed to alloc memory");
648 if ((char)md->value[0] == '/')
649 snprintf(file_path, path_len, "%s%s",app_path, (char *)md->value);
651 snprintf(file_path, path_len, "%s%s%s",app_path, "/", (char *)md->value);
653 if (__get_sticker_info_from_json(appid, file_path, app_path) == 0)
654 LOGE("failed to get sticker information [path : %s]", file_path);
662 package_info_destroy(package_info);
673 int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgid, const char *appid, GList *list)
675 LOGD("METADATA UNINSTALL");
676 LOGD("pkgid: %s, appid: %s", pkgid, appid);
681 sqlite3_stmt *stmt = NULL;
683 GList *id_list = NULL;
685 db_path = tzplatform_mkpath(TZ_SYS_DB, ".sticker_info.db");
686 db = __db_open(db_path);
690 ret = sqlite3_prepare_v2(db, "SELECT sticker_info_id from sticker_info WHERE app_id = ?", -1, &stmt, NULL);
691 if (ret == SQLITE_OK) {
692 sqlite3_bind_text(stmt, 1, appid, -1, SQLITE_TRANSIENT);
693 while (sqlite3_step(stmt) == SQLITE_ROW) {
694 const unsigned char *record_id = sqlite3_column_text(stmt, 0);
696 id_list = g_list_append(id_list, strdup((const char *)record_id));
699 sqlite3_finalize(stmt);
702 for(GList *tmp = g_list_first(id_list); tmp != NULL; tmp = tmp->next) {
703 del_id = atoi((const char*)tmp->data);
704 __delete_sticker_info(db_path, del_id);
708 g_list_free_full(id_list, free);
710 LOGE("failed to get sticker id");
711 sqlite3_finalize(stmt);
719 int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgid, const char *appid, GList *list)
721 LOGD("METADATA UPGRADE");
722 LOGD("pkgid: %s, appid: %s", pkgid, appid);
724 PKGMGR_MDPARSER_PLUGIN_UNINSTALL(pkgid, appid, list);
725 PKGMGR_MDPARSER_PLUGIN_INSTALL(pkgid, appid, list);
730 int PKGMGR_CATEGORY_PARSER_PLUGIN_INSTALL(const char *pkgid, const char *appid, GList *list)
732 LOGD("STICKER CATEGORY INSTALL");
733 LOGD("pkgid: %s, appid: %s", pkgid, appid);
735 int len = strlen(STICKER_DIRECTORY) + strlen(appid) + 2;
736 char *dir_path = (char *)calloc(len, sizeof(char));
738 if (dir_path != NULL) {
739 snprintf(dir_path, len, "%s%s%s", STICKER_DIRECTORY, "/", appid);
740 LOGD("directory path : %s", dir_path);
742 if (mkdir(dir_path, 0755) == -1 && errno != EEXIST) {
743 strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
744 LOGE("directory create error : %s", error_buffer);
746 if (__change_ownership(dir_path, UIFW_ID, UIFW_ID) != 0)
747 LOGE("failed to change ownership");
758 int PKGMGR_CATEGORY_PARSER_PLUGIN_UNINSTALL(const char *pkgid, const char *appid, GList *list)
760 LOGD("STICKER CATEGORY UNINSTALL");
761 LOGD("pkgid: %s, appid: %s", pkgid, appid);
763 int len = strlen(STICKER_DIRECTORY) + strlen(appid) + 2;
764 char * dir_path = (char *)calloc(len, sizeof(char));
766 if (dir_path != NULL) {
767 snprintf(dir_path, len, "%s%s%s", STICKER_DIRECTORY, "/", appid);
768 LOGD("directory path : %s", dir_path);
770 if (__remove_directory(dir_path, 0) < 0) {
771 strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
772 LOGE("directory remove error : %s", error_buffer);
783 int PKGMGR_CATEGORY_PARSER_PLUGIN_UPGRADE(const char *pkgid, const char *appid, GList *list)
785 LOGD("STICKER CATEGORY UPGRADE");
786 LOGD("pkgid: %s, appid: %s", pkgid, appid);
788 PKGMGR_CATEGORY_PARSER_PLUGIN_UNINSTALL(pkgid, appid, list);
789 PKGMGR_CATEGORY_PARSER_PLUGIN_INSTALL(pkgid, appid, list);