Added getSize() to FSNodeZIP. This allows to detect too large files in ZIP files.

This commit is contained in:
Stephen Anthony 2022-06-11 19:15:44 -02:30
parent 42b6a29274
commit b5cc7d41c9
4 changed files with 40 additions and 23 deletions

View File

@ -80,11 +80,12 @@ FilesystemNodeZIP::FilesystemNodeZIP(const string& p)
bool found = false; bool found = false;
while(myZipHandler->hasNext() && !found) while(myZipHandler->hasNext() && !found)
{ {
const string& file = myZipHandler->next(); const auto [name, size, isFile] = myZipHandler->next();
if(Bankswitch::isValidRomName(file)) if(Bankswitch::isValidRomName(name))
{ {
_virtualPath = file; _virtualPath = name;
_isFile = true; _size = size;
_isFile = isFile;
found = true; found = true;
} }
@ -109,8 +110,9 @@ FilesystemNodeZIP::FilesystemNodeZIP(const string& p)
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FilesystemNodeZIP::FilesystemNodeZIP( FilesystemNodeZIP::FilesystemNodeZIP(
const string& zipfile, const string& virtualpath, const string& zipfile, const string& virtualpath,
const AbstractFSNodePtr& realnode, bool isdir) const AbstractFSNodePtr& realnode, size_t size, bool isdir)
: _isDirectory{isdir}, : _size{size},
_isDirectory{isdir},
_isFile{!isdir} _isFile{!isdir}
{ {
setFlags(zipfile, virtualpath, realnode); setFlags(zipfile, virtualpath, realnode);
@ -152,9 +154,12 @@ bool FilesystemNodeZIP::exists() const
{ {
myZipHandler->open(_zipFile); myZipHandler->open(_zipFile);
while(myZipHandler->hasNext()) while(myZipHandler->hasNext())
if(BSPF::startsWithIgnoreCase(myZipHandler->next(), _virtualPath)) {
const auto [name, size, isFile] = myZipHandler->next();
if(BSPF::startsWithIgnoreCase(name, _virtualPath))
return true; return true;
} }
}
catch(const runtime_error&) catch(const runtime_error&)
{ {
// TODO: Actually present the error passed in back to the user // TODO: Actually present the error passed in back to the user
@ -177,26 +182,26 @@ bool FilesystemNodeZIP::getChildren(AbstractFSList& myList, ListMode mode) const
{ {
// Only consider entries that start with '_virtualPath' // Only consider entries that start with '_virtualPath'
// Ignore empty filenames and '__MACOSX' virtual directories // Ignore empty filenames and '__MACOSX' virtual directories
const string& next = myZipHandler->next(); const auto [name, size, isFile] = myZipHandler->next();
if(BSPF::startsWithIgnoreCase(next, "__MACOSX") || next == EmptyString) if(BSPF::startsWithIgnoreCase(name, "__MACOSX") || name == EmptyString)
continue; continue;
if(BSPF::startsWithIgnoreCase(next, _virtualPath)) if(BSPF::startsWithIgnoreCase(name, _virtualPath))
{ {
// First strip off the leading directory // 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 // Only add sub-directory entries once
const auto pos = curr.find_first_of("/\\"); const auto pos = curr.find_first_of("/\\");
if(pos != string::npos) if(pos != string::npos)
dirs.emplace(curr.substr(0, pos)); dirs.emplace(curr.substr(0, pos));
else 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) for(const auto& dir: dirs)
{ {
// Prepend previous path // Prepend previous path
const string& vpath = _virtualPath != "" ? _virtualPath + "/" + dir : dir; 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; return true;
@ -217,7 +222,10 @@ size_t FilesystemNodeZIP::read(ByteBuffer& image, size_t) const
bool found = false; bool found = false;
while(myZipHandler->hasNext() && !found) while(myZipHandler->hasNext() && !found)
found = myZipHandler->next() == _virtualPath; {
const auto [name, size, isFile] = myZipHandler->next();
found = name == _virtualPath;
}
return found ? myZipHandler->decompress(image) : 0; return found ? myZipHandler->decompress(image) : 0;
} }

View File

@ -59,6 +59,7 @@ class FilesystemNodeZIP : public AbstractFSNode
bool rename(const string& newfile) override { return false; } bool rename(const string& newfile) override { return false; }
////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////
size_t getSize() const override { return _size; }
bool getChildren(AbstractFSList& list, ListMode mode) const override; bool getChildren(AbstractFSList& list, ListMode mode) const override;
AbstractFSNodePtr getParent() const override; AbstractFSNodePtr getParent() const override;
@ -69,7 +70,7 @@ class FilesystemNodeZIP : public AbstractFSNode
private: private:
FilesystemNodeZIP(const string& zipfile, const string& virtualpath, 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, void setFlags(const string& zipfile, const string& virtualpath,
const AbstractFSNodePtr& realnode); const AbstractFSNodePtr& realnode);
@ -78,7 +79,9 @@ class FilesystemNodeZIP : public AbstractFSNode
{ {
os << "_zipFile: " << node._zipFile << endl os << "_zipFile: " << node._zipFile << endl
<< "_virtualPath: " << node._virtualPath << endl << "_virtualPath: " << node._virtualPath << endl
<< "_name: " << node._name << endl
<< "_path: " << node._path << endl << "_path: " << node._path << endl
<< "_size: " << node._size << endl
<< "_shortPath: " << node._shortPath << endl; << "_shortPath: " << node._shortPath << endl;
return os; return os;
} }
@ -100,7 +103,8 @@ class FilesystemNodeZIP : public AbstractFSNode
string _zipFile, _virtualPath; string _zipFile, _virtualPath;
string _name, _path, _shortPath; string _name, _path, _shortPath;
zip_error _error{zip_error::NONE}; zip_error _error{zip_error::NONE};
uInt32 _numFiles{0}; uInt16 _numFiles{0};
size_t _size{0};
bool _isDirectory{false}, _isFile{false}; bool _isDirectory{false}, _isFile{false};

View File

@ -66,9 +66,12 @@ void ZipHandler::open(const string& filename)
try try
{ {
while(hasNext()) while(hasNext())
if(Bankswitch::isValidRomName(next())) {
const auto [name, size, isFile] = next();
if(Bankswitch::isValidRomName(name))
myZip->myRomfiles++; myZip->myRomfiles++;
} }
}
catch(...) catch(...)
{ {
myZip->myRomfiles = 0; myZip->myRomfiles = 0;
@ -93,7 +96,7 @@ bool ZipHandler::hasNext() const
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
const string& ZipHandler::next() std::tuple<string, size_t, bool> ZipHandler::next()
{ {
if(hasNext()) if(hasNext())
{ {
@ -103,9 +106,9 @@ const string& ZipHandler::next()
else if(header->uncompressedLength == 0) else if(header->uncompressedLength == 0)
return next(); return next();
else else
return header->filename; return {header->filename, header->uncompressedLength, true};
} }
return EmptyString; return {EmptyString, 0, false};
} }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -20,6 +20,8 @@
#ifndef ZIP_HANDLER_HXX #ifndef ZIP_HANDLER_HXX
#define ZIP_HANDLER_HXX #define ZIP_HANDLER_HXX
#include <tuple>
#include "bspf.hxx" #include "bspf.hxx"
/** /**
@ -41,7 +43,7 @@ class ZipHandler
// The following form an iterator for processing the filenames in the ZIP file // The following form an iterator for processing the filenames in the ZIP file
void reset(); // Reset iterator to first file void reset(); // Reset iterator to first file
bool hasNext() const; // Answer whether there are more files present bool hasNext() const; // Answer whether there are more files present
const string& next(); // Get next file std::tuple<string, size_t, bool> next(); // Get information on next file
// Decompress the currently selected file and return its length // Decompress the currently selected file and return its length
// An exception will be thrown on any errors // An exception will be thrown on any errors
@ -297,8 +299,8 @@ class ZipHandler
void addToCache(); void addToCache();
private: private:
static constexpr size_t DECOMPRESS_BUFSIZE = 16_KB; static constexpr size_t DECOMPRESS_BUFSIZE = 128_KB;
static constexpr uInt32 CACHE_SIZE = 8; // number of open files to cache static constexpr size_t CACHE_SIZE = 16; // number of open files to cache
ZipFilePtr myZip; ZipFilePtr myZip;
std::array<ZipFilePtr, CACHE_SIZE> myZipCache; std::array<ZipFilePtr, CACHE_SIZE> myZipCache;