summaryrefslogtreecommitdiff
path: root/lib/qt-tar-xz/QTarDecode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/qt-tar-xz/QTarDecode.cpp')
-rw-r--r--lib/qt-tar-xz/QTarDecode.cpp174
1 files changed, 174 insertions, 0 deletions
diff --git a/lib/qt-tar-xz/QTarDecode.cpp b/lib/qt-tar-xz/QTarDecode.cpp
new file mode 100644
index 0000000..10c38ca
--- /dev/null
+++ b/lib/qt-tar-xz/QTarDecode.cpp
@@ -0,0 +1,174 @@
+/** \file QTarDecode.cpp
+\brief To read a tar data block
+\author alpha_one_x86
+\licence GPL3, see the file COPYING */
+
+#include "QTarDecode.h"
+
+#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="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;
+}
+
+void QTarDecode::setErrorString(const std::string &error)
+{
+ this->error=error;
+ fileList.clear();
+ dataList.clear();
+}
+
+bool QTarDecode::stringStartWith(std::string const &fullString, std::string const &starting)
+{
+ if (fullString.length() >= starting.length()) {
+ return (fullString.substr(0,starting.length())==starting);
+ } else {
+ return false;
+ }
+}
+
+bool QTarDecode::decodeData(const std::vector<char> &data)
+{
+ 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;
+}
+
+std::vector<std::string> QTarDecode::getFileList()
+{
+ return fileList;
+}
+
+std::vector<std::vector<char> > QTarDecode::getDataList()
+{
+ return dataList;
+}
+
+