1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-07-13 01:20:34 +02:00

fix crash when map is packaged in a zip mod

This commit is contained in:
kdmcser
2025-05-16 01:14:12 +08:00
parent 29207c0b0f
commit 5e4912d056
11 changed files with 94 additions and 11 deletions

View File

@ -56,6 +56,18 @@ std::unordered_set<ResourcePath> CMappedFileLoader::getFilteredFiles(std::functi
return foundID; return foundID;
} }
std::string CMappedFileLoader::getFullFileURI(const ResourcePath& resourceName) const
{
return CResourceHandler::get()->getFullFileURI(fileList.at(resourceName));
}
std::time_t CMappedFileLoader::getLastWriteTime(const ResourcePath& resourceName) const
{
return CResourceHandler::get()->getLastWriteTime(fileList.at(resourceName));
}
CFilesystemList::CFilesystemList() CFilesystemList::CFilesystemList()
{ {
} }
@ -176,7 +188,29 @@ bool CFilesystemList::removeLoader(ISimpleResourceLoader * loader)
return true; return true;
} }
} }
return false; return false;
} }
std::string CFilesystemList::getFullFileURI(const ResourcePath& resourceName) const
{
for (const auto& loader : boost::adaptors::reverse(loaders))
if (loader->existsResource(resourceName))
return loader->getFullFileURI(resourceName);
throw std::runtime_error("Resource with name " + resourceName.getName() + " and type "
+ EResTypeHelper::getEResTypeAsString(resourceName.getType()) + " wasn't found.");
}
std::time_t CFilesystemList::getLastWriteTime(const ResourcePath& resourceName) const
{
for (const auto& loader : boost::adaptors::reverse(loaders))
if (loader->existsResource(resourceName))
return loader->getLastWriteTime(resourceName);
throw std::runtime_error("Resource with name " + resourceName.getName() + " and type "
+ EResTypeHelper::getEResTypeAsString(resourceName.getType()) + " wasn't found.");
}
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -44,6 +44,8 @@ public:
std::optional<boost::filesystem::path> getResourceName(const ResourcePath & resourceName) const override; std::optional<boost::filesystem::path> getResourceName(const ResourcePath & resourceName) const override;
void updateFilteredFiles(std::function<bool(const std::string &)> filter) const override {} void updateFilteredFiles(std::function<bool(const std::string &)> filter) const override {}
std::unordered_set<ResourcePath> getFilteredFiles(std::function<bool(const ResourcePath &)> filter) const override; std::unordered_set<ResourcePath> getFilteredFiles(std::function<bool(const ResourcePath &)> filter) const override;
std::string getFullFileURI(const ResourcePath& resourceName) const override;
std::time_t getLastWriteTime(const ResourcePath& resourceName) const override;
private: private:
/** A list of files in this map /** A list of files in this map
@ -77,6 +79,8 @@ public:
std::unordered_set<ResourcePath> getFilteredFiles(std::function<bool(const ResourcePath &)> filter) const override; std::unordered_set<ResourcePath> getFilteredFiles(std::function<bool(const ResourcePath &)> filter) const override;
bool createResource(const std::string & filename, bool update = false) override; bool createResource(const std::string & filename, bool update = false) override;
std::vector<const ISimpleResourceLoader *> getResourcesWithName(const ResourcePath & resourceName) const override; std::vector<const ISimpleResourceLoader *> getResourcesWithName(const ResourcePath & resourceName) const override;
std::string getFullFileURI(const ResourcePath& resourceName) const override;
std::time_t getLastWriteTime(const ResourcePath& resourceName) const override;
/** /**
* Adds a resource loader to the loaders list * Adds a resource loader to the loaders list

View File

@ -15,6 +15,7 @@
#include "CCompressedStream.h" #include "CCompressedStream.h"
#include "CBinaryReader.h" #include "CBinaryReader.h"
#include "../texts/TextOperations.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@ -240,6 +241,19 @@ void CArchiveLoader::extractToFolder(const std::string & outputSubFolder, const
extractToFolder(outputSubFolder, *inputStream, entry, absolute); extractToFolder(outputSubFolder, *inputStream, entry, absolute);
} }
std::string CArchiveLoader::getFullFileURI(const ResourcePath& resourceName) const
{
auto relativePath = TextOperations::Utf8TofilesystemPath(resourceName.getName());
auto path = boost::filesystem::canonical(archive) / relativePath;
return TextOperations::filesystemPathToUtf8(path);
}
std::time_t CArchiveLoader::getLastWriteTime(const ResourcePath& resourceName) const
{
return boost::filesystem::last_write_time(archive);
}
boost::filesystem::path createExtractedFilePath(const std::string & outputSubFolder, const std::string & entryName, bool absolute) boost::filesystem::path createExtractedFilePath(const std::string & outputSubFolder, const std::string & entryName, bool absolute)
{ {
boost::filesystem::path extractionFolderPath = absolute ? outputSubFolder : VCMIDirs::get().userExtractedPath() / outputSubFolder; boost::filesystem::path extractionFolderPath = absolute ? outputSubFolder : VCMIDirs::get().userExtractedPath() / outputSubFolder;

View File

@ -70,6 +70,8 @@ public:
void extractToFolder(const std::string & outputSubFolder, CInputStream & fileStream, const ArchiveEntry & entry, bool absolute = false) const; void extractToFolder(const std::string & outputSubFolder, CInputStream & fileStream, const ArchiveEntry & entry, bool absolute = false) const;
/** Extracts one archive entry to the specified subfolder. Used for Images, Sprites, etc */ /** Extracts one archive entry to the specified subfolder. Used for Images, Sprites, etc */
void extractToFolder(const std::string & outputSubFolder, const std::string & mountPoint, ArchiveEntry entry, bool absolute = false) const; void extractToFolder(const std::string & outputSubFolder, const std::string & mountPoint, ArchiveEntry entry, bool absolute = false) const;
std::string getFullFileURI(const ResourcePath& resourceName) const override;
std::time_t getLastWriteTime(const ResourcePath& resourceName) const override;
private: private:
/** /**

View File

@ -198,4 +198,17 @@ std::unordered_map<ResourcePath, boost::filesystem::path> CFilesystemLoader::lis
return fileList; return fileList;
} }
std::string CFilesystemLoader::getFullFileURI(const ResourcePath& resourceName) const
{
auto filePath = getResourceName(resourceName);
auto path = boost::filesystem::canonical(*filePath);
return TextOperations::filesystemPathToUtf8(path);
}
std::time_t CFilesystemLoader::getLastWriteTime(const ResourcePath& resourceName) const
{
auto resourcePath = getResourceName(resourceName);
return boost::filesystem::last_write_time(*resourcePath);
}
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -41,6 +41,8 @@ public:
std::optional<boost::filesystem::path> getResourceName(const ResourcePath & resourceName) const override; std::optional<boost::filesystem::path> getResourceName(const ResourcePath & resourceName) const override;
void updateFilteredFiles(std::function<bool(const std::string &)> filter) const override; void updateFilteredFiles(std::function<bool(const std::string &)> filter) const override;
std::unordered_set<ResourcePath> getFilteredFiles(std::function<bool(const ResourcePath &)> filter) const override; std::unordered_set<ResourcePath> getFilteredFiles(std::function<bool(const ResourcePath &)> filter) const override;
std::string getFullFileURI(const ResourcePath& resourceName) const override;
std::time_t getLastWriteTime(const ResourcePath& resourceName) const override;
private: private:
/** The base directory which is scanned and indexed. */ /** The base directory which is scanned and indexed. */

View File

@ -11,6 +11,7 @@
#include "CZipLoader.h" #include "CZipLoader.h"
#include "../ScopeGuard.h" #include "../ScopeGuard.h"
#include "../texts/TextOperations.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@ -120,6 +121,19 @@ std::unordered_set<ResourcePath> CZipLoader::getFilteredFiles(std::function<bool
return foundID; return foundID;
} }
std::string CZipLoader::getFullFileURI(const ResourcePath& resourceName) const
{
auto relativePath = TextOperations::Utf8TofilesystemPath(resourceName.getName());
auto path = boost::filesystem::canonical(archiveName) / relativePath;
return TextOperations::filesystemPathToUtf8(path);
}
std::time_t CZipLoader::getLastWriteTime(const ResourcePath& resourceName) const
{
auto path = boost::filesystem::canonical(archiveName);
return boost::filesystem::last_write_time(path);
}
/// extracts currently selected file from zip into stream "where" /// extracts currently selected file from zip into stream "where"
static bool extractCurrent(unzFile file, std::ostream & where) static bool extractCurrent(unzFile file, std::ostream & where)
{ {

View File

@ -59,6 +59,8 @@ public:
std::string getMountPoint() const override; std::string getMountPoint() const override;
void updateFilteredFiles(std::function<bool(const std::string &)> filter) const override {} void updateFilteredFiles(std::function<bool(const std::string &)> filter) const override {}
std::unordered_set<ResourcePath> getFilteredFiles(std::function<bool(const ResourcePath &)> filter) const override; std::unordered_set<ResourcePath> getFilteredFiles(std::function<bool(const ResourcePath &)> filter) const override;
std::string getFullFileURI(const ResourcePath& resourceName) const override;
std::time_t getLastWriteTime(const ResourcePath& resourceName) const override;
}; };
class DLL_LINKAGE ZipArchive : boost::noncopyable class DLL_LINKAGE ZipArchive : boost::noncopyable

View File

@ -106,6 +106,10 @@ public:
return std::vector<const ISimpleResourceLoader *>(1, this); return std::vector<const ISimpleResourceLoader *>(1, this);
return std::vector<const ISimpleResourceLoader *>(); return std::vector<const ISimpleResourceLoader *>();
} }
virtual std::string getFullFileURI(const ResourcePath& resourceName) const = 0;
virtual std::time_t getLastWriteTime(const ResourcePath& resourceName) const = 0;
}; };
VCMI_LIB_NAMESPACE_END VCMI_LIB_NAMESPACE_END

View File

@ -38,11 +38,6 @@ CMapInfo::CMapInfo()
CMapInfo::~CMapInfo() = default; CMapInfo::~CMapInfo() = default;
std::string CMapInfo::getFullFileURI(const ResourcePath & file) const
{
auto path = boost::filesystem::canonical(*CResourceHandler::get()->getResourceName(file));
return TextOperations::filesystemPathToUtf8(path);
}
void CMapInfo::mapInit(const std::string & fname) void CMapInfo::mapInit(const std::string & fname)
{ {
@ -50,9 +45,9 @@ void CMapInfo::mapInit(const std::string & fname)
CMapService mapService; CMapService mapService;
ResourcePath resource = ResourcePath(fname, EResType::MAP); ResourcePath resource = ResourcePath(fname, EResType::MAP);
originalFileURI = resource.getOriginalName(); originalFileURI = resource.getOriginalName();
fullFileURI = getFullFileURI(resource); fullFileURI = CResourceHandler::get()->getFullFileURI(resource);
mapHeader = mapService.loadMapHeader(resource); mapHeader = mapService.loadMapHeader(resource);
lastWrite = boost::filesystem::last_write_time(*CResourceHandler::get()->getResourceName(resource)); lastWrite = CResourceHandler::get()->getLastWriteTime(resource);
date = TextOperations::getFormattedDateTimeLocal(lastWrite); date = TextOperations::getFormattedDateTimeLocal(lastWrite);
countPlayers(); countPlayers();
} }
@ -71,9 +66,9 @@ void CMapInfo::saveInit(const ResourcePath & file)
fileURI = file.getName(); fileURI = file.getName();
originalFileURI = file.getOriginalName(); originalFileURI = file.getOriginalName();
fullFileURI = getFullFileURI(file); fullFileURI = CResourceHandler::get()->getFullFileURI(file);
countPlayers(); countPlayers();
lastWrite = boost::filesystem::last_write_time(*CResourceHandler::get()->getResourceName(file)); lastWrite = CResourceHandler::get()->getLastWriteTime(file);
date = TextOperations::getFormattedDateTimeLocal(lastWrite); date = TextOperations::getFormattedDateTimeLocal(lastWrite);
// We absolutely not need this data for lobby and server will read it from save // We absolutely not need this data for lobby and server will read it from save
@ -85,7 +80,7 @@ void CMapInfo::campaignInit()
{ {
ResourcePath resource = ResourcePath(fileURI, EResType::CAMPAIGN); ResourcePath resource = ResourcePath(fileURI, EResType::CAMPAIGN);
originalFileURI = resource.getOriginalName(); originalFileURI = resource.getOriginalName();
fullFileURI = getFullFileURI(resource); fullFileURI = CResourceHandler::get()->getFullFileURI(resource);
campaign = CampaignHandler::getHeader(fileURI); campaign = CampaignHandler::getHeader(fileURI);
lastWrite = boost::filesystem::last_write_time(*CResourceHandler::get()->getResourceName(resource)); lastWrite = boost::filesystem::last_write_time(*CResourceHandler::get()->getResourceName(resource));
date = TextOperations::getFormattedDateTimeLocal(lastWrite); date = TextOperations::getFormattedDateTimeLocal(lastWrite);

View File

@ -48,7 +48,6 @@ public:
CMapInfo &operator=(CMapInfo &&other) = delete; CMapInfo &operator=(CMapInfo &&other) = delete;
CMapInfo &operator=(const CMapInfo &other) = delete; CMapInfo &operator=(const CMapInfo &other) = delete;
std::string getFullFileURI(const ResourcePath& file) const;
void mapInit(const std::string & fname); void mapInit(const std::string & fname);
void saveInit(const ResourcePath & file); void saveInit(const ResourcePath & file);
void campaignInit(); void campaignInit();