diff --git a/YACReader/YACReader.pro b/YACReader/YACReader.pro index 77f21926..b17ffb7f 100644 --- a/YACReader/YACReader.pro +++ b/YACReader/YACReader.pro @@ -223,12 +223,7 @@ exists (../compressed_archive/libp7zip) { Please check the compressed_archive folder for further instructions.) } } -} else { -exists (../compressed_archive/unarr/unarr-master) { - message(Found unarr source-code) - } -} - +} unix:!macx { #set install prefix if it's empty diff --git a/YACReaderLibrary/YACReaderLibrary.pro b/YACReaderLibrary/YACReaderLibrary.pro index 21265c48..b33896f7 100644 --- a/YACReaderLibrary/YACReaderLibrary.pro +++ b/YACReaderLibrary/YACReaderLibrary.pro @@ -285,10 +285,6 @@ exists (../compressed_archive/libp7zip) { Please check the compressed_archive folder for further instructions.) } } -} else { - exists (../compressed_archive/unarr/unarr-master) { - message(Found unarr source code) - } } unix:!macx { diff --git a/YACReaderLibrary/library_creator.cpp b/YACReaderLibrary/library_creator.cpp index 42e43271..8b5662f4 100644 --- a/YACReaderLibrary/library_creator.cpp +++ b/YACReaderLibrary/library_creator.cpp @@ -122,8 +122,8 @@ void LibraryCreator::processLibrary(const QString & source, const QString & targ void LibraryCreator::run() { stopRunning = false; - - //check for 7z lib +#ifndef use_unarr +//check for 7z lib #if defined Q_OS_UNIX && !defined Q_OS_MAC QLibrary *sevenzLib = new QLibrary(QString(LIBDIR)+"/p7zip/7z.so"); #else @@ -137,7 +137,7 @@ void LibraryCreator::run() exit(); } sevenzLib->deleteLater(); - +#endif if(_mode == CREATOR) { QLOG_INFO() << "Starting to create new library ( " << _source << "," << _target << ")"; diff --git a/YACReaderLibrary/main.cpp b/YACReaderLibrary/main.cpp index a883151f..1233ffac 100644 --- a/YACReaderLibrary/main.cpp +++ b/YACReaderLibrary/main.cpp @@ -92,6 +92,7 @@ void logSystemAndConfig() QLOG_INFO() << "SO : Unknown"; #endif +#ifndef use_unarr #ifdef Q_OS_WIN if(QLibrary::isLibrary(QApplication::applicationDirPath()+"/utils/7z.dll")) #elif defined Q_OS_UNIX && !defined Q_OS_MAC @@ -102,6 +103,9 @@ void logSystemAndConfig() QLOG_INFO() << "7z : found"; else QLOG_ERROR() << "7z : not found"; +#else + QLOG_INFO() << "using unarr decompression backend"; +#endif #if defined Q_OS_UNIX && !defined Q_OS_MAC if(QFileInfo(QString(BINDIR)+"/qrencode").exists()) #else diff --git a/compressed_archive/compressed_archive.cpp b/compressed_archive/compressed_archive.cpp index e11b054c..6d75ad6b 100644 --- a/compressed_archive/compressed_archive.cpp +++ b/compressed_archive/compressed_archive.cpp @@ -73,6 +73,13 @@ struct SevenZipInterface { //SevenZipInterface * szInterface; +const char rar[7]={0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x00}; +const char rar5[8]={0x52, 0x61, 0x72, 0x21, 0x1A, 0x07, 0x01, 0x00}; +const char zip[2]={0x50, 0x4B}; +const char sevenz[6]={0x37, 0x7A, 0xBC, 0xAF, 0x27, 0x1C}; +const char tar[6]="ustar"; +const char arj[2]={0x60, 0xEA}; + CompressedArchive::CompressedArchive(const QString & filePath, QObject *parent) : QObject(parent),sevenzLib(0),valid(false),tools(false) #ifdef Q_OS_UNIX @@ -101,35 +108,76 @@ CompressedArchive::CompressedArchive(const QString & filePath, QObject *parent) // openCallbackSpec->Password = L"1"; //get file type from suffix - QString suffix=QFileInfo(filePath).suffix(); - int i; + int i=-1; + QFile filex(filePath); + + if (!filex.open(QIODevice::ReadOnly)) + return; + QByteArray magicNumber=filex.read(8); //read first 8 bytes + + //if (memcmp(magicNumber,rar5,8)==0) + //return; //rar5 is not supported + //qDebug() << memcmp(magicNumber,rar,7); //TODO: this suffix matching is rather primitive - better approach? #ifdef Q_OS_UNIX - if (suffix != "cbr" && suffix != "rar") + if (memcmp(magicNumber,rar,6) != 0) { //match suffix to GUID list - if (suffix == "zip" || suffix == "cbz") + if (memcmp(magicNumber,zip,2)==0) i=0; - else if (suffix == "tar" || suffix == "cbt") - i=1; - else if (suffix == "7z" || suffix == "cb7") + else if (memcmp(magicNumber,sevenz,6)==0) i=2; - else if (suffix == "arj") + else if (memcmp(magicNumber,arj,2)==0) i=3; - else return; + else + { + filex.seek(257); + magicNumber=filex.read(8); + if (memcmp(magicNumber,tar,5)==0) + i=1; + } + if (i==-1) //fallback code + { + QFileInfo fileinfo(filePath); + if (fileinfo.suffix() == "zip" || fileinfo.suffix() == "cbz") + { + i=0; + } + else + { + return; + } + } #else - //match suffix to GUID list - if (suffix == "rar" || suffix == "cbr") - i=0; - else if (suffix == "zip" || suffix == "cbz") + if (memcmp(magicNumber,rar,6) == 0) + if (memcmp(magicNumber,rar5,7) == 0) + return; + else + i=0; + else if (memcmp(magicNumber,zip,2)==0) i=1; - else if (suffix == "tar" || suffix == "cbt") - i=2; - else if (suffix == "7z" || suffix == "cb7") + else if (memcmp(magicNumber,sevenz,6)==0) i=3; - else if (suffix == "arj") + else if (memcmp(magicNumber,arj,2)==0) i=4; - else return; + else { + filex.seek(257); + magicNumber=filex.read(8); + if (memcmp(magicNumber,tar,5)==0) + i=2; + } + if (i==-1) //fallback code + { + QFileInfo fileinfo(filePath); + if (fileinfo.suffix() == "zip" || fileinfo.suffix() == "cbz") + { + i=1; + } + else + { + return; + } + } #endif #ifdef UNICODE @@ -169,8 +217,10 @@ CompressedArchive::CompressedArchive(const QString & filePath, QObject *parent) } else { - isRar=true; //tell the destructor we *tried* to open a rar file! - //according to valgrind, something goes wrong here + if (memcmp(magicNumber,rar5,7) == 0) + return;//we don't support rar5 + + isRar=true; //tell the destructor we *tried* to open a rar file! if (szInterface->createObjectFunc(&CLSID_CFormatRar, &IID_InArchive, (void **)&szInterface->archive) != S_OK) { qDebug() << "Error creating rar archive :" + filePath; @@ -207,7 +257,6 @@ CompressedArchive::CompressedArchive(const QString & filePath, QObject *parent) //isRar = true; } } - } } #endif @@ -215,10 +264,13 @@ CompressedArchive::CompressedArchive(const QString & filePath, QObject *parent) CompressedArchive::~CompressedArchive() { //always close the archive! - szInterface->archive->Close(); + if (szInterface->archive) + { + szInterface->archive->Close(); + } #ifdef Q_OS_UNIX - if(isRar) //TODO: fix this!!! Memory leak!!!! If AddRef is not used, a crash occurs in "delete szInterface" + if(isRar) //TODO: Memory leak!!!! If AddRef is not used, a crash occurs in "delete szInterface" { szInterface->archive->AddRef(); } @@ -425,6 +477,4 @@ STDMETHODIMP CompressedArchive::CreateEncoder(UInt32 index, const GUID *interfac return S_OK;//szInterface->createObjectFuncRar(&CLSID_CFormatRar,interfaceID,coder); } -#endif - - +#endif \ No newline at end of file diff --git a/compressed_archive/unarr/compressed_archive.cpp b/compressed_archive/unarr/compressed_archive.cpp index 2a4b9805..b7594986 100644 --- a/compressed_archive/unarr/compressed_archive.cpp +++ b/compressed_archive/unarr/compressed_archive.cpp @@ -12,27 +12,46 @@ extern"C" { CompressedArchive::CompressedArchive(const QString & filePath, QObject *parent) : QObject(parent),valid(false),tools(true),numFiles(0),ar(NULL),stream(NULL) { + //open file stream = ar_open_file(filePath.toStdString().c_str()); - //try to open archive + if (!stream) + { + return; + } + + //open archive ar = ar_open_rar_archive(stream); - if (!ar) ar = ar_open_zip_archive(stream, false); + //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)) { - numFiles++; - fileNames.append(ar_entry_get_name(ar)); - offsets.append(ar_entry_get_offset(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; - tools = true; } } @@ -54,6 +73,7 @@ bool CompressedArchive::isValid() bool CompressedArchive::toolsLoaded() { + //for backwards compatibilty return tools; } @@ -72,17 +92,17 @@ void CompressedArchive::getAllData(const QVector & indexes, ExtractDele int i=0; while (i < indexes.count()) { - if (i==0) + //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? { - ar_parse_entry_at(ar, offsets.at(indexes.at(0))); //set ar_entry to start of indexes + delegate->fileExtracted(indexes.at(i), buffer); //return extracted file } else { - ar_parse_entry(ar); - } - buffer.resize(ar_entry_get_size(ar)); - ar_entry_uncompress(ar, buffer.data(), buffer.size()); - delegate->fileExtracted(indexes.at(i), buffer); //return extracted files :) + delegate->crcError(indexes.at(i)); //we could not extract it... + } i++; } } @@ -93,13 +113,15 @@ QByteArray CompressedArchive::getRawDataAtIndex(int index) if(index >= 0 && index < getNumFiles()) { ar_parse_entry_at(ar, offsets.at(index)); - while (ar_entry_get_size(ar)==0) - { - ar_parse_entry(ar); - } buffer.resize(ar_entry_get_size(ar)); - ar_entry_uncompress(ar, buffer.data(), buffer.size()); - //return buffer; + if(ar_entry_uncompress(ar, buffer.data(), buffer.size())) + { + return buffer; + } + else + { + return QByteArray(); + } } return buffer; } diff --git a/compressed_archive/unarr/unarr-wrapper.pri b/compressed_archive/unarr/unarr-wrapper.pri index f4f630e9..2ba188c6 100644 --- a/compressed_archive/unarr/unarr-wrapper.pri +++ b/compressed_archive/unarr/unarr-wrapper.pri @@ -6,8 +6,31 @@ HEADERS += $$PWD/extract_delegate.h \ SOURCES += $$PWD/compressed_archive.cpp \ -#static build (no lib) -include(unarr.pro) +unix:!macx:exists (/usr/include/unarr.h) { + message(Using system provided unarr installation) + LIBS+=-lunarr + DEFINES+=use_unarr + } +else:macx:exists (../../dependencies/unarr/libunarr.dynlib) { + LIBS += -L../../dependencies/unarr/ -lunarr + DEFINES+=use_unarr + } -#for system libunarr.so -#LIBS+=-lunarr \ No newline at end of file +else:win32:exists (../../dependencies/unarr/unarr.dll) { + LIBS += -L../../dependencies/unarr/ -lunarr + DEFINES+=use_unarr + } + +else:exists ($$PWD/unarr-master) { + message(Found unarr source-code) + message(Unarr will be build as a part of YACReader) + + #qmake based unarr build system + #this should only be used for testing or as a last resort + include(unarr.pro) + DEFINES+=use_unarr + } + else { + error(Missing dependency: unarr decrompression backend. Please install libunarr on your system\ + or provide a copy of the unarr source code in compressed_archive/unarr/unarr-master) + } \ No newline at end of file diff --git a/tests/compressed_archive_test/compressed_archive_test.pro b/tests/compressed_archive_test/compressed_archive_test.pro index ebf2185e..a6c55cc4 100644 --- a/tests/compressed_archive_test/compressed_archive_test.pro +++ b/tests/compressed_archive_test/compressed_archive_test.pro @@ -13,10 +13,6 @@ win32 { CONFIG -= embed_manifest_exe } -unix { - DEFINES += "LIBDIR=\\\"$$/usr/lib\\\"" - } - !CONFIG(unarr){ include(../../compressed_archive/wrapper.pri) } else { diff --git a/tests/compressed_archive_test/main.cpp b/tests/compressed_archive_test/main.cpp index a2024a2a..f2686a51 100644 --- a/tests/compressed_archive_test/main.cpp +++ b/tests/compressed_archive_test/main.cpp @@ -25,7 +25,7 @@ int main(int argc, char *argv[]) return 0; } - QCoreApplication app(argc, argv); + //QCoreApplication app(argc, argv); QString s(argv[1]);