Launch sticker-receiver for receiving sticker feature
[platform/core/uifw/capi-ui-sticker.git] / sticker-parser / sticker-parser.c
index dc27241..a54e9ab 100644 (file)
 #endif
 #define LOG_TAG "STICKER_PARSER"
 
-#define STICKER_DIRECTORY tzplatform_mkpath(TZ_SYS_SHARE, "sticker-data")
+#define STICKER_DIRECTORY "/opt/usr/share/sticker-data"
+#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)"
+#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)"
+#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)"
+#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)"
 #define UIFW_ID           502
 #define APPFW_ID          301
 #define MAX_ERROR_BUFFER  256
 
 static char error_buffer[MAX_ERROR_BUFFER];
+static gboolean is_corrupted = FALSE;
 
 typedef struct metadata {
     const char *key;
@@ -74,39 +79,168 @@ static int __get_int_from_object(JsonObject *object, const char *key)
     return type;
 }
 
-static sqlite3 *__db_open(const char *path)
+static int __change_ownership(const char *path, int user, int group)
+{
+    int ret;
+    uid_t uid = (uid_t)user;
+    gid_t gid = (gid_t)group;
+
+    ret = chown(path, uid, gid);
+    if (ret != 0) {
+        strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
+        LOGE("chown() failed : %s", error_buffer);
+    }
+
+    return ret;
+}
+
+static void __recover_db()
 {
     int ret;
     sqlite3 *db = NULL;
     char *err = NULL;
+    const char *db_path = tzplatform_mkpath(TZ_SYS_DB, ".sticker_info.db");
 
-    ret = sqlite3_open(path, &db);
+    LOGD("Start to recover sticker db");
+    if (unlink(db_path) == -1)
+        LOGE("Failed to remove db file");
+
+    ret = sqlite3_open_v2(db_path, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
     if (ret != SQLITE_OK) {
         LOGE("Failed to open db : %s", sqlite3_errmsg(db));
-        return NULL;
+        if (unlink(db_path) == -1)
+            LOGE("Failed to remove db file");
+        goto cleanup;
     }
 
-    ret = sqlite3_exec(db, "PRAGMA foreign_keys = ON", NULL, NULL, &err);
+    ret = sqlite3_exec(db, STICKER_INFO_CREATE_TABLE, NULL, NULL, &err);
     if (ret != SQLITE_OK) {
-        LOGE("Failed to turn on foreign keys : %s", err);
+        LOGE("Failed to create sticker_info table : %s" , err);
+        goto cleanup;
     }
 
-    return db;
+    ret = sqlite3_exec(db, STICKER_KEYWORD_INFO_CREATE_TABLE, NULL, NULL, &err);
+    if (ret != SQLITE_OK) {
+        LOGE("Failed to create sticker_keyword_info table : %s", err);
+        goto cleanup;
+    }
+
+    ret = sqlite3_exec(db, STICKER_WHITELIST_INFO_CREATE_TABLE, NULL, NULL, &err);
+    if (ret != SQLITE_OK) {
+        LOGE("Failed to create sticker_whitelist_info table : %s", err);
+        goto cleanup;
+    }
+
+    ret = sqlite3_exec(db, STICKER_RECENT_HISTORY_INFO_CREATE_TABLE, NULL, NULL, &err);
+    if (ret != SQLITE_OK) {
+        LOGE("Failed to create sticker_recent_history_info table : %s", err);
+        goto cleanup;
+    }
+
+    is_corrupted = FALSE;
+
+cleanup:
+    if (err)
+        sqlite3_free(err);
+
+    if (db)
+        sqlite3_close(db);
 }
 
-static int __change_ownership(const char *path, int user, int group)
+static int __integrity_check_cb(void *pid, int argc, char **argv, char **notUsed)
+{
+    if (strcmp(argv[0], "ok") != 0) {
+        LOGE("DB integrity check failed : %s", argv[0]);
+        is_corrupted = TRUE;
+        return -1;
+    }
+
+    LOGD("Result integrity : %s", argv[0]);
+    return 0;
+}
+
+static void __db_init()
 {
     int ret;
-    uid_t uid = (uid_t)user;
-    gid_t gid = (gid_t)group;
+    sqlite3 *db = NULL;
+    char *err = NULL;
+    const char *db_path = tzplatform_mkpath(TZ_SYS_DB, ".sticker_info.db");
 
-    ret = chown(path, uid, gid);
-    if (ret != 0) {
-        strerror_r(errno, error_buffer, MAX_ERROR_BUFFER);
-        LOGE("chown() failed : %s", error_buffer);
+    ret = sqlite3_open_v2(db_path, &db, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE, NULL);
+    if (ret != SQLITE_OK) {
+        LOGE("Failed to open db : %s", sqlite3_errmsg(db));
+        goto cleanup;
     }
 
-    return ret;
+    if (__change_ownership(db_path, UIFW_ID, UIFW_ID) != 0)
+        LOGE("failed to change ownership");
+
+    ret = sqlite3_exec(db, STICKER_INFO_CREATE_TABLE, NULL, NULL, &err);
+    if (ret != SQLITE_OK) {
+        LOGE("Failed to create sticker_info table : %s" , err);
+        goto cleanup;
+    }
+
+    ret = sqlite3_exec(db, STICKER_KEYWORD_INFO_CREATE_TABLE, NULL, NULL, &err);
+    if (ret != SQLITE_OK) {
+        LOGE("Failed to create sticker_keyword_info table : %s", err);
+        goto cleanup;
+    }
+
+    ret = sqlite3_exec(db, STICKER_WHITELIST_INFO_CREATE_TABLE, NULL, NULL, &err);
+    if (ret != SQLITE_OK) {
+        LOGE("Failed to create sticker_whitelist_info table : %s", err);
+        goto cleanup;
+    }
+
+    ret = sqlite3_exec(db, STICKER_RECENT_HISTORY_INFO_CREATE_TABLE, NULL, NULL, &err);
+    if (ret != SQLITE_OK) {
+        LOGE("Failed to create sticker_recent_history_info table : %s", err);
+        goto cleanup;
+    }
+
+    ret = sqlite3_exec(db, "PRAGMA journal_mode = WAL", NULL, NULL, &err);
+    if (ret != SQLITE_OK) {
+        LOGE("Failed to set journal_mode : %s", err);
+        goto cleanup;
+    }
+
+    ret = sqlite3_exec(db, "PRAGMA integrity_check", __integrity_check_cb, NULL, &err);
+    if (ret != SQLITE_OK)
+        LOGE("Failed to check integrity : %s", err);
+
+cleanup:
+    if (err)
+        sqlite3_free(err);
+
+    if (db)
+        sqlite3_close(db);
+
+    if (ret == SQLITE_CORRUPT || ret == SQLITE_NOTADB || is_corrupted)
+        __recover_db();
+}
+
+static sqlite3 *__db_open(const char *path)
+{
+    int ret;
+    sqlite3 *db = NULL;
+    char *err = NULL;
+
+    ret = sqlite3_open(path, &db);
+    if (ret != SQLITE_OK) {
+        LOGE("Failed to open db : %s", sqlite3_errmsg(db));
+        return NULL;
+    }
+
+    ret = sqlite3_exec(db, "PRAGMA foreign_keys = ON", NULL, NULL, &err);
+    if (ret != SQLITE_OK) {
+        LOGE("Failed to turn on foreign keys : %s", err);
+    }
+
+    if (err)
+        sqlite3_free(err);
+
+    return db;
 }
 
 static int __remove_app_path(char *uri, const char *app_path)
@@ -227,21 +361,17 @@ cleanup:
     return ret;
 }
 
-static char* __convert_sticker_uri(const char *uri, const char *appid, const char *app_path)
+static char* __convert_sticker_uri(char *uri, const char *appid, const char *app_path)
 {
     int ret;
-    char *rel_path = strdup(uri);
 
-    __remove_app_path(rel_path, app_path);
-    int len = strlen(STICKER_DIRECTORY) + strlen(appid) + strlen(rel_path) + 2;
+    __remove_app_path(uri, app_path);
+    int len = strlen(STICKER_DIRECTORY) + strlen(appid) + strlen(uri) + 2;
     char *new_path = (char *)calloc(len, sizeof(char));
-    if (new_path == NULL) {
-        free(rel_path);
-        rel_path = NULL;
+    if (new_path == NULL)
         return NULL;
-    }
 
-    snprintf(new_path, len, "%s/%s%s",STICKER_DIRECTORY, appid, rel_path);
+    snprintf(new_path, len, "%s/%s%s",STICKER_DIRECTORY, appid, uri);
 
     if (access(new_path, F_OK) == 0) {
         LOGE("sticker file already exists");
@@ -272,9 +402,6 @@ static char* __convert_sticker_uri(const char *uri, const char *appid, const cha
         LOGE("failed to change ownership");
 
 cleanup:
-    free(rel_path);
-    rel_path = NULL;
-
     if (ret == 0) {
         return new_path;
     } else {
@@ -284,7 +411,7 @@ cleanup:
     }
 }
 
-static void __insert_sticker_info(const char *app_id, int type, const char *uri, const char *group, const char *thumbnail, const char *description)
+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)
 {
     int ret;
     sqlite3 *db = NULL;
@@ -296,7 +423,7 @@ static void __insert_sticker_info(const char *app_id, int type, const char *uri,
     if (!db)
         return;
 
-    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);
+    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);
     if (ret == SQLITE_OK) {
         sqlite3_bind_text(stmt, 1, app_id, -1, SQLITE_TRANSIENT);
         sqlite3_bind_int(stmt, 2, type);
@@ -304,6 +431,7 @@ static void __insert_sticker_info(const char *app_id, int type, const char *uri,
         sqlite3_bind_text(stmt, 4, thumbnail, -1, SQLITE_TRANSIENT);
         sqlite3_bind_text(stmt, 5, description, -1, SQLITE_TRANSIENT);
         sqlite3_bind_text(stmt, 6, group, -1, SQLITE_TRANSIENT);
+        sqlite3_bind_int(stmt, 7, disp_type);
 
         ret = sqlite3_step(stmt);
         if (ret != SQLITE_OK && ret != SQLITE_DONE)
@@ -378,15 +506,50 @@ static void __insert_sticker_keyword_info(const char *keyword)
     return;
 }
 
+static void __insert_sticker_whitelist_info(const char *provider, const char *consumer) {
+    int ret;
+    sqlite3 *db = NULL;
+    sqlite3_stmt *stmt = NULL;
+    const char *db_path;
+
+    db_path = tzplatform_mkpath(TZ_SYS_DB, ".sticker_info.db");
+    db = __db_open(db_path);
+    if (!db)
+        return;
+
+    ret = sqlite3_prepare_v2(db, "INSERT INTO sticker_whitelist_info (provider_id, consumer_id) VALUES (?, ?)", -1, &stmt, NULL);
+    if (ret == SQLITE_OK) {
+        sqlite3_bind_text(stmt, 1, provider, -1, SQLITE_TRANSIENT);
+        sqlite3_bind_text(stmt, 2, consumer, -1, SQLITE_TRANSIENT);
+
+        ret = sqlite3_step(stmt);
+        if (ret != SQLITE_OK && ret != SQLITE_DONE)
+            LOGE("sqlite3_step() failed : ret(%d)", ret);
+
+        if (sqlite3_changes(db) == 0)
+            LOGE("No changes to DB");
+
+        sqlite3_finalize(stmt);
+        sqlite3_close(db);
+    } else {
+        LOGE("fail to insert sticker whiltelist : %s", sqlite3_errmsg(db));
+        sqlite3_finalize(stmt);
+        sqlite3_close(db);
+    }
+
+    return;
+}
+
 static int __get_sticker_info_from_json(const char *appid, const char *file_path, const char *app_path)
 {
     int ret = 1;
+    int arr_len = 0;
     JsonParser* parser = NULL;
     GError* err_msg = NULL;
     char *uri = NULL;
     char *group = NULL;
     char *description = NULL;
-    char *thumbnail = NULL;
+    char *thumbnail_path = NULL;
     char *uri_path = NULL;
 
     parser = json_parser_new();
@@ -411,6 +574,13 @@ static int __get_sticker_info_from_json(const char *appid, const char *file_path
         goto cleanup;
     }
 
+    JsonArray *whitelist_arr = json_object_get_array_member(root_obj, "whitelist");
+    if (whitelist_arr != NULL) {
+        for (int i = 0; i < json_array_get_length(whitelist_arr); i++) {
+            __insert_sticker_whitelist_info(appid, json_array_get_string_element(whitelist_arr, i));
+        }
+    }
+
     JsonArray *sticker_arr = json_object_get_array_member(root_obj, "sticker");
     if (sticker_arr == NULL) {
         LOGE("failed to get array member");
@@ -418,7 +588,7 @@ static int __get_sticker_info_from_json(const char *appid, const char *file_path
         goto cleanup;
     }
 
-    int arr_len = json_array_get_length(sticker_arr);
+    arr_len = json_array_get_length(sticker_arr);
     for (int i = 0; i < arr_len; i++) {
         JsonObject *info_object = json_array_get_object_element(sticker_arr, i);
         if (info_object != NULL) {
@@ -434,8 +604,16 @@ static int __get_sticker_info_from_json(const char *appid, const char *file_path
             if (!group)
                 goto free_memory;
 
-            thumbnail = __get_string_from_object(info_object, "thumbnail");
+            char *rel_thumbnail = __get_string_from_object(info_object, "thumbnail");
+            if (rel_thumbnail) {
+                if (rel_thumbnail[0] != '\0')
+                    thumbnail_path = __convert_sticker_uri(rel_thumbnail, appid, app_path);
+
+                free(rel_thumbnail);
+            }
+
             description = __get_string_from_object(info_object, "description");
+            int disp_type = __get_int_from_object(info_object, "display_type");
 
             JsonArray *keyword_arr = json_object_get_array_member(info_object, "keyword");
             int keyword_arr_len = json_array_get_length(keyword_arr);
@@ -447,7 +625,7 @@ static int __get_sticker_info_from_json(const char *appid, const char *file_path
                     char *new_uri = __convert_sticker_uri(uri, appid, app_path);
                     if (!new_uri)
                         goto free_memory;
-                    __insert_sticker_info(appid, type, new_uri, group, thumbnail, description);
+                    __insert_sticker_info(appid, type, new_uri, group, thumbnail_path, description, disp_type);
 
                     if (new_uri) {
                         free(new_uri);
@@ -473,7 +651,7 @@ static int __get_sticker_info_from_json(const char *appid, const char *file_path
                             uri_path = NULL;
                             goto free_memory;
                         }
-                        __insert_sticker_info(appid, type, new_uri, group, thumbnail, description);
+                        __insert_sticker_info(appid, type, new_uri, group, thumbnail_path, description, disp_type);
 
                         free(new_uri);
                         new_uri = NULL;
@@ -488,7 +666,7 @@ static int __get_sticker_info_from_json(const char *appid, const char *file_path
                     }
                 }
             } else {
-                __insert_sticker_info(appid, type, uri, group, thumbnail, description);
+                __insert_sticker_info(appid, type, uri, group, thumbnail_path, description, disp_type);
             }
 
             for (int j = 0; j < keyword_arr_len; j++) {
@@ -506,9 +684,9 @@ free_memory:
                 group = NULL;
             }
 
-            if (thumbnail) {
-                free(thumbnail);
-                thumbnail = NULL;
+            if (thumbnail_path) {
+                free(thumbnail_path);
+                thumbnail_path = NULL;
             }
 
             if (description) {
@@ -528,6 +706,47 @@ cleanup:
     return ret;
 }
 
+static void __delete_sticker_whitelist(const char *db_path, const char *app_id)
+{
+    int ret;
+    sqlite3 *db = NULL;
+    sqlite3_stmt *stmt = NULL;
+
+    db = __db_open(db_path);
+    if (!db)
+        return;
+
+    ret = sqlite3_prepare_v2(db, "DELETE FROM sticker_whitelist_info WHERE provider_id = ?", -1, &stmt, NULL);
+    if (ret != SQLITE_OK) {
+        LOGE("failed to delete sticker whitelist : %s", sqlite3_errmsg(db));
+        sqlite3_finalize(stmt);
+        sqlite3_close(db);
+        goto cleanup;
+    }
+
+    sqlite3_bind_text(stmt, 1, app_id, -1, SQLITE_TRANSIENT);
+
+    ret = sqlite3_step(stmt);
+    if (ret != SQLITE_OK && ret != SQLITE_DONE) {
+        LOGE("sqlite3_step() failed : ret(%d)", ret);
+        goto cleanup;
+    }
+
+    if (sqlite3_changes(db) == 0) {
+        LOGE("No changes to DB");
+        goto cleanup;
+    }
+
+    sqlite3_finalize(stmt);
+    sqlite3_close(db);
+    return;
+
+cleanup:
+    sqlite3_finalize(stmt);
+    sqlite3_close(db);
+    return;
+}
+
 static void __delete_sticker_info(const char *db_path, int record_id)
 {
     int ret;
@@ -617,46 +836,41 @@ int PKGMGR_MDPARSER_PLUGIN_INSTALL(const char *pkgid, const char *appid, GList *
     LOGD("METADATA INSTALL");
     LOGD("pkgid: %s, appid: %s", pkgid, appid);
 
-    metadata *md = NULL;
-    GList *md_list = NULL;
+    metadata *md = (metadata *)list->data;
     package_info_h package_info = NULL;
     char *app_path = NULL;
     char *file_path = NULL;
     int ret = 0;
 
+    __db_init();
+
     ret = package_info_create(pkgid, &package_info);
     if (ret != PACKAGE_MANAGER_ERROR_NONE || package_info == NULL) {
-        LOGE("faild to create package_info. ret: %d", ret);
+        LOGE("failed to create package_info. ret: %d", ret);
         goto cleanup;
     }
 
     ret = package_info_get_root_path(package_info, &app_path);
     if (ret != PACKAGE_MANAGER_ERROR_NONE || app_path == NULL) {
-        LOGE("faild to create package_info. ret: %d", ret);
+        LOGE("failed to create package_info. ret: %d", ret);
         goto cleanup;
     }
 
-    for(md_list = g_list_first(list); md_list != NULL; md_list = md_list->next) {
-        md = (metadata *)md_list->data;
-        int path_len = strlen(app_path) + strlen((char *)md->value) + 2;
-        file_path = (char *)calloc(path_len, sizeof(char));
-        if (!file_path) {
-            LOGE("failed to alloc memory");
-            continue;
-        }
+    int path_len = strlen(app_path) + strlen((char *)md->value) + 2;
+    file_path = (char *)calloc(path_len, sizeof(char));
+    if (!file_path) {
+        LOGE("failed to alloc memory");
+        goto cleanup;
+    }
 
-        if ((char)md->value[0] == '/')
-            snprintf(file_path, path_len, "%s%s",app_path, (char *)md->value);
-        else
-            snprintf(file_path, path_len, "%s%s%s",app_path, "/", (char *)md->value);
+    if ((char)md->value[0] == '/')
+        snprintf(file_path, path_len, "%s%s",app_path, (char *)md->value);
+    else
+        snprintf(file_path, path_len, "%s%s%s",app_path, "/", (char *)md->value);
 
-        if (__get_sticker_info_from_json(appid, file_path, app_path) == 0)
+    if (__get_sticker_info_from_json(appid, file_path, app_path) == 0)
             LOGE("failed to get sticker information [path : %s]", file_path);
 
-        free(file_path);
-        file_path = NULL;
-    }
-
 cleanup:
     if (package_info)
         package_info_destroy(package_info);
@@ -666,6 +880,11 @@ cleanup:
         app_path = NULL;
     }
 
+    if (file_path) {
+        free(file_path);
+        file_path = NULL;
+    }
+
     return 0;
 }
 
@@ -712,6 +931,8 @@ int PKGMGR_MDPARSER_PLUGIN_UNINSTALL(const char *pkgid, const char *appid, GList
         sqlite3_close(db);
     }
 
+    __delete_sticker_whitelist(db_path, appid);
+
     return 0;
 }