diff options
Diffstat (limited to 'lib/qt-tar-xz/QTarDecode.cpp')
-rw-r--r-- | lib/qt-tar-xz/QTarDecode.cpp | 233 |
1 files changed, 147 insertions, 86 deletions
diff --git a/lib/qt-tar-xz/QTarDecode.cpp b/lib/qt-tar-xz/QTarDecode.cpp index fe15359..e1d9bce 100644 --- a/lib/qt-tar-xz/QTarDecode.cpp +++ b/lib/qt-tar-xz/QTarDecode.cpp @@ -1,113 +1,174 @@ /** \file QTarDecode.cpp \brief To read a tar data block \author alpha_one_x86 -\version 0.3 -\date 2010 \licence GPL3, see the file COPYING */ #include "QTarDecode.h" -#include <QDebug> + +#include <inttypes.h> +#include <regex> +#include <cstring> +#include <iostream> + +static const std::regex isaunsignednumber("^[0-9]+$",std::regex::optimize); +static const std::regex isaunoctalnumber("^[0-7]+$",std::regex::optimize); +static const char* const lut = "0123456789ABCDEF"; QTarDecode::QTarDecode() { - error="Unknow error"; + error="Unknown error"; +} + +uint64_t QTarDecode::octaltouint64(const std::string &string,bool *ok) +{ + if(std::regex_match(string,isaunsignednumber)) + { + if(ok!=NULL) + *ok=true; + return std::stoi(string,0,8); + } + else + { + if(ok!=NULL) + *ok=false; + return 0; + } +} + +uint64_t QTarDecode::stringtouint64(const std::string &string,bool *ok) +{ + if(std::regex_match(string,isaunsignednumber)) + { + if(ok!=NULL) + *ok=true; + return std::stoull(string); + } + else + { + if(ok!=NULL) + *ok=false; + return 0; + } +} + +std::string QTarDecode::errorString() +{ + return error; } -QString QTarDecode::errorString() +void QTarDecode::setErrorString(const std::string &error) { - return error; + this->error=error; + fileList.clear(); + dataList.clear(); } -void QTarDecode::setErrorString(QString error) +bool QTarDecode::stringStartWith(std::string const &fullString, std::string const &starting) { - this->error=error; - fileList.clear(); - dataList.clear(); + if (fullString.length() >= starting.length()) { + return (fullString.substr(0,starting.length())==starting); + } else { + return false; + } } -bool QTarDecode::decodeData(QByteArray data) +bool QTarDecode::decodeData(const std::vector<char> &data) { - setErrorString("Unknow error"); - if(data.size()<1024) - return false; - int offset=0; - while(offset<data.size()) - { - //load the file name from ascii, from 0+offset with size of 100 - QString fileName=data.mid(0+offset,100); - //load the file type - QString fileType=data.mid(156+offset,1); - //load the ustar string - QString ustar=data.mid(257+offset,5); - //load the ustar version - QString ustarVersion=data.mid(263+offset,2); - bool ok; - //load the file size from ascii, from 124+offset with size of 12 - int finalSize=QString(data.mid(124+offset,12)).toUInt(&ok,8); - //if the size conversion to qulonglong have failed, then qui with error - if(ok==false) - { - //if((offset+1024)==data.size()) - //it's the end of the archive, no more verification - break; - /*else - { - setErrorString("Unable to convert ascii size at "+QString::number(124+offset)+" to usigned long long: \""+QString(data.mid(124+offset,12))+"\""); - return false; - }*/ - } - //if check if the ustar not found - if(ustar!="ustar") - { - setErrorString("\"ustar\" string not found at "+QString::number(257+offset)+", content: \""+ustar+"\""); - return false; - } - if(ustarVersion!="00") - { - setErrorString("ustar version string is wrong, content:\""+ustarVersion+"\""); - return false; - } - //check if the file have the good size for load the data - if((offset+512+finalSize)>data.size()) - { - setErrorString("The tar file seem be too short"); - return false; - } - if(fileType=="0") //this code manage only the file, then only the file is returned - { - QByteArray fileData=data.mid(512+offset,finalSize); - fileList << fileName; - dataList << fileData; - } - //calculate the offset for the next header - bool retenu=((finalSize%512)!=0); - //go to the next header - offset+=512+(finalSize/512+retenu)*512; - } - if(fileList.size()>0) - { - QString baseDirToTest=fileList.at(0); - baseDirToTest.remove(QRegExp("/.*$")); - baseDirToTest+='/'; - bool isFoundForAllEntries=true; - for (int i = 0; i < fileList.size(); ++i) - if(!fileList.at(i).startsWith(baseDirToTest)) - isFoundForAllEntries=false; - if(isFoundForAllEntries) - for (int i = 0; i < fileList.size(); ++i) - fileList[i].remove(0,baseDirToTest.size()); - } - return true; + setErrorString("Unknown error"); + if(data.size()<1024) + return false; + unsigned int offset=0; + while(offset<data.size()) + { + //load the file name from ascii, from 0+offset with size of 100 + std::string fileName(data.data()+offset,100); + while(!fileName.empty() && fileName.at(fileName.size()-1)==0x00) + fileName.resize(fileName.size()-1); + //load the file type + std::string fileType(data.data()+156+offset,1); + while(!fileName.empty() && fileType.at(fileType.size()-1)==0x00) + fileType.resize(fileType.size()-1); + //load the ustar string + std::string ustar(data.data()+257+offset,5); + while(!fileName.empty() && ustar.at(ustar.size()-1)==0x00) + ustar.resize(ustar.size()-1); + //load the ustar version + std::string ustarVersion(data.data()+263+offset,2); + while(!fileName.empty() && ustarVersion.at(ustarVersion.size()-1)==0x00) + ustarVersion.resize(ustarVersion.size()-1); + bool ok=false; + //load the file size from ascii, from 124+offset with size of 12 + uint64_t finalSize=0; + std::string sizeString(data.data()+124+offset,12); + if(sizeString.at(sizeString.size()-1)==0x00) + { + //the size is in octal base + sizeString.resize(sizeString.size()-1); + finalSize=octaltouint64(sizeString,&ok); + } + else + finalSize=stringtouint64(sizeString,&ok); + //if the size conversion to qulonglong have failed, then qui with error + if(ok==false) + { + //it's the end of the archive, no more verification + break; + } + //if check if the ustar not found + if(ustar!="ustar") + { + setErrorString("\"ustar\" string not found at "+std::to_string(257+offset)+", content: \""+ustar+"\""); + return false; + } + if(ustarVersion!="00") + { + setErrorString("ustar version string is wrong, content:\""+ustarVersion+"\""); + return false; + } + //check if the file have the good size for load the data + if((offset+512+finalSize)>data.size()) + { + setErrorString("The tar file seem be too short"); + return false; + } + if(fileType=="0") //this code manage only the file, then only the file is returned + { + std::vector<char> newdata; + newdata.resize(finalSize); + memcpy(newdata.data(),data.data()+512+offset,finalSize); + fileList.push_back(fileName); + dataList.push_back(newdata); + } + //calculate the offset for the next header + bool retenu=((finalSize%512)!=0); + //go to the next header + offset+=512+(finalSize/512+retenu)*512; + } + if(fileList.size()>0) + { + std::string baseDirToTest=fileList.at(0); + std::size_t found = baseDirToTest.find_last_of("/"); + if(found!=std::string::npos && found>=baseDirToTest.size()) + baseDirToTest.resize(baseDirToTest.size()-(baseDirToTest.size()-found)); + bool isFoundForAllEntries=true; + for (unsigned int i = 0; i < fileList.size(); ++i) + if(!stringStartWith(fileList.at(i),baseDirToTest)) + isFoundForAllEntries=false; + if(isFoundForAllEntries) + for (unsigned int i = 0; i < fileList.size(); ++i) + fileList[i].erase(0,baseDirToTest.size()); + } + return true; } -QStringList QTarDecode::getFileList() +std::vector<std::string> QTarDecode::getFileList() { - return fileList; + return fileList; } -QList<QByteArray> QTarDecode::getDataList() +std::vector<std::vector<char> > QTarDecode::getDataList() { - return dataList; + return dataList; } |