From e259b316288852c08afad5eab2d655bf6f262851 Mon Sep 17 00:00:00 2001 From: "Robin E. R. Davies" Date: Wed, 21 Jan 2026 08:24:16 -0500 Subject: [PATCH] Allow upload of readme.txt/.md and license.txt/.md --- docs/ReleaseNotes.md | 1 + src/Storage.cpp | 38 +++++++++++++++++++------ src/Storage.hpp | 1 + vite/src/pipedal/FilePropertyDialog.tsx | 2 +- 4 files changed, 32 insertions(+), 10 deletions(-) diff --git a/docs/ReleaseNotes.md b/docs/ReleaseNotes.md index bf0f3b5..1a23ddc 100644 --- a/docs/ReleaseNotes.md +++ b/docs/ReleaseNotes.md @@ -18,6 +18,7 @@ - Split controls behave unpredictably if the type of a Split is changed when switching between presets that have otherwise identical structure. - File selections are lost when switching between presets that have identical structure. - Snapshot plugin states are not trimmed when a plugin is removed. +- Allow license.txt/.md and readme.txt/.md files to be uploaded via .zip files. ## PiPedal 1.5.95 Beta diff --git a/src/Storage.cpp b/src/Storage.cpp index 1a70acd..81e283b 100644 --- a/src/Storage.cpp +++ b/src/Storage.cpp @@ -43,6 +43,7 @@ #include "Utf8Utils.hpp" #include "AtomConverter.hpp" #include "FileBrowserFilesFeature.hpp" +#include using namespace pipedal; namespace fs = std::filesystem; @@ -65,7 +66,7 @@ Storage::Storage() inline bool isSafeCharacter(char c) { - return (c >= '0' && c <= '9') | (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '-'; + return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '-'; } static int fromhexStrict(char c) @@ -2074,15 +2075,29 @@ static bool ensureNoDotDot(const std::filesystem::path &path) return true; } +static bool isInfoFile(const std::string&fileName) +{ + if (strcasecmp(fileName.c_str(),"license.txt") == 0) + { + return true; + } + if (strcasecmp(fileName.c_str(),"license.md") == 0) + { + return true; + } + if (strcasecmp(fileName.c_str(),"readme.txt") == 0) + { + return true; + } + if (strcasecmp(fileName.c_str(),"readme.md") == 0) + { + return true; + } + return false; +} static bool isInfoFile(const FileEntry &l) { - if (l.displayName_.starts_with("LICENSE")) - return true; - if (l.displayName_.starts_with("README")) - return true; - if (l.displayName_.find(".md") == l.displayName_.length() - 3) - return true; - return false; + return isInfoFile(l.displayName_); } static void AddFilesToResult( @@ -2557,6 +2572,11 @@ std::filesystem::path Storage::MakeUserFilePath(const std::string &directory, co return result; } +bool Storage::IsValidReadmeFile(const std::filesystem::path &fullPath) +{ + return isInfoFile(fullPath.filename().string()); +} + bool Storage::IsValidArtworkFile(const std::filesystem::path &fullPath) { if (IsInAudioTracksDirectory(fullPath) && isArtworkFileName(fullPath.filename().string())) @@ -2590,7 +2610,7 @@ std::string Storage::UploadUserFile(const std::string &directory, throw std::logic_error("Permission denied. Path is outside the upload storage directory."); } - if (!(uiFileProperty->IsValidExtension(relativePath) || IsValidArtworkFile(path))) + if (!(uiFileProperty->IsValidExtension(relativePath) || IsValidArtworkFile(path) || IsValidReadmeFile(path))) { throw std::logic_error("Permission denied. Invalid file extension for this directory."); } diff --git a/src/Storage.hpp b/src/Storage.hpp index f6044fa..21ae5ba 100644 --- a/src/Storage.hpp +++ b/src/Storage.hpp @@ -178,6 +178,7 @@ public: bool IsInUploadsDirectory(const std::filesystem::path&path) const; bool IsInAudioTracksDirectory(const std::filesystem::path&path) const; bool IsValidArtworkFile(const std::filesystem::path& fullPath); + bool IsValidReadmeFile(const std::filesystem::path& fullpath); FileRequestResult GetFileList2(const std::string&relativePath,const UiFileProperty&fileProperty); diff --git a/vite/src/pipedal/FilePropertyDialog.tsx b/vite/src/pipedal/FilePropertyDialog.tsx index e1d1614..26321ba 100644 --- a/vite/src/pipedal/FilePropertyDialog.tsx +++ b/vite/src/pipedal/FilePropertyDialog.tsx @@ -1775,7 +1775,7 @@ export default withStyles( return true; } let fileNameOnly = pathFileNameOnly(fileName); - if (fileNameOnly === "LICENSE" || fileNameOnly === "README") + if (fileNameOnly.toUpperCase() === "LICENSE" || fileNameOnly.toUpperCase() === "README") { return true; }