#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; }