mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-27 01:45:35 -05:00
fun zip optimizations
This commit is contained in:
parent
415ffc5e3b
commit
b22ed7de21
1 changed files with 68 additions and 22 deletions
|
@ -283,6 +283,73 @@ public:
|
||||||
return Ok(std::move(ret));
|
return Ok(std::move(ret));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result<> extractAt(Path const& dir, Path const& name) {
|
||||||
|
auto entry = m_entries.at(name);
|
||||||
|
|
||||||
|
GEODE_UNWRAP(
|
||||||
|
mzTry(mz_zip_entry_read_open(m_handle, 0, nullptr))
|
||||||
|
.expect("Unable to open entry (code {error})")
|
||||||
|
);
|
||||||
|
|
||||||
|
// if the file is empty, its data is empty (duh)
|
||||||
|
if (!entry.uncompressedSize) {
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteVector res;
|
||||||
|
res.resize(entry.uncompressedSize);
|
||||||
|
auto read = mz_zip_entry_read(m_handle, res.data(), entry.uncompressedSize);
|
||||||
|
if (read < 0) {
|
||||||
|
mz_zip_entry_close(m_handle);
|
||||||
|
return Err("Unable to read entry (code " + std::to_string(read) + ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
mz_zip_entry_close(m_handle);
|
||||||
|
|
||||||
|
GEODE_UNWRAP(file::writeBinary(dir / name, res));
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<> extractAllTo(Path const& dir) {
|
||||||
|
GEODE_UNWRAP(
|
||||||
|
mzTry(mz_zip_goto_first_entry(m_handle))
|
||||||
|
.expect("Unable to navigate to first entry (code {error})")
|
||||||
|
);
|
||||||
|
|
||||||
|
// while not at MZ_END_OF_LIST
|
||||||
|
while (mz_zip_goto_next_entry(m_handle) == MZ_OK) {
|
||||||
|
mz_zip_file* info = nullptr;
|
||||||
|
if (mz_zip_entry_get_info(m_handle, &info) != MZ_OK) {
|
||||||
|
return Err("Unable to get entry info");
|
||||||
|
}
|
||||||
|
|
||||||
|
Path filePath;
|
||||||
|
filePath.assign(info->filename, info->filename + info->filename_size);
|
||||||
|
|
||||||
|
// make sure zip files like root/../../file.txt don't get extracted to
|
||||||
|
// avoid zip attacks
|
||||||
|
#ifdef GEODE_IS_WINDOWS
|
||||||
|
if (!std::filesystem::relative((dir / filePath).wstring(), dir.wstring()).empty()) {
|
||||||
|
#else
|
||||||
|
if (!ghc::filesystem::relative(dir / filePath, dir).empty()) {
|
||||||
|
#endif
|
||||||
|
if (m_entries.at(filePath).isDirectory) {
|
||||||
|
GEODE_UNWRAP(file::createDirectoryAll(dir / filePath));
|
||||||
|
} else {
|
||||||
|
GEODE_UNWRAP(this->extractAt(dir, filePath));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log::error(
|
||||||
|
"Zip entry '{}' is not contained within zip bounds",
|
||||||
|
dir / filePath
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
Result<ByteVector> extract(Path const& name) {
|
Result<ByteVector> extract(Path const& name) {
|
||||||
if (!m_entries.count(name)) {
|
if (!m_entries.count(name)) {
|
||||||
return Err("Entry not found");
|
return Err("Entry not found");
|
||||||
|
@ -458,28 +525,7 @@ Result<> Unzip::extractTo(Path const& name, Path const& path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<> Unzip::extractAllTo(Path const& dir) {
|
Result<> Unzip::extractAllTo(Path const& dir) {
|
||||||
GEODE_UNWRAP(file::createDirectoryAll(dir));
|
return m_impl->extractAllTo(dir);
|
||||||
for (auto& [entry, info] : m_impl->getEntries()) {
|
|
||||||
// make sure zip files like root/../../file.txt don't get extracted to
|
|
||||||
// avoid zip attacks
|
|
||||||
#ifdef GEODE_IS_WINDOWS
|
|
||||||
if (!std::filesystem::relative((dir / entry).wstring(), dir.wstring()).empty()) {
|
|
||||||
#else
|
|
||||||
if (!ghc::filesystem::relative(dir / entry, dir).empty()) {
|
|
||||||
#endif
|
|
||||||
if (info.isDirectory) {
|
|
||||||
GEODE_UNWRAP(file::createDirectoryAll(dir / entry));
|
|
||||||
} else {
|
|
||||||
GEODE_UNWRAP(this->extractTo(entry, dir / entry));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
log::error(
|
|
||||||
"Zip entry '{}' is not contained within zip bounds",
|
|
||||||
dir / entry
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Ok();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result<> Unzip::intoDir(
|
Result<> Unzip::intoDir(
|
||||||
|
|
Loading…
Reference in a new issue