diff --git a/src/main.c b/src/main.c index b7ed7c9b..b2112118 100644 --- a/src/main.c +++ b/src/main.c @@ -357,7 +357,14 @@ static int _tf_run_task(const tf_run_args_t* args, int index) tf_task_activate(task); if (args->ssb_port) { - tf_ssb_import(tf_task_get_ssb(task), "core", "apps"); + if (args->zip) + { + tf_ssb_import_from_zip(tf_task_get_ssb(task), args->zip, "core", "apps"); + } + else + { + tf_ssb_import(tf_task_get_ssb(task), "core", "apps"); + } } if (tf_task_execute(task, args->script)) { diff --git a/src/ssb.import.c b/src/ssb.import.c index 9a1c730e..b6e87889 100644 --- a/src/ssb.import.c +++ b/src/ssb.import.c @@ -11,6 +11,7 @@ #include #include #include +#include #include static void _tf_ssb_import_add_app(tf_ssb_t* ssb, const char* user, const char* app) @@ -237,7 +238,8 @@ void tf_ssb_import(tf_ssb_t* ssb, const char* user, const char* path) size_t len = strlen(path) + strlen(ent.name) + 2; char* full_path = tf_malloc(len); snprintf(full_path, len, "%s/%s", path, ent.name); - if (strcasecmp(ent.name + strlen(ent.name) - strlen(".json"), ".json") == 0) + if (strlen(ent.name) > strlen(".json") && + strcasecmp(ent.name + strlen(ent.name) - strlen(".json"), ".json") == 0) { _tf_ssb_import_app_json(ssb, tf_ssb_get_loop(ssb), tf_ssb_get_context(ssb), user, full_path); } @@ -250,3 +252,128 @@ void tf_ssb_import(tf_ssb_t* ssb, const char* user, const char* path) } uv_fs_req_cleanup(&req); } + +static char* _tf_ssb_import_read_current_file_from_zip(unzFile zip, size_t* size) +{ + char* result = NULL; + unz_file_info64 info = { 0 }; + if (unzGetCurrentFileInfo64(zip, &info, NULL, 0, NULL, 0, NULL, 0) == UNZ_OK) + { + char* buffer = tf_malloc(info.uncompressed_size + 1); + if (unzOpenCurrentFile(zip) == UNZ_OK) + { + if (unzReadCurrentFile(zip, buffer, info.uncompressed_size) == (int)info.uncompressed_size) + { + *size = info.uncompressed_size; + buffer[info.uncompressed_size] = '\0'; + result = buffer; + buffer = NULL; + } + unzCloseCurrentFile(zip); + } + tf_free(buffer); + } + return result; +} + +static void _tf_ssb_import_recursive_add_files_from_zip(tf_ssb_t* ssb, unzFile zip, JSContext* context, JSValue files, const char* root) +{ + if (unzGoToFirstFile(zip) == UNZ_OK) + { + while (unzGoToNextFile(zip) == UNZ_OK) + { + char file_path[256]; + unz_file_info64 info = { 0 }; + if (unzGetCurrentFileInfo64(zip, &info, file_path, sizeof(file_path), NULL, 0, NULL, 0) == UNZ_OK) + { + if (strncmp(file_path, root, strlen(root)) == 0 && + file_path[strlen(root)] == '/') + { + size_t size = 0; + char* blob = _tf_ssb_import_read_current_file_from_zip(zip, &size); + char id[k_id_base64_len] = { 0 }; + bool is_new = false; + if (tf_ssb_db_blob_store(ssb, (const uint8_t*)blob, size, id, sizeof(id), &is_new) && is_new) + { + tf_printf("Stored %s as %s.\n", file_path, id); + } + JS_SetPropertyStr(context, files, file_path + strlen(root) + 1, JS_NewString(context, id)); + + tf_free(blob); + } + } + } + } +} + +static void _tf_ssb_import_app_json_from_zip(tf_ssb_t* ssb, unzFile zip, JSContext* context, const char* user, const char* path) +{ + size_t size = 0; + char* file = _tf_ssb_import_read_current_file_from_zip(zip, &size); + if (file) + { + JSValue app = JS_ParseJSON(context, file, size, NULL); + if (!tf_util_report_error(context, app)) + { + char* dir = tf_strdup(path); + dir[strlen(dir) - strlen(".json")] = '\0'; + JSValue files = JS_NewObject(context); + _tf_ssb_import_recursive_add_files_from_zip(ssb, zip, context, files, dir); + JS_SetPropertyStr(context, app, "files", files); + + JSValue json = JS_JSONStringify(context, app, JS_NULL, JS_NULL); + size_t size = 0; + const char* blob = JS_ToCStringLen(context, &size, json); + char id[k_id_base64_len] = { 0 }; + if (tf_ssb_db_blob_store(ssb, (const uint8_t*)blob, size, id, sizeof(id), NULL)) + { + const char* app = dir; + char* slash = strrchr(dir, '/'); + app = slash ? slash + 1 : app; + + if (_tf_ssb_register_app(ssb, user, app, id)) + { + tf_printf("Registered %s path:%s as %s.\n", user, app, id); + _tf_ssb_import_add_app(ssb, user, app); + } + } + JS_FreeCString(context, blob); + JS_FreeValue(context, json); + + tf_free(dir); + } + JS_FreeValue(context, app); + tf_free(file); + } +} + +void tf_ssb_import_from_zip(tf_ssb_t* ssb, const char* zip_path, const char* user, const char* path) +{ + unzFile zip = unzOpen(zip_path); + if (zip) + { + tf_printf("Importing from %s.", zip_path); + if (unzGoToFirstFile(zip) == UNZ_OK) + { + while (unzGoToNextFile(zip) == UNZ_OK) + { + char file_path[256]; + unz_file_info64 info = { 0 }; + if (unzGetCurrentFileInfo64(zip, &info, file_path, sizeof(file_path), NULL, 0, NULL, 0) == UNZ_OK) + { + if (strncmp(file_path, path, strlen(path)) == 0 && + !strchr(file_path + strlen(path) + 1, '/') && + strlen(file_path) > strlen(".json") && + strcasecmp(file_path + strlen(file_path) - strlen(".json"), ".json") == 0) + { + unz_file_pos pos = { 0 }; + unzGetFilePos(zip, &pos); + _tf_ssb_import_app_json_from_zip(ssb, zip, tf_ssb_get_context(ssb), user, file_path); + unzGoToFilePos(zip, &pos); + } + } + } + } + unzClose(zip); + } +} diff --git a/src/ssb.import.h b/src/ssb.import.h index 73ab1707..e11d1933 100644 --- a/src/ssb.import.h +++ b/src/ssb.import.h @@ -3,3 +3,4 @@ typedef struct _tf_ssb_t tf_ssb_t; void tf_ssb_import(tf_ssb_t* ssb, const char* user, const char* path); +void tf_ssb_import_from_zip(tf_ssb_t* ssb, const char* zip_path, const char* user, const char* path);