move more zip parsings

Signed-off-by: Trial97 <alexandru.tripon97@gmail.com>
This commit is contained in:
Trial97 2025-07-11 00:43:28 +03:00
parent 43ceacbe56
commit e0fad4a784
No known key found for this signature in database
GPG Key ID: 55EF5DA53DB36318
20 changed files with 165 additions and 253 deletions

View File

@ -59,8 +59,6 @@
#include <QtConcurrentRun>
#include <memory>
#include <quazip/quazipdir.h>
InstanceImportTask::InstanceImportTask(const QUrl& sourceUrl, QWidget* parent, QMap<QString, QString>&& extra_info)
: m_sourceUrl(sourceUrl), m_extra_info(extra_info), m_parent(parent)
{}

View File

@ -40,8 +40,6 @@
#include <QUrl>
#include "InstanceTask.h"
class QuaZip;
class InstanceImportTask : public InstanceTask {
Q_OBJECT
public:

View File

@ -37,9 +37,6 @@
#include "MMCZip.h"
#include <archive.h>
#include <qcontainerfwd.h>
#include <quazip/quazip.h>
#include <quazip/quazipdir.h>
#include <quazip/quazipfile.h>
#include "FileSystem.h"
#include "archive/ArchiveReader.h"
@ -201,21 +198,8 @@ std::optional<QStringList> extractSubDir(ArchiveReader* zip, const QString& subd
return extracted;
}
int flags;
/* Select which attributes we want to restore. */
flags = ARCHIVE_EXTRACT_TIME;
flags |= ARCHIVE_EXTRACT_PERM;
flags |= ARCHIVE_EXTRACT_ACL;
flags |= ARCHIVE_EXTRACT_FFLAGS;
std::unique_ptr<archive, void (*)(archive*)> extPtr(archive_write_disk_new(), [](archive* a) {
archive_write_close(a);
archive_write_free(a);
});
auto extPtr = ArchiveWriter::createDiskWriter();
auto ext = extPtr.get();
archive_write_disk_set_options(ext, flags);
archive_write_disk_set_standard_lookup(ext);
if (!zip->parse([&subdir, &target, &target_top_dir, ext, &extracted](ArchiveReader::File* f) {
QString file_name = f->filename();
@ -309,21 +293,8 @@ bool extractFile(QString fileCompressed, QString file, QString target)
if (!f) {
return false;
}
int flags;
/* Select which attributes we want to restore. */
flags = ARCHIVE_EXTRACT_TIME;
flags |= ARCHIVE_EXTRACT_PERM;
flags |= ARCHIVE_EXTRACT_ACL;
flags |= ARCHIVE_EXTRACT_FFLAGS;
std::unique_ptr<archive, void (*)(archive*)> extPtr(archive_write_disk_new(), [](archive* a) {
archive_write_close(a);
archive_write_free(a);
});
auto extPtr = ArchiveWriter::createDiskWriter();
auto ext = extPtr.get();
archive_write_disk_set_options(ext, flags);
archive_write_disk_set_standard_lookup(ext);
return f->writeFile(ext, target);
}

View File

@ -36,8 +36,6 @@
#pragma once
#include <quazip.h>
#include <quazip/JlCompress.h>
#include <QDir>
#include <QFileInfo>
#include <QFuture>
@ -46,14 +44,12 @@
#include <QSet>
#include <QString>
#include <functional>
#include <memory>
#include <optional>
#include "archive/ArchiveReader.h"
#if defined(LAUNCHER_APPLICATION)
#include "minecraft/mod/Mod.h"
#endif
#include "tasks/Task.h"
namespace MMCZip {
using FilterFileFunction = std::function<bool(const QFileInfo&)>;

View File

@ -40,7 +40,6 @@ QByteArray ArchiveReader::File::readAll(int* outStatus)
if (outStatus) {
*outStatus = status;
}
archive_read_close(m_archive.get());
return data;
}
@ -131,7 +130,7 @@ bool ArchiveReader::File::writeFile(archive* out, QString targetFileName, bool n
return (r > ARCHIVE_WARN);
}
bool ArchiveReader::parse(std::function<bool(File*)> doStuff)
bool ArchiveReader::parse(std::function<bool(File*, bool&)> doStuff)
{
auto f = std::make_unique<File>();
auto a = f->m_archive.get();
@ -143,16 +142,24 @@ bool ArchiveReader::parse(std::function<bool(File*)> doStuff)
return false;
}
bool breakControl = false;
while (f->readNextHeader() == ARCHIVE_OK) {
if (!doStuff(f.get())) {
if (!doStuff(f.get(), breakControl)) {
qCritical() << "Failed to parse file:" << f->filename() << "-" << f->error();
return false;
}
if (breakControl) {
break;
}
}
archive_read_close(a);
return true;
}
bool ArchiveReader::parse(std::function<bool(File*)> doStuff)
{
return parse([doStuff](File* f, bool&) { return doStuff(f); });
}
bool ArchiveReader::File::isFile()
{

View File

@ -45,6 +45,7 @@ class ArchiveReader {
std::unique_ptr<File> goToFile(QString filename);
bool parse(std::function<bool(File*)>);
bool parse(std::function<bool(File*, bool&)>);
private:
QString m_archivePath;

View File

@ -176,4 +176,21 @@ bool ArchiveWriter::addFile(ArchiveReader::File* f)
{
return f->writeFile(m_archive, "", true);
}
std::unique_ptr<archive, void (*)(archive*)> ArchiveWriter::createDiskWriter()
{
int flags = ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL | ARCHIVE_EXTRACT_FFLAGS;
std::unique_ptr<archive, void (*)(archive*)> extPtr(archive_write_disk_new(), [](archive* a) {
if (a) {
archive_write_close(a);
archive_write_free(a);
}
});
archive* ext = extPtr.get();
archive_write_disk_set_options(ext, flags);
archive_write_disk_set_standard_lookup(ext);
return extPtr;
}
} // namespace MMCZip

View File

@ -21,6 +21,8 @@ class ArchiveWriter {
bool addFile(const QString& fileDest, const QByteArray& data);
bool addFile(ArchiveReader::File* f);
static std::unique_ptr<archive, void (*)(archive*)> createDiskWriter();
private:
struct archive* m_archive = nullptr;
QString m_filename;

View File

@ -2,6 +2,7 @@
#include <QtConcurrent>
#include "FileSystem.h"
#include "archive/ArchiveReader.h"
#include "archive/ArchiveWriter.h"
namespace MMCZip {
@ -28,21 +29,8 @@ auto ExtractZipTask::extractZip() -> ZipResult
return ZipResult();
}
int flags;
/* Select which attributes we want to restore. */
flags = ARCHIVE_EXTRACT_TIME;
flags |= ARCHIVE_EXTRACT_PERM;
flags |= ARCHIVE_EXTRACT_ACL;
flags |= ARCHIVE_EXTRACT_FFLAGS;
std::unique_ptr<archive, void (*)(archive*)> extPtr(archive_write_disk_new(), [](archive* a) {
archive_write_close(a);
archive_write_free(a);
});
auto extPtr = ArchiveWriter::createDiskWriter();
auto ext = extPtr.get();
archive_write_disk_set_options(ext, flags);
archive_write_disk_set_standard_lookup(ext);
setStatus("Extracting files...");
setProgress(0, m_input.getFiles().count());

View File

@ -16,7 +16,6 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "java/download/ArchiveDownloadTask.h"
#include <quazip.h>
#include <memory>
#include "Application.h"

View File

@ -43,9 +43,6 @@
#include <FileSystem.h>
#include <MMCZip.h>
#include <io/stream_reader.h>
#include <quazip/quazip.h>
#include <quazip/quazipdir.h>
#include <quazip/quazipfile.h>
#include <tag_primitive.h>
#include <tag_string.h>
#include <sstream>

View File

@ -17,11 +17,10 @@
#include <launch/LaunchTask.h>
#include <minecraft/MinecraftInstance.h>
#include <quazip/quazip.h>
#include <quazip/quazipdir.h>
#include <QDir>
#include "FileSystem.h"
#include "MMCZip.h"
#include "archive/ArchiveReader.h"
#include "archive/ArchiveWriter.h"
#ifdef major
#undef major
@ -41,30 +40,21 @@ static QString replaceSuffix(QString target, const QString& suffix, const QStrin
static bool unzipNatives(QString source, QString targetFolder, bool applyJnilibHack)
{
QuaZip zip(source);
if (!zip.open(QuaZip::mdUnzip)) {
return false;
}
MMCZip::ArchiveReader zip(source);
QDir directory(targetFolder);
if (!zip.goToFirstFile()) {
return false;
}
do {
QString name = zip.getCurrentFileName();
auto extPtr = MMCZip::ArchiveWriter::createDiskWriter();
auto ext = extPtr.get();
return zip.parse([applyJnilibHack, directory, ext](MMCZip::ArchiveReader::File* f) {
QString name = f->filename();
auto lowercase = name.toLower();
if (applyJnilibHack) {
name = replaceSuffix(name, ".jnilib", ".dylib");
}
QString absFilePath = directory.absoluteFilePath(name);
if (!JlCompress::extractFile(&zip, "", absFilePath)) {
return false;
}
} while (zip.goToNextFile());
zip.close();
if (zip.getZipError() != 0) {
return false;
}
return true;
return f->writeFile(ext, absFilePath);
});
}
void ExtractNatives::executeTask()

View File

@ -23,12 +23,9 @@
#include "FileSystem.h"
#include "Json.h"
#include "archive/ArchiveReader.h"
#include "minecraft/mod/ResourcePack.h"
#include <quazip/quazip.h>
#include <quazip/quazipdir.h>
#include <quazip/quazipfile.h>
#include <QCryptographicHash>
namespace DataPackUtils {
@ -111,72 +108,72 @@ bool processZIP(DataPack* pack, ProcessingLevel level)
{
Q_ASSERT(pack->type() == ResourceType::ZIPFILE);
QuaZip zip(pack->fileinfo().filePath());
if (!zip.open(QuaZip::mdUnzip))
MMCZip::ArchiveReader zip(pack->fileinfo().filePath());
bool metaParsed = false;
bool directoryFound = false;
bool iconParsed = false;
bool mcmeta_result = false;
bool pack_png_result = false;
if (!zip.parse([&metaParsed, &directoryFound, &iconParsed, &mcmeta_result, &pack_png_result, pack, level](
MMCZip::ArchiveReader::File* f, bool& breakControl) {
bool skip = true;
if (!metaParsed && f->filename() == "pack.mcmeta") {
metaParsed = true;
skip = false;
auto data = f->readAll();
mcmeta_result = DataPackUtils::processMCMeta(pack, std::move(data));
if (!mcmeta_result) {
breakControl = true;
return true; // mcmeta invalid
}
}
if (!directoryFound) {
QString normalizedPath = QDir::cleanPath(pack->directory()) + QLatin1Char('/');
if (normalizedPath.startsWith('/'))
normalizedPath.remove(0, 1);
directoryFound = f->filename().startsWith(normalizedPath, Qt::CaseInsensitive);
}
if (!iconParsed && level != ProcessingLevel::BasicInfoOnly && f->filename() == "pack.png") {
iconParsed = true;
skip = false;
auto data = f->readAll();
pack_png_result = DataPackUtils::processPackPNG(pack, std::move(data));
if (!pack_png_result) {
breakControl = true;
return true; // pack.png invalid
}
}
if (skip) {
f->skip();
}
if (metaParsed && directoryFound && (level == ProcessingLevel::BasicInfoOnly || iconParsed)) {
breakControl = true;
}
return true;
})) {
return false; // can't open zip file
QuaZipFile file(&zip);
auto mcmeta_invalid = [&pack]() {
}
if (!mcmeta_result) {
qWarning() << "Data pack at" << pack->fileinfo().filePath() << "does not have a valid pack.mcmeta";
return false; // the mcmeta is not optional
};
if (zip.setCurrentFile("pack.mcmeta")) {
if (!file.open(QIODevice::ReadOnly)) {
qCritical() << "Failed to open file in zip.";
zip.close();
return mcmeta_invalid();
}
auto data = file.readAll();
bool mcmeta_result = DataPackUtils::processMCMeta(pack, std::move(data));
file.close();
if (!mcmeta_result) {
return mcmeta_invalid(); // mcmeta invalid
}
} else {
return mcmeta_invalid(); // could not set pack.mcmeta as current file.
}
QuaZipDir zipDir(&zip);
if (!zipDir.exists(pack->directory())) {
if (!directoryFound) {
return false; // data dir does not exists at zip root
}
if (level == ProcessingLevel::BasicInfoOnly) {
zip.close();
return true; // only need basic info already checked
}
auto png_invalid = [&pack]() {
if (!pack_png_result) {
qWarning() << "Data pack at" << pack->fileinfo().filePath() << "does not have a valid pack.png";
return true; // the png is optional
};
if (zip.setCurrentFile("pack.png")) {
if (!file.open(QIODevice::ReadOnly)) {
qCritical() << "Failed to open file in zip.";
zip.close();
return png_invalid();
}
auto data = file.readAll();
bool pack_png_result = DataPackUtils::processPackPNG(pack, std::move(data));
file.close();
zip.close();
if (!pack_png_result) {
return png_invalid(); // pack.png invalid
}
} else {
zip.close();
return png_invalid(); // could not set pack.mcmeta as current file.
}
zip.close();
return true;
}
@ -321,28 +318,17 @@ bool processPackPNG(const DataPack* pack)
return false; // not processed correctly; https://github.com/PrismLauncher/PrismLauncher/issues/1740
}
case ResourceType::ZIPFILE: {
QuaZip zip(pack->fileinfo().filePath());
if (!zip.open(QuaZip::mdUnzip))
return false; // can't open zip file
MMCZip::ArchiveReader zip(pack->fileinfo().filePath());
auto f = zip.goToFile("pack.png");
if (!f) {
return png_invalid();
}
auto data = f->readAll();
QuaZipFile file(&zip);
if (zip.setCurrentFile("pack.png")) {
if (!file.open(QIODevice::ReadOnly)) {
qCritical() << "Failed to open file in zip.";
zip.close();
return png_invalid();
}
bool pack_png_result = DataPackUtils::processPackPNG(pack, std::move(data));
auto data = file.readAll();
bool pack_png_result = DataPackUtils::processPackPNG(pack, std::move(data));
file.close();
if (!pack_png_result) {
return png_invalid(); // pack.png invalid
}
} else {
return png_invalid(); // could not set pack.mcmeta as current file.
if (!pack_png_result) {
return png_invalid(); // pack.png invalid
}
return false; // not processed correctly; https://github.com/PrismLauncher/PrismLauncher/issues/1740
}

View File

@ -22,10 +22,7 @@
#include "LocalShaderPackParseTask.h"
#include "FileSystem.h"
#include <quazip/quazip.h>
#include <quazip/quazipdir.h>
#include <quazip/quazipfile.h>
#include "archive/ArchiveReader.h"
namespace ShaderPackUtils {
@ -63,25 +60,19 @@ bool processZIP(ShaderPack& pack, ProcessingLevel level)
{
Q_ASSERT(pack.type() == ResourceType::ZIPFILE);
QuaZip zip(pack.fileinfo().filePath());
if (!zip.open(QuaZip::mdUnzip))
MMCZip::ArchiveReader zip(pack.fileinfo().filePath());
if (!zip.collectFiles())
return false; // can't open zip file
QuaZipFile file(&zip);
QuaZipDir zipDir(&zip);
if (!zipDir.exists("/shaders")) {
if (!zip.exists("/shaders")) {
return false; // assets dir does not exists at zip root
}
pack.setPackFormat(ShaderPackFormat::VALID);
if (level == ProcessingLevel::BasicInfoOnly) {
zip.close();
return true; // only need basic info already checked
}
zip.close();
return true;
}

View File

@ -20,9 +20,7 @@
#include "LocalTexturePackParseTask.h"
#include "FileSystem.h"
#include <quazip/quazip.h>
#include <quazip/quazipfile.h>
#include "archive/ArchiveReader.h"
#include <QCryptographicHash>
@ -91,54 +89,35 @@ bool processZIP(TexturePack& pack, ProcessingLevel level)
{
Q_ASSERT(pack.type() == ResourceType::ZIPFILE);
QuaZip zip(pack.fileinfo().filePath());
if (!zip.open(QuaZip::mdUnzip))
return false;
MMCZip::ArchiveReader zip(pack.fileinfo().filePath());
QuaZipFile file(&zip);
{
auto file = zip.goToFile("pack.txt");
if (file) {
auto data = file->readAll();
if (zip.setCurrentFile("pack.txt")) {
if (!file.open(QIODevice::ReadOnly)) {
qCritical() << "Failed to open file in zip.";
zip.close();
return false;
}
bool packTXT_result = TexturePackUtils::processPackTXT(pack, std::move(data));
auto data = file.readAll();
bool packTXT_result = TexturePackUtils::processPackTXT(pack, std::move(data));
file.close();
if (!packTXT_result) {
return false;
if (!packTXT_result) {
return false;
}
}
}
if (level == ProcessingLevel::BasicInfoOnly) {
zip.close();
return true;
}
if (zip.setCurrentFile("pack.png")) {
if (!file.open(QIODevice::ReadOnly)) {
qCritical() << "Failed to open file in zip.";
zip.close();
return false;
}
auto data = file.readAll();
auto file = zip.goToFile("pack.png");
if (file) {
auto data = file->readAll();
bool packPNG_result = TexturePackUtils::processPackPNG(pack, std::move(data));
file.close();
zip.close();
if (!packPNG_result) {
return false;
}
}
zip.close();
return true;
}
@ -189,32 +168,19 @@ bool processPackPNG(const TexturePack& pack)
return false;
}
case ResourceType::ZIPFILE: {
QuaZip zip(pack.fileinfo().filePath());
if (!zip.open(QuaZip::mdUnzip))
return false; // can't open zip file
MMCZip::ArchiveReader zip(pack.fileinfo().filePath());
QuaZipFile file(&zip);
if (zip.setCurrentFile("pack.png")) {
if (!file.open(QIODevice::ReadOnly)) {
qCritical() << "Failed to open file in zip.";
zip.close();
return png_invalid();
}
auto data = file.readAll();
auto file = zip.goToFile("pack.png");
if (file) {
auto data = file->readAll();
bool pack_png_result = TexturePackUtils::processPackPNG(pack, std::move(data));
file.close();
if (!pack_png_result) {
zip.close();
return png_invalid(); // pack.png invalid
}
} else {
zip.close();
return png_invalid(); // could not set pack.mcmeta as current file.
}
return false;
return png_invalid(); // could not set pack.mcmeta as current file.
}
default:
qWarning() << "Invalid type for resource pack parse task!";

View File

@ -23,13 +23,11 @@
#include "LocalWorldSaveParseTask.h"
#include "FileSystem.h"
#include <quazip/quazip.h>
#include <quazip/quazipdir.h>
#include <quazip/quazipfile.h>
#include "archive/ArchiveReader.h"
#include <QDir>
#include <QFileInfo>
#include <tuple>
namespace WorldSaveUtils {
@ -105,22 +103,41 @@ bool processFolder(WorldSave& save, ProcessingLevel level)
/// QString <name of folder containing level.dat>,
/// bool <saves folder found>
/// )
static std::tuple<bool, QString, bool> contains_level_dat(QuaZip& zip)
static std::tuple<bool, QString, bool> contains_level_dat(QString fileName)
{
MMCZip::ArchiveReader zip(fileName);
if (!zip.collectFiles()) {
return std::make_tuple(false, "", false);
}
bool saves = false;
QuaZipDir zipDir(&zip);
if (zipDir.exists("/saves")) {
if (zip.exists("/saves")) {
saves = true;
zipDir.cd("/saves");
}
for (auto const& entry : zipDir.entryList()) {
zipDir.cd(entry);
if (zipDir.exists("level.dat")) {
return std::make_tuple(true, entry, saves);
for (auto file : zip.getFiles()) {
QString relativePath = file;
if (saves) {
if (!relativePath.startsWith("saves/", Qt::CaseInsensitive))
continue;
relativePath = relativePath.mid(QString("saves/").length());
}
if (!relativePath.endsWith("/level.dat", Qt::CaseInsensitive))
continue;
int slashIndex = relativePath.indexOf('/');
if (slashIndex == -1)
continue; // malformed: no slash between saves/ and level.dat
QString worldName = relativePath.left(slashIndex);
QString remaining = relativePath.mid(slashIndex + 1);
// Check that there's nothing between worldName/ and level.dat
if (remaining == "level.dat") {
QString worldDir = (saves ? "saves/" : "") + worldName;
return std::make_tuple(true, worldDir, saves);
}
zipDir.cd("..");
}
return std::make_tuple(false, "", saves);
}
@ -128,19 +145,14 @@ bool processZIP(WorldSave& save, ProcessingLevel level)
{
Q_ASSERT(save.type() == ResourceType::ZIPFILE);
QuaZip zip(save.fileinfo().filePath());
if (!zip.open(QuaZip::mdUnzip))
return false; // can't open zip file
auto [found, save_dir_name, found_saves_dir] = contains_level_dat(zip);
if (save_dir_name.endsWith("/")) {
save_dir_name.chop(1);
}
auto [found, save_dir_name, found_saves_dir] = contains_level_dat(save.fileinfo().filePath());
if (!found) {
return false;
}
if (save_dir_name.endsWith("/")) {
save_dir_name.chop(1);
}
save.setSaveDirName(save_dir_name);
@ -151,14 +163,11 @@ bool processZIP(WorldSave& save, ProcessingLevel level)
}
if (level == ProcessingLevel::BasicInfoOnly) {
zip.close();
return true; // only need basic info already checked
}
// reserved for more intensive processing
zip.close();
return true;
}

View File

@ -39,8 +39,6 @@
#include <QtConcurrent>
#include <algorithm>
#include <quazip/quazip.h>
#include "FileSystem.h"
#include "Json.h"
#include "MMCZip.h"

View File

@ -1,6 +1,4 @@
#pragma once
#include <quazip/quazip.h>
#include <quazip/quazipdir.h>
#include "InstanceTask.h"
#include "PackHelpers.h"
#include "meta/Index.h"

View File

@ -19,8 +19,6 @@
#include "archive/ArchiveReader.h"
#include "net/NetJob.h"
#include <quazip/quazip.h>
#include <QFutureWatcher>
#include <QStringList>
#include <QUrl>

View File

@ -17,6 +17,7 @@
zlib,
msaClientID ? null,
gamemodeSupport ? stdenv.hostPlatform.isLinux,
libarchive,
}:
assert lib.assertMsg (
gamemodeSupport -> stdenv.hostPlatform.isLinux
@ -82,6 +83,7 @@ stdenv.mkDerivation {
kdePackages.qtbase
kdePackages.qtnetworkauth
kdePackages.quazip
libarchive
tomlplusplus
zlib
]