#include "downloadablefile.h" #include "binaryverifier.h" #include "bitstreamverifier.h" #include #include #include #include "miniz.h" #include #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; ifilename=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 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; }