From 16c48993b04d31decf86a14a4c54909670fbcd19 Mon Sep 17 00:00:00 2001 From: AMIR <31338382+amiremohamadi@users.noreply.github.com> Date: Sat, 16 Feb 2019 22:30:09 +0330 Subject: [PATCH 01/86] Update README.md zlib package in ubuntu is zlib1g --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9c96e40..5e0ce10 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ the repo and it gets compiled with the project. #### Download dependencies ```shell -sudo apt-get install zlib-dev # for ubuntu +sudo apt-get install zlib1g-dev # for ubuntu sudo dnf install zlib-devel # for fedora sudo dnf install gcc-c++ # for fedora From 3d4caaf199d8f5c899f1c75581799dd812a623ff Mon Sep 17 00:00:00 2001 From: Thomas Hassler Date: Wed, 20 Mar 2019 19:25:30 +0100 Subject: [PATCH 02/86] Add memory size when initializing with stream (#38) --- zipper/unzipper.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/zipper/unzipper.cpp b/zipper/unzipper.cpp index 9b2fa38..91a3435 100644 --- a/zipper/unzipper.cpp +++ b/zipper/unzipper.cpp @@ -363,6 +363,7 @@ namespace zipper { if (size > 0) { m_zipmem.base = new char[(size_t)size]; + m_zipmem.size = (uLong)size; stream.read(m_zipmem.base, size); } From 7916d3332762021d22c9493bc55ea3c31a8d2e68 Mon Sep 17 00:00:00 2001 From: Quentin Quadrat Date: Wed, 20 Mar 2019 19:26:11 +0100 Subject: [PATCH 03/86] Add continuous integration: Travis and appveyor (#23) Add scripts for continuous integration: * Travis: gcc and clang for Linux 17.04 and OS X. * appVeyor: MinGW: not yet ok (cmake fails locating zlib). Note: tested for 64-bits architectures. --- .integration/appveyor-install-window.sh | 21 ++++++++++++++++ .integration/appveyor-launch_tests.sh | 15 ++++++++++++ .integration/travis-deploy.sh | 3 +++ .integration/travis-install-linux.sh | 3 +++ .integration/travis-install-osx.sh | 12 ++++++++++ .integration/travis-launch_tests.sh | 11 +++++++++ .travis.yml | 32 +++++++++++++++++++++++++ appveyor.yml | 18 ++++++++++++++ 8 files changed, 115 insertions(+) create mode 100755 .integration/appveyor-install-window.sh create mode 100755 .integration/appveyor-launch_tests.sh create mode 100755 .integration/travis-deploy.sh create mode 100755 .integration/travis-install-linux.sh create mode 100755 .integration/travis-install-osx.sh create mode 100755 .integration/travis-launch_tests.sh create mode 100644 .travis.yml create mode 100644 appveyor.yml diff --git a/.integration/appveyor-install-window.sh b/.integration/appveyor-install-window.sh new file mode 100755 index 0000000..4f736ae --- /dev/null +++ b/.integration/appveyor-install-window.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +packages="" +function mingw_packages +{ + arch=x86_64 + if [ "$PLATFORM" == "x86" ]; + then + arch=i686 + fi + + prefix="mingw-w64-${arch}-" + for i in $1 + do + packages="$prefix""$i "$packages + done +} + +mingw_packages "zlib cmake toolchain clang" + +sh -c "pacman -S --noconfirm git make $packages" diff --git a/.integration/appveyor-launch_tests.sh b/.integration/appveyor-launch_tests.sh new file mode 100755 index 0000000..f2193c3 --- /dev/null +++ b/.integration/appveyor-launch_tests.sh @@ -0,0 +1,15 @@ +#!/bin/bash + +export PATH="/mingw64/bin:/usr/local/bin:/usr/bin:/bin:/c/WINDOWS/system32:/c/WINDOWS:/c/WINDOWS/System32/Wbem:/c/WINDOWS/System32/WindowsPowerShell/v1.0" +bf=$(cygpath ${APPVEYOR_BUILD_FOLDER}) +cd "$bf" || (echo "Cannot go to directory $bf"; return 1) + +# Compile +mkdir -p build +cd build || exit 1 +cmake .. || exit 1 +make -j4 || exit 1 +cd .. + +# Unit test +(cd build && ./Zipper-test) || exit 1 diff --git a/.integration/travis-deploy.sh b/.integration/travis-deploy.sh new file mode 100755 index 0000000..46ea28c --- /dev/null +++ b/.integration/travis-deploy.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +echo "TODO if deploying is needed" diff --git a/.integration/travis-install-linux.sh b/.integration/travis-install-linux.sh new file mode 100755 index 0000000..1c38078 --- /dev/null +++ b/.integration/travis-install-linux.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +apt-get update && apt-get install -y cmake git g++ clang zlib1g-dev valgrind diff --git a/.integration/travis-install-osx.sh b/.integration/travis-install-osx.sh new file mode 100755 index 0000000..e83aace --- /dev/null +++ b/.integration/travis-install-osx.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +function brew_install +{ +# (brew outdated "$1" || brew install "$1") || (echo "Error installing $1"; return 1) + (brew install "$1") || (echo "Error installing $1"; return 1) +} + +brew update +#brew upgrade +brew_install valgrind +brew link --force valgrind diff --git a/.integration/travis-launch_tests.sh b/.integration/travis-launch_tests.sh new file mode 100755 index 0000000..fd98609 --- /dev/null +++ b/.integration/travis-launch_tests.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# Compile +mkdir -p build +cd build || exit 1 +cmake .. || exit 1 +make -j4 || exit 1 +cd .. + +# Unit test +(cd build && valgrind --track-origins=yes ./Zipper-test) || exit 1 diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..c844436 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,32 @@ +sudo: required +dist: trusty +language: cpp + +compiler: + - gcc + - clang + +services: + - docker + +os: + - linux + - osx + +before_install: + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker pull ubuntu:17.04 ; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker run -e CXX="$CXX" --name travis-ci -v $TRAVIS_BUILD_DIR:/zipper -td ubuntu:16.04 /bin/bash ; fi + +install: + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec -ti travis-ci bash -c "cd zipper && ./.integration/travis-install-linux.sh" ; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" && "$CXX" != "g++" ]]; then ./.integration/travis-install-osx.sh ; fi + +script: + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec -ti travis-ci bash -c "cd zipper && ./.integration/travis-launch_tests.sh" ; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" && "$CXX" != "g++" ]]; then ./.integration/travis-launch_tests.sh ; fi + +after_success: + - if [[ "$TRAVIS_OS_NAME" == "linux" && "$CXX" == "g++" ]]; then docker exec -ti travis-ci bash -c "cd zipper && ./.integration/travis-deploy.sh" ; fi + +after_script: + - docker stop travis-ci diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 0000000..b480e65 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,18 @@ +platform: + - x64 + +environment: + MSYSTEM: MSYS + +before_build: + - C:\msys64\usr\bin\pacman --noconfirm --sync --refresh --refresh --sysupgrade --sysupgrade + - C:\msys64\usr\bin\pacman --noconfirm --sync --refresh --refresh pacman + - C:\msys64\usr\bin\pacman --noconfirm --sync --refresh --refresh git + - C:\msys64\usr\bin\bash -lc "$(cygpath ${APPVEYOR_BUILD_FOLDER})/.integration/appveyor-install-window.sh" + +build_script: + - C:\msys64\usr\bin\bash -lc "$(cygpath ${APPVEYOR_BUILD_FOLDER})/.integration/appveyor-launch_tests.sh" + +branches: + only: + - master From 81bb33b31befe6eeece9da51a56340b18bdd97bb Mon Sep 17 00:00:00 2001 From: Quentin Quadrat Date: Wed, 20 Mar 2019 19:35:10 +0100 Subject: [PATCH 04/86] Fix memory leaks (#25) --- zipper/unzipper.cpp | 53 ++++++++++++++++++++++++++++++++++------- zipper/unzipper.h | 3 ++- zipper/zipper.cpp | 57 +++++++++++++++++++++++++++++++++++++-------- zipper/zipper.h | 3 ++- 4 files changed, 96 insertions(+), 20 deletions(-) diff --git a/zipper/unzipper.cpp b/zipper/unzipper.cpp index 91a3435..6295644 100644 --- a/zipper/unzipper.cpp +++ b/zipper/unzipper.cpp @@ -329,17 +329,28 @@ namespace zipper { Impl(Unzipper& outer) : m_outer(outer), m_zipmem(), m_filefunc() { + m_zipmem.base = NULL; m_zf = NULL; } ~Impl() { + close(); } void close() { - if (m_zf) + if (m_zf != NULL) + { unzClose(m_zf); + m_zf = NULL; + } + + if (m_zipmem.base != NULL) + { + free(m_zipmem.base); + m_zipmem.base = NULL; + } } bool initFile(const std::string& filename) @@ -376,7 +387,8 @@ namespace zipper { { if (!buffer.empty()) { - m_zipmem.base = (char*)buffer.data(); + m_zipmem.base = (char*) malloc (buffer.size() * sizeof (char)); + memcpy(m_zipmem.base, (char*) buffer.data(), buffer.size()); m_zipmem.size = (uLong)buffer.size(); } @@ -467,7 +479,10 @@ namespace zipper { , m_impl(new Impl(*this)) { if (!m_impl->initWithStream(m_ibuffer)) - throw EXCEPTION_CLASS("Error loading zip in memory!"); + { + release(); + throw EXCEPTION_CLASS("Error loading zip in memory!"); + } m_open = true; } @@ -479,7 +494,10 @@ namespace zipper { , m_impl(new Impl(*this)) { if (!m_impl->initWithVector(m_vecbuffer)) - throw EXCEPTION_CLASS("Error loading zip in memory!"); + { + release(); + throw EXCEPTION_CLASS("Error loading zip in memory!"); + } m_open = true; } @@ -493,7 +511,10 @@ namespace zipper { , m_impl(new Impl(*this)) { if (!m_impl->initFile(zipname)) - throw EXCEPTION_CLASS("Error loading zip file!"); + { + release(); + throw EXCEPTION_CLASS("Error loading zip file!"); + } m_open = true; } @@ -508,14 +529,17 @@ namespace zipper { , m_impl(new Impl(*this)) { if (!m_impl->initFile(zipname)) - throw EXCEPTION_CLASS("Error loading zip file!"); - + { + release(); + throw EXCEPTION_CLASS("Error loading zip file!"); + } m_open = true; } - Unzipper::~Unzipper(void) + Unzipper::~Unzipper() { close(); + release(); } std::vector Unzipper::entries() @@ -550,6 +574,19 @@ namespace zipper { return m_impl->extractAll(destination, std::map()); } + void Unzipper::release() + { + if (!m_usingMemoryVector) + { + delete &m_vecbuffer; + } + if (!m_usingStream) + { + delete &m_ibuffer; + } + delete m_impl; + } + void Unzipper::close() { if (m_open) diff --git a/zipper/unzipper.h b/zipper/unzipper.h index e1e6556..1c837b7 100644 --- a/zipper/unzipper.h +++ b/zipper/unzipper.h @@ -20,7 +20,7 @@ namespace zipper { Unzipper(const std::string& zipname); Unzipper(const std::string& zipname, const std::string& password); - ~Unzipper(void); + ~Unzipper(); std::vector entries(); @@ -33,6 +33,7 @@ namespace zipper { void close(); private: + void release(); std::string m_password; std::string m_zipname; std::istream& m_ibuffer; diff --git a/zipper/zipper.cpp b/zipper/zipper.cpp index 84ce390..45542e3 100644 --- a/zipper/zipper.cpp +++ b/zipper/zipper.cpp @@ -18,9 +18,15 @@ namespace zipper { Impl(Zipper& outer) : m_outer(outer), m_zipmem(), m_filefunc() { m_zf = NULL; + m_zipmem.base = NULL; //m_filefunc = { 0 }; } + ~Impl() + { + close(); + } + bool initFile(const std::string& filename) { #ifdef USEWIN32IOAPI @@ -56,7 +62,8 @@ namespace zipper { if (size > 0) { - m_zipmem.base = new char[(size_t)size]; + if (m_zipmem.base != NULL) { free(m_zipmem.base); } + m_zipmem.base = (char*) malloc (size * sizeof (char)); stream.read(m_zipmem.base, size); } @@ -71,8 +78,9 @@ namespace zipper { if (!buffer.empty()) { - m_zipmem.base = new char[buffer.size()]; - memcpy(m_zipmem.base, (char*)buffer.data(), buffer.size()); + if (m_zipmem.base != NULL) { free(m_zipmem.base); } + m_zipmem.base = (char*) malloc (buffer.size() * sizeof (char)); + memcpy(m_zipmem.base, (char*) buffer.data(), buffer.size()); m_zipmem.size = (uLong)buffer.size(); } @@ -168,8 +176,11 @@ namespace zipper { void close() { - if (m_zf) + if (m_zf != NULL) + { zipClose(m_zf, NULL); + m_zf = NULL; + } if (m_zipmem.base && m_zipmem.limit > 0) { @@ -183,7 +194,11 @@ namespace zipper { m_outer.m_obuffer.write(m_zipmem.base, m_zipmem.limit); } - free(m_zipmem.base); + if (m_zipmem.base != NULL) + { + free(m_zipmem.base); + m_zipmem.base = NULL; + } } }; @@ -199,8 +214,10 @@ namespace zipper { , m_impl(new Impl(*this)) { if (!m_impl->initFile(zipname)) + { + release(); throw EXCEPTION_CLASS("Error creating zip in file!"); - + } m_open = true; } @@ -214,8 +231,10 @@ namespace zipper { , m_impl(new Impl(*this)) { if (!m_impl->initFile(zipname)) + { + release(); throw EXCEPTION_CLASS("Error creating zip in file!"); - + } m_open = true; } @@ -227,8 +246,10 @@ namespace zipper { , m_impl(new Impl(*this)) { if (!m_impl->initWithStream(m_obuffer)) + { + release(); throw EXCEPTION_CLASS("Error creating zip in memory!"); - + } m_open = true; } @@ -240,14 +261,30 @@ namespace zipper { , m_impl(new Impl(*this)) { if (!m_impl->initWithVector(m_vecbuffer)) + { + release(); throw EXCEPTION_CLASS("Error creating zip in memory!"); - + } m_open = true; } - Zipper::~Zipper(void) + Zipper::~Zipper() { close(); + release(); + } + + void Zipper::release() + { + if (!m_usingMemoryVector) + { + delete &m_vecbuffer; + } + if (!m_usingStream) + { + delete &m_obuffer; + } + delete m_impl; } bool Zipper::add(std::istream& source, const std::string& nameInZip, zipFlags flags) diff --git a/zipper/zipper.h b/zipper/zipper.h index 56fb5f2..d554cf3 100644 --- a/zipper/zipper.h +++ b/zipper/zipper.h @@ -20,7 +20,7 @@ namespace zipper { Zipper(const std::string& zipname); Zipper(const std::string& zipname, const std::string& password); - ~Zipper(void); + ~Zipper(); bool add(std::istream& source, const std::string& nameInZip = std::string(), zipFlags flags = Better); bool add(const std::string& fileOrFolderPath, zipFlags flags = Better); @@ -29,6 +29,7 @@ namespace zipper { void close(); private: + void release(); std::string m_password; std::string m_zipname; std::iostream& m_obuffer; From f7f3f63cc38e7b5dbb1ec5243169bbf8bbf543ae Mon Sep 17 00:00:00 2001 From: seb Date: Wed, 20 Mar 2019 15:44:45 -0300 Subject: [PATCH 05/86] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5e0ce10..96a0970 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ ![Zipper](https://github.com/sebastiandev/zipper/blob/master/logo.png) +[![Build Status](https://travis-ci.org/sebastiandev/zipper.svg?branch=development)](https://travis-ci.org/sebastiandev/zipper) [![Build Status](https://ci.appveyor.com/api/projects/status/github/sebastiandev/zipper)](https://ci.appveyor.com/api/projects/status/github/sebastiandev/zipper) C++ wrapper around minizip compression library From 481b770908533d9c92114a6e27d80fc8adbd4173 Mon Sep 17 00:00:00 2001 From: Seba Date: Wed, 20 Mar 2019 16:04:53 -0300 Subject: [PATCH 06/86] update latest minizip --- minizip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minizip b/minizip index 4acd44b..0b46a2b 160000 --- a/minizip +++ b/minizip @@ -1 +1 @@ -Subproject commit 4acd44bf24025b58e9cf6f8545eb42d2ab36d714 +Subproject commit 0b46a2b4ca317b80bc53594688883f7188ac4d08 From e748fbc0dc5fad83a3e0ea5919499f081f366e9b Mon Sep 17 00:00:00 2001 From: LeCrapouille Date: Thu, 11 Apr 2019 22:20:03 +0200 Subject: [PATCH 07/86] Fix Travis-CI Fix Ubuntu version in Travis-CI. Exclude compiling with g++ on OSX because they only use clang. Fix Travis-CI badge linked on dev branch instead of master. --- .travis.yml | 11 ++++++++--- README.md | 6 +++++- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index c844436..4e975e1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,17 +13,22 @@ os: - linux - osx +matrix: + exclude: # On OSX g++ is a symlink to clang++ by default + - os: osx + compiler: gcc + before_install: - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker pull ubuntu:17.04 ; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker pull ubuntu:16.04 ; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker run -e CXX="$CXX" --name travis-ci -v $TRAVIS_BUILD_DIR:/zipper -td ubuntu:16.04 /bin/bash ; fi install: - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec -ti travis-ci bash -c "cd zipper && ./.integration/travis-install-linux.sh" ; fi - - if [[ "$TRAVIS_OS_NAME" == "osx" && "$CXX" != "g++" ]]; then ./.integration/travis-install-osx.sh ; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./.integration/travis-install-osx.sh ; fi script: - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec -ti travis-ci bash -c "cd zipper && ./.integration/travis-launch_tests.sh" ; fi - - if [[ "$TRAVIS_OS_NAME" == "osx" && "$CXX" != "g++" ]]; then ./.integration/travis-launch_tests.sh ; fi + - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ./.integration/travis-launch_tests.sh ; fi after_success: - if [[ "$TRAVIS_OS_NAME" == "linux" && "$CXX" == "g++" ]]; then docker exec -ti travis-ci bash -c "cd zipper && ./.integration/travis-deploy.sh" ; fi diff --git a/README.md b/README.md index 96a0970..1d09161 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ ![Zipper](https://github.com/sebastiandev/zipper/blob/master/logo.png) -[![Build Status](https://travis-ci.org/sebastiandev/zipper.svg?branch=development)](https://travis-ci.org/sebastiandev/zipper) [![Build Status](https://ci.appveyor.com/api/projects/status/github/sebastiandev/zipper)](https://ci.appveyor.com/api/projects/status/github/sebastiandev/zipper) + +|Branch | **`Linux/Mac OS`** | **`Windows`** | +|-----------|------------------|-------------| +|master |[![Build Status](https://travis-ci.org/sebastiandev/zipper.svg?branch=master)](https://travis-ci.org/sebastiandev/zipper)|[![Build status](https://ci.appveyor.com/api/projects/status/github/sebastiandev/zipper)](https://ci.appveyor.com/api/projects/status/github/sebastiandev/zipper)| +|development|[![Build Status](https://travis-ci.org/sebastiandev/zipper.svg?branch=develop)](https://travis-ci.org/sebastiandev/zipper)|| C++ wrapper around minizip compression library From e9f150516cb55d194b5e01d21a9527783e98311d Mon Sep 17 00:00:00 2001 From: LeCrapouille Date: Thu, 11 Apr 2019 22:36:15 +0200 Subject: [PATCH 08/86] Update version to 1.0.1 --- VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION.txt b/VERSION.txt index f374f66..7dea76e 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -0.9.1 +1.0.1 From 01b3566b36ae2a22573172a18f24f9c259e902b2 Mon Sep 17 00:00:00 2001 From: Andrew Ferg Date: Mon, 6 May 2019 18:11:51 -0400 Subject: [PATCH 09/86] Updated CMake to use more modern target export format (#41) * added config, target export to CMake * UNIX, Windows have same Zipper library name --- CMakeLists.txt | 41 ++++++++++++++++++++++++++--------------- zipperConfig.cmake.in | 8 ++++++++ 2 files changed, 34 insertions(+), 15 deletions(-) create mode 100644 zipperConfig.cmake.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 394132a..3eb7e65 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,11 +88,8 @@ if(WITH_WALL) endif() endif() -if (UNIX) - set(ZIPPER_LIBRARY Zipper) -else() - set(ZIPPER_LIBRARY libZipper) -endif() +set(ZIPPER_LIBRARY Zipper) + # Set build type default. set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build to perform. The options are: None (CMAKE_CXX_FLAGS @@ -342,11 +339,7 @@ if (BUILD_SHARED_VERSION) target_link_libraries(${ZIPPER_LIBRARY} ${LIBZ_LIBRARY} ${EXTRA_LIBS}) - INSTALL(TARGETS ${ZIPPER_LIBRARY} - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - ) + list(APPEND TARGET_LIST ${ZIPPER_LIBRARY}) endif() option(BUILD_STATIC_VERSION "Build the static version of the library." ON) @@ -355,11 +348,7 @@ if (BUILD_STATIC_VERSION) target_link_libraries(${ZIPPER_LIBRARY}-static ${LIBZ_LIBRARY} ${EXTRA_LIBS}) - INSTALL(TARGETS ${ZIPPER_LIBRARY}-static - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - ) + list(APPEND TARGET_LIST ${ZIPPER_LIBRARY}-static) endif() @@ -384,6 +373,7 @@ if (BUILD_TEST) add_executable(${ZIPPER_LIBRARY}-test ${TEST_SOURCES}) target_link_libraries(${ZIPPER_LIBRARY}-test ${ZIPPER_LIBRARY}-static ${LIBZ_LIBRARY} ${EXTRA_LIBS}) + list(APPEND TARGET_LIST ${ZIPPER_LIBRARY}-test) add_test( NAME test_zipper_run @@ -395,12 +385,33 @@ if (BUILD_TEST) ) endif() +configure_file(${CMAKE_SOURCE_DIR}/zipperConfig.cmake.in + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake + @ONLY) + +export(TARGETS ${TARGET_LIST} FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake) + +install(TARGETS ${TARGET_LIST} EXPORT ${PROJECT_NAME} + RUNTIME DESTINATION bin COMPONENT lib + LIBRARY DESTINATION lib${LIB_SUFFIX} COMPONENT lib + ARCHIVE DESTINATION lib${LIB_SUFFIX} COMPONENT lib + INCLUDES DESTINATION include + PUBLIC_HEADER DESTINATION include/zipper +) + file(GLOB ZIPPER_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/zipper/*.h ${CMAKE_CURRENT_SOURCE_DIR}/minizip/*.h ) install(FILES ${ZIPPER_HEADERS} DESTINATION include/zipper ) +install(FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake + DESTINATION lib${LIB_SUFFIX}/cmake) + +install(EXPORT ${PROJECT_NAME} + DESTINATION lib${LIB_SUFFIX}/cmake + FILE ${PROJECT_NAME}Targets.cmake) + message(STATUS " ---------------------------------------------------------------------- Zipper version ${PACKAGE_VERSION} diff --git a/zipperConfig.cmake.in b/zipperConfig.cmake.in new file mode 100644 index 0000000..a9476d0 --- /dev/null +++ b/zipperConfig.cmake.in @@ -0,0 +1,8 @@ +@FIND_DEPENDENCIES@ +@PACKAGE_INIT@ + +list(APPEND CMAKE_MODULE_PATH @CMAKE_CURRENT_SOURCE_DIR@/cmake) + +if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake AND NOT TARGET @GUARD_TARGET@) + include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake) +endif() From 3b0ca4e18caa04d61434c23716d410e581ffd1b5 Mon Sep 17 00:00:00 2001 From: Mez Gebre Date: Thu, 16 May 2019 05:39:45 -0700 Subject: [PATCH 10/86] update cmake to fix compiling as a subdirectory (#43) --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3eb7e65..0f6accd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -385,7 +385,7 @@ if (BUILD_TEST) ) endif() -configure_file(${CMAKE_SOURCE_DIR}/zipperConfig.cmake.in +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/zipperConfig.cmake.in ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake @ONLY) From 6a0d1d64d1addc1e04d02b8b0a9d4429cd9e04e7 Mon Sep 17 00:00:00 2001 From: Gergely Zombori Date: Wed, 21 Aug 2019 11:06:54 +0200 Subject: [PATCH 11/86] Ticket #45: Passworded encryption failed because CRC generation did not rewind the file correctly. This is now fixed in tools.cpp so the password can be passed onto the Impl::add(..) method. --- zipper/tools.cpp | 4 +++- zipper/zipper.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/zipper/tools.cpp b/zipper/tools.cpp index 5c2fee5..e1b8205 100644 --- a/zipper/tools.cpp +++ b/zipper/tools.cpp @@ -6,6 +6,7 @@ #include #include +#include #if defined(WIN32) && !defined(CYGWIN) # include "tps/dirent.h" @@ -40,7 +41,8 @@ namespace zipper { } while (size_read > 0); - input_stream.seekg(0); + input_stream.clear(); + input_stream.seekg(0, std::ios_base::beg); result_crc = calculate_crc; } diff --git a/zipper/zipper.cpp b/zipper/zipper.cpp index 45542e3..679f0e7 100644 --- a/zipper/zipper.cpp +++ b/zipper/zipper.cpp @@ -289,7 +289,7 @@ namespace zipper { bool Zipper::add(std::istream& source, const std::string& nameInZip, zipFlags flags) { - return m_impl->add(source, nameInZip, "", flags); + return m_impl->add(source, nameInZip, m_password, flags); } bool Zipper::add(const std::string& fileOrFolderPath, zipFlags flags) From 11b1ac461dcff6c85306ef659bffa5bc92e8641c Mon Sep 17 00:00:00 2001 From: Gergely Zombori Date: Wed, 21 Aug 2019 11:35:57 +0200 Subject: [PATCH 12/86] Ticket #48: Require C++ 11, export all symbols on Windows and define debug postfix --- CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0f6accd..63c7e54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,12 @@ set(CMAKE_LEGACY_CYGWIN_WIN32 0) cmake_minimum_required(VERSION 2.6) project(zipper) +# Set useful CMake flags +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON) +set(CMAKE_DEBUG_POSTFIX "d") + include (CMakeTestCCompiler) include (CheckCSourceCompiles) include (CheckCXXSourceCompiles) From 91935654244ab5a853fd27192733dc82e0ef5953 Mon Sep 17 00:00:00 2001 From: LeCrapouille Date: Thu, 11 Apr 2019 23:07:14 +0200 Subject: [PATCH 13/86] Fix folder separators #32 --- zipper/unzipper.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/zipper/unzipper.cpp b/zipper/unzipper.cpp index 6295644..2561d10 100644 --- a/zipper/unzipper.cpp +++ b/zipper/unzipper.cpp @@ -1,4 +1,5 @@ #include "unzipper.h" +#include "CDirEntry.h" #include "defs.h" #include "tools.h" @@ -416,7 +417,7 @@ namespace zipper { if (!locateEntry(it->name)) continue; - std::string alternativeName = destination.empty() ? "" : destination + "/"; + std::string alternativeName = destination.empty() ? "" : destination + CDirEntry::Separator; if (alternativeNames.find(it->name) != alternativeNames.end()) alternativeName += alternativeNames.at(it->name); @@ -431,7 +432,7 @@ namespace zipper { bool extractEntry(const std::string& name, const std::string& destination) { - std::string outputFile = destination.empty() ? name : destination + "\\" + name; + std::string outputFile = destination.empty() ? name : destination + CDirEntry::Separator + name; if (locateEntry(name)) { From 27106090b2d9a2f91deac10cc573ab680605733c Mon Sep 17 00:00:00 2001 From: LeCrapouille Date: Thu, 11 Apr 2019 23:11:31 +0200 Subject: [PATCH 14/86] Windows won't zip directories #36 --- zipper/tps/dirent.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zipper/tps/dirent.c b/zipper/tps/dirent.c index beafc5e..6319512 100644 --- a/zipper/tps/dirent.c +++ b/zipper/tps/dirent.c @@ -127,7 +127,7 @@ DIR *opendir(char const *name) /* Must be a valid name */ if( !name || !*name || - (dwAttr = GetFileAttributes(name)) == 0xFFFFFFFF) + (dwAttr = GetFileAttributesA(name)) == 0xFFFFFFFF) { errno = ENOENT; } From 064e047a3d226c46959369761ab7a4a4a8dfe7c8 Mon Sep 17 00:00:00 2001 From: LeCrapouille Date: Thu, 11 Apr 2019 23:36:08 +0200 Subject: [PATCH 15/86] Update minizip --- minizip | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minizip b/minizip index 0b46a2b..e3a8cb7 160000 --- a/minizip +++ b/minizip @@ -1 +1 @@ -Subproject commit 0b46a2b4ca317b80bc53594688883f7188ac4d08 +Subproject commit e3a8cb79a034cb4f2ffc3abb6bd916ffa8678fed From f5268ae73c8b124936d40e2336c1a4b4b716574d Mon Sep 17 00:00:00 2001 From: prowinsk Date: Tue, 12 Nov 2019 11:38:31 +0000 Subject: [PATCH 16/86] Allow to add timestamp for archive streams. --- zipper/zipper.cpp | 16 ++++++++++++++-- zipper/zipper.h | 2 ++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/zipper/zipper.cpp b/zipper/zipper.cpp index 679f0e7..88f638e 100644 --- a/zipper/zipper.cpp +++ b/zipper/zipper.cpp @@ -95,7 +95,7 @@ namespace zipper { return m_zf != NULL; } - bool add(std::istream& input_stream, const std::string& nameInZip, const std::string& password, int flags) + bool add(std::istream& input_stream, const std::tm& timestamp, const std::string& nameInZip, const std::string& password, int flags) { if (!m_zf) return false; @@ -106,6 +106,13 @@ namespace zipper { unsigned long crcFile = 0; zip_fileinfo zi = { 0 }; + zi.tmz_date.tm_sec = timestamp.tm_sec; + zi.tmz_date.tm_min = timestamp.tm_min; + zi.tmz_date.tm_hour = timestamp.tm_hour; + zi.tmz_date.tm_mday = timestamp.tm_mday; + zi.tmz_date.tm_mon = timestamp.tm_mon; + zi.tmz_date.tm_year = timestamp.tm_year; + size_t size_read; std::vector buff; @@ -287,9 +294,14 @@ namespace zipper { delete m_impl; } + bool Zipper::add(std::istream& source, const std::tm& timestamp, const std::string& nameInZip, zipFlags flags) + { + return m_impl->add(source, timestamp, nameInZip, "", flags); + } + bool Zipper::add(std::istream& source, const std::string& nameInZip, zipFlags flags) { - return m_impl->add(source, nameInZip, m_password, flags); + return add(source, {}, nameInZip, flags); } bool Zipper::add(const std::string& fileOrFolderPath, zipFlags flags) diff --git a/zipper/zipper.h b/zipper/zipper.h index d554cf3..7cbcfa2 100644 --- a/zipper/zipper.h +++ b/zipper/zipper.h @@ -5,6 +5,7 @@ #include #include #include +#include namespace zipper { @@ -22,6 +23,7 @@ namespace zipper { ~Zipper(); + bool add(std::istream& source, const std::tm& timestamp, const std::string& nameInZip = std::string(), zipFlags flags = Better); bool add(std::istream& source, const std::string& nameInZip = std::string(), zipFlags flags = Better); bool add(const std::string& fileOrFolderPath, zipFlags flags = Better); From 3d1ef500c66869be548b86f080945cd2b613f7f8 Mon Sep 17 00:00:00 2001 From: prowinsk Date: Tue, 12 Nov 2019 12:03:02 +0000 Subject: [PATCH 17/86] Pass correct password parameter. --- zipper/zipper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zipper/zipper.cpp b/zipper/zipper.cpp index 88f638e..b710f43 100644 --- a/zipper/zipper.cpp +++ b/zipper/zipper.cpp @@ -296,7 +296,7 @@ namespace zipper { bool Zipper::add(std::istream& source, const std::tm& timestamp, const std::string& nameInZip, zipFlags flags) { - return m_impl->add(source, timestamp, nameInZip, "", flags); + return m_impl->add(source, timestamp, nameInZip, m_password, flags); } bool Zipper::add(std::istream& source, const std::string& nameInZip, zipFlags flags) From 596b3a021ad7e98d8e4a5a5a7307c15a50cc3928 Mon Sep 17 00:00:00 2001 From: oficsu <35731382+oficsu@users.noreply.github.com> Date: Thu, 21 Nov 2019 21:02:44 +0300 Subject: [PATCH 18/86] Add new flag to save file prefix (#52) * Add new flag to save file prefix This flag allows you to not lose file prefix (e.g. ./some/dir/before/file.txt) when we use add zipper::Zipper::add() --- test/memory_zip_test.cpp | 49 ++++++++++++++++++++++++++++++++++++++++ zipper/zipper.cpp | 10 +++++++- zipper/zipper.h | 4 ++-- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/test/memory_zip_test.cpp b/test/memory_zip_test.cpp index 66824de..e728b2a 100644 --- a/test/memory_zip_test.cpp +++ b/test/memory_zip_test.cpp @@ -164,5 +164,54 @@ SCENARIO("zip vector feed with different inputs", "[zip]") std::remove("strdata"); zipvec.clear(); } + + WHEN("a file containing 'test file compression' is added and named 'test1' in subdirectory 'subdirectory'") + { + bool fileWasCreated = zipper::makedir("subdirectory"); + + REQUIRE(fileWasCreated); + + std::ofstream test1("./subdirectory/test1.txt"); + test1 << "test file compression"; + test1.flush(); + test1.close(); + + + auto flags = Zipper::zipFlags::Better | Zipper::zipFlags::SaveHierarchy; + zipper.add("./subdirectory/test1.txt", static_cast(flags)); + + zipper.close(); + + std::remove("./subdirectory/test1.txt"); + + zipper::Unzipper unzipper(zipvec); + + THEN("the zip vector has entry named './subdirectory/test1.txt'") + { + REQUIRE(unzipper.entries().size() == 1); + REQUIRE(unzipper.entries().front().name == "./subdirectory/test1.txt"); + + AND_THEN("extracting the test1.txt entry creates a file named 'test1.txt' with the text 'test file compression'") + { + unzipper.extractEntry("./subdirectory/test1.txt"); + // due to sections forking or creating different stacks we need to make sure the local instance is closed to + // prevent mixing the closing when both instances are freed at the end of the scope + unzipper.close(); + + REQUIRE(checkFileExists("./subdirectory/test1.txt")); + + std::ifstream testfile("./subdirectory/test1.txt"); + REQUIRE(testfile.good()); + + std::string test((std::istreambuf_iterator(testfile)), std::istreambuf_iterator()); + testfile.close(); + REQUIRE(test == "test file compression"); + + removeFolder("subdirectory"); + } + } + + zipvec.clear(); + } } } diff --git a/zipper/zipper.cpp b/zipper/zipper.cpp index b710f43..bd2343f 100644 --- a/zipper/zipper.cpp +++ b/zipper/zipper.cpp @@ -322,7 +322,15 @@ namespace zipper { else { std::ifstream input(fileOrFolderPath.c_str(), std::ios::binary); - add(input, fileNameFromPath(fileOrFolderPath), flags); + std::string fullFileName; + + if (flags & Zipper::SaveHierarchy) + fullFileName = fileOrFolderPath; + else + fullFileName = fileNameFromPath(fileOrFolderPath); + + add(input, fullFileName, flags); + input.close(); } diff --git a/zipper/zipper.h b/zipper/zipper.h index 7cbcfa2..3921891 100644 --- a/zipper/zipper.h +++ b/zipper/zipper.h @@ -14,7 +14,7 @@ namespace zipper { public: // Minizip options/params: // -o -a -0 -1 -9 -j - enum zipFlags { Overwrite = 0x01, Append = 0x02, Store = 0x04, Faster = 0x08, Better = 0x10, NoPaths = 0x20 }; + enum zipFlags { Overwrite = 0x01, Append = 0x02, Store = 0x04, Faster = 0x08, Better = 0x10, NoPaths = 0x20, SaveHierarchy = 0x40 }; Zipper(std::iostream& buffer); Zipper(std::vector& buffer); @@ -26,7 +26,7 @@ namespace zipper { bool add(std::istream& source, const std::tm& timestamp, const std::string& nameInZip = std::string(), zipFlags flags = Better); bool add(std::istream& source, const std::string& nameInZip = std::string(), zipFlags flags = Better); bool add(const std::string& fileOrFolderPath, zipFlags flags = Better); - + void open(); void close(); From 77f9ae4ba9e24964d24c4e7cf720f289baa15576 Mon Sep 17 00:00:00 2001 From: Quentin Quadrat Date: Fri, 24 Jan 2020 20:33:44 +0100 Subject: [PATCH 19/86] Fix #53 unzipper.extractEntry returnin an error on nominal case --- README.md | 2 ++ zipper/unzipper.cpp | 6 ++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1d09161..0f00e26 100644 --- a/README.md +++ b/README.md @@ -150,3 +150,5 @@ Unzipper unzipper("zipfile.zip"); unzipper.extractEntryToMemory("entry name", unzipped_entry); unzipper.close(); ``` + +**Note:** Methods `extract`, `extractEntry`, `extractEntryToMemory` return a boolean indicating the success (`true`) or the failure (`false`). diff --git a/zipper/unzipper.cpp b/zipper/unzipper.cpp index 2561d10..d56c90e 100644 --- a/zipper/unzipper.cpp +++ b/zipper/unzipper.cpp @@ -240,7 +240,7 @@ namespace zipper { if (output_file.good()) { - if (extractToStream(output_file, info)) + if (UNZ_OK == extractToStream(output_file, info)) err = UNZ_OK; output_file.close(); @@ -259,9 +259,7 @@ namespace zipper { int extractToStream(std::ostream& stream, ZipEntry& info) { - size_t err = UNZ_ERRNO; - - err = unzOpenCurrentFilePassword(m_zf, m_outer.m_password.c_str()); + size_t err = unzOpenCurrentFilePassword(m_zf, m_outer.m_password.c_str()); if (UNZ_OK != err) { std::stringstream str; From 1e95b5bd2185422b17d1f1f2f7d3f6e92b69c8bd Mon Sep 17 00:00:00 2001 From: Quentin Quadrat Date: Sat, 25 Jan 2020 00:11:32 +0100 Subject: [PATCH 20/86] Install pkg-config file, force installing shared lib and rename static lib - Install a pkg-config file to avoid to know the path of includes and libraries for non CMake users. - Force by default to compile the shared library. - Install a second static library with the name libZipper.a (the 1st is still name libZipper-static.a) but this is not Unix way to name a static lib (ie I dunno make pkg-config knows it). - Read the VZERSION.txt file --- CMakeLists.txt | 28 +++++++++++++++++------- README.md | 54 +++++++++++++++++++++++++++++++++++++++++++++++ zipper.pc.cmakein | 12 +++++++++++ 3 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 zipper.pc.cmakein diff --git a/CMakeLists.txt b/CMakeLists.txt index 63c7e54..7ab870c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -333,7 +333,9 @@ file(GLOB TEST_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/test/*.hpp ) -option(BUILD_SHARED_VERSION "Build the shared version of the library." OFF) +file(READ "${CMAKE_CURRENT_SOURCE_DIR}/VERSION.txt" VERSION) + +option(BUILD_SHARED_VERSION "Build the shared version of the library." ON) if (BUILD_SHARED_VERSION) add_library (${ZIPPER_LIBRARY} SHARED ${ZIPPER_SOURCES} ${MINIZIP_SOURCES} ) @@ -350,10 +352,16 @@ endif() option(BUILD_STATIC_VERSION "Build the static version of the library." ON) if (BUILD_STATIC_VERSION) + set(STATIC_ZIPPER_LIBRARY static${ZIPPER_LIBRARY}) + add_library (${STATIC_ZIPPER_LIBRARY} STATIC ${ZIPPER_SOURCES} ${MINIZIP_SOURCES}) + set_target_properties(${STATIC_ZIPPER_LIBRARY} PROPERTIES OUTPUT_NAME ${ZIPPER_LIBRARY}) + target_link_libraries(${STATIC_ZIPPER_LIBRARY} ${LIBZ_LIBRARY} ${EXTRA_LIBS}) + list(APPEND TARGET_LIST ${STATIC_ZIPPER_LIBRARY}) + + # Deprecated code: old zipper static lib was named libZipper-static.a but this was not + # a good unix name. Anyway keep installing it to avoid breaking programs link with it. add_library (${ZIPPER_LIBRARY}-static STATIC ${ZIPPER_SOURCES} ${MINIZIP_SOURCES}) - target_link_libraries(${ZIPPER_LIBRARY}-static ${LIBZ_LIBRARY} ${EXTRA_LIBS}) - list(APPEND TARGET_LIST ${ZIPPER_LIBRARY}-static) endif() @@ -378,7 +386,7 @@ if (BUILD_TEST) include(CTest) add_executable(${ZIPPER_LIBRARY}-test ${TEST_SOURCES}) - target_link_libraries(${ZIPPER_LIBRARY}-test ${ZIPPER_LIBRARY}-static ${LIBZ_LIBRARY} ${EXTRA_LIBS}) + target_link_libraries(${ZIPPER_LIBRARY}-test static${ZIPPER_LIBRARY} ${LIBZ_LIBRARY} ${EXTRA_LIBS}) list(APPEND TARGET_LIST ${ZIPPER_LIBRARY}-test) add_test( @@ -394,22 +402,26 @@ endif() configure_file(${CMAKE_CURRENT_SOURCE_DIR}/zipperConfig.cmake.in ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake @ONLY) +configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/zipper.pc.cmakein + ${PROJECT_BINARY_DIR}/zipper.pc + @ONLY) export(TARGETS ${TARGET_LIST} FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Targets.cmake) +set(INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files") + install(TARGETS ${TARGET_LIST} EXPORT ${PROJECT_NAME} RUNTIME DESTINATION bin COMPONENT lib LIBRARY DESTINATION lib${LIB_SUFFIX} COMPONENT lib ARCHIVE DESTINATION lib${LIB_SUFFIX} COMPONENT lib INCLUDES DESTINATION include - PUBLIC_HEADER DESTINATION include/zipper -) + PUBLIC_HEADER DESTINATION include/zipper) +install(FILES ${PROJECT_BINARY_DIR}/zipper.pc DESTINATION ${INSTALL_PKGCONFIG_DIR}) file(GLOB ZIPPER_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/zipper/*.h ${CMAKE_CURRENT_SOURCE_DIR}/minizip/*.h ) install(FILES ${ZIPPER_HEADERS} - DESTINATION include/zipper -) + DESTINATION include/zipper) install(FILES ${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake DESTINATION lib${LIB_SUFFIX}/cmake) diff --git a/README.md b/README.md index 0f00e26..e7bf5bd 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,42 @@ cmake ../ make ``` +#### Installing + +Following the previous section `Compiling`, still from the `build` folder, type: +```shell +sudo make install +``` + +You will see a message like: +``` +Install the project... +-- Install configuration: "Release" +-- Installing: /usr/local/lib/libZipper.so.1.0.1 +-- Up-to-date: /usr/local/lib/libZipper.so.1 +-- Up-to-date: /usr/local/lib/libZipper.so +-- Installing: /usr/local/lib/libZipper.a +-- Installing: /usr/local/lib/libZipper-static.a +-- Installing: /usr/local/bin/Zipper-test +-- Installing: /usr/local/share/pkgconfig/zipper.pc +-- Installing: /usr/local/bin/Zipper-test +-- Installing: /usr/local/include/zipper/crypt.h +-- Installing: /usr/local/include/zipper/ioapi.h +-- Installing: /usr/local/include/zipper/ioapi_buf.h +-- Installing: /usr/local/include/zipper/ioapi_mem.h +-- Installing: /usr/local/include/zipper/iowin32.h +-- Installing: /usr/local/include/zipper/unzip.h +-- Installing: /usr/local/include/zipper/zip.h +-- Installing: /usr/local/include/zipper/CDirEntry.h +-- Installing: /usr/local/include/zipper/defs.h +-- Installing: /usr/local/include/zipper/tools.h +-- Installing: /usr/local/include/zipper/unzipper.h +-- Installing: /usr/local/include/zipper/zipper.h +-- Installing: /usr/local/lib/cmake/zipperConfig.cmake +-- Installing: /usr/local/lib/cmake/zipperTargets.cmake +-- Installing: /usr/local/lib/cmake/zipperTargets-release.cmake +``` + ### Usage: There are two classes available Zipper and Unzipper. They behave in the same manner regarding constructors and storage parameters. (for a complete example take a look at the [tests](https://github.com/sebastiandev/zipper/blob/develop/test/file_zip_test.cpp ) using the awesome BDD's from Catch library ) @@ -152,3 +188,21 @@ unzipper.close(); ``` **Note:** Methods `extract`, `extractEntry`, `extractEntryToMemory` return a boolean indicating the success (`true`) or the failure (`false`). + +##### Linking Zipper to your project + +In your project add the needed headers in your c++ files: +```c++ +#include +#include +``` + +There are several ways to link your project against Zipper: +- Straight forward: `g++ -W -Wall -I/usr/local/include main.cpp -o prog -L/usr/local/lib/ -lZipper -lz`. Note: you may have to adapt `/usr/local` to your installation directory (see the previous section `Installing`). You can also adapt and export your environment variable `LD_LIBRARY_PATH` (via you .bashrc for example). +- Pkg-config is a better alternative to the previous command: +``` +g++ -W -Wall main.cpp -o prog `pkg-config libZipper --cflags --libs` +``` +Indeed pkg-config knows for you where to find libraries and, by default, it will choose the shared library. In the case it is not present then the static library will be chosen. You can force choosing the static library with `pkg-config libZipper --static --libs` +- Makefile: set `LDFLAGS` to `pkg-config zipper --libs` and set `CPPFLAGS` to `pkg-config zipper --cflags` +- CMake: TODO diff --git a/zipper.pc.cmakein b/zipper.pc.cmakein new file mode 100644 index 0000000..5bed1cc --- /dev/null +++ b/zipper.pc.cmakein @@ -0,0 +1,12 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@CMAKE_INSTALL_PREFIX@/lib +includedir=@CMAKE_INSTALL_PREFIX@/include + +Name: zipper +Description: C++ wrapper around minizip compression library +Version: @VERSION@ + +Requires: +Libs: -L${libdir} -l@ZIPPER_LIBRARY@ @LIBZ_LIBRARY@ +Cflags: -I${includedir} From 067ceaa8cd7739009042f903c858cb2657ac12fd Mon Sep 17 00:00:00 2001 From: Quentin Quadrat Date: Tue, 7 Jul 2020 21:11:36 +0200 Subject: [PATCH 21/86] Ticket #57: Set minimum required CMake version to 3.0 https://github.com/sebastiandev/zipper/issues/57 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ab870c..bf18daf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ ############################################################################### set(CMAKE_LEGACY_CYGWIN_WIN32 0) -cmake_minimum_required(VERSION 2.6) +cmake_minimum_required(VERSION 3.0) project(zipper) # Set useful CMake flags From 34050f0792b1217db680a42378e461ac7b3050aa Mon Sep 17 00:00:00 2001 From: Quentin Quadrat Date: Tue, 7 Jul 2020 21:12:08 +0200 Subject: [PATCH 22/86] Ticket #57: Use newer namespacing-style https://github.com/sebastiandev/zipper/issues/57 --- zipperConfig.cmake.in | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/zipperConfig.cmake.in b/zipperConfig.cmake.in index a9476d0..852f346 100644 --- a/zipperConfig.cmake.in +++ b/zipperConfig.cmake.in @@ -5,4 +5,17 @@ list(APPEND CMAKE_MODULE_PATH @CMAKE_CURRENT_SOURCE_DIR@/cmake) if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake AND NOT TARGET @GUARD_TARGET@) include(${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake) + if(NOT TARGET @PROJECT_NAME@::@PROJECT_NAME@) + if(TARGET Zipper-static) + set_target_properties(Zipper-static PROPERTIES IMPORTED_GLOBAL TRUE) + add_library(@PROJECT_NAME@::static ALIAS Zipper-static) + endif() + if(TARGET Zipper) + set_target_properties(Zipper PROPERTIES IMPORTED_GLOBAL TRUE) + add_library(@PROJECT_NAME@::shared ALIAS Zipper) + add_library(@PROJECT_NAME@::@PROJECT_NAME@ ALIAS Zipper) + elseif(TARGET Zipper-static) + add_library(@PROJECT_NAME@::@PROJECT_NAME@ ALIAS Zipper-static) + endif() + endif() endif() From 474d4ab716c795fc6dab6dda60965c1856fd5fd3 Mon Sep 17 00:00:00 2001 From: Quentin Quadrat Date: Tue, 7 Jul 2020 21:37:39 +0200 Subject: [PATCH 23/86] Ticket #56: Manage negative tellg --- zipper/unzipper.cpp | 7 ++++++- zipper/zipper.cpp | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/zipper/unzipper.cpp b/zipper/unzipper.cpp index d56c90e..520de12 100644 --- a/zipper/unzipper.cpp +++ b/zipper/unzipper.cpp @@ -367,7 +367,12 @@ namespace zipper { bool initWithStream(std::istream& stream) { stream.seekg(0, std::ios::end); - size_t size = (size_t)stream.tellg(); + std::streampos s = stream.tellg(); + if (s < 0) + { + return false; + } + size_t size = static_cast(s); stream.seekg(0); if (size > 0) diff --git a/zipper/zipper.cpp b/zipper/zipper.cpp index bd2343f..df4c7ad 100644 --- a/zipper/zipper.cpp +++ b/zipper/zipper.cpp @@ -57,7 +57,12 @@ namespace zipper { m_zipmem.grow = 1; stream.seekg(0, std::ios::end); - size_t size = (size_t)stream.tellg(); + std::streampos s = stream.tellg(); + if (s < 0) + { + return false; + } + size_t size = static_cast(s); stream.seekg(0); if (size > 0) From c14d0f23a9b92885f3d3714c2c7c9cd6cae0cb1f Mon Sep 17 00:00:00 2001 From: Quentin Quadrat Date: Tue, 7 Jul 2020 22:17:11 +0200 Subject: [PATCH 24/86] Uniformize indentation and brackets, delete trailing whitespaces --- test/file_zip_test.cpp | 324 ++++++++--------- test/main.cpp | 1 - test/memory_zip_test.cpp | 294 +++++++-------- zipper/CDirEntry.cpp | 665 ++++++++++++++++++---------------- zipper/CDirEntry.h | 40 ++- zipper/defs.h | 42 +-- zipper/tools.cpp | 133 +++---- zipper/tools.h | 27 +- zipper/tps/dirent.c | 4 +- zipper/tps/dirent.h | 4 +- zipper/unzipper.cpp | 703 ++++++++++++++++++------------------ zipper/unzipper.h | 67 ++-- zipper/zipper.cpp | 746 ++++++++++++++++++++------------------- zipper/zipper.h | 73 ++-- 14 files changed, 1616 insertions(+), 1507 deletions(-) diff --git a/test/file_zip_test.cpp b/test/file_zip_test.cpp index 3a88938..091be08 100644 --- a/test/file_zip_test.cpp +++ b/test/file_zip_test.cpp @@ -14,205 +14,205 @@ using namespace zipper; SCENARIO("zipfile feed with different inputs", "[zip]") { - GIVEN("A Zip outputed to a file") - { - // just in case the last test fails there - // will still be one zip file around delete it first - - if (checkFileExists("ziptest.zip")) - std::remove("ziptest.zip"); - - zipper::Zipper zipper("ziptest.zip"); - - WHEN("a file containing 'test file compression' is added and named 'test1'") + GIVEN("A Zip outputed to a file") { - std::ofstream test1("test1.txt"); - test1 << "test file compression"; - test1.flush(); - test1.close(); - - std::ifstream test1stream("test1.txt"); - - zipper.add(test1stream, "test1.txt"); + // just in case the last test fails there + // will still be one zip file around delete it first - test1stream.close(); - zipper.close(); + if (checkFileExists("ziptest.zip")) + std::remove("ziptest.zip"); - std::remove("test1.txt"); + zipper::Zipper zipper("ziptest.zip"); - zipper::Unzipper unzipper("ziptest.zip"); - - THEN("the zip file has one entry named 'test1.txt'") - { - std::vector entries = unzipper.entries(); - REQUIRE(entries.size() == 1); - REQUIRE(entries.front().name == "test1.txt"); - - AND_THEN("extracting the test1.txt entry creates a file named 'test1.txt' with the text 'test file compression'") + WHEN("a file containing 'test file compression' is added and named 'test1'") { - unzipper.extractEntry("test1.txt"); - // due to sections forking or creating different stacks we need to make sure the local instance is closed to - // prevent mixing the closing when both instances are freed at the end of the scope - unzipper.close(); - - REQUIRE(checkFileExists("test1.txt")); - - std::ifstream testfile("test1.txt"); - REQUIRE(testfile.good()); + std::ofstream test1("test1.txt"); + test1 << "test file compression"; + test1.flush(); + test1.close(); - std::string test((std::istreambuf_iterator(testfile)), std::istreambuf_iterator()); - testfile.close(); - REQUIRE(test == "test file compression"); + std::ifstream test1stream("test1.txt"); - AND_WHEN("another file containing 'other data to compression test' and named 'test2.dat' is added inside a folder 'TestFolder'") - { - std::ofstream test2("test2.dat"); - test2 << "other data to compression test"; - test2.flush(); - test2.close(); + zipper.add(test1stream, "test1.txt"); - std::ifstream test2stream("test2.dat"); - - zipper.open(); - zipper.add(test2stream, "TestFolder/test2.dat"); + test1stream.close(); zipper.close(); - test2stream.close(); - std::remove("test2.dat"); + std::remove("test1.txt"); zipper::Unzipper unzipper("ziptest.zip"); - AND_THEN("the zip file has two entrys named 'test1.txt' and 'TestFolder/test2.dat'") + THEN("the zip file has one entry named 'test1.txt'") { - REQUIRE(unzipper.entries().size() == 2); - REQUIRE(unzipper.entries().front().name == "test1.txt"); - REQUIRE(unzipper.entries()[1].name == "TestFolder/test2.dat"); - - AND_THEN("extracting the test2.dat entry creates a folder 'TestFolder' with a file named 'test2.dat' with the text 'other data to compression test'") - { - unzipper.extract(); - unzipper.close(); - - REQUIRE(checkFileExists("TestFolder/test2.dat")); - - std::ifstream testfile("TestFolder/test2.dat"); - REQUIRE(testfile.good()); + std::vector entries = unzipper.entries(); + REQUIRE(entries.size() == 1); + REQUIRE(entries.front().name == "test1.txt"); - std::string test((std::istreambuf_iterator(testfile)), std::istreambuf_iterator()); - testfile.close(); - REQUIRE(test == "other data to compression test"); - - AND_WHEN("adding a folder to the zip, creates one entry for each file inside the folder with the name in zip as 'Folder/...'") + AND_THEN("extracting the test1.txt entry creates a file named 'test1.txt' with the text 'test file compression'") { - makedir(currentPath() + "/TestFiles/subfolder"); - std::ofstream test("TestFiles/test1.txt"); - test << "test file compression"; - test.flush(); - test.close(); - - std::ofstream test1("TestFiles/test2.pdf"); - test1 << "test file compression"; - test1.flush(); - test1.close(); - - std::ofstream test2("TestFiles/subfolder/test-sub.txt"); - test2 << "test file compression"; - test2.flush(); - test2.close(); - - zipper.open(); - zipper.add("TestFiles"); - zipper.close(); - - zipper::Unzipper unzipper("ziptest.zip"); - REQUIRE(unzipper.entries().size() == 5); - - AND_THEN("extracting to a new folder 'NewDestination' creates the file structure from zip in the new destination folder") - { - makedir(currentPath() + "/NewDestination"); - - unzipper.extract(currentPath() + "/NewDestination"); - - std::vector files = zipper::filesFromDirectory(currentPath() + "/NewDestination"); - - REQUIRE(checkFileExists("NewDestination/TestFiles/test1.txt")); - REQUIRE(checkFileExists("NewDestination/TestFiles/test2.pdf")); - REQUIRE(checkFileExists("NewDestination/TestFiles/subfolder/test-sub.txt")); - } - - unzipper.close(); + unzipper.extractEntry("test1.txt"); + // due to sections forking or creating different stacks we need to make sure the local instance is closed to + // prevent mixing the closing when both instances are freed at the end of the scope + unzipper.close(); + + REQUIRE(checkFileExists("test1.txt")); + + std::ifstream testfile("test1.txt"); + REQUIRE(testfile.good()); + + std::string test((std::istreambuf_iterator(testfile)), std::istreambuf_iterator()); + testfile.close(); + REQUIRE(test == "test file compression"); + + AND_WHEN("another file containing 'other data to compression test' and named 'test2.dat' is added inside a folder 'TestFolder'") + { + std::ofstream test2("test2.dat"); + test2 << "other data to compression test"; + test2.flush(); + test2.close(); + + std::ifstream test2stream("test2.dat"); + + zipper.open(); + zipper.add(test2stream, "TestFolder/test2.dat"); + zipper.close(); + + test2stream.close(); + std::remove("test2.dat"); + + zipper::Unzipper unzipper("ziptest.zip"); + + AND_THEN("the zip file has two entrys named 'test1.txt' and 'TestFolder/test2.dat'") + { + REQUIRE(unzipper.entries().size() == 2); + REQUIRE(unzipper.entries().front().name == "test1.txt"); + REQUIRE(unzipper.entries()[1].name == "TestFolder/test2.dat"); + + AND_THEN("extracting the test2.dat entry creates a folder 'TestFolder' with a file named 'test2.dat' with the text 'other data to compression test'") + { + unzipper.extract(); + unzipper.close(); + + REQUIRE(checkFileExists("TestFolder/test2.dat")); + + std::ifstream testfile("TestFolder/test2.dat"); + REQUIRE(testfile.good()); + + std::string test((std::istreambuf_iterator(testfile)), std::istreambuf_iterator()); + testfile.close(); + REQUIRE(test == "other data to compression test"); + + AND_WHEN("adding a folder to the zip, creates one entry for each file inside the folder with the name in zip as 'Folder/...'") + { + makedir(currentPath() + "/TestFiles/subfolder"); + std::ofstream test("TestFiles/test1.txt"); + test << "test file compression"; + test.flush(); + test.close(); + + std::ofstream test1("TestFiles/test2.pdf"); + test1 << "test file compression"; + test1.flush(); + test1.close(); + + std::ofstream test2("TestFiles/subfolder/test-sub.txt"); + test2 << "test file compression"; + test2.flush(); + test2.close(); + + zipper.open(); + zipper.add("TestFiles"); + zipper.close(); + + zipper::Unzipper unzipper("ziptest.zip"); + REQUIRE(unzipper.entries().size() == 5); + + AND_THEN("extracting to a new folder 'NewDestination' creates the file structure from zip in the new destination folder") + { + makedir(currentPath() + "/NewDestination"); + + unzipper.extract(currentPath() + "/NewDestination"); + + std::vector files = zipper::filesFromDirectory(currentPath() + "/NewDestination"); + + REQUIRE(checkFileExists("NewDestination/TestFiles/test1.txt")); + REQUIRE(checkFileExists("NewDestination/TestFiles/test2.pdf")); + REQUIRE(checkFileExists("NewDestination/TestFiles/subfolder/test-sub.txt")); + } + + unzipper.close(); + } + } + } + + removeFolder("TestFolder"); + removeFolder("TestFiles"); + removeFolder("NewDestination"); + std::remove("test1.txt"); + } } - } } - removeFolder("TestFolder"); - removeFolder("TestFiles"); - removeFolder("NewDestination"); - std::remove("test1.txt"); - } + std::remove("ziptest.zip"); } - } - std::remove("ziptest.zip"); - } + WHEN("a stringstream containing 'test string data compression' is added and named 'strdata'") + { + std::stringstream strdata; + strdata << "test string data compression"; - WHEN("a stringstream containing 'test string data compression' is added and named 'strdata'") - { - std::stringstream strdata; - strdata << "test string data compression"; + zipper.add(strdata, "strdata"); + zipper.close(); - zipper.add(strdata, "strdata"); - zipper.close(); + zipper::Unzipper unzipper("ziptest.zip"); - zipper::Unzipper unzipper("ziptest.zip"); + THEN("the zip file has one entry named 'strdata'") + { + REQUIRE(unzipper.entries().size() == 1); + REQUIRE(unzipper.entries().front().name == "strdata"); - THEN("the zip file has one entry named 'strdata'") - { - REQUIRE(unzipper.entries().size() == 1); - REQUIRE(unzipper.entries().front().name == "strdata"); + AND_THEN("extracting the strdata entry creates a file named 'strdata' with the txt 'test string data compression'") + { + unzipper.extract(); - AND_THEN("extracting the strdata entry creates a file named 'strdata' with the txt 'test string data compression'") - { - unzipper.extract(); + REQUIRE(checkFileExists("strdata")); - REQUIRE(checkFileExists("strdata")); + std::ifstream testfile("strdata"); + REQUIRE(testfile.good()); - std::ifstream testfile("strdata"); - REQUIRE(testfile.good()); + std::string test((std::istreambuf_iterator(testfile)), std::istreambuf_iterator()); + testfile.close(); + REQUIRE(test == "test string data compression"); - std::string test((std::istreambuf_iterator(testfile)), std::istreambuf_iterator()); - testfile.close(); - REQUIRE(test == "test string data compression"); + AND_THEN("extracting with an alternative name 'alternative_strdata.dat' crates a file with that name instead of the one inside de zip") + { + std::map alt_names; + alt_names["strdata"] = "alternative_strdata.dat"; - AND_THEN("extracting with an alternative name 'alternative_strdata.dat' crates a file with that name instead of the one inside de zip") - { - std::map alt_names; - alt_names["strdata"] = "alternative_strdata.dat"; + unzipper.extract("", alt_names); - unzipper.extract("", alt_names); + REQUIRE(checkFileExists("alternative_strdata.dat")); - REQUIRE(checkFileExists("alternative_strdata.dat")); + std::ifstream testfile2("alternative_strdata.dat"); + REQUIRE(testfile2.good()); - std::ifstream testfile2("alternative_strdata.dat"); - REQUIRE(testfile2.good()); + std::string test2((std::istreambuf_iterator(testfile2)), std::istreambuf_iterator()); + testfile2.close(); + REQUIRE(test2 == "test string data compression"); - std::string test2((std::istreambuf_iterator(testfile2)), std::istreambuf_iterator()); - testfile2.close(); - REQUIRE(test2 == "test string data compression"); + AND_THEN("trying to extract a file 'fake.dat' that doesn't exists, returns false") + { + REQUIRE(false == unzipper.extractEntry("fake.dat")); + } + } - AND_THEN("trying to extract a file 'fake.dat' that doesn't exists, returns false") - { - REQUIRE(false == unzipper.extractEntry("fake.dat")); + unzipper.close(); + } } - } - unzipper.close(); + std::remove("strdata"); + std::remove("alternative_strdata.dat"); + std::remove("ziptest.zip"); } - } - - std::remove("strdata"); - std::remove("alternative_strdata.dat"); - std::remove("ziptest.zip"); } - } } diff --git a/test/main.cpp b/test/main.cpp index 178916e..0c7c351 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -1,3 +1,2 @@ #define CATCH_CONFIG_MAIN #include "catch.hpp" - diff --git a/test/memory_zip_test.cpp b/test/memory_zip_test.cpp index e728b2a..3f4e2c0 100644 --- a/test/memory_zip_test.cpp +++ b/test/memory_zip_test.cpp @@ -13,205 +13,205 @@ using namespace zipper; SCENARIO("zip vector feed with different inputs", "[zip]") { - GIVEN("A Zip outputed to a vector") - { - std::vector zipvec; - zipper::Zipper zipper(zipvec); + GIVEN("A Zip outputed to a vector") + { + std::vector zipvec; + zipper::Zipper zipper(zipvec); - WHEN("a file containing 'test file compression' is added and named 'test1'") - { - std::ofstream test1("test1.txt"); - test1 << "test file compression"; - test1.flush(); - test1.close(); + WHEN("a file containing 'test file compression' is added and named 'test1'") + { + std::ofstream test1("test1.txt"); + test1 << "test file compression"; + test1.flush(); + test1.close(); - std::ifstream test1stream("test1.txt"); + std::ifstream test1stream("test1.txt"); - zipper.add(test1stream, "test1.txt"); + zipper.add(test1stream, "test1.txt"); - test1stream.close(); - zipper.close(); + test1stream.close(); + zipper.close(); - std::remove("test1.txt"); - - zipper::Unzipper unzipper(zipvec); + std::remove("test1.txt"); - THEN("the zip vector has one entry named 'test1.txt'") - { - REQUIRE(unzipper.entries().size() == 1); - REQUIRE(unzipper.entries().front().name == "test1.txt"); + zipper::Unzipper unzipper(zipvec); - AND_THEN("extracting the test1.txt entry creates a file named 'test1.txt' with the text 'test file compression'") - { - unzipper.extractEntry("test1.txt"); - // due to sections forking or creating different stacks we need to make sure the local instance is closed to - // prevent mixing the closing when both instances are freed at the end of the scope - unzipper.close(); + THEN("the zip vector has one entry named 'test1.txt'") + { + REQUIRE(unzipper.entries().size() == 1); + REQUIRE(unzipper.entries().front().name == "test1.txt"); - REQUIRE(checkFileExists("test1.txt")); + AND_THEN("extracting the test1.txt entry creates a file named 'test1.txt' with the text 'test file compression'") + { + unzipper.extractEntry("test1.txt"); + // due to sections forking or creating different stacks we need to make sure the local instance is closed to + // prevent mixing the closing when both instances are freed at the end of the scope + unzipper.close(); - std::ifstream testfile("test1.txt"); - REQUIRE(testfile.good()); + REQUIRE(checkFileExists("test1.txt")); - std::string test((std::istreambuf_iterator(testfile)), std::istreambuf_iterator()); - testfile.close(); - REQUIRE(test == "test file compression"); + std::ifstream testfile("test1.txt"); + REQUIRE(testfile.good()); - AND_WHEN("another file containing 'other data to compression test' and named 'test2.dat' is added inside a folder 'TestFolder'") - { - std::ofstream test2("test2.dat"); - test2 << "other data to compression test"; - test2.flush(); - test2.close(); + std::string test((std::istreambuf_iterator(testfile)), std::istreambuf_iterator()); + testfile.close(); + REQUIRE(test == "test file compression"); - std::ifstream test2stream("test2.dat"); + AND_WHEN("another file containing 'other data to compression test' and named 'test2.dat' is added inside a folder 'TestFolder'") + { + std::ofstream test2("test2.dat"); + test2 << "other data to compression test"; + test2.flush(); + test2.close(); - zipper.open(); - zipper.add(test2stream, "TestFolder/test2.dat"); - zipper.close(); + std::ifstream test2stream("test2.dat"); - test2stream.close(); - std::remove("test2.dat"); + zipper.open(); + zipper.add(test2stream, "TestFolder/test2.dat"); + zipper.close(); - zipper::Unzipper unzipper(zipvec); + test2stream.close(); + std::remove("test2.dat"); - THEN("the zip vector has two entries named 'test1.txt' and 'TestFolder/test2.dat'") - { - REQUIRE(unzipper.entries().size() == 2); - REQUIRE(unzipper.entries().front().name == "test1.txt"); - REQUIRE(unzipper.entries()[1].name == "TestFolder/test2.dat"); + zipper::Unzipper unzipper(zipvec); - AND_THEN("extracting the test2.dat entry creates a folder 'TestFolder' with a file named 'test2.dat' with the text 'other data to compression test'") - { - unzipper.extract(); + THEN("the zip vector has two entries named 'test1.txt' and 'TestFolder/test2.dat'") + { + REQUIRE(unzipper.entries().size() == 2); + REQUIRE(unzipper.entries().front().name == "test1.txt"); + REQUIRE(unzipper.entries()[1].name == "TestFolder/test2.dat"); - REQUIRE(checkFileExists("TestFolder/test2.dat")); + AND_THEN("extracting the test2.dat entry creates a folder 'TestFolder' with a file named 'test2.dat' with the text 'other data to compression test'") + { + unzipper.extract(); - std::ifstream testfile("TestFolder/test2.dat"); - REQUIRE(testfile.good()); + REQUIRE(checkFileExists("TestFolder/test2.dat")); - std::string test((std::istreambuf_iterator(testfile)), std::istreambuf_iterator()); - testfile.close(); - REQUIRE(test == "other data to compression test"); + std::ifstream testfile("TestFolder/test2.dat"); + REQUIRE(testfile.good()); - AND_THEN("extracting the test2.dat entry to memory fills a vector with 'other data to compression test'") - { - std::vector resvec; - unzipper.extractEntryToMemory("TestFolder/test2.dat", resvec); - unzipper.close(); + std::string test((std::istreambuf_iterator(testfile)), std::istreambuf_iterator()); + testfile.close(); + REQUIRE(test == "other data to compression test"); - std::string test(resvec.begin(), resvec.end()); + AND_THEN("extracting the test2.dat entry to memory fills a vector with 'other data to compression test'") + { + std::vector resvec; + unzipper.extractEntryToMemory("TestFolder/test2.dat", resvec); + unzipper.close(); - REQUIRE(test == "other data to compression test"); - } + std::string test(resvec.begin(), resvec.end()); - unzipper.close(); - } - } + REQUIRE(test == "other data to compression test"); + } - std::remove("test1.txt"); - removeFolder("TestFolder"); - } - } - } + unzipper.close(); + } + } - zipvec.clear(); - } + std::remove("test1.txt"); + removeFolder("TestFolder"); + } + } + } - WHEN("a stringstream containing 'test string data compression' is added and named 'strdata'") - { - std::stringstream strdata; - strdata << "test string data compression"; + zipvec.clear(); + } - zipper.add(strdata, "strdata"); - zipper.close(); + WHEN("a stringstream containing 'test string data compression' is added and named 'strdata'") + { + std::stringstream strdata; + strdata << "test string data compression"; - zipper::Unzipper unzipper(zipvec); + zipper.add(strdata, "strdata"); + zipper.close(); - THEN("the zip vector has one entry named 'strdata'") - { - REQUIRE(unzipper.entries().size() == 1); - REQUIRE(unzipper.entries().front().name == "strdata"); + zipper::Unzipper unzipper(zipvec); - AND_THEN("extracting the strdata entry creates a file named 'strdata' with the txt 'test string data compression'") - { - unzipper.extract(); + THEN("the zip vector has one entry named 'strdata'") + { + REQUIRE(unzipper.entries().size() == 1); + REQUIRE(unzipper.entries().front().name == "strdata"); - REQUIRE(checkFileExists("strdata")); + AND_THEN("extracting the strdata entry creates a file named 'strdata' with the txt 'test string data compression'") + { + unzipper.extract(); - std::ifstream testfile("strdata"); - REQUIRE(testfile.good()); + REQUIRE(checkFileExists("strdata")); - std::string test((std::istreambuf_iterator(testfile)), std::istreambuf_iterator()); - testfile.close(); - REQUIRE(test == "test string data compression"); + std::ifstream testfile("strdata"); + REQUIRE(testfile.good()); - AND_THEN("extracting the strdata entry to memory, fills a vector with the txt 'test string data compression'") - { - std::vector resvec; - unzipper.extractEntryToMemory("strdata", resvec); - unzipper.close(); + std::string test((std::istreambuf_iterator(testfile)), std::istreambuf_iterator()); + testfile.close(); + REQUIRE(test == "test string data compression"); - std::string test(resvec.begin(), resvec.end()); + AND_THEN("extracting the strdata entry to memory, fills a vector with the txt 'test string data compression'") + { + std::vector resvec; + unzipper.extractEntryToMemory("strdata", resvec); + unzipper.close(); - REQUIRE(test == "test string data compression"); - } + std::string test(resvec.begin(), resvec.end()); - unzipper.close(); - } - } + REQUIRE(test == "test string data compression"); + } - std::remove("strdata"); - zipvec.clear(); - } + unzipper.close(); + } + } - WHEN("a file containing 'test file compression' is added and named 'test1' in subdirectory 'subdirectory'") - { - bool fileWasCreated = zipper::makedir("subdirectory"); + std::remove("strdata"); + zipvec.clear(); + } - REQUIRE(fileWasCreated); + WHEN("a file containing 'test file compression' is added and named 'test1' in subdirectory 'subdirectory'") + { + bool fileWasCreated = zipper::makedir("subdirectory"); - std::ofstream test1("./subdirectory/test1.txt"); - test1 << "test file compression"; - test1.flush(); - test1.close(); + REQUIRE(fileWasCreated); + std::ofstream test1("./subdirectory/test1.txt"); + test1 << "test file compression"; + test1.flush(); + test1.close(); - auto flags = Zipper::zipFlags::Better | Zipper::zipFlags::SaveHierarchy; - zipper.add("./subdirectory/test1.txt", static_cast(flags)); - zipper.close(); + auto flags = Zipper::zipFlags::Better | Zipper::zipFlags::SaveHierarchy; + zipper.add("./subdirectory/test1.txt", static_cast(flags)); - std::remove("./subdirectory/test1.txt"); + zipper.close(); - zipper::Unzipper unzipper(zipvec); + std::remove("./subdirectory/test1.txt"); - THEN("the zip vector has entry named './subdirectory/test1.txt'") - { - REQUIRE(unzipper.entries().size() == 1); - REQUIRE(unzipper.entries().front().name == "./subdirectory/test1.txt"); + zipper::Unzipper unzipper(zipvec); - AND_THEN("extracting the test1.txt entry creates a file named 'test1.txt' with the text 'test file compression'") - { - unzipper.extractEntry("./subdirectory/test1.txt"); - // due to sections forking or creating different stacks we need to make sure the local instance is closed to - // prevent mixing the closing when both instances are freed at the end of the scope - unzipper.close(); + THEN("the zip vector has entry named './subdirectory/test1.txt'") + { + REQUIRE(unzipper.entries().size() == 1); + REQUIRE(unzipper.entries().front().name == "./subdirectory/test1.txt"); - REQUIRE(checkFileExists("./subdirectory/test1.txt")); + AND_THEN("extracting the test1.txt entry creates a file named 'test1.txt' with the text 'test file compression'") + { + unzipper.extractEntry("./subdirectory/test1.txt"); + // due to sections forking or creating different stacks we need to make sure the local instance is closed to + // prevent mixing the closing when both instances are freed at the end of the scope + unzipper.close(); - std::ifstream testfile("./subdirectory/test1.txt"); - REQUIRE(testfile.good()); + REQUIRE(checkFileExists("./subdirectory/test1.txt")); - std::string test((std::istreambuf_iterator(testfile)), std::istreambuf_iterator()); - testfile.close(); - REQUIRE(test == "test file compression"); + std::ifstream testfile("./subdirectory/test1.txt"); + REQUIRE(testfile.good()); - removeFolder("subdirectory"); - } - } + std::string test((std::istreambuf_iterator(testfile)), std::istreambuf_iterator()); + testfile.close(); + REQUIRE(test == "test file compression"); - zipvec.clear(); - } - } + removeFolder("subdirectory"); + } + } + + zipvec.clear(); + } + } } diff --git a/zipper/CDirEntry.cpp b/zipper/CDirEntry.cpp index 5f6c4e4..45976ed 100644 --- a/zipper/CDirEntry.cpp +++ b/zipper/CDirEntry.cpp @@ -1,41 +1,41 @@ +// ----------------------------------------------------------------------------- // Copyright (C) 2010 - 2014 by Pedro Mendes, Virginia Tech Intellectual // Properties, Inc., University of Heidelberg, and The University // of Manchester. // All rights reserved. - +// // Copyright (C) 2008 - 2009 by Pedro Mendes, Virginia Tech Intellectual // Properties, Inc., EML Research, gGmbH, University of Heidelberg, // and The University of Manchester. // All rights reserved. - +// // Copyright (C) 2005 - 2007 by Pedro Mendes, Virginia Tech Intellectual // Properties, Inc. and EML Research, gGmbH. // All rights reserved. +// ----------------------------------------------------------------------------- #include #include #include #ifdef WIN32 -# include -# include +# include +# include typedef struct _stat STAT; -# define stat _stat -# define S_IFREG _S_IFREG -# define S_IFDIR _S_IFDIR -# define access _access -# define mkdir _mkdir -# define rmdir _rmdir +# define stat _stat +# define S_IFREG _S_IFREG +# define S_IFDIR _S_IFDIR +# define access _access +# define mkdir _mkdir +# define rmdir _rmdir #else typedef struct stat STAT; -# include -# include +# include +# include #endif // WIN32 #include "CDirEntry.h" - #include - #include using namespace zipper; @@ -46,577 +46,652 @@ const std::string CDirEntry::Separator = "\\"; const std::string CDirEntry::Separator = "/"; #endif +// ----------------------------------------------------------------------------- bool CDirEntry::isFile(const std::string & path) { - STAT st; + STAT st; - if (stat(path.c_str(), & st) == -1) return false; + if (stat(path.c_str(), & st) == -1) + return false; #ifdef WIN32 - return ((st.st_mode & S_IFREG) == S_IFREG); + return ((st.st_mode & S_IFREG) == S_IFREG); #else - return S_ISREG(st.st_mode); + return S_ISREG(st.st_mode); #endif } +// ----------------------------------------------------------------------------- bool CDirEntry::isDir(const std::string & path) { - STAT st; + STAT st; - if (stat(path.c_str(), & st) == -1) return false; + if (stat(path.c_str(), & st) == -1) + return false; #ifdef WIN32 - return ((st.st_mode & S_IFDIR) == S_IFDIR); + return ((st.st_mode & S_IFDIR) == S_IFDIR); #else - return S_ISDIR(st.st_mode); + return S_ISDIR(st.st_mode); #endif } +// ----------------------------------------------------------------------------- bool CDirEntry::exist(const std::string & path) { - STAT st; + STAT st; - if (stat(path.c_str(), & st) == -1) return false; + if (stat(path.c_str(), & st) == -1) + return false; #ifdef WIN32 - return ((st.st_mode & S_IFREG) == S_IFREG || - (st.st_mode & S_IFDIR) == S_IFDIR); + return ((st.st_mode & S_IFREG) == S_IFREG || + (st.st_mode & S_IFDIR) == S_IFDIR); #else - return (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)); + return (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)); #endif } +// ----------------------------------------------------------------------------- bool CDirEntry::isReadable(const std::string & path) -{return (access(path.c_str(), 0x4) == 0);} +{ + return (access(path.c_str(), 0x4) == 0); +} +// ----------------------------------------------------------------------------- bool CDirEntry::isWritable(const std::string & path) -{return (access(path.c_str(), 0x2) == 0);} +{ + return (access(path.c_str(), 0x2) == 0); +} +// ----------------------------------------------------------------------------- std::string CDirEntry::baseName(const std::string & path) { - std::string::size_type start = path.find_last_of(Separator); -#ifdef WIN32 // WIN32 also understands '/' as the separator. - - if (start == std::string::npos) - start = path.find_last_of("/"); + std::string::size_type start = path.find_last_of(Separator); +#ifdef WIN32 // WIN32 also understands '/' as the separator. + if (start == std::string::npos) + { + start = path.find_last_of("/"); + } #endif - if (start == std::string::npos) start = 0; - else start++; // We do not want the separator. + if (start == std::string::npos) + { + start = 0; + } + else + { + start++; // We do not want the separator. + } - std::string::size_type end = path.find_last_of("."); + std::string::size_type end = path.find_last_of("."); - if (end == std::string::npos || end < start) - end = path.length(); + if (end == std::string::npos || end < start) + { + end = path.length(); + } - return path.substr(start, end - start); + return path.substr(start, end - start); } +// ----------------------------------------------------------------------------- std::string CDirEntry::fileName(const std::string & path) { - std::string::size_type start = path.find_last_of(Separator); -#ifdef WIN32 // WIN32 also understands '/' as the separator. - - if (start == std::string::npos) - start = path.find_last_of("/"); + std::string::size_type start = path.find_last_of(Separator); +#ifdef WIN32 // WIN32 also understands '/' as the separator. + if (start == std::string::npos) + { + start = path.find_last_of("/"); + } #endif - if (start == std::string::npos) start = 0; - else start++; // We do not want the separator. + if (start == std::string::npos) + { + start = 0; + } + else + { + start++; // We do not want the separator. + } - return path.substr(start); + return path.substr(start); } +// ----------------------------------------------------------------------------- std::string CDirEntry::dirName(const std::string & path) { - if (path == "") return path; + if (path == "") + return path; #ifdef WIN32 // WIN32 also understands '/' as the separator. - std::string::size_type end = path.find_last_of(Separator + "/"); + std::string::size_type end = path.find_last_of(Separator + "/"); #else - std::string::size_type end = path.find_last_of(Separator); + std::string::size_type end = path.find_last_of(Separator); #endif - if (end == path.length() - 1) + if (end == path.length() - 1) { #ifdef WIN32 // WIN32 also understands '/' as the separator. - end = path.find_last_of(Separator + "/", end); + end = path.find_last_of(Separator + "/", end); #else - end = path.find_last_of(Separator, end); + end = path.find_last_of(Separator, end); #endif } - if (end == std::string::npos) return ""; + if (end == std::string::npos) + return {}; - return path.substr(0, end); + return path.substr(0, end); } +// ----------------------------------------------------------------------------- std::string CDirEntry::suffix(const std::string & path) { - std::string::size_type start = path.find_last_of(Separator); -#ifdef WIN32 // WIN32 also understands '/' as the separator. - - if (start == std::string::npos) - start = path.find_last_of("/"); + std::string::size_type start = path.find_last_of(Separator); +#ifdef WIN32 // WIN32 also understands '/' as the separator. + if (start == std::string::npos) + { + start = path.find_last_of("/"); + } #endif - if (start == std::string::npos) start = 0; - else start++; // We do not want the separator. + if (start == std::string::npos) + { + start = 0; + } + else + { + start++; // We do not want the separator. + } + + std::string::size_type end = path.find_last_of("."); - std::string::size_type end = path.find_last_of("."); + if (end == std::string::npos || end < start) + return {}; - if (end == std::string::npos || end < start) - return ""; - else return path.substr(end); } -bool CDirEntry::createDir(const std::string & dir, - const std::string & parent) +// ----------------------------------------------------------------------------- +bool CDirEntry::createDir(const std::string & dir, const std::string & parent) { - std::string Dir; + std::string Dir; - if (parent != "") Dir = parent + Separator; + if (parent != "") + { + Dir = parent + Separator; + } - Dir += dir; + Dir += dir; - // Check whether the directory already exists and is writable. - if (isDir(Dir) && isWritable(Dir)) return true; + // Check whether the directory already exists and is writable. + if (isDir(Dir) && isWritable(Dir)) + return true; - // Check whether the parent directory exists and is writable. - if (!parent.empty() && (!isDir(parent) || !isWritable(parent))) return false; + // Check whether the parent directory exists and is writable. + if (!parent.empty() && (!isDir(parent) || !isWritable(parent))) + return false; - Dir = normalize(Dir); + Dir = normalize(Dir); - // ensure we have parent - std::string actualParent = dirName(Dir); + // ensure we have parent + std::string actualParent = dirName(Dir); - if (!actualParent.empty() && (!exist(actualParent))) - createDir(actualParent); + if (!actualParent.empty() && (!exist(actualParent))) + { + createDir(actualParent); + } #ifdef WIN32 - return (mkdir(Dir.c_str()) == 0); + return (mkdir(Dir.c_str()) == 0); #else - return (mkdir(Dir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0); + return (mkdir(Dir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0); #endif } -std::string CDirEntry::createTmpName(const std::string & dir, - const std::string & suffix) +// ----------------------------------------------------------------------------- +std::string CDirEntry::createTmpName(const std::string & dir, const std::string & suffix) { - std::string RandomName; + std::string RandomName; - do + do { - RandomName = dir + Separator; - unsigned int Char; + RandomName = dir + Separator; + unsigned int Char; - for (size_t i = 0; i < 8; i++) + for (size_t i = 0; i < 8; i++) { - Char = int((rand()/double(RAND_MAX))*35.0); + Char = int((rand()/double(RAND_MAX))*35.0); - if (Char < 10) - RandomName += '0' + Char; - else - RandomName += 'a' - 10 + Char; + if (Char < 10) + { + RandomName += '0' + Char; + } + else + { + RandomName += 'a' - 10 + Char; + } } - RandomName += suffix; + RandomName += suffix; } - while (exist(RandomName)); + while (exist(RandomName)); - return RandomName; + return RandomName; } -bool CDirEntry::move(const std::string & from, - const std::string & to) +// ----------------------------------------------------------------------------- +bool CDirEntry::move(const std::string & from, const std::string & to) { - if (!isFile(from)) return false; + if (!isFile(from)) + return false; - std::string To = to; + std::string To = to; - // Check whether To is a directory and append the - // filename of from - if (isDir(To)) - To += Separator + fileName(from); + // Check whether To is a directory and append the + // filename of from + if (isDir(To)) + To += Separator + fileName(from); - if (isDir(To)) return false; + if (isDir(To)) + return false; #ifdef WIN32 - // The target must not exist under WIN32 for rename to succeed. - if (exist(To) && !remove(To)) - return false; + // The target must not exist under WIN32 for rename to succeed. + if (exist(To) && !remove(To)) + return false; #endif // WIN32 - bool success = - (::rename(from.c_str(), To.c_str()) == 0); + bool success = + (::rename(from.c_str(), To.c_str()) == 0); - if (!success) + if (!success) { - { - std::ifstream in(from.c_str()); - std::ofstream out(To.c_str()); + { + std::ifstream in(from.c_str()); + std::ofstream out(To.c_str()); - out << in.rdbuf(); + out << in.rdbuf(); - success = out.good(); - } + success = out.good(); + } - remove(from); + remove(from); } - return success; + return success; } +// ----------------------------------------------------------------------------- bool CDirEntry::remove(const std::string & path) { - if (isDir(path)) - return (rmdir(path.c_str()) == 0); - else if (isFile(path)) + if (isDir(path)) + return (rmdir(path.c_str()) == 0); + else if (isFile(path)) #ifdef WIN32 - return (::remove(path.c_str()) == 0); - + return (::remove(path.c_str()) == 0); #else - return (::remove(path.c_str()) == 0); + return (::remove(path.c_str()) == 0); #endif - return false; + return false; } +// ----------------------------------------------------------------------------- bool CDirEntry::removeFiles(const std::string & pattern, const std::string & path) { - bool success = true; - std::vector< std::string > PatternList; + bool success = true; + std::vector< std::string > PatternList; - PatternList = compilePattern(pattern); + PatternList = compilePattern(pattern); #ifdef WIN32 - // We want the same pattern matching behaviour for all platforms. - // Therefore, we do not use the MS provided one and list all files instead. - std::string FilePattern = path + "\\*"; + // We want the same pattern matching behaviour for all platforms. + // Therefore, we do not use the MS provided one and list all files instead. + std::string FilePattern = path + "\\*"; - // Open directory stream and try read info about first entry - struct _finddata_t Entry; - intptr_t hList = _findfirst(FilePattern.c_str(), &Entry); + // Open directory stream and try read info about first entry + struct _finddata_t Entry; + intptr_t hList = _findfirst(FilePattern.c_str(), &Entry); - if (hList == -1) return success; + if (hList == -1) + return success; - do + do { - std::string Utf8 = Entry.name; + std::string Utf8 = Entry.name; - if (match(Utf8, PatternList)) + if (match(Utf8, PatternList)) { - if (Entry.attrib | _A_NORMAL) + if (Entry.attrib | _A_NORMAL) { -#ifdef WIN32 - - if (::remove((path + Separator + Utf8).c_str()) != 0) success = false; - -#else - - if (::remove((path + Separator + Utf8).c_str()) != 0) success = false; - -#endif + if (::remove((path + Separator + Utf8).c_str()) != 0) + success = false; } - else + else { - if (rmdir((path + Separator + Utf8).c_str()) != 0) success = false; + if (rmdir((path + Separator + Utf8).c_str()) != 0) + success = false; } } } - while (_findnext(hList, &Entry) == 0); + while (_findnext(hList, &Entry) == 0); - _findclose(hList); + _findclose(hList); #else - DIR * pDir = opendir(path.c_str()); + DIR * pDir = opendir(path.c_str()); - if (!pDir) return false; + if (!pDir) return false; - struct dirent * pEntry; + struct dirent * pEntry; - while ((pEntry = readdir(pDir)) != NULL) + while ((pEntry = readdir(pDir)) != NULL) { - std::string Utf8 = pEntry->d_name; + std::string Utf8 = pEntry->d_name; - if (match(Utf8, PatternList)) + if (match(Utf8, PatternList)) { - if (isDir(Utf8)) + if (isDir(Utf8)) { - if (::rmdir((path + Separator + Utf8).c_str()) != 0) - success = false; + if (::rmdir((path + Separator + Utf8).c_str()) != 0) + success = false; } - else + else { - if (::remove((path + Separator + Utf8).c_str()) != 0) - success = false; + if (::remove((path + Separator + Utf8).c_str()) != 0) + success = false; } } } - closedir(pDir); + closedir(pDir); #endif // WIN32 - return success; + return success; } +// ----------------------------------------------------------------------------- std::vector< std::string > CDirEntry::compilePattern(const std::string & pattern) { - std::string::size_type pos = 0; - std::string::size_type start = 0; - std::string::size_type end = 0; - std::vector< std::string > PatternList; + std::string::size_type pos = 0; + std::string::size_type start = 0; + std::string::size_type end = 0; + std::vector< std::string > PatternList; - while (pos != std::string::npos) + while (pos != std::string::npos) { - start = pos; - pos = pattern.find_first_of("*?", pos); + start = pos; + pos = pattern.find_first_of("*?", pos); - end = std::min(pos, pattern.length()); + end = std::min(pos, pattern.length()); - if (start != end) - PatternList.push_back(pattern.substr(start, end - start)); - else + if (start != end) { - PatternList.push_back(pattern.substr(start, 1)); - pos++; + PatternList.push_back(pattern.substr(start, end - start)); + } + else + { + PatternList.push_back(pattern.substr(start, 1)); + pos++; } }; - return PatternList; + return PatternList; } +// ----------------------------------------------------------------------------- bool CDirEntry::match(const std::string & name, const std::vector< std::string > & patternList) { - std::vector< std::string >::const_iterator it = patternList.begin(); - std::vector< std::string >::const_iterator end = patternList.end(); - std::string::size_type at = 0; - std::string::size_type after = 0; + std::vector< std::string >::const_iterator it = patternList.begin(); + std::vector< std::string >::const_iterator end = patternList.end(); + std::string::size_type at = 0; + std::string::size_type after = 0; - bool Match = true; + bool Match = true; - while (it != end && Match) - Match = matchInternal(name, *it++, at, after); + while (it != end && Match) + { + Match = matchInternal(name, *it++, at, after); + } - return Match; + return Match; } +// ----------------------------------------------------------------------------- bool CDirEntry::isRelativePath(const std::string & path) { #ifdef WIN32 - std::string Path = normalize(path); + std::string Path = normalize(path); - if (Path.length() < 2) - return true; + if (Path.length() < 2) + return true; - if (Path[1] == ':') - return false; + if (Path[1] == ':') + return false; - if (Path[0] == '/' && Path[1] == '/') - return false; + if (Path[0] == '/' && Path[1] == '/') + return false; - return true; + return true; #else - return (path.length() < 1 || path[0] != '/'); + return (path.length() < 1 || path[0] != '/'); #endif } -bool CDirEntry::makePathRelative(std::string & absolutePath, - const std::string & relativeTo) +// ----------------------------------------------------------------------------- +bool CDirEntry::makePathRelative(std::string & absolutePath, const std::string & relativeTo) { - if (isRelativePath(absolutePath) || - isRelativePath(relativeTo)) return false; // Nothing can be done. + if (isRelativePath(absolutePath) || isRelativePath(relativeTo)) + return false; // Nothing can be done. - std:: string RelativeTo = normalize(relativeTo); + std:: string RelativeTo = normalize(relativeTo); - if (isFile(RelativeTo)) RelativeTo = dirName(RelativeTo); + if (isFile(RelativeTo)) + RelativeTo = dirName(RelativeTo); - if (!isDir(RelativeTo)) return false; + if (!isDir(RelativeTo)) + return false; - absolutePath = normalize(absolutePath); + absolutePath = normalize(absolutePath); - size_t i, imax = std::min(absolutePath.length(), RelativeTo.length()); + size_t i, imax = std::min(absolutePath.length(), RelativeTo.length()); - for (i = 0; i < imax; i++) - if (absolutePath[i] != RelativeTo[i]) break; + for (i = 0; i < imax; i++) + { + if (absolutePath[i] != RelativeTo[i]) + break; + } - // We need to retract to the beginning of the current directory. - if (i != imax) - i = absolutePath.find_last_of('/', i) + 1; + // We need to retract to the beginning of the current directory. + if (i != imax) + { + i = absolutePath.find_last_of('/', i) + 1; + } #ifdef WIN32 - if (i == 0) return false; // A different drive letter we cannot do anything + if (i == 0) + { + return false; // A different drive letter we cannot do anything + } #endif - RelativeTo = RelativeTo.substr(i); + RelativeTo = RelativeTo.substr(i); - std::string relativePath; + std::string relativePath; - while (RelativeTo != "") + while (RelativeTo != "") { - relativePath += "../"; - RelativeTo = dirName(RelativeTo); + relativePath += "../"; + RelativeTo = dirName(RelativeTo); } - if (relativePath != "") - absolutePath = relativePath + absolutePath.substr(i); - else - absolutePath = absolutePath.substr(i + 1); + if (relativePath != "") + { + absolutePath = relativePath + absolutePath.substr(i); + } + else + { + absolutePath = absolutePath.substr(i + 1); + } - return true; + return true; } -bool CDirEntry::makePathAbsolute(std::string & relativePath, - const std::string & absoluteTo) +// ----------------------------------------------------------------------------- +bool CDirEntry::makePathAbsolute(std::string & relativePath, const std::string & absoluteTo) { - if (!isRelativePath(relativePath) || - isRelativePath(absoluteTo)) return false; // Nothing can be done. + if (!isRelativePath(relativePath) || isRelativePath(absoluteTo)) + return false; // Nothing can be done. - std:: string AbsoluteTo = normalize(absoluteTo); + std:: string AbsoluteTo = normalize(absoluteTo); - if (isFile(AbsoluteTo)) AbsoluteTo = dirName(AbsoluteTo); + if (isFile(AbsoluteTo)) + AbsoluteTo = dirName(AbsoluteTo); - if (!isDir(AbsoluteTo)) return false; + if (!isDir(AbsoluteTo)) + return false; - relativePath = normalize(relativePath); + relativePath = normalize(relativePath); - while (!relativePath.compare(0, 3, "../")) + while (!relativePath.compare(0, 3, "../")) { - AbsoluteTo = dirName(AbsoluteTo); - relativePath = relativePath.substr(3); + AbsoluteTo = dirName(AbsoluteTo); + relativePath = relativePath.substr(3); } - relativePath = AbsoluteTo + "/" + relativePath; + relativePath = AbsoluteTo + "/" + relativePath; - return true; + return true; } +// ----------------------------------------------------------------------------- bool CDirEntry::matchInternal(const std::string & name, const std::string pattern, std::string::size_type & at, std::string::size_type & after) { - bool Match = true; + bool Match = true; - switch (pattern[0]) + switch (pattern[0]) { - case '*': - + case '*': if (at != std::string::npos) - { + { after = at; at = std::string::npos; - } - + } break; - case '?': - + case '?': if (at != std::string::npos) - { + { ++at; Match = (name.length() >= at); - } + } else - { + { ++after; Match = (name.length() >= after); - } - + } break; - default: - + default: if (at != std::string::npos) - { + { Match = (name.compare(at, pattern.length(), pattern) == 0); at += pattern.length(); - } + } else - { + { at = name.find(pattern, after); Match = (at != std::string::npos); at += pattern.length(); - } - + } break; } - return Match; + return Match; } +// ----------------------------------------------------------------------------- std::string CDirEntry::normalize(const std::string & path) { - std::string Normalized = path; + std::string Normalized = path; #ifdef WIN32 - // converts all '\' to '/' (only on WIN32) - size_t i, imax; + // converts all '\' to '/' (only on WIN32) + size_t i, imax; - for (i = 0, imax = Normalized.length(); i < imax; i++) - if (Normalized[i] == '\\') Normalized[i] = '/'; + for (i = 0, imax = Normalized.length(); i < imax; i++) + { + if (Normalized[i] == '\\') + Normalized[i] = '/'; + } #endif - // Remove leading './' - while (!Normalized.compare(0, 2, "./")) - Normalized = Normalized.substr(2); + // Remove leading './' + while (!Normalized.compare(0, 2, "./")) + { + Normalized = Normalized.substr(2); + } - // Collapse '//' to '/' - std::string::size_type pos = 1; + // Collapse '//' to '/' + std::string::size_type pos = 1; - while (true) + while (true) { - pos = Normalized.find("//", pos); - - if (pos == std::string::npos) break; + pos = Normalized.find("//", pos); + if (pos == std::string::npos) + break; - Normalized.erase(pos, 1); + Normalized.erase(pos, 1); } - // Collapse '/./' to '/' - pos = 0; + // Collapse '/./' to '/' + pos = 0; - while (true) + while (true) { - pos = Normalized.find("/./", pos); + pos = Normalized.find("/./", pos); + if (pos == std::string::npos) + break; - if (pos == std::string::npos) break; - - Normalized.erase(pos, 2); + Normalized.erase(pos, 2); } - // Collapse '[^/]+/../' to '/' - std::string::size_type start = Normalized.length(); + // Collapse '[^/]+/../' to '/' + std::string::size_type start = Normalized.length(); - while (true) + while (true) { - pos = Normalized.rfind("/../", start); - - if (pos == std::string::npos) break; - - start = Normalized.rfind('/', pos - 1); + pos = Normalized.rfind("/../", start); + if (pos == std::string::npos) + break; - if (start == std::string::npos) break; + start = Normalized.rfind('/', pos - 1); + if (start == std::string::npos) + break; - if (!Normalized.compare(start, 4, "/../")) continue; + if (!Normalized.compare(start, 4, "/../")) + continue; - Normalized.erase(start, pos - start + 3); - start = Normalized.length(); + Normalized.erase(start, pos - start + 3); + start = Normalized.length(); } - return Normalized; + return Normalized; } diff --git a/zipper/CDirEntry.h b/zipper/CDirEntry.h index 9c1ae0c..df2e19c 100644 --- a/zipper/CDirEntry.h +++ b/zipper/CDirEntry.h @@ -15,13 +15,14 @@ namespace zipper { - /** - * This class provides an OS independent interface to directory entries - * such as files and directories. - */ - class CDirEntry - { - public: +/** + * This class provides an OS independent interface to directory entries + * such as files and directories. + */ +class CDirEntry +{ +public: + /** * The character used to separate directory entries. */ @@ -104,7 +105,7 @@ namespace zipper * @return bool success */ static bool createDir(const std::string & dir, - const std::string & parent = ""); + const std::string & parent = ""); /** * Create a name for a temporary directory entry. The directory entry @@ -114,7 +115,7 @@ namespace zipper * @return std::string tmpName */ static std::string createTmpName(const std::string & dir, - const std::string & suffix); + const std::string & suffix); /** * Move a file from. If to is the directory the filename of from is @@ -124,7 +125,7 @@ namespace zipper * @return bool success */ static bool move(const std::string & from, - const std::string & to); + const std::string & to); /** * Removes a file or directory specified by path. @@ -140,7 +141,7 @@ namespace zipper * @return bool success */ static bool removeFiles(const std::string & pattern, - const std::string & dir); + const std::string & dir); /** * Compiles the pattern to a patternList. Valid wildcards in the pattern are: @@ -159,7 +160,7 @@ namespace zipper * @return bool match */ static bool match(const std::string & name, - const std::vector< std::string > & patternList); + const std::vector< std::string > & patternList); /** * Checks whether the given path is relative @@ -174,7 +175,7 @@ namespace zipper * @return bool success */ static bool makePathRelative(std::string & absolutePath, - const std::string & relativeTo); + const std::string & relativeTo); /** * Makes the relative path absolute to the path given in absoluteTo @@ -183,7 +184,7 @@ namespace zipper * @return bool success */ static bool makePathAbsolute(std::string & relativePath, - const std::string & absoluteTo); + const std::string & absoluteTo); /** * This method normalizes the path, i.e., @@ -194,7 +195,8 @@ namespace zipper */ static std::string normalize(const std::string & path); - private: +private: + /** * This private methods checks whether the active section matches the * specified patter. The section is automatically advanced to allow @@ -207,9 +209,9 @@ namespace zipper * @return bool match */ static bool matchInternal(const std::string & name, - const std::string pattern, - std::string::size_type & at, - std::string::size_type & after); - }; + const std::string pattern, + std::string::size_type & at, + std::string::size_type & after); +}; } #endif // ZIPPER_CDirEntry diff --git a/zipper/defs.h b/zipper/defs.h index d89036c..a0ee07e 100644 --- a/zipper/defs.h +++ b/zipper/defs.h @@ -11,11 +11,11 @@ extern "C" #include #if (defined(_WIN32)) || (defined(_WIN64)) -# include -# include +# include +# include #else -# include -# include +# include +# include #endif #include @@ -26,35 +26,35 @@ extern "C" #define MAXFILENAME (256) #if (defined(_WIN32)) || (defined(_WIN64)) -#define USEWIN32IOAPI -#include "iowin32.h" +# define USEWIN32IOAPI +# include "iowin32.h" #endif } #if (defined(_WIN32)) || (defined(_WIN64)) - #include +# include #endif #if (defined(_WIN32)) || (defined(_WIN64)) - #define EXCEPTION_CLASS std::exception +# define EXCEPTION_CLASS std::exception #else - #define EXCEPTION_CLASS std::runtime_error +# define EXCEPTION_CLASS std::runtime_error #endif #if (defined(_WIN64)) && (!defined(__APPLE__)) -#ifndef __USE_FILE_OFFSET64 -#define __USE_FILE_OFFSET64 -#endif -#ifndef __USE_LARGEFILE64 -#define __USE_LARGEFILE64 -#endif -#ifndef _LARGEFILE64_SOURCE -#define _LARGEFILE64_SOURCE -#endif -#ifndef _FILE_OFFSET_BIT -#define _FILE_OFFSET_BIT 64 -#endif +# ifndef __USE_FILE_OFFSET64 +# define __USE_FILE_OFFSET64 +# endif +# ifndef __USE_LARGEFILE64 +# define __USE_LARGEFILE64 +# endif +# ifndef _LARGEFILE64_SOURCE +# define _LARGEFILE64_SOURCE +# endif +# ifndef _FILE_OFFSET_BIT +# define _FILE_OFFSET_BIT 64 +# endif #endif #if (defined(_WIN32)) || (defined(_WIN64)) diff --git a/zipper/tools.cpp b/zipper/tools.cpp index e1b8205..8995d27 100644 --- a/zipper/tools.cpp +++ b/zipper/tools.cpp @@ -17,94 +17,98 @@ # include #endif /* WIN32 */ - - namespace zipper { - /* calculate the CRC32 of a file, - because to encrypt a file, we need known the CRC32 of the file before */ - - void getFileCrc(std::istream& input_stream, std::vector& buff, unsigned long& result_crc) - { +// ----------------------------------------------------------------------------- +// Calculate the CRC32 of a file because to encrypt a file, we need known the +// CRC32 of the file before. +void getFileCrc(std::istream& input_stream, std::vector& buff, unsigned long& result_crc) +{ unsigned long calculate_crc = 0; unsigned long size_read = 0; unsigned long total_read = 0; do { - input_stream.read(buff.data(), buff.size()); - size_read = (unsigned long)input_stream.gcount(); + input_stream.read(buff.data(), buff.size()); + size_read = (unsigned long)input_stream.gcount(); - if (size_read > 0) - calculate_crc = crc32(calculate_crc, (const unsigned char*)buff.data(), size_read); + if (size_read > 0) + calculate_crc = crc32(calculate_crc, (const unsigned char*)buff.data(), size_read); - total_read += size_read; + total_read += size_read; } while (size_read > 0); input_stream.clear(); input_stream.seekg(0, std::ios_base::beg); result_crc = calculate_crc; - } +} - bool isLargeFile(std::istream& input_stream) - { +// ----------------------------------------------------------------------------- +bool isLargeFile(std::istream& input_stream) +{ ZPOS64_T pos = 0; input_stream.seekg(0, std::ios::end); pos = input_stream.tellg(); input_stream.seekg(0); return pos >= 0xffffffff; - } +} - bool checkFileExists(const std::string& filename) - { +// ----------------------------------------------------------------------------- +bool checkFileExists(const std::string& filename) +{ return CDirEntry::exist(filename); - } +} - bool makedir(const std::string& newdir) - { +// ----------------------------------------------------------------------------- +bool makedir(const std::string& newdir) +{ return CDirEntry::createDir(newdir); - } +} - void removeFolder(const std::string& foldername) - { +// ----------------------------------------------------------------------------- +void removeFolder(const std::string& foldername) +{ if (!CDirEntry::remove(foldername)) { - std::vector files = filesFromDirectory(foldername); - std::vector::iterator it = files.begin(); - for (; it != files.end(); ++it) - { - if (isDirectory(*it) && *it != foldername) - removeFolder(*it); - else - std::remove(it->c_str()); - } - CDirEntry::remove(foldername); + std::vector files = filesFromDirectory(foldername); + std::vector::iterator it = files.begin(); + for (; it != files.end(); ++it) + { + if (isDirectory(*it) && *it != foldername) + removeFolder(*it); + else + std::remove(it->c_str()); + } + CDirEntry::remove(foldername); } - } +} - bool isDirectory(const std::string& path) - { +// ----------------------------------------------------------------------------- +bool isDirectory(const std::string& path) +{ return CDirEntry::isDir(path); - } +} - std::string parentDirectory(const std::string& filepath) - { +// ----------------------------------------------------------------------------- +std::string parentDirectory(const std::string& filepath) +{ return CDirEntry::dirName(filepath); - } +} - std::string currentPath() - { +// ----------------------------------------------------------------------------- +std::string currentPath() +{ char buffer[1024]; getcwd(buffer, 1024); std::string result(buffer); return result; +} - } - - - std::vector filesFromDirectory(const std::string& path) - { +// ----------------------------------------------------------------------------- +std::vector filesFromDirectory(const std::string& path) +{ std::vector files; DIR* dir; struct dirent* entry; @@ -112,36 +116,35 @@ namespace zipper { dir = opendir(path.c_str()); if (dir == NULL) - { - return files; - } + return files; for (entry = readdir(dir); entry != NULL; entry = readdir(dir)) { - std::string filename(entry->d_name); + std::string filename(entry->d_name); - if (filename == "." || filename == "..") continue; + if (filename == "." || filename == "..") continue; - if (CDirEntry::isDir(path + CDirEntry::Separator + filename)) - { - std::vector moreFiles = filesFromDirectory(path + CDirEntry::Separator + filename); - std::copy(moreFiles.begin(), moreFiles.end(), std::back_inserter(files)); - continue; - } + if (CDirEntry::isDir(path + CDirEntry::Separator + filename)) + { + std::vector moreFiles = filesFromDirectory(path + CDirEntry::Separator + filename); + std::copy(moreFiles.begin(), moreFiles.end(), std::back_inserter(files)); + continue; + } - files.push_back(path + CDirEntry::Separator + filename); + files.push_back(path + CDirEntry::Separator + filename); } closedir(dir); return files; - } +} - std::string fileNameFromPath(const std::string& fullPath) - { +// ----------------------------------------------------------------------------- +std::string fileNameFromPath(const std::string& fullPath) +{ return CDirEntry::fileName(fullPath); - } - } + +} // namespace zipper diff --git a/zipper/tools.h b/zipper/tools.h index 5d0ab63..05bc674 100644 --- a/zipper/tools.h +++ b/zipper/tools.h @@ -4,17 +4,18 @@ #include #include - -namespace zipper +namespace zipper { - void getFileCrc(std::istream& input_stream, std::vector& buff, unsigned long& result_crc); - bool isLargeFile(std::istream& input_stream); - bool checkFileExists(const std::string& filename); - bool makedir(const std::string& newdir); - void removeFolder(const std::string& foldername); - std::string parentDirectory(const std::string& filepath); - std::string currentPath(); - bool isDirectory(const std::string& path); - std::vector filesFromDirectory(const std::string& path); - std::string fileNameFromPath(const std::string& path); -} + +void getFileCrc(std::istream& input_stream, std::vector& buff, unsigned long& result_crc); +bool isLargeFile(std::istream& input_stream); +bool checkFileExists(const std::string& filename); +bool makedir(const std::string& newdir); +void removeFolder(const std::string& foldername); +std::string parentDirectory(const std::string& filepath); +std::string currentPath(); +bool isDirectory(const std::string& path); +std::vector filesFromDirectory(const std::string& path); +std::string fileNameFromPath(const std::string& path); + +} // namespace zipper diff --git a/zipper/tps/dirent.c b/zipper/tps/dirent.c index 6319512..a6c9871 100644 --- a/zipper/tps/dirent.c +++ b/zipper/tps/dirent.c @@ -11,11 +11,11 @@ * Copyright 2002-2005, Matthew Wilson and Synesis Software * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. + * list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. diff --git a/zipper/tps/dirent.h b/zipper/tps/dirent.h index 4703aa2..4e73b94 100644 --- a/zipper/tps/dirent.h +++ b/zipper/tps/dirent.h @@ -12,11 +12,11 @@ * Copyright 2002-2005, Matthew Wilson and Synesis Software * All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * - Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. + * list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. diff --git a/zipper/unzipper.cpp b/zipper/unzipper.cpp index 520de12..a0a4513 100644 --- a/zipper/unzipper.cpp +++ b/zipper/unzipper.cpp @@ -10,219 +10,219 @@ namespace zipper { - struct Unzipper::Impl - { +struct Unzipper::Impl +{ Unzipper& m_outer; zipFile m_zf; ourmemory_t m_zipmem; zlib_filefunc_def m_filefunc; - private: +private: bool initMemory(zlib_filefunc_def& filefunc) { - m_zf = unzOpen2("__notused__", &filefunc); - return m_zf != NULL; + m_zf = unzOpen2("__notused__", &filefunc); + return m_zf != NULL; } bool locateEntry(const std::string& name) { - return UNZ_OK == unzLocateFile(m_zf, name.c_str(), NULL); + return UNZ_OK == unzLocateFile(m_zf, name.c_str(), NULL); } ZipEntry currentEntryInfo() { - unz_file_info64 file_info = { 0 }; - char filename_inzip[256] = { 0 }; + unz_file_info64 file_info = { 0 }; + char filename_inzip[256] = { 0 }; - int err = unzGetCurrentFileInfo64(m_zf, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0); - if (UNZ_OK != err) - throw EXCEPTION_CLASS("Error, couln't get the current entry info"); + int err = unzGetCurrentFileInfo64(m_zf, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0); + if (UNZ_OK != err) + throw EXCEPTION_CLASS("Error, couln't get the current entry info"); - return ZipEntry(std::string(filename_inzip), file_info.compressed_size, file_info.uncompressed_size, - file_info.tmu_date.tm_year, file_info.tmu_date.tm_mon, file_info.tmu_date.tm_mday, - file_info.tmu_date.tm_hour, file_info.tmu_date.tm_min, file_info.tmu_date.tm_sec, file_info.dosDate); + return ZipEntry(std::string(filename_inzip), file_info.compressed_size, file_info.uncompressed_size, + file_info.tmu_date.tm_year, file_info.tmu_date.tm_mon, file_info.tmu_date.tm_mday, + file_info.tmu_date.tm_hour, file_info.tmu_date.tm_min, file_info.tmu_date.tm_sec, file_info.dosDate); } #if 0 // lambda as a parameter https://en.wikipedia.org/wiki/C%2B%2B11#Polymorphic_wrappers_for_function_objects void iterEntries(std::function callback) { - int err = unzGoToFirstFile(m_zf); - if (UNZ_OK == err) - { - do + int err = unzGoToFirstFile(m_zf); + if (UNZ_OK == err) { - ZipEntry entryinfo = currentEntryInfo(); - - if (entryinfo.valid()) - { - callback(entryinfo); - err = unzGoToNextFile(m_zf); - } - else - err = UNZ_ERRNO; - - } while (UNZ_OK == err); - - if (UNZ_END_OF_LIST_OF_FILE != err && UNZ_OK != err) - return; - } + do + { + ZipEntry entryinfo = currentEntryInfo(); + + if (entryinfo.valid()) + { + callback(entryinfo); + err = unzGoToNextFile(m_zf); + } + else + err = UNZ_ERRNO; + + } while (UNZ_OK == err); + + if (UNZ_END_OF_LIST_OF_FILE != err && UNZ_OK != err) + return; + } } #endif void getEntries(std::vector& entries) { - int err = unzGoToFirstFile(m_zf); - if (UNZ_OK == err) - { - do + int err = unzGoToFirstFile(m_zf); + if (UNZ_OK == err) { - ZipEntry entryinfo = currentEntryInfo(); - - if (entryinfo.valid()) - { - entries.push_back(entryinfo); - err = unzGoToNextFile(m_zf); - } - else - err = UNZ_ERRNO; - - } while (UNZ_OK == err); - - if (UNZ_END_OF_LIST_OF_FILE != err && UNZ_OK != err) - return; - } + do + { + ZipEntry entryinfo = currentEntryInfo(); + + if (entryinfo.valid()) + { + entries.push_back(entryinfo); + err = unzGoToNextFile(m_zf); + } + else + err = UNZ_ERRNO; + + } while (UNZ_OK == err); + + if (UNZ_END_OF_LIST_OF_FILE != err && UNZ_OK != err) + return; + } } - public: +public: #if 0 bool extractCurrentEntry(ZipEntry& entryinfo, int (extractStrategy)(ZipEntry&) ) { - int err = UNZ_OK; + int err = UNZ_OK; - if (!entryinfo.valid()) - return false; + if (!entryinfo.valid()) + return false; - err = extractStrategy(entryinfo); - if (UNZ_OK == err) - { - err = unzCloseCurrentFile(m_zf); - if (UNZ_OK != err) - throw EXCEPTION_CLASS(("Error " + std::to_string(err) + " closing internal file '" + entryinfo.name + - "' in zip").c_str()); - } + err = extractStrategy(entryinfo); + if (UNZ_OK == err) + { + err = unzCloseCurrentFile(m_zf); + if (UNZ_OK != err) + throw EXCEPTION_CLASS(("Error " + std::to_string(err) + " closing internal file '" + entryinfo.name + + "' in zip").c_str()); + } - return UNZ_OK == err; + return UNZ_OK == err; } #endif bool extractCurrentEntryToFile(ZipEntry& entryinfo, const std::string& fileName) { - int err = UNZ_OK; + int err = UNZ_OK; - if (!entryinfo.valid()) - return false; + if (!entryinfo.valid()) + return false; - err = extractToFile(fileName, entryinfo); - if (UNZ_OK == err) - { - err = unzCloseCurrentFile(m_zf); - if (UNZ_OK != err) + err = extractToFile(fileName, entryinfo); + if (UNZ_OK == err) { - std::stringstream str; - str << "Error " << err << " openinginternal file '" - << entryinfo.name << "' in zip"; - - throw EXCEPTION_CLASS(str.str().c_str()); + err = unzCloseCurrentFile(m_zf); + if (UNZ_OK != err) + { + std::stringstream str; + str << "Error " << err << " openinginternal file '" + << entryinfo.name << "' in zip"; + + throw EXCEPTION_CLASS(str.str().c_str()); + } } - } - return UNZ_OK == err; + return UNZ_OK == err; } bool extractCurrentEntryToStream(ZipEntry& entryinfo, std::ostream& stream) { - int err = UNZ_OK; + int err = UNZ_OK; - if (!entryinfo.valid()) - return false; + if (!entryinfo.valid()) + return false; - err = extractToStream(stream, entryinfo); - if (UNZ_OK == err) - { - err = unzCloseCurrentFile(m_zf); - if (UNZ_OK != err) + err = extractToStream(stream, entryinfo); + if (UNZ_OK == err) { - std::stringstream str; - str << "Error " << err << " opening internal file '" - << entryinfo.name << "' in zip"; - - throw EXCEPTION_CLASS(str.str().c_str()); + err = unzCloseCurrentFile(m_zf); + if (UNZ_OK != err) + { + std::stringstream str; + str << "Error " << err << " opening internal file '" + << entryinfo.name << "' in zip"; + + throw EXCEPTION_CLASS(str.str().c_str()); + } } - } - return UNZ_OK == err; + return UNZ_OK == err; } bool extractCurrentEntryToMemory(ZipEntry& entryinfo, std::vector& outvec) { - int err = UNZ_OK; + int err = UNZ_OK; - if (!entryinfo.valid()) - return false; + if (!entryinfo.valid()) + return false; - err = extractToMemory(outvec, entryinfo); - if (UNZ_OK == err) - { - err = unzCloseCurrentFile(m_zf); - if (UNZ_OK != err) + err = extractToMemory(outvec, entryinfo); + if (UNZ_OK == err) { - std::stringstream str; - str << "Error " << err << " opening internal file '" - << entryinfo.name << "' in zip"; - - throw EXCEPTION_CLASS(str.str().c_str()); + err = unzCloseCurrentFile(m_zf); + if (UNZ_OK != err) + { + std::stringstream str; + str << "Error " << err << " opening internal file '" + << entryinfo.name << "' in zip"; + + throw EXCEPTION_CLASS(str.str().c_str()); + } } - } - return UNZ_OK == err; + return UNZ_OK == err; } void changeFileDate(const std::string& filename, uLong dosdate, tm_unz tmu_date) { #ifdef _WIN32 - HANDLE hFile; - FILETIME ftm, ftLocal, ftCreate, ftLastAcc, ftLastWrite; - - hFile = CreateFileA(filename.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); - if (hFile != INVALID_HANDLE_VALUE) - { - GetFileTime(hFile, &ftCreate, &ftLastAcc, &ftLastWrite); - DosDateTimeToFileTime((WORD)(dosdate >> 16), (WORD)dosdate, &ftLocal); - LocalFileTimeToFileTime(&ftLocal, &ftm); - SetFileTime(hFile, &ftm, &ftLastAcc, &ftm); - CloseHandle(hFile); - } + HANDLE hFile; + FILETIME ftm, ftLocal, ftCreate, ftLastAcc, ftLastWrite; + + hFile = CreateFileA(filename.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); + if (hFile != INVALID_HANDLE_VALUE) + { + GetFileTime(hFile, &ftCreate, &ftLastAcc, &ftLastWrite); + DosDateTimeToFileTime((WORD)(dosdate >> 16), (WORD)dosdate, &ftLocal); + LocalFileTimeToFileTime(&ftLocal, &ftm); + SetFileTime(hFile, &ftm, &ftLastAcc, &ftm); + CloseHandle(hFile); + } #else #if defined unix || defined __APPLE__ - struct utimbuf ut; - struct tm newdate; - - newdate.tm_sec = tmu_date.tm_sec; - newdate.tm_min = tmu_date.tm_min; - newdate.tm_hour = tmu_date.tm_hour; - newdate.tm_mday = tmu_date.tm_mday; - newdate.tm_mon = tmu_date.tm_mon; - if (tmu_date.tm_year > 1900) - newdate.tm_year = tmu_date.tm_year - 1900; - else - newdate.tm_year = tmu_date.tm_year; - newdate.tm_isdst = -1; - - ut.actime = ut.modtime = mktime(&newdate); - utime(filename.c_str(), &ut); + struct utimbuf ut; + struct tm newdate; + + newdate.tm_sec = tmu_date.tm_sec; + newdate.tm_min = tmu_date.tm_min; + newdate.tm_hour = tmu_date.tm_hour; + newdate.tm_mday = tmu_date.tm_mday; + newdate.tm_mon = tmu_date.tm_mon; + if (tmu_date.tm_year > 1900) + newdate.tm_year = tmu_date.tm_year - 1900; + else + newdate.tm_year = tmu_date.tm_year; + newdate.tm_isdst = -1; + + ut.actime = ut.modtime = mktime(&newdate); + utime(filename.c_str(), &ut); #endif #endif } @@ -230,300 +230,300 @@ namespace zipper { int extractToFile(const std::string& filename, ZipEntry& info) { - int err = UNZ_ERRNO; + int err = UNZ_ERRNO; - /* If zip entry is a directory then create it on disk */ - makedir(parentDirectory(filename)); + /* If zip entry is a directory then create it on disk */ + makedir(parentDirectory(filename)); - /* Create the file on disk so we can unzip to it */ - std::ofstream output_file(filename.c_str(), std::ofstream::binary); + /* Create the file on disk so we can unzip to it */ + std::ofstream output_file(filename.c_str(), std::ofstream::binary); - if (output_file.good()) - { - if (UNZ_OK == extractToStream(output_file, info)) - err = UNZ_OK; + if (output_file.good()) + { + if (UNZ_OK == extractToStream(output_file, info)) + err = UNZ_OK; - output_file.close(); + output_file.close(); - /* Set the time of the file that has been unzipped */ - tm_unz timeaux; - memcpy(&timeaux, &info.unixdate, sizeof(timeaux)); + /* Set the time of the file that has been unzipped */ + tm_unz timeaux; + memcpy(&timeaux, &info.unixdate, sizeof(timeaux)); - changeFileDate(filename, info.dosdate, timeaux); - } - else - output_file.close(); + changeFileDate(filename, info.dosdate, timeaux); + } + else + output_file.close(); - return err; + return err; } int extractToStream(std::ostream& stream, ZipEntry& info) { - size_t err = unzOpenCurrentFilePassword(m_zf, m_outer.m_password.c_str()); - if (UNZ_OK != err) - { - std::stringstream str; - str << "Error " << err << " opening internal file '" - << info.name << "' in zip"; - - throw EXCEPTION_CLASS(str.str().c_str()); - } - - std::vector buffer; - buffer.resize(WRITEBUFFERSIZE); - - do - { - err = unzReadCurrentFile(m_zf, buffer.data(), (unsigned int)buffer.size()); - if (err < 0 || err == 0) - break; - - stream.write(buffer.data(), err); - if (!stream.good()) + size_t err = unzOpenCurrentFilePassword(m_zf, m_outer.m_password.c_str()); + if (UNZ_OK != err) { - err = UNZ_ERRNO; - break; + std::stringstream str; + str << "Error " << err << " opening internal file '" + << info.name << "' in zip"; + + throw EXCEPTION_CLASS(str.str().c_str()); } - } while (err > 0); + std::vector buffer; + buffer.resize(WRITEBUFFERSIZE); - stream.flush(); + do + { + err = unzReadCurrentFile(m_zf, buffer.data(), (unsigned int)buffer.size()); + if (err < 0 || err == 0) + break; - return (int)err; + stream.write(buffer.data(), err); + if (!stream.good()) + { + err = UNZ_ERRNO; + break; + } + + } while (err > 0); + + stream.flush(); + + return (int)err; } int extractToMemory(std::vector& outvec, ZipEntry& info) { - size_t err = UNZ_ERRNO; + size_t err = UNZ_ERRNO; - err = unzOpenCurrentFilePassword(m_zf, m_outer.m_password.c_str()); - if (UNZ_OK != err) - { - std::stringstream str; - str << "Error " << err << " opening internal file '" - << info.name << "' in zip"; + err = unzOpenCurrentFilePassword(m_zf, m_outer.m_password.c_str()); + if (UNZ_OK != err) + { + std::stringstream str; + str << "Error " << err << " opening internal file '" + << info.name << "' in zip"; - throw EXCEPTION_CLASS(str.str().c_str()); - } + throw EXCEPTION_CLASS(str.str().c_str()); + } - std::vector buffer; - buffer.resize(WRITEBUFFERSIZE); + std::vector buffer; + buffer.resize(WRITEBUFFERSIZE); - outvec.reserve((size_t)info.uncompressedSize); + outvec.reserve((size_t)info.uncompressedSize); - do - { - err = unzReadCurrentFile(m_zf, buffer.data(), (unsigned int)buffer.size()); - if (err < 0 || err == 0) - break; + do + { + err = unzReadCurrentFile(m_zf, buffer.data(), (unsigned int)buffer.size()); + if (err < 0 || err == 0) + break; - outvec.insert(outvec.end(), buffer.data(), buffer.data() + err); + outvec.insert(outvec.end(), buffer.data(), buffer.data() + err); - } while (err > 0); + } while (err > 0); - return (int)err; + return (int)err; } - public: +public: Impl(Unzipper& outer) : m_outer(outer), m_zipmem(), m_filefunc() { - m_zipmem.base = NULL; - m_zf = NULL; + m_zipmem.base = NULL; + m_zf = NULL; } ~Impl() { - close(); + close(); } void close() { - if (m_zf != NULL) - { - unzClose(m_zf); - m_zf = NULL; - } + if (m_zf != NULL) + { + unzClose(m_zf); + m_zf = NULL; + } - if (m_zipmem.base != NULL) - { - free(m_zipmem.base); - m_zipmem.base = NULL; - } + if (m_zipmem.base != NULL) + { + free(m_zipmem.base); + m_zipmem.base = NULL; + } } bool initFile(const std::string& filename) { #ifdef USEWIN32IOAPI - zlib_filefunc64_def ffunc; - fill_win32_filefunc64A(&ffunc); - m_zf = unzOpen2_64(filename.c_str(), &ffunc); + zlib_filefunc64_def ffunc; + fill_win32_filefunc64A(&ffunc); + m_zf = unzOpen2_64(filename.c_str(), &ffunc); #else - m_zf = unzOpen64(filename.c_str()); + m_zf = unzOpen64(filename.c_str()); #endif - return m_zf != NULL; + return m_zf != NULL; } bool initWithStream(std::istream& stream) { - stream.seekg(0, std::ios::end); - std::streampos s = stream.tellg(); - if (s < 0) - { - return false; - } - size_t size = static_cast(s); - stream.seekg(0); - - if (size > 0) - { - m_zipmem.base = new char[(size_t)size]; - m_zipmem.size = (uLong)size; - stream.read(m_zipmem.base, size); - } - - fill_memory_filefunc(&m_filefunc, &m_zipmem); - - return initMemory(m_filefunc); + stream.seekg(0, std::ios::end); + std::streampos s = stream.tellg(); + if (s < 0) + { + return false; + } + size_t size = static_cast(s); + stream.seekg(0); + + if (size > 0) + { + m_zipmem.base = new char[(size_t)size]; + m_zipmem.size = (uLong)size; + stream.read(m_zipmem.base, size); + } + + fill_memory_filefunc(&m_filefunc, &m_zipmem); + + return initMemory(m_filefunc); } bool initWithVector(std::vector& buffer) { - if (!buffer.empty()) - { - m_zipmem.base = (char*) malloc (buffer.size() * sizeof (char)); - memcpy(m_zipmem.base, (char*) buffer.data(), buffer.size()); - m_zipmem.size = (uLong)buffer.size(); - } + if (!buffer.empty()) + { + m_zipmem.base = (char*) malloc (buffer.size() * sizeof (char)); + memcpy(m_zipmem.base, (char*) buffer.data(), buffer.size()); + m_zipmem.size = (uLong)buffer.size(); + } - fill_memory_filefunc(&m_filefunc, &m_zipmem); + fill_memory_filefunc(&m_filefunc, &m_zipmem); - return initMemory(m_filefunc); + return initMemory(m_filefunc); } std::vector entries() { - std::vector entrylist; - getEntries(entrylist); - return entrylist; + std::vector entrylist; + getEntries(entrylist); + return entrylist; } - + bool extractAll(const std::string& destination, const std::map& alternativeNames) { - std::vector entries; - getEntries(entries); - std::vector::iterator it = entries.begin(); - for (; it != entries.end(); ++it) - { - if (!locateEntry(it->name)) - continue; - - std::string alternativeName = destination.empty() ? "" : destination + CDirEntry::Separator; - - if (alternativeNames.find(it->name) != alternativeNames.end()) - alternativeName += alternativeNames.at(it->name); - else - alternativeName += it->name; + std::vector entries; + getEntries(entries); + std::vector::iterator it = entries.begin(); + for (; it != entries.end(); ++it) + { + if (!locateEntry(it->name)) + continue; - this->extractCurrentEntryToFile(*it, alternativeName); - }; + std::string alternativeName = destination.empty() ? "" : destination + CDirEntry::Separator; - return true; + if (alternativeNames.find(it->name) != alternativeNames.end()) + alternativeName += alternativeNames.at(it->name); + else + alternativeName += it->name; + + this->extractCurrentEntryToFile(*it, alternativeName); + }; + + return true; } bool extractEntry(const std::string& name, const std::string& destination) { - std::string outputFile = destination.empty() ? name : destination + CDirEntry::Separator + name; - - if (locateEntry(name)) - { - ZipEntry entry = currentEntryInfo(); - return extractCurrentEntryToFile(entry, outputFile); - } - else - { - return false; - } + std::string outputFile = destination.empty() ? name : destination + CDirEntry::Separator + name; + + if (locateEntry(name)) + { + ZipEntry entry = currentEntryInfo(); + return extractCurrentEntryToFile(entry, outputFile); + } + else + { + return false; + } } bool extractEntryToStream(const std::string& name, std::ostream& stream) { - if (locateEntry(name)) - { - ZipEntry entry = currentEntryInfo(); - return extractCurrentEntryToStream(entry, stream); - } - else - { - return false; - } + if (locateEntry(name)) + { + ZipEntry entry = currentEntryInfo(); + return extractCurrentEntryToStream(entry, stream); + } + else + { + return false; + } } bool extractEntryToMemory(const std::string& name, std::vector& vec) { - if (locateEntry(name)) - { - ZipEntry entry = currentEntryInfo(); - return extractCurrentEntryToMemory(entry, vec); - } - else - { - return false; - } + if (locateEntry(name)) + { + ZipEntry entry = currentEntryInfo(); + return extractCurrentEntryToMemory(entry, vec); + } + else + { + return false; + } } - }; +}; - Unzipper::Unzipper(std::istream& zippedBuffer) +Unzipper::Unzipper(std::istream& zippedBuffer) : m_ibuffer(zippedBuffer) , m_vecbuffer(*(new std::vector())) //not used but using local variable throws exception , m_usingMemoryVector(false) , m_usingStream(true) , m_impl(new Impl(*this)) - { +{ if (!m_impl->initWithStream(m_ibuffer)) - { + { release(); throw EXCEPTION_CLASS("Error loading zip in memory!"); - } + } m_open = true; - } +} - Unzipper::Unzipper(std::vector& zippedBuffer) +Unzipper::Unzipper(std::vector& zippedBuffer) : m_ibuffer(*(new std::stringstream())) //not used but using local variable throws exception , m_vecbuffer(zippedBuffer) , m_usingMemoryVector(true) , m_usingStream(false) , m_impl(new Impl(*this)) - { +{ if (!m_impl->initWithVector(m_vecbuffer)) - { + { release(); throw EXCEPTION_CLASS("Error loading zip in memory!"); - } + } m_open = true; - } +} - Unzipper::Unzipper(const std::string& zipname) +Unzipper::Unzipper(const std::string& zipname) : m_ibuffer(*(new std::stringstream())) //not used but using local variable throws exception , m_vecbuffer(*(new std::vector())) //not used but using local variable throws exception , m_zipname(zipname) , m_usingMemoryVector(false) , m_usingStream(false) , m_impl(new Impl(*this)) - { +{ if (!m_impl->initFile(zipname)) - { + { release(); throw EXCEPTION_CLASS("Error loading zip file!"); - } + } m_open = true; - } +} - Unzipper::Unzipper(const std::string& zipname, const std::string& password) +Unzipper::Unzipper(const std::string& zipname, const std::string& password) : m_ibuffer(*(new std::stringstream())) //not used but using local variable throws exception , m_vecbuffer(*(new std::vector())) //not used but using local variable throws exception , m_zipname(zipname) @@ -531,74 +531,73 @@ namespace zipper { , m_usingMemoryVector(false) , m_usingStream(false) , m_impl(new Impl(*this)) - { +{ if (!m_impl->initFile(zipname)) - { + { release(); throw EXCEPTION_CLASS("Error loading zip file!"); - } + } m_open = true; - } +} - Unzipper::~Unzipper() - { +Unzipper::~Unzipper() +{ close(); release(); - } +} - std::vector Unzipper::entries() - { +std::vector Unzipper::entries() +{ return m_impl->entries(); - } +} - bool Unzipper::extractEntry(const std::string& name, const std::string& destination) - { +bool Unzipper::extractEntry(const std::string& name, const std::string& destination) +{ return m_impl->extractEntry(name, destination); - } +} - bool Unzipper::extractEntryToStream(const std::string& name, std::ostream& stream) - { +bool Unzipper::extractEntryToStream(const std::string& name, std::ostream& stream) +{ return m_impl->extractEntryToStream(name, stream); - } +} - bool Unzipper::extractEntryToMemory(const std::string& name, std::vector& vec) - { +bool Unzipper::extractEntryToMemory(const std::string& name, std::vector& vec) +{ return m_impl->extractEntryToMemory(name, vec); - } +} - bool Unzipper::extract(const std::string& destination, const std::map& alternativeNames) - { +bool Unzipper::extract(const std::string& destination, const std::map& alternativeNames) +{ return m_impl->extractAll(destination, alternativeNames); - } +} - bool - Unzipper::extract(const std::string& destination) - { +bool +Unzipper::extract(const std::string& destination) +{ return m_impl->extractAll(destination, std::map()); - } +} - void Unzipper::release() - { +void Unzipper::release() +{ if (!m_usingMemoryVector) { - delete &m_vecbuffer; + delete &m_vecbuffer; } if (!m_usingStream) { - delete &m_ibuffer; + delete &m_ibuffer; } delete m_impl; - } +} - void Unzipper::close() - { +void Unzipper::close() +{ if (m_open) { - m_impl->close(); - m_open = false; + m_impl->close(); + m_open = false; } - } - } +} // namespace zipper diff --git a/zipper/unzipper.h b/zipper/unzipper.h index 1c837b7..f509184 100644 --- a/zipper/unzipper.h +++ b/zipper/unzipper.h @@ -9,12 +9,12 @@ #include namespace zipper { - - class ZipEntry; - class Unzipper - { - public: +class ZipEntry; + +class Unzipper +{ +public: Unzipper(std::istream& buffer); Unzipper(std::vector& buffer); Unzipper(const std::string& zipname); @@ -32,7 +32,7 @@ namespace zipper { void close(); - private: +private: void release(); std::string m_password; std::string m_zipname; @@ -44,39 +44,39 @@ namespace zipper { struct Impl; Impl* m_impl; - }; +}; - class ZipEntry - { - private: +class ZipEntry +{ +private: typedef struct { - unsigned int tm_sec; - unsigned int tm_min; - unsigned int tm_hour; - unsigned int tm_mday; - unsigned int tm_mon; - unsigned int tm_year; + unsigned int tm_sec; + unsigned int tm_min; + unsigned int tm_hour; + unsigned int tm_mday; + unsigned int tm_mon; + unsigned int tm_year; } tm_s; - public: +public: ZipEntry(const std::string& name, unsigned long long int compressed_size, unsigned long long int uncompressed_size, - int year, int month, int day, int hour, int minute, int second, unsigned long dosdate) - : name(name), compressedSize(compressed_size), uncompressedSize(uncompressed_size), dosdate(dosdate) + int year, int month, int day, int hour, int minute, int second, unsigned long dosdate) + : name(name), compressedSize(compressed_size), uncompressedSize(uncompressed_size), dosdate(dosdate) { - // timestamp YYYY-MM-DD HH:MM:SS - std::stringstream str; - str << year << "-" << month << "-" << day << - " " << hour << ":" << minute << ":" << second; - timestamp = str.str(); - - unixdate.tm_year = year; - unixdate.tm_mon = month; - unixdate.tm_mday = day; - unixdate.tm_hour = hour; - unixdate.tm_min = minute; - unixdate.tm_sec = second; + // timestamp YYYY-MM-DD HH:MM:SS + std::stringstream str; + str << year << "-" << month << "-" << day << + " " << hour << ":" << minute << ":" << second; + timestamp = str.str(); + + unixdate.tm_year = year; + unixdate.tm_mon = month; + unixdate.tm_mday = day; + unixdate.tm_hour = hour; + unixdate.tm_min = minute; + unixdate.tm_sec = second; } bool valid() { return !name.empty(); } @@ -85,5 +85,6 @@ namespace zipper { unsigned long long int compressedSize, uncompressedSize; unsigned long dosdate; tm_s unixdate; - }; -} +}; + +} // namespace zipper diff --git a/zipper/zipper.cpp b/zipper/zipper.cpp index df4c7ad..6ac2d31 100644 --- a/zipper/zipper.cpp +++ b/zipper/zipper.cpp @@ -8,371 +8,397 @@ namespace zipper { - struct Zipper::Impl - { - Zipper& m_outer; - zipFile m_zf; - ourmemory_t m_zipmem; - zlib_filefunc_def m_filefunc; - - Impl(Zipper& outer) : m_outer(outer), m_zipmem(), m_filefunc() - { - m_zf = NULL; - m_zipmem.base = NULL; - //m_filefunc = { 0 }; - } - - ~Impl() - { - close(); - } - - bool initFile(const std::string& filename) - { - #ifdef USEWIN32IOAPI - zlib_filefunc64_def ffunc = { 0 }; - #endif - - int mode = 0; - int flags = Zipper::Append; - - /* open the zip file for output */ - if (checkFileExists(filename)) - mode = (flags & Zipper::Overwrite) ? APPEND_STATUS_CREATE : APPEND_STATUS_ADDINZIP; - else - mode = APPEND_STATUS_CREATE; - - #ifdef USEWIN32IOAPI - fill_win32_filefunc64A(&ffunc); - m_zf = zipOpen2_64(filename.c_str(), mode, NULL, &ffunc); - #else - m_zf = zipOpen64(filename.c_str(), mode); - #endif - - return NULL != m_zf; - } - - bool initWithStream(std::iostream& stream) - { - m_zipmem.grow = 1; - - stream.seekg(0, std::ios::end); - std::streampos s = stream.tellg(); - if (s < 0) - { - return false; - } - size_t size = static_cast(s); - stream.seekg(0); - - if (size > 0) - { - if (m_zipmem.base != NULL) { free(m_zipmem.base); } - m_zipmem.base = (char*) malloc (size * sizeof (char)); - stream.read(m_zipmem.base, size); - } - - fill_memory_filefunc(&m_filefunc, &m_zipmem); - - return initMemory(size > 0 ? APPEND_STATUS_CREATE : APPEND_STATUS_ADDINZIP, m_filefunc); - } - - bool initWithVector(std::vector& buffer) - { - m_zipmem.grow = 1; - - if (!buffer.empty()) - { - if (m_zipmem.base != NULL) { free(m_zipmem.base); } - m_zipmem.base = (char*) malloc (buffer.size() * sizeof (char)); - memcpy(m_zipmem.base, (char*) buffer.data(), buffer.size()); - m_zipmem.size = (uLong)buffer.size(); - } - - fill_memory_filefunc(&m_filefunc, &m_zipmem); - - return initMemory(buffer.empty() ? APPEND_STATUS_CREATE : APPEND_STATUS_ADDINZIP, m_filefunc); - } - - bool initMemory(int mode, zlib_filefunc_def& filefunc) - { - m_zf = zipOpen3("__notused__", mode, 0, 0, &filefunc); - return m_zf != NULL; - } - - bool add(std::istream& input_stream, const std::tm& timestamp, const std::string& nameInZip, const std::string& password, int flags) - { - if (!m_zf) return false; - - int compressLevel = 0; - int zip64 = 0; - int size_buf = WRITEBUFFERSIZE; - int err = ZIP_OK; - unsigned long crcFile = 0; - - zip_fileinfo zi = { 0 }; - zi.tmz_date.tm_sec = timestamp.tm_sec; - zi.tmz_date.tm_min = timestamp.tm_min; - zi.tmz_date.tm_hour = timestamp.tm_hour; - zi.tmz_date.tm_mday = timestamp.tm_mday; - zi.tmz_date.tm_mon = timestamp.tm_mon; - zi.tmz_date.tm_year = timestamp.tm_year; - - size_t size_read; - - std::vector buff; - buff.resize(size_buf); - - if (nameInZip.empty()) - return false; - - if (flags & Zipper::Faster) compressLevel = 1; - if (flags & Zipper::Better) compressLevel = 9; - - zip64 = (int)isLargeFile(input_stream); - if (password.empty()) - err = zipOpenNewFileInZip64(m_zf, - nameInZip.c_str(), - &zi, - NULL, - 0, - NULL, - 0, - NULL /* comment*/, - (compressLevel != 0) ? Z_DEFLATED : 0, - compressLevel, - zip64); - else - { - getFileCrc(input_stream, buff, crcFile); - err = zipOpenNewFileInZip3_64(m_zf, - nameInZip.c_str(), - &zi, - NULL, - 0, - NULL, - 0, - NULL /* comment*/, - (compressLevel != 0) ? Z_DEFLATED : 0, - compressLevel, - 0, - /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */ - -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, - password.c_str(), - crcFile, - zip64); - } - - if (ZIP_OK == err) - { - do { - err = ZIP_OK; - input_stream.read(buff.data(), buff.size()); - size_read = (size_t)input_stream.gcount(); - if (size_read < buff.size() && !input_stream.eof() && !input_stream.good()) - err = ZIP_ERRNO; - - if (size_read > 0) - err = zipWriteInFileInZip(this->m_zf, buff.data(), (unsigned int)size_read); - - } while ((err == ZIP_OK) && (size_read>0)); - } - else - throw EXCEPTION_CLASS(("Error adding '" + nameInZip + "' to zip").c_str()); - - if (ZIP_OK == err) - err = zipCloseFileInZip(this->m_zf); - - return ZIP_OK == err; - } - - void close() - { - if (m_zf != NULL) - { - zipClose(m_zf, NULL); - m_zf = NULL; - } - - if (m_zipmem.base && m_zipmem.limit > 0) - { - if (m_outer.m_usingMemoryVector) - { - m_outer.m_vecbuffer.resize(m_zipmem.limit); - m_outer.m_vecbuffer.assign(m_zipmem.base, m_zipmem.base + m_zipmem.limit); - } - - else if (m_outer.m_usingStream) - m_outer.m_obuffer.write(m_zipmem.base, m_zipmem.limit); - } - - if (m_zipmem.base != NULL) - { - free(m_zipmem.base); - m_zipmem.base = NULL; - } - } - }; - - /////////////////////////////////////////////////////////////////////////////// - /////////////////////////////////////////////////////////////////////////////// - - Zipper::Zipper(const std::string& zipname) - : m_obuffer(*(new std::stringstream())) //not used but using local variable throws exception - , m_vecbuffer(*(new std::vector())) //not used but using local variable throws exception - , m_usingMemoryVector(false) - , m_usingStream(false) - , m_zipname(zipname) - , m_impl(new Impl(*this)) - { - if (!m_impl->initFile(zipname)) - { - release(); - throw EXCEPTION_CLASS("Error creating zip in file!"); - } - m_open = true; - } - - Zipper::Zipper(const std::string& zipname, const std::string& password) - : m_obuffer(*(new std::stringstream())) //not used but using local variable throws exception - , m_vecbuffer(*(new std::vector())) //not used but using local variable throws exception - , m_usingMemoryVector(false) - , m_usingStream(false) - , m_zipname(zipname) - , m_password(password) - , m_impl(new Impl(*this)) - { - if (!m_impl->initFile(zipname)) - { - release(); - throw EXCEPTION_CLASS("Error creating zip in file!"); - } - m_open = true; - } - - Zipper::Zipper(std::iostream& buffer) - : m_vecbuffer(*(new std::vector())) //not used but using local variable throws exception - , m_obuffer(buffer) - , m_usingMemoryVector(false) - , m_usingStream(true) - , m_impl(new Impl(*this)) - { - if (!m_impl->initWithStream(m_obuffer)) - { - release(); - throw EXCEPTION_CLASS("Error creating zip in memory!"); - } - m_open = true; - } - - Zipper::Zipper(std::vector& buffer) - : m_vecbuffer(buffer) - , m_obuffer(*(new std::stringstream())) //not used but using local variable throws exception - , m_usingMemoryVector(true) - , m_usingStream(false) - , m_impl(new Impl(*this)) - { - if (!m_impl->initWithVector(m_vecbuffer)) - { - release(); - throw EXCEPTION_CLASS("Error creating zip in memory!"); - } - m_open = true; - } - - Zipper::~Zipper() - { - close(); - release(); +struct Zipper::Impl +{ + Zipper& m_outer; + zipFile m_zf; + ourmemory_t m_zipmem; + zlib_filefunc_def m_filefunc; + + Impl(Zipper& outer) : m_outer(outer), m_zipmem(), m_filefunc() + { + m_zf = NULL; + m_zipmem.base = NULL; + //m_filefunc = { 0 }; + } + + ~Impl() + { + close(); + } + + bool initFile(const std::string& filename) + { +#ifdef USEWIN32IOAPI + zlib_filefunc64_def ffunc = { 0 }; +#endif + + int mode = 0; + int flags = Zipper::Append; + + /* open the zip file for output */ + if (checkFileExists(filename)) + { + mode = (flags & Zipper::Overwrite) ? APPEND_STATUS_CREATE : APPEND_STATUS_ADDINZIP; + } + else + { + mode = APPEND_STATUS_CREATE; + } + +#ifdef USEWIN32IOAPI + fill_win32_filefunc64A(&ffunc); + m_zf = zipOpen2_64(filename.c_str(), mode, NULL, &ffunc); +#else + m_zf = zipOpen64(filename.c_str(), mode); +#endif + + return NULL != m_zf; + } + + bool initWithStream(std::iostream& stream) + { + m_zipmem.grow = 1; + + stream.seekg(0, std::ios::end); + std::streampos s = stream.tellg(); + if (s < 0) + { + return false; } + size_t size = static_cast(s); + stream.seekg(0); - void Zipper::release() + if (size > 0) { - if (!m_usingMemoryVector) + if (m_zipmem.base != NULL) { free(m_zipmem.base); } + m_zipmem.base = (char*) malloc (size * sizeof (char)); + stream.read(m_zipmem.base, size); + } + + fill_memory_filefunc(&m_filefunc, &m_zipmem); + + return initMemory(size > 0 ? APPEND_STATUS_CREATE : APPEND_STATUS_ADDINZIP, m_filefunc); + } + + bool initWithVector(std::vector& buffer) + { + m_zipmem.grow = 1; + + if (!buffer.empty()) + { + if (m_zipmem.base != NULL) + { + free(m_zipmem.base); + } + m_zipmem.base = (char*) malloc (buffer.size() * sizeof (char)); + memcpy(m_zipmem.base, (char*) buffer.data(), buffer.size()); + m_zipmem.size = (uLong)buffer.size(); + } + + fill_memory_filefunc(&m_filefunc, &m_zipmem); + + return initMemory(buffer.empty() ? APPEND_STATUS_CREATE : APPEND_STATUS_ADDINZIP, m_filefunc); + } + + bool initMemory(int mode, zlib_filefunc_def& filefunc) + { + m_zf = zipOpen3("__notused__", mode, 0, 0, &filefunc); + return m_zf != NULL; + } + + bool add(std::istream& input_stream, const std::tm& timestamp, + const std::string& nameInZip, const std::string& password, int flags) + { + if (!m_zf) + return false; + + int compressLevel = 0; + int zip64 = 0; + int size_buf = WRITEBUFFERSIZE; + int err = ZIP_OK; + unsigned long crcFile = 0; + + zip_fileinfo zi = { 0 }; + zi.tmz_date.tm_sec = timestamp.tm_sec; + zi.tmz_date.tm_min = timestamp.tm_min; + zi.tmz_date.tm_hour = timestamp.tm_hour; + zi.tmz_date.tm_mday = timestamp.tm_mday; + zi.tmz_date.tm_mon = timestamp.tm_mon; + zi.tmz_date.tm_year = timestamp.tm_year; + + size_t size_read; + + std::vector buff; + buff.resize(size_buf); + + if (nameInZip.empty()) + return false; + + if (flags & Zipper::Faster) + compressLevel = 1; + if (flags & Zipper::Better) + compressLevel = 9; + + zip64 = (int)isLargeFile(input_stream); + if (password.empty()) + { + err = zipOpenNewFileInZip64(m_zf, + nameInZip.c_str(), + &zi, + NULL, + 0, + NULL, + 0, + NULL /* comment*/, + (compressLevel != 0) ? Z_DEFLATED : 0, + compressLevel, + zip64); + } + else + { + getFileCrc(input_stream, buff, crcFile); + err = zipOpenNewFileInZip3_64(m_zf, + nameInZip.c_str(), + &zi, + NULL, + 0, + NULL, + 0, + NULL /* comment*/, + (compressLevel != 0) ? Z_DEFLATED : 0, + compressLevel, + 0, + /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */ + -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, + password.c_str(), + crcFile, + zip64); + } + + if (ZIP_OK == err) + { + do { + err = ZIP_OK; + input_stream.read(buff.data(), buff.size()); + size_read = (size_t)input_stream.gcount(); + if (size_read < buff.size() && !input_stream.eof() && !input_stream.good()) { - delete &m_vecbuffer; + err = ZIP_ERRNO; } - if (!m_usingStream) + + if (size_read > 0) { - delete &m_obuffer; + err = zipWriteInFileInZip(this->m_zf, buff.data(), (unsigned int)size_read); } - delete m_impl; - } - - bool Zipper::add(std::istream& source, const std::tm& timestamp, const std::string& nameInZip, zipFlags flags) - { - return m_impl->add(source, timestamp, nameInZip, m_password, flags); - } - - bool Zipper::add(std::istream& source, const std::string& nameInZip, zipFlags flags) - { - return add(source, {}, nameInZip, flags); - } - - bool Zipper::add(const std::string& fileOrFolderPath, zipFlags flags) - { - if (isDirectory(fileOrFolderPath)) - { - std::string folderName = fileNameFromPath(fileOrFolderPath); - std::vector files = filesFromDirectory(fileOrFolderPath); - std::vector::iterator it = files.begin(); - for (; it != files.end(); ++it) - { - std::ifstream input(it->c_str(), std::ios::binary); - std::string nameInZip = it->substr(it->rfind(folderName + CDirEntry::Separator), it->size()); - add(input, nameInZip, flags); - input.close(); - } - } - else - { - std::ifstream input(fileOrFolderPath.c_str(), std::ios::binary); - std::string fullFileName; - - if (flags & Zipper::SaveHierarchy) - fullFileName = fileOrFolderPath; - else - fullFileName = fileNameFromPath(fileOrFolderPath); - - add(input, fullFileName, flags); - - input.close(); - } - - return true; - } - - - void Zipper::open() - { - if (!m_open) - { - if (m_usingMemoryVector) - { - if (!m_impl->initWithVector(m_vecbuffer)) - throw EXCEPTION_CLASS("Error opening zip memory!"); - } - else if (m_usingStream) - { - if (!m_impl->initWithStream(m_obuffer)) - throw EXCEPTION_CLASS("Error opening zip memory!"); - } - else - { - if (!m_impl->initFile(m_zipname)) - throw EXCEPTION_CLASS("Error opening zip file!"); - } - - m_open = true; - } - } - - void Zipper::close() - { - if (m_open) - { - m_impl->close(); - m_open = false; - } - } + } while ((err == ZIP_OK) && (size_read>0)); + } + else + { + throw EXCEPTION_CLASS(("Error adding '" + nameInZip + "' to zip").c_str()); + } + + if (ZIP_OK == err) + { + err = zipCloseFileInZip(this->m_zf); + } + + return ZIP_OK == err; + } + + void close() + { + if (m_zf != NULL) + { + zipClose(m_zf, NULL); + m_zf = NULL; + } + + if (m_zipmem.base && m_zipmem.limit > 0) + { + if (m_outer.m_usingMemoryVector) + { + m_outer.m_vecbuffer.resize(m_zipmem.limit); + m_outer.m_vecbuffer.assign(m_zipmem.base, m_zipmem.base + m_zipmem.limit); + } + else if (m_outer.m_usingStream) + { + m_outer.m_obuffer.write(m_zipmem.base, m_zipmem.limit); + } + } + + if (m_zipmem.base != NULL) + { + free(m_zipmem.base); + m_zipmem.base = NULL; + } + } +}; + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// + +Zipper::Zipper(const std::string& zipname) + : m_obuffer(*(new std::stringstream())) //not used but using local variable throws exception + , m_vecbuffer(*(new std::vector())) //not used but using local variable throws exception + , m_usingMemoryVector(false) + , m_usingStream(false) + , m_zipname(zipname) + , m_impl(new Impl(*this)) +{ + if (!m_impl->initFile(zipname)) + { + release(); + throw EXCEPTION_CLASS("Error creating zip in file!"); + } + m_open = true; +} + +Zipper::Zipper(const std::string& zipname, const std::string& password) + : m_obuffer(*(new std::stringstream())) //not used but using local variable throws exception + , m_vecbuffer(*(new std::vector())) //not used but using local variable throws exception + , m_usingMemoryVector(false) + , m_usingStream(false) + , m_zipname(zipname) + , m_password(password) + , m_impl(new Impl(*this)) +{ + if (!m_impl->initFile(zipname)) + { + release(); + throw EXCEPTION_CLASS("Error creating zip in file!"); + } + m_open = true; +} + +Zipper::Zipper(std::iostream& buffer) + : m_vecbuffer(*(new std::vector())) //not used but using local variable throws exception + , m_obuffer(buffer) + , m_usingMemoryVector(false) + , m_usingStream(true) + , m_impl(new Impl(*this)) +{ + if (!m_impl->initWithStream(m_obuffer)) + { + release(); + throw EXCEPTION_CLASS("Error creating zip in memory!"); + } + m_open = true; +} + +Zipper::Zipper(std::vector& buffer) + : m_vecbuffer(buffer) + , m_obuffer(*(new std::stringstream())) //not used but using local variable throws exception + , m_usingMemoryVector(true) + , m_usingStream(false) + , m_impl(new Impl(*this)) +{ + if (!m_impl->initWithVector(m_vecbuffer)) + { + release(); + throw EXCEPTION_CLASS("Error creating zip in memory!"); + } + m_open = true; +} + +Zipper::~Zipper() +{ + close(); + release(); +} + +void Zipper::release() +{ + if (!m_usingMemoryVector) + { + delete &m_vecbuffer; + } + if (!m_usingStream) + { + delete &m_obuffer; + } + delete m_impl; +} + +bool Zipper::add(std::istream& source, const std::tm& timestamp, const std::string& nameInZip, zipFlags flags) +{ + return m_impl->add(source, timestamp, nameInZip, m_password, flags); +} + +bool Zipper::add(std::istream& source, const std::string& nameInZip, zipFlags flags) +{ + return add(source, {}, nameInZip, flags); +} + +bool Zipper::add(const std::string& fileOrFolderPath, zipFlags flags) +{ + if (isDirectory(fileOrFolderPath)) + { + std::string folderName = fileNameFromPath(fileOrFolderPath); + std::vector files = filesFromDirectory(fileOrFolderPath); + std::vector::iterator it = files.begin(); + for (; it != files.end(); ++it) + { + std::ifstream input(it->c_str(), std::ios::binary); + std::string nameInZip = it->substr(it->rfind(folderName + CDirEntry::Separator), it->size()); + add(input, nameInZip, flags); + input.close(); + } + } + else + { + std::ifstream input(fileOrFolderPath.c_str(), std::ios::binary); + std::string fullFileName; + + if (flags & Zipper::SaveHierarchy) + { + fullFileName = fileOrFolderPath; + } + else + { + fullFileName = fileNameFromPath(fileOrFolderPath); + } + + add(input, fullFileName, flags); + + input.close(); + } + + return true; +} + + +void Zipper::open() +{ + if (!m_open) + { + if (m_usingMemoryVector) + { + if (!m_impl->initWithVector(m_vecbuffer)) + throw EXCEPTION_CLASS("Error opening zip memory!"); + } + else if (m_usingStream) + { + if (!m_impl->initWithStream(m_obuffer)) + throw EXCEPTION_CLASS("Error opening zip memory!"); + } + else + { + if (!m_impl->initFile(m_zipname)) + throw EXCEPTION_CLASS("Error opening zip file!"); + } + + m_open = true; + } } + +void Zipper::close() +{ + if (m_open) + { + m_impl->close(); + m_open = false; + } +} + +} // namespace zipper diff --git a/zipper/zipper.h b/zipper/zipper.h index 3921891..b055ce7 100644 --- a/zipper/zipper.h +++ b/zipper/zipper.h @@ -9,38 +9,41 @@ namespace zipper { - class Zipper - { - public: - // Minizip options/params: - // -o -a -0 -1 -9 -j - enum zipFlags { Overwrite = 0x01, Append = 0x02, Store = 0x04, Faster = 0x08, Better = 0x10, NoPaths = 0x20, SaveHierarchy = 0x40 }; - - Zipper(std::iostream& buffer); - Zipper(std::vector& buffer); - Zipper(const std::string& zipname); - Zipper(const std::string& zipname, const std::string& password); - - ~Zipper(); - - bool add(std::istream& source, const std::tm& timestamp, const std::string& nameInZip = std::string(), zipFlags flags = Better); - bool add(std::istream& source, const std::string& nameInZip = std::string(), zipFlags flags = Better); - bool add(const std::string& fileOrFolderPath, zipFlags flags = Better); - - void open(); - void close(); - - private: - void release(); - std::string m_password; - std::string m_zipname; - std::iostream& m_obuffer; - std::vector& m_vecbuffer; - bool m_usingMemoryVector; - bool m_usingStream; - bool m_open; - - struct Impl; - Impl* m_impl; - }; -} +class Zipper +{ +public: + + // Minizip options/params: + // -o -a -0 -1 -9 -j + enum zipFlags { Overwrite = 0x01, Append = 0x02, Store = 0x04, Faster = 0x08, Better = 0x10, NoPaths = 0x20, SaveHierarchy = 0x40 }; + + Zipper(std::iostream& buffer); + Zipper(std::vector& buffer); + Zipper(const std::string& zipname); + Zipper(const std::string& zipname, const std::string& password); + + ~Zipper(); + + bool add(std::istream& source, const std::tm& timestamp, const std::string& nameInZip = std::string(), zipFlags flags = Better); + bool add(std::istream& source, const std::string& nameInZip = std::string(), zipFlags flags = Better); + bool add(const std::string& fileOrFolderPath, zipFlags flags = Better); + + void open(); + void close(); + +private: + + void release(); + std::string m_password; + std::string m_zipname; + std::iostream& m_obuffer; + std::vector& m_vecbuffer; + bool m_usingMemoryVector; + bool m_usingStream; + bool m_open; + + struct Impl; + Impl* m_impl; +}; + +} // namespace zipper From d86ae60f3a81f421323efc7d1965572d0d01ebae Mon Sep 17 00:00:00 2001 From: Tomas Berger <33124639+Togtja@users.noreply.github.com> Date: Fri, 21 Aug 2020 15:51:15 +0200 Subject: [PATCH 25/86] Add more inclusive windows enviroment (#65) * Add more inclusive windows enviroment * Add define for WIN32, to not change alot of code Co-authored-by: Tomas Berger --- zipper/CDirEntry.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zipper/CDirEntry.cpp b/zipper/CDirEntry.cpp index 45976ed..d351d2d 100644 --- a/zipper/CDirEntry.cpp +++ b/zipper/CDirEntry.cpp @@ -18,6 +18,10 @@ #include #include +#if defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) +#define WIN32 1 +#endif + #ifdef WIN32 # include # include From e83e25a38282cbd7ac86693ded5a7bd9ff9374c7 Mon Sep 17 00:00:00 2001 From: Tomas Berger <33124639+Togtja@users.noreply.github.com> Date: Mon, 24 Aug 2020 22:36:36 +0200 Subject: [PATCH 26/86] Fix Cmake include dir (#67) * Add target_include_directories to CMake * Fix ordering Co-authored-by: Tomas Berger --- CMakeLists.txt | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bf18daf..0a4ee88 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -338,7 +338,12 @@ file(READ "${CMAKE_CURRENT_SOURCE_DIR}/VERSION.txt" VERSION) option(BUILD_SHARED_VERSION "Build the shared version of the library." ON) if (BUILD_SHARED_VERSION) add_library (${ZIPPER_LIBRARY} SHARED ${ZIPPER_SOURCES} ${MINIZIP_SOURCES} ) - + target_include_directories( + ${ZIPPER_LIBRARY} + PUBLIC + $ + $ + ) if (UNIX) SET_TARGET_PROPERTIES(${ZIPPER_LIBRARY} PROPERTIES SOVERSION ${ZIPPER_VERSION_MAJOR} @@ -354,6 +359,12 @@ option(BUILD_STATIC_VERSION "Build the static version of the library." ON) if (BUILD_STATIC_VERSION) set(STATIC_ZIPPER_LIBRARY static${ZIPPER_LIBRARY}) add_library (${STATIC_ZIPPER_LIBRARY} STATIC ${ZIPPER_SOURCES} ${MINIZIP_SOURCES}) + target_include_directories( + ${STATIC_ZIPPER_LIBRARY} + PUBLIC + $ + $ + ) set_target_properties(${STATIC_ZIPPER_LIBRARY} PROPERTIES OUTPUT_NAME ${ZIPPER_LIBRARY}) target_link_libraries(${STATIC_ZIPPER_LIBRARY} ${LIBZ_LIBRARY} ${EXTRA_LIBS}) list(APPEND TARGET_LIST ${STATIC_ZIPPER_LIBRARY}) From 47902f27257e7cb0a0b66268e93cdfc7736e2904 Mon Sep 17 00:00:00 2001 From: Tomas Berger <33124639+Togtja@users.noreply.github.com> Date: Mon, 24 Aug 2020 22:39:29 +0200 Subject: [PATCH 27/86] Add use of find ZLIB instead of custom CMake (#68) Co-authored-by: Tomas Berger --- CMakeLists.txt | 57 +++++++++++--------------------------------------- 1 file changed, 12 insertions(+), 45 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0a4ee88..3e36c1e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -106,40 +106,7 @@ if("${CMAKE_BUILD_TYPE}" STREQUAL "") or CMAKE_C_FLAGS are used), Debug, Release, RelWithDebInfo, MinSizeRel." FORCE) endif() - -find_library(LIBZ_LIBRARY - NAMES zdll.lib z zlib.lib - PATHS /usr/lib /usr/local/lib - ${CMAKE_OSX_SYSROOT}/usr/lib - ${ZIPPER_DEPENDENCY_DIR}/lib - ${ADDITIONAL_LIB_DIRS} - $ENV{ZLIBROOT}/lib - DOC "The file name of the zip compression library." -) - - -if (NOT LIBZ_INCLUDE_DIR) - find_path(LIBZ_INCLUDE_DIR - NAMES zlib.h zlib/zlib.h - PATHS ${CMAKE_OSX_SYSROOT}/usr/include - /usr/include /usr/local/include - ${ZIPPER_DEPENDENCY_DIR}/include - $ENV{ZLIBROOT}/include - NO_DEFAULT_PATH - DOC "The directory containing the zlib include files." - ) -endif() - -if (NOT LIBZ_INCLUDE_DIR) - find_path(LIBZ_INCLUDE_DIR - NAMES zlib.h zlib/zlib.h - PATHS ${CMAKE_OSX_SYSROOT}/usr/include - /usr/include /usr/local/include - ${ZIPPER_DEPENDENCY_DIR}/include - $ENV{ZLIBROOT}/include - DOC "The directory containing the zlib include files." - ) -endif() +find_package(ZLIB REQUIRED) # allow the user to define additional compilation symbols if (EXTRA_DEFS) @@ -152,7 +119,7 @@ set(USE_ZLIB ON) add_definitions( -DUSE_ZLIB ) # make sure that we have a valid zip library -check_library_exists("${LIBZ_LIBRARY}" "gzopen" "" LIBZ_FOUND_SYMBOL) +check_library_exists("${ZLIB_LIBRARIES}" "gzopen" "" LIBZ_FOUND_SYMBOL) if(NOT LIBZ_FOUND_SYMBOL) # this is odd, but on windows this check always fails! must be a # bug in the current cmake version so for now only issue this @@ -160,17 +127,17 @@ if(NOT LIBZ_FOUND_SYMBOL) if(UNIX) message(WARNING "The chosen zlib library does not appear to be valid because it is -missing certain required symbols. Please check that ${LIBZ_LIBRARY} is +missing certain required symbols. Please check that ${ZLIB_LIBRARIES} is the correct zlib library. For details about the error, please see ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log") endif() endif() -if(NOT EXISTS "${LIBZ_INCLUDE_DIR}/zlib.h") +if(NOT EXISTS "${ZLIB_INCLUDE_DIRS}/zlib.h") message(FATAL_ERROR "The include directory specified for zlib does not appear to be valid. It should contain the file zlib.h, but it does not. Please -verify the LIBZ_INCLUDE_DIR variable.") +verify the ZLIB_INCLUDE_DIRS (${ZLIB_INCLUDE_DIRS}) variable.") endif() set(USING_INTEL) @@ -284,7 +251,7 @@ add_definitions(-D__APPLE__) endif() -include_directories(BEFORE ${LIBZ_INCLUDE_DIR}) +include_directories(BEFORE ${ZLIB_INCLUDE_DIRS}) include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}) include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}/zipper) @@ -350,7 +317,7 @@ if (BUILD_SHARED_VERSION) VERSION ${ZIPPER_VERSION_MAJOR}.${ZIPPER_VERSION_MINOR}.${ZIPPER_VERSION_PATCH}) endif() - target_link_libraries(${ZIPPER_LIBRARY} ${LIBZ_LIBRARY} ${EXTRA_LIBS}) + target_link_libraries(${ZIPPER_LIBRARY} ${ZLIB_LIBRARIES} ${EXTRA_LIBS}) list(APPEND TARGET_LIST ${ZIPPER_LIBRARY}) endif() @@ -366,13 +333,13 @@ if (BUILD_STATIC_VERSION) $ ) set_target_properties(${STATIC_ZIPPER_LIBRARY} PROPERTIES OUTPUT_NAME ${ZIPPER_LIBRARY}) - target_link_libraries(${STATIC_ZIPPER_LIBRARY} ${LIBZ_LIBRARY} ${EXTRA_LIBS}) + target_link_libraries(${STATIC_ZIPPER_LIBRARY} ${ZLIB_LIBRARIES} ${EXTRA_LIBS}) list(APPEND TARGET_LIST ${STATIC_ZIPPER_LIBRARY}) # Deprecated code: old zipper static lib was named libZipper-static.a but this was not # a good unix name. Anyway keep installing it to avoid breaking programs link with it. add_library (${ZIPPER_LIBRARY}-static STATIC ${ZIPPER_SOURCES} ${MINIZIP_SOURCES}) - target_link_libraries(${ZIPPER_LIBRARY}-static ${LIBZ_LIBRARY} ${EXTRA_LIBS}) + target_link_libraries(${ZIPPER_LIBRARY}-static ${ZLIB_LIBRARIES} ${EXTRA_LIBS}) list(APPEND TARGET_LIST ${ZIPPER_LIBRARY}-static) endif() @@ -397,7 +364,7 @@ if (BUILD_TEST) include(CTest) add_executable(${ZIPPER_LIBRARY}-test ${TEST_SOURCES}) - target_link_libraries(${ZIPPER_LIBRARY}-test static${ZIPPER_LIBRARY} ${LIBZ_LIBRARY} ${EXTRA_LIBS}) + target_link_libraries(${ZIPPER_LIBRARY}-test static${ZIPPER_LIBRARY} ${ZLIB_LIBRARIES} ${EXTRA_LIBS}) list(APPEND TARGET_LIST ${ZIPPER_LIBRARY}-test) add_test( @@ -460,8 +427,8 @@ Zipper version ${PACKAGE_VERSION} LDFLAGS = ${CMAKE_EXE_LINKER_FLAGS} Zlib library configuration: - Zlib library = ${LIBZ_LIBRARY} - Zlib include dir = ${LIBZ_INCLUDE_DIR} + Zlib library = ${ZLIB_LIBRARIES} + Zlib include dir = ${ZLIB_INCLUDE_DIRS} Other configuration settings: Installation $prefix = ${CMAKE_INSTALL_PREFIX} From 9c8caeb9f0ff6194eaac893b047eb48117369db5 Mon Sep 17 00:00:00 2001 From: Quentin Quadrat Date: Sat, 29 Aug 2020 12:40:20 +0200 Subject: [PATCH 28/86] CI: Fix keyring until appveyor updates its installation --- appveyor.yml | 39 ++++++++++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index b480e65..4f425d6 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,18 +1,35 @@ -platform: - - x64 - environment: - MSYSTEM: MSYS + matrix: + - MSYS2_ARCH: x86_64 + MSYSTEM: MINGW64 +# - MSYS2_ARCH: i686 +# MSYSTEM: MINGW32 + +clone_depth: 1 +branches: + only: + - master + - develop + +install: + - set PATH=C:\msys64\usr\bin;%PATH% + # Fix appveyor not git cloning recursively + - cd %APPVEYOR_BUILD_FOLDER% + - git submodule update --init --recursive + # Download new keyring until appveyor updates its installation + - bash -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz" + - bash -lc "curl -O http://repo.msys2.org/msys/x86_64/msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig" + - bash -lc "pacman-key --verify msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz.sig" + - bash -lc "pacman -U msys2-keyring-r21.b39fb11-1-any.pkg.tar.xz --noconfirm" + - bash -lc "pacman --needed --noconfirm -Syu" + # This is needed because without killing all processes -Su will fail + - ps: Get-Process | Where-Object {$_.path -like 'C:\msys64*'} | Stop-Process + - bash -lc "pacman --needed --noconfirm -Su" before_build: - - C:\msys64\usr\bin\pacman --noconfirm --sync --refresh --refresh --sysupgrade --sysupgrade - - C:\msys64\usr\bin\pacman --noconfirm --sync --refresh --refresh pacman - - C:\msys64\usr\bin\pacman --noconfirm --sync --refresh --refresh git + - C:\msys64\usr\bin\pacman --noconfirm --sync --refresh pacman + - C:\msys64\usr\bin\pacman --noconfirm --sync --refresh git - C:\msys64\usr\bin\bash -lc "$(cygpath ${APPVEYOR_BUILD_FOLDER})/.integration/appveyor-install-window.sh" build_script: - C:\msys64\usr\bin\bash -lc "$(cygpath ${APPVEYOR_BUILD_FOLDER})/.integration/appveyor-launch_tests.sh" - -branches: - only: - - master From 5f05775c64468b2d8030ceaad3636a584f9d2317 Mon Sep 17 00:00:00 2001 From: Quentin Quadrat Date: Tue, 1 Sep 2020 20:44:04 +0200 Subject: [PATCH 29/86] Fix erroneous command in README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e7bf5bd..fb8d91e 100644 --- a/README.md +++ b/README.md @@ -201,7 +201,7 @@ There are several ways to link your project against Zipper: - Straight forward: `g++ -W -Wall -I/usr/local/include main.cpp -o prog -L/usr/local/lib/ -lZipper -lz`. Note: you may have to adapt `/usr/local` to your installation directory (see the previous section `Installing`). You can also adapt and export your environment variable `LD_LIBRARY_PATH` (via you .bashrc for example). - Pkg-config is a better alternative to the previous command: ``` -g++ -W -Wall main.cpp -o prog `pkg-config libZipper --cflags --libs` +g++ -W -Wall main.cpp -o prog `pkg-config zipper --cflags --libs` ``` Indeed pkg-config knows for you where to find libraries and, by default, it will choose the shared library. In the case it is not present then the static library will be chosen. You can force choosing the static library with `pkg-config libZipper --static --libs` - Makefile: set `LDFLAGS` to `pkg-config zipper --libs` and set `CPPFLAGS` to `pkg-config zipper --cflags` From 72c9c45504497785400da0e895ceb0932a4370e4 Mon Sep 17 00:00:00 2001 From: Tomas Berger <33124639+Togtja@users.noreply.github.com> Date: Fri, 4 Sep 2020 18:41:27 +0200 Subject: [PATCH 30/86] Add linking for Cmake in readme (#71) * Ticket #58: Update documentation * Fix pkg-config name in README * Ticket #58: Update documentation Fix previous commit 6770bbadd2713358df646fb118aa60ff1a568163 * Add Readme for CMake linking #64 Co-authored-by: Quentin Quadrat Co-authored-by: Tomas Berger --- README.md | 50 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index fb8d91e..7355eec 100644 --- a/README.md +++ b/README.md @@ -8,17 +8,17 @@ C++ wrapper around minizip compression library **Zipper**'s goal is to bring the power and simplicity of minizip to a more object oriented/c++ user friendly library. -It was born out of the necessity of a compression library that would be reliable, simple and flexible. +It 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 been able to compress into memory instead of been restricted to file compression only, and using data from memory instead of just files as well. -### Features: +### Features + - [x] Create zip in memory - [x] Allow files, vector and generic streams as input to zip - [x] File mappings for replacing strategies (overwrite if exists or use alternative name from mapping) - [x] Password protected zip - [x] Multi platform - ### Getting Started In order to use and compile zipper you need to have [zlib](http://www.zlib.net) source files. @@ -37,6 +37,7 @@ sudo dnf install gcc-c++ # for fedora ``` #### Compiling + The preferred way is to create a folder for the compilation output to avoid polluting the root folder ```shell @@ -51,12 +52,14 @@ make #### Installing Following the previous section `Compiling`, still from the `build` folder, type: + ```shell sudo make install ``` You will see a message like: -``` + +```shell Install the project... -- Install configuration: "Release" -- Installing: /usr/local/lib/libZipper.so.1.0.1 @@ -84,13 +87,14 @@ Install the project... -- Installing: /usr/local/lib/cmake/zipperTargets-release.cmake ``` -### Usage: +### Usage There are two classes available Zipper and Unzipper. They behave in the same manner regarding constructors and storage parameters. (for a complete example take a look at the [tests](https://github.com/sebastiandev/zipper/blob/develop/test/file_zip_test.cpp ) using the awesome BDD's from Catch library ) -##### Zipping +#### Zipping - Creating a zip file with 2 files: + ```c++ using namespace zipper; @@ -105,6 +109,7 @@ zipper.close(); ``` - Adding a file by name and an entire folder to a zip: + ```c++ Zipper zipper("ziptest.zip"); @@ -112,6 +117,7 @@ zipper.add("somefile.txt"); zipper.add("myFolder"); zipper.close(); ``` + - Creating a zip file using the awesome streams from boost that lets us use a vector as a stream: ```c++ @@ -126,6 +132,7 @@ zipper.close(); ``` - Creating a zip in memory stream with files: + ```c++ #include ... @@ -139,6 +146,7 @@ zipper.close(); ``` - Creating a zip in a vector with files: + ```c++ std::vector zip_vect; @@ -150,7 +158,9 @@ zipper.close(); ``` ##### Unzipping + - Getting all entries in zip + ```c++ Unzipper unzipper("zipfile.zip"); std::vector entries = unzipper.entries(); @@ -158,6 +168,7 @@ unzipper.close(); ``` - Extracting all entries from zip + ```c++ Unzipper unzipper("zipfile.zip"); unzipper.extract(); @@ -165,6 +176,7 @@ unzipper.close(); ``` - Extracting all entries from zip using alternative names for existing files on disk + ```c++ std::map alternativeNames = { {"Test1", "alternative_name_test1"} }; Unzipper unzipper("zipfile.zip"); @@ -173,6 +185,7 @@ unzipper.close(); ``` - Extracting a single entry from zip + ```c++ Unzipper unzipper("zipfile.zip"); unzipper.extractEntry("entry name"); @@ -180,6 +193,7 @@ unzipper.close(); ``` - Extracting a single entry from zip to memory + ```c++ std::vector unzipped_entry; Unzipper unzipper("zipfile.zip"); @@ -192,17 +206,37 @@ unzipper.close(); ##### Linking Zipper to your project In your project add the needed headers in your c++ files: + ```c++ #include #include ``` There are several ways to link your project against Zipper: + - Straight forward: `g++ -W -Wall -I/usr/local/include main.cpp -o prog -L/usr/local/lib/ -lZipper -lz`. Note: you may have to adapt `/usr/local` to your installation directory (see the previous section `Installing`). You can also adapt and export your environment variable `LD_LIBRARY_PATH` (via you .bashrc for example). + - Pkg-config is a better alternative to the previous command: -``` + +```shell g++ -W -Wall main.cpp -o prog `pkg-config zipper --cflags --libs` ``` + Indeed pkg-config knows for you where to find libraries and, by default, it will choose the shared library. In the case it is not present then the static library will be chosen. You can force choosing the static library with `pkg-config libZipper --static --libs` + - Makefile: set `LDFLAGS` to `pkg-config zipper --libs` and set `CPPFLAGS` to `pkg-config zipper --cflags` -- CMake: TODO + +- CMake: Simply place zipper in your project hieracy, and then use `add_subdirectory(zipper)` or whatever you called the zipper folder. Then link it with `Zipper`/`staticZipper` + +```cmake +Project(projZipper) + +add_subdirectory(zipper) + +add_executable(projZipper main.cpp) +target_link_libraries( + projZipper + PUBLIC + staticZipper +) +``` From 5b298460dbfcdb73893fabb6f7fbd157676b2349 Mon Sep 17 00:00:00 2001 From: Quentin Quadrat Date: Tue, 1 Sep 2020 20:33:18 +0200 Subject: [PATCH 31/86] Ticket #60: Do not use std::exception(const char*) since not C++ standard The constructor of the std::exception class does not take any arguments according to C++ standard. Microsoft C++ has a constructor taking arguments but this is not standard. The std::runtime_error class has a constructor taking arguments (char*) on both platforms, Windows and Linux. To be portable, better use runtime_error. --- zipper/defs.h | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/zipper/defs.h b/zipper/defs.h index a0ee07e..535852b 100644 --- a/zipper/defs.h +++ b/zipper/defs.h @@ -35,12 +35,7 @@ extern "C" # include #endif -#if (defined(_WIN32)) || (defined(_WIN64)) -# define EXCEPTION_CLASS std::exception -#else -# define EXCEPTION_CLASS std::runtime_error -#endif - +#define EXCEPTION_CLASS std::runtime_error #if (defined(_WIN64)) && (!defined(__APPLE__)) # ifndef __USE_FILE_OFFSET64 From bf8005120be58298e5bce5ac42dade600e719578 Mon Sep 17 00:00:00 2001 From: Quentin Quadrat Date: Mon, 31 Aug 2020 22:24:45 +0200 Subject: [PATCH 32/86] Cleaning WIN32 defines --- zipper/CDirEntry.cpp | 62 +++++++++++++------------------------------- zipper/defs.h | 29 +++++++++++++++++---- zipper/tools.cpp | 4 +-- 3 files changed, 44 insertions(+), 51 deletions(-) diff --git a/zipper/CDirEntry.cpp b/zipper/CDirEntry.cpp index d351d2d..9ec920f 100644 --- a/zipper/CDirEntry.cpp +++ b/zipper/CDirEntry.cpp @@ -14,41 +14,15 @@ // All rights reserved. // ----------------------------------------------------------------------------- +#include "defs.h" +#include "CDirEntry.h" #include #include -#include - -#if defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) -#define WIN32 1 -#endif - -#ifdef WIN32 -# include -# include -typedef struct _stat STAT; -# define stat _stat -# define S_IFREG _S_IFREG -# define S_IFDIR _S_IFDIR -# define access _access -# define mkdir _mkdir -# define rmdir _rmdir -#else -typedef struct stat STAT; -# include -# include -#endif // WIN32 - -#include "CDirEntry.h" -#include #include using namespace zipper; -#ifdef WIN32 -const std::string CDirEntry::Separator = "\\"; -#else -const std::string CDirEntry::Separator = "/"; -#endif +const std::string CDirEntry::Separator(DIRECTORY_SEPARATOR); // ----------------------------------------------------------------------------- bool CDirEntry::isFile(const std::string & path) @@ -58,7 +32,7 @@ bool CDirEntry::isFile(const std::string & path) if (stat(path.c_str(), & st) == -1) return false; -#ifdef WIN32 +#if defined(USE_WINDOWS) return ((st.st_mode & S_IFREG) == S_IFREG); #else return S_ISREG(st.st_mode); @@ -73,7 +47,7 @@ bool CDirEntry::isDir(const std::string & path) if (stat(path.c_str(), & st) == -1) return false; -#ifdef WIN32 +#if defined(USE_WINDOWS) return ((st.st_mode & S_IFDIR) == S_IFDIR); #else return S_ISDIR(st.st_mode); @@ -88,7 +62,7 @@ bool CDirEntry::exist(const std::string & path) if (stat(path.c_str(), & st) == -1) return false; -#ifdef WIN32 +#if defined(USE_WINDOWS) return ((st.st_mode & S_IFREG) == S_IFREG || (st.st_mode & S_IFDIR) == S_IFDIR); #else @@ -113,7 +87,7 @@ std::string CDirEntry::baseName(const std::string & path) { std::string::size_type start = path.find_last_of(Separator); -#ifdef WIN32 // WIN32 also understands '/' as the separator. +#if defined(USE_WINDOWS) // WIN32 also understands '/' as the separator. if (start == std::string::npos) { start = path.find_last_of("/"); @@ -144,7 +118,7 @@ std::string CDirEntry::fileName(const std::string & path) { std::string::size_type start = path.find_last_of(Separator); -#ifdef WIN32 // WIN32 also understands '/' as the separator. +#if defined(USE_WINDOWS) // WIN32 also understands '/' as the separator. if (start == std::string::npos) { start = path.find_last_of("/"); @@ -169,7 +143,7 @@ std::string CDirEntry::dirName(const std::string & path) if (path == "") return path; -#ifdef WIN32 // WIN32 also understands '/' as the separator. +#if defined(USE_WINDOWS) // WIN32 also understands '/' as the separator. std::string::size_type end = path.find_last_of(Separator + "/"); #else std::string::size_type end = path.find_last_of(Separator); @@ -177,7 +151,7 @@ std::string CDirEntry::dirName(const std::string & path) if (end == path.length() - 1) { -#ifdef WIN32 // WIN32 also understands '/' as the separator. +#if defined(USE_WINDOWS) // WIN32 also understands '/' as the separator. end = path.find_last_of(Separator + "/", end); #else end = path.find_last_of(Separator, end); @@ -195,7 +169,7 @@ std::string CDirEntry::suffix(const std::string & path) { std::string::size_type start = path.find_last_of(Separator); -#ifdef WIN32 // WIN32 also understands '/' as the separator. +#if defined(USE_WINDOWS) // WIN32 also understands '/' as the separator. if (start == std::string::npos) { start = path.find_last_of("/"); @@ -249,7 +223,7 @@ bool CDirEntry::createDir(const std::string & dir, const std::string & parent) createDir(actualParent); } -#ifdef WIN32 +#if defined(USE_WINDOWS) return (mkdir(Dir.c_str()) == 0); #else return (mkdir(Dir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0); @@ -303,7 +277,7 @@ bool CDirEntry::move(const std::string & from, const std::string & to) if (isDir(To)) return false; -#ifdef WIN32 +#if defined(USE_WINDOWS) // The target must not exist under WIN32 for rename to succeed. if (exist(To) && !remove(To)) @@ -337,7 +311,7 @@ bool CDirEntry::remove(const std::string & path) if (isDir(path)) return (rmdir(path.c_str()) == 0); else if (isFile(path)) -#ifdef WIN32 +#if defined(USE_WINDOWS) return (::remove(path.c_str()) == 0); #else return (::remove(path.c_str()) == 0); @@ -355,7 +329,7 @@ bool CDirEntry::removeFiles(const std::string & pattern, PatternList = compilePattern(pattern); -#ifdef WIN32 +#if defined(USE_WINDOWS) // We want the same pattern matching behaviour for all platforms. // Therefore, we do not use the MS provided one and list all files instead. @@ -475,7 +449,7 @@ bool CDirEntry::match(const std::string & name, // ----------------------------------------------------------------------------- bool CDirEntry::isRelativePath(const std::string & path) { -#ifdef WIN32 +#if defined(USE_WINDOWS) std::string Path = normalize(path); if (Path.length() < 2) @@ -523,7 +497,7 @@ bool CDirEntry::makePathRelative(std::string & absolutePath, const std::string & i = absolutePath.find_last_of('/', i) + 1; } -#ifdef WIN32 +#if defined(USE_WINDOWS) if (i == 0) { @@ -635,7 +609,7 @@ std::string CDirEntry::normalize(const std::string & path) { std::string Normalized = path; -#ifdef WIN32 +#if defined(USE_WINDOWS) // converts all '\' to '/' (only on WIN32) size_t i, imax; diff --git a/zipper/defs.h b/zipper/defs.h index 535852b..fb8f8e0 100644 --- a/zipper/defs.h +++ b/zipper/defs.h @@ -10,12 +10,31 @@ extern "C" #include #include -#if (defined(_WIN32)) || (defined(_WIN64)) +#if (defined(__WIN32__) || defined(WIN32) || defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)) && !defined(CYGWIN) +# define USE_WINDOWS 1 +#endif + +#if defined(USE_WINDOWS) +# define DIRECTORY_SEPARATOR "\\" +#else +# define DIRECTORY_SEPARATOR "/" +#endif + +#if defined(USE_WINDOWS) # include # include +typedef struct _stat STAT; +# define stat _stat +# define S_IFREG _S_IFREG +# define S_IFDIR _S_IFDIR +# define access _access +# define mkdir _mkdir +# define rmdir _rmdir #else +# include # include # include +typedef struct stat STAT; #endif #include @@ -25,19 +44,19 @@ extern "C" #define WRITEBUFFERSIZE (8192) #define MAXFILENAME (256) -#if (defined(_WIN32)) || (defined(_WIN64)) +#if defined(USE_WINDOWS) # define USEWIN32IOAPI # include "iowin32.h" #endif } -#if (defined(_WIN32)) || (defined(_WIN64)) +#if defined(USE_WINDOWS) # include #endif #define EXCEPTION_CLASS std::runtime_error -#if (defined(_WIN64)) && (!defined(__APPLE__)) +#if defined(_WIN64) && (!defined(__APPLE__)) # ifndef __USE_FILE_OFFSET64 # define __USE_FILE_OFFSET64 # endif @@ -52,7 +71,7 @@ extern "C" # endif #endif -#if (defined(_WIN32)) || (defined(_WIN64)) +#if defined(USE_WINDOWS) # define MKDIR(d) _mkdir(d) # define CHDIR(d) _chdir(d) #else diff --git a/zipper/tools.cpp b/zipper/tools.cpp index 8995d27..0f5c52a 100644 --- a/zipper/tools.cpp +++ b/zipper/tools.cpp @@ -8,14 +8,14 @@ #include #include -#if defined(WIN32) && !defined(CYGWIN) +#if (USE_WINDOWS) # include "tps/dirent.h" # include "tps/dirent.c" #else # include # include # include -#endif /* WIN32 */ +#endif /* WINDOWS */ namespace zipper { From 226b35935e4df0a1a25bbc28b42ae84a44c7ebed Mon Sep 17 00:00:00 2001 From: Giuseppe Cesarano Date: Fri, 18 Sep 2020 02:32:14 +0200 Subject: [PATCH 33/86] Support for msys2 / mingw-w64 (#73) * Support for msys2 / mingw-w64 * Changed windows detection for syntax consistency --- zipper/CDirEntry.cpp | 2 +- zipper/defs.h | 4 ++-- zipper/tools.cpp | 2 +- zipper/unzipper.cpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/zipper/CDirEntry.cpp b/zipper/CDirEntry.cpp index 9ec920f..2fd0acc 100644 --- a/zipper/CDirEntry.cpp +++ b/zipper/CDirEntry.cpp @@ -223,7 +223,7 @@ bool CDirEntry::createDir(const std::string & dir, const std::string & parent) createDir(actualParent); } -#if defined(USE_WINDOWS) +#if defined(USE_WINDOWS) || defined (__MINGW32__) return (mkdir(Dir.c_str()) == 0); #else return (mkdir(Dir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0); diff --git a/zipper/defs.h b/zipper/defs.h index fb8f8e0..d28f49b 100644 --- a/zipper/defs.h +++ b/zipper/defs.h @@ -10,7 +10,7 @@ extern "C" #include #include -#if (defined(__WIN32__) || defined(WIN32) || defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)) && !defined(CYGWIN) +#if (defined(__WIN32__) || defined(WIN32) || defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)) && !defined(CYGWIN) && !defined(__MINGW32__) # define USE_WINDOWS 1 #endif @@ -71,7 +71,7 @@ typedef struct stat STAT; # endif #endif -#if defined(USE_WINDOWS) +#if defined(USE_WINDOWS) || defined (__MINGW32__) # define MKDIR(d) _mkdir(d) # define CHDIR(d) _chdir(d) #else diff --git a/zipper/tools.cpp b/zipper/tools.cpp index 0f5c52a..9aafab9 100644 --- a/zipper/tools.cpp +++ b/zipper/tools.cpp @@ -8,7 +8,7 @@ #include #include -#if (USE_WINDOWS) +#if defined(USE_WINDOWS) # include "tps/dirent.h" # include "tps/dirent.c" #else diff --git a/zipper/unzipper.cpp b/zipper/unzipper.cpp index a0a4513..f236b7d 100644 --- a/zipper/unzipper.cpp +++ b/zipper/unzipper.cpp @@ -192,7 +192,7 @@ struct Unzipper::Impl void changeFileDate(const std::string& filename, uLong dosdate, tm_unz tmu_date) { -#ifdef _WIN32 +#if defined(USE_WINDOWS) HANDLE hFile; FILETIME ftm, ftLocal, ftCreate, ftLastAcc, ftLastWrite; From c146a6bc1fa850355b14eeb3940ed03c47913cf7 Mon Sep 17 00:00:00 2001 From: Giuseppe Cesarano Date: Fri, 18 Sep 2020 02:36:34 +0200 Subject: [PATCH 34/86] Appveyor fix (#76) --- .integration/appveyor-install-window.sh | 2 +- .integration/appveyor-launch_tests.sh | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/.integration/appveyor-install-window.sh b/.integration/appveyor-install-window.sh index 4f736ae..14754e6 100755 --- a/.integration/appveyor-install-window.sh +++ b/.integration/appveyor-install-window.sh @@ -16,6 +16,6 @@ function mingw_packages done } -mingw_packages "zlib cmake toolchain clang" +mingw_packages "zlib cmake toolchain clang ninja" sh -c "pacman -S --noconfirm git make $packages" diff --git a/.integration/appveyor-launch_tests.sh b/.integration/appveyor-launch_tests.sh index f2193c3..6e28488 100755 --- a/.integration/appveyor-launch_tests.sh +++ b/.integration/appveyor-launch_tests.sh @@ -1,14 +1,12 @@ #!/bin/bash -export PATH="/mingw64/bin:/usr/local/bin:/usr/bin:/bin:/c/WINDOWS/system32:/c/WINDOWS:/c/WINDOWS/System32/Wbem:/c/WINDOWS/System32/WindowsPowerShell/v1.0" -bf=$(cygpath ${APPVEYOR_BUILD_FOLDER}) -cd "$bf" || (echo "Cannot go to directory $bf"; return 1) +export PATH="/mingw64/bin" +cd ${APPVEYOR_BUILD_FOLDER} # Compile -mkdir -p build +cmake -B build -GNinja . cd build || exit 1 -cmake .. || exit 1 -make -j4 || exit 1 +cmake --build . || exit 1 cd .. # Unit test From 8f799a04cd252e2c910a1028bc8e75c7a05a1984 Mon Sep 17 00:00:00 2001 From: Quentin Quadrat Date: Fri, 18 Sep 2020 20:42:14 +0200 Subject: [PATCH 35/86] Add Appveyor baners dev and master --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7355eec..9adf43e 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ |Branch | **`Linux/Mac OS`** | **`Windows`** | |-----------|------------------|-------------| -|master |[![Build Status](https://travis-ci.org/sebastiandev/zipper.svg?branch=master)](https://travis-ci.org/sebastiandev/zipper)|[![Build status](https://ci.appveyor.com/api/projects/status/github/sebastiandev/zipper)](https://ci.appveyor.com/api/projects/status/github/sebastiandev/zipper)| -|development|[![Build Status](https://travis-ci.org/sebastiandev/zipper.svg?branch=develop)](https://travis-ci.org/sebastiandev/zipper)|| +|master |[![Build Status](https://travis-ci.org/sebastiandev/zipper.svg?branch=master)](https://travis-ci.org/sebastiandev/zipper)|[![Build status](https://ci.appveyor.com/api/projects/status/github/sebastiandev/zipper?branch=master)](https://ci.appveyor.com/api/projects/status/github/sebastiandev/zipper)| +|development|[![Build Status](https://travis-ci.org/sebastiandev/zipper.svg?branch=develop)](https://travis-ci.org/sebastiandev/zipper)|[![Build status](https://ci.appveyor.com/api/projects/status/github/sebastiandev/zipper?branch=develop)](https://ci.appveyor.com/api/projects/status/github/sebastiandev/zipper)| C++ wrapper around minizip compression library From 8cb0f00bb00862786e4de7de62942d29ab6b34f5 Mon Sep 17 00:00:00 2001 From: Tomas Berger <33124639+Togtja@users.noreply.github.com> Date: Mon, 5 Oct 2020 19:25:37 +0200 Subject: [PATCH 36/86] Add cpp version for MSVC (#77) * Add cpp version for MSVC --- test/catch.hpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/catch.hpp b/test/catch.hpp index 3c02c7a..6a1c237 100644 --- a/test/catch.hpp +++ b/test/catch.hpp @@ -116,6 +116,18 @@ # define CATCH_CPP14_OR_GREATER # endif +# endif + +// unless compiled with /Zc:__cplusplus, the __cplusplus value is 199711L with MSVC +#ifdef _MSVC_LANG +# if _MSVC_LANG >= 201103L +# define CATCH_CPP11_OR_GREATER +# endif + +# if _MSVC_LANG >= 201402L +# define CATCH_CPP14_OR_GREATER +# endif + #endif #ifdef __clang__ From 33e67be94415f474932fa4d7aba636cb04caca78 Mon Sep 17 00:00:00 2001 From: FrozenSource Date: Mon, 19 Oct 2020 21:35:35 +0200 Subject: [PATCH 37/86] Correction for windows and minizip (#81) --- zipper/CDirEntry.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zipper/CDirEntry.cpp b/zipper/CDirEntry.cpp index 2fd0acc..590ef63 100644 --- a/zipper/CDirEntry.cpp +++ b/zipper/CDirEntry.cpp @@ -411,7 +411,7 @@ std::vector< std::string > CDirEntry::compilePattern(const std::string & pattern start = pos; pos = pattern.find_first_of("*?", pos); - end = std::min(pos, pattern.length()); + end = (std::min)(pos, pattern.length()); if (start != end) { @@ -482,8 +482,8 @@ bool CDirEntry::makePathRelative(std::string & absolutePath, const std::string & return false; absolutePath = normalize(absolutePath); - - size_t i, imax = std::min(absolutePath.length(), RelativeTo.length()); + + size_t i, imax = (std::min)(absolutePath.length(), RelativeTo.length()); for (i = 0; i < imax; i++) { From 63272e034e53bd34c818d961e9f6e2f70993f0cf Mon Sep 17 00:00:00 2001 From: Quentin Quadrat Date: Wed, 10 Feb 2021 22:14:24 +0100 Subject: [PATCH 38/86] Fix extract silently fails #83 --- zipper/unzipper.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zipper/unzipper.cpp b/zipper/unzipper.cpp index f236b7d..e897613 100644 --- a/zipper/unzipper.cpp +++ b/zipper/unzipper.cpp @@ -427,7 +427,8 @@ struct Unzipper::Impl else alternativeName += it->name; - this->extractCurrentEntryToFile(*it, alternativeName); + if (!extractCurrentEntryToFile(*it, alternativeName)) + return false; }; return true; From df76bf8f5a88b56c4aac08d2bdc520c6df6708aa Mon Sep 17 00:00:00 2001 From: Quentin Quadrat Date: Wed, 10 Feb 2021 22:55:24 +0100 Subject: [PATCH 39/86] Update README --- README.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9adf43e..9b21010 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ Install the project... ### Usage -There are two classes available Zipper and Unzipper. They behave in the same manner regarding constructors and storage parameters. (for a complete example take a look at the [tests](https://github.com/sebastiandev/zipper/blob/develop/test/file_zip_test.cpp ) using the awesome BDD's from Catch library ) +There are two classes available Zipper and Unzipper. They behave in the same manner regarding constructors and storage parameters. (for a complete example take a look at the [zip file tests](test/file_zip_test.cpp) and [zip memory tests](test/memory_zip_test.cpp) using the awesome BDD's from Catch library ) #### Zipping @@ -149,7 +149,7 @@ zipper.close(); ```c++ -std::vector zip_vect; +std::vector zip_vect; std::ifstream input1("some file"); Zipper zipper(zip_vect); @@ -201,6 +201,16 @@ unzipper.extractEntryToMemory("entry name", unzipped_entry); unzipper.close(); ``` +- Extracting from a vector: + +```c++ + +std::vector zip_vect; // Populated with Zipper zipper(zip_vect); + +Unzipper unzipper(zip_vect); +unzipper.extractEntry("Test1") +``` + **Note:** Methods `extract`, `extractEntry`, `extractEntryToMemory` return a boolean indicating the success (`true`) or the failure (`false`). ##### Linking Zipper to your project From 910a2fb193db73c42bf51246e85654637a9ed98d Mon Sep 17 00:00:00 2001 From: Quentin Quadrat Date: Thu, 11 Feb 2021 00:17:49 +0100 Subject: [PATCH 40/86] Fix Can't provide password to unzipper with vector input #86 --- README.md | 12 ++++++++++++ zipper/unzipper.cpp | 23 ++++------------------- zipper/unzipper.h | 7 +++---- zipper/zipper.cpp | 24 +++++------------------- zipper/zipper.h | 7 +++---- 5 files changed, 27 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 9b21010..92acfd1 100644 --- a/README.md +++ b/README.md @@ -157,6 +157,12 @@ zipper.add(input1, "Test1"); zipper.close(); ``` +- Adding a password. You can pass your password as a `std::string` as second parameter to any of constructors: + +```c++ +Zipper zipper("ziptest.zip", "mypassword"); +``` + ##### Unzipping - Getting all entries in zip @@ -213,6 +219,12 @@ unzipper.extractEntry("Test1") **Note:** Methods `extract`, `extractEntry`, `extractEntryToMemory` return a boolean indicating the success (`true`) or the failure (`false`). +- Extraction using a password. You can pass your password as a `std::string` as second parameter to any of constructors: + +```c++ +Zipper unzipper("ziptest.zip", "mypassword"); +``` + ##### Linking Zipper to your project In your project add the needed headers in your c++ files: diff --git a/zipper/unzipper.cpp b/zipper/unzipper.cpp index e897613..9201ad1 100644 --- a/zipper/unzipper.cpp +++ b/zipper/unzipper.cpp @@ -476,9 +476,10 @@ struct Unzipper::Impl } }; -Unzipper::Unzipper(std::istream& zippedBuffer) +Unzipper::Unzipper(std::istream& zippedBuffer, const std::string& password) : m_ibuffer(zippedBuffer) , m_vecbuffer(*(new std::vector())) //not used but using local variable throws exception + , m_password(password) , m_usingMemoryVector(false) , m_usingStream(true) , m_impl(new Impl(*this)) @@ -491,9 +492,10 @@ Unzipper::Unzipper(std::istream& zippedBuffer) m_open = true; } -Unzipper::Unzipper(std::vector& zippedBuffer) +Unzipper::Unzipper(std::vector& zippedBuffer, const std::string& password) : m_ibuffer(*(new std::stringstream())) //not used but using local variable throws exception , m_vecbuffer(zippedBuffer) + , m_password(password) , m_usingMemoryVector(true) , m_usingStream(false) , m_impl(new Impl(*this)) @@ -507,23 +509,6 @@ Unzipper::Unzipper(std::vector& zippedBuffer) m_open = true; } -Unzipper::Unzipper(const std::string& zipname) - : m_ibuffer(*(new std::stringstream())) //not used but using local variable throws exception - , m_vecbuffer(*(new std::vector())) //not used but using local variable throws exception - , m_zipname(zipname) - , m_usingMemoryVector(false) - , m_usingStream(false) - , m_impl(new Impl(*this)) -{ - if (!m_impl->initFile(zipname)) - { - release(); - throw EXCEPTION_CLASS("Error loading zip file!"); - } - - m_open = true; -} - Unzipper::Unzipper(const std::string& zipname, const std::string& password) : m_ibuffer(*(new std::stringstream())) //not used but using local variable throws exception , m_vecbuffer(*(new std::vector())) //not used but using local variable throws exception diff --git a/zipper/unzipper.h b/zipper/unzipper.h index f509184..7ad9364 100644 --- a/zipper/unzipper.h +++ b/zipper/unzipper.h @@ -15,10 +15,9 @@ class ZipEntry; class Unzipper { public: - Unzipper(std::istream& buffer); - Unzipper(std::vector& buffer); - Unzipper(const std::string& zipname); - Unzipper(const std::string& zipname, const std::string& password); + Unzipper(std::istream& buffer, const std::string& password = std::string()); + Unzipper(std::vector& buffer, const std::string& password = std::string()); + Unzipper(const std::string& zipname, const std::string& password = std::string()); ~Unzipper(); diff --git a/zipper/zipper.cpp b/zipper/zipper.cpp index 6ac2d31..fbdc2b2 100644 --- a/zipper/zipper.cpp +++ b/zipper/zipper.cpp @@ -238,22 +238,6 @@ struct Zipper::Impl /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// -Zipper::Zipper(const std::string& zipname) - : m_obuffer(*(new std::stringstream())) //not used but using local variable throws exception - , m_vecbuffer(*(new std::vector())) //not used but using local variable throws exception - , m_usingMemoryVector(false) - , m_usingStream(false) - , m_zipname(zipname) - , m_impl(new Impl(*this)) -{ - if (!m_impl->initFile(zipname)) - { - release(); - throw EXCEPTION_CLASS("Error creating zip in file!"); - } - m_open = true; -} - Zipper::Zipper(const std::string& zipname, const std::string& password) : m_obuffer(*(new std::stringstream())) //not used but using local variable throws exception , m_vecbuffer(*(new std::vector())) //not used but using local variable throws exception @@ -271,11 +255,12 @@ Zipper::Zipper(const std::string& zipname, const std::string& password) m_open = true; } -Zipper::Zipper(std::iostream& buffer) +Zipper::Zipper(std::iostream& buffer, const std::string& password) : m_vecbuffer(*(new std::vector())) //not used but using local variable throws exception , m_obuffer(buffer) , m_usingMemoryVector(false) , m_usingStream(true) + , m_password(password) , m_impl(new Impl(*this)) { if (!m_impl->initWithStream(m_obuffer)) @@ -286,11 +271,12 @@ Zipper::Zipper(std::iostream& buffer) m_open = true; } -Zipper::Zipper(std::vector& buffer) +Zipper::Zipper(std::vector& buffer, const std::string& password) : m_vecbuffer(buffer) , m_obuffer(*(new std::stringstream())) //not used but using local variable throws exception , m_usingMemoryVector(true) , m_usingStream(false) + , m_password(password) , m_impl(new Impl(*this)) { if (!m_impl->initWithVector(m_vecbuffer)) @@ -327,7 +313,7 @@ bool Zipper::add(std::istream& source, const std::tm& timestamp, const std::stri bool Zipper::add(std::istream& source, const std::string& nameInZip, zipFlags flags) { - return add(source, {}, nameInZip, flags); + return m_impl->add(source, {}, nameInZip, m_password, flags); } bool Zipper::add(const std::string& fileOrFolderPath, zipFlags flags) diff --git a/zipper/zipper.h b/zipper/zipper.h index b055ce7..557334c 100644 --- a/zipper/zipper.h +++ b/zipper/zipper.h @@ -17,10 +17,9 @@ class Zipper // -o -a -0 -1 -9 -j enum zipFlags { Overwrite = 0x01, Append = 0x02, Store = 0x04, Faster = 0x08, Better = 0x10, NoPaths = 0x20, SaveHierarchy = 0x40 }; - Zipper(std::iostream& buffer); - Zipper(std::vector& buffer); - Zipper(const std::string& zipname); - Zipper(const std::string& zipname, const std::string& password); + Zipper(std::iostream& buffer, const std::string& password = std::string()); + Zipper(std::vector& buffer, const std::string& password = std::string()); + Zipper(const std::string& zipname, const std::string& password = std::string()); ~Zipper(); From 8c70143b340a158efcf3203b64f999d07ae344c8 Mon Sep 17 00:00:00 2001 From: Quentin Quadrat Date: Thu, 11 Feb 2021 00:20:51 +0100 Subject: [PATCH 41/86] Add and apply .clang-format from dev-modernize --- README.md | 9 +++++ zipper/.clang-format | 14 +++++++ zipper/CDirEntry.cpp | 90 +++++++++++++++++++++----------------------- zipper/CDirEntry.h | 65 +++++++++++++++----------------- zipper/defs.h | 71 +++++++++++++++++----------------- zipper/tools.cpp | 17 +++++---- zipper/tools.h | 3 +- zipper/unzipper.cpp | 19 ++++------ zipper/unzipper.h | 5 +-- zipper/zipper.cpp | 25 +++++++----- zipper/zipper.h | 10 +++-- 11 files changed, 174 insertions(+), 154 deletions(-) create mode 100644 zipper/.clang-format diff --git a/README.md b/README.md index 92acfd1..fe78de1 100644 --- a/README.md +++ b/README.md @@ -262,3 +262,12 @@ target_link_libraries( staticZipper ) ``` + +##### Coding style + +Before submitting a pull request, you can ident the code with the following command: + +```shell +cd src +clang-format -i *.cpp *.h +``` diff --git a/zipper/.clang-format b/zipper/.clang-format new file mode 100644 index 0000000..4ce87a9 --- /dev/null +++ b/zipper/.clang-format @@ -0,0 +1,14 @@ +BasedOnStyle: WebKit +AlignAfterOpenBracket: Align +AllowShortIfStatementsOnASingleLine: true +BraceWrapping: + AfterClass: true + AfterControlStatement: true + AfterFunction: true + AfterStruct: true + BeforeElse: true +BreakBeforeBraces: Custom +ConstructorInitializerAllOnOneLineOrOnePerLine: true +IndentPPDirectives: AfterHash +MaxEmptyLinesToKeep: 2 +SortIncludes: false diff --git a/zipper/CDirEntry.cpp b/zipper/CDirEntry.cpp index 590ef63..eaf8b99 100644 --- a/zipper/CDirEntry.cpp +++ b/zipper/CDirEntry.cpp @@ -25,11 +25,11 @@ using namespace zipper; const std::string CDirEntry::Separator(DIRECTORY_SEPARATOR); // ----------------------------------------------------------------------------- -bool CDirEntry::isFile(const std::string & path) +bool CDirEntry::isFile(const std::string& path) { STAT st; - if (stat(path.c_str(), & st) == -1) + if (stat(path.c_str(), &st) == -1) return false; #if defined(USE_WINDOWS) @@ -40,11 +40,11 @@ bool CDirEntry::isFile(const std::string & path) } // ----------------------------------------------------------------------------- -bool CDirEntry::isDir(const std::string & path) +bool CDirEntry::isDir(const std::string& path) { STAT st; - if (stat(path.c_str(), & st) == -1) + if (stat(path.c_str(), &st) == -1) return false; #if defined(USE_WINDOWS) @@ -55,35 +55,34 @@ bool CDirEntry::isDir(const std::string & path) } // ----------------------------------------------------------------------------- -bool CDirEntry::exist(const std::string & path) +bool CDirEntry::exist(const std::string& path) { STAT st; - if (stat(path.c_str(), & st) == -1) + if (stat(path.c_str(), &st) == -1) return false; #if defined(USE_WINDOWS) - return ((st.st_mode & S_IFREG) == S_IFREG || - (st.st_mode & S_IFDIR) == S_IFDIR); + return ((st.st_mode & S_IFREG) == S_IFREG || (st.st_mode & S_IFDIR) == S_IFDIR); #else return (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode)); #endif } // ----------------------------------------------------------------------------- -bool CDirEntry::isReadable(const std::string & path) +bool CDirEntry::isReadable(const std::string& path) { return (access(path.c_str(), 0x4) == 0); } // ----------------------------------------------------------------------------- -bool CDirEntry::isWritable(const std::string & path) +bool CDirEntry::isWritable(const std::string& path) { return (access(path.c_str(), 0x2) == 0); } // ----------------------------------------------------------------------------- -std::string CDirEntry::baseName(const std::string & path) +std::string CDirEntry::baseName(const std::string& path) { std::string::size_type start = path.find_last_of(Separator); @@ -114,7 +113,7 @@ std::string CDirEntry::baseName(const std::string & path) } // ----------------------------------------------------------------------------- -std::string CDirEntry::fileName(const std::string & path) +std::string CDirEntry::fileName(const std::string& path) { std::string::size_type start = path.find_last_of(Separator); @@ -138,7 +137,7 @@ std::string CDirEntry::fileName(const std::string & path) } // ----------------------------------------------------------------------------- -std::string CDirEntry::dirName(const std::string & path) +std::string CDirEntry::dirName(const std::string& path) { if (path == "") return path; @@ -165,7 +164,7 @@ std::string CDirEntry::dirName(const std::string & path) } // ----------------------------------------------------------------------------- -std::string CDirEntry::suffix(const std::string & path) +std::string CDirEntry::suffix(const std::string& path) { std::string::size_type start = path.find_last_of(Separator); @@ -194,7 +193,7 @@ std::string CDirEntry::suffix(const std::string & path) } // ----------------------------------------------------------------------------- -bool CDirEntry::createDir(const std::string & dir, const std::string & parent) +bool CDirEntry::createDir(const std::string& dir, const std::string& parent) { std::string Dir; @@ -223,7 +222,7 @@ bool CDirEntry::createDir(const std::string & dir, const std::string & parent) createDir(actualParent); } -#if defined(USE_WINDOWS) || defined (__MINGW32__) +#if defined(USE_WINDOWS) || defined(__MINGW32__) return (mkdir(Dir.c_str()) == 0); #else return (mkdir(Dir.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0); @@ -231,7 +230,7 @@ bool CDirEntry::createDir(const std::string & dir, const std::string & parent) } // ----------------------------------------------------------------------------- -std::string CDirEntry::createTmpName(const std::string & dir, const std::string & suffix) +std::string CDirEntry::createTmpName(const std::string& dir, const std::string& suffix) { std::string RandomName; @@ -242,7 +241,7 @@ std::string CDirEntry::createTmpName(const std::string & dir, const std::string for (size_t i = 0; i < 8; i++) { - Char = int((rand()/double(RAND_MAX))*35.0); + Char = int((rand() / double(RAND_MAX)) * 35.0); if (Char < 10) { @@ -255,14 +254,13 @@ std::string CDirEntry::createTmpName(const std::string & dir, const std::string } RandomName += suffix; - } - while (exist(RandomName)); + } while (exist(RandomName)); return RandomName; } // ----------------------------------------------------------------------------- -bool CDirEntry::move(const std::string & from, const std::string & to) +bool CDirEntry::move(const std::string& from, const std::string& to) { if (!isFile(from)) return false; @@ -285,8 +283,7 @@ bool CDirEntry::move(const std::string & from, const std::string & to) #endif // WIN32 - bool success = - (::rename(from.c_str(), To.c_str()) == 0); + bool success = (::rename(from.c_str(), To.c_str()) == 0); if (!success) { @@ -306,7 +303,7 @@ bool CDirEntry::move(const std::string & from, const std::string & to) } // ----------------------------------------------------------------------------- -bool CDirEntry::remove(const std::string & path) +bool CDirEntry::remove(const std::string& path) { if (isDir(path)) return (rmdir(path.c_str()) == 0); @@ -321,11 +318,11 @@ bool CDirEntry::remove(const std::string & path) } // ----------------------------------------------------------------------------- -bool CDirEntry::removeFiles(const std::string & pattern, - const std::string & path) +bool CDirEntry::removeFiles(const std::string& pattern, + const std::string& path) { bool success = true; - std::vector< std::string > PatternList; + std::vector PatternList; PatternList = compilePattern(pattern); @@ -359,18 +356,17 @@ bool CDirEntry::removeFiles(const std::string & pattern, success = false; } } - } - while (_findnext(hList, &Entry) == 0); + } while (_findnext(hList, &Entry) == 0); _findclose(hList); #else - DIR * pDir = opendir(path.c_str()); + DIR* pDir = opendir(path.c_str()); if (!pDir) return false; - struct dirent * pEntry; + struct dirent* pEntry; while ((pEntry = readdir(pDir)) != NULL) { @@ -399,12 +395,12 @@ bool CDirEntry::removeFiles(const std::string & pattern, } // ----------------------------------------------------------------------------- -std::vector< std::string > CDirEntry::compilePattern(const std::string & pattern) +std::vector CDirEntry::compilePattern(const std::string& pattern) { std::string::size_type pos = 0; std::string::size_type start = 0; std::string::size_type end = 0; - std::vector< std::string > PatternList; + std::vector PatternList; while (pos != std::string::npos) { @@ -428,11 +424,11 @@ std::vector< std::string > CDirEntry::compilePattern(const std::string & pattern } // ----------------------------------------------------------------------------- -bool CDirEntry::match(const std::string & name, - const std::vector< std::string > & patternList) +bool CDirEntry::match(const std::string& name, + const std::vector& patternList) { - std::vector< std::string >::const_iterator it = patternList.begin(); - std::vector< std::string >::const_iterator end = patternList.end(); + std::vector::const_iterator it = patternList.begin(); + std::vector::const_iterator end = patternList.end(); std::string::size_type at = 0; std::string::size_type after = 0; @@ -447,7 +443,7 @@ bool CDirEntry::match(const std::string & name, } // ----------------------------------------------------------------------------- -bool CDirEntry::isRelativePath(const std::string & path) +bool CDirEntry::isRelativePath(const std::string& path) { #if defined(USE_WINDOWS) std::string Path = normalize(path); @@ -468,12 +464,12 @@ bool CDirEntry::isRelativePath(const std::string & path) } // ----------------------------------------------------------------------------- -bool CDirEntry::makePathRelative(std::string & absolutePath, const std::string & relativeTo) +bool CDirEntry::makePathRelative(std::string& absolutePath, const std::string& relativeTo) { if (isRelativePath(absolutePath) || isRelativePath(relativeTo)) return false; // Nothing can be done. - std:: string RelativeTo = normalize(relativeTo); + std::string RelativeTo = normalize(relativeTo); if (isFile(RelativeTo)) RelativeTo = dirName(RelativeTo); @@ -482,7 +478,7 @@ bool CDirEntry::makePathRelative(std::string & absolutePath, const std::string & return false; absolutePath = normalize(absolutePath); - + size_t i, imax = (std::min)(absolutePath.length(), RelativeTo.length()); for (i = 0; i < imax; i++) @@ -529,12 +525,12 @@ bool CDirEntry::makePathRelative(std::string & absolutePath, const std::string & } // ----------------------------------------------------------------------------- -bool CDirEntry::makePathAbsolute(std::string & relativePath, const std::string & absoluteTo) +bool CDirEntry::makePathAbsolute(std::string& relativePath, const std::string& absoluteTo) { if (!isRelativePath(relativePath) || isRelativePath(absoluteTo)) return false; // Nothing can be done. - std:: string AbsoluteTo = normalize(absoluteTo); + std::string AbsoluteTo = normalize(absoluteTo); if (isFile(AbsoluteTo)) AbsoluteTo = dirName(AbsoluteTo); @@ -556,10 +552,10 @@ bool CDirEntry::makePathAbsolute(std::string & relativePath, const std::string & } // ----------------------------------------------------------------------------- -bool CDirEntry::matchInternal(const std::string & name, +bool CDirEntry::matchInternal(const std::string& name, const std::string pattern, - std::string::size_type & at, - std::string::size_type & after) + std::string::size_type& at, + std::string::size_type& after) { bool Match = true; @@ -605,7 +601,7 @@ bool CDirEntry::matchInternal(const std::string & name, } // ----------------------------------------------------------------------------- -std::string CDirEntry::normalize(const std::string & path) +std::string CDirEntry::normalize(const std::string& path) { std::string Normalized = path; diff --git a/zipper/CDirEntry.h b/zipper/CDirEntry.h index df2e19c..9aeb667 100644 --- a/zipper/CDirEntry.h +++ b/zipper/CDirEntry.h @@ -13,8 +13,7 @@ #include #include -namespace zipper -{ +namespace zipper { /** * This class provides an OS independent interface to directory entries * such as files and directories. @@ -22,7 +21,6 @@ namespace zipper class CDirEntry { public: - /** * The character used to separate directory entries. */ @@ -34,7 +32,7 @@ class CDirEntry * @param const std::string & path * @return bool isFile */ - static bool isFile(const std::string & path); + static bool isFile(const std::string& path); /** * Check whether the directory entry specified by 'path' is @@ -42,14 +40,14 @@ class CDirEntry * @param const std::string & path * @return bool isDir */ - static bool isDir(const std::string & path); + static bool isDir(const std::string& path); /** * Check whether the directory entry specified by 'path' exists. * @param const std::string & path * @return bool exist */ - static bool exist(const std::string & path); + static bool exist(const std::string& path); /** * Check whether the directory entry specified by 'path' is @@ -57,7 +55,7 @@ class CDirEntry * @param const std::string & path * @return bool isReadable */ - static bool isReadable(const std::string & path); + static bool isReadable(const std::string& path); /** * Check whether the directory entry specified by 'path' is @@ -65,7 +63,7 @@ class CDirEntry * @param const std::string & path * @return bool isWritable */ - static bool isWritable(const std::string & path); + static bool isWritable(const std::string& path); /** * Returns the base name, i.e., the directory path and the @@ -73,14 +71,14 @@ class CDirEntry * @param const std::string & path * @return std::string baseName */ - static std::string baseName(const std::string & path); + static std::string baseName(const std::string& path); /** * Returns the file name, i.e., the directory path is removed from 'path'. * @param const std::string & path * @return std::string fileName */ - static std::string fileName(const std::string & path); + static std::string fileName(const std::string& path); /** * Returns the directory path to the parent directoryu, i.e., @@ -88,7 +86,7 @@ class CDirEntry * @param const std::string & path * @return std::string dirName */ - static std::string dirName(const std::string & path); + static std::string dirName(const std::string& path); /** * Returns the suffix, i.e., the directory path and the @@ -96,7 +94,7 @@ class CDirEntry * @param const std::string & path * @return std::string basename */ - static std::string suffix(const std::string & path); + static std::string suffix(const std::string& path); /** * Create the directory 'dir' in the parent directory 'parent'. @@ -104,8 +102,8 @@ class CDirEntry * @param const std::string & parent (Default: current working directory) * @return bool success */ - static bool createDir(const std::string & dir, - const std::string & parent = ""); + static bool createDir(const std::string& dir, + const std::string& parent = ""); /** * Create a name for a temporary directory entry. The directory entry @@ -114,8 +112,8 @@ class CDirEntry * @param const std::string & suffix * @return std::string tmpName */ - static std::string createTmpName(const std::string & dir, - const std::string & suffix); + static std::string createTmpName(const std::string& dir, + const std::string& suffix); /** * Move a file from. If to is the directory the filename of from is @@ -124,15 +122,15 @@ class CDirEntry * @param const std::string & to * @return bool success */ - static bool move(const std::string & from, - const std::string & to); + static bool move(const std::string& from, + const std::string& to); /** * Removes a file or directory specified by path. * @param const std::string & path * @return bool success */ - static bool remove(const std::string & path); + static bool remove(const std::string& path); /** * Remove files or directories matching the pattern in directory dir. @@ -140,8 +138,8 @@ class CDirEntry * @param const std::string & dir * @return bool success */ - static bool removeFiles(const std::string & pattern, - const std::string & dir); + static bool removeFiles(const std::string& pattern, + const std::string& dir); /** * Compiles the pattern to a patternList. Valid wildcards in the pattern are: @@ -149,7 +147,7 @@ class CDirEntry * @param const std::string & pattern * @return std::vector< std::string > patternList */ - static std::vector< std::string > compilePattern(const std::string & pattern); + static std::vector compilePattern(const std::string& pattern); /** * Compare the name against the pattern list and returns whether the @@ -159,14 +157,14 @@ class CDirEntry * @param const std::vector< std::string > & patternList * @return bool match */ - static bool match(const std::string & name, - const std::vector< std::string > & patternList); + static bool match(const std::string& name, + const std::vector& patternList); /** * Checks whether the given path is relative * @return bool isRelative */ - static bool isRelativePath(const std::string & path); + static bool isRelativePath(const std::string& path); /** * Makes the absolute path relative to the path given in relativeTo @@ -174,8 +172,8 @@ class CDirEntry * @param const std::string & relativeTo * @return bool success */ - static bool makePathRelative(std::string & absolutePath, - const std::string & relativeTo); + static bool makePathRelative(std::string& absolutePath, + const std::string& relativeTo); /** * Makes the relative path absolute to the path given in absoluteTo @@ -183,8 +181,8 @@ class CDirEntry * @param const std::string & absoluteTo * @return bool success */ - static bool makePathAbsolute(std::string & relativePath, - const std::string & absoluteTo); + static bool makePathAbsolute(std::string& relativePath, + const std::string& absoluteTo); /** * This method normalizes the path, i.e., @@ -193,10 +191,9 @@ class CDirEntry * @param const std::string & path * @return std::string normalizedPath */ - static std::string normalize(const std::string & path); + static std::string normalize(const std::string& path); private: - /** * This private methods checks whether the active section matches the * specified patter. The section is automatically advanced to allow @@ -208,10 +205,10 @@ class CDirEntry * @param std::string::size_type & after * @return bool match */ - static bool matchInternal(const std::string & name, + static bool matchInternal(const std::string& name, const std::string pattern, - std::string::size_type & at, - std::string::size_type & after); + std::string::size_type& at, + std::string::size_type& after); }; } #endif // ZIPPER_CDirEntry diff --git a/zipper/defs.h b/zipper/defs.h index d28f49b..fe58fd7 100644 --- a/zipper/defs.h +++ b/zipper/defs.h @@ -1,7 +1,6 @@ #pragma once -extern "C" -{ +extern "C" { #include #include #include @@ -11,29 +10,29 @@ extern "C" #include #if (defined(__WIN32__) || defined(WIN32) || defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)) && !defined(CYGWIN) && !defined(__MINGW32__) -# define USE_WINDOWS 1 +# define USE_WINDOWS 1 #endif #if defined(USE_WINDOWS) -# define DIRECTORY_SEPARATOR "\\" +# define DIRECTORY_SEPARATOR "\\" #else -# define DIRECTORY_SEPARATOR "/" +# define DIRECTORY_SEPARATOR "/" #endif #if defined(USE_WINDOWS) -# include -# include +# include +# include typedef struct _stat STAT; -# define stat _stat -# define S_IFREG _S_IFREG -# define S_IFDIR _S_IFDIR -# define access _access -# define mkdir _mkdir -# define rmdir _rmdir +# define stat _stat +# define S_IFREG _S_IFREG +# define S_IFDIR _S_IFDIR +# define access _access +# define mkdir _mkdir +# define rmdir _rmdir #else -# include -# include -# include +# include +# include +# include typedef struct stat STAT; #endif @@ -45,36 +44,36 @@ typedef struct stat STAT; #define MAXFILENAME (256) #if defined(USE_WINDOWS) -# define USEWIN32IOAPI -# include "iowin32.h" +# define USEWIN32IOAPI +# include "iowin32.h" #endif } #if defined(USE_WINDOWS) -# include +# include #endif #define EXCEPTION_CLASS std::runtime_error #if defined(_WIN64) && (!defined(__APPLE__)) -# ifndef __USE_FILE_OFFSET64 -# define __USE_FILE_OFFSET64 -# endif -# ifndef __USE_LARGEFILE64 -# define __USE_LARGEFILE64 -# endif -# ifndef _LARGEFILE64_SOURCE -# define _LARGEFILE64_SOURCE -# endif -# ifndef _FILE_OFFSET_BIT -# define _FILE_OFFSET_BIT 64 -# endif +# ifndef __USE_FILE_OFFSET64 +# define __USE_FILE_OFFSET64 +# endif +# ifndef __USE_LARGEFILE64 +# define __USE_LARGEFILE64 +# endif +# ifndef _LARGEFILE64_SOURCE +# define _LARGEFILE64_SOURCE +# endif +# ifndef _FILE_OFFSET_BIT +# define _FILE_OFFSET_BIT 64 +# endif #endif -#if defined(USE_WINDOWS) || defined (__MINGW32__) -# define MKDIR(d) _mkdir(d) -# define CHDIR(d) _chdir(d) +#if defined(USE_WINDOWS) || defined(__MINGW32__) +# define MKDIR(d) _mkdir(d) +# define CHDIR(d) _chdir(d) #else -# define MKDIR(d) mkdir(d, 0775) -# define CHDIR(d) chdir(d) +# define MKDIR(d) mkdir(d, 0775) +# define CHDIR(d) chdir(d) #endif diff --git a/zipper/tools.cpp b/zipper/tools.cpp index 9aafab9..93d79f3 100644 --- a/zipper/tools.cpp +++ b/zipper/tools.cpp @@ -9,13 +9,13 @@ #include #if defined(USE_WINDOWS) -# include "tps/dirent.h" -# include "tps/dirent.c" +# include "tps/dirent.h" +# include "tps/dirent.c" #else -# include -# include -# include -#endif /* WINDOWS */ +# include +# include +# include +#endif /* WINDOWS */ namespace zipper { @@ -28,7 +28,8 @@ void getFileCrc(std::istream& input_stream, std::vector& buff, unsigned lo unsigned long size_read = 0; unsigned long total_read = 0; - do { + do + { input_stream.read(buff.data(), buff.size()); size_read = (unsigned long)input_stream.gcount(); @@ -110,7 +111,7 @@ std::string currentPath() std::vector filesFromDirectory(const std::string& path) { std::vector files; - DIR* dir; + DIR* dir; struct dirent* entry; dir = opendir(path.c_str()); diff --git a/zipper/tools.h b/zipper/tools.h index 05bc674..b540148 100644 --- a/zipper/tools.h +++ b/zipper/tools.h @@ -4,8 +4,7 @@ #include #include -namespace zipper -{ +namespace zipper { void getFileCrc(std::istream& input_stream, std::vector& buff, unsigned long& result_crc); bool isLargeFile(std::istream& input_stream); diff --git a/zipper/unzipper.cpp b/zipper/unzipper.cpp index 9201ad1..a88584b 100644 --- a/zipper/unzipper.cpp +++ b/zipper/unzipper.cpp @@ -18,7 +18,6 @@ struct Unzipper::Impl zlib_filefunc_def m_filefunc; private: - bool initMemory(zlib_filefunc_def& filefunc) { m_zf = unzOpen2("__notused__", &filefunc); @@ -206,7 +205,7 @@ struct Unzipper::Impl CloseHandle(hFile); } #else -#if defined unix || defined __APPLE__ +# if defined unix || defined __APPLE__ struct utimbuf ut; struct tm newdate; @@ -223,7 +222,7 @@ struct Unzipper::Impl ut.actime = ut.modtime = mktime(&newdate); utime(filename.c_str(), &ut); -#endif +# endif #endif } @@ -325,8 +324,8 @@ struct Unzipper::Impl } public: - - Impl(Unzipper& outer) : m_outer(outer), m_zipmem(), m_filefunc() + Impl(Unzipper& outer) + : m_outer(outer), m_zipmem(), m_filefunc() { m_zipmem.base = NULL; m_zf = NULL; @@ -391,8 +390,8 @@ struct Unzipper::Impl { if (!buffer.empty()) { - m_zipmem.base = (char*) malloc (buffer.size() * sizeof (char)); - memcpy(m_zipmem.base, (char*) buffer.data(), buffer.size()); + m_zipmem.base = (char*)malloc(buffer.size() * sizeof(char)); + memcpy(m_zipmem.base, (char*)buffer.data(), buffer.size()); m_zipmem.size = (uLong)buffer.size(); } @@ -409,7 +408,6 @@ struct Unzipper::Impl } - bool extractAll(const std::string& destination, const std::map& alternativeNames) { std::vector entries; @@ -428,7 +426,7 @@ struct Unzipper::Impl alternativeName += it->name; if (!extractCurrentEntryToFile(*it, alternativeName)) - return false; + return false; }; return true; @@ -558,8 +556,7 @@ bool Unzipper::extract(const std::string& destination, const std::mapextractAll(destination, alternativeNames); } -bool -Unzipper::extract(const std::string& destination) +bool Unzipper::extract(const std::string& destination) { return m_impl->extractAll(destination, std::map()); } diff --git a/zipper/unzipper.h b/zipper/unzipper.h index 7ad9364..c3df6cf 100644 --- a/zipper/unzipper.h +++ b/zipper/unzipper.h @@ -24,7 +24,7 @@ class Unzipper std::vector entries(); bool extract(const std::string& destination, const std::map& alternativeNames); - bool extract(const std::string& destination=std::string()); + bool extract(const std::string& destination = std::string()); bool extractEntry(const std::string& name, const std::string& destination = std::string()); bool extractEntryToStream(const std::string& name, std::ostream& stream); bool extractEntryToMemory(const std::string& name, std::vector& vec); @@ -66,8 +66,7 @@ class ZipEntry { // timestamp YYYY-MM-DD HH:MM:SS std::stringstream str; - str << year << "-" << month << "-" << day << - " " << hour << ":" << minute << ":" << second; + str << year << "-" << month << "-" << day << " " << hour << ":" << minute << ":" << second; timestamp = str.str(); unixdate.tm_year = year; diff --git a/zipper/zipper.cpp b/zipper/zipper.cpp index fbdc2b2..0a81863 100644 --- a/zipper/zipper.cpp +++ b/zipper/zipper.cpp @@ -15,7 +15,8 @@ struct Zipper::Impl ourmemory_t m_zipmem; zlib_filefunc_def m_filefunc; - Impl(Zipper& outer) : m_outer(outer), m_zipmem(), m_filefunc() + Impl(Zipper& outer) + : m_outer(outer), m_zipmem(), m_filefunc() { m_zf = NULL; m_zipmem.base = NULL; @@ -71,8 +72,11 @@ struct Zipper::Impl if (size > 0) { - if (m_zipmem.base != NULL) { free(m_zipmem.base); } - m_zipmem.base = (char*) malloc (size * sizeof (char)); + if (m_zipmem.base != NULL) + { + free(m_zipmem.base); + } + m_zipmem.base = (char*)malloc(size * sizeof(char)); stream.read(m_zipmem.base, size); } @@ -91,8 +95,8 @@ struct Zipper::Impl { free(m_zipmem.base); } - m_zipmem.base = (char*) malloc (buffer.size() * sizeof (char)); - memcpy(m_zipmem.base, (char*) buffer.data(), buffer.size()); + m_zipmem.base = (char*)malloc(buffer.size() * sizeof(char)); + memcpy(m_zipmem.base, (char*)buffer.data(), buffer.size()); m_zipmem.size = (uLong)buffer.size(); } @@ -120,11 +124,11 @@ struct Zipper::Impl unsigned long crcFile = 0; zip_fileinfo zi = { 0 }; - zi.tmz_date.tm_sec = timestamp.tm_sec; - zi.tmz_date.tm_min = timestamp.tm_min; + zi.tmz_date.tm_sec = timestamp.tm_sec; + zi.tmz_date.tm_min = timestamp.tm_min; zi.tmz_date.tm_hour = timestamp.tm_hour; zi.tmz_date.tm_mday = timestamp.tm_mday; - zi.tmz_date.tm_mon = timestamp.tm_mon; + zi.tmz_date.tm_mon = timestamp.tm_mon; zi.tmz_date.tm_year = timestamp.tm_year; size_t size_read; @@ -178,7 +182,8 @@ struct Zipper::Impl if (ZIP_OK == err) { - do { + do + { err = ZIP_OK; input_stream.read(buff.data(), buff.size()); size_read = (size_t)input_stream.gcount(); @@ -191,7 +196,7 @@ struct Zipper::Impl { err = zipWriteInFileInZip(this->m_zf, buff.data(), (unsigned int)size_read); } - } while ((err == ZIP_OK) && (size_read>0)); + } while ((err == ZIP_OK) && (size_read > 0)); } else { diff --git a/zipper/zipper.h b/zipper/zipper.h index 557334c..25306a2 100644 --- a/zipper/zipper.h +++ b/zipper/zipper.h @@ -12,10 +12,15 @@ namespace zipper { class Zipper { public: - // Minizip options/params: // -o -a -0 -1 -9 -j - enum zipFlags { Overwrite = 0x01, Append = 0x02, Store = 0x04, Faster = 0x08, Better = 0x10, NoPaths = 0x20, SaveHierarchy = 0x40 }; + enum zipFlags { Overwrite = 0x01, + Append = 0x02, + Store = 0x04, + Faster = 0x08, + Better = 0x10, + NoPaths = 0x20, + SaveHierarchy = 0x40 }; Zipper(std::iostream& buffer, const std::string& password = std::string()); Zipper(std::vector& buffer, const std::string& password = std::string()); @@ -31,7 +36,6 @@ class Zipper void close(); private: - void release(); std::string m_password; std::string m_zipname; From 4452c9525de06c641e7031d71dddd1cbcf86a005 Mon Sep 17 00:00:00 2001 From: Quentin Quadrat Date: Fri, 12 Feb 2021 19:41:39 +0100 Subject: [PATCH 42/86] Delete trailling whitespaces --- CMakeLists.txt | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3e36c1e..5f83711 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -160,7 +160,7 @@ if(MSVC OR USING_INTEL) if(${flag_var} MATCHES "/MD") string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") endif(${flag_var} MATCHES "/MD") - + endforeach(flag_var) add_definitions( -D_MT) endif(WITH_STATIC_RUNTIME) @@ -174,16 +174,16 @@ if(MSVC OR USING_INTEL) CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO) - + if(${flag_var} MATCHES "/Zi") STRING(REPLACE "/Zi" "/Z7" "${flag_var}" "${${flag_var}}") endif(${flag_var} MATCHES "/Zi") - - endforeach(flag_var) + + endforeach(flag_var) endif() else() - + if(APPLE) # on osx starting with xcode 4.3 the system root is in # the app bundle, however cmake (up to 2.8.8) does not seem @@ -195,7 +195,7 @@ else() endif() add_definitions(-DMACOSX) set(BUILD_DEFINITIONS "${BUILD_DEFINITIONS} -DMACOSX") - + # Since we are encountering errors with the use of libc++ on OSX # this option allows to override which stdlib to use if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") @@ -204,12 +204,12 @@ else() SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++" ) endif() endif() - + # On OSX it is common to build universal binaries to support multiple # processor architectures. The default behavior is not to build # multiple architectures, as most users might not need that. option(ENABLE_UNIVERSAL "Create universal binaries on Mac OS X." OFF) - + set(CMAKE_OSX_ARCHITECTURES "${CMAKE_OSX_ARCHITECTURES}" CACHE STRING "A semicolon-separated list of build architectures to be used.") if(ENABLE_UNIVERSAL) @@ -231,21 +231,21 @@ else() endif(ENABLE_UNIVERSAL) else(APPLE) add_definitions(-DLINUX) - + if(NOT CYGWIN) # on cygwin all code is position independent so -fPIC is not needed set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing -fPIC") set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-strict-aliasing -fPIC") endif() - + set(BUILD_DEFINITIONS "${BUILD_DEFINITIONS} -DLINUX") endif(APPLE) endif() -# need an extra definition of __APPLE__ to prevent ioapi.c to +# need an extra definition of __APPLE__ to prevent ioapi.c to # change the name for the fopen/ftell/fseek commands -# unfortunately that won't work for qt +# unfortunately that won't work for qt if (CYGWIN AND NOT WITH_QT_FILESYSTEM) add_definitions(-D__APPLE__) endif() @@ -262,7 +262,7 @@ if (EXTRA_INCLUDE_DIRS) include_directories(${EXTRA_INCLUDE_DIRS}) endif() -file(GLOB MINIZIP_SOURCES +file(GLOB MINIZIP_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/minizip/*.c ${CMAKE_CURRENT_SOURCE_DIR}/minizip/*.h ${CMAKE_CURRENT_SOURCE_DIR}/minizip/aes/*.c @@ -316,9 +316,9 @@ if (BUILD_SHARED_VERSION) SOVERSION ${ZIPPER_VERSION_MAJOR} VERSION ${ZIPPER_VERSION_MAJOR}.${ZIPPER_VERSION_MINOR}.${ZIPPER_VERSION_PATCH}) endif() - + target_link_libraries(${ZIPPER_LIBRARY} ${ZLIB_LIBRARIES} ${EXTRA_LIBS}) - + list(APPEND TARGET_LIST ${ZIPPER_LIBRARY}) endif() @@ -371,8 +371,8 @@ if (BUILD_TEST) NAME test_zipper_run COMMAND $ ) - - set_tests_properties(test_zipper_run + + set_tests_properties(test_zipper_run PROPERTIES PASS_REGULAR_EXPRESSION "All tests passed" ) endif() @@ -397,7 +397,7 @@ install(TARGETS ${TARGET_LIST} EXPORT ${PROJECT_NAME} install(FILES ${PROJECT_BINARY_DIR}/zipper.pc DESTINATION ${INSTALL_PKGCONFIG_DIR}) file(GLOB ZIPPER_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/zipper/*.h ${CMAKE_CURRENT_SOURCE_DIR}/minizip/*.h ) -install(FILES +install(FILES ${ZIPPER_HEADERS} DESTINATION include/zipper) From 92bd0c0b0b9b6d9f3baf266c403bcf4a0eb6fbe9 Mon Sep 17 00:00:00 2001 From: Quentin Quadrat Date: Fri, 12 Feb 2021 20:41:15 +0100 Subject: [PATCH 43/86] Add more compilation flags and fix compilation warnings --- CMakeLists.txt | 2 +- zipper/CDirEntry.cpp | 10 +++---- zipper/tools.cpp | 18 ++++++------- zipper/unzipper.cpp | 63 ++++++++++++++++++++++---------------------- zipper/unzipper.h | 11 +++++--- zipper/zipper.cpp | 54 ++++++++++++++++++------------------- zipper/zipper.h | 8 ++++-- 7 files changed, 87 insertions(+), 79 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f83711..8a00315 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -90,7 +90,7 @@ if(WITH_WALL) if(MSVC OR USING_INTEL) add_definitions(/W4) else() - add_definitions(-Wall) + add_definitions(-Wall -Wextra -Wuninitialized -Wundef -Wunused -Wunused-result -Wunused-parameter -Wtype-limits -Wcast-align -Wcast-qual -Wconversion -Wfloat-equal -Wpointer-arith -Wswitch-enum -pedantic -Wpacked -Wold-style-cast -Wdeprecated -Wvariadic-macros -Wvla -Wsign-conversion -Wtautological-compare -Wformat -Wformat-security -Werror=format-security -D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong) endif() endif() diff --git a/zipper/CDirEntry.cpp b/zipper/CDirEntry.cpp index eaf8b99..b7b0639 100644 --- a/zipper/CDirEntry.cpp +++ b/zipper/CDirEntry.cpp @@ -237,19 +237,19 @@ std::string CDirEntry::createTmpName(const std::string& dir, const std::string& do { RandomName = dir + Separator; - unsigned int Char; + int Char; - for (size_t i = 0; i < 8; i++) + for (size_t i = 0; i < 8u; i++) { - Char = int((rand() / double(RAND_MAX)) * 35.0); + Char = static_cast((rand() / double(RAND_MAX)) * 35.0); if (Char < 10) { - RandomName += '0' + Char; + RandomName += char('0' + Char); } else { - RandomName += 'a' - 10 + Char; + RandomName += char('a' - 10 + Char); } } diff --git a/zipper/tools.cpp b/zipper/tools.cpp index 93d79f3..b474334 100644 --- a/zipper/tools.cpp +++ b/zipper/tools.cpp @@ -25,18 +25,18 @@ namespace zipper { void getFileCrc(std::istream& input_stream, std::vector& buff, unsigned long& result_crc) { unsigned long calculate_crc = 0; - unsigned long size_read = 0; + unsigned int size_read = 0; unsigned long total_read = 0; do { - input_stream.read(buff.data(), buff.size()); - size_read = (unsigned long)input_stream.gcount(); + input_stream.read(buff.data(), std::streamsize(buff.size())); + size_read = static_cast(input_stream.gcount()); if (size_read > 0) - calculate_crc = crc32(calculate_crc, (const unsigned char*)buff.data(), size_read); + calculate_crc = crc32(calculate_crc, reinterpret_cast(buff.data()), size_read); - total_read += size_read; + total_read += static_cast(size_read); } while (size_read > 0); @@ -48,7 +48,7 @@ void getFileCrc(std::istream& input_stream, std::vector& buff, unsigned lo // ----------------------------------------------------------------------------- bool isLargeFile(std::istream& input_stream) { - ZPOS64_T pos = 0; + std::streampos pos = 0; input_stream.seekg(0, std::ios::end); pos = input_stream.tellg(); input_stream.seekg(0); @@ -101,10 +101,8 @@ std::string parentDirectory(const std::string& filepath) // ----------------------------------------------------------------------------- std::string currentPath() { - char buffer[1024]; - getcwd(buffer, 1024); - std::string result(buffer); - return result; + char buffer[1024u]; + return (getcwd(buffer, sizeof(buffer)) ? std::string(buffer) : std::string("")); } // ----------------------------------------------------------------------------- diff --git a/zipper/unzipper.cpp b/zipper/unzipper.cpp index a88584b..dd8cf2b 100644 --- a/zipper/unzipper.cpp +++ b/zipper/unzipper.cpp @@ -31,7 +31,7 @@ struct Unzipper::Impl ZipEntry currentEntryInfo() { - unz_file_info64 file_info = { 0 }; + unz_file_info64 file_info; char filename_inzip[256] = { 0 }; int err = unzGetCurrentFileInfo64(m_zf, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0); @@ -189,9 +189,9 @@ struct Unzipper::Impl return UNZ_OK == err; } - void changeFileDate(const std::string& filename, uLong dosdate, tm_unz tmu_date) - { #if defined(USE_WINDOWS) + void changeFileDate(const std::string& filename, uLong dosdate, tm_unz /*tmu_date*/) + { HANDLE hFile; FILETIME ftm, ftLocal, ftCreate, ftLastAcc, ftLastWrite; @@ -204,28 +204,29 @@ struct Unzipper::Impl SetFileTime(hFile, &ftm, &ftLastAcc, &ftm); CloseHandle(hFile); } -#else -# if defined unix || defined __APPLE__ + } + +#elif defined unix || defined __APPLE__ + void changeFileDate(const std::string& filename, uLong /*dosdate*/, tm_unz tmu_date) + { struct utimbuf ut; struct tm newdate; - newdate.tm_sec = tmu_date.tm_sec; - newdate.tm_min = tmu_date.tm_min; - newdate.tm_hour = tmu_date.tm_hour; - newdate.tm_mday = tmu_date.tm_mday; - newdate.tm_mon = tmu_date.tm_mon; - if (tmu_date.tm_year > 1900) - newdate.tm_year = tmu_date.tm_year - 1900; + newdate.tm_sec = int(tmu_date.tm_sec); + newdate.tm_min = int(tmu_date.tm_min); + newdate.tm_hour = int(tmu_date.tm_hour); + newdate.tm_mday = int(tmu_date.tm_mday); + newdate.tm_mon = int(tmu_date.tm_mon); + if (tmu_date.tm_year > 1900u) + newdate.tm_year = int(tmu_date.tm_year - 1900u); else - newdate.tm_year = tmu_date.tm_year; + newdate.tm_year = int(tmu_date.tm_year); newdate.tm_isdst = -1; ut.actime = ut.modtime = mktime(&newdate); utime(filename.c_str(), &ut); -# endif -#endif } - +#endif int extractToFile(const std::string& filename, ZipEntry& info) { @@ -258,7 +259,7 @@ struct Unzipper::Impl int extractToStream(std::ostream& stream, ZipEntry& info) { - size_t err = unzOpenCurrentFilePassword(m_zf, m_outer.m_password.c_str()); + int err = unzOpenCurrentFilePassword(m_zf, m_outer.m_password.c_str()); if (UNZ_OK != err) { std::stringstream str; @@ -273,11 +274,11 @@ struct Unzipper::Impl do { - err = unzReadCurrentFile(m_zf, buffer.data(), (unsigned int)buffer.size()); + err = unzReadCurrentFile(m_zf, buffer.data(), static_cast(buffer.size())); if (err < 0 || err == 0) break; - stream.write(buffer.data(), err); + stream.write(buffer.data(), std::streamsize(err)); if (!stream.good()) { err = UNZ_ERRNO; @@ -288,12 +289,12 @@ struct Unzipper::Impl stream.flush(); - return (int)err; + return err; } int extractToMemory(std::vector& outvec, ZipEntry& info) { - size_t err = UNZ_ERRNO; + int err = UNZ_ERRNO; err = unzOpenCurrentFilePassword(m_zf, m_outer.m_password.c_str()); if (UNZ_OK != err) @@ -308,11 +309,11 @@ struct Unzipper::Impl std::vector buffer; buffer.resize(WRITEBUFFERSIZE); - outvec.reserve((size_t)info.uncompressedSize); + outvec.reserve(static_cast(info.uncompressedSize)); do { - err = unzReadCurrentFile(m_zf, buffer.data(), (unsigned int)buffer.size()); + err = unzReadCurrentFile(m_zf, buffer.data(), static_cast(buffer.size())); if (err < 0 || err == 0) break; @@ -320,7 +321,7 @@ struct Unzipper::Impl } while (err > 0); - return (int)err; + return err; } public: @@ -374,11 +375,11 @@ struct Unzipper::Impl size_t size = static_cast(s); stream.seekg(0); - if (size > 0) + if (size > 0u) { - m_zipmem.base = new char[(size_t)size]; - m_zipmem.size = (uLong)size; - stream.read(m_zipmem.base, size); + m_zipmem.base = new char[size]; + m_zipmem.size = static_cast(size); + stream.read(m_zipmem.base, std::streamsize(size)); } fill_memory_filefunc(&m_filefunc, &m_zipmem); @@ -390,9 +391,9 @@ struct Unzipper::Impl { if (!buffer.empty()) { - m_zipmem.base = (char*)malloc(buffer.size() * sizeof(char)); - memcpy(m_zipmem.base, (char*)buffer.data(), buffer.size()); - m_zipmem.size = (uLong)buffer.size(); + m_zipmem.base = reinterpret_cast(malloc(buffer.size() * sizeof(char))); + memcpy(m_zipmem.base, reinterpret_cast(buffer.data()), buffer.size()); + m_zipmem.size = static_cast(buffer.size()); } fill_memory_filefunc(&m_filefunc, &m_zipmem); diff --git a/zipper/unzipper.h b/zipper/unzipper.h index c3df6cf..becb4c4 100644 --- a/zipper/unzipper.h +++ b/zipper/unzipper.h @@ -32,11 +32,15 @@ class Unzipper void close(); private: + void release(); - std::string m_password; - std::string m_zipname; + +private: + std::istream& m_ibuffer; std::vector& m_vecbuffer; + std::string m_zipname; + std::string m_password; bool m_usingMemoryVector; bool m_usingStream; bool m_open; @@ -61,7 +65,8 @@ class ZipEntry public: ZipEntry(const std::string& name, unsigned long long int compressed_size, unsigned long long int uncompressed_size, - int year, int month, int day, int hour, int minute, int second, unsigned long dosdate) + unsigned int year, unsigned int month, unsigned int day, unsigned int hour, unsigned int minute, unsigned int second, + unsigned long dosdate) : name(name), compressedSize(compressed_size), uncompressedSize(uncompressed_size), dosdate(dosdate) { // timestamp YYYY-MM-DD HH:MM:SS diff --git a/zipper/zipper.cpp b/zipper/zipper.cpp index 0a81863..694bffb 100644 --- a/zipper/zipper.cpp +++ b/zipper/zipper.cpp @@ -76,8 +76,8 @@ struct Zipper::Impl { free(m_zipmem.base); } - m_zipmem.base = (char*)malloc(size * sizeof(char)); - stream.read(m_zipmem.base, size); + m_zipmem.base = reinterpret_cast(malloc(size * sizeof(char))); + stream.read(m_zipmem.base, std::streamsize(size)); } fill_memory_filefunc(&m_filefunc, &m_zipmem); @@ -95,9 +95,9 @@ struct Zipper::Impl { free(m_zipmem.base); } - m_zipmem.base = (char*)malloc(buffer.size() * sizeof(char)); - memcpy(m_zipmem.base, (char*)buffer.data(), buffer.size()); - m_zipmem.size = (uLong)buffer.size(); + m_zipmem.base = reinterpret_cast(malloc(buffer.size() * sizeof(char))); + memcpy(m_zipmem.base, reinterpret_cast(buffer.data()), buffer.size()); + m_zipmem.size = static_cast(buffer.size()); } fill_memory_filefunc(&m_filefunc, &m_zipmem); @@ -118,18 +118,18 @@ struct Zipper::Impl return false; int compressLevel = 0; - int zip64 = 0; - int size_buf = WRITEBUFFERSIZE; + bool zip64; + size_t size_buf = WRITEBUFFERSIZE; int err = ZIP_OK; unsigned long crcFile = 0; - zip_fileinfo zi = { 0 }; - zi.tmz_date.tm_sec = timestamp.tm_sec; - zi.tmz_date.tm_min = timestamp.tm_min; - zi.tmz_date.tm_hour = timestamp.tm_hour; - zi.tmz_date.tm_mday = timestamp.tm_mday; - zi.tmz_date.tm_mon = timestamp.tm_mon; - zi.tmz_date.tm_year = timestamp.tm_year; + zip_fileinfo zi; + zi.tmz_date.tm_sec = uInt(timestamp.tm_sec); + zi.tmz_date.tm_min = uInt(timestamp.tm_min); + zi.tmz_date.tm_hour = uInt(timestamp.tm_hour); + zi.tmz_date.tm_mday = uInt(timestamp.tm_mday); + zi.tmz_date.tm_mon = uInt(timestamp.tm_mon); + zi.tmz_date.tm_year = uInt(timestamp.tm_year); size_t size_read; @@ -144,7 +144,7 @@ struct Zipper::Impl if (flags & Zipper::Better) compressLevel = 9; - zip64 = (int)isLargeFile(input_stream); + zip64 = isLargeFile(input_stream); if (password.empty()) { err = zipOpenNewFileInZip64(m_zf, @@ -185,8 +185,8 @@ struct Zipper::Impl do { err = ZIP_OK; - input_stream.read(buff.data(), buff.size()); - size_read = (size_t)input_stream.gcount(); + input_stream.read(buff.data(), std::streamsize(buff.size())); + size_read = static_cast(input_stream.gcount()); if (size_read < buff.size() && !input_stream.eof() && !input_stream.good()) { err = ZIP_ERRNO; @@ -194,7 +194,7 @@ struct Zipper::Impl if (size_read > 0) { - err = zipWriteInFileInZip(this->m_zf, buff.data(), (unsigned int)size_read); + err = zipWriteInFileInZip(this->m_zf, buff.data(), static_cast(size_read)); } } while ((err == ZIP_OK) && (size_read > 0)); } @@ -228,7 +228,7 @@ struct Zipper::Impl } else if (m_outer.m_usingStream) { - m_outer.m_obuffer.write(m_zipmem.base, m_zipmem.limit); + m_outer.m_obuffer.write(m_zipmem.base, std::streamsize(m_zipmem.limit)); } } @@ -246,10 +246,10 @@ struct Zipper::Impl Zipper::Zipper(const std::string& zipname, const std::string& password) : m_obuffer(*(new std::stringstream())) //not used but using local variable throws exception , m_vecbuffer(*(new std::vector())) //not used but using local variable throws exception - , m_usingMemoryVector(false) - , m_usingStream(false) , m_zipname(zipname) , m_password(password) + , m_usingMemoryVector(false) + , m_usingStream(false) , m_impl(new Impl(*this)) { if (!m_impl->initFile(zipname)) @@ -261,11 +261,11 @@ Zipper::Zipper(const std::string& zipname, const std::string& password) } Zipper::Zipper(std::iostream& buffer, const std::string& password) - : m_vecbuffer(*(new std::vector())) //not used but using local variable throws exception - , m_obuffer(buffer) + : m_obuffer(buffer) + , m_vecbuffer(*(new std::vector())) //not used but using local variable throws exception + , m_password(password) , m_usingMemoryVector(false) , m_usingStream(true) - , m_password(password) , m_impl(new Impl(*this)) { if (!m_impl->initWithStream(m_obuffer)) @@ -277,11 +277,11 @@ Zipper::Zipper(std::iostream& buffer, const std::string& password) } Zipper::Zipper(std::vector& buffer, const std::string& password) - : m_vecbuffer(buffer) - , m_obuffer(*(new std::stringstream())) //not used but using local variable throws exception + : m_obuffer(*(new std::stringstream())) //not used but using local variable throws exception + , m_vecbuffer(buffer) + , m_password(password) , m_usingMemoryVector(true) , m_usingStream(false) - , m_password(password) , m_impl(new Impl(*this)) { if (!m_impl->initWithVector(m_vecbuffer)) diff --git a/zipper/zipper.h b/zipper/zipper.h index 25306a2..3c2438c 100644 --- a/zipper/zipper.h +++ b/zipper/zipper.h @@ -36,11 +36,15 @@ class Zipper void close(); private: + void release(); - std::string m_password; - std::string m_zipname; + +private: + std::iostream& m_obuffer; std::vector& m_vecbuffer; + std::string m_zipname; + std::string m_password; bool m_usingMemoryVector; bool m_usingStream; bool m_open; From d6e3b46cd87930f000bcc3d46083b7caa056efef Mon Sep 17 00:00:00 2001 From: Quentin Quadrat Date: Fri, 12 Feb 2021 20:43:15 +0100 Subject: [PATCH 44/86] Remove ability to accidentally create empty zip #75 --- zipper/zipper.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zipper/zipper.h b/zipper/zipper.h index 3c2438c..f78318f 100644 --- a/zipper/zipper.h +++ b/zipper/zipper.h @@ -28,8 +28,8 @@ class Zipper ~Zipper(); - bool add(std::istream& source, const std::tm& timestamp, const std::string& nameInZip = std::string(), zipFlags flags = Better); - bool add(std::istream& source, const std::string& nameInZip = std::string(), zipFlags flags = Better); + bool add(std::istream& source, const std::tm& timestamp, const std::string& nameInZip, zipFlags flags = Better); + bool add(std::istream& source, const std::string& nameInZip, zipFlags flags = Better); bool add(const std::string& fileOrFolderPath, zipFlags flags = Better); void open(); From f8b0df85c02e562420ec9677f5c07f50519001ec Mon Sep 17 00:00:00 2001 From: Quentin Quadrat Date: Fri, 12 Feb 2021 22:48:40 +0100 Subject: [PATCH 45/86] First attempt to give doxygen comments on the API --- .gitignore | 5 +- Doxyfile | 2536 ++++++++++++++++++++++++++++++++++++++++++++ zipper/CDirEntry.h | 61 +- zipper/unzipper.h | 132 ++- zipper/zipper.h | 116 +- 5 files changed, 2795 insertions(+), 55 deletions(-) create mode 100644 Doxyfile diff --git a/.gitignore b/.gitignore index dca99f6..be8d815 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +## Doxygen generated doc +doc/ + ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. @@ -161,4 +164,4 @@ test/*.zip *.txt.user -build/ \ No newline at end of file +build/ diff --git a/Doxyfile b/Doxyfile new file mode 100644 index 0000000..4e0203b --- /dev/null +++ b/Doxyfile @@ -0,0 +1,2536 @@ +# Doxyfile 1.8.17 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = zipper + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = 1.0.1 + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = C++ wrapper around minizip compression library + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = ./doc + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all generated output in the proper direction. +# Possible values are: None, LTR, RTL and Context. +# The default value is: None. + +OUTPUT_TEXT_DIRECTION = None + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = NO + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = YES + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = YES + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = YES + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. +# When you need a literal { or } or , in the value part of an alias you have to +# escape them by means of a backslash (\), this can lead to conflicts with the +# commands \{ and \} for these it is advised to use the version @{ and @} or use +# a double escape (\\{ and \\}) + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = NO + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, +# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files), VHDL, tcl. For instance to make doxygen treat +# .inc files as Fortran files (default is PHP), and .f files as C (default is +# Fortran), use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See https://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 0 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO, these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES, upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# (including Cygwin) ands Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. If +# EXTRACT_ALL is set to YES then this flag will automatically be disabled. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = README.md \ + ./zipper + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: https://www.gnu.org/software/libiconv/) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), +# *.doc (to be provided as doxygen C comment), *.txt (to be provided as doxygen +# C comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f, *.for, *.tcl, *.vhd, +# *.vhdl, *.ucf, *.qsf and *.ice. + +FILE_PATTERNS = *.c \ + *.cpp \ + *.ipp \ + *.tpp \ + *.hpp \ + *.h \ + *.md + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = .git \ + build \ + external \ + tests + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = README.md + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# entity all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = NO + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = YES + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + +# If clang assisted parsing is enabled you can provide the clang parser with the +# path to the compilation database (see: +# http://clang.llvm.org/docs/HowToSetupToolingForLLVM.html) used when the files +# were built. This is equivalent to specifying the "-p" option to a clang tool, +# such as clang-check. These options will then be passed to the parser. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse_libclang=ON option for CMake. + +CLANG_DATABASE_PATH = + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = YES + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via Javascript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have Javascript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: https://developer.apple.com/xcode/), introduced with OSX +# 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "OpenGLCppWrapper Documentation" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.OpenGLCppWrapper + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.OpenGLCppWrapper + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = OpenGLCppWrapper + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: https://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NO + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = https://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /