forked from organicmaps/organicmaps
Added ZipReader::UnzipFile() to unpack archived files from android apk
This commit is contained in:
parent
b631f5de7c
commit
31061cd31a
3 changed files with 102 additions and 0 deletions
|
@ -127,3 +127,57 @@ UNIT_TEST(ZipFilesList)
|
|||
FileWriter::DeleteFileX(ZIPFILE_INVALID);
|
||||
FileWriter::DeleteFileX(ZIPFILE);
|
||||
}
|
||||
|
||||
/// Compressed zip file with 2 files in assets folder:
|
||||
/// assets/aaaaaaaaaa.txt (contains text "aaaaaaaaaa\x0A")
|
||||
/// assets/holalala.txt (contains text "Holalala\x0A")
|
||||
static char const zipBytes3[] = \
|
||||
"\x50\x4B\x03\x04\x14\x00\x02\x00\x08\x00\xAF\x96\x56\x40\x42\xE5\x26\x8F\x06\x00" \
|
||||
"\x00\x00\x0B\x00\x00\x00\x15\x00\x1C\x00\x61\x73\x73\x65\x74\x73\x2F\x61\x61\x61" \
|
||||
"\x61\x61\x61\x61\x61\x61\x61\x2E\x74\x78\x74\x55\x54\x09\x00\x03\x7A\x0F\x45\x4F" \
|
||||
"\xD8\x0F\x45\x4F\x75\x78\x0B\x00\x01\x04\xF5\x01\x00\x00\x04\x14\x00\x00\x00\x4B" \
|
||||
"\x4C\x84\x01\x2E\x00\x50\x4B\x03\x04\x14\x00\x02\x00\x08\x00\xE6\x96\x56\x40\x5E" \
|
||||
"\x76\x90\x07\x08\x00\x00\x00\x09\x00\x00\x00\x13\x00\x1C\x00\x61\x73\x73\x65\x74" \
|
||||
"\x73\x2F\x68\x6F\x6C\x61\x6C\x61\x6C\x61\x2E\x74\x78\x74\x55\x54\x09\x00\x03\xDF" \
|
||||
"\x0F\x45\x4F\xDC\x0F\x45\x4F\x75\x78\x0B\x00\x01\x04\xF5\x01\x00\x00\x04\x14\x00" \
|
||||
"\x00\x00\xF3\xC8\xCF\x49\x04\x41\x2E\x00\x50\x4B\x01\x02\x1E\x03\x14\x00\x02\x00" \
|
||||
"\x08\x00\xAF\x96\x56\x40\x42\xE5\x26\x8F\x06\x00\x00\x00\x0B\x00\x00\x00\x15\x00" \
|
||||
"\x18\x00\x00\x00\x00\x00\x01\x00\x00\x00\xA4\x81\x00\x00\x00\x00\x61\x73\x73\x65" \
|
||||
"\x74\x73\x2F\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x2E\x74\x78\x74\x55\x54\x05" \
|
||||
"\x00\x03\x7A\x0F\x45\x4F\x75\x78\x0B\x00\x01\x04\xF5\x01\x00\x00\x04\x14\x00\x00" \
|
||||
"\x00\x50\x4B\x01\x02\x1E\x03\x14\x00\x02\x00\x08\x00\xE6\x96\x56\x40\x5E\x76\x90" \
|
||||
"\x07\x08\x00\x00\x00\x09\x00\x00\x00\x13\x00\x18\x00\x00\x00\x00\x00\x01\x00\x00" \
|
||||
"\x00\xA4\x81\x55\x00\x00\x00\x61\x73\x73\x65\x74\x73\x2F\x68\x6F\x6C\x61\x6C\x61" \
|
||||
"\x6C\x61\x2E\x74\x78\x74\x55\x54\x05\x00\x03\xDF\x0F\x45\x4F\x75\x78\x0B\x00\x01" \
|
||||
"\x04\xF5\x01\x00\x00\x04\x14\x00\x00\x00\x50\x4B\x05\x06\x00\x00\x00\x00\x02\x00" \
|
||||
"\x02\x00\xB4\x00\x00\x00\xAA\x00\x00\x00\x00\x00";
|
||||
|
||||
UNIT_TEST(ZipExtract)
|
||||
{
|
||||
string const ZIPFILE = "test.zip";
|
||||
{
|
||||
FileWriter f(ZIPFILE);
|
||||
f.Write(zipBytes3, ARRAY_SIZE(zipBytes3));
|
||||
}
|
||||
TEST(ZipFileReader::IsZip(ZIPFILE), ("Not a zip file"));
|
||||
|
||||
vector<string> files = ZipFileReader::FilesList(ZIPFILE);
|
||||
TEST_EQUAL(files.size(), 2, ());
|
||||
|
||||
string const OUTFILE = "out.tmp";
|
||||
string s;
|
||||
ZipFileReader::UnzipFile(ZIPFILE, files[0], OUTFILE);
|
||||
{
|
||||
FileReader(OUTFILE).ReadAsString(s);
|
||||
}
|
||||
TEST_EQUAL(s, "aaaaaaaaaa\x0A", ());
|
||||
// OUTFILE should be rewritten correctly in the next lines
|
||||
ZipFileReader::UnzipFile(ZIPFILE, files[1], OUTFILE);
|
||||
{
|
||||
FileReader(OUTFILE).ReadAsString(s);
|
||||
}
|
||||
TEST_EQUAL(s, "Holalala\x0A", ());
|
||||
FileWriter::DeleteFileX(OUTFILE);
|
||||
|
||||
FileWriter::DeleteFileX(ZIPFILE);
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
#include "../base/scope_guard.hpp"
|
||||
#include "../base/logging.hpp"
|
||||
|
||||
#include "../coding/file_writer.hpp"
|
||||
|
||||
#include "../std/bind.hpp"
|
||||
|
||||
#include "../3party/zlib/contrib/minizip/unzip.h"
|
||||
|
@ -73,3 +75,45 @@ bool ZipFileReader::IsZip(string const & zipContainer)
|
|||
unzClose(zip);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ZipFileReader::UnzipFile(string const & zipContainer, string const & fileInZip,
|
||||
string const & outFilePath)
|
||||
{
|
||||
unzFile zip = unzOpen64(zipContainer.c_str());
|
||||
if (!zip)
|
||||
MYTHROW(OpenZipException, ("Can't get zip file handle", zipContainer));
|
||||
MY_SCOPE_GUARD(zipGuard, bind(&unzClose, zip));
|
||||
|
||||
if (UNZ_OK != unzLocateFile(zip, fileInZip.c_str(), 1))
|
||||
MYTHROW(LocateZipException, ("Can't locate file inside zip", fileInZip));
|
||||
|
||||
if (UNZ_OK != unzOpenCurrentFile(zip))
|
||||
MYTHROW(LocateZipException, ("Can't open file inside zip", fileInZip));
|
||||
MY_SCOPE_GUARD(currentFileGuard, bind(&unzCloseCurrentFile, zip));
|
||||
|
||||
try
|
||||
{
|
||||
FileWriter outFile(outFilePath);
|
||||
|
||||
int readBytes;
|
||||
static size_t const BUF_SIZE = 4096;
|
||||
char buf[BUF_SIZE];
|
||||
while (true)
|
||||
{
|
||||
readBytes = unzReadCurrentFile(zip, buf, BUF_SIZE);
|
||||
if (readBytes > 0)
|
||||
outFile.Write(buf, static_cast<size_t>(readBytes));
|
||||
else if (readBytes < 0)
|
||||
MYTHROW(InvalidZipException, ("Error", readBytes, "while unzipping", fileInZip, "from", zipContainer));
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (Exception const & e)
|
||||
{
|
||||
// Delete unfinished output file
|
||||
FileWriter::DeleteFileX(outFilePath);
|
||||
// Rethrow exception - we've failed
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,10 @@ public:
|
|||
|
||||
ZipFileReader(string const & container, string const & file);
|
||||
|
||||
// Can also throw Writer::OpenException and Writer::WriteException
|
||||
static void UnzipFile(string const & zipContainer, string const & fileInZip,
|
||||
string const & outFilePath);
|
||||
|
||||
static vector<string> FilesList(string const & zipContainer);
|
||||
/// Quick version without exceptions
|
||||
static bool IsZip(string const & zipContainer);
|
||||
|
|
Loading…
Add table
Reference in a new issue