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;
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;
}

View File

@ -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};

View File

@ -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<string, size_t, bool> 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};
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@ -20,6 +20,8 @@
#ifndef ZIP_HANDLER_HXX
#define ZIP_HANDLER_HXX
#include <tuple>
#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<string, size_t, bool> 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<ZipFilePtr, CACHE_SIZE> myZipCache;