1[![Build Status](https://travis-ci.com/ctabin/libzippp.svg?branch=master)](https://travis-ci.com/ctabin/libzippp)
2
3# LIBZIPPP
4
5libzippp is a simple basic C++ wrapper around the libzip library.
6It is meant to be a portable and easy-to-use library for ZIP handling.
7
8Compilation has been tested with:
9- GCC 8 (Travis CI)
10- GCC 10.2.1 (GNU/Linux Debian)
11- MS Visual Studio 2012 (Windows 7)
12
13Underlying libraries:
14- [ZLib](http://zlib.net) 1.2.11
15- [libzip](http://www.nih.at/libzip) 1.8.0
16- [BZip2](https://www.sourceware.org/bzip2/) 1.0.8 (optional)
17
18## Integration
19
20libzippp has been ported  to [vcpkg](https://github.com/microsoft/vcpkg) and thus can be
21very easily integrated by running:
22```
23./vcpkg install libzippp
24```
25
26## Compilation
27
28### Install Prerequisites
29
30This library requires at least C++ 11 to be compiled.
31
32- Linux
33  - Install the development packages for zlib and libzip (e.g. `zlib1g-dev`, `libzip-dev`, `liblzma-dev`, `libbz2-dev`).
34  - It is possible to use the Makefile by executing `make libraries`.
35
36- Windows:
37  - Use precompiled libraries from *libzippp-\<version\>-windows-ready_to_compile.zip*.
38  - Install from source via CMake (similar to workflow below).
39
40- All Operating systems
41  - If it is intended to be used with encryption it is necessary to compile libzip with any encryption and to enable it in libzippp through the cmake flag `LIBZIPPP_ENABLE_ENCRYPTION`.
42
43### Compile libzippp
44
45#### Quick start
46
47```sh
48mkdir build
49cd build
50cmake ..
51make
52make install
53```
54
55#### Step by step
56
57- Make sure you have a compiler (MSVC, g++, ...) and CMake installed
58- Switch to the source folder
59- Create a build folder and switch to it, e.g.: `mkdir build && cd build`
60- Configure the build with cmake:
61  - Commandline: `cmake .. -DCMAKE_BUILD_TYPE=Release`
62  - Within the CMake GUI, set source and build folder accordingly
63	- Click `Add Cache Entry` to add `CMAKE_BUILD_TYPE` if not building with MSVC
64	- Click `Configure` & `Generate`
65  - If CMake can't find zlib and/or libzip you need to set `CMAKE_PREFIX_PATH` to the directories where you installed those into
66  (either via `-DCMAKE_PREFIX_PATH=<...>` or via the GUI)
67    - Example: `-DCMAKE_PREFIX_PATH=/home/user/libzip-1.8.0:/home/user/zlib-1.2.11`
68- Compile as usual
69  - Linux: `make && make install`
70  - Windows: Open generated project in MSVC. Build the `INSTALL` target to install.
71
72#### CMake variables of interest
73
74Set via commandline as `cmake -DNAME=VALUE <other opts>` or via CMake GUI or CCMake `Add Cache Entry`.
75
76- `LIBZIPPP_INSTALL`: Enable/Disable installation of libzippp. Default is OFF when using via `add_subdirectory`, else ON
77- `LIBZIPPP_INSTALL_HEADERS`: Enable/Disable installation of libzippp headers. Default is OFF when using via `add_subdirectory`, else ON
78- `LIBZIPPP_BUILD_TESTS`: Enable/Disable building libzippp tests. Default is OFF when using via `add_subdirectory`, else ON
79- `LIBZIPPP_ENABLE_ENCRYPTION`: Enable/Disable building libzippp with encryption capabilities. Default is OFF.
80- `CMAKE_INSTALL_PREFIX`: Where to install the project to
81- `CMAKE_BUILD_TYPE`: Set to Release or Debug to build with or without optimizations
82- `CMAKE_PREFIX_PATH`: Colon-separated list of prefix paths (paths containing `lib` and `include` folders) for installed libs to be used by this
83- `BUILD_SHARED_LIBS`: Set to ON or OFF to build shared or static libs, uses platform default if not set
84
85### Referencing libzippp
86
87Once installed libzippp can be used from any CMake project with ease:
88Given that it was installed (via `CMAKE_INSTALL_PREFIX`) into a standard location or its install prefix is passed into your projects
89`CMAKE_PREFIX_PATH` you can simply call `find_package(libzippp 3.0 REQUIRED)` and link against `libzippp::libzippp`.
90
91When not using CMake to consume libzippp you have to pass its include directory to your compiler and link against `libzippp.{a,so}`.
92Do not forget to also link against libzip libraries e.g. in *lib/libzip-1.8.0/lib/.libs/*).
93An example of compilation with g++:
94
95```shell
96g++ -I./src \
97    -I./lib/libzip-1.8.0/lib I./lib/libzip-1.8.0/build \
98    main.cpp libzippp.a \
99    lib/libzip-1.8.0/lib/.libs/libzip.a \
100    lib/zlib-1.2.11/libz.a
101```
102
103### Encryption
104
105Since version 1.5, libzip uses an underlying cryptographic library (OpenSSL, GNUTLS or CommonCrypto) that
106is necessary for static compilation. By default, libzippp will use `-lssl -lcrypto` (OpenSSL) as default flags
107to compile the tests. This can be changed by using `make CRYPTO_FLAGS="-lsome_lib" LIBZIP_CMAKE="" tests`.
108
109Since libzip `cmake`'s file detects automatically the cryptographic library to use, by default all the allowed
110libraries but OpenSSL are explicitely disabled in the `LIBZIP_CMAKE` variable in the Makefile.
111
112See [here](https://github.com/nih-at/libzip/blob/master/INSTALL.md) for more information.
113
114### WINDOWS - Alternative way
115
116The easiest way is to download zlib, libzip and libzippp sources and use CMake GUI to build each library in order:
117
118- Open CMake GUI
119- Point `Source` to the libraries source folder, `Build` to a new folder `build` inside it
120- Run `Generate`
121- Open the generated solution in MSVC and build & install it
122- Repeat for the next library
123
124But there is also a prepared batch file to help automate this.
125It may need some adjusting though.
126
127#### From Stage 1 - Use prepared environment
128
1290. Make sure you have cmake 3.20 (*cmake.exe* must be in the PATH) and MS Visual Studio.
130
1311. Download the *libzippp-\<version\>-windows-ready_to_compile.zip* file from the release
132  and extract it somewhere on your system. This will create a prepared structure, so *libzippp* can
133  be compiled along with the needed libraries.
134
1352. Simply execute the *compile.bat* file. This will compile *zlib*, *libzip* and
136 finally *libzippp*.
137
1383. You'll have a *dist* folder containing the *release* and *debug* folders
139  where you can now execute the libzippp tests.
140
141#### From Stage 0 - DIY
142
1430. Make sure you have cmake 3.10 (*cmake.exe* must be in the PATH) and MS Visual Studio 2012.
144
1451. Download [libzip](http://www.nih.at/libzip/libzip-1.8.0.tar.gz) and [zlib](http://zlib.net/zlib1211.zip) sources and extract them in the 'lib' folder.
146  You should end up with the following structure:
147  ```
148  libzippp/compile.bat
149  libzippp/lib/zlib-1.2.11
150  libzippp/lib/libzip-1.8.0
151  ```
1522. Execute the *compile.bat* (simply double-click on it). The compilation should
153  go without error.
154
1553. You'll have a *dist* folder containing the *release* and *debug* folders
156  where you can now execute the libzippp tests.
157
1584. You can either use *libzippp.dll* and *libzippp.lib* to link dynamically the
159  library or simply use *libzippp_static.lib* to link it statically. Unless you
160  also link zlib and libzippp statically, you'll need the dll packaged with
161  your executable.
162
163# Usage
164
165The API is meant to be very straight forward. Some french explanations
166can be found [here](http://www.astorm.ch/blog).
167
168### List and read files in an archive:
169
170```C++
171#include "libzippp.h"
172using namespace libzippp;
173
174int main(int argc, char** argv) {
175  ZipArchive zf("archive.zip");
176  zf.open(ZipArchive::ReadOnly);
177
178  vector<ZipEntry> entries = zf.getEntries();
179  vector<ZipEntry>::iterator it;
180  for(it=entries.begin() ; it!=entries.end(); ++it) {
181    ZipEntry entry = *it;
182    string name = entry.getName();
183    int size = entry.getSize();
184
185    //the length of binaryData will be size
186    void* binaryData = entry.readAsBinary();
187
188    //the length of textData will be size
189    string textData = entry.readAsText();
190
191    //...
192  }
193
194  zf.close();
195
196  return 0;
197}
198```
199
200You can also create an archive directly from a buffer:
201```C++
202#include "libzippp.h"
203using namespace libzippp;
204
205int main(int argc, char** argv) {
206  char* buffer = someData;
207  uint32_t bufferSize = sizeOfBuffer;
208
209  ZipArchive* zf = ZipArchive::fromBuffer(buffer, bufferSize);
210  if(zf!=nullptr) {
211    /* work with zf */
212    zf->close();
213    delete zf;
214  }
215
216  return 0;
217}
218```
219
220### Read a specific entry from an archive:
221
222```C++
223#include "libzippp.h"
224using namespace libzippp;
225
226int main(int argc, char** argv) {
227  ZipArchive zf("archive.zip");
228  zf.open(ZipArchive::ReadOnly);
229
230  //raw access
231  char* data = (char*)zf.readEntry("myFile.txt", true);
232  ZipEntry entry1 = zf.getEntry("myFile.txt");
233  string str1(data, entry1.getSize());
234
235  //text access
236  ZipEntry entry2 = zf.getEntry("myFile.txt");
237  string str2 = entry2.readAsText();
238
239  zf.close();
240
241  return 0;
242}
243```
244
245### Read a large entry from an archive:
246
247```C++
248#include "libzippp.h"
249using namespace libzippp;
250
251int main(int argc, char** argv) {
252  ZipArchive zf("archive.zip");
253  zf.open(ZipArchive::ReadOnly);
254
255  ZipEntry largeEntry = z1.getEntry("largeentry");
256  std::ofstream ofUnzippedFile("largeFileContent.data");
257  largeEntry.readContent(ofUnzippedFile);
258  ofUnzippedFile.close();
259
260  zf.close();
261
262  return 0;
263}
264```
265
266### Add data to an archive:
267
268```C++
269#include "libzippp.h"
270using namespace libzippp;
271
272int main(int argc, char** argv) {
273  ZipArchive zf("archive.zip");
274  zf.open(ZipArchive::Write);
275  zf.addEntry("folder/subdir/");
276
277  const char* textData = "Hello,World!";
278  zf.addData("helloworld.txt", textData, 12);
279
280  zf.close();
281
282  return 0;
283}
284```
285
286### Remove data from an archive:
287
288```C++
289#include "libzippp.h"
290using namespace libzippp;
291
292int main(int argc, char** argv) {
293  ZipArchive zf("archive.zip");
294  zf.open(ZipArchive::Write);
295  zf.deleteEntry("myFile.txt");
296  zf.deleteEntry("myDir/subDir/");
297  zf.close();
298
299  return 0;
300}
301```
302
303### Progression of committed changes
304
305```C++
306#include "libzippp.h"
307using namespace libzippp;
308
309class SimpleProgressListener : public ZipProgressListener {
310public:
311    SimpleProgressListener(void) {}
312    virtual ~SimpleProgressListener(void) {}
313
314    void progression(double p) {
315        cout << "-- Progression: " << p << endl;
316    }
317};
318
319int main(int argc, char** argv) {
320  ZipArchive zf("archive.zip");
321  /* add/modify/delete entries in the archive */
322
323  //register the listener
324  SimpleProgressListener spl;
325  zf.addProgressListener(&spl);
326
327  //adjust how often the listener will be invoked
328  zf.setProgressPrecision(0.1);
329
330  //listener will be invoked
331  zf.close();
332
333  return 0;
334}
335```
336
337### In-memory archives
338
339```C++
340#include "libzippp.h"
341using namespace libzippp;
342
343int main(int argc, char** argv) {
344  char* buffer = new char[4096];
345
346  ZipArchive* z1 = ZipArchive::fromBuffer(buffer, 4096, ZipArchive::New);
347  /* add content to the archive */
348
349  //will update the content of the buffer
350  z1->close();
351
352  //length of the buffer content
353  int bufferContentLength = z1->getBufferLength();
354
355  //read again from the archive:
356  ZipArchive* z2 = ZipArchive::fromBuffer(buffer, bufferContentLength);
357  /* read/modify the archive */
358
359  delete z1;
360  delete z2;
361  delete buffer;
362
363  return 0;
364}
365```
366
367## Known issues
368
369### LINUX
370
371You might already have libzip compiled elsewhere on your system. Hence, you
372don't need to run 'make libzip'. Instead, just put the libzip location when
373you compile libzippp:
374
375```shell
376make LIBZIP=path/to/libzip
377```
378
379Under Debian, you'll have to install the package `zlib1g-dev` in order to compile
380if you don't want to install zlib manually.
381
382### WINDOWS
383
384By default, MS Visual Studio 2012 is installed under the following path:
385
386```
387C:\Program Files (x86)\Microsoft Visual Studio 11.0\
388```
389
390Be aware that non-virtual-only classes are shared within the DLL of libzippp.
391Hence you'll need to use the same compiler for libzippp and the pieces of code
392that will use it. To avoid this issue, you'll have to link the library statically.
393
394More information [here](http://www.codeproject.com/Articles/28969/HowTo-Export-C-classes-from-a-DLL).
395
396### Static linkage
397
398Extra explanations can be found [here](http://hostagebrain.blogspot.com/search/label/zlib).
399
400