detect archive type by using magic numbers. Provide a fallback mechanism for .zip files lacking magic numbers.

This commit is contained in:
Felix Kauselmann 2015-04-08 15:20:12 +02:00
parent 3f0359ddcf
commit ccd4c9e2d8

View File

@ -73,6 +73,13 @@ struct SevenZipInterface {
//SevenZipInterface * szInterface; //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) : CompressedArchive::CompressedArchive(const QString & filePath, QObject *parent) :
QObject(parent),sevenzLib(0),valid(false),tools(false) QObject(parent),sevenzLib(0),valid(false),tools(false)
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
@ -101,35 +108,76 @@ CompressedArchive::CompressedArchive(const QString & filePath, QObject *parent)
// openCallbackSpec->Password = L"1"; // openCallbackSpec->Password = L"1";
//get file type from suffix //get file type from suffix
QString suffix=QFileInfo(filePath).suffix(); int i=-1;
int i; 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? //TODO: this suffix matching is rather primitive - better approach?
#ifdef Q_OS_UNIX #ifdef Q_OS_UNIX
if (suffix != "cbr" && suffix != "rar") if (memcmp(magicNumber,rar,6) != 0)
{ {
//match suffix to GUID list //match suffix to GUID list
if (suffix == "zip" || suffix == "cbz") if (memcmp(magicNumber,zip,2)==0)
i=0; i=0;
else if (suffix == "tar" || suffix == "cbt") else if (memcmp(magicNumber,sevenz,6)==0)
i=1;
else if (suffix == "7z" || suffix == "cb7")
i=2; i=2;
else if (suffix == "arj") else if (memcmp(magicNumber,arj,2)==0)
i=3; 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 #else
//match suffix to GUID list if (memcmp(magicNumber,rar,6) == 0)
if (suffix == "rar" || suffix == "cbr") if (memcmp(magicNumber,rar5,7) == 0)
return;
else
i=0; i=0;
else if (suffix == "zip" || suffix == "cbz") else if (memcmp(magicNumber,zip,2)==0)
i=1; i=1;
else if (suffix == "tar" || suffix == "cbt") else if (memcmp(magicNumber,sevenz,6)==0)
i=2;
else if (suffix == "7z" || suffix == "cb7")
i=3; i=3;
else if (suffix == "arj") else if (memcmp(magicNumber,arj,2)==0)
i=4; 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 #endif
#ifdef UNICODE #ifdef UNICODE
@ -169,8 +217,10 @@ CompressedArchive::CompressedArchive(const QString & filePath, QObject *parent)
} }
else else
{ {
if (memcmp(magicNumber,rar5,7) == 0)
return;//we don't support rar5
isRar=true; //tell the destructor we *tried* to open a rar file! isRar=true; //tell the destructor we *tried* to open a rar file!
//according to valgrind, something goes wrong here
if (szInterface->createObjectFunc(&CLSID_CFormatRar, &IID_InArchive, (void **)&szInterface->archive) != S_OK) if (szInterface->createObjectFunc(&CLSID_CFormatRar, &IID_InArchive, (void **)&szInterface->archive) != S_OK)
{ {
qDebug() << "Error creating rar archive :" + filePath; qDebug() << "Error creating rar archive :" + filePath;
@ -207,7 +257,6 @@ CompressedArchive::CompressedArchive(const QString & filePath, QObject *parent)
//isRar = true; //isRar = true;
} }
} }
} }
} }
#endif #endif
@ -215,10 +264,13 @@ CompressedArchive::CompressedArchive(const QString & filePath, QObject *parent)
CompressedArchive::~CompressedArchive() CompressedArchive::~CompressedArchive()
{ {
//always close the archive! //always close the archive!
if (szInterface->archive)
{
szInterface->archive->Close(); szInterface->archive->Close();
}
#ifdef Q_OS_UNIX #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(); szInterface->archive->AddRef();
} }
@ -426,5 +478,3 @@ STDMETHODIMP CompressedArchive::CreateEncoder(UInt32 index, const GUID *interfac
} }
#endif #endif