Skip to content

Commit

Permalink
3.2.1
Browse files Browse the repository at this point in the history
Changed default zip algorithm to miniz-cpp (more reliable and faster for many small files).
Improved error catching and handling in ZipComponentUWP and ZipProxy.js.
Added version number to ZipComponentUWP and pre-build script that updates it.
  • Loading branch information
ChrisBase committed Jul 14, 2021
1 parent 1ca8410 commit 4fe7ae4
Show file tree
Hide file tree
Showing 28 changed files with 337 additions and 89 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ node_modules/

*.vcxproj.user
.vs/
src/windows/ZipComponentUWP/*.aps
src/windows/ZipComponentUWP/Bin/*_Debug
src/windows/ZipComponentUWP/Bin/*/*.exe
src/windows/ZipComponentUWP/Bin/*/*.exp
Expand Down
2 changes: 1 addition & 1 deletion plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<plugin xmlns="http://phonegap.com/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="cordova-plugin-zip"
version="3.2.0">
version="3.2.1">
<engines>
<engine name="cordova" version=">=3.3.0"/>
</engines>
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
15 changes: 15 additions & 0 deletions src/windows/ZipComponentUWP/Source/Resource.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by C:\CG\Projects\sitewaerts\cordova-plugin-zip\src\windows\ZipComponentUWP\ZipComponentUWP.rc
//

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
19 changes: 16 additions & 3 deletions src/windows/ZipComponentUWP/Source/ZipAlgorithm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,11 @@ const char* ZipAlgorithm::NameMinizCpp = "miniz-cpp";

ZipAlgorithm* ZipAlgorithm::Create(const char* pchAlgorithmName)
{
if( pchAlgorithmName == nullptr )
if( pchAlgorithmName == nullptr || ::strlen(pchAlgorithmName) == 0 )
{
throw std::runtime_error("ZipAlgorithm::Create(): invalid algorithm name");
return nullptr;
}

if( ::strcmp(pchAlgorithmName, NameAndyZip) == 0 )
return new ZipAlgorithm_andyzip();
Expand All @@ -34,14 +37,24 @@ void ZipAlgorithm::Destroy(ZipAlgorithm*& pAlgorithm)

void ZipAlgorithm::SetOutputDirWithTrailingSlash(const char* pchOutputDir)
{
// Only for empty paths we don't append trailing slashes
if( pchOutputDir == nullptr || pchOutputDir[0] == '\0' )
m_strOutputDir = "";

m_strOutputDir = pchOutputDir;
if( m_strOutputDir[m_strOutputDir.length() - 1] != '/' && m_strOutputDir[m_strOutputDir.length() - 1] != '\\' )

const char chLastChar = m_strOutputDir[m_strOutputDir.length() - 1];
if( chLastChar != '/' && chLastChar != '\\' )
m_strOutputDir += '/';
}

bool ZipAlgorithm::CreateEntryDir(const std::string& strEntryDir) const
{
const char& chLastChar = strEntryDir[strEntryDir.length() - 1];
const size_t szEntryDirLength = strEntryDir.length();
if( szEntryDirLength < 1 )
throw std::runtime_error("ZipAlgorithm::CreateEntryDir(): invalid/empty entry dir");

const char& chLastChar = strEntryDir[szEntryDirLength - 1];
if( chLastChar != '/' && chLastChar != '\\' )
return false;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ __pragma(pack(pop))

// This is a replacement for the zipfile_reader class.
// It fixes an issue in zipfile_reader with local file headers not containing
// the uncompressed size and reduces allocations by reserving memory upfront.
// the uncompressed size and reduces allocations by reserving memory upfront.
// Assumes little endianness and supports only deflate for decompression!
class ZipAlgorithm_andyzip::Reader
{
Expand Down
20 changes: 20 additions & 0 deletions src/windows/ZipComponentUWP/Source/ZipComponent.Version.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// DO NOT EDIT THIS FILE MANUALLY
//
// This file is automatically generated in the pre-build step by the UpdateVersion.bat script
// Change the version number in the ZipComponentUWP.rc file
//
// DO NOT EDIT THIS FILE MANUALLY
//
#include "pch.h"
#include <cvt/wstring>
#include <codecvt>
#include "ZipAlgorithm.h"
#include "ZipComponent.h"

using namespace ZipComponentUWP;

String^ ZipComponent::GetVersion()
{
return "1.0.1.0";
}
94 changes: 74 additions & 20 deletions src/windows/ZipComponentUWP/Source/ZipComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,33 +25,48 @@ static inline std::string PlatformStringToStdString(String^ platformString)
ZipComponent::ZipComponent(String^ strAlgorithmName, String^ strZipFile, String^ strOutputDir)
: m_pAlgorithm(nullptr)
{
const std::string stringAlgorithmNameUtf8 = PlatformStringToStdString(strAlgorithmName);
m_pAlgorithm = ZipAlgorithm::Create(stringAlgorithmNameUtf8.c_str());
if( m_pAlgorithm == nullptr )
try
{
m_strLastError = "Failed to create algorithm: " + StdStringToPlatformString(stringAlgorithmNameUtf8);
return;
const std::string stringAlgorithmNameUtf8 = PlatformStringToStdString(strAlgorithmName);
m_pAlgorithm = ZipAlgorithm::Create(stringAlgorithmNameUtf8.c_str());
if( m_pAlgorithm == nullptr )
{
m_strLastError = "Failed to create algorithm: " + StdStringToPlatformString(stringAlgorithmNameUtf8);
return;
}

m_strZipFileUtf8 = PlatformStringToStdString(strZipFile);
m_strOutputDirUtf8 = PlatformStringToStdString(strOutputDir);

if( !m_pAlgorithm->Open(m_strZipFileUtf8.c_str(), m_strOutputDirUtf8.c_str()) )
{
m_strLastError = "Failed to open zip file " + StdStringToPlatformString(m_strZipFileUtf8)
+ " (output dir = " + StdStringToPlatformString(m_strOutputDirUtf8) + ")";

m_pAlgorithm->Close();
ZipAlgorithm::Destroy(m_pAlgorithm);
}
}

m_strZipFileUtf8 = PlatformStringToStdString(strZipFile);
m_strOutputDirUtf8 = PlatformStringToStdString(strOutputDir);

if( !m_pAlgorithm->Open(m_strZipFileUtf8.c_str(), m_strOutputDirUtf8.c_str()) )
catch( std::exception exception )
{
m_strLastError = "Failed to open zip file " + StdStringToPlatformString(m_strZipFileUtf8)
+ " (output dir = " + StdStringToPlatformString(m_strOutputDirUtf8) + ")";

m_pAlgorithm->Close();
ZipAlgorithm::Destroy(m_pAlgorithm);
if( exception.what() )
m_strLastError += StdStringToPlatformString(std::string("\n\n") + exception.what());
}
}

ZipComponent::~ZipComponent()
{
if( m_pAlgorithm )
{
m_pAlgorithm->Close();
ZipAlgorithm::Destroy(m_pAlgorithm);
try
{
m_pAlgorithm->Close();
ZipAlgorithm::Destroy(m_pAlgorithm);
}
catch( std::exception exception )
{
// Can't do much here, since we're destructing the object
}
}
}

Expand All @@ -63,7 +78,17 @@ size_t ZipComponent::GetEntryCount()
return 0u;
}

return m_pAlgorithm->GetEntryCount();
try
{
return m_pAlgorithm->GetEntryCount();
}
catch( std::exception exception )
{
if( exception.what() )
m_strLastError += StdStringToPlatformString(std::string("\n\n") + exception.what());
}

return 0u;
}

String^ ZipComponent::GetEntryName(const size_t szEntryIndex)
Expand All @@ -74,7 +99,17 @@ String^ ZipComponent::GetEntryName(const size_t szEntryIndex)
return "";
}

return StdStringToPlatformString(m_pAlgorithm->GetEntryName(szEntryIndex));
try
{
return StdStringToPlatformString(m_pAlgorithm->GetEntryName(szEntryIndex));
}
catch( std::exception exception )
{
if( exception.what() )
m_strLastError += StdStringToPlatformString(std::string("\n\n") + exception.what());
}

return "";
}

bool ZipComponent::UnzipEntry(const size_t szEntryIndex)
Expand All @@ -85,10 +120,29 @@ bool ZipComponent::UnzipEntry(const size_t szEntryIndex)
return false;
}

return m_pAlgorithm->UnzipEntry(szEntryIndex);
try
{
return m_pAlgorithm->UnzipEntry(szEntryIndex);
}
catch( std::exception exception )
{
if( exception.what() )
m_strLastError += StdStringToPlatformString(std::string("\n\n") + exception.what());
}

return false;
}

String^ ZipComponent::GetLastError()
{
return m_strLastError;
}

// This method is defined in ZipComponent.Version.cpp
// UWP components don't have access to the methods required to read entries out of the modules resource section.
// The pre-build executed UpdateVersion.bat script reads it and updates ZipComponent.Version.cpp accordingly.
//
// String^ ZipComponent::GetVersion()
// {
// return ...;
// }
1 change: 1 addition & 0 deletions src/windows/ZipComponentUWP/Source/ZipComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace ZipComponentUWP
bool UnzipEntry(size_t szEntryIndex);

String^ GetLastError();
String^ GetVersion();

private:
ZipAlgorithm* m_pAlgorithm;
Expand Down
101 changes: 55 additions & 46 deletions src/windows/ZipComponentUWP/Source/ZipTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,58 +6,67 @@

int main(int argc, const char* argv[])
{
// Print app usage if parameter count doesn't match
if( argc != 4 )
try
{
const std::string strPath(argv[0]);
const std::string strAppExecutable(strPath.substr(strPath.find_last_of("/\\") + 1));
std::cout << "Usage: " << strAppExecutable << " zipFile outputDir algorithm\n\nSupported algorithms:\n";
std::cout << " " << ZipAlgorithm::NameAndyZip << "\n";
std::cout << " " << ZipAlgorithm::NameMinizCpp << "\n";
return EXIT_FAILURE;
}

// Retrieve input parameters and unzip algorithm matching the provided algorithm name
const char* pchZipFile = argv[1];
const char* pchOutputDir = argv[2];
const char* pchAlgorithmName = argv[3];
auto* pAlgorithm = ZipAlgorithm::Create(pchAlgorithmName);

if( pAlgorithm == nullptr )
{
std::cout << "Unsupported algorithm: " << pchAlgorithmName << "\n";
return EXIT_FAILURE;
}
// Print app usage if parameter count doesn't match
if( argc != 4 )
{
const std::string strPath(argv[0]);
const std::string strAppExecutable(strPath.substr(strPath.find_last_of("/\\") + 1));
std::cout << "Usage: " << strAppExecutable << " zipFile outputDir algorithm\n\nSupported algorithms:\n";
std::cout << " " << ZipAlgorithm::NameAndyZip << "\n";
std::cout << " " << ZipAlgorithm::NameMinizCpp << "\n";
return EXIT_FAILURE;
}

if( !pAlgorithm->Open(pchZipFile, pchOutputDir) )
{
std::cout << "Failed to open zip file: " << pchZipFile << "\n";
ZipAlgorithm::Destroy(pAlgorithm);
return EXIT_FAILURE;
}
// Retrieve input parameters and unzip algorithm matching the provided algorithm name
const char* pchZipFile = argv[1];
const char* pchOutputDir = argv[2];
const char* pchAlgorithmName = argv[3];
auto* pAlgorithm = ZipAlgorithm::Create(pchAlgorithmName);

auto unzip = [](ZipAlgorithm* pAlgorithm, const char* pchZipFile, const char* pchOutputDir)
{
bool bErrorsOccured = false;
const size_t szEntries = pAlgorithm->GetEntryCount();
for( size_t i = 0; i < szEntries; ++i )
if( !pAlgorithm->UnzipEntry(i) )
bErrorsOccured = true;
if( pAlgorithm == nullptr )
{
std::cout << "Unsupported algorithm: " << pchAlgorithmName << "\n";
return EXIT_FAILURE;
}

return bErrorsOccured ? EXIT_FAILURE : EXIT_SUCCESS;
};
if( !pAlgorithm->Open(pchZipFile, pchOutputDir) )
{
std::cout << "Failed to open zip file: " << pchZipFile << "\n";
ZipAlgorithm::Destroy(pAlgorithm);
return EXIT_FAILURE;
}

// Execute the decompression and measure duration
const auto timeBegin = std::chrono::steady_clock::now();
const int iResult = unzip(pAlgorithm, pchZipFile, pchOutputDir);
const auto timeEnd = std::chrono::steady_clock::now();
auto unzip = [](ZipAlgorithm* pAlgorithm, const char* pchZipFile, const char* pchOutputDir)
{
bool bErrorsOccured = false;
const size_t szEntries = pAlgorithm->GetEntryCount();
for( size_t i = 0; i < szEntries; ++i )
if( !pAlgorithm->UnzipEntry(i) )
bErrorsOccured = true;

pAlgorithm->Close();
ZipAlgorithm::Destroy(pAlgorithm);
return bErrorsOccured ? EXIT_FAILURE : EXIT_SUCCESS;
};

std::cout << "Duration: " << std::chrono::duration_cast<std::chrono::milliseconds>(timeEnd - timeBegin).count() << " ms";
if( iResult != EXIT_SUCCESS )
std::cout << "Error: " << iResult << std::endl;
// Execute the decompression and measure duration
const auto timeBegin = std::chrono::steady_clock::now();
const int iResult = unzip(pAlgorithm, pchZipFile, pchOutputDir);
const auto timeEnd = std::chrono::steady_clock::now();

pAlgorithm->Close();
ZipAlgorithm::Destroy(pAlgorithm);

std::cout << "Duration: " << std::chrono::duration_cast<std::chrono::milliseconds>(timeEnd - timeBegin).count() << " ms";
if (iResult != EXIT_SUCCESS)
std::cout << "Error: " << iResult << std::endl;

return iResult;
}
catch(std::exception exception)
{
std::cout << "Exception: " << exception.what() << std::endl;
}

return iResult;
return EXIT_FAILURE;
}
Loading

0 comments on commit 4fe7ae4

Please sign in to comment.