From b5cc7d41c9987717e36e3e977c2bea96e2d8800d Mon Sep 17 00:00:00 2001 From: Stephen Anthony Date: Sat, 11 Jun 2022 19:15:44 -0230 Subject: [PATCH] Added getSize() to FSNodeZIP. This allows to detect too large files in ZIP files. --- src/common/FSNodeZIP.cxx | 36 ++++++++++++++++++++++-------------- src/common/FSNodeZIP.hxx | 8 ++++++-- src/common/ZipHandler.cxx | 11 +++++++---- src/common/ZipHandler.hxx | 8 +++++--- 4 files changed, 40 insertions(+), 23 deletions(-) diff --git a/src/common/FSNodeZIP.cxx b/src/common/FSNodeZIP.cxx index 50cbb770a..f56b255da 100644 --- a/src/common/FSNodeZIP.cxx +++ b/src/common/FSNodeZIP.cxx @@ -80,11 +80,12 @@ FilesystemNodeZIP::FilesystemNodeZIP(const string& p) bool found = false; while(myZipHandler->hasNext() && !found) { - const string& file = myZipHandler->next(); - if(Bankswitch::isValidRomName(file)) + const auto [name, size, isFile] = myZipHandler->next(); + if(Bankswitch::isValidRomName(name)) { - _virtualPath = file; - _isFile = true; + _virtualPath = name; + _size = size; + _isFile = isFile; found = true; } @@ -109,8 +110,9 @@ FilesystemNodeZIP::FilesystemNodeZIP(const string& p) // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - FilesystemNodeZIP::FilesystemNodeZIP( const string& zipfile, const string& virtualpath, - const AbstractFSNodePtr& realnode, bool isdir) - : _isDirectory{isdir}, + const AbstractFSNodePtr& realnode, size_t size, bool isdir) + : _size{size}, + _isDirectory{isdir}, _isFile{!isdir} { setFlags(zipfile, virtualpath, realnode); @@ -152,8 +154,11 @@ bool FilesystemNodeZIP::exists() const { myZipHandler->open(_zipFile); while(myZipHandler->hasNext()) - if(BSPF::startsWithIgnoreCase(myZipHandler->next(), _virtualPath)) + { + const auto [name, size, isFile] = myZipHandler->next(); + if(BSPF::startsWithIgnoreCase(name, _virtualPath)) return true; + } } catch(const runtime_error&) { @@ -177,26 +182,26 @@ bool FilesystemNodeZIP::getChildren(AbstractFSList& myList, ListMode mode) const { // Only consider entries that start with '_virtualPath' // Ignore empty filenames and '__MACOSX' virtual directories - const string& next = myZipHandler->next(); - if(BSPF::startsWithIgnoreCase(next, "__MACOSX") || next == EmptyString) + const auto [name, size, isFile] = myZipHandler->next(); + if(BSPF::startsWithIgnoreCase(name, "__MACOSX") || name == EmptyString) continue; - if(BSPF::startsWithIgnoreCase(next, _virtualPath)) + if(BSPF::startsWithIgnoreCase(name, _virtualPath)) { // First strip off the leading directory - const string& curr = next.substr(_virtualPath == "" ? 0 : _virtualPath.size()+1); + const string& curr = name.substr(_virtualPath == "" ? 0 : _virtualPath.size()+1); // Only add sub-directory entries once const auto pos = curr.find_first_of("/\\"); if(pos != string::npos) dirs.emplace(curr.substr(0, pos)); else - myList.emplace_back(new FilesystemNodeZIP(_zipFile, next, _realNode, false)); + myList.emplace_back(new FilesystemNodeZIP(_zipFile, name, _realNode, size, false)); } } for(const auto& dir: dirs) { // Prepend previous path const string& vpath = _virtualPath != "" ? _virtualPath + "/" + dir : dir; - myList.emplace_back(new FilesystemNodeZIP(_zipFile, vpath, _realNode, true)); + myList.emplace_back(new FilesystemNodeZIP(_zipFile, vpath, _realNode, 0, true)); } return true; @@ -217,7 +222,10 @@ size_t FilesystemNodeZIP::read(ByteBuffer& image, size_t) const bool found = false; while(myZipHandler->hasNext() && !found) - found = myZipHandler->next() == _virtualPath; + { + const auto [name, size, isFile] = myZipHandler->next(); + found = name == _virtualPath; + } return found ? myZipHandler->decompress(image) : 0; } diff --git a/src/common/FSNodeZIP.hxx b/src/common/FSNodeZIP.hxx index 0fe625908..dc4c49127 100644 --- a/src/common/FSNodeZIP.hxx +++ b/src/common/FSNodeZIP.hxx @@ -59,6 +59,7 @@ class FilesystemNodeZIP : public AbstractFSNode bool rename(const string& newfile) override { return false; } ////////////////////////////////////////////////////////// + size_t getSize() const override { return _size; } bool getChildren(AbstractFSList& list, ListMode mode) const override; AbstractFSNodePtr getParent() const override; @@ -69,7 +70,7 @@ class FilesystemNodeZIP : public AbstractFSNode private: FilesystemNodeZIP(const string& zipfile, const string& virtualpath, - const AbstractFSNodePtr& realnode, bool isdir); + const AbstractFSNodePtr& realnode, size_t size, bool isdir); void setFlags(const string& zipfile, const string& virtualpath, const AbstractFSNodePtr& realnode); @@ -78,7 +79,9 @@ class FilesystemNodeZIP : public AbstractFSNode { os << "_zipFile: " << node._zipFile << endl << "_virtualPath: " << node._virtualPath << endl + << "_name: " << node._name << endl << "_path: " << node._path << endl + << "_size: " << node._size << endl << "_shortPath: " << node._shortPath << endl; return os; } @@ -100,7 +103,8 @@ class FilesystemNodeZIP : public AbstractFSNode string _zipFile, _virtualPath; string _name, _path, _shortPath; zip_error _error{zip_error::NONE}; - uInt32 _numFiles{0}; + uInt16 _numFiles{0}; + size_t _size{0}; bool _isDirectory{false}, _isFile{false}; diff --git a/src/common/ZipHandler.cxx b/src/common/ZipHandler.cxx index 3ac21625d..28683a80d 100644 --- a/src/common/ZipHandler.cxx +++ b/src/common/ZipHandler.cxx @@ -66,8 +66,11 @@ void ZipHandler::open(const string& filename) try { while(hasNext()) - if(Bankswitch::isValidRomName(next())) + { + const auto [name, size, isFile] = next(); + if(Bankswitch::isValidRomName(name)) myZip->myRomfiles++; + } } catch(...) { @@ -93,7 +96,7 @@ bool ZipHandler::hasNext() const } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -const string& ZipHandler::next() +std::tuple ZipHandler::next() { if(hasNext()) { @@ -103,9 +106,9 @@ const string& ZipHandler::next() else if(header->uncompressedLength == 0) return next(); else - return header->filename; + return {header->filename, header->uncompressedLength, true}; } - return EmptyString; + return {EmptyString, 0, false}; } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/common/ZipHandler.hxx b/src/common/ZipHandler.hxx index 21bd8f8f7..b50645143 100644 --- a/src/common/ZipHandler.hxx +++ b/src/common/ZipHandler.hxx @@ -20,6 +20,8 @@ #ifndef ZIP_HANDLER_HXX #define ZIP_HANDLER_HXX +#include + #include "bspf.hxx" /** @@ -41,7 +43,7 @@ class ZipHandler // The following form an iterator for processing the filenames in the ZIP file void reset(); // Reset iterator to first file bool hasNext() const; // Answer whether there are more files present - const string& next(); // Get next file + std::tuple next(); // Get information on next file // Decompress the currently selected file and return its length // An exception will be thrown on any errors @@ -297,8 +299,8 @@ class ZipHandler void addToCache(); private: - static constexpr size_t DECOMPRESS_BUFSIZE = 16_KB; - static constexpr uInt32 CACHE_SIZE = 8; // number of open files to cache + static constexpr size_t DECOMPRESS_BUFSIZE = 128_KB; + static constexpr size_t CACHE_SIZE = 16; // number of open files to cache ZipFilePtr myZip; std::array myZipCache;