SXXXXXXX_PyDownloadFwViaSRIO/_OLD/Vecchia_app/FpgaBeamMeUp/downloadablefile.cpp
2026-01-22 17:10:05 +01:00

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