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