264 lines
6.7 KiB
C++
264 lines
6.7 KiB
C++
#include "downloadablefile.h"
|
|
|
|
#include "binaryverifier.h"
|
|
#include "bitstreamverifier.h"
|
|
|
|
#include <QFile>
|
|
#include <QFileInfo>
|
|
#include <QtEndian>
|
|
|
|
#include "miniz.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include "mydebug.h"
|
|
|
|
class ZipHelper
|
|
{
|
|
public:
|
|
enum
|
|
{
|
|
MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100,
|
|
MZ_ZIP_FLAG_IGNORE_PATH = 0x0200,
|
|
MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400,
|
|
MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800
|
|
} mz_zip_flags;
|
|
|
|
struct bsk_zip_info_t
|
|
{
|
|
int valid;
|
|
int compressed;
|
|
unsigned int compressed_size;
|
|
unsigned int uncompressed_size;
|
|
const char* filename;
|
|
unsigned int crc32;
|
|
unsigned int data_offset;
|
|
const void* data_start;
|
|
};
|
|
|
|
struct zip_file_header_t
|
|
{
|
|
unsigned char header_signature[4];
|
|
unsigned char ver_extractor[2];
|
|
unsigned char flags[2];
|
|
unsigned char comp_method[2];
|
|
unsigned char mod_time[2];
|
|
unsigned char mod_date[2];
|
|
unsigned char crc32[4];
|
|
unsigned char csize[4];
|
|
unsigned char usize[4];
|
|
unsigned char fname_len[2];
|
|
unsigned char extra_len[2];
|
|
};
|
|
|
|
bsk_zip_info_t mzi;
|
|
|
|
char buffer[1024];
|
|
|
|
bool check(QFile& f)
|
|
{
|
|
QByteArray d=f.read(4096);
|
|
return check(d);
|
|
}
|
|
|
|
bool check(const QByteArray& d)
|
|
{
|
|
//QByteArray d=f.read(4096);
|
|
|
|
const char* image=(const char*)d.constData();
|
|
|
|
const struct zip_file_header_t* zh=(const struct zip_file_header_t*)image;
|
|
if (!(zh->header_signature[0]=='P' && zh->header_signature[1]=='K' && zh->header_signature[2]==3 && zh->header_signature[3]==4))
|
|
return false; //not a zip file
|
|
|
|
unsigned long csize=mz_b2l(zh->csize);
|
|
unsigned long usize=mz_b2l(zh->usize);
|
|
|
|
unsigned short fname_len=mz_b2s(zh->fname_len);
|
|
unsigned short extra_len=mz_b2s(zh->extra_len);
|
|
|
|
unsigned short flags=mz_b2s(zh->flags);
|
|
|
|
bsk_zip_info_t* zi=&mzi;
|
|
memset(zi, 0, sizeof *zi);
|
|
zi->valid=1;
|
|
zi->filename=buffer;
|
|
|
|
zi->compressed=(flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? 1 : 0;
|
|
zi->compressed|=csize!=usize ? 2 : 0;
|
|
|
|
zi->compressed_size=csize;
|
|
zi->uncompressed_size=usize;
|
|
zi->crc32=mz_b2l(zh->crc32);
|
|
|
|
if (!fname_len)
|
|
{
|
|
buffer[0]=0;
|
|
zi->filename=0;
|
|
}
|
|
else
|
|
{
|
|
unsigned int len=fname_len;
|
|
if (len>(sizeof(buffer)-1))
|
|
len=sizeof(buffer)-1;
|
|
unsigned int i;
|
|
char* s=(char*)&image[sizeof(struct zip_file_header_t)];
|
|
for(i=0; i<len; ++i)
|
|
buffer[i]=s[i];
|
|
buffer[i]=0;
|
|
zi->filename=buffer;
|
|
}
|
|
|
|
zi->data_offset=sizeof(struct zip_file_header_t)+fname_len+extra_len;
|
|
zi->data_start=&image[zi->data_offset];
|
|
|
|
return true;
|
|
}
|
|
|
|
QByteArray uncompress(const void* src, unsigned int len, unsigned int expected_len)
|
|
{
|
|
unsigned char* p=new unsigned char[expected_len+1000];
|
|
unsigned long dst_len=expected_len;
|
|
|
|
//int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len)
|
|
int r=mz_uncompress(p, &dst_len, (const unsigned char*)src, len);
|
|
if (r)
|
|
return QByteArray();
|
|
return QByteArray((char*)p, dst_len);
|
|
}
|
|
|
|
unsigned long mz_b2l(const unsigned char* b)
|
|
{
|
|
unsigned long l;
|
|
memcpy(&l, b, sizeof l);
|
|
return l;
|
|
}
|
|
|
|
unsigned short mz_b2s(const unsigned char* b)
|
|
{
|
|
unsigned short l;
|
|
memcpy(&l, b, sizeof l);
|
|
return l;
|
|
}
|
|
|
|
void mz_s2b(unsigned char* b, unsigned short s)
|
|
{
|
|
memcpy(b, &s, sizeof s);
|
|
}
|
|
|
|
void mz_l2b(unsigned char* b, unsigned long s)
|
|
{
|
|
memcpy(b, &s, sizeof s);
|
|
}
|
|
};
|
|
|
|
DownloadableFile::DownloadableFile()
|
|
{
|
|
}
|
|
|
|
#include <QCryptographicHash>
|
|
|
|
bool DownloadableFile::open(const QString &filename)
|
|
{
|
|
m_fn=filename;
|
|
|
|
QFileInfo finfo(filename);
|
|
|
|
m_info.filename=finfo.fileName();
|
|
m_info.sourcefile=finfo.fileName();
|
|
|
|
m_info.errStr="not yet validated";
|
|
|
|
QFile f(m_fn);
|
|
|
|
m_info.compressed_size=finfo.size();
|
|
m_info.uncompressed_size=finfo.size();
|
|
|
|
bool ok=f.open(QIODevice::ReadOnly);
|
|
if (!ok)
|
|
{
|
|
m_info.errStr=f.errorString();
|
|
return false;
|
|
}
|
|
|
|
QByteArray all=f.readAll();
|
|
|
|
//Zipped?
|
|
{
|
|
ZipHelper zhelp;
|
|
bool zipped=zhelp.check(all);
|
|
if (zipped)
|
|
{
|
|
m_info.uncompressed_size=zhelp.mzi.uncompressed_size;
|
|
m_info.filename=zhelp.mzi.filename;
|
|
|
|
QByteArray tmp=zhelp.uncompress(&all.constData()[zhelp.mzi.data_offset], zhelp.mzi.compressed_size, zhelp.mzi.uncompressed_size);
|
|
all=tmp;
|
|
m_info.zip_crc32=zhelp.mzi.crc32;
|
|
|
|
if (all.size()<=0)
|
|
{
|
|
m_info.errStr="uncompression fail";
|
|
MyDebug.logMsg( type_log_error,
|
|
origin_msg_generic ,
|
|
"QUncompress fail!");
|
|
return false;
|
|
}
|
|
#if 0
|
|
//This is very memory demanding...
|
|
unsigned char exp_len[4];
|
|
qToBigEndian(m_info.uncompressed_size, exp_len);
|
|
QByteArray tmp((const char*)exp_len, 4);
|
|
tmp+=all.mid(zhelp.mzi.data_offset);
|
|
all=qUncompress(tmp);
|
|
if (all.size()!=(int)m_info.uncompressed_size)
|
|
{
|
|
m_info.errStr="uncompression fail";
|
|
MyDebug()<<"QUncompress fail!";
|
|
return false;
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
f.close();
|
|
|
|
QByteArray hash=QCryptographicHash::hash(all, QCryptographicHash::Md5);
|
|
m_info.file_md5=QString(hash.toHex()).toUpper();
|
|
|
|
BinaryVerifier v;
|
|
ok=v.verify(all); //filename);
|
|
m_info.binaryInfo=v.info();
|
|
|
|
if (!ok)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (m_info.binaryInfo.format()==BinaryInfo::Binary)
|
|
{
|
|
//Try bitstream
|
|
BitstreamVerifier bv;
|
|
//ok=bv.verify(filename);
|
|
ok=bv.verify(all);
|
|
if (ok)
|
|
{
|
|
m_info.binaryInfo.m_fmtName="Bitstream";
|
|
m_info.binaryInfo.m_arch=BinaryInfo::Xilinx;
|
|
m_info.binaryInfo.m_archName="Xilinx";
|
|
m_info.binaryInfo.m_name=bv.info().name;
|
|
m_info.binaryInfo.m_host=bv.info().user;
|
|
m_info.binaryInfo.m_ftm=BinaryInfo::Bitstream;
|
|
m_info.binaryInfo.m_generator=bv.info().generator;
|
|
m_info.binaryInfo.m_pn=bv.info().partNumber;
|
|
m_info.binaryInfo.m_date=bv.info().date;
|
|
m_info.binaryInfo.m_partType=bv.info().repType;
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
else
|
|
return true;
|
|
}
|