From 44db400cbcf1044b5099db6042646afbc2afacec Mon Sep 17 00:00:00 2001 From: StackZ <47382115+SuperSaiyajinStackZ@users.noreply.github.com> Date: Sat, 21 Mar 2020 06:48:05 +0100 Subject: [PATCH] Add copy & move & more error checks. --- include/utils/fileBrowse.hpp | 3 ++ include/utils/scriptHelper.hpp | 8 ++- romfs/lang/en/app.json | 5 +- source/screens/scriptlist.cpp | 36 +++++++++++-- source/screens/unistore.cpp | 37 +++++++++++-- source/utils/fileBrowse.cpp | 97 ++++++++++++++++++++++++++++++++++ source/utils/scriptHelper.cpp | 35 +++++++++++- 7 files changed, 210 insertions(+), 11 deletions(-) diff --git a/include/utils/fileBrowse.hpp b/include/utils/fileBrowse.hpp index d7c29f5..a38a7e8 100644 --- a/include/utils/fileBrowse.hpp +++ b/include/utils/fileBrowse.hpp @@ -24,4 +24,7 @@ bool returnIfExist(const std::string &path, const std::vector &exte std::string selectFilePath(std::string selectText, const std::vector &extensionList, int selectionMode = 1); +void dirCopy(DirEntry* entry, int i, const char *destinationPath, const char *sourcePath); +int fcopy(const char *sourcePath, const char *destinationPath); + #endif //FILE_BROWSE_HPP \ No newline at end of file diff --git a/include/utils/scriptHelper.hpp b/include/utils/scriptHelper.hpp index c2a4fcc..d55cffe 100644 --- a/include/utils/scriptHelper.hpp +++ b/include/utils/scriptHelper.hpp @@ -52,6 +52,9 @@ enum ScriptState { FAILED_DOWNLOAD, SCRIPT_CANCELED, SYNTAX_ERROR, + COPY_ERROR, + MOVE_ERROR, + DELETE_ERROR, }; namespace ScriptHelper { @@ -63,7 +66,7 @@ namespace ScriptHelper { Result downloadRelease(std::string repo, std::string file, std::string output, bool includePrereleases, bool showVersions, std::string message); Result downloadFile(std::string file, std::string output, std::string message); - void removeFile(std::string file, std::string message); + Result removeFile(std::string file, std::string message); void installFile(std::string file, std::string message); void extractFile(std::string file, std::string input, std::string output, std::string message); Result createFile(const char * path); @@ -75,6 +78,9 @@ namespace ScriptHelper { void bootTitle(const std::string TitleID, bool isNAND, std::string message); Result prompt(std::string message); + + Result copyFile(std::string source, std::string destination, std::string message); + Result renameFile(std::string oldName, std::string newName, std::string message); } #endif \ No newline at end of file diff --git a/romfs/lang/en/app.json b/romfs/lang/en/app.json index 6e95dfc..bf4a9d6 100644 --- a/romfs/lang/en/app.json +++ b/romfs/lang/en/app.json @@ -170,5 +170,8 @@ "IS_PRERELEASE": "PreRelease: ", "DOWNLOAD_ERROR": "Download Error!", "SCRIPT_CANCELED": "Script Canceled!", - "SYNTAX_ERROR": "Syntax Error!" + "SYNTAX_ERROR": "Syntax Error!", + "COPY_ERROR": "Copy Error!", + "MOVE_ERROR": "Move Error!", + "DELETE_ERROR": "Delete Error!" } diff --git a/source/screens/scriptlist.cpp b/source/screens/scriptlist.cpp index e29c4e7..da22d5e 100644 --- a/source/screens/scriptlist.cpp +++ b/source/screens/scriptlist.cpp @@ -896,7 +896,7 @@ Result ScriptList::runFunctions(nlohmann::json &json) { if(json.at(choice).at(i).contains("file")) file = json.at(choice).at(i).at("file"); else missing = true; if(json.at(choice).at(i).contains("message")) message = json.at(choice).at(i).at("message"); - if(!missing) ScriptHelper::removeFile(file, message); + if(!missing) ret = ScriptHelper::removeFile(file, message); else ret = SYNTAX_ERROR; } else if(type == "downloadFile") { @@ -963,8 +963,12 @@ Result ScriptList::runFunctions(nlohmann::json &json) { else missing = true; promptmsg = Lang::get("DELETE_PROMPT") + "\n" + directory; if(!missing) { - if (Msg::promptMsg(promptmsg)) { - removeDirRecursive(directory.c_str()); + if(access(directory.c_str(), F_OK) != 0 ) { + ret = DELETE_ERROR; + } else { + if (Msg::promptMsg(promptmsg)) { + removeDirRecursive(directory.c_str()); + } } } else ret = SYNTAX_ERROR; @@ -1021,12 +1025,36 @@ Result ScriptList::runFunctions(nlohmann::json &json) { std::string Message = ""; if(json.at(choice).at(i).contains("message")) Message = json.at(choice).at(i).at("message"); ret = ScriptHelper::prompt(Message); + } else if (type == "copy") { + std::string Message = "", source = "", destination = ""; + bool missing = false; + if(json.at(choice).at(i).contains("source")) source = json.at(choice).at(i).at("source"); + else missing = true; + if(json.at(choice).at(i).contains("destination")) destination = json.at(choice).at(i).at("destination"); + else missing = true; + if(json.at(choice).at(i).contains("message")) Message = json.at(choice).at(i).at("message"); + if (!missing) ret = ScriptHelper::copyFile(source, destination, Message); + else ret = SYNTAX_ERROR; + + } else if (type == "move") { + std::string Message = "", oldFile = "", newFile = ""; + bool missing = false; + if(json.at(choice).at(i).contains("old")) oldFile = json.at(choice).at(i).at("old"); + else missing = true; + if(json.at(choice).at(i).contains("new")) newFile = json.at(choice).at(i).at("new"); + else missing = true; + if(json.at(choice).at(i).contains("message")) Message = json.at(choice).at(i).at("message"); + if (!missing) ret = ScriptHelper::renameFile(oldFile, newFile, Message); + else ret = SYNTAX_ERROR; } } } if (ret == NONE) doneMsg(); else if (ret == FAILED_DOWNLOAD) Msg::DisplayWarnMsg(Lang::get("DOWNLOAD_ERROR")); else if (ret == SCRIPT_CANCELED) Msg::DisplayWarnMsg(Lang::get("SCRIPT_CANCELED")); - else Msg::DisplayWarnMsg(Lang::get("SYNTAX_ERROR")); + else if (ret == SYNTAX_ERROR) Msg::DisplayWarnMsg(Lang::get("SYNTAX_ERROR")); + else if (ret == COPY_ERROR) Msg::DisplayWarnMsg(Lang::get("COPY_ERROR")); + else if (ret == MOVE_ERROR) Msg::DisplayWarnMsg(Lang::get("MOVE_ERROR")); + else if (ret == DELETE_ERROR) Msg::DisplayWarnMsg(Lang::get("DELETE_ERROR")); return ret; } \ No newline at end of file diff --git a/source/screens/unistore.cpp b/source/screens/unistore.cpp index bd0b636..4a30e06 100644 --- a/source/screens/unistore.cpp +++ b/source/screens/unistore.cpp @@ -1228,7 +1228,7 @@ Result UniStore::execute() { if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("file")) file = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("file"); else missing = true; if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) message = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("message"); - if(!missing) ScriptHelper::removeFile(file, message); + if(!missing) ret = ScriptHelper::removeFile(file, message); else ret = SYNTAX_ERROR; } else if(type == "downloadFile") { @@ -1296,8 +1296,12 @@ Result UniStore::execute() { else missing = true; promptmsg = Lang::get("DELETE_PROMPT") + "\n" + directory; if(!missing) { - if (Msg::promptMsg(promptmsg)) { - removeDirRecursive(directory.c_str()); + if(access(directory.c_str(), F_OK) != 0 ) { + ret = DELETE_ERROR; + } else { + if (Msg::promptMsg(promptmsg)) { + removeDirRecursive(directory.c_str()); + } } } else ret = SYNTAX_ERROR; @@ -1357,12 +1361,37 @@ Result UniStore::execute() { std::string Message = ""; if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) Message = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("message"); ret = ScriptHelper::prompt(Message); + + } else if (type == "copy") { + std::string Message = "", source = "", destination = ""; + bool missing = false; + if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("source")) source = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("source"); + else missing = true; + if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("destination")) destination = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("destination"); + else missing = true; + if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) Message = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("message"); + if (!missing) ret = ScriptHelper::copyFile(source, destination, Message); + else ret = SYNTAX_ERROR; + + } else if (type == "move") { + std::string Message = "", oldFile = "", newFile = ""; + bool missing = false; + if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("old")) oldFile = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("old"); + else missing = true; + if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("new")) newFile = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("new"); + else missing = true; + if(appStoreJson.at("storeContent").at(Selection).at("script").at(i).contains("message")) Message = appStoreJson.at("storeContent").at(Selection).at("script").at(i).at("message"); + if (!missing) ret = ScriptHelper::renameFile(oldFile, newFile, Message); + else ret = SYNTAX_ERROR; } } } if (ret == NONE) doneMsg(); else if (ret == FAILED_DOWNLOAD) Msg::DisplayWarnMsg(Lang::get("DOWNLOAD_ERROR")); else if (ret == SCRIPT_CANCELED) Msg::DisplayWarnMsg(Lang::get("SCRIPT_CANCELED")); - else Msg::DisplayWarnMsg(Lang::get("SYNTAX_ERROR")); + else if (ret == SYNTAX_ERROR) Msg::DisplayWarnMsg(Lang::get("SYNTAX_ERROR")); + else if (ret == COPY_ERROR) Msg::DisplayWarnMsg(Lang::get("COPY_ERROR")); + else if (ret == MOVE_ERROR) Msg::DisplayWarnMsg(Lang::get("MOVE_ERROR")); + else if (ret == DELETE_ERROR) Msg::DisplayWarnMsg(Lang::get("DELETE_ERROR")); return ret; } \ No newline at end of file diff --git a/source/utils/fileBrowse.cpp b/source/utils/fileBrowse.cpp index 14368c5..9e9593e 100644 --- a/source/utils/fileBrowse.cpp +++ b/source/utils/fileBrowse.cpp @@ -319,4 +319,101 @@ std::string selectFilePath(std::string selectText, const std::vector dirContents; + dirContents.clear(); + if(entry->isDirectory) chdir((sourcePath + ("/" + entry->name)).c_str()); + getDirectoryContents(dirContents); + if(((int)dirContents.size()) == 1) mkdir((destinationPath + ("/" + entry->name)).c_str(), 0777); + if(((int)dirContents.size()) != 1) fcopy((sourcePath + ("/" + entry->name)).c_str(), (destinationPath + ("/" + entry->name)).c_str()); +} + +int fcopy(const char *sourcePath, const char *destinationPath) { + DIR *isDir = opendir(sourcePath); + + if(isDir != NULL) { + closedir(isDir); + + // Source path is a directory + chdir(sourcePath); + std::vector dirContents; + getDirectoryContents(dirContents); + DirEntry* entry = &dirContents.at(1); + + mkdir(destinationPath, 0777); + for(int i = 1; i < ((int)dirContents.size()); i++) { + chdir(sourcePath); + entry = &dirContents.at(i); + dirCopy(entry, i, destinationPath, sourcePath); + } + + chdir(destinationPath); + chdir(".."); + return 1; + } else { + closedir(isDir); + + // Source path is a file + FILE* sourceFile = fopen(sourcePath, "rb"); + off_t fsize = 0; + if(sourceFile) { + fseek(sourceFile, 0, SEEK_END); + fsize = ftell(sourceFile); // Get source file's size + fseek(sourceFile, 0, SEEK_SET); + } else { + fclose(sourceFile); + return -1; + } + + FILE* destinationFile = fopen(destinationPath, "wb"); + //if(destinationFile) { + fseek(destinationFile, 0, SEEK_SET); + /*} else { + fclose(sourceFile); + fclose(destinationFile); + return -1; + }*/ + + off_t offset = 0; + int numr; + while(1) + { + scanKeys(); + if(keysHeld() & KEY_B) { + // Cancel copying + fclose(sourceFile); + fclose(destinationFile); + return -1; + break; + } + printf("\x1b[16;0H"); + printf("Progress:\n"); + printf("%i/%i Bytes ", (int)offset, (int)fsize); + + // Copy file to destination path + numr = fread(copyBuf, 2, copyBufSize, sourceFile); + fwrite(copyBuf, 2, numr, destinationFile); + offset += copyBufSize; + + if(offset > fsize) { + fclose(sourceFile); + fclose(destinationFile); + + printf("\x1b[17;0H"); + printf("%i/%i Bytes ", (int)fsize, (int)fsize); + for(int i = 0; i < 30; i++) gspWaitForVBlank(); + + return 1; + break; + } + } + + return -1; + } } \ No newline at end of file diff --git a/source/utils/scriptHelper.cpp b/source/utils/scriptHelper.cpp index d24d33c..ae455fa 100644 --- a/source/utils/scriptHelper.cpp +++ b/source/utils/scriptHelper.cpp @@ -26,12 +26,14 @@ #include "download.hpp" #include "extract.hpp" +#include "fileBrowse.hpp" #include "gui.hpp" #include "msg.hpp" #include "scriptHelper.hpp" #include "thread.hpp" #include +#include extern "C" { #include "cia.h" @@ -96,9 +98,14 @@ Result ScriptHelper::downloadFile(std::string file, std::string output, std::str } // Remove a File. -void ScriptHelper::removeFile(std::string file, std::string message) { +Result ScriptHelper::removeFile(std::string file, std::string message) { + Result ret = NONE; + if(access(file.c_str(), F_OK) != 0 ) { + return DELETE_ERROR; + } Msg::DisplayMsg(message); deleteFile(file.c_str()); + return ret; } // Install a file. @@ -194,4 +201,30 @@ Result ScriptHelper::prompt(std::string message) { ret = SCRIPT_CANCELED; } return ret; +} + +Result ScriptHelper::copyFile(std::string source, std::string destination, std::string message) { + Result ret = NONE; + if(access(source.c_str(), F_OK) != 0 ) { + return COPY_ERROR; + } + Msg::DisplayMsg(message); + // If destination does not exist, create dirs. + if(access(destination.c_str(), F_OK) != 0 ) { + makeDirs(destination.c_str()); + } + fcopy(source.c_str(), destination.c_str()); + return ret; +} + +Result ScriptHelper::renameFile(std::string oldName, std::string newName, std::string message) { + Result ret = NONE; + if(access(oldName.c_str(), F_OK) != 0 ) { + return MOVE_ERROR; + } + Msg::DisplayMsg(message); + // TODO: Kinda avoid that? + makeDirs(newName.c_str()); + rename(oldName.c_str(), newName.c_str()); + return ret; } \ No newline at end of file