diff options
author | ChrisEt <ChrisEt@users.noreply.github.com> | 2019-12-02 18:15:09 +0100 |
---|---|---|
committer | ChrisEt <ChrisEt@users.noreply.github.com> | 2020-03-27 17:07:51 +0100 |
commit | 1d37ef5fe647a5b2c285ef3d8cb7d003579775fe (patch) | |
tree | 38676ccd59fa9b3d96d7131aff8c7f8759736f95 | |
parent | 365650875096120a52fa16073f8cea44e16e1f84 (diff) |
added support for ZIP extended local headers
-rw-r--r-- | cmake/installdata/test-reference-data.txt | 1 | ||||
-rw-r--r-- | xbmc/filesystem/ZipFile.cpp | 41 | ||||
-rw-r--r-- | xbmc/filesystem/ZipManager.h | 1 | ||||
-rw-r--r-- | xbmc/filesystem/test/TestZipFile.cpp | 24 | ||||
-rw-r--r-- | xbmc/filesystem/test/extendedlocalheader.zip | bin | 0 -> 15352 bytes |
5 files changed, 62 insertions, 5 deletions
diff --git a/cmake/installdata/test-reference-data.txt b/cmake/installdata/test-reference-data.txt index b6c94a7f7d..8bc1c03adc 100644 --- a/cmake/installdata/test-reference-data.txt +++ b/cmake/installdata/test-reference-data.txt @@ -1,5 +1,6 @@ xbmc/utils/test/CXBMCTinyXML-test.xml xbmc/utils/test/data/language/Spanish/strings.po +xbmc/filesystem/test/extendedlocalheader.zip xbmc/filesystem/test/reffile.txt xbmc/filesystem/test/reffile.txt.rar xbmc/filesystem/test/reffile.txt.zip diff --git a/xbmc/filesystem/ZipFile.cpp b/xbmc/filesystem/ZipFile.cpp index 071f926914..46e06c785f 100644 --- a/xbmc/filesystem/ZipFile.cpp +++ b/xbmc/filesystem/ZipFile.cpp @@ -398,12 +398,47 @@ int CZipFile::UnpackFromMemory(std::string& strDest, const std::string& strInput if (!isGZ) { CZipManager::readHeader(strInput.data()+iPos,mZipItem); - if( mZipItem.header != ZIP_LOCAL_HEADER ) + if (mZipItem.header == ZIP_DATA_RECORD_HEADER) + { + // this header concerns a file we already processed, so we can just skip it + iPos += DREC_SIZE; + continue; + } + if (mZipItem.header != ZIP_LOCAL_HEADER) return iResult; if( (mZipItem.flags & 8) == 8 ) { - CLog::Log(LOGERROR,"FileZip: extended local header, not supported!"); - return iResult; + // if an extended local header (=data record header) is present, + // the following fields are 0 in the local header and we need to read + // them from the extended local header + + // search for the extended local header + unsigned int i = iPos + LHDR_SIZE + mZipItem.flength + mZipItem.elength; + while (1) + { + if (i + DREC_SIZE > strInput.size()) + { + CLog::Log(LOGERROR, "FileZip: extended local header expected, but not present!"); + return iResult; + } + if ((strInput[i] == 0x50) && (strInput[i + 1] == 0x4b) && + (strInput[i + 2] == 0x07) && (strInput[i + 3] == 0x08)) + break; // header found + i++; + } + // ZIP is little endian: + mZipItem.crc32 = static_cast<uint8_t>(strInput[i + 4]) | + static_cast<uint8_t>(strInput[i + 5]) << 8 | + static_cast<uint8_t>(strInput[i + 6]) << 16 | + static_cast<uint8_t>(strInput[i + 7]) << 24; + mZipItem.csize = static_cast<uint8_t>(strInput[i + 8]) | + static_cast<uint8_t>(strInput[i + 9]) << 8 | + static_cast<uint8_t>(strInput[i + 10]) << 16 | + static_cast<uint8_t>(strInput[i + 11]) << 24; + mZipItem.usize = static_cast<uint8_t>(strInput[i + 12]) | + static_cast<uint8_t>(strInput[i + 13]) << 8 | + static_cast<uint8_t>(strInput[i + 14]) << 16 | + static_cast<uint8_t>(strInput[i + 15]) << 24; } } if (!InitDecompress()) diff --git a/xbmc/filesystem/ZipManager.h b/xbmc/filesystem/ZipManager.h index f24d45944c..45754152eb 100644 --- a/xbmc/filesystem/ZipManager.h +++ b/xbmc/filesystem/ZipManager.h @@ -15,6 +15,7 @@ #define ZIP_END_CENTRAL_HEADER 0x06054b50 #define ZIP_SPLIT_ARCHIVE_HEADER 0x30304b50 #define LHDR_SIZE 30 +#define DREC_SIZE 16 #define CHDR_SIZE 46 #define ECDREC_SIZE 22 diff --git a/xbmc/filesystem/test/TestZipFile.cpp b/xbmc/filesystem/test/TestZipFile.cpp index 5029cf73d0..4ac3690bff 100644 --- a/xbmc/filesystem/test/TestZipFile.cpp +++ b/xbmc/filesystem/test/TestZipFile.cpp @@ -9,12 +9,13 @@ #include "ServiceBroker.h" #include "filesystem/Directory.h" #include "filesystem/File.h" -#include "utils/StringUtils.h" -#include "utils/URIUtils.h" +#include "filesystem/ZipFile.h" #include "FileItem.h" #include "settings/Settings.h" #include "settings/SettingsComponent.h" #include "test/TestUtils.h" +#include "utils/StringUtils.h" +#include "utils/URIUtils.h" #include "URL.h" #include <errno.h> @@ -207,3 +208,22 @@ TEST_F(TestZipFile, CorruptedFile) file->Close(); XBMC_DELETETEMPFILE(file); } + +TEST_F(TestZipFile, ExtendedLocalHeader) +{ + XFILE::CFile file; + ssize_t readlen; + char zipdata[20000]; // size of zip file is 15352 Bytes + + ASSERT_TRUE(file.Open(XBMC_REF_FILE_PATH("xbmc/filesystem/test/extendedlocalheader.zip"))); + readlen = file.Read(zipdata, sizeof(zipdata)); + EXPECT_TRUE(readlen); + + XFILE::CZipFile zipfile; + std::string strBuffer; + + int iSize = zipfile.UnpackFromMemory(strBuffer, std::string(zipdata, readlen), false); + EXPECT_EQ(152774, iSize); // sum of uncompressed size of all files in zip + EXPECT_TRUE(strBuffer.substr(0, 6) == "<Data>"); + file.Close(); +} diff --git a/xbmc/filesystem/test/extendedlocalheader.zip b/xbmc/filesystem/test/extendedlocalheader.zip Binary files differnew file mode 100644 index 0000000000..b30d92e128 --- /dev/null +++ b/xbmc/filesystem/test/extendedlocalheader.zip |