diff --git a/Dockerfile.portable-json-creator b/Dockerfile.portable-json-creator new file mode 100644 index 0000000..53add01 --- /dev/null +++ b/Dockerfile.portable-json-creator @@ -0,0 +1,7 @@ +FROM onedev.site.tesses.net/tesses-framework/tesses-framework:latest + +COPY ./portable-json-creator /wwwroot + +EXPOSE 4999 + +ENTRYPOINT ["tfileserver","--port","4999","/wwwroot"] \ No newline at end of file diff --git a/docker-compose/portable-json-creator/docker-compose.yml b/docker-compose/portable-json-creator/docker-compose.yml new file mode 100644 index 0000000..2917c48 --- /dev/null +++ b/docker-compose/portable-json-creator/docker-compose.yml @@ -0,0 +1,5 @@ +services: + portable-json: + image: onedev.site.tesses.net/tesses-framework/portable-json-creator:latest + ports: + - "4999:4999" \ No newline at end of file diff --git a/include/TessesFramework/Common.hpp b/include/TessesFramework/Common.hpp index 5c96d27..9f129fe 100644 --- a/include/TessesFramework/Common.hpp +++ b/include/TessesFramework/Common.hpp @@ -13,6 +13,7 @@ namespace Tesses::Framework { + template class Event { public: @@ -90,6 +91,7 @@ namespace Tesses::Framework extern EventList OnItteraton; std::optional TF_GetCommandName(); + void TF_Init(); void TF_InitWithConsole(); void TF_AllowPortable(std::string argv0); diff --git a/include/TessesFramework/Platform/Environment.hpp b/include/TessesFramework/Platform/Environment.hpp index 6000c96..349e29d 100644 --- a/include/TessesFramework/Platform/Environment.hpp +++ b/include/TessesFramework/Platform/Environment.hpp @@ -6,7 +6,23 @@ namespace Tesses::Framework::Platform::Environment { extern const char EnvPathSeperator; - + struct PortableAppConfig { + + std::optional desktop; + std::optional documents; + std::optional music; + std::optional pictures; + std::optional videos; + std::optional downloads; + std::optional user; + std::optional config; + std::optional state; + std::optional data; + std::optional cache; + std::optional temp; + }; + + extern PortableAppConfig portable_config; namespace SpecialFolders { Tesses::Framework::Filesystem::VFSPath GetTemp(); diff --git a/portable-json-creator/index.html b/portable-json-creator/index.html new file mode 100644 index 0000000..0b181bc --- /dev/null +++ b/portable-json-creator/index.html @@ -0,0 +1,25 @@ + + + + + + TessesFramework portable.json creator + + +

TessesFramework portable.json creator

+ + Choose the way you want your app to be portable + + + \ No newline at end of file diff --git a/portable-json-creator/portableapps/index.html b/portable-json-creator/portableapps/index.html new file mode 100644 index 0000000..6c3d6af --- /dev/null +++ b/portable-json-creator/portableapps/index.html @@ -0,0 +1,98 @@ + + + + + + TessesFramework portable.json creator + + +

TessesFramework portable.json creator

+ Don't want PortableApps.com click here for just having directories relative to application + +
+ Configuration + + + + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + + +
+ + + +
+ + + + \ No newline at end of file diff --git a/portable-json-creator/relative/index.html b/portable-json-creator/relative/index.html new file mode 100644 index 0000000..3f99661 --- /dev/null +++ b/portable-json-creator/relative/index.html @@ -0,0 +1,157 @@ + + + + + + TessesFramework portable.json creator + + +

TessesFramework portable.json creator

+ Want PortableApps.com click here +
system: don't make this folder portable, default: the default value (not portable if TF_User directory is "system", otherwise it's a subdirectory in the TF_User directory), anything else is relative to executable directory (for all of these) +
Please use "/" and not "\" even if on Windows +
+ Configuration + + + + + + + +
+ + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + +
+ + + + + + + + +
+ + + + + + + + +
+ + + + + + + + +
+ + + + + + + + +
+ + + + + + + + +
+ + + + + + + +
+ + + + + + + diff --git a/src/Filesystem/TempFS.cpp b/src/Filesystem/TempFS.cpp index 388d190..c271127 100644 --- a/src/Filesystem/TempFS.cpp +++ b/src/Filesystem/TempFS.cpp @@ -210,7 +210,13 @@ namespace Tesses::Framework::Filesystem { } TempFS::~TempFS() { - Close(); + VFSPath p; + p.relative = false; + p.path.push_back(this->tmp_str); + this->vfs = nullptr; + if(this->deleteOnDestroy && this->parent->DirectoryExists(p)) + this->parent->DeleteDirectoryRecurse(p); + } } \ No newline at end of file diff --git a/src/Platform/Environment.cpp b/src/Platform/Environment.cpp index 9c803ca..cf487b0 100644 --- a/src/Platform/Environment.cpp +++ b/src/Platform/Environment.cpp @@ -22,15 +22,23 @@ namespace Tesses::Framework::Platform::Environment #else const char EnvPathSeperator=':'; #endif + PortableAppConfig portable_config; namespace SpecialFolders { VFSPath GetTemp() { + + if(portable_config.temp) + return *portable_config.temp; return std::filesystem::temp_directory_path().string(); } VFSPath GetHomeFolder() { + + if(portable_config.user) + return *portable_config.user; + #if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS) && !defined(SAGO_DISABLE) return sago::getHomeDir(); #elif defined(__EMSCRIPTEN__) @@ -43,6 +51,9 @@ namespace Tesses::Framework::Platform::Environment } VFSPath GetDownloads() { + if(portable_config.downloads) + return *portable_config.downloads; + #if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS) && !defined(SAGO_DISABLE) return sago::getDownloadFolder(); #elif defined(__ANDROID__) @@ -53,6 +64,9 @@ namespace Tesses::Framework::Platform::Environment } VFSPath GetMusic() { + + if(portable_config.music) + return *portable_config.music; #if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS) && !defined(SAGO_DISABLE) return sago::getMusicFolder(); #elif defined(__ANDROID__) @@ -63,6 +77,9 @@ namespace Tesses::Framework::Platform::Environment } VFSPath GetPictures() { + + if(portable_config.pictures) + return *portable_config.pictures; #if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS) && !defined(SAGO_DISABLE) return sago::getPicturesFolder(); #elif defined(__ANDROID__) @@ -73,6 +90,8 @@ namespace Tesses::Framework::Platform::Environment } VFSPath GetVideos() { + if(portable_config.videos) + return *portable_config.videos; #if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS) && !defined(SAGO_DISABLE) return sago::getVideoFolder(); #elif defined(__ANDROID__) @@ -83,6 +102,9 @@ namespace Tesses::Framework::Platform::Environment } VFSPath GetDocuments() { + + if(portable_config.documents) + return *portable_config.documents; #if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS) && !defined(SAGO_DISABLE) return sago::getDocumentsFolder(); #elif defined(__ANDROID__) @@ -93,6 +115,9 @@ namespace Tesses::Framework::Platform::Environment } VFSPath GetConfig() { + + if(portable_config.config) + return *portable_config.config; #if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS) && !defined(SAGO_DISABLE) return sago::getConfigHome(); #else @@ -101,6 +126,8 @@ namespace Tesses::Framework::Platform::Environment } VFSPath GetDesktop() { + if(portable_config.desktop) + return *portable_config.desktop; #if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS) && !defined(SAGO_DISABLE) return sago::getDesktopFolder(); #else @@ -109,6 +136,9 @@ namespace Tesses::Framework::Platform::Environment } VFSPath GetState() { + + if(portable_config.state) + return *portable_config.state; #if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS) && !defined(SAGO_DISABLE) return sago::getStateDir(); #else @@ -117,6 +147,9 @@ namespace Tesses::Framework::Platform::Environment } VFSPath GetCache() { + + if(portable_config.cache) + return *portable_config.cache; #if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS) && !defined(SAGO_DISABLE) return sago::getCacheDir(); #else @@ -125,6 +158,9 @@ namespace Tesses::Framework::Platform::Environment } VFSPath GetData() { + + if(portable_config.data) + return *portable_config.data; #if defined(TESSESFRAMEWORK_ENABLE_PLATFORMFOLDERS) && !defined(SAGO_DISABLE) return sago::getDataHome(); #else diff --git a/src/Streams/FileStream.cpp b/src/Streams/FileStream.cpp index 0bc2a7f..6e4dd9c 100644 --- a/src/Streams/FileStream.cpp +++ b/src/Streams/FileStream.cpp @@ -104,7 +104,12 @@ namespace Tesses::Framework::Streams } FileStream::~FileStream() { - Close(); + if(!f) return; + if(this->owns) + { + fclose(this->f); + f=NULL; + } } void FileStream::Close() { diff --git a/src/Streams/NetworkStream.cpp b/src/Streams/NetworkStream.cpp index 91560c2..07ff02d 100644 --- a/src/Streams/NetworkStream.cpp +++ b/src/Streams/NetworkStream.cpp @@ -538,7 +538,10 @@ namespace Tesses::Framework::Streams { TcpServer::~TcpServer() { if(this->valid && this->owns) - Close(); + { + NETWORK_CLOSE(this->sock); + } + this->valid=false; } void TcpServer::Close() { @@ -818,7 +821,9 @@ namespace Tesses::Framework::Streams { } NetworkStream::~NetworkStream() { - Close(); + if(this->owns && this->success) + NETWORK_CLOSE(this->sock); + this->success=0; } void NetworkStream::SetNoDelay(bool noDelay) { @@ -945,5 +950,8 @@ uint16_t TcpServer::GetPort() { return 0; } +bool NetworkStream::DataAvailable(int to){ + return false; +} } #endif diff --git a/src/Streams/PtyStream.cpp b/src/Streams/PtyStream.cpp index 786f457..5aaa57f 100644 --- a/src/Streams/PtyStream.cpp +++ b/src/Streams/PtyStream.cpp @@ -126,7 +126,13 @@ namespace Tesses::Framework::Streams { } PtyStream::~PtyStream() { - Close(); + if(this->eos) return; + this->eos=true; + #if !defined(GEKKO) && !defined(__APPLE__) && !defined(__PS2__) && !defined(_WIN32) && !defined(__SWITCH__) && !defined(__FreeBSD__) && defined(TESSESFRAMEWORK_ENABLE_PROCESS) + close(this->socket); + + kill((pid_t)this->pid,SIGHUP); + #endif } void PtyStream::Close() { diff --git a/src/TF_Init.cpp b/src/TF_Init.cpp index 45f2f31..d61aaa2 100644 --- a/src/TF_Init.cpp +++ b/src/TF_Init.cpp @@ -2,6 +2,9 @@ #include "TessesFramework/Streams/NetworkStream.hpp" #include "TessesFramework/Lazy.hpp" #include "TessesFramework/Filesystem/LocalFS.hpp" +#include "TessesFramework/Platform/Environment.hpp" +#include "TessesFramework/Filesystem/FSHelpers.hpp" +#include "TessesFramework/Serialization/Json.hpp" #include #include #include @@ -329,10 +332,390 @@ if (iResult != 0) { } std::optional _argv0=std::nullopt; + void TF_AllowPortable(std::string argv0) { + using namespace Tesses::Framework::Serialization::Json; + using namespace Tesses::Framework::Platform::Environment; + using namespace Tesses::Framework::Filesystem; _argv0 = argv0; + VFSPath path(argv0); + auto realPath=path.MakeAbsolute(); + auto dir = realPath.GetParent(); + auto portable=dir / "portable.json"; + if(LocalFS->FileExists(portable)) + { + + std::string portable_str; + Helpers::ReadAllText(LocalFS,portable, portable_str); + auto jsonObj=Json::Decode(portable_str); + JObject dict; + JObject dict2; + if(TryGetJToken(jsonObj,dict) && dict.TryGetValueAsType("portable_data",dict2)) + { + + if(dict.TryGetValueAsType("portable_type", portable_str)) + { + if(portable_str == "PortableApps.com") + { + //do the special stuffs for PortableApps.com based apps + auto paf_documents = GetVariable("PortableApps.comDocuments"); + auto paf_music = GetVariable("PortableApps.comMusic"); + auto paf_pictures = GetVariable("PortableApps.comPictures"); + auto paf_videos = GetVariable("PortableApps.comVideos"); + auto paf_data = GetVariable("PAL:DataDir"); + + + + bool bV=false; + if(!dict2.TryGetValueAsType("system_documents",bV) || !bV) + { + if(paf_documents) + { + portable_config.documents = LocalFS->SystemToVFSPath(*paf_documents); + } + } + if(!dict2.TryGetValueAsType("system_pictures",bV) || !bV) + { + if(paf_pictures) + { + portable_config.pictures = LocalFS->SystemToVFSPath(*paf_pictures); + } + } + if(!dict2.TryGetValueAsType("system_videos",bV) || !bV) + { + if(paf_videos) + { + portable_config.videos = LocalFS->SystemToVFSPath(*paf_videos); + } + } + if(!dict2.TryGetValueAsType("system_music",bV) || !bV) + { + if(paf_music) + { + portable_config.music = LocalFS->SystemToVFSPath(*paf_music); + } + } + if(dict2.TryGetValueAsType("user",portable_str)) + { + if(portable_str == "app") + { + if(paf_data) + portable_config.user = LocalFS->SystemToVFSPath(*paf_data) / "TF_User"; + } + else if(portable_str == "documents") + { + if(paf_documents) + portable_config.user = LocalFS->SystemToVFSPath(*paf_documents) / "TF_User"; + } + } + if(dict2.TryGetValueAsType("desktop",portable_str)) + { + if(portable_str == "tf_user") + { + if(portable_config.user) + portable_config.desktop = *(portable_config.user) / "Desktop"; + } + else if(portable_str == "documents") + { + if(paf_documents) + portable_config.desktop = LocalFS->SystemToVFSPath(*paf_documents) / "Desktop"; + } + } + if(dict2.TryGetValueAsType("downloads",portable_str)) + { + if(portable_str == "tf_user") + { + if(portable_config.user) + portable_config.downloads = *(portable_config.user) / "Downloads"; + } + else if(portable_str == "documents") + { + if(paf_documents) + portable_config.downloads = LocalFS->SystemToVFSPath(*paf_documents) / "Downloads"; + } + } + if(!dict2.TryGetValueAsType("system_config",bV) || !bV) + { + if(portable_config.user) + portable_config.config = *(portable_config.user) / "Config"; + } + if(!dict2.TryGetValueAsType("system_cache",bV) || !bV) + { + if(portable_config.user) + portable_config.cache = *(portable_config.user) / "Cache"; + } + if(!dict2.TryGetValueAsType("system_data",bV) || !bV) + { + if(portable_config.user) + portable_config.data = *(portable_config.user) / "Data"; + } + if(!dict2.TryGetValueAsType("system_state",bV) || !bV) + { + if(portable_config.user) + portable_config.state = *(portable_config.user) / "State"; + } + if(!dict2.TryGetValueAsType("system_temp",bV) || !bV) + { + if(portable_config.user) + portable_config.temp = *(portable_config.user) / "Temp"; + } + } + else if(portable_str == "relative") + { + if(dict2.TryGetValueAsType("user",portable_str)) + { + if(portable_str != "system") + { + auto userDir = dir / portable_str; + portable_config.user = userDir.CollapseRelativeParents(); + + + } + + + + } + + if(dict2.TryGetValueAsType("documents", portable_str)) + { + + if(portable_str != "system") + { + if(portable_str == "default") + { + if(portable_config.user) + { + portable_config.documents = *(portable_config.user) / "Documents"; + } + } + else + { + auto userDir = dir / portable_str; + portable_config.documents = userDir.CollapseRelativeParents(); + + } + } + } + if(dict2.TryGetValueAsType("downloads", portable_str)) + { + + if(portable_str != "system") + { + if(portable_str == "default") + { + if(portable_config.user) + { + portable_config.downloads = *(portable_config.user) / "Downloads"; + } + } + else + { + auto userDir = dir / portable_str; + portable_config.downloads = userDir.CollapseRelativeParents(); + + } + } + } + if(dict2.TryGetValueAsType("desktop", portable_str)) + { + + if(portable_str != "system") + { + if(portable_str == "default") + { + if(portable_config.user) + { + portable_config.desktop = *(portable_config.user) / "Desktop"; + } + } + else + { + auto userDir = dir / portable_str; + portable_config.desktop = userDir.CollapseRelativeParents(); + + } + } + } + if(dict2.TryGetValueAsType("pictures", portable_str)) + { + + if(portable_str != "system") + { + if(portable_str == "default") + { + if(portable_config.user) + { + portable_config.pictures = *(portable_config.user) / "Pictures"; + } + } + else + { + auto userDir = dir / portable_str; + portable_config.pictures = userDir.CollapseRelativeParents(); + + } + } + } + if(dict2.TryGetValueAsType("videos", portable_str)) + { + + if(portable_str != "system") + { + if(portable_str == "default") + { + if(portable_config.user) + { + portable_config.videos = *(portable_config.user) / "Videos"; + } + } + else + { + auto userDir = dir / portable_str; + portable_config.videos = userDir.CollapseRelativeParents(); + + } + } + } + if(dict2.TryGetValueAsType("music", portable_str)) + { + + if(portable_str != "system") + { + if(portable_str == "default") + { + if(portable_config.user) + { + portable_config.music = *(portable_config.user) / "Music"; + } + } + else + { + auto userDir = dir / portable_str; + portable_config.music = userDir.CollapseRelativeParents(); + + } + } + } + if(dict2.TryGetValueAsType("config", portable_str)) + { + + if(portable_str != "system") + { + if(portable_str == "default") + { + if(portable_config.user) + { + portable_config.config = *(portable_config.user) / "Config"; + } + } + else + { + auto userDir = dir / portable_str; + portable_config.config = userDir.CollapseRelativeParents(); + + } + } + } + if(dict2.TryGetValueAsType("cache", portable_str)) + { + + if(portable_str != "system") + { + if(portable_str == "default") + { + if(portable_config.user) + { + portable_config.cache = *(portable_config.user) / "Cache"; + } + } + else + { + auto userDir = dir / portable_str; + portable_config.cache = userDir.CollapseRelativeParents(); + + } + } + } + if(dict2.TryGetValueAsType("data", portable_str)) + { + + if(portable_str != "system") + { + if(portable_str == "default") + { + if(portable_config.user) + { + portable_config.data = *(portable_config.user) / "Data"; + } + } + else + { + auto userDir = dir / portable_str; + portable_config.data = userDir.CollapseRelativeParents(); + + } + } + } + if(dict2.TryGetValueAsType("state", portable_str)) + { + + if(portable_str != "system") + { + if(portable_str == "default") + { + if(portable_config.user) + { + portable_config.state = *(portable_config.user) / "State"; + } + } + else + { + auto userDir = dir / portable_str; + portable_config.state = userDir.CollapseRelativeParents(); + + } + } + } + if(dict2.TryGetValueAsType("temp", portable_str)) + { + + if(portable_str != "system") + { + if(portable_str == "default") + { + if(portable_config.user) + { + portable_config.temp = *(portable_config.user) / "Temp"; + } + } + else + { + auto userDir = dir / portable_str; + portable_config.temp = userDir.CollapseRelativeParents(); + + } + } + } + + + + + + + + + + + + + + + } + } + } + } } std::optional TF_GetCommandName()