mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-30 03:32:36 +00:00
Hard fail on loading BSA with records using unicode paths.
This commit is contained in:
parent
a60cebd0f9
commit
9ceafe770d
@ -83,7 +83,7 @@ void MWState::Character::addSlot (const ESM::SavedGame& profile)
|
||||
}
|
||||
|
||||
MWState::Character::Character (std::filesystem::path saves, const std::string& game)
|
||||
: mPath (std::move(saves))
|
||||
: mPath (std::move(saves))
|
||||
{
|
||||
if (!std::filesystem::is_directory (mPath))
|
||||
{
|
||||
|
@ -35,7 +35,7 @@ using namespace Bsa;
|
||||
|
||||
|
||||
/// Error handling
|
||||
[[noreturn]] void BSAFile::fail(const std::string &msg)
|
||||
[[noreturn]] void BSAFile::fail(const std::string &msg) const
|
||||
{
|
||||
throw std::runtime_error("BSA Error: " + msg + "\nArchive: " + Files::pathToUnicodeString(mFilepath));
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ protected:
|
||||
std::filesystem::path mFilepath;
|
||||
|
||||
/// Error handling
|
||||
[[noreturn]] void fail(const std::string &msg);
|
||||
[[noreturn]] void fail(const std::string &msg) const;
|
||||
|
||||
/// Read header information from the input source
|
||||
virtual void readHeader();
|
||||
|
@ -300,6 +300,13 @@ void CompressedBSAFile::readHeader()
|
||||
|
||||
CompressedBSAFile::FileRecord CompressedBSAFile::getFileRecord(const std::string& str) const
|
||||
{
|
||||
for (const auto c : str)
|
||||
{
|
||||
if (((static_cast<unsigned>(c) >> 7U) & 1U) != 0U) {
|
||||
fail("File record " + str + " contains unicode characters, refusing to load.");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
const auto& path = str;
|
||||
#else
|
||||
@ -310,9 +317,9 @@ CompressedBSAFile::FileRecord CompressedBSAFile::getFileRecord(const std::string
|
||||
std::replace(path.begin(), path.end(), '\\', '/');
|
||||
#endif
|
||||
|
||||
auto p = Files::pathFromUnicodeString(path);
|
||||
const auto p = std::filesystem::path{ path }; // Purposefully damage Unicode strings.
|
||||
const auto stem = p.stem();
|
||||
const auto ext = p.extension().u8string();
|
||||
const auto ext = p.extension().string(); // Purposefully damage Unicode strings.
|
||||
|
||||
std::uint64_t folderHash = generateHash(p.parent_path(), {});
|
||||
|
||||
@ -471,13 +478,13 @@ void CompressedBSAFile::convertCompressedSizesToUncompressed()
|
||||
}
|
||||
}
|
||||
|
||||
std::uint64_t CompressedBSAFile::generateHash(const std::filesystem::path& stem, std::u8string extension)
|
||||
std::uint64_t CompressedBSAFile::generateHash(const std::filesystem::path& stem, std::string extension)
|
||||
{
|
||||
auto str = stem.u8string();
|
||||
size_t len = str.length();
|
||||
if (len == 0)
|
||||
return 0;
|
||||
std::replace(str.begin(), str.end(), u8'/', u8'\\');
|
||||
std::replace(str.begin(), str.end(), '/', '\\');
|
||||
Misc::StringUtils::lowerCaseInPlace(str);
|
||||
uint64_t result = str[len-1] | (len >= 3 ? (str[len-2] << 8) : 0) | (len << 16) | (str[0] << 24);
|
||||
if (len >= 4)
|
||||
@ -490,10 +497,10 @@ std::uint64_t CompressedBSAFile::generateHash(const std::filesystem::path& stem,
|
||||
if (extension.empty())
|
||||
return result;
|
||||
Misc::StringUtils::lowerCaseInPlace(extension);
|
||||
if (extension == u8".kf") result |= 0x80;
|
||||
else if (extension == u8".nif") result |= 0x8000;
|
||||
else if (extension == u8".dds") result |= 0x8080;
|
||||
else if (extension == u8".wav") result |= 0x80000000;
|
||||
if (extension == ".kf") result |= 0x80;
|
||||
else if (extension == ".nif") result |= 0x8000;
|
||||
else if (extension == ".dds") result |= 0x8080;
|
||||
else if (extension == ".wav") result |= 0x80000000;
|
||||
uint32_t hash = 0;
|
||||
for (const auto &c : extension)
|
||||
hash = hash * 0x1003f + c;
|
||||
|
@ -83,7 +83,7 @@ namespace Bsa
|
||||
//mFiles used by OpenMW will contain uncompressed file sizes
|
||||
void convertCompressedSizesToUncompressed();
|
||||
/// \brief Normalizes given filename or folder and generates format-compatible hash. See https://en.uesp.net/wiki/Tes4Mod:Hash_Calculation.
|
||||
static std::uint64_t generateHash(const std::filesystem::path& stem, std::u8string extension) ;
|
||||
static std::uint64_t generateHash(const std::filesystem::path& stem, std::string extension) ;
|
||||
Files::IStreamPtr getFile(const FileRecord& fileRecord);
|
||||
public:
|
||||
using BSAFile::open;
|
||||
|
Loading…
x
Reference in New Issue
Block a user