Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

[Lib][Version 2.2.0][Functional] C++ wrapper around minizip compression library

License

NotificationsYou must be signed in to change notification settings

Lecrapouille/zipper

Repository files navigation

CI testing

Zipper

Zipper is a C++11 wrapper around minizip compression library. Its goal is to bring the power and simplicity of minizip to a more object-oriented/c++ user-friendly library. Note: We are currently using C++14 because the unit tests library needs it.

This project is the continuation of the originalproject. The original project was born out of the necessity of a compression library that would be reliable, simple, and flexible. By flexibility I mean supporting all kinds of inputs and outputs, but specifically being able to compress into memory instead of being restricted to file compression only, and using data from memory instead of just files as well.

This current fork repo has been made because the original project was no longer maintained by the original authors and I, Lecrapouille, have some issues due to missing administration rights (needed for CI, branch management ...).

Zipper Features

  • Create zip in memory.
  • Allow files, vectors, and generic streams as input to zip.
  • File mappings for replacing strategies (overwrite if exists or use alternative names from mapping).
  • Password-protected zip (EAS).
  • Multi-platform.
  • Project compiled as static and dynamic libraries.
  • Protection against theZip Slip attack.
  • Non-regression tests.

⚠️ Security Notice

Getting Started

Compiling / Installing

To download the project and compile it:

git clone https://github.com/lecrapouille/zipper.git --recursivecd zipper# Optionally: make download-external-libsmake compile-external-libsmake -j`nproc --all`# make -j`sysctl -n hw.logicalcpu` for MacOS X

Notes:

  • Git cloning needs the recursivity option to install the Makefile helper and third-part libs (zlib andminizip). They are based on fixed SHA1.
  • Optionalymake download-external-libs will git clone HEADs of zlib and minizip to theexternal folder. This replaces git submodules.
  • make compile-external-libs will compile zlib and minizip but not install them on your operating system. They arecompiled as static libraries and merged into this library.

Installing C++ header files and compiled libraries, type:

sudo make install

For Linux, you will see a message like:

*** Installing: doc => /usr/share/Zipper/2.0.0/doc*** Installing: libs => /usr/lib*** Installing: pkg-config => /usr/lib/pkgconfig*** Installing: headers => /usr/include/Zipper-2.0.0*** Installing: Zipper => /usr/include/Zipper-2.0.0

Optionally, you can compile demos present in the folder doc/demos:

make demos -j8

See their README files for their usage.

Linking Zipper to your project

  • In your project add the needed headers in your c++ files:
#include<Zipper/Unzipper.hpp>#include<Zipper/Zipper.hpp>
  • To compile your project against Zipper use pkg-config:
g++ -W -Wall --std=c++11 main.cpp -o prog`pkg-config zipper --cflags --libs`
  • For Makefile:

    • setLDFLAGS topkg-config zipper --libs
    • setCPPFLAGS topkg-config zipper --cflags
  • For CMake:

include(FindPkgConfig)find_package(zipper)

API

There are two classes availableZipper andUnzipper. They behave in the same manner regarding constructors and storage parameters.

Zipping API

Header

#include<Zipper/Zipper.hpp>usingnamespacezipper;

Constructor

  • Constructor without password and replaceziptest.zip if already present. The new zip archive is dummy.
Zipperzipper("ziptest.zip", Zipper::openFlags::Overwrite);// Or simply: zipper("ziptest.zip");
  • Constructor without password and preserveziptest.zip if already present.
Zipperzipper("ziptest.zip", Zipper::openFlags::Append);
  • Constructor with password (using AES algorithm) and replaceziptest.zip if already present. The new zip archive is dummy.
Zipperzipper("ziptest.zip","mypassword", Zipper::openFlags::Overwrite);// Or simply: zipper("ziptest.zip");
  • Constructor with a password and preserveziptest.zip if already present.
Zipperzipper("ziptest.zip","mypassword", Zipper::openFlags::Append);
  • Note: all constructors will throwstd::run_time exception in case of failure.
try{    Zipperzipper("ziptest.zip", ...);    ...}catch (std::run_timeconst& e){    std::cerr << e.what() << std::endl;}

Destructor / closing / reopening

Do not forget to call explicitlyclose() (called implicitly from its destructor) elsethe zip will not be well formed andUnzipper will fail to open it for example.

Zipperzipper("ziptest.zip", ...);...zipper.close();// Now Unzipper unzipper("ziptest.zip") can work

Afterclose() you can reopen the zip archive withopen(). The implicit optionZipper::openFlags::Append is to preserve the zip content. To replace the zipfile is to useZipper::openFlags::Overwrite.

Zipperzipper("ziptest.zip", ...);...zipper.close();...zipper.open();// equivalent to zipper.open(Zipper::openFlags::Append);// or zipper.open(Zipper::openFlags::Overwrite);...zipper.close();

In case of success theopen() will returntrue else will returnfalse and theerror() should be used for getting thestd::error_code.

if (!zipper.open()){    std::cerr << zipper.error().message() << std::endl;}

Appending files or folders inside the archive.

Theadd() method allows appending files or folders. TheZipper::zipFlags::Better is set implicitly. Other options are (in the last option in the arguments):

  • Store only:Zipper::zipFlags::Store.
  • Compress faster, less compressed:Zipper::zipFlags::Faster.
  • Compress intermediate time/compression:Zipper::zipFlags::Medium.
  • Compress faster better:Zipper::zipFlags::Better.

In case of success theopen() will returntrue else will returnfalse and theerror() should be used for getting the std::error_code.

  • Adding an entire folder to a zip:
Zipperzipper("ziptest.zip");zipper.add("myFolder/");zipper.close();
  • Adding a file by name:
Zipperzipper("ziptest.zip");zipper.add("somefile.txt");zipper.close();
  • You can change their name in the archive:
Zipperzipper("ziptest.zip");zipper.add("somefile.txt","new_name_in_archive");zipper.close();
  • Create a zip file with 2 files referred by theirstd::ifstream and change their name in the archive:
std::ifstreaminput1("first_file");std::ifstreaminput2("second_file");Zipperzipper("ziptest.zip");zipper.add(input1,"Test1");zipper.add(input2,"Test2");zipper.close();
zipper.add(input1,"../Test1");

Will always returnfalse becauseTest1 will be extracted outside the destination folder. This prevents malicious attack from replacing your password files:

zipper.add(malicious_passwd,"../../../../../../../../../../../../../../../etc/passwd");

Becase in Unix try to go outside the root folder/ will stay in the root folder. Example

cd /pwdcd ../../../../../../../../../../../../../../..pwd
  • The Zipper lib force canonical paths in the archive. The following code works (will returntrue):
zipper.add(input1,"foo/../Test1");

becausefoo/../Test1 is replaced byTest1 (even if the folderfoo is not present in thezip archive.

Vector and stream

  • Creating a zip file using the awesome streams from theboost library that lets us use a vector as a stream:
#include<boost/interprocess/streams/vectorstream.hpp>...boost::interprocess::basic_vectorstream<std::vector<char>>input_data(some_vector);Zipperzipper("ziptest.zip");zipper.add(input_data,"Test1");zipper.close();
  • Creating a zip in a vector with files:
#include<boost/interprocess/streams/vectorstream.hpp>...boost::interprocess::basic_vectorstream<std::vector<char>> zip_in_memory;std::ifstreaminput1("some file");Zipperzipper(zip_in_memory);// You can pass passwordzipper.add(input1,"Test1");zipper.close();zipper::Unzipperunzipper(zip_in_memory);unzipper.extractEntry(...

Or:

#include<vector>std::vector<unsignedchar> zip_vect;std::ifstreaminput1("some file");Zipperzipper(zip_vect);// You can pass passwordzipper.add(input1,"Test1");zipper.close();
  • Creating a zip in-memory stream with files:
std::stringstream ss;std::ifstreaminput1("some file");Zipperzipper(ss);// You can pass passwordzipper.add(input1,"Test1");zipper.close();zipper::Unzipperunzipper(ss);unzipper.extractEntry(...

Unzipping API

Header

#include<Zipper/Unzipper.hpp>usingnamespacezipper;

Constructor

  • Constructor without password and openingziptest.zip (shall be already present).
Zipperunzipper("ziptest.zip");...zipper.close();
  • Constructor with a password and openingziptest.zip (shall be already present).
Zipperunzipper("ziptest.zip","mypassword");...zipper.close();
  • Note: all constructors will throwstd::run_time exception in case of failure.
try{    Zipperzipper("ziptest.zip", ...);    ...}catch (std::run_timeconst& e){    std::cerr << e.what() << std::endl;}

Getting the list of zip entries

Unzipperunzipper("zipfile.zip");std::vector<ZipEntry> entries = unzipper.entries();for (auto& it: unzipper.entries()){    std::cout << it.name <<":"              << it.timestamp              << std::endl;}unzipper.close();

Extracting all entries from the zip file

Two methodsextract() for the whole archive andextractEntry() fora single element in the archive. They returntrue in case of successorfalse in case of failure. In case of failure, useunzipper.error();to get thestd::error_code.

  • If you do not care about replacing existing files or folders:
Unzipperunzipper("zipfile.zip");unzipper.extractAll(true);unzipper.close();
  • If you care about replacing existing files or folders. The method will fail (returnfalse)if a file is replaced.
Unzipperunzipper("zipfile.zip");unzipper.extractAll();// equivalent to unzipper.extractAll(false);unzipper.close();
  • Extracting all entries from the zip file to the desired destination:
Unzipperunzipper("zipfile.zip");unzipper.extractAll("/the/destination/path");// Fail if a file exists (false argument is implicit)unzipper.extractAll("/the/destination/path",true);// Replace existing filesunzipper.close();
  • Extracting all entries from the zip file using alternative names for existing files on disk:
std::map<std::string, std::string> alternativeNames = { {"Test1","alternative_name_test1"} };Unzipperunzipper("zipfile.zip");unzipper.extractAll(".", alternativeNames);unzipper.close();
  • Extracting a single entry from the zip file:
Unzipperunzipper("zipfile.zip");unzipper.extractEntry("entry name");unzipper.close();

Returntrue in case of success orfalse in case of failure.In case of failure, useunzipper.error(); to get thestd::error_code.

  • Extracting a single entry from the zip file to destination:
Unzipperunzipper("zipfile.zip");unzipper.extractEntry("entry name","/the/destination/path");// Fail if a file exists (false argument is implicit)unzipper.extractEntry("entry name","/the/destination/path",true);// Replace existing fileunzipper.close();

Returntrue in case of success orfalse in case of failure.In case of failure, useunzipper.error(); to get thestd::error_code.

  • Extracting a single entry from the zip file to memory:
std::vector<unsignedchar> unzipped_entry;Unzipperunzipper("zipfile.zip");unzipper.extractEntryToMemory("entry name", unzipped_entry);unzipper.close();

Returntrue in case of success orfalse in case of failure.In case of failure, useunzipper.error(); to get thestd::error_code.

  • Extracting from a vector:
std::vector<unsignedchar> zip_vect;// Populated with Zipper zipper(zip_vect);Unzipperunzipper(zip_vect);unzipper.extractEntry("Test1");
  • Zipper has security againstZip Slip vulnerability: if an entry has a path outside the extraction folder (like../foo.txt) itwill returnsfalse even if the replace option is set.

Hello zip

Basic unzipper standalone application given as demo indoc/demos.

For developers

Non regression tests

Depends on:

Two ways of running them:

  • From the root folder:
make tests -j`nproc --all`
  • From the tests/ folder:
cd testsmake coverage -j`nproc --all`

A coverage report has created an opening. If you do not desire to generate the report.

cd testsmake -j`nproc --all`./build/Zipper-UnitTest

FAQ

  • Q: I used a password when zipping with the Zipper lib, but now when I want to extract data with my operating system zip tool, I got an error.A: By default, Zipper encrypts with the EAS algorithm which is not the default encryption algorithm for zip files. Your operating system zip tools seemnot to understand EAS. You can extract it with the 7-Zip tool:7za e your.zip. If you want the default zip encryption (at your own risk since thepassword can be cracked) you can remove EAS option in the following files:Make andexternal/compile-external-libs.shand recompile the Zipper project.

About

[Lib][Version 2.2.0][Functional] C++ wrapper around minizip compression library

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

[8]ページ先頭

©2009-2025 Movatter.jp