Added ZipReader::UnzipFile() to unpack archived files from android apk

This commit is contained in:
Alex Zolotarev 2012-02-22 20:19:10 +03:00 committed by Alex Zolotarev
parent b631f5de7c
commit 31061cd31a
3 changed files with 102 additions and 0 deletions

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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);