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);
100 static int __change_ownership(const char *path, int user, int group)
103 uid_t uid = (uid_t)user;
104 gid_t gid = (gid_t)group;
106 ret = chown(path, uid, gid);
108 strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
109 LOGE("chown() failed : %s", error_buffer);
115 static int __remove_app_path(char *uri, const char *app_path)
119 for (int i = 0; uri[i] != '\0'; i++) {
120 if (uri[i] == app_path[n]) {
122 while (uri[i] == app_path[n]) {
123 if (app_path[++n] == '\0') {
124 for(; uri[k + n] != '\0'; k++) {
139 static int __mkdirs(const char *path, mode_t mode)
142 char prev_path[2048];
143 const char *tmp = path;
145 if (!path || strlen(path) > 2048)
148 memset(prev_path, '\0', 2048);
149 while ((tmp = strchr(tmp, '/')) != NULL) {
156 strncpy(prev_path, path, len);
157 prev_path[len] = 0x00;
159 if (mkdir(prev_path, mode) == -1) {
160 if (errno != EEXIST) {
161 strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
162 LOGE("directory create error : %s", error_buffer);
166 if (__change_ownership(prev_path, UIFW_ID, UIFW_ID) != 0)
167 LOGE("failed to change ownership");
171 if (mkdir(prev_path, mode) == -1) {
172 if (errno != EEXIST) {
173 strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
174 LOGE("directory create error : %s", error_buffer);
178 if (__change_ownership(prev_path, UIFW_ID, UIFW_ID) != 0)
179 LOGE("failed to change ownership");
184 static int __file_copy(const char *src, const char *dest)
187 int fd = -1, n_fd = -1;
192 memset(buf, '\0', 4096);
193 fd = open(src, O_RDONLY);
194 n_fd = open(dest, O_WRONLY | O_CREAT | O_TRUNC, 0755);
196 if (fd == -1 || n_fd == -1) {
202 while((size = read(fd, buf, 4096))) {
212 while(write(n_fd, buf, size) == -1) {
233 static char* __convert_sticker_uri(const char *uri, const char *appid, const char *app_path)
236 char *rel_path = strdup(uri);
238 __remove_app_path(rel_path, app_path);
239 int len = strlen(STICKER_DIRECTORY) + strlen(appid) + strlen(rel_path) + 2;
240 char *new_path = (char *)calloc(len, sizeof(char));
241 if (new_path == NULL) {
247 snprintf(new_path, len, "%s/%s%s",STICKER_DIRECTORY, appid, rel_path);
249 if (access(new_path, F_OK) == 0) {
250 LOGE("sticker file already exists");
255 ret = __mkdirs(new_path, 0755);
257 LOGE("directory create error");
261 if (__file_copy(uri, new_path) == -1) {
262 strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
263 LOGE("failed to copy sticker file : %s", error_buffer);
270 strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
271 LOGE("failed to remove sticker file : %s", error_buffer);
274 if (__change_ownership(new_path, UIFW_ID, UIFW_ID) != 0)
275 LOGE("failed to change ownership");
290 static void __insert_sticker_info(const char *app_id, int type, const char *uri, const char *group, const char *thumbnail, const char *description)
294 sqlite3_stmt *stmt = NULL;
297 db_path = tzplatform_mkpath(TZ_SYS_DB, ".sticker_info.db");
298 db = __db_open(db_path);
302 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);
303 if (ret == SQLITE_OK) {
304 sqlite3_bind_text(stmt, 1, app_id, -1, SQLITE_TRANSIENT);
305 sqlite3_bind_int(stmt, 2, type);
306 sqlite3_bind_text(stmt, 3, uri, -1, SQLITE_TRANSIENT);
307 sqlite3_bind_text(stmt, 4, thumbnail, -1, SQLITE_TRANSIENT);
308 sqlite3_bind_text(stmt, 5, description, -1, SQLITE_TRANSIENT);
309 sqlite3_bind_text(stmt, 6, group, -1, SQLITE_TRANSIENT);
311 ret = sqlite3_step(stmt);
312 if (ret != SQLITE_OK && ret != SQLITE_DONE)
313 LOGE("sqlite3_step() failed : ret(%d)", ret);
315 if (sqlite3_changes(db) == 0)
316 LOGE("No changes to DB");
318 sqlite3_finalize(stmt);
321 LOGE("failed to insert sticker information : %s", sqlite3_errmsg(db));
322 sqlite3_finalize(stmt);
329 static void __insert_sticker_keyword_info(const char *keyword)
334 sqlite3_stmt *stmt = NULL;
337 db_path = tzplatform_mkpath(TZ_SYS_DB, ".sticker_info.db");
338 db = __db_open(db_path);
342 ret = sqlite3_prepare_v2(db, "SELECT sticker_info_id FROM sticker_info ORDER BY sticker_info_id DESC LIMIT 1", -1, &stmt, NULL);
343 if (ret == SQLITE_OK) {
344 ret = sqlite3_step(stmt);
345 if (ret == SQLITE_ERROR) {
346 LOGE("sqlite3_step() failed : ret(%d)", ret);
347 sqlite3_finalize(stmt);
350 record_id = sqlite3_column_int(stmt, 0);
352 sqlite3_finalize(stmt);
355 ret = sqlite3_prepare_v2(db, "INSERT INTO sticker_keyword_info (sticker_info_id, keyword) VALUES (?, ?)", -1, &stmt, NULL);
356 if (ret == SQLITE_OK) {
357 sqlite3_bind_int(stmt, 1, record_id);
358 sqlite3_bind_text(stmt, 2, keyword, -1, SQLITE_TRANSIENT);
360 ret = sqlite3_step(stmt);
361 if (ret != SQLITE_OK && ret != SQLITE_DONE)
362 LOGE("sqlite3_step() failed : ret(%d)", ret);
364 if (sqlite3_changes(db) == 0)
365 LOGE("No changes to DB");
367 sqlite3_finalize(stmt);
370 LOGE("fail to insert sticker keyword : %s", sqlite3_errmsg(db));
371 sqlite3_finalize(stmt);
376 LOGE("fail to insert sticker information : %s", sqlite3_errmsg(db));
377 sqlite3_finalize(stmt);
384 static int __get_sticker_info_from_json(const char *appid, const char *file_path, const char *app_path)
387 JsonParser* parser = NULL;
388 GError* err_msg = NULL;
391 char *description = NULL;
392 char *thumbnail = NULL;
393 char *uri_path = NULL;
395 parser = json_parser_new();
396 json_parser_load_from_file(parser, file_path, &err_msg);
398 LOGE("failed to load json file. error message: %s", err_msg->message);
403 JsonNode *root = json_parser_get_root(parser);
405 LOGE("failed to get root");
410 JsonObject *root_obj = json_node_get_object(root);
411 if (root_obj == NULL) {
412 LOGE("failed to get object");
417 JsonArray *sticker_arr = json_object_get_array_member(root_obj, "sticker");
418 if (sticker_arr == NULL) {
419 LOGE("failed to get array member");
424 int arr_len = json_array_get_length(sticker_arr);
425 for (int i = 0; i < arr_len; i++) {
426 JsonObject *info_object = json_array_get_object_element(sticker_arr, i);
427 if (info_object != NULL) {
428 int type = __get_int_from_object(info_object, "type");
432 uri = __get_string_from_object(info_object, "uri");
436 group = __get_string_from_object(info_object, "group");
440 thumbnail = __get_string_from_object(info_object, "thumbnail");
441 description = __get_string_from_object(info_object, "description");
443 JsonArray *keyword_arr = json_object_get_array_member(info_object, "keyword");
444 int keyword_arr_len = json_array_get_length(keyword_arr);
445 if (keyword_arr_len < 1)
449 if (access(uri, F_OK) == 0) {
450 char *new_uri = __convert_sticker_uri(uri, appid, app_path);
453 __insert_sticker_info(appid, type, new_uri, group, thumbnail, description);
460 int path_len = strlen(app_path) + strlen(uri) + 2;
461 uri_path = (char *)calloc(path_len, sizeof(char));
463 LOGE("failed to alloc memory");
468 snprintf(uri_path, path_len, "%s%s",app_path, uri);
470 snprintf(uri_path, path_len, "%s%s%s",app_path, "/", uri);
472 if (access(uri_path, F_OK) == 0) {
473 char *new_uri = __convert_sticker_uri(uri_path, appid, app_path);
479 __insert_sticker_info(appid, type, new_uri, group, thumbnail, description);
487 LOGE("%s does not exist", uri_path);
494 __insert_sticker_info(appid, type, uri, group, thumbnail, description);
497 for (int j = 0; j < keyword_arr_len; j++) {
498 __insert_sticker_keyword_info(json_array_get_string_element(keyword_arr, j));
526 g_error_free(err_msg);
529 g_object_unref(parser);
534 static void __delete_sticker_info(const char *db_path, int record_id)
538 sqlite3_stmt *stmt = NULL;
540 db = __db_open(db_path);
544 ret = sqlite3_prepare_v2(db, "DELETE FROM sticker_info WHERE sticker_info_id = ?", -1, &stmt, NULL);
545 if (ret != SQLITE_OK) {
546 LOGE("failed to delete sticker information : %s", sqlite3_errmsg(db));
547 sqlite3_finalize(stmt);
552 sqlite3_bind_int(stmt, 1, record_id);
554 ret = sqlite3_step(stmt);
555 if (ret != SQLITE_OK && ret != SQLITE_DONE) {
556 LOGE("sqlite3_step() failed : ret(%d)", ret);
560 if (sqlite3_changes(db) == 0) {
561 LOGE("No changes to DB");
565 sqlite3_finalize(stmt);
570 sqlite3_finalize(stmt);
575 static int __remove_directory(const char *path, int is_error_stop)
578 struct dirent *file = NULL;
582 memset(filename, '\0', 1024);
584 if (__change_ownership(path, APPFW_ID, APPFW_ID) != 0)
585 LOGE("failed to change ownership");
587 dir_ptr = opendir(path);
591 while ((file = readdir(dir_ptr)) != NULL) {
592 if (strcmp(file->d_name, ".") == 0 || strcmp(file->d_name, "..") == 0)
595 snprintf(filename, strlen(path) + strlen(file->d_name) + 2, "%s/%s", path, file->d_name);
597 if (lstat(filename, &buf) == -1)
600 if (S_ISDIR(buf.st_mode)) {
601 if (__remove_directory(filename, is_error_stop) == -1 && is_error_stop) {
605 } else if (S_ISREG(buf.st_mode) || S_ISLNK(buf.st_mode)) {
606 if (unlink(filename) == -1 && is_error_stop) {
618 int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgid, const char *appid, GList *list)
620 LOGD("METADATA INSTALL");
621 LOGD("pkgid: %s, appid: %s", pkgid, appid);
624 GList *md_list = NULL;
625 package_info_h package_info = NULL;
626 char *app_path = NULL;
627 char *file_path = NULL;
630 ret = package_info_create(pkgid, &package_info);
631 if (ret != PACKAGE_MANAGER_ERROR_NONE || package_info == NULL) {
632 LOGE("failed to create package_info. ret: %d", ret);
636 ret = package_info_get_root_path(package_info, &app_path);
637 if (ret != PACKAGE_MANAGER_ERROR_NONE || app_path == NULL) {
638 LOGE("failed to create package_info. ret: %d", ret);
642 for(md_list = g_list_first(list); md_list != NULL; md_list = md_list->next) {
643 md = (metadata *)md_list->data;
644 int path_len = strlen(app_path) + strlen((char *)md->value) + 2;
645 file_path = (char *)calloc(path_len, sizeof(char));
647 LOGE("failed to alloc memory");
651 if ((char)md->value[0] == '/')
652 snprintf(file_path, path_len, "%s%s",app_path, (char *)md->value);
654 snprintf(file_path, path_len, "%s%s%s",app_path, "/", (char *)md->value);
656 if (__get_sticker_info_from_json(appid, file_path, app_path) == 0)
657 LOGE("failed to get sticker information [path : %s]", file_path);
665 package_info_destroy(package_info);
676 int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgid, const char *appid, GList *list)
678 LOGD("METADATA UNINSTALL");
679 LOGD("pkgid: %s, appid: %s", pkgid, appid);
684 sqlite3_stmt *stmt = NULL;
686 GList *id_list = NULL;
688 db_path = tzplatform_mkpath(TZ_SYS_DB, ".sticker_info.db");
689 db = __db_open(db_path);
693 ret = sqlite3_prepare_v2(db, "SELECT sticker_info_id from sticker_info WHERE app_id = ?", -1, &stmt, NULL);
694 if (ret == SQLITE_OK) {
695 sqlite3_bind_text(stmt, 1, appid, -1, SQLITE_TRANSIENT);
696 while (sqlite3_step(stmt) == SQLITE_ROW) {
697 const unsigned char *record_id = sqlite3_column_text(stmt, 0);
699 id_list = g_list_append(id_list, strdup((const char *)record_id));
702 sqlite3_finalize(stmt);
705 for(GList *tmp = g_list_first(id_list); tmp != NULL; tmp = tmp->next) {
706 del_id = atoi((const char*)tmp->data);
707 __delete_sticker_info(db_path, del_id);
711 g_list_free_full(id_list, free);
713 LOGE("failed to get sticker id");
714 sqlite3_finalize(stmt);
722 int PKGMGR_MDPARSER_PLUGIN_UPGRADE(const char *pkgid, const char *appid, GList *list)
724 LOGD("METADATA UPGRADE");
725 LOGD("pkgid: %s, appid: %s", pkgid, appid);
727 PKGMGR_MDPARSER_PLUGIN_UNINSTALL(pkgid, appid, list);
728 PKGMGR_MDPARSER_PLUGIN_INSTALL(pkgid, appid, list);
733 int PKGMGR_CATEGORY_PARSER_PLUGIN_INSTALL(const char *pkgid, const char *appid, GList *list)
735 LOGD("STICKER CATEGORY INSTALL");
736 LOGD("pkgid: %s, appid: %s", pkgid, appid);
738 int len = strlen(STICKER_DIRECTORY) + strlen(appid) + 2;
739 char *dir_path = (char *)calloc(len, sizeof(char));
741 if (dir_path != NULL) {
742 snprintf(dir_path, len, "%s%s%s", STICKER_DIRECTORY, "/", appid);
743 LOGD("directory path : %s", dir_path);
745 if (mkdir(dir_path, 0755) == -1 && errno != EEXIST) {
746 strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
747 LOGE("directory create error : %s", error_buffer);
749 if (__change_ownership(dir_path, UIFW_ID, UIFW_ID) != 0)
750 LOGE("failed to change ownership");
761 int PKGMGR_CATEGORY_PARSER_PLUGIN_UNINSTALL(const char *pkgid, const char *appid, GList *list)
763 LOGD("STICKER CATEGORY UNINSTALL");
764 LOGD("pkgid: %s, appid: %s", pkgid, appid);
766 int len = strlen(STICKER_DIRECTORY) + strlen(appid) + 2;
767 char * dir_path = (char *)calloc(len, sizeof(char));
769 if (dir_path != NULL) {
770 snprintf(dir_path, len, "%s%s%s", STICKER_DIRECTORY, "/", appid);
771 LOGD("directory path : %s", dir_path);
773 if (__remove_directory(dir_path, 0) < 0) {
774 strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
775 LOGE("directory remove error : %s", error_buffer);
786 int PKGMGR_CATEGORY_PARSER_PLUGIN_UPGRADE(const char *pkgid, const char *appid, GList *list)
788 LOGD("STICKER CATEGORY UPGRADE");
789 LOGD("pkgid: %s, appid: %s", pkgid, appid);
791 PKGMGR_CATEGORY_PARSER_PLUGIN_UNINSTALL(pkgid, appid, list);
792 PKGMGR_CATEGORY_PARSER_PLUGIN_INSTALL(pkgid, appid, list);