#include "compressed_archive.h" #include #include #include "extract_delegate.h" #include CompressedArchive::CompressedArchive(const QString &filePath, QObject *parent) : QObject(parent), tools(true), valid(false), numFiles(0), ar(NULL), stream(NULL) { // open file #ifdef Q_OS_WIN stream = ar_open_file_w((wchar_t *)filePath.utf16()); #else stream = ar_open_file(filePath.toLocal8Bit().constData()); #endif if (!stream) { return; } // open archive ar = ar_open_rar_archive(stream); // TODO: build unarr with 7z support and test this! if (!ar) ar = ar_open_7z_archive(stream); if (!ar) ar = ar_open_tar_archive(stream); // zip detection is costly, so it comes last... if (!ar) ar = ar_open_zip_archive(stream, false); if (!ar) { return; } // initial parse while (ar_parse_entry(ar)) { // make sure we really got a file header if (ar_entry_get_size(ar) > 0) { fileNames.append(ar_entry_get_name(ar)); offsets.append(ar_entry_get_offset(ar)); numFiles++; } } if (!ar_at_eof(ar)) { // fail if the initial parse didn't reach EOF // this might be a bit too drastic qDebug() << "Error while parsing archive"; return; } if (numFiles > 0) { valid = true; } } CompressedArchive::~CompressedArchive() { ar_close_archive(ar); ar_close(stream); } QList CompressedArchive::getFileNames() { return fileNames; } bool CompressedArchive::isValid() { return valid; } bool CompressedArchive::toolsLoaded() { // for backwards compatibilty return tools; } int CompressedArchive::getNumFiles() { return numFiles; } void CompressedArchive::getAllData(const QVector &indexes, ExtractDelegate *delegate) { if (indexes.isEmpty()) return; QByteArray buffer; int i = 0; while (i < indexes.count()) { if (delegate == nullptr || delegate->isCancelled()) { return; } // use the offset list so we generated so we're not getting any non-page files ar_parse_entry_at(ar, offsets.at(indexes.at(i))); // set ar_entry to start of indexes buffer.resize(ar_entry_get_size(ar)); if (ar_entry_uncompress(ar, buffer.data(), buffer.size())) // did we extract it? { delegate->fileExtracted(indexes.at(i), buffer); // return extracted file } else { delegate->crcError(indexes.at(i)); // we could not extract it... } i++; } } QByteArray CompressedArchive::getRawDataAtIndex(int index) { QByteArray buffer; if (index >= 0 && index < getNumFiles()) { ar_parse_entry_at(ar, offsets.at(index)); buffer.resize(ar_entry_get_size(ar)); if (ar_entry_uncompress(ar, buffer.data(), buffer.size())) { return buffer; } else { return QByteArray(); } } return buffer; }