From 0484956a1fa260c92a78fed08539567e086cbcf3 Mon Sep 17 00:00:00 2001 From: OTHGMars Date: Mon, 11 Jan 2021 04:53:38 -0500 Subject: [PATCH] Enables pattern searches to enter zipped sub-directories. --- Engine/source/core/util/zip/zipVolume.cpp | 79 +++++++++++++++++++++++ Engine/source/core/util/zip/zipVolume.h | 7 ++ Engine/source/core/volume.cpp | 2 +- Engine/source/core/volume.h | 1 + 4 files changed, 88 insertions(+), 1 deletion(-) diff --git a/Engine/source/core/util/zip/zipVolume.cpp b/Engine/source/core/util/zip/zipVolume.cpp index 6982c70c0..801a77e92 100644 --- a/Engine/source/core/util/zip/zipVolume.cpp +++ b/Engine/source/core/util/zip/zipVolume.cpp @@ -357,6 +357,10 @@ ZipFileSystem::ZipFileSystem(String& zipFilename, bool zipNameIsDir /* = false * if(mZipNameIsDir) { Path path(zipFilename); +#ifdef TORQUE_DISABLE_FIND_ROOT_WITHIN_ZIP + if (path.getFileName().equal(path.getRoot())) + mZipNameIsDir = false; +#endif mFakeRoot = Path::Join(path.getPath(), '/', path.getFileName()); } @@ -397,6 +401,81 @@ FileNodeRef ZipFileSystem::resolve(const Path& path) if(name.isEmpty() && mZipNameIsDir) return new ZipFakeRootNode(mZipArchive, path, mFakeRoot); +#ifdef TORQUE_LOWER_ZIPCASE + name = String::ToLower(name); +#endif + if(mZipNameIsDir) + { + // Remove the fake root from the name so things can be found + if(name.find(mFakeRoot) == 0) + name = name.substr(mFakeRoot.length()); + +#ifdef TORQUE_DISABLE_FIND_ROOT_WITHIN_ZIP + else + // If a zip file's name isn't the root of the path we're looking for + // then do not continue. Otherwise, we'll continue to look for the + // path's root within the zip file itself. i.e. we're looking for the + // path "scripts/test.cs". If the zip file itself isn't called scripts.zip + // then we won't look within the archive for a "scripts" directory. + return NULL; +#endif + + if (name.find("/") == 0) + name = name.substr(1, name.length() - 1); + } + + // first check to see if input path is a directory + // check for request of root directory + if (name.isEmpty()) + { + ZipDirectoryNode* zdn = new ZipDirectoryNode(mZipArchive, path, mZipArchive->getRoot()); + return zdn; + } + + ZipArchive::ZipEntry* ze = mZipArchive->findZipEntry(name); + if (ze == NULL) + return NULL; + + if (ze->mIsDirectory) + { + ZipDirectoryNode* zdn = new ZipDirectoryNode(mZipArchive, path, ze); + return zdn; + } + + // pass in the zip entry so that openFile() doesn't need to look it up again. + Stream* stream = mZipArchive->openFile(name, ze, ZipArchive::Read); + if (stream == NULL) + return NULL; + + ZipFileNode* zfn = new ZipFileNode(mZipArchive, name, stream, ze); + return zfn; +} + +FileNodeRef ZipFileSystem::resolveLoose(const Path& path) +{ + if (!mInitted) + _init(); + + if (mZipArchive.isNull()) + return NULL; + + // eat leading "/" + String name = path.getFullPathWithoutRoot(); + if (name.find("/") == 0) + name = name.substr(1, name.length() - 1); + + if(name.isEmpty() && mZipNameIsDir) + return new ZipFakeRootNode(mZipArchive, path, mFakeRoot); + +#ifdef TORQUE_LOWER_ZIPCASE + name = String::ToLower(name); +#endif + + if ((mFakeRoot.find(name) == 0) && (mFakeRoot.length() > name.length())) + { // This file system is mounted as a sub-directory of the path being searched. + String tmpRoot = mFakeRoot.substr(name.length()); + return new ZipFakeRootNode(mZipArchive, path, tmpRoot); + } if(mZipNameIsDir) { diff --git a/Engine/source/core/util/zip/zipVolume.h b/Engine/source/core/util/zip/zipVolume.h index 75838579c..6f949df5e 100644 --- a/Engine/source/core/util/zip/zipVolume.h +++ b/Engine/source/core/util/zip/zipVolume.h @@ -40,8 +40,15 @@ public: String getTypeStr() const { return "Zip"; } + // Strict resolve function will reteurn a node if it is mounted *AS* the requested path. FileNodeRef resolve(const Path& path); + // Loose resolve function will return a node if it is mounted as or under the requested path. + // This is needed so mounted subdirectories will be included in recursive FindByPatern searches. + // i.e. If data/ui.zip is mounted as data/ui, a search for data/*.module will only include files + // under data/ui if the loose resolve function is used. + FileNodeRef resolveLoose(const Path& path); + // these are unsupported, ZipFileSystem is currently read only access FileNodeRef create(const Path& path,FileNode::Mode) { return 0; } bool remove(const Path& path) { return 0; } diff --git a/Engine/source/core/volume.cpp b/Engine/source/core/volume.cpp index 3630f7ffb..aec3052db 100644 --- a/Engine/source/core/volume.cpp +++ b/Engine/source/core/volume.cpp @@ -730,7 +730,7 @@ S32 MountSystem::findByPattern( const Path &inBasePath, const String &inFilePatt else { // use specified filesystem to open directory - FileNodeRef fNode = mFindByPatternOverrideFS->resolve(inBasePath); + FileNodeRef fNode = mFindByPatternOverrideFS->resolveLoose(inBasePath); if (fNode && (dir = dynamic_cast(fNode.getPointer())) != NULL) dir->open(); } diff --git a/Engine/source/core/volume.h b/Engine/source/core/volume.h index bd041fa42..25a2d33c4 100644 --- a/Engine/source/core/volume.h +++ b/Engine/source/core/volume.h @@ -302,6 +302,7 @@ public: virtual String getTypeStr() const = 0; ///< Used for describing the file system type virtual FileNodeRef resolve(const Path& path) = 0; + virtual FileNodeRef resolveLoose(const Path& path) { return resolve(path); } virtual FileNodeRef create(const Path& path,FileNode::Mode) = 0; virtual bool remove(const Path& path) = 0; virtual bool rename(const Path& a,const Path& b) = 0;