diff --git a/CMakeLists.txt b/CMakeLists.txt index 22b982902..ebdb56064 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,10 +6,10 @@ # ENABLE_{COMPONENT} # ENABLE_TESTS -project(Poco) - cmake_minimum_required(VERSION 3.0.0) +project(Poco) + file(STRINGS "${PROJECT_SOURCE_DIR}/libversion" SHARED_LIBRARY_VERSION) # Read the version information from the VERSION file @@ -51,20 +51,7 @@ endif() if (CMAKE_BUILD_TYPE STREQUAL "") set( CMAKE_BUILD_TYPE "RelWithDebInfo" ) -endif () - -# http://www.cmake.org/Wiki/CMake_Useful_Variables : -# CMAKE_BUILD_TYPE -# Choose the type of build. CMake has default flags for these: -# -# * None (CMAKE_C_FLAGS or CMAKE_CXX_FLAGS used) -# * Debug (CMAKE_C_FLAGS_DEBUG or CMAKE_CXX_FLAGS_DEBUG) -# * Release (CMAKE_C_FLAGS_RELEASE or CMAKE_CXX_FLAGS_RELEASE) -# * RelWithDebInfo (CMAKE_C_FLAGS_RELWITHDEBINFO or CMAKE_CXX_FLAGS_RELWITHDEBINFO -# * MinSizeRel (CMAKE_C_FLAGS_MINSIZEREL or CMAKE_CXX_FLAGS_MINSIZEREL) - -# For Debug build types, append a "d" to the library names. -set(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Set debug library postfix" FORCE) +endif() # Include some common macros to simpilfy the Poco CMake files include(PocoMacros) @@ -102,7 +89,12 @@ option(POCO_STATIC option(POCO_UNBUNDLED "Set to OFF|ON (default is OFF) to control linking dependencies as external" OFF) -# Uncomment from next two lines to force statitc or dynamic library, default is autodetection +if(MSVC) + option(POCO_MT + "Set to OFF|ON (default is OFF) to control build of POCO as /MT instead of /MD" OFF) +endif() + +# Uncomment from next two lines to force static or dynamic library, default is autodetection if(POCO_STATIC) add_definitions( -DPOCO_STATIC -DPOCO_NO_AUTOMATIC_LIBS) set( LIB_MODE STATIC ) @@ -127,58 +119,7 @@ else () message(STATUS "Build with using internal copy of sqlite, libz, pcre, expat, ...") endif () -include(CheckTypeSize) -find_package(Cygwin) - -# OS Detection -if(WIN32) - add_definitions( -DPOCO_OS_FAMILY_WINDOWS -DUNICODE -D_UNICODE) - #set(SYSLIBS iphlpapi gdi32 odbc32) -endif(WIN32) - -if (UNIX AND NOT ANDROID ) - add_definitions( -DPOCO_OS_FAMILY_UNIX ) - # Standard 'must be' defines - if (APPLE) - add_definitions( -DPOCO_HAVE_IPv6 -DPOCO_NO_STAT64) - set(SYSLIBS dl) - else (APPLE) - add_definitions( -D_XOPEN_SOURCE=500 -D_REENTRANT -D_THREAD_SAFE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64) - set(SYSLIBS pthread dl rt) - endif (APPLE) -endif(UNIX AND NOT ANDROID ) - -if (CMAKE_SYSTEM MATCHES "SunOS") - add_definitions( -DPOCO_OS_FAMILY_UNIX ) - # Standard 'must be' defines - add_definitions( -D_XOPEN_SOURCE=500 -D_REENTRANT -D_THREAD_SAFE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 ) - set(SYSLIBS pthread socket xnet nsl resolv rt dl) -endif(CMAKE_SYSTEM MATCHES "SunOS") - -if (CMAKE_COMPILER_IS_MINGW) - add_definitions(-DWC_NO_BEST_FIT_CHARS=0x400 -DPOCO_WIN32_UTF8) - add_definitions(-D_WIN32 -DMINGW32 -DWINVER=0x500 -DODBCVER=0x0300 -DPOCO_THREAD_STACK_SIZE) -endif (CMAKE_COMPILER_IS_MINGW) - -if (CYGWIN) -# add_definitions(-DWC_NO_BEST_FIT_CHARS=0x400 -DPOCO_WIN32_UTF8) -endif (CYGWIN) - -# SunPro C++ -if (${CMAKE_CXX_COMPILER_ID} MATCHES "SunPro") - add_definitions( -D_BSD_SOURCE -library=stlport4) -endif (${CMAKE_CXX_COMPILER_ID} MATCHES "SunPro") - -# iOS -if (IOS) - add_definitions( -DPOCO_HAVE_IPv6 -DPOCO_NO_FPENVIRONMENT -DPOCO_NO_STAT64 -DPOCO_NO_SHAREDLIBS -DPOCO_NO_NET_IFTYPES ) -endif(IOS) - -#Android -if (ANDROID) - add_definitions( -DPOCO_ANDROID -DPOCO_NO_FPENVIRONMENT -DPOCO_NO_WSTRING -DPOCO_NO_SHAREDMEMORY ) -endif(ANDROID) - +include(DefinePlatformSpecifc) # Collect the built libraries and include dirs, the will be used to create the PocoConfig.cmake file set(Poco_COMPONENTS "") @@ -330,7 +271,17 @@ message(STATUS "CMake ${CMAKE_VERSION} successfully configured ${PROJECT_NAME} u message(STATUS "Installation target path: ${CMAKE_INSTALL_PREFIX}") message(STATUS "C_FLAGS: =${CMAKE_C_FLAGS}") +message(STATUS "CMAKE_C_FLAGS_DEBUG:=${CMAKE_C_FLAGS_DEBUG}") +message(STATUS "CMAKE_C_FLAGS_RELEASE:=${CMAKE_C_FLAGS_RELEASE}") +message(STATUS "CMAKE_C_FLAGS_MINSIZEREL:=${CMAKE_C_FLAGS_MINSIZEREL}") +message(STATUS "CMAKE_C_FLAGS_RELWITHDEBINFO:=${CMAKE_C_FLAGS_RELWITHDEBINFO}") +message(STATUS "") +message(STATUS "") message(STATUS "CXX_FLAGS:=${CMAKE_CXX_FLAGS}") +message(STATUS "CMAKE_CXX_FLAGS_DEBUG:=${CMAKE_CXX_FLAGS_DEBUG}") +message(STATUS "CMAKE_CXX_FLAGS_RELEASE:=${CMAKE_CXX_FLAGS_RELEASE}") +message(STATUS "CMAKE_CXX_FLAGS_MINSIZEREL:=${CMAKE_CXX_FLAGS_MINSIZEREL}") +message(STATUS "CMAKE_CXX_FLAGS_RELWITHDEBINFO:=${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") foreach(component ${Poco_COMPONENTS}) message(STATUS "Building: ${component}") diff --git a/Crypto/include/Poco/Crypto/OpenSSLInitializer.h b/Crypto/include/Poco/Crypto/OpenSSLInitializer.h index ade2531e1..f647d3614 100644 --- a/Crypto/include/Poco/Crypto/OpenSSLInitializer.h +++ b/Crypto/include/Poco/Crypto/OpenSSLInitializer.h @@ -44,7 +44,7 @@ namespace Crypto { class Crypto_API OpenSSLInitializer - /// Initializes the OpenSSL library. + /// Initalizes the OpenSSL library. /// /// The class ensures the earliest initialization and the /// latest shutdown of the OpenSSL library. @@ -68,6 +68,8 @@ public: static void enableFIPSMode(bool enabled); // Enable or disable FIPS mode. If FIPS is not available, this method doesn't do anything. + static void disableSSLInitialization(); // Call if OpenSSL is already being initialized by another component before constructing any OpenSSLInitializers. + protected: enum { @@ -84,6 +86,7 @@ protected: private: static Poco::FastMutex* _mutexes; static Poco::AtomicCounter _rc; + static bool _disableSSLInitialization; }; @@ -110,6 +113,11 @@ inline void OpenSSLInitializer::enableFIPSMode(bool /*enabled*/) } #endif +inline void OpenSSLInitializer::disableSSLInitialization() +{ + _disableSSLInitialization = true; +} + } } // namespace Poco::Crypto diff --git a/Crypto/src/OpenSSLInitializer.cpp b/Crypto/src/OpenSSLInitializer.cpp index 28ecd115d..d76ca2f23 100644 --- a/Crypto/src/OpenSSLInitializer.cpp +++ b/Crypto/src/OpenSSLInitializer.cpp @@ -36,7 +36,7 @@ namespace Crypto { Poco::FastMutex* OpenSSLInitializer::_mutexes(0); Poco::AtomicCounter OpenSSLInitializer::_rc; - +bool OpenSSLInitializer::_disableSSLInitialization = false; OpenSSLInitializer::OpenSSLInitializer() { @@ -64,18 +64,21 @@ void OpenSSLInitializer::initialize() #if OPENSSL_VERSION_NUMBER >= 0x0907000L OPENSSL_config(NULL); #endif - SSL_library_init(); - SSL_load_error_strings(); - OpenSSL_add_all_algorithms(); - + if(! _disableSSLInitialization) { + SSL_library_init(); + SSL_load_error_strings(); + OpenSSL_add_all_algorithms(); + } + char seed[SEEDSIZE]; RandomInputStream rnd; rnd.read(seed, sizeof(seed)); RAND_seed(seed, SEEDSIZE); - int nMutexes = CRYPTO_num_locks(); - _mutexes = new Poco::FastMutex[nMutexes]; - CRYPTO_set_locking_callback(&OpenSSLInitializer::lock); + if(CRYPTO_get_locking_callback() == NULL) { + int nMutexes = CRYPTO_num_locks(); + _mutexes = new Poco::FastMutex[nMutexes]; + CRYPTO_set_locking_callback(&OpenSSLInitializer::lock); #ifndef POCO_OS_FAMILY_WINDOWS // Not needed on Windows (see SF #110: random unhandled exceptions when linking with ssl). // https://sourceforge.net/p/poco/bugs/110/ @@ -84,11 +87,17 @@ void OpenSSLInitializer::initialize() // "If the application does not register such a callback using CRYPTO_THREADID_set_callback(), // then a default implementation is used - on Windows and BeOS this uses the system's // default thread identifying APIs" - CRYPTO_set_id_callback(&OpenSSLInitializer::id); +#ifndef OPENSSL_NO_DEPRECATED + CRYPTO_set_id_callback(&OpenSSLInitializer::id); +#else + CRYPTO_THREADID tid; + CRYPTO_THREADID_set_numeric(&tid, OpenSSLInitializer::id()); +#endif /* OPENSSL_NO_DEPRECATED */ #endif - CRYPTO_set_dynlock_create_callback(&OpenSSLInitializer::dynlockCreate); - CRYPTO_set_dynlock_lock_callback(&OpenSSLInitializer::dynlock); - CRYPTO_set_dynlock_destroy_callback(&OpenSSLInitializer::dynlockDestroy); + CRYPTO_set_dynlock_create_callback(&OpenSSLInitializer::dynlockCreate); + CRYPTO_set_dynlock_lock_callback(&OpenSSLInitializer::dynlock); + CRYPTO_set_dynlock_destroy_callback(&OpenSSLInitializer::dynlockDestroy); + } } } @@ -97,15 +106,26 @@ void OpenSSLInitializer::uninitialize() { if (--_rc == 0) { - EVP_cleanup(); - ERR_free_strings(); - CRYPTO_set_locking_callback(0); + if(_mutexes != NULL) { + CRYPTO_set_dynlock_create_callback(0); + CRYPTO_set_dynlock_lock_callback(0); + CRYPTO_set_dynlock_destroy_callback(0); + CRYPTO_set_locking_callback(0); #ifndef POCO_OS_FAMILY_WINDOWS - CRYPTO_set_id_callback(0); +#ifndef OPENSSL_NO_DEPRECATED + CRYPTO_set_id_callback(0); +#else + CRYPTO_THREADID tid; + CRYPTO_THREADID_set_numeric(&tid, 0); +#endif /* OPENSSL_NO_DEPRECATED */ #endif - delete [] _mutexes; - - CONF_modules_free(); + delete [] _mutexes; + } + if(! _disableSSLInitialization) { + EVP_cleanup(); + ERR_free_strings(); + CONF_modules_free(); + } } } diff --git a/Data/include/Poco/Data/Transaction.h b/Data/include/Poco/Data/Transaction.h index c231dbebe..bdecbbba9 100644 --- a/Data/include/Poco/Data/Transaction.h +++ b/Data/include/Poco/Data/Transaction.h @@ -117,7 +117,7 @@ public: /// of this Transaction object. template - void transact(T& t) + void transact(const T& t) /// Executes the transactor and, unless transactor throws an exception, /// commits the transaction. { diff --git a/FAQ.md b/FAQ.md new file mode 100644 index 000000000..fc008e381 --- /dev/null +++ b/FAQ.md @@ -0,0 +1,49 @@ +# POCO Frequently Asked Questions +--- + +## Generic Questions + +**Q:** How do I do [xyz] with POCO? + +**A:** It depends on what exactly [xyz] is. POCO community is more than happy to help newcomers and experienced C++ programmers alike. There are, however, certain limitations as to how far we are willing to go as well as expectations we have for people asking questions: + + - First and foremost, read the relevant [documentation](http://pocoproject.org/documentation/index.html) + + - Please be patient and respectful; we answer questions free of charge and our time is at least as valuable as yours. + + - Please do [your share of work before asking](#resources); since we are doing this free of charge, make sure to make it as easy as possible for us to identify the problem - it will greatly increase the chances of getting an answer. + + - Please do not ask us to solve your homework, commercial or hobby project application problems; although we provide answers free of monetary charge, we do have an incentive - improving POCO for yours and our benefit. Your question may contain important information in that sense but you must demonstrate it clearly to get our attention quickly. In the process, the solution to your particular problem is often a side-effect; we are happy to help, but keep in mind - that is not our primary incentive. + + - We are not here to teach you about basics of networking, XML or JSON parsing, C++ language etc.; there are many other resources to learn about those topics. Keep in mind our primary incentive (improving POCO by fixing bugs, improving usability or adding features). + + - If nobody steps up to help or someone starts but chooses to stop helping you at any point, please do not get upset and/or verbally abusive; remember - we have lives and obligations and we do this free of charge, therefore owe you nothing unless you choose to enter into a contractual relationship with us to obtain needed help; we do such arrangements and you can contact us individually should you need one. Consider also that your demeanor may have caused the person helping to you to stop. + + - Please spend some time studying the answers we provide; do not come back without thoroughly understanding and trying the proposed solution + +Resources to help with asking the question right and provide code examples in an effective and productive manner: + +- [Getting Started With The POCO C++ Libraries](http://pocoproject.org/docs/00200-GettingStarted.html) +- [How To Ask Questions The Smart Way](http://www.catb.org/esr/faqs/smart-questions.html) +- [How to create a Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve) + +-- +**Q:** How do I contribute to POCO? + +**A:** See [Contributing](https://github.com/pocoproject/poco/blob/develop/CONTRIBUTING.md) + +## Specific Questions + +**Q:** How do I build POCO on platform [xyz]? + +**A:** POCO builds out-of-the-box on many platforms. See [Building portion](http://pocoproject.org/docs/00200-GettingStarted.html#7) for your platform in the [Getting Started](http://pocoproject.org/docs/00200-GettingStarted.html) document. If things don't work according to the documentation, please let us know. If you find a problem and know how to fix it, please do and send us a [pull request](https://help.github.com/articles/using-pull-requests/). + +-- +**Q:** Is there a coding style guide? + +**A:** [Yes](http://www.appinf.com/download/CppCodingStyleGuide.pdf). + +-- +**Q:** Where can I find examples of POCO usage? + +**A:** Every POCO library comes with a set of small, fully-functional, example applications; the samples are located in the "samples" directory of each POCO library; additionally, the knowledge on usage of POCO can also be gained by studying and running unit tests, located under "testsuite" directory for each POCO library. diff --git a/Foundation/include/Poco/Bugcheck.h b/Foundation/include/Poco/Bugcheck.h index 7dab4998e..941676029 100644 --- a/Foundation/include/Poco/Bugcheck.h +++ b/Foundation/include/Poco/Bugcheck.h @@ -148,11 +148,6 @@ protected: // -#if defined(POCO_COMPILER_GCC) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 408) && !defined(POCO_ANDROID) - GCC_DIAG_OFF(unused-local-typedefs) // supress numerous gcc warnings -#endif // POCO_COMPILER_GCC && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 408) - - template struct POCO_STATIC_ASSERTION_FAILURE; @@ -180,7 +175,7 @@ struct poco_static_assert_test #else #define poco_static_assert(B) \ typedef poco_static_assert_test)> \ - POCO_JOIN(poco_static_assert_typedef_, __LINE__) + POCO_JOIN(poco_static_assert_typedef_, __LINE__) POCO_UNUSED #endif diff --git a/Foundation/include/Poco/Platform.h b/Foundation/include/Poco/Platform.h index 45b454c71..29660e25b 100644 --- a/Foundation/include/Poco/Platform.h +++ b/Foundation/include/Poco/Platform.h @@ -112,12 +112,6 @@ #endif -#ifndef __GNUC__ - #define GCC_DIAG_OFF(x) - #define GCC_DIAG_ON(x) -#endif - - // // Hardware Architecture and Byte Order // @@ -257,6 +251,13 @@ #endif +#ifdef __GNUC__ +#define POCO_UNUSED __attribute__((unused)) +#else +#define POCO_UNUSED +#endif // __GNUC__ + + #if !defined(POCO_ARCH) #error "Unknown Hardware Architecture." #endif diff --git a/Foundation/include/Poco/Platform_POSIX.h b/Foundation/include/Poco/Platform_POSIX.h index dc877fbdc..6a9189c15 100644 --- a/Foundation/include/Poco/Platform_POSIX.h +++ b/Foundation/include/Poco/Platform_POSIX.h @@ -44,38 +44,6 @@ #endif -// -// GCC diagnostics enable/disable by Patrick Horgan, see -// http://dbp-consulting.com/tutorials/SuppressingGCCWarnings.html -// use example: GCC_DIAG_OFF(unused-variable) -// -#ifdef __GNUC__ - #if defined(POCO_COMPILER_GCC) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) && !defined(POCO_NO_GCC_DIAG) - #ifdef GCC_DIAG_OFF - #undef GCC_DIAG_OFF - #endif - #ifdef GCC_DIAG_ON - #undef GCC_DIAG_ON - #endif - #define GCC_DIAG_STR(s) #s - #define GCC_DIAG_JOINSTR(x,y) GCC_DIAG_STR(x ## y) - #define GCC_DIAG_DO_PRAGMA(x) _Pragma (#x) - #define GCC_DIAG_PRAGMA(x) GCC_DIAG_DO_PRAGMA(GCC diagnostic x) - #if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406 - #define GCC_DIAG_OFF(x) GCC_DIAG_PRAGMA(push) \ - GCC_DIAG_PRAGMA(ignored GCC_DIAG_JOINSTR(-W,x)) - #define GCC_DIAG_ON(x) GCC_DIAG_PRAGMA(pop) - #else - #define GCC_DIAG_OFF(x) GCC_DIAG_PRAGMA(ignored GCC_DIAG_JOINSTR(-W,x)) - #define GCC_DIAG_ON(x) GCC_DIAG_PRAGMA(warning GCC_DIAG_JOINSTR(-W,x)) - #endif - #else - #define GCC_DIAG_OFF(x) - #define GCC_DIAG_ON(x) - #endif -#endif // __GNUC__ - - // // No syslog.h on QNX/BB10 // diff --git a/Foundation/src/Thread_POSIX.cpp b/Foundation/src/Thread_POSIX.cpp index 97813fbca..7bd66a8f4 100644 --- a/Foundation/src/Thread_POSIX.cpp +++ b/Foundation/src/Thread_POSIX.cpp @@ -225,7 +225,6 @@ void ThreadImpl::setAffinityImpl(int cpu) int ThreadImpl::getAffinityImpl() const { int cpuSet = -1; - int cpuCount = Environment::processorCount(); #if defined (POCO_OS_FAMILY_UNIX) && POCO_OS != POCO_OS_MAC_OS_X #ifdef HAVE_PTHREAD_SETAFFINITY_NP cpu_set_t cpuset; @@ -237,6 +236,7 @@ int ThreadImpl::getAffinityImpl() const if (pthread_getaffinity_np(_pData->thread, &cpuset) != 0) throw SystemException("Failed to get affinity", errno); #endif + int cpuCount = Environment::processorCount(); for (int i = 0; i < cpuCount; i++) { if (CPU_ISSET(i, &cpuset)) @@ -263,6 +263,7 @@ int ThreadImpl::getAffinityImpl() const throw SystemException("Failed to get affinity", errno); } cpuSet = policy.affinity_tag; + int cpuCount = Environment::processorCount(); if (cpuSet >= cpuCount) cpuSet = -1; diff --git a/Foundation/testsuite/src/AnyTest.cpp b/Foundation/testsuite/src/AnyTest.cpp index 330789b7f..cd2b0da6e 100644 --- a/Foundation/testsuite/src/AnyTest.cpp +++ b/Foundation/testsuite/src/AnyTest.cpp @@ -18,11 +18,12 @@ #include "Poco/Bugcheck.h" #include -GCC_DIAG_OFF(unused-but-set-variable) + #if defined(_MSC_VER) && _MSC_VER < 1400 #pragma warning(disable:4800)//forcing value to bool 'true' or 'false' #endif + using namespace Poco; diff --git a/Foundation/testsuite/src/ClassLoaderTest.cpp b/Foundation/testsuite/src/ClassLoaderTest.cpp index 7b697f8f7..9ab4e6bbf 100644 --- a/Foundation/testsuite/src/ClassLoaderTest.cpp +++ b/Foundation/testsuite/src/ClassLoaderTest.cpp @@ -18,7 +18,6 @@ #include "Poco/Exception.h" #include "TestPlugin.h" -GCC_DIAG_OFF(unused-variable) using Poco::ClassLoader; using Poco::Manifest; diff --git a/Foundation/testsuite/src/CoreTest.cpp b/Foundation/testsuite/src/CoreTest.cpp index d1226b52c..bf8b03dce 100644 --- a/Foundation/testsuite/src/CoreTest.cpp +++ b/Foundation/testsuite/src/CoreTest.cpp @@ -31,7 +31,6 @@ #include #include -GCC_DIAG_OFF(unused-variable) using Poco::Bugcheck; using Poco::Exception; diff --git a/Foundation/testsuite/src/DateTimeTest.cpp b/Foundation/testsuite/src/DateTimeTest.cpp index 55146f780..969e7bc9b 100644 --- a/Foundation/testsuite/src/DateTimeTest.cpp +++ b/Foundation/testsuite/src/DateTimeTest.cpp @@ -19,9 +19,6 @@ #include "Poco/Exception.h" -GCC_DIAG_OFF(unused-variable) - - using Poco::Timestamp; using Poco::DateTime; using Poco::Timespan; diff --git a/Foundation/testsuite/src/FileTest.cpp b/Foundation/testsuite/src/FileTest.cpp index d5586623e..a9dfb1932 100644 --- a/Foundation/testsuite/src/FileTest.cpp +++ b/Foundation/testsuite/src/FileTest.cpp @@ -21,7 +21,6 @@ #include #include -GCC_DIAG_OFF(unused-variable) using Poco::File; using Poco::TemporaryFile; diff --git a/Foundation/testsuite/src/HashMapTest.cpp b/Foundation/testsuite/src/HashMapTest.cpp index b101dc39b..5f14ad4ea 100644 --- a/Foundation/testsuite/src/HashMapTest.cpp +++ b/Foundation/testsuite/src/HashMapTest.cpp @@ -17,7 +17,6 @@ #include "Poco/Exception.h" #include -GCC_DIAG_OFF(unused-variable) using Poco::HashMap; diff --git a/Foundation/testsuite/src/HashTableTest.cpp b/Foundation/testsuite/src/HashTableTest.cpp index 34478a7a9..da305b991 100644 --- a/Foundation/testsuite/src/HashTableTest.cpp +++ b/Foundation/testsuite/src/HashTableTest.cpp @@ -17,9 +17,6 @@ #include "Poco/NumberFormatter.h" -GCC_DIAG_OFF(unused-variable) - - using namespace Poco; diff --git a/Foundation/testsuite/src/ListMapTest.cpp b/Foundation/testsuite/src/ListMapTest.cpp index 527cb6e29..e3b1ae0c1 100644 --- a/Foundation/testsuite/src/ListMapTest.cpp +++ b/Foundation/testsuite/src/ListMapTest.cpp @@ -17,7 +17,6 @@ #include "Poco/Exception.h" #include -GCC_DIAG_OFF(unused-variable) using Poco::ListMap; diff --git a/Foundation/testsuite/src/LoggingRegistryTest.cpp b/Foundation/testsuite/src/LoggingRegistryTest.cpp index 238d46a6b..8ed076521 100644 --- a/Foundation/testsuite/src/LoggingRegistryTest.cpp +++ b/Foundation/testsuite/src/LoggingRegistryTest.cpp @@ -18,7 +18,6 @@ #include "Poco/PatternFormatter.h" #include "Poco/AutoPtr.h" -GCC_DIAG_OFF(unused-variable) using Poco::LoggingRegistry; using Poco::Channel; diff --git a/Foundation/testsuite/src/NamedTuplesTest.cpp b/Foundation/testsuite/src/NamedTuplesTest.cpp index f0a2fc018..3442e52b5 100644 --- a/Foundation/testsuite/src/NamedTuplesTest.cpp +++ b/Foundation/testsuite/src/NamedTuplesTest.cpp @@ -16,7 +16,6 @@ #include "Poco/NamedTuple.h" #include "Poco/Exception.h" -GCC_DIAG_OFF(unused-but-set-variable) using Poco::NamedTuple; using Poco::Int8; diff --git a/Foundation/testsuite/src/SimpleHashTableTest.cpp b/Foundation/testsuite/src/SimpleHashTableTest.cpp index 294e57a06..3ee4081eb 100644 --- a/Foundation/testsuite/src/SimpleHashTableTest.cpp +++ b/Foundation/testsuite/src/SimpleHashTableTest.cpp @@ -17,9 +17,6 @@ #include "Poco/NumberFormatter.h" -GCC_DIAG_OFF(unused-variable) - - using namespace Poco; diff --git a/Foundation/testsuite/src/StringTokenizerTest.cpp b/Foundation/testsuite/src/StringTokenizerTest.cpp index 5a7bbabc6..a2e4f6127 100644 --- a/Foundation/testsuite/src/StringTokenizerTest.cpp +++ b/Foundation/testsuite/src/StringTokenizerTest.cpp @@ -16,7 +16,6 @@ #include "Poco/StringTokenizer.h" #include "Poco/Exception.h" -GCC_DIAG_OFF(unused-variable) using Poco::StringTokenizer; using Poco::RangeException; diff --git a/Foundation/testsuite/src/TypeListTest.cpp b/Foundation/testsuite/src/TypeListTest.cpp index 4e6375f11..02bcdd2b0 100644 --- a/Foundation/testsuite/src/TypeListTest.cpp +++ b/Foundation/testsuite/src/TypeListTest.cpp @@ -18,11 +18,12 @@ #include "Poco/Void.h" #include -GCC_DIAG_OFF(unused-but-set-variable) + #if defined(_MSC_VER) # pragma warning(disable:4800) // forcing value to bool 'true' or 'false' on MSVC 71 #endif + using Poco::TypeList; using Poco::Tuple; using Poco::NullTypeList; diff --git a/Foundation/testsuite/src/VarTest.cpp b/Foundation/testsuite/src/VarTest.cpp index 2a7d73a56..c2b01dd34 100644 --- a/Foundation/testsuite/src/VarTest.cpp +++ b/Foundation/testsuite/src/VarTest.cpp @@ -22,7 +22,7 @@ #include -GCC_DIAG_OFF(unused-variable) + #if defined(_MSC_VER) && _MSC_VER < 1400 #pragma warning(disable:4800)//forcing value to bool 'true' or 'false' #endif diff --git a/Foundation/testsuite/src/VarTest.h b/Foundation/testsuite/src/VarTest.h index 7e27108da..f911042d5 100644 --- a/Foundation/testsuite/src/VarTest.h +++ b/Foundation/testsuite/src/VarTest.h @@ -21,7 +21,6 @@ #include "Poco/Exception.h" #include "CppUnit/TestCase.h" -GCC_DIAG_OFF(unused-but-set-variable) class VarTest: public CppUnit::TestCase { diff --git a/JSON/src/Object.cpp b/JSON/src/Object.cpp index 683ec8ff0..a22bf0b61 100644 --- a/JSON/src/Object.cpp +++ b/JSON/src/Object.cpp @@ -107,7 +107,7 @@ const std::string& Object::getKey(KeyPtrList::const_iterator& iter) const ValueMap::const_iterator end = _values.end(); for (; it != end; ++it) { - if (&it->second == *iter) return it->first; + if (it->second == **iter) return it->first; } throw NotFoundException((*iter)->convert()); diff --git a/MongoDB/include/Poco/MongoDB/Document.h b/MongoDB/include/Poco/MongoDB/Document.h index 589213d82..226769f0a 100644 --- a/MongoDB/include/Poco/MongoDB/Document.h +++ b/MongoDB/include/Poco/MongoDB/Document.h @@ -185,7 +185,7 @@ protected: inline Document& Document::addElement(Element::Ptr element) { - _elements.insert(element); + _elements.push_back(element); return *this; } diff --git a/MongoDB/include/Poco/MongoDB/Element.h b/MongoDB/include/Poco/MongoDB/Element.h index 5e45bf731..790a4af96 100644 --- a/MongoDB/include/Poco/MongoDB/Element.h +++ b/MongoDB/include/Poco/MongoDB/Element.h @@ -33,7 +33,7 @@ #include #include #include -#include +#include namespace Poco { @@ -76,17 +76,7 @@ inline std::string Element::name() const } -class ElementComparator -{ -public: - bool operator()(const Element::Ptr& s1, const Element::Ptr& s2) - { - return s1->name() < s2->name(); - } -}; - - -typedef std::set ElementSet; +typedef std::list ElementSet; template diff --git a/MongoDB/samples/SQLToMongo/src/SQLToMongo.cpp b/MongoDB/samples/SQLToMongo/src/SQLToMongo.cpp index c744ec3b4..df3d9744d 100644 --- a/MongoDB/samples/SQLToMongo/src/SQLToMongo.cpp +++ b/MongoDB/samples/SQLToMongo/src/SQLToMongo.cpp @@ -234,7 +234,7 @@ void sample5(Poco::MongoDB::Connection& connection) // When orderby is needed, use 2 separate documents in the query selector cursor.query().selector().addNewDocument("$query").add("birthyear", 1987); - cursor.query().selector().addNewDocument("$orderby").add("lastname", 0); + cursor.query().selector().addNewDocument("$orderby").add("lastname", -1); Poco::MongoDB::ResponseMessage& response = cursor.next(connection); while(1) @@ -410,7 +410,7 @@ void sample11(Poco::MongoDB::Connection& connection) if ( response.hasDocuments() ) { - std::cout << "Count: " << response.documents()[0]->get("n") << std::endl; + std::cout << "Count: " << response.documents()[0]->get("n") << std::endl; } } diff --git a/MongoDB/src/Document.cpp b/MongoDB/src/Document.cpp index a3863e30e..f9ce2c98c 100644 --- a/MongoDB/src/Document.cpp +++ b/MongoDB/src/Document.cpp @@ -120,7 +120,7 @@ void Document::read(BinaryReader& reader) } element->read(reader); - _elements.insert(element); + _elements.push_back(element); reader >> type; } diff --git a/MongoDB/testsuite/src/MongoDBTest.cpp b/MongoDB/testsuite/src/MongoDBTest.cpp index e55418fef..d7156009a 100644 --- a/MongoDB/testsuite/src/MongoDBTest.cpp +++ b/MongoDB/testsuite/src/MongoDBTest.cpp @@ -410,6 +410,29 @@ void MongoDBTest::testObjectID() } +void MongoDBTest::testCommand() { + Poco::MongoDB::Database db("team"); + Poco::SharedPtr command = db.createCommand(); + command->selector().add("create", "fixCol") + .add("capped", true) + .add("max", 1024*1024) + .add("size", 1024); + + Poco::MongoDB::ResponseMessage response; + _mongo.sendRequest(*command, response); + if ( response.documents().size() > 0 ) + { + Poco::MongoDB::Document::Ptr doc = response.documents()[0]; + std::cout << doc->toString(2); + } + else + { + Poco::MongoDB::Document::Ptr lastError = db.getLastErrorDoc(_mongo); + std::cout << "LastError: " << lastError->toString(2) << std::endl; + fail("Didn't get a response from the command"); + } +} + CppUnit::Test* MongoDBTest::suite() { CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("MongoDBTest"); @@ -425,6 +448,7 @@ CppUnit::Test* MongoDBTest::suite() CppUnit_addTest(pSuite, MongoDBTest, testBuildInfo); CppUnit_addTest(pSuite, MongoDBTest, testCursorRequest); CppUnit_addTest(pSuite, MongoDBTest, testObjectID); + CppUnit_addTest(pSuite, MongoDBTest, testCommand); return pSuite; } diff --git a/MongoDB/testsuite/src/MongoDBTest.h b/MongoDB/testsuite/src/MongoDBTest.h index 7e7de188f..940695568 100644 --- a/MongoDB/testsuite/src/MongoDBTest.h +++ b/MongoDB/testsuite/src/MongoDBTest.h @@ -41,6 +41,7 @@ public: void testConnectionPool(); void testCursorRequest(); void testObjectID(); + void testCommand(); void setUp(); void tearDown(); diff --git a/Net/testsuite/src/HTTPResponseTest.cpp b/Net/testsuite/src/HTTPResponseTest.cpp index 83e84bf2c..424ecfd5a 100644 --- a/Net/testsuite/src/HTTPResponseTest.cpp +++ b/Net/testsuite/src/HTTPResponseTest.cpp @@ -18,7 +18,6 @@ #include "Poco/Net/NetException.h" #include -GCC_DIAG_OFF(parentheses) using Poco::Net::HTTPResponse; using Poco::Net::HTTPMessage; diff --git a/Util/CMakeLists.txt b/Util/CMakeLists.txt index 852519227..4bd083f58 100644 --- a/Util/CMakeLists.txt +++ b/Util/CMakeLists.txt @@ -24,7 +24,18 @@ set_target_properties( "${LIBNAME}" DEFINE_SYMBOL Util_EXPORTS ) -target_link_libraries( "${LIBNAME}" JSON XML Foundation) +target_link_libraries( "${LIBNAME}" Foundation) +if (ENABLE_XML) + target_link_libraries( "${LIBNAME}" XML) +else () + add_definitions( -DPOCO_UTIL_NO_XMLCONFIGURATION ) +endif() +if (ENABLE_JSON) + target_link_libraries( "${LIBNAME}" JSON) +else () + add_definitions( -DPOCO_UTIL_NO_JSONCONFIGURATION ) +endif() + target_include_directories( "${LIBNAME}" PUBLIC $ diff --git a/Zip/include/Poco/Zip/Compress.h b/Zip/include/Poco/Zip/Compress.h index 3e9e931d9..670f6ff86 100644 --- a/Zip/include/Poco/Zip/Compress.h +++ b/Zip/include/Poco/Zip/Compress.h @@ -5,14 +5,14 @@ // // Library: Zip // Package: Zip -// Module: Compress +// Module: Compress // // Definition of the Compress class. // // Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // and Contributors. // -// SPDX-License-Identifier: BSL-1.0 +// SPDX-License-Identifier: BSL-1.0 // @@ -38,9 +38,11 @@ class Zip_API Compress public: Poco::FIFOEvent EDone; - Compress(std::ostream& out, bool seekableOut); + Compress(std::ostream& out, bool seekableOut, bool forceZip64 = false); /// seekableOut determines how we write the zip, setting it to true is recommended for local files (smaller zip file), /// if you are compressing directly to a network, you MUST set it to false + /// If forceZip64 is set true then the file header is allocated with zip64 extension so that it can be updated after the file data is written + /// if seekableOut is true in case the compressed or uncompressed size exceeds 32 bits. ~Compress(); @@ -78,10 +80,10 @@ public: /// leads to worse results. Extensions will be converted to lower case. /// /// The default extensions are: - /// - gif - /// - jpg - /// - jpeg - /// - png + /// - gif + /// - jpg + /// - jpeg + /// - png const std::set& getStoreExtensions() const; /// Returns the file extensions for which the CM_STORE compression method @@ -103,17 +105,19 @@ private: /// for directories. void addFileRaw(std::istream& in, const ZipLocalFileHeader& hdr, const Poco::Path& fileName); - /// Copies an already compressed ZipEntry from in + /// copys an already compressed ZipEntry from in private: - std::set _storeExtensions; - std::ostream& _out; - bool _seekableOut; - ZipArchive::FileHeaders _files; - ZipArchive::FileInfos _infos; - ZipArchive::DirectoryInfos _dirs; - Poco::UInt32 _offset; - std::string _comment; + std::set _storeExtensions; + std::ostream& _out; + bool _seekableOut; + bool _forceZip64; + ZipArchive::FileHeaders _files; + ZipArchive::FileInfos _infos; + ZipArchive::DirectoryInfos _dirs; + ZipArchive::DirectoryInfos64 _dirs64; + Poco::UInt64 _offset; + std::string _comment; friend class Keep; friend class Rename; @@ -123,6 +127,8 @@ private: // // inlines // + + inline void Compress::setZipComment(const std::string& comment) { _comment = comment; diff --git a/Zip/include/Poco/Zip/ZipArchive.h b/Zip/include/Poco/Zip/ZipArchive.h index 943485d9b..2631afa07 100644 --- a/Zip/include/Poco/Zip/ZipArchive.h +++ b/Zip/include/Poco/Zip/ZipArchive.h @@ -5,14 +5,14 @@ // // Library: Zip // Package: Zip -// Module: ZipArchive +// Module: ZipArchive // // Definition of the ZipArchive class. // // Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // and Contributors. // -// SPDX-License-Identifier: BSL-1.0 +// SPDX-License-Identifier: BSL-1.0 // @@ -24,6 +24,7 @@ #include "Poco/Zip/ZipLocalFileHeader.h" #include "Poco/Zip/ZipFileInfo.h" #include "Poco/Zip/ZipArchiveInfo.h" + #include #include @@ -43,6 +44,7 @@ public: typedef std::map FileHeaders; typedef std::map FileInfos; typedef std::map DirectoryInfos; + typedef std::map DirectoryInfos64; ZipArchive(std::istream& in); /// Creates the ZipArchive from a file. Note that the in stream will be in state failed after the constructor is finished @@ -68,15 +70,17 @@ public: private: void parse(std::istream& in, ParseCallback& pc); - ZipArchive(const FileHeaders& entries, const FileInfos& infos, const DirectoryInfos& dirs ); + ZipArchive(const FileHeaders& entries, const FileInfos& infos, const DirectoryInfos& dirs, const DirectoryInfos64& dirs64 ); private: - FileHeaders _entries; + FileHeaders _entries; /// Info generated by parsing the data block of the zip file - FileInfos _infos; + FileInfos _infos; /// Info generated by parsing the directory block of the zip file DirectoryInfos _disks; /// Stores directory info for all found disks + DirectoryInfos64 _disks64; + /// Stores directory info for all found disks friend class Compress; }; diff --git a/Zip/include/Poco/Zip/ZipArchiveInfo.h b/Zip/include/Poco/Zip/ZipArchiveInfo.h index 571c7a379..f2feba3e9 100644 --- a/Zip/include/Poco/Zip/ZipArchiveInfo.h +++ b/Zip/include/Poco/Zip/ZipArchiveInfo.h @@ -5,14 +5,14 @@ // // Library: Zip // Package: Zip -// Module: ZipArchiveInfo +// Module: ZipArchiveInfo // // Definition of the ZipArchiveInfo class. // // Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // and Contributors. // -// SPDX-License-Identifier: BSL-1.0 +// SPDX-License-Identifier: BSL-1.0 // @@ -70,16 +70,20 @@ public: /// Sets the optional Zip comment. void setNumberOfEntries(Poco::UInt16 val); - /// Returns the number of entries on this disk + /// Sets the number of entries on this disk void setTotalNumberOfEntries(Poco::UInt16 val); - /// Returns the total number of entries on all disks + /// Sets the total number of entries on all disks void setCentralDirectorySize(Poco::UInt32 val); - /// Returns the size of the central directory in bytes + /// Sets the size of the central directory in bytes - void setHeaderOffset(Poco::UInt32 val); + void setCentralDirectoryOffset(Poco::UInt32 val); + /// Sets the offset of the central directory from beginning of first disk + void setHeaderOffset(std::streamoff val); + /// Sets the offset of the header in relation to the begin of this disk + std::string createHeader() const; /// Creates a header @@ -109,12 +113,128 @@ private: FULLHEADER_SIZE = 22 }; - char _rawInfo[FULLHEADER_SIZE]; + char _rawInfo[FULLHEADER_SIZE]; std::streamoff _startPos; - std::string _comment; + std::string _comment; }; +class Zip_API ZipArchiveInfo64 + /// A ZipArchiveInfo64 stores central directory info +{ +public: + static const char HEADER[ZipCommon::HEADER_SIZE]; + static const char LOCATOR_HEADER[ZipCommon::HEADER_SIZE]; + + ZipArchiveInfo64(); + /// Default constructor, everything set to zero or empty + + ZipArchiveInfo64(std::istream& in, bool assumeHeaderRead); + /// Creates the ZipArchiveInfo64 by parsing the input stream. + /// If assumeHeaderRead is true we assume that the first 4 bytes were already read outside. + + ~ZipArchiveInfo64(); + /// Destroys the ZipArchiveInfo64. + + void getVersionMadeBy(int& major, int& minor); + /// The ZIP version used to create the file + + void getRequiredVersion(int& major, int& minor); + /// The minimum version required to extract the data + + Poco::UInt32 getDiskNumber() const; + /// Get the number of the disk where this header can be found + + Poco::UInt32 getFirstDiskForDirectoryHeader() const; + /// Returns the number of the disk that contains the start of the directory header + + Poco::UInt64 getNumberOfEntries() const; + /// Returns the number of entries on this disk + + Poco::UInt64 getTotalNumberOfEntries() const; + /// Returns the total number of entries on all disks + + Poco::UInt64 getCentralDirectorySize() const; + /// Returns the size of the central directory in bytes + + std::streamoff getCentralDirectoryOffset() const; + /// Returns the offset of the central directory from beginning of first disk + + std::streamoff getHeaderOffset() const; + /// Returns the offset of the header in relation to the begin of this disk + + void setNumberOfEntries(Poco::UInt64 val); + /// Sets the number of entries on this disk + + void setTotalNumberOfEntries(Poco::UInt64 val); + /// Sets the total number of entries on all disks + + void setCentralDirectorySize(Poco::UInt64 val); + /// Set the size of the central directory in bytes + + void setCentralDirectoryOffset(Poco::UInt64 val); + /// Returns the offset of the central directory from beginning of first disk + + void setHeaderOffset(std::streamoff val); + /// Sets the offset of the header in relation to the begin of this disk + + void setTotalNumberOfDisks(Poco::UInt32 val); + /// Sets the offset of the central directory from beginning of first disk + + std::string createHeader() const; + /// Creates a header + +private: + void parse(std::istream& inp, bool assumeHeaderRead); + void setRequiredVersion(int major, int minor); + +private: + enum + { + HEADER_POS = 0, + RECORDSIZE_POS = HEADER_POS + ZipCommon::HEADER_SIZE, + RECORDSIZE_SIZE = 8, + VERSIONMADEBY_POS = RECORDSIZE_POS + RECORDSIZE_SIZE, + VERSIONMADEBY_SIZE = 2, + VERSION_NEEDED_POS = VERSIONMADEBY_POS + VERSIONMADEBY_SIZE, + VERSION_NEEDED_SIZE = 2, + NUMBEROFTHISDISK_POS = VERSION_NEEDED_POS + VERSION_NEEDED_SIZE, + NUMBEROFTHISDISK_SIZE = 4, + NUMBEROFCENTRALDIRDISK_POS = NUMBEROFTHISDISK_POS + NUMBEROFTHISDISK_SIZE, + NUMBEROFCENTRALDIRDISK_SIZE = 4, + NUMENTRIESTHISDISK_POS = NUMBEROFCENTRALDIRDISK_POS + NUMBEROFCENTRALDIRDISK_SIZE, + NUMENTRIESTHISDISK_SIZE = 8, + TOTALNUMENTRIES_POS = NUMENTRIESTHISDISK_POS + NUMENTRIESTHISDISK_SIZE, + TOTALNUMENTRIES_SIZE = 8, + CENTRALDIRSIZE_POS = TOTALNUMENTRIES_POS + TOTALNUMENTRIES_SIZE, + CENTRALDIRSIZE_SIZE = 8, + CENTRALDIRSTARTOFFSET_POS = CENTRALDIRSIZE_POS + CENTRALDIRSIZE_SIZE, + CENTRALDIRSTARTOFFSET_SIZE = 8, + FULL_HEADER_SIZE = 56, + + LOCATOR_HEADER_POS = 0, + NUMBEROFENDOFCENTRALDIRDISK_POS = LOCATOR_HEADER_POS + ZipCommon::HEADER_SIZE, + NUMBEROFENDOFCENTRALDIRDISK_SIZE = 4, + ENDOFCENTRALDIROFFSET_POS = NUMBEROFENDOFCENTRALDIRDISK_POS + NUMBEROFENDOFCENTRALDIRDISK_SIZE, + ENDOFCENTRALDIROFFSET_SIZE = 8, + TOTALNUMBEROFENDDISKS_POS = ENDOFCENTRALDIROFFSET_POS + ENDOFCENTRALDIROFFSET_SIZE, + TOTALNUMBEROFENDDISKS_SIZE = 4, + + FULL_LOCATOR_SIZE = 20 + }; + + char _rawInfo[FULL_HEADER_SIZE]; + std::string _extraField; + char _locInfo[FULL_LOCATOR_SIZE]; + std::streamoff _startPos; +}; + + +// +// inlines +// + + inline Poco::UInt16 ZipArchiveInfo::getDiskNumber() const { return ZipUtil::get16BitValue(_rawInfo, NUMBEROFTHISDISK_POS); @@ -181,11 +301,105 @@ inline void ZipArchiveInfo::setCentralDirectorySize(Poco::UInt32 val) } -inline void ZipArchiveInfo::setHeaderOffset(Poco::UInt32 val) +inline void ZipArchiveInfo::setCentralDirectoryOffset(Poco::UInt32 val) { ZipUtil::set32BitValue(val, _rawInfo, CENTRALDIRSTARTOFFSET_POS); } +inline void ZipArchiveInfo::setHeaderOffset(std::streamoff val) +{ + _startPos = val; +} + + +inline Poco::UInt32 ZipArchiveInfo64::getDiskNumber() const +{ + return ZipUtil::get32BitValue(_rawInfo, NUMBEROFTHISDISK_POS); +} + + +inline Poco::UInt32 ZipArchiveInfo64::getFirstDiskForDirectoryHeader() const +{ + return ZipUtil::get32BitValue(_rawInfo, NUMBEROFCENTRALDIRDISK_POS); +} + + +inline Poco::UInt64 ZipArchiveInfo64::getNumberOfEntries() const +{ + return ZipUtil::get64BitValue(_rawInfo, NUMENTRIESTHISDISK_POS); +} + + +inline Poco::UInt64 ZipArchiveInfo64::getTotalNumberOfEntries() const +{ + return ZipUtil::get64BitValue(_rawInfo, TOTALNUMENTRIES_POS); +} + + +inline Poco::UInt64 ZipArchiveInfo64::getCentralDirectorySize() const +{ + return ZipUtil::get64BitValue(_rawInfo, CENTRALDIRSIZE_POS); +} + + +inline std::streamoff ZipArchiveInfo64::getCentralDirectoryOffset() const +{ + return _startPos; +} + + +inline std::streamoff ZipArchiveInfo64::getHeaderOffset() const +{ + return _startPos; +} + + +inline void ZipArchiveInfo64::setRequiredVersion(int major, int minor) +{ + poco_assert (minor < 10); + poco_assert (major < 24); + Poco::UInt8 val = static_cast(major)*10+static_cast(minor); + _rawInfo[VERSIONMADEBY_POS] = static_cast(val); + _rawInfo[VERSION_NEEDED_POS] = static_cast(val); +} + + +inline void ZipArchiveInfo64::setNumberOfEntries(Poco::UInt64 val) +{ + ZipUtil::set64BitValue(val, _rawInfo, NUMENTRIESTHISDISK_POS); +} + + +inline void ZipArchiveInfo64::setTotalNumberOfEntries(Poco::UInt64 val) +{ + ZipUtil::set64BitValue(val, _rawInfo, TOTALNUMENTRIES_POS); +} + + +inline void ZipArchiveInfo64::setCentralDirectorySize(Poco::UInt64 val) +{ + ZipUtil::set64BitValue(val, _rawInfo, CENTRALDIRSIZE_POS); +} + + +inline void ZipArchiveInfo64::setCentralDirectoryOffset(Poco::UInt64 val) +{ + ZipUtil::set64BitValue(val, _rawInfo, CENTRALDIRSTARTOFFSET_POS); +} + + +inline void ZipArchiveInfo64::setHeaderOffset(std::streamoff val) +{ + _startPos = val; + ZipUtil::set64BitValue(val, _locInfo, ENDOFCENTRALDIROFFSET_POS); +} + + +inline void ZipArchiveInfo64::setTotalNumberOfDisks(Poco::UInt32 val) +{ + ZipUtil::set32BitValue(val, _locInfo, TOTALNUMBEROFENDDISKS_POS); +} + } } // namespace Poco::Zip diff --git a/Zip/include/Poco/Zip/ZipCommon.h b/Zip/include/Poco/Zip/ZipCommon.h index aa4e687db..aacc0da74 100644 --- a/Zip/include/Poco/Zip/ZipCommon.h +++ b/Zip/include/Poco/Zip/ZipCommon.h @@ -5,14 +5,14 @@ // // Library: Zip // Package: Zip -// Module: ZipCommon +// Module: ZipCommon // // Definition of the ZipCommon class. // // Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // and Contributors. // -// SPDX-License-Identifier: BSL-1.0 +// SPDX-License-Identifier: BSL-1.0 // @@ -33,9 +33,13 @@ class Zip_API ZipCommon public: enum { - HEADER_SIZE = 4 + HEADER_SIZE = 4, }; + static const Poco::UInt16 ZIP64_EXTRA_ID = 0x1; // Extra data id tag for Zip64 data (in extension for ZipLocalFileHeader and ZipFileInfo) + static const Poco::UInt16 ZIP64_MAGIC_SHORT = 0xFFFF; + static const Poco::UInt32 ZIP64_MAGIC = 0xFFFFFFFF; + enum CompressionMethod { CM_STORE = 0, @@ -55,15 +59,15 @@ public: enum CompressionLevel { - CL_NORMAL = 0, - CL_MAXIMUM = 1, - CL_FAST = 2, + CL_NORMAL = 0, + CL_MAXIMUM = 1, + CL_FAST = 2, CL_SUPERFAST = 3 }; enum HostSystem { - HS_FAT = 0, // + PKZIPW 2.50 VFAT, NTFS + HS_FAT = 0, // + PKZIPW 2.50 VFAT, NTFS HS_AMIGA = 1, HS_VMS = 2, HS_UNIX = 3, diff --git a/Zip/include/Poco/Zip/ZipDataInfo.h b/Zip/include/Poco/Zip/ZipDataInfo.h index bf4be2327..c2bc01808 100644 --- a/Zip/include/Poco/Zip/ZipDataInfo.h +++ b/Zip/include/Poco/Zip/ZipDataInfo.h @@ -5,14 +5,14 @@ // // Library: Zip // Package: Zip -// Module: ZipDataInfo +// Module: ZipDataInfo // // Definition of the ZipDataInfo class. // // Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // and Contributors. // -// SPDX-License-Identifier: BSL-1.0 +// SPDX-License-Identifier: BSL-1.0 // @@ -80,6 +80,62 @@ private: }; +class Zip_API ZipDataInfo64 + /// A ZipDataInfo64 stores a Zip data descriptor for a Zip64 file +{ +public: + static const char HEADER[ZipCommon::HEADER_SIZE]; + + ZipDataInfo64(); + /// Creates a header with all fields (except the header field) set to 0 + + ZipDataInfo64(std::istream& in, bool assumeHeaderRead); + /// Creates the ZipDataInfo64. + + ~ZipDataInfo64(); + /// Destroys the ZipDataInfo64. + + bool isValid() const; + + Poco::UInt32 getCRC32() const; + + void setCRC32(Poco::UInt32 crc); + + Poco::UInt64 getCompressedSize() const; + + void setCompressedSize(Poco::UInt64 size); + + Poco::UInt64 getUncompressedSize() const; + + void setUncompressedSize(Poco::UInt64 size); + + static Poco::UInt32 getFullHeaderSize(); + + const char* getRawHeader() const; + +private: + enum + { + HEADER_POS = 0, + CRC32_POS = HEADER_POS + ZipCommon::HEADER_SIZE, + CRC32_SIZE = 4, + COMPRESSED_POS = CRC32_POS + CRC32_SIZE, + COMPRESSED_SIZE = 8, + UNCOMPRESSED_POS = COMPRESSED_POS + COMPRESSED_SIZE, + UNCOMPRESSED_SIZE = 8, + FULLHEADER_SIZE = UNCOMPRESSED_POS + UNCOMPRESSED_SIZE + }; + + char _rawInfo[FULLHEADER_SIZE]; + bool _valid; +}; + + +// +// inlines +// + + inline const char* ZipDataInfo::getRawHeader() const { return _rawInfo; @@ -134,6 +190,60 @@ inline Poco::UInt32 ZipDataInfo::getFullHeaderSize() } +inline const char* ZipDataInfo64::getRawHeader() const +{ + return _rawInfo; +} + + +inline bool ZipDataInfo64::isValid() const +{ + return _valid; +} + + +inline Poco::UInt32 ZipDataInfo64::getCRC32() const +{ + return ZipUtil::get32BitValue(_rawInfo, CRC32_POS); +} + + +inline void ZipDataInfo64::setCRC32(Poco::UInt32 crc) +{ + return ZipUtil::set32BitValue(crc, _rawInfo, CRC32_POS); +} + + +inline Poco::UInt64 ZipDataInfo64::getCompressedSize() const +{ + return ZipUtil::get64BitValue(_rawInfo, COMPRESSED_POS); +} + + +inline void ZipDataInfo64::setCompressedSize(Poco::UInt64 size) +{ + return ZipUtil::set64BitValue(size, _rawInfo, COMPRESSED_POS); +} + + +inline Poco::UInt64 ZipDataInfo64::getUncompressedSize() const +{ + return ZipUtil::get64BitValue(_rawInfo, UNCOMPRESSED_POS); +} + + +inline void ZipDataInfo64::setUncompressedSize(Poco::UInt64 size) +{ + return ZipUtil::set64BitValue(size, _rawInfo, UNCOMPRESSED_POS); +} + + +inline Poco::UInt32 ZipDataInfo64::getFullHeaderSize() +{ + return FULLHEADER_SIZE; +} + + } } // namespace Poco::Zip diff --git a/Zip/include/Poco/Zip/ZipFileInfo.h b/Zip/include/Poco/Zip/ZipFileInfo.h index 5e6ad343e..0598950a8 100644 --- a/Zip/include/Poco/Zip/ZipFileInfo.h +++ b/Zip/include/Poco/Zip/ZipFileInfo.h @@ -5,14 +5,14 @@ // // Library: Zip // Package: Zip -// Module: ZipFileInfo +// Module: ZipFileInfo // // Definition of the ZipFileInfo class. // // Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // and Contributors. // -// SPDX-License-Identifier: BSL-1.0 +// SPDX-License-Identifier: BSL-1.0 // @@ -48,9 +48,6 @@ public: ~ZipFileInfo(); /// Destroys the ZipFileInfo. - Poco::UInt32 getRelativeOffsetOfLocalHeader() const; - /// Where on the disk starts the localheader. Combined with the disk number gives the exact location of the header - ZipCommon::CompressionMethod getCompressionMethod() const; bool isEncrypted() const; @@ -62,9 +59,12 @@ public: Poco::UInt32 getHeaderSize() const; /// Returns the total size of the header including filename + other additional fields - Poco::UInt32 getCompressedSize() const; + Poco::UInt64 getCompressedSize() const; - Poco::UInt32 getUncompressedSize() const; + Poco::UInt64 getUncompressedSize() const; + + Poco::UInt64 getOffset() const; + /// Where on the disk starts the localheader. Combined with the disk number gives the exact location of the header const std::string& getFileName() const; @@ -94,14 +94,19 @@ public: std::string createHeader() const; - void setOffset(Poco::UInt32 val); + void setOffset(Poco::UInt64 val); + + bool needsZip64() const; + + void setZip64Data(); private: + void setCRC(Poco::UInt32 val); - void setCompressedSize(Poco::UInt32 val); + void setCompressedSize(Poco::UInt64 val); - void setUncompressedSize(Poco::UInt32 val); + void setUncompressedSize(Poco::UInt64 val); void setCompressionMethod(ZipCommon::CompressionMethod cm); @@ -131,6 +136,8 @@ private: Poco::UInt32 getUncompressedSizeFromHeader() const; + Poco::UInt32 getOffsetFromHeader() const; + Poco::UInt16 getFileNameLength() const; Poco::UInt16 getExtraFieldLength() const; @@ -177,7 +184,17 @@ private: EXTERNALFILE_ATTR_SIZE = 4, RELATIVEOFFSETLOCALHEADER_POS = EXTERNALFILE_ATTR_POS + EXTERNALFILE_ATTR_SIZE, RELATIVEOFFSETLOCALHEADER_SIZE = 4, - FULLHEADER_SIZE = 46 + FULLHEADER_SIZE = 46, + + EXTRA_DATA_TAG_SIZE = 2, + EXTRA_DATA_TAG_POS = 0, + EXTRA_DATA_SIZE_SIZE = 2, + EXTRA_DATA_SIZE_POS = EXTRA_DATA_TAG_POS + EXTRA_DATA_TAG_SIZE, + EXTRA_DATA_POS = EXTRA_DATA_SIZE_POS + EXTRA_DATA_SIZE_SIZE, + EXTRA_DATA_UNCOMPRESSED_SIZE_SIZE = 8, + EXTRA_DATA_COMPRESSED_SIZE_SIZE = 8, + EXTRA_DATA_OFFSET_SIZE = 8, + FULLEXTRA_DATA_SIZE = 28 }; enum @@ -186,22 +203,18 @@ private: DEFAULT_UNIX_DIR_MODE = 0755 }; - char _rawInfo[FULLHEADER_SIZE]; + char _rawInfo[FULLHEADER_SIZE]; Poco::UInt32 _crc32; - Poco::UInt32 _compressedSize; - Poco::UInt32 _uncompressedSize; - std::string _fileName; + Poco::UInt64 _compressedSize; + Poco::UInt64 _uncompressedSize; + Poco::UInt64 _localHeaderOffset; + std::string _fileName; Poco::DateTime _lastModifiedAt; - std::string _extraField; - std::string _fileComment; + std::string _extraField; + std::string _fileComment; }; -inline Poco::UInt32 ZipFileInfo::getRelativeOffsetOfLocalHeader() const -{ - return ZipUtil::get32BitValue(_rawInfo, RELATIVEOFFSETLOCALHEADER_POS); -} - inline Poco::UInt32 ZipFileInfo::getCRCFromHeader() const { @@ -220,6 +233,11 @@ inline Poco::UInt32 ZipFileInfo::getUncompressedSizeFromHeader() const return ZipUtil::get32BitValue(_rawInfo, UNCOMPRESSED_SIZE_POS); } +inline Poco::UInt32 ZipFileInfo::getOffsetFromHeader() const +{ + return ZipUtil::get32BitValue(_rawInfo, RELATIVEOFFSETLOCALHEADER_POS); +} + inline void ZipFileInfo::parseDateTime() { @@ -246,19 +264,25 @@ inline const Poco::DateTime& ZipFileInfo::lastModifiedAt() const } +inline Poco::UInt64 ZipFileInfo::getOffset() const +{ + return _localHeaderOffset; +} + + inline Poco::UInt32 ZipFileInfo::getCRC() const { return _crc32; } -inline Poco::UInt32 ZipFileInfo::getCompressedSize() const +inline Poco::UInt64 ZipFileInfo::getCompressedSize() const { return _compressedSize; } -inline Poco::UInt32 ZipFileInfo::getUncompressedSize() const +inline Poco::UInt64 ZipFileInfo::getUncompressedSize() const { return _uncompressedSize; } @@ -363,6 +387,39 @@ inline Poco::UInt32 ZipFileInfo::getHeaderSize() const } +inline bool ZipFileInfo::needsZip64() const +{ + return _localHeaderOffset >= ZipCommon::ZIP64_MAGIC || _compressedSize >= ZipCommon::ZIP64_MAGIC || _uncompressedSize >= ZipCommon::ZIP64_MAGIC; +} + + +inline void ZipFileInfo::setZip64Data() +{ + if (needsZip64()) + { + setRequiredVersion(4, 5); + char data[FULLEXTRA_DATA_SIZE]; + ZipUtil::set16BitValue(ZipCommon::ZIP64_EXTRA_ID, data, EXTRA_DATA_TAG_POS); + Poco::UInt16 pos = EXTRA_DATA_POS; + if (_uncompressedSize >= ZipCommon::ZIP64_MAGIC) + { + ZipUtil::set64BitValue(_uncompressedSize, data, pos); pos += 8; + } + if (_compressedSize >= ZipCommon::ZIP64_MAGIC) + { + ZipUtil::set64BitValue(_compressedSize, data, pos); pos += 8; + } + if (_localHeaderOffset >= ZipCommon::ZIP64_MAGIC) + { + ZipUtil::set64BitValue(_localHeaderOffset, data, pos); pos += 8; + } + ZipUtil::set16BitValue(pos - EXTRA_DATA_POS, data, EXTRA_DATA_SIZE_POS); + _extraField = std::string(data, pos); + ZipUtil::set16BitValue(pos, _rawInfo, EXTRAFIELD_LENGTH_POS); + } +} + + inline void ZipFileInfo::setCRC(Poco::UInt32 val) { _crc32 = val; @@ -370,23 +427,24 @@ inline void ZipFileInfo::setCRC(Poco::UInt32 val) } -inline void ZipFileInfo::setOffset(Poco::UInt32 val) +inline void ZipFileInfo::setOffset(Poco::UInt64 val) { - ZipUtil::set32BitValue(val, _rawInfo, RELATIVEOFFSETLOCALHEADER_POS); + _localHeaderOffset = val; + ZipUtil::set32BitValue(val >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast(val), _rawInfo, RELATIVEOFFSETLOCALHEADER_POS); } -inline void ZipFileInfo::setCompressedSize(Poco::UInt32 val) +inline void ZipFileInfo::setCompressedSize(Poco::UInt64 val) { _compressedSize = val; - ZipUtil::set32BitValue(val, _rawInfo, COMPRESSED_SIZE_POS); + ZipUtil::set32BitValue(val >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast(val), _rawInfo, COMPRESSED_SIZE_POS); } -inline void ZipFileInfo::setUncompressedSize(Poco::UInt32 val) +inline void ZipFileInfo::setUncompressedSize(Poco::UInt64 val) { _uncompressedSize = val; - ZipUtil::set32BitValue(val, _rawInfo, UNCOMPRESSED_SIZE_POS); + ZipUtil::set32BitValue(val >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast(val), _rawInfo, UNCOMPRESSED_SIZE_POS); } diff --git a/Zip/include/Poco/Zip/ZipLocalFileHeader.h b/Zip/include/Poco/Zip/ZipLocalFileHeader.h index 67645a2c6..05bf00b77 100644 --- a/Zip/include/Poco/Zip/ZipLocalFileHeader.h +++ b/Zip/include/Poco/Zip/ZipLocalFileHeader.h @@ -5,14 +5,14 @@ // // Library: Zip // Package: Zip -// Module: ZipLocalFileHeader +// Module: ZipLocalFileHeader // // Definition of the ZipLocalFileHeader class. // // Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // and Contributors. // -// SPDX-License-Identifier: BSL-1.0 +// SPDX-License-Identifier: BSL-1.0 // @@ -41,9 +41,10 @@ class Zip_API ZipLocalFileHeader public: static const char HEADER[ZipCommon::HEADER_SIZE]; - ZipLocalFileHeader(const Poco::Path& fileName, const Poco::DateTime& lastModifiedAt, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl); + ZipLocalFileHeader(const Poco::Path& fileName, const Poco::DateTime& lastModifiedAt, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl, bool forceZip64 = false); /// Creates a zip file header from an absoluteFile. fileName is the name of the file in the zip, outputIsSeekable determines if we write /// CRC and file sizes to the LocalFileHeader or after data compression into a ZipDataInfo + /// If forceZip64 is set true then the file header is allocated with zip64 extension. ZipLocalFileHeader(std::istream& inp, bool assumeHeaderRead, ParseCallback& callback); /// Creates the ZipLocalFileHeader by parsing the input stream. @@ -82,7 +83,7 @@ public: ZipCommon::CompressionMethod getCompressionMethod() const; ZipCommon::CompressionLevel getCompressionLevel() const; - /// Returns the compression level used. Only valid when the compression method is CM_DEFLATE + /// Returns the compression level used. Only valid when the compression method is CM_DEFLATE bool isEncrypted() const; @@ -90,15 +91,15 @@ public: Poco::UInt32 getCRC() const; - Poco::UInt32 getCompressedSize() const; + Poco::UInt64 getCompressedSize() const; - Poco::UInt32 getUncompressedSize() const; + Poco::UInt64 getUncompressedSize() const; void setCRC(Poco::UInt32 val); - void setCompressedSize(Poco::UInt32 val); + void setCompressedSize(Poco::UInt64 val); - void setUncompressedSize(Poco::UInt32 val); + void setUncompressedSize(Poco::UInt64 val); const std::string& getFileName() const; @@ -118,6 +119,10 @@ public: void setFileName(const std::string& fileName, bool isDirectory); + bool needsZip64() const; + + void setZip64Data(); + std::string createHeader() const; /// Creates a header @@ -170,38 +175,48 @@ private: LASTMODEFILEDATE_POS = LASTMODEFILETIME_POS + LASTMODEFILETIME_SIZE, CRC32_SIZE = 4, CRC32_POS = LASTMODEFILEDATE_POS + LASTMODEFILEDATE_SIZE, - COMPRESSEDSIZE_SIZE = 4, - COMPRESSEDSIZE_POS = CRC32_POS + CRC32_SIZE, - UNCOMPRESSEDSIZE_SIZE = 4, - UNCOMPRESSEDSIZE_POS = COMPRESSEDSIZE_POS + COMPRESSEDSIZE_SIZE, - FILELENGTH_SIZE = 2, - FILELENGTH_POS = UNCOMPRESSEDSIZE_POS + UNCOMPRESSEDSIZE_SIZE, - EXTRAFIELD_LENGTH = 2, - EXTRAFIELD_POS = FILELENGTH_POS + FILELENGTH_SIZE, - FULLHEADER_SIZE = 30 + COMPRESSED_SIZE_SIZE = 4, + COMPRESSED_SIZE_POS = CRC32_POS + CRC32_SIZE, + UNCOMPRESSED_SIZE_SIZE = 4, + UNCOMPRESSED_SIZE_POS = COMPRESSED_SIZE_POS + COMPRESSED_SIZE_SIZE, + FILE_LENGTH_SIZE = 2, + FILE_LENGTH_POS = UNCOMPRESSED_SIZE_POS + UNCOMPRESSED_SIZE_SIZE, + EXTRA_FIELD_LENGTH = 2, + EXTRA_FIELD_POS = FILE_LENGTH_POS + FILE_LENGTH_SIZE, + FULLHEADER_SIZE = 30, + + EXTRA_DATA_TAG_SIZE = 2, + EXTRA_DATA_TAG_POS = 0, + EXTRA_DATA_SIZE_SIZE = 2, + EXTRA_DATA_SIZE_POS = EXTRA_DATA_TAG_POS + EXTRA_DATA_TAG_SIZE, + EXTRA_DATA_POS = EXTRA_DATA_SIZE_POS + EXTRA_DATA_SIZE_SIZE, + EXTRA_DATA_UNCOMPRESSED_SIZE_SIZE = 8, + EXTRA_DATA_COMPRESSED_SIZE_SIZE = 8, + FULLEXTRA_DATA_SIZE = 20 }; - char _rawHeader[FULLHEADER_SIZE]; + bool _forceZip64; + char _rawHeader[FULLHEADER_SIZE]; std::streamoff _startPos; std::streamoff _endPos; - std::string _fileName; + std::string _fileName; Poco::DateTime _lastModifiedAt; - std::string _extraField; + std::string _extraField; Poco::UInt32 _crc32; - Poco::UInt32 _compressedSize; - Poco::UInt32 _uncompressedSize; + Poco::UInt64 _compressedSize; + Poco::UInt64 _uncompressedSize; }; inline void ZipLocalFileHeader::setFileNameLength(Poco::UInt16 size) { - ZipUtil::set16BitValue(size, _rawHeader, FILELENGTH_POS); + ZipUtil::set16BitValue(size, _rawHeader, FILE_LENGTH_POS); } inline void ZipLocalFileHeader::setExtraFieldSize(Poco::UInt16 size) { - ZipUtil::set16BitValue(size, _rawHeader, EXTRAFIELD_POS); + ZipUtil::set16BitValue(size, _rawHeader, EXTRA_FIELD_POS); } @@ -236,6 +251,28 @@ inline void ZipLocalFileHeader::getRequiredVersion(int& major, int& minor) } +inline bool ZipLocalFileHeader::needsZip64() const +{ + return _forceZip64 || _startPos >= ZipCommon::ZIP64_MAGIC || _compressedSize >= ZipCommon::ZIP64_MAGIC || _uncompressedSize >= ZipCommon::ZIP64_MAGIC; +} + + +inline void ZipLocalFileHeader::setZip64Data() +{ + setRequiredVersion(4, 5); + char data[FULLEXTRA_DATA_SIZE]; + ZipUtil::set16BitValue(ZipCommon::ZIP64_EXTRA_ID, data, EXTRA_DATA_TAG_POS); + Poco::UInt16 pos = EXTRA_DATA_POS; + ZipUtil::set64BitValue(_uncompressedSize, data, pos); pos += 8; + ZipUtil::set32BitValue(ZipCommon::ZIP64_MAGIC, _rawHeader, UNCOMPRESSED_SIZE_POS); + ZipUtil::set64BitValue(_compressedSize, data, pos); pos += 8; + ZipUtil::set32BitValue(ZipCommon::ZIP64_MAGIC, _rawHeader, COMPRESSED_SIZE_POS); + ZipUtil::set16BitValue(pos - EXTRA_DATA_POS, data, EXTRA_DATA_SIZE_POS); + _extraField = std::string(data, pos); + ZipUtil::set16BitValue(pos, _rawHeader, EXTRA_FIELD_POS); +} + + inline void ZipLocalFileHeader::setRequiredVersion(int major, int minor) { poco_assert (minor < 10); @@ -245,13 +282,13 @@ inline void ZipLocalFileHeader::setRequiredVersion(int major, int minor) inline Poco::UInt16 ZipLocalFileHeader::getFileNameLength() const { - return ZipUtil::get16BitValue(_rawHeader, FILELENGTH_POS); + return ZipUtil::get16BitValue(_rawHeader, FILE_LENGTH_POS); } inline Poco::UInt16 ZipLocalFileHeader::getExtraFieldLength() const { - return ZipUtil::get16BitValue(_rawHeader, EXTRAFIELD_POS); + return ZipUtil::get16BitValue(_rawHeader, EXTRA_FIELD_POS); } @@ -360,13 +397,13 @@ inline Poco::UInt32 ZipLocalFileHeader::getCRC() const } -inline Poco::UInt32 ZipLocalFileHeader::getCompressedSize() const +inline Poco::UInt64 ZipLocalFileHeader::getCompressedSize() const { return _compressedSize; } -inline Poco::UInt32 ZipLocalFileHeader::getUncompressedSize() const +inline Poco::UInt64 ZipLocalFileHeader::getUncompressedSize() const { return _uncompressedSize; } @@ -379,17 +416,17 @@ inline void ZipLocalFileHeader::setCRC(Poco::UInt32 val) } -inline void ZipLocalFileHeader::setCompressedSize(Poco::UInt32 val) +inline void ZipLocalFileHeader::setCompressedSize(Poco::UInt64 val) { _compressedSize = val; - ZipUtil::set32BitValue(val, _rawHeader, COMPRESSEDSIZE_POS); + ZipUtil::set32BitValue(val >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast(val), _rawHeader, COMPRESSED_SIZE_POS); } -inline void ZipLocalFileHeader::setUncompressedSize(Poco::UInt32 val) +inline void ZipLocalFileHeader::setUncompressedSize(Poco::UInt64 val) { _uncompressedSize = val; - ZipUtil::set32BitValue(val, _rawHeader, UNCOMPRESSEDSIZE_POS); + ZipUtil::set32BitValue(val >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast(val), _rawHeader, UNCOMPRESSED_SIZE_POS); } @@ -401,13 +438,13 @@ inline Poco::UInt32 ZipLocalFileHeader::getCRCFromHeader() const inline Poco::UInt32 ZipLocalFileHeader::getCompressedSizeFromHeader() const { - return ZipUtil::get32BitValue(_rawHeader, COMPRESSEDSIZE_POS); + return ZipUtil::get32BitValue(_rawHeader, COMPRESSED_SIZE_POS); } inline Poco::UInt32 ZipLocalFileHeader::getUncompressedSizeFromHeader() const { - return ZipUtil::get32BitValue(_rawHeader, UNCOMPRESSEDSIZE_POS); + return ZipUtil::get32BitValue(_rawHeader, UNCOMPRESSED_SIZE_POS); } diff --git a/Zip/include/Poco/Zip/ZipStream.h b/Zip/include/Poco/Zip/ZipStream.h index 052d5bf0b..c9005c9cf 100644 --- a/Zip/include/Poco/Zip/ZipStream.h +++ b/Zip/include/Poco/Zip/ZipStream.h @@ -5,14 +5,14 @@ // // Library: Zip // Package: Zip -// Module: ZipStream +// Module: ZipStream // // Definition of the ZipStream class. // // Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // and Contributors. // -// SPDX-License-Identifier: BSL-1.0 +// SPDX-License-Identifier: BSL-1.0 // @@ -50,7 +50,7 @@ public: virtual ~ZipStreamBuf(); /// Destroys the ZipStreamBuf. - void close(); + void close(Poco::UInt64& extraDataSize); /// Informs a writing outputstream that writing is done for this stream bool crcValid() const; @@ -71,15 +71,15 @@ private: typedef Poco::SharedPtr PtrOStream; std::istream* _pIstr; std::ostream* _pOstr; - PtrIStream _ptrBuf; - PtrOStream _ptrOBuf; - PtrIStream _ptrHelper; + PtrIStream _ptrBuf; + PtrOStream _ptrOBuf; + PtrIStream _ptrHelper; Poco::SharedPtr _ptrOHelper; Poco::Checksum _crc32; Poco::UInt32 _expectedCrc32; - bool _checkCRC; + bool _checkCRC; /// Note: we do not check crc if we decompress a streaming zip file and the crc is stored in the directory header - Poco::UInt32 _bytesWritten; + Poco::UInt64 _bytesWritten; ZipLocalFileHeader* _pHeader; }; @@ -140,7 +140,7 @@ public: ~ZipOutputStream(); /// Destroys the ZipOutputStream. - void close(); + void close(Poco::UInt64& extraDataSize); /// Must be called for ZipOutputStreams! }; diff --git a/Zip/include/Poco/Zip/ZipUtil.h b/Zip/include/Poco/Zip/ZipUtil.h index 0e89b4878..e3278d630 100644 --- a/Zip/include/Poco/Zip/ZipUtil.h +++ b/Zip/include/Poco/Zip/ZipUtil.h @@ -5,14 +5,14 @@ // // Library: Zip // Package: Zip -// Module: ZipUtil +// Module: ZipUtil // // Definition of the ZipUtil class. // // Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // and Contributors. // -// SPDX-License-Identifier: BSL-1.0 +// SPDX-License-Identifier: BSL-1.0 // @@ -39,10 +39,14 @@ public: static Poco::UInt32 get32BitValue(const char* pVal, const Poco::UInt32 pos); + static Poco::UInt64 get64BitValue(const char* pVal, const Poco::UInt32 pos); + static void set16BitValue(const Poco::UInt16 val, char* pVal, const Poco::UInt32 pos); static void set32BitValue(const Poco::UInt32 val, char* pVal, const Poco::UInt32 pos); + static void set64BitValue(const Poco::UInt64 val, char* pVal, const Poco::UInt32 pos); + static Poco::DateTime parseDateTime(const char* pVal, const Poco::UInt32 timePos, const Poco::UInt32 datePos); static void setDateTime(const Poco::DateTime& dt, char* pVal, const Poco::UInt32 timePos, const Poco::UInt32 datePos); @@ -78,6 +82,14 @@ inline Poco::UInt32 ZipUtil::get32BitValue(const char* pVal, const Poco::UInt32 } +inline Poco::UInt64 ZipUtil::get64BitValue(const char* pVal, const Poco::UInt32 pos) +{ + Poco::UInt64 val = ZipUtil::get32BitValue(pVal, pos+4); + val = (val << 32) | ZipUtil::get32BitValue(pVal, pos); + return val; +} + + inline void ZipUtil::set16BitValue(const Poco::UInt16 val, char* pVal, const Poco::UInt32 pos) { pVal[pos] = static_cast(val); @@ -94,6 +106,19 @@ inline void ZipUtil::set32BitValue(const Poco::UInt32 val, char* pVal, const Poc } +inline void ZipUtil::set64BitValue(const Poco::UInt64 val, char* pVal, const Poco::UInt32 pos) +{ + pVal[pos] = static_cast(val); + pVal[pos+1] = static_cast(val>>8); + pVal[pos+2] = static_cast(val>>16); + pVal[pos+3] = static_cast(val>>24); + pVal[pos+4] = static_cast(val>>32); + pVal[pos+5] = static_cast(val>>40); + pVal[pos+6] = static_cast(val>>48); + pVal[pos+7] = static_cast(val>>56); +} + + } } // namespace Poco::Zip diff --git a/Zip/src/Compress.cpp b/Zip/src/Compress.cpp index fe9a3f365..b335a3074 100644 --- a/Zip/src/Compress.cpp +++ b/Zip/src/Compress.cpp @@ -5,12 +5,12 @@ // // Library: Zip // Package: Zip -// Module: Compress +// Module: Compress // // Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // and Contributors. // -// SPDX-License-Identifier: BSL-1.0 +// SPDX-License-Identifier: BSL-1.0 // @@ -30,9 +30,10 @@ namespace Poco { namespace Zip { -Compress::Compress(std::ostream& out, bool seekableOut): +Compress::Compress(std::ostream& out, bool seekableOut, bool forceZip64): _out(out), _seekableOut(seekableOut), + _forceZip64(forceZip64), _files(), _infos(), _dirs(), @@ -63,26 +64,24 @@ void Compress::addEntry(std::istream& in, const Poco::DateTime& lastModifiedAt, std::string fn = ZipUtil::validZipEntryFileName(fileName); - if (_files.size() >= 65535) - throw ZipException("Maximum number of entries for a ZIP file reached: 65535"); if (!in.good()) throw ZipException("Invalid input stream"); std::streamoff localHeaderOffset = _offset; - ZipLocalFileHeader hdr(fileName, lastModifiedAt, cm, cl); + ZipLocalFileHeader hdr(fileName, lastModifiedAt, cm, cl, _forceZip64); hdr.setStartPos(localHeaderOffset); ZipOutputStream zipOut(_out, hdr, _seekableOut); Poco::StreamCopier::copyStream(in, zipOut); - zipOut.close(); - hdr.setStartPos(localHeaderOffset); // reset again now that compressed Size is known + Poco::UInt64 extraDataSize; + zipOut.close(extraDataSize); _offset = hdr.getEndPos(); - if (hdr.searchCRCAndSizesAfterData()) - _offset += ZipDataInfo::getFullHeaderSize(); + _offset += extraDataSize; _files.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), hdr)); poco_assert (_out); ZipFileInfo nfo(hdr); nfo.setOffset(localHeaderOffset); + nfo.setZip64Data(); _infos.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), nfo)); EDone.notify(this, hdr); } @@ -94,8 +93,6 @@ void Compress::addFileRaw(std::istream& in, const ZipLocalFileHeader& h, const P //bypass the header of the input stream and point to the first byte of the data payload in.seekg(h.getDataStartPos(), std::ios_base::beg); - if (_files.size() >= 65535) - throw ZipException("Maximum number of entries for a ZIP file reached: 65535"); if (!in.good()) throw ZipException("Invalid input stream"); @@ -103,16 +100,18 @@ void Compress::addFileRaw(std::istream& in, const ZipLocalFileHeader& h, const P ZipLocalFileHeader hdr(h); hdr.setFileName(fn, h.isDirectory()); hdr.setStartPos(localHeaderOffset); + if(hdr.needsZip64()) + hdr.setZip64Data(); //bypass zipoutputstream //write the header directly std::string header = hdr.createHeader(); _out.write(header.c_str(), static_cast(header.size())); // now fwd the payload to _out in chunks of size CHUNKSIZE - Poco::UInt32 totalSize = hdr.getCompressedSize(); + Poco::UInt64 totalSize = hdr.getCompressedSize(); if (totalSize > 0) { Poco::Buffer buffer(COMPRESS_CHUNK_SIZE); - Poco::UInt32 remaining = totalSize; + Poco::UInt64 remaining = totalSize; while(remaining > 0) { if (remaining > COMPRESS_CHUNK_SIZE) @@ -133,20 +132,39 @@ void Compress::addFileRaw(std::istream& in, const ZipLocalFileHeader& h, const P } } } - //write optional block afterwards - if (hdr.searchCRCAndSizesAfterData()) - { - ZipDataInfo info(in, false); - _out.write(info.getRawHeader(), static_cast(info.getFullHeaderSize())); - } - hdr.setStartPos(localHeaderOffset); // reset again now that compressed Size is known + hdr.setStartPos(localHeaderOffset); // This resets EndPos now that compressed Size is known _offset = hdr.getEndPos(); - if (hdr.searchCRCAndSizesAfterData()) - _offset += ZipDataInfo::getFullHeaderSize(); + //write optional block afterwards + if (hdr.searchCRCAndSizesAfterData()) + { + if (hdr.needsZip64()) + { + ZipDataInfo64 info(in, false); + _out.write(info.getRawHeader(), static_cast(info.getFullHeaderSize())); + _offset += ZipDataInfo::getFullHeaderSize(); + } + else + { + ZipDataInfo info(in, false); + _out.write(info.getRawHeader(), static_cast(info.getFullHeaderSize())); + _offset += ZipDataInfo::getFullHeaderSize(); + } + } + else + { + if(hdr.hasExtraField()) // Update sizes in header extension. + hdr.setZip64Data(); + _out.seekp(hdr.getStartPos(), std::ios_base::beg); + std::string header = hdr.createHeader(); + _out.write(header.c_str(), static_cast(header.size())); + _out.seekp(0, std::ios_base::end); + } + _files.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), hdr)); poco_assert (_out); ZipFileInfo nfo(hdr); nfo.setOffset(localHeaderOffset); + nfo.setZip64Data(); _infos.insert(std::make_pair(fileName.toString(Poco::Path::PATH_UNIX), nfo)); EDone.notify(this, hdr); } @@ -186,8 +204,6 @@ void Compress::addDirectory(const Poco::Path& entryName, const Poco::DateTime& l std::string fileStr = entryName.toString(Poco::Path::PATH_UNIX); if (_files.find(fileStr) != _files.end()) return; // ignore duplicate add - if (_files.size() >= 65535) - throw ZipException("Maximum number of entries for a ZIP file reached: 65535"); if (fileStr == "/") throw ZipException("Illegal entry name /"); if (fileStr.empty()) @@ -206,15 +222,17 @@ void Compress::addDirectory(const Poco::Path& entryName, const Poco::DateTime& l ZipLocalFileHeader hdr(entryName, lastModifiedAt, cm, cl); hdr.setStartPos(localHeaderOffset); ZipOutputStream zipOut(_out, hdr, _seekableOut); - zipOut.close(); + Poco::UInt64 extraDataSize; + zipOut.close(extraDataSize); hdr.setStartPos(localHeaderOffset); // reset again now that compressed Size is known _offset = hdr.getEndPos(); if (hdr.searchCRCAndSizesAfterData()) - _offset += ZipDataInfo::getFullHeaderSize(); + _offset += extraDataSize; _files.insert(std::make_pair(entryName.toString(Poco::Path::PATH_UNIX), hdr)); poco_assert (_out); ZipFileInfo nfo(hdr); nfo.setOffset(localHeaderOffset); + nfo.setZip64Data(); _infos.insert(std::make_pair(entryName.toString(Poco::Path::PATH_UNIX), nfo)); EDone.notify(this, hdr); } @@ -274,34 +292,58 @@ void Compress::addRecursive(const Poco::Path& entry, ZipCommon::CompressionMetho ZipArchive Compress::close() { - if (!_dirs.empty()) - return ZipArchive(_files, _infos, _dirs); + if (!_dirs.empty() || ! _dirs64.empty()) + return ZipArchive(_files, _infos, _dirs, _dirs64); poco_assert (_infos.size() == _files.size()); - poco_assert (_files.size() < 65536); - Poco::UInt32 centralDirStart = _offset; - Poco::UInt32 centralDirSize = 0; + Poco::UInt64 centralDirSize64 = 0; + Poco::UInt64 centralDirStart64 = _offset; // write all infos ZipArchive::FileInfos::const_iterator it = _infos.begin(); ZipArchive::FileInfos::const_iterator itEnd = _infos.end(); + bool needZip64 = _forceZip64; + needZip64 = needZip64 || _files.size() >= ZipCommon::ZIP64_MAGIC_SHORT || centralDirStart64 >= ZipCommon::ZIP64_MAGIC; for (; it != itEnd; ++it) { const ZipFileInfo& nfo = it->second; + needZip64 = needZip64 || nfo.needsZip64(); + std::string info(nfo.createHeader()); _out.write(info.c_str(), static_cast(info.size())); Poco::UInt32 entrySize = static_cast(info.size()); - centralDirSize += entrySize; + centralDirSize64 += entrySize; _offset += entrySize; } poco_assert (_out); - - Poco::UInt16 numEntries = static_cast(_infos.size()); + Poco::UInt64 numEntries64 = _infos.size(); + needZip64 = needZip64 || _offset >= ZipCommon::ZIP64_MAGIC; + if(needZip64) + { + ZipArchiveInfo64 central; + central.setCentralDirectorySize(centralDirSize64); + central.setCentralDirectoryOffset(centralDirStart64); + central.setNumberOfEntries(numEntries64); + central.setTotalNumberOfEntries(numEntries64); + central.setHeaderOffset(_offset); + central.setTotalNumberOfDisks(1); + std::string centr(central.createHeader()); + _out.write(centr.c_str(), static_cast(centr.size())); + _out.flush(); + _offset += centr.size(); + _dirs64.insert(std::make_pair(0, central)); + } + + Poco::UInt16 numEntries = numEntries64 >= ZipCommon::ZIP64_MAGIC_SHORT ? ZipCommon::ZIP64_MAGIC_SHORT : static_cast(numEntries64); + Poco::UInt32 centralDirStart = centralDirStart64 >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast(centralDirStart64); + Poco::UInt32 centralDirSize = centralDirSize64 >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast(centralDirSize64); + Poco::UInt32 offset = _offset >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast(_offset); ZipArchiveInfo central; central.setCentralDirectorySize(centralDirSize); + central.setCentralDirectoryOffset(centralDirStart); central.setNumberOfEntries(numEntries); central.setTotalNumberOfEntries(numEntries); - central.setHeaderOffset(centralDirStart); + central.setHeaderOffset(offset); if (!_comment.empty() && _comment.size() <= 65535) { central.setZipComment(_comment); @@ -309,8 +351,9 @@ ZipArchive Compress::close() std::string centr(central.createHeader()); _out.write(centr.c_str(), static_cast(centr.size())); _out.flush(); + _offset += centr.size(); _dirs.insert(std::make_pair(0, central)); - return ZipArchive(_files, _infos, _dirs); + return ZipArchive(_files, _infos, _dirs, _dirs64); } diff --git a/Zip/src/ZipArchive.cpp b/Zip/src/ZipArchive.cpp index c24ed66dd..1d32028cb 100644 --- a/Zip/src/ZipArchive.cpp +++ b/Zip/src/ZipArchive.cpp @@ -5,12 +5,12 @@ // // Library: Zip // Package: Zip -// Module: ZipArchive +// Module: ZipArchive // // Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // and Contributors. // -// SPDX-License-Identifier: BSL-1.0 +// SPDX-License-Identifier: BSL-1.0 // @@ -27,7 +27,8 @@ namespace Zip { ZipArchive::ZipArchive(std::istream& in): _entries(), _infos(), - _disks() + _disks(), + _disks64() { poco_assert_dbg (in); SkipCallback skip; @@ -35,10 +36,11 @@ ZipArchive::ZipArchive(std::istream& in): } -ZipArchive::ZipArchive(const FileHeaders& entries, const FileInfos& infos, const DirectoryInfos& dirs): +ZipArchive::ZipArchive(const FileHeaders& entries, const FileInfos& infos, const DirectoryInfos& dirs, const DirectoryInfos64& dirs64): _entries(entries), _infos(infos), - _disks(dirs) + _disks(dirs), + _disks64(dirs64) { } @@ -46,7 +48,8 @@ ZipArchive::ZipArchive(const FileHeaders& entries, const FileInfos& infos, const ZipArchive::ZipArchive(std::istream& in, ParseCallback& pc): _entries(), _infos(), - _disks() + _disks(), + _disks64() { poco_assert_dbg (in); parse(in, pc); @@ -78,7 +81,7 @@ void ZipArchive::parse(std::istream& in, ParseCallback& pc) FileHeaders::iterator it = _entries.find(info.getFileName()); if (it != _entries.end()) { - it->second.setStartPos(info.getRelativeOffsetOfLocalHeader()); + it->second.setStartPos(info.getOffset()); } poco_assert (_infos.insert(std::make_pair(info.getFileName(), info)).second); } @@ -87,9 +90,14 @@ void ZipArchive::parse(std::istream& in, ParseCallback& pc) ZipArchiveInfo nfo(in, true); poco_assert (_disks.insert(std::make_pair(nfo.getDiskNumber(), nfo)).second); } + else if (std::memcmp(header, ZipArchiveInfo64::HEADER, ZipCommon::HEADER_SIZE) == 0) + { + ZipArchiveInfo64 nfo(in, true); + poco_assert (_disks64.insert(std::make_pair(nfo.getDiskNumber(), nfo)).second); + } else { - if (_disks.empty()) + if (_disks.empty() && _disks64.empty()) throw Poco::IllegalStateException("Illegal header in zip file"); else throw Poco::IllegalStateException("Garbage after directory header"); diff --git a/Zip/src/ZipArchiveInfo.cpp b/Zip/src/ZipArchiveInfo.cpp index c76a53dab..9299eb4cb 100644 --- a/Zip/src/ZipArchiveInfo.cpp +++ b/Zip/src/ZipArchiveInfo.cpp @@ -5,12 +5,12 @@ // // Library: Zip // Package: Zip -// Module: ZipArchiveInfo +// Module: ZipArchiveInfo // // Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // and Contributors. // -// SPDX-License-Identifier: BSL-1.0 +// SPDX-License-Identifier: BSL-1.0 // @@ -38,6 +38,7 @@ ZipArchiveInfo::ZipArchiveInfo(std::istream& in, bool assumeHeaderRead): parse(in, assumeHeaderRead); } + ZipArchiveInfo::ZipArchiveInfo(): _rawInfo(), _startPos(0), @@ -98,4 +99,82 @@ void ZipArchiveInfo::setZipComment(const std::string& comment) } +const char ZipArchiveInfo64::HEADER[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', '\x06', '\x06'}; +const char ZipArchiveInfo64::LOCATOR_HEADER[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', '\x06', '\x07'}; + + +ZipArchiveInfo64::ZipArchiveInfo64(std::istream& in, bool assumeHeaderRead): + _rawInfo(), + _startPos(in.tellg()) +{ + if (assumeHeaderRead) + _startPos -= ZipCommon::HEADER_SIZE; + parse(in, assumeHeaderRead); +} + + +ZipArchiveInfo64::ZipArchiveInfo64(): + _rawInfo(), + _startPos(0) +{ + std::memset(_rawInfo, 0, FULL_HEADER_SIZE); + std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); + ZipUtil::set64BitValue(FULL_HEADER_SIZE - (RECORDSIZE_POS + RECORDSIZE_SIZE), _rawInfo, RECORDSIZE_POS); + std::memset(_locInfo, 0, FULL_LOCATOR_SIZE); + std::memcpy(_locInfo, LOCATOR_HEADER, ZipCommon::HEADER_SIZE); + setRequiredVersion(4, 5); +} + + +ZipArchiveInfo64::~ZipArchiveInfo64() +{ +} + + +void ZipArchiveInfo64::parse(std::istream& inp, bool assumeHeaderRead) +{ + if (!assumeHeaderRead) + { + inp.read(_rawInfo, ZipCommon::HEADER_SIZE); + } + else + { + std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); + } + poco_assert (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) == 0); + std::memset(_rawInfo + ZipCommon::HEADER_SIZE, 0, FULL_HEADER_SIZE - ZipCommon::HEADER_SIZE); + + // read the rest of the header + Poco::UInt64 offset = RECORDSIZE_POS; + inp.read(_rawInfo + ZipCommon::HEADER_SIZE, RECORDSIZE_SIZE); + offset += RECORDSIZE_SIZE; + Poco::UInt64 len = ZipUtil::get64BitValue(_rawInfo, RECORDSIZE_POS); + if (len <= FULL_HEADER_SIZE - offset) + { + inp.read(_rawInfo + offset, len); + ZipUtil::set64BitValue(FULL_HEADER_SIZE - offset, _rawInfo, RECORDSIZE_POS); + } + else + { + inp.read(_rawInfo + offset, FULL_HEADER_SIZE - offset); + len -= (FULL_HEADER_SIZE - offset); + Poco::Buffer xtra(len); + inp.read(xtra.begin(), len); + _extraField = std::string(xtra.begin(), len); + ZipUtil::set64BitValue(FULL_HEADER_SIZE + len - offset, _rawInfo, RECORDSIZE_POS); + } + inp.read(_locInfo, FULL_LOCATOR_SIZE); + poco_assert (std::memcmp(_locInfo, LOCATOR_HEADER, ZipCommon::HEADER_SIZE) == 0); +} + + +std::string ZipArchiveInfo64::createHeader() const +{ + std::string result(_rawInfo, FULL_HEADER_SIZE); + result.append(_extraField); + result.append(_locInfo, FULL_LOCATOR_SIZE); + return result; +} + + } } // namespace Poco::Zip diff --git a/Zip/src/ZipDataInfo.cpp b/Zip/src/ZipDataInfo.cpp index 3d5197a0c..79b70e8a2 100644 --- a/Zip/src/ZipDataInfo.cpp +++ b/Zip/src/ZipDataInfo.cpp @@ -56,4 +56,38 @@ ZipDataInfo::~ZipDataInfo() } + +const char ZipDataInfo64::HEADER[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', '\x07', '\x08'}; + + +ZipDataInfo64::ZipDataInfo64(): + _rawInfo(), + _valid(true) +{ + std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); + std::memset(_rawInfo+ZipCommon::HEADER_SIZE, 0, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); + _valid = true; +} + + +ZipDataInfo64::ZipDataInfo64(std::istream& in, bool assumeHeaderRead): + _rawInfo(), + _valid(false) +{ + if (assumeHeaderRead) + std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); + else + in.read(_rawInfo, ZipCommon::HEADER_SIZE); + poco_assert (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) == 0); + // now copy the rest of the header + in.read(_rawInfo+ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); + _valid = (!in.eof() && in.good()); +} + + +ZipDataInfo64::~ZipDataInfo64() +{ +} + + } } // namespace Poco::Zip diff --git a/Zip/src/ZipFileInfo.cpp b/Zip/src/ZipFileInfo.cpp index aa91571cc..69ec052df 100644 --- a/Zip/src/ZipFileInfo.cpp +++ b/Zip/src/ZipFileInfo.cpp @@ -5,12 +5,12 @@ // // Library: Zip // Package: Zip -// Module: ZipFileInfo +// Module: ZipFileInfo // // Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // and Contributors. // -// SPDX-License-Identifier: BSL-1.0 +// SPDX-License-Identifier: BSL-1.0 // @@ -33,6 +33,7 @@ ZipFileInfo::ZipFileInfo(const ZipLocalFileHeader& header): _crc32(0), _compressedSize(0), _uncompressedSize(0), + _localHeaderOffset(0), _fileName(), _lastModifiedAt(), _extraField() @@ -52,6 +53,8 @@ ZipFileInfo::ZipFileInfo(const ZipLocalFileHeader& header): if (getHostSystem() == ZipCommon::HS_UNIX) setUnixAttributes(); + + _rawInfo[GENERAL_PURPOSE_POS+1] |= 0x08; // Set "language encoding flag" to indicate that filenames and paths are in UTF-8. } @@ -60,6 +63,7 @@ ZipFileInfo::ZipFileInfo(std::istream& in, bool assumeHeaderRead): _crc32(0), _compressedSize(0), _uncompressedSize(0), + _localHeaderOffset(0), _fileName(), _lastModifiedAt(), _extraField() @@ -102,6 +106,25 @@ void ZipFileInfo::parse(std::istream& inp, bool assumeHeaderRead) Poco::Buffer xtra(len); inp.read(xtra.begin(), len); _extraField = std::string(xtra.begin(), len); + char* ptr = xtra.begin(); + while(ptr <= xtra.begin() + len - 4) { + Poco::UInt16 id = ZipUtil::get16BitValue(ptr, 0); ptr +=2; + Poco::UInt16 size = ZipUtil::get16BitValue(ptr, 0); ptr += 2; + if(id == ZipCommon::ZIP64_EXTRA_ID) { + poco_assert(size >= 8); + if(getUncompressedSizeFromHeader() == ZipCommon::ZIP64_MAGIC) { + setUncompressedSize(ZipUtil::get64BitValue(ptr, 0)); size -= 8; ptr += 8; + } + if(size >= 8 && getCompressedSizeFromHeader() == ZipCommon::ZIP64_MAGIC) { + setCompressedSize(ZipUtil::get64BitValue(ptr, 0)); size -= 8; ptr += 8; + } + if(size >= 8 && getOffsetFromHeader() == ZipCommon::ZIP64_MAGIC) { + setOffset(ZipUtil::get64BitValue(ptr, 0)); size -= 8; ptr += 8; + } + } else { + ptr += size; + } + } } len = getFileCommentLength(); if (len > 0) diff --git a/Zip/src/ZipLocalFileHeader.cpp b/Zip/src/ZipLocalFileHeader.cpp index 7e81aec74..64dae2b90 100644 --- a/Zip/src/ZipLocalFileHeader.cpp +++ b/Zip/src/ZipLocalFileHeader.cpp @@ -10,7 +10,7 @@ // Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // and Contributors. // -// SPDX-License-Identifier: BSL-1.0 +// SPDX-License-Identifier: BSL-1.0 // @@ -31,76 +31,91 @@ const char ZipLocalFileHeader::HEADER[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', ZipLocalFileHeader::ZipLocalFileHeader(const Poco::Path& fileName, - const Poco::DateTime& lastModifiedAt, - ZipCommon::CompressionMethod cm, - ZipCommon::CompressionLevel cl): - _rawHeader(), - _startPos(-1), - _endPos(-1), - _fileName(), - _lastModifiedAt(), - _extraField(), - _crc32(0), - _compressedSize(0), - _uncompressedSize(0) + const Poco::DateTime& lastModifiedAt, + ZipCommon::CompressionMethod cm, + ZipCommon::CompressionLevel cl, + bool forceZip64): + _forceZip64(forceZip64), + _rawHeader(), + _startPos(-1), + _endPos(-1), + _fileName(), + _lastModifiedAt(), + _extraField(), + _crc32(0), + _compressedSize(0), + _uncompressedSize(0) { - std::memcpy(_rawHeader, HEADER, ZipCommon::HEADER_SIZE); - std::memset(_rawHeader+ZipCommon::HEADER_SIZE, 0, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); - ZipCommon::HostSystem hs = ZipCommon::HS_FAT; + std::memcpy(_rawHeader, HEADER, ZipCommon::HEADER_SIZE); + std::memset(_rawHeader+ZipCommon::HEADER_SIZE, 0, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); + ZipCommon::HostSystem hs = ZipCommon::HS_FAT; #if (POCO_OS == POCO_OS_CYGWIN) - hs = ZipCommon::HS_UNIX; + hs = ZipCommon::HS_UNIX; #endif #if (POCO_OS == POCO_OS_VMS) - hs = ZipCommon::HS_VMS; + hs = ZipCommon::HS_VMS; #endif #if defined(POCO_OS_FAMILY_UNIX) - hs = ZipCommon::HS_UNIX; + hs = ZipCommon::HS_UNIX; #endif - setHostSystem(hs); - setEncryption(false); - setExtraFieldSize(0); - setLastModifiedAt(lastModifiedAt); - init(fileName, cm, cl); + setHostSystem(hs); + setEncryption(false); + setExtraFieldSize(0); + setLastModifiedAt(lastModifiedAt); + init(fileName, cm, cl); } ZipLocalFileHeader::ZipLocalFileHeader(std::istream& inp, bool assumeHeaderRead, ParseCallback& callback): - _rawHeader(), - _startPos(inp.tellg()), - _endPos(-1), - _fileName(), - _lastModifiedAt(), - _extraField(), - _crc32(0), - _compressedSize(0), - _uncompressedSize(0) + _forceZip64(false), + _rawHeader(), + _startPos(inp.tellg()), + _endPos(-1), + _fileName(), + _lastModifiedAt(), + _extraField(), + _crc32(0), + _compressedSize(0), + _uncompressedSize(0) { - poco_assert_dbg( (EXTRAFIELD_POS+EXTRAFIELD_LENGTH) == FULLHEADER_SIZE); + poco_assert_dbg( (EXTRA_FIELD_POS+EXTRA_FIELD_LENGTH) == FULLHEADER_SIZE); - if (assumeHeaderRead) - _startPos -= ZipCommon::HEADER_SIZE; + if (assumeHeaderRead) + _startPos -= ZipCommon::HEADER_SIZE; - parse(inp, assumeHeaderRead); + parse(inp, assumeHeaderRead); - bool ok = callback.handleZipEntry(inp, *this); + bool ok = callback.handleZipEntry(inp, *this); - if (ok) - { - if (searchCRCAndSizesAfterData()) - { - ZipDataInfo nfo(inp, false); - setCRC(nfo.getCRC32()); - setCompressedSize(nfo.getCompressedSize()); - setUncompressedSize(nfo.getUncompressedSize()); - } - } - else - { - poco_assert_dbg(!searchCRCAndSizesAfterData()); - ZipUtil::sync(inp); - } - _endPos = _startPos + getHeaderSize() + _compressedSize; // exclude the data block! + if (ok) + { + if (searchCRCAndSizesAfterData()) + { + char header[ZipCommon::HEADER_SIZE]={'\x00', '\x00', '\x00', '\x00'}; + inp.read(header, ZipCommon::HEADER_SIZE); + if (std::memcmp(header, ZipDataInfo64::HEADER, sizeof(header)) == 0) + { + ZipDataInfo64 nfo(inp, true); + setCRC(nfo.getCRC32()); + setCompressedSize(nfo.getCompressedSize()); + setUncompressedSize(nfo.getUncompressedSize()); + } + else + { + ZipDataInfo nfo(inp, true); + setCRC(nfo.getCRC32()); + setCompressedSize(nfo.getCompressedSize()); + setUncompressedSize(nfo.getUncompressedSize()); + } + } + } + else + { + poco_assert_dbg(!searchCRCAndSizesAfterData()); + ZipUtil::sync(inp); + } + _endPos = _startPos + getHeaderSize() + _compressedSize; // exclude the data block! } @@ -111,108 +126,134 @@ ZipLocalFileHeader::~ZipLocalFileHeader() void ZipLocalFileHeader::parse(std::istream& inp, bool assumeHeaderRead) { - if (!assumeHeaderRead) - { - inp.read(_rawHeader, ZipCommon::HEADER_SIZE); - } - else - { - std::memcpy(_rawHeader, HEADER, ZipCommon::HEADER_SIZE); - } - poco_assert (std::memcmp(_rawHeader, HEADER, ZipCommon::HEADER_SIZE) == 0); - // read the rest of the header - inp.read(_rawHeader + ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); - if (!(_rawHeader[VERSION_POS + 1]>= ZipCommon::HS_FAT && _rawHeader[VERSION_POS + 1] < ZipCommon::HS_UNUSED)) - throw Poco::DataFormatException("bad ZIP file header", "invalid version"); - if (ZipUtil::get16BitValue(_rawHeader, COMPR_METHOD_POS) >= ZipCommon::CM_UNUSED) - throw Poco::DataFormatException("bad ZIP file header", "invalid compression method"); - parseDateTime(); - Poco::UInt16 len = getFileNameLength(); - Poco::Buffer buf(len); - inp.read(buf.begin(), len); - _fileName = std::string(buf.begin(), len); - if (hasExtraField()) - { - len = getExtraFieldLength(); - Poco::Buffer xtra(len); - inp.read(xtra.begin(), len); - _extraField = std::string(xtra.begin(), len); - } - if (!searchCRCAndSizesAfterData()) - { - _crc32 = getCRCFromHeader(); - _compressedSize = getCompressedSizeFromHeader(); - _uncompressedSize = getUncompressedSizeFromHeader(); - } + if (!assumeHeaderRead) + { + inp.read(_rawHeader, ZipCommon::HEADER_SIZE); + } + else + { + std::memcpy(_rawHeader, HEADER, ZipCommon::HEADER_SIZE); + } + poco_assert (std::memcmp(_rawHeader, HEADER, ZipCommon::HEADER_SIZE) == 0); + // read the rest of the header + inp.read(_rawHeader + ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); + poco_assert (_rawHeader[VERSION_POS + 1]>= ZipCommon::HS_FAT && _rawHeader[VERSION_POS + 1] < ZipCommon::HS_UNUSED); + poco_assert (getMajorVersionNumber() <= 4); // Allow for Zip64 version 4.5 + poco_assert (ZipUtil::get16BitValue(_rawHeader, COMPR_METHOD_POS) < ZipCommon::CM_UNUSED); + parseDateTime(); + Poco::UInt16 len = getFileNameLength(); + Poco::Buffer buf(len); + inp.read(buf.begin(), len); + _fileName = std::string(buf.begin(), len); + + if (!searchCRCAndSizesAfterData()) + { + _crc32 = getCRCFromHeader(); + _compressedSize = getCompressedSizeFromHeader(); + _uncompressedSize = getUncompressedSizeFromHeader(); + } + + if (hasExtraField()) + { + len = getExtraFieldLength(); + Poco::Buffer xtra(len); + inp.read(xtra.begin(), len); + _extraField = std::string(xtra.begin(), len); + char* ptr = xtra.begin(); + while (ptr <= xtra.begin() + len - 4) + { + Poco::UInt16 id = ZipUtil::get16BitValue(ptr, 0); ptr +=2; + Poco::UInt16 size = ZipUtil::get16BitValue(ptr, 0); ptr += 2; + if (id == ZipCommon::ZIP64_EXTRA_ID) + { + poco_assert(size >= 8); + if (getUncompressedSizeFromHeader() == ZipCommon::ZIP64_MAGIC) + { + setUncompressedSize(ZipUtil::get64BitValue(ptr, 0)); size -= 8; ptr += 8; + } + if (size >= 8 && getCompressedSizeFromHeader() == ZipCommon::ZIP64_MAGIC) + { + setCompressedSize(ZipUtil::get64BitValue(ptr, 0)); size -= 8; ptr += 8; + } + } + else + { + ptr += size; + } + } + } + } bool ZipLocalFileHeader::searchCRCAndSizesAfterData() const { - if (getCompressionMethod() == ZipCommon::CM_DEFLATE) - { - // check bit 3 - return ((ZipUtil::get16BitValue(_rawHeader, GENERAL_PURPOSE_POS) & 0x0008) != 0); - } - return false; + if (getCompressionMethod() == ZipCommon::CM_DEFLATE) + { + // check bit 3 + return ((ZipUtil::get16BitValue(_rawHeader, GENERAL_PURPOSE_POS) & 0x0008) != 0); + } + return false; } void ZipLocalFileHeader::setFileName(const std::string& fileName, bool isDirectory) { - poco_assert (!fileName.empty()); - Poco::Path aPath(fileName); + poco_assert (!fileName.empty()); + Poco::Path aPath(fileName); - if (isDirectory) - { - aPath.makeDirectory(); - setCRC(0); - setCompressedSize(0); - setUncompressedSize(0); - setCompressionMethod(ZipCommon::CM_STORE); - setCompressionLevel(ZipCommon::CL_NORMAL); - } - else - { - aPath.makeFile(); - } - _fileName = aPath.toString(Poco::Path::PATH_UNIX); - if (_fileName[0] == '/') - _fileName = _fileName.substr(1); - if (isDirectory) - { - poco_assert_dbg (_fileName[_fileName.size()-1] == '/'); - } - setFileNameLength(static_cast(_fileName.size())); + if (isDirectory) + { + aPath.makeDirectory(); + setCRC(0); + setCompressedSize(0); + setUncompressedSize(0); + setCompressionMethod(ZipCommon::CM_STORE); + setCompressionLevel(ZipCommon::CL_NORMAL); + } + else + { + aPath.makeFile(); + } + _fileName = aPath.toString(Poco::Path::PATH_UNIX); + if (_fileName[0] == '/') + _fileName = _fileName.substr(1); + if (isDirectory) + { + poco_assert_dbg (_fileName[_fileName.size()-1] == '/'); + } + setFileNameLength(static_cast(_fileName.size())); } -void ZipLocalFileHeader::init( const Poco::Path& fName, - ZipCommon::CompressionMethod cm, - ZipCommon::CompressionLevel cl) +void ZipLocalFileHeader::init(const Poco::Path& fName, ZipCommon::CompressionMethod cm, ZipCommon::CompressionLevel cl) { - poco_assert (_fileName.empty()); - setSearchCRCAndSizesAfterData(false); - Poco::Path fileName(fName); - fileName.setDevice(""); // clear device! - setFileName(fileName.toString(Poco::Path::PATH_UNIX), fileName.isDirectory()); - setRequiredVersion(2, 0); - if (fileName.isFile()) - { - setCompressionMethod(cm); - setCompressionLevel(cl); - } - else - setCompressionMethod(ZipCommon::CM_STORE); + poco_assert (_fileName.empty()); + setSearchCRCAndSizesAfterData(false); + Poco::Path fileName(fName); + fileName.setDevice(""); // clear device! + setFileName(fileName.toString(Poco::Path::PATH_UNIX), fileName.isDirectory()); + setRequiredVersion(2, 0); + if (fileName.isFile()) + { + setCompressionMethod(cm); + setCompressionLevel(cl); + } + else + setCompressionMethod(ZipCommon::CM_STORE); + if (_forceZip64) + setZip64Data(); + + _rawHeader[GENERAL_PURPOSE_POS+1] |= 0x08; // Set "language encoding flag" to indicate that filenames and paths are in UTF-8. } std::string ZipLocalFileHeader::createHeader() const { - std::string result(_rawHeader, FULLHEADER_SIZE); - result.append(_fileName); - result.append(_extraField); - return result; + std::string result(_rawHeader, FULLHEADER_SIZE); + result.append(_fileName); + result.append(_extraField); + return result; } diff --git a/Zip/src/ZipStream.cpp b/Zip/src/ZipStream.cpp index e8d466a0d..4505f5efa 100644 --- a/Zip/src/ZipStream.cpp +++ b/Zip/src/ZipStream.cpp @@ -135,6 +135,8 @@ ZipStreamBuf::ZipStreamBuf(std::ostream& ostr, ZipLocalFileHeader& fileEntry, bo else throw Poco::NotImplementedException("Unsupported compression method"); // now write the header to the ostr! + if (fileEntry.needsZip64()) + fileEntry.setZip64Data(); std::string header = fileEntry.createHeader(); ostr.write(header.c_str(), static_cast(header.size())); } @@ -198,8 +200,9 @@ int ZipStreamBuf::writeToDevice(const char* buffer, std::streamsize length) } -void ZipStreamBuf::close() +void ZipStreamBuf::close(Poco::UInt64& extraDataSize) { + extraDataSize = 0; if (_ptrOBuf && _pHeader) { _ptrOBuf->flush(); @@ -217,20 +220,36 @@ void ZipStreamBuf::close() // or fix the crc entries if (_pHeader->searchCRCAndSizesAfterData()) { - ZipDataInfo info; - info.setCRC32(_crc32.checksum()); - info.setUncompressedSize(_bytesWritten); - info.setCompressedSize(static_cast(_ptrOHelper->bytesWritten())); - _pOstr->write(info.getRawHeader(), static_cast(info.getFullHeaderSize())); + if (_pHeader->needsZip64()) + { + ZipDataInfo64 info; + info.setCRC32(_crc32.checksum()); + info.setUncompressedSize(_bytesWritten); + info.setCompressedSize(_ptrOHelper->bytesWritten()); + extraDataSize = info.getFullHeaderSize(); + _pOstr->write(info.getRawHeader(), static_cast(extraDataSize)); + } + else + { + ZipDataInfo info; + info.setCRC32(_crc32.checksum()); + info.setUncompressedSize(static_cast(_bytesWritten)); + info.setCompressedSize(static_cast(_ptrOHelper->bytesWritten())); + extraDataSize = info.getFullHeaderSize(); + _pOstr->write(info.getRawHeader(), static_cast(extraDataSize)); + } } else { poco_check_ptr (_pHeader); _pHeader->setCRC(_crc32.checksum()); _pHeader->setUncompressedSize(_bytesWritten); - _pHeader->setCompressedSize(static_cast(_ptrOHelper->bytesWritten())); + _pHeader->setCompressedSize(_ptrOHelper->bytesWritten()); _pOstr->seekp(_pHeader->getStartPos(), std::ios_base::beg); poco_assert (*_pOstr); + _pHeader->setStartPos(_pHeader->getStartPos()); // This resets EndPos now that compressed Size is known + if (_pHeader->hasExtraField()) // Update sizes in header extension. + _pHeader->setZip64Data(); std::string header = _pHeader->createHeader(); _pOstr->write(header.c_str(), static_cast(header.size())); _pOstr->seekp(0, std::ios_base::end); @@ -297,10 +316,10 @@ ZipOutputStream::~ZipOutputStream() } -void ZipOutputStream::close() +void ZipOutputStream::close(Poco::UInt64& extraDataSize) { flush(); - _buf.close(); + _buf.close(extraDataSize); } diff --git a/Zip/testsuite/src/CompressTest.cpp b/Zip/testsuite/src/CompressTest.cpp index ee8bf8428..4af1598f4 100644 --- a/Zip/testsuite/src/CompressTest.cpp +++ b/Zip/testsuite/src/CompressTest.cpp @@ -6,12 +6,13 @@ // Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // and Contributors. // -// SPDX-License-Identifier: BSL-1.0 +// SPDX-License-Identifier: BSL-1.0 // #include "CompressTest.h" #include "ZipTest.h" +#include "Poco/Buffer.h" #include "Poco/Zip/Compress.h" #include "Poco/Zip/ZipManipulator.h" #include "Poco/File.h" @@ -19,6 +20,8 @@ #include "CppUnit/TestCaller.h" #include "CppUnit/TestSuite.h" #include +#undef min +#include using namespace Poco::Zip; @@ -134,6 +137,57 @@ void CompressTest::testSetZipComment() } +void CompressTest::createDataFile(const std::string& path, Poco::UInt64 size) +{ + std::ofstream out(path.c_str(), std::ios::binary | std::ios::trunc); + assert( ! out.fail() ); + Poco::Buffer buffer(MB); + for(int i = 0; size != 0; i++) { + std::memset(buffer.begin(), i, buffer.size()); + Poco::UInt64 bytesToWrite = std::min(size, static_cast(buffer.size())); + out.write(buffer.begin(), bytesToWrite); + assert( ! out.fail() ); + size -= bytesToWrite; + } + out.flush(); + assert( ! out.fail() ); + out.close(); + assert( ! out.fail() ); +} + + +void CompressTest::testZip64() +{ + std::map files; + files["data1.bin"] = static_cast(MB)*4096+1; + files["data2.bin"] = static_cast(MB)*16; + files["data3.bin"] = static_cast(MB)*4096-1; + + for(std::map::const_iterator it = files.begin(); it != files.end(); it++) + { + createDataFile(it->first, it->second); + } + std::ofstream out("zip64.zip", std::ios::binary | std::ios::trunc); + Compress c(out, true, true); + for(std::map::const_iterator it = files.begin(); it != files.end(); it++) + { + const std::string& path = it->first; + c.addFile(path, path, ZipCommon::CM_STORE); + } + ZipArchive a(c.close()); + for(std::map::const_iterator it = files.begin(); it != files.end(); it++) + { + const std::string& path = it->first; + Poco::UInt64 size = it->second; + ZipArchive::FileHeaders::const_iterator it2 = a.findHeader(path); + assert (it2 != a.headerEnd()); + const Poco::Zip::ZipLocalFileHeader& file = it2->second; + assert(file.getUncompressedSize() == size); + assert(file.getCompressedSize() == size); + } +} + + void CompressTest::setUp() { } @@ -154,6 +208,7 @@ CppUnit::Test* CompressTest::suite() CppUnit_addTest(pSuite, CompressTest, testManipulatorDel); CppUnit_addTest(pSuite, CompressTest, testManipulatorReplace); CppUnit_addTest(pSuite, CompressTest, testSetZipComment); + CppUnit_addTest(pSuite, CompressTest, testZip64); return pSuite; } diff --git a/Zip/testsuite/src/CompressTest.h b/Zip/testsuite/src/CompressTest.h index 98fbd56ed..0d24921a7 100644 --- a/Zip/testsuite/src/CompressTest.h +++ b/Zip/testsuite/src/CompressTest.h @@ -8,7 +8,7 @@ // Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // and Contributors. // -// SPDX-License-Identifier: BSL-1.0 +// SPDX-License-Identifier: BSL-1.0 // @@ -33,6 +33,10 @@ public: void testManipulatorReplace(); void testSetZipComment(); + static const Poco::UInt64 MB = (1024*1024); + void createDataFile(const std::string& path, Poco::UInt64 size); + void testZip64(); + void setUp(); void tearDown(); diff --git a/Zip/testsuite/src/ZipTest.cpp b/Zip/testsuite/src/ZipTest.cpp index 0b89bd9e6..48bad1765 100644 --- a/Zip/testsuite/src/ZipTest.cpp +++ b/Zip/testsuite/src/ZipTest.cpp @@ -6,7 +6,7 @@ // Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // and Contributors. // -// SPDX-License-Identifier: BSL-1.0 +// SPDX-License-Identifier: BSL-1.0 // @@ -25,6 +25,8 @@ #include "Poco/StreamCopier.h" #include "CppUnit/TestCaller.h" #include "CppUnit/TestSuite.h" +#undef min +#include #include #include @@ -58,8 +60,8 @@ void ZipTest::testSkipSingleFile() ZipCommon::CompressionMethod cm = hdr.getCompressionMethod(); assert (!hdr.isEncrypted()); Poco::DateTime aDate = hdr.lastModifiedAt(); - Poco::UInt32 cS = hdr.getCompressedSize(); - Poco::UInt32 uS = hdr.getUncompressedSize(); + Poco::UInt64 cS = hdr.getCompressedSize(); + Poco::UInt64 uS = hdr.getUncompressedSize(); const std::string& fileName = hdr.getFileName(); } @@ -164,6 +166,51 @@ void ZipTest::testDecompressFlat() } +void ZipTest::verifyDataFile(const std::string& path, Poco::UInt64 size) +{ + std::ifstream in(path.c_str(), std::ios::binary); + assert( ! in.fail() ); + Poco::Buffer buffer1(MB); + Poco::Buffer buffer2(MB); + for (int i = 0; size != 0; i++) + { + std::memset(buffer1.begin(), i, buffer1.size()); + std::memset(buffer2.begin(), 0, buffer2.size()); + Poco::UInt64 bytesToRead = std::min(size, static_cast(buffer2.size())); + in.read(buffer2.begin(), bytesToRead); + assert(!in.fail() ); + assert(std::memcmp(buffer1.begin(), buffer2.begin(), static_cast(bytesToRead)) == 0); + size -= bytesToRead; + } + char c; + in.read(&c, 1); + assert ( in.eof() ); +} + + +void ZipTest::testDecompressZip64() +{ + std::map files; + files["data1.bin"] = static_cast(MB)*4096+1; + files["data2.bin"] = static_cast(MB)*16; + files["data3.bin"] = static_cast(MB)*4096-1; + + for(std::map::const_iterator it = files.begin(); it != files.end(); it++) + { + Poco::File file(it->first); + if(file.exists()) + file.remove(); + } + std::ifstream in("zip64.zip", std::ios::binary); + Decompress c(in, "."); + c.decompressAllFiles(); + for(std::map::const_iterator it = files.begin(); it != files.end(); it++) + { + verifyDataFile(it->first, it->second); + } +} + + void ZipTest::onDecompressError(const void* pSender, std::pair& info) { ++_errCnt; @@ -191,5 +238,7 @@ CppUnit::Test* ZipTest::suite() CppUnit_addTest(pSuite, ZipTest, testDecompressFlat); CppUnit_addTest(pSuite, ZipTest, testCrcAndSizeAfterData); CppUnit_addTest(pSuite, ZipTest, testCrcAndSizeAfterDataWithArchive); + CppUnit_addTest(pSuite, ZipTest, testDecompressZip64); + return pSuite; } diff --git a/Zip/testsuite/src/ZipTest.h b/Zip/testsuite/src/ZipTest.h index 8f8adeeb1..312b9a63e 100644 --- a/Zip/testsuite/src/ZipTest.h +++ b/Zip/testsuite/src/ZipTest.h @@ -8,7 +8,7 @@ // Copyright (c) 2007, Applied Informatics Software Engineering GmbH. // and Contributors. // -// SPDX-License-Identifier: BSL-1.0 +// SPDX-License-Identifier: BSL-1.0 // @@ -35,6 +35,10 @@ public: void testDecompressFlat(); + static const Poco::UInt64 MB = (1024*1024); + void verifyDataFile(const std::string& path, Poco::UInt64 size); + void testDecompressZip64(); + void setUp(); void tearDown(); diff --git a/Zip/testsuite/src/ZipTestSuite.cpp b/Zip/testsuite/src/ZipTestSuite.cpp index 6e5832a12..1dc55bf03 100644 --- a/Zip/testsuite/src/ZipTestSuite.cpp +++ b/Zip/testsuite/src/ZipTestSuite.cpp @@ -20,9 +20,9 @@ CppUnit::Test* ZipTestSuite::suite() { CppUnit::TestSuite* pSuite = new CppUnit::TestSuite("ZipTestSuite"); + pSuite->addTest(CompressTest::suite()); pSuite->addTest(ZipTest::suite()); pSuite->addTest(PartialStreamTest::suite()); - pSuite->addTest(CompressTest::suite()); return pSuite; } diff --git a/build/config/iPhone b/build/config/iPhone index b4320bb74..84f3d1d8c 100644 --- a/build/config/iPhone +++ b/build/config/iPhone @@ -30,7 +30,7 @@ IPHONE_SDK_VERSION_MIN ?= $(patsubst %.sdk,%,$(patsubst $(IPHONE_SDK_ROOT_DIR)%, POCO_TARGET_OSNAME ?= $(IPHONE_SDK) POCO_TARGET_OSARCH ?= armv6 -TOOL_PREFIX ?= /Developer/Platforms/$(IPHONE_SDK).platform/Developer/usr/bin +TOOL_PREFIX ?= $(shell xcode-select -print-path)/Platforms/$(IPHONE_SDK).platform/Developer/usr/bin OSFLAGS ?= -arch $(POCO_TARGET_OSARCH) -isysroot $(IPHONE_SDK_BASE) -mthumb -miphoneos-version-min=$(IPHONE_SDK_VERSION_MIN) # @@ -39,8 +39,8 @@ OSFLAGS ?= -arch $(POCO_TARGET_OSARCH) -isysroot $(IPHONE_SDK_BAS # If GCC_VER is defined then use it. # Otherwise select the latest version # -CC = $(shell ls $(TOOL_PREFIX)/llvm-gcc-$(GCC_VER)* | tail -1) -CXX = $(shell ls $(TOOL_PREFIX)/llvm-g++-$(GCC_VER)* | tail -1) +CC = $(shell xcrun -find clang) +CXX = $(shell xcrun -find clang++) LINK = $(CXX) -bind_at_load LIB = libtool -static -o diff --git a/cmake/DefinePlatformSpecifc.cmake b/cmake/DefinePlatformSpecifc.cmake new file mode 100644 index 000000000..2e76faeff --- /dev/null +++ b/cmake/DefinePlatformSpecifc.cmake @@ -0,0 +1,111 @@ +# http://www.cmake.org/Wiki/CMake_Useful_Variables : +# CMAKE_BUILD_TYPE +# Choose the type of build. CMake has default flags for these: +# +# * None (CMAKE_C_FLAGS or CMAKE_CXX_FLAGS used) +# * Debug (CMAKE_C_FLAGS_DEBUG or CMAKE_CXX_FLAGS_DEBUG) +# * Release (CMAKE_C_FLAGS_RELEASE or CMAKE_CXX_FLAGS_RELEASE) +# * RelWithDebInfo (CMAKE_C_FLAGS_RELWITHDEBINFO or CMAKE_CXX_FLAGS_RELWITHDEBINFO +# * MinSizeRel (CMAKE_C_FLAGS_MINSIZEREL or CMAKE_CXX_FLAGS_MINSIZEREL) + +# Setting CXX Flag /MD or /MT and POSTFIX values i.e MDd / MD / MTd / MT / d +# +# For visual studio the library naming is as following: +# Dynamic libraries: +# - PocoX.dll for release library +# - PocoXd.dll for debug library +# +# Static libraries: +# - PocoXmd.lib for /MD release build +# - PocoXtmt.lib for /MT release build +# +# - PocoXmdd.lib for /MD debug build +# - PocoXmtd.lib for /MT debug build + +if(MSVC) + if(POCO_MT) + set(CompilerFlags + CMAKE_CXX_FLAGS + CMAKE_CXX_FLAGS_DEBUG + CMAKE_CXX_FLAGS_RELEASE + CMAKE_C_FLAGS + CMAKE_C_FLAGS_DEBUG + CMAKE_C_FLAGS_RELEASE + ) + foreach(CompilerFlag ${CompilerFlags}) + string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}") + endforeach() + + set(STATIC_POSTFIX "mt" CACHE STRING "Set static library postfix" FORCE) + else(POCO_MT) + set(STATIC_POSTFIX "md" CACHE STRING "Set static library postfix" FORCE) + endif(POCO_MT) +else(MSVC) + # Other compilers then MSVC don't have a static STATIC_POSTFIX at the moment + set(STATIC_POSTFIX "" CACHE STRING "Set static library postfix" FORCE) +endif(MSVC) + +# Add a d postfix to the debug libraries +if(POCO_STATIC) + set(CMAKE_DEBUG_POSTFIX "${STATIC_POSTFIX}d" CACHE STRING "Set Debug library postfix" FORCE) + set(CMAKE_RELEASE_POSTFIX "${STATIC_POSTFIX}" CACHE STRING "Set Release library postfix" FORCE) + set(CMAKE_MINSIZEREL_POSTFIX "${STATIC_POSTFIX}" CACHE STRING "Set MinSizeRel library postfix" FORCE) + set(CMAKE_RELWITHDEBINFO_POSTFIX "${STATIC_POSTFIX}d" CACHE STRING "Set RelWithDebInfo library postfix" FORCE) +else(POCO_STATIC) + set(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Set Debug library postfix" FORCE) + set(CMAKE_RELEASE_POSTFIX "" CACHE STRING "Set Release library postfix" FORCE) + set(CMAKE_MINSIZEREL_POSTFIX "" CACHE STRING "Set MinSizeRel library postfix" FORCE) + set(CMAKE_RELWITHDEBINFO_POSTFIX "d" CACHE STRING "Set RelWithDebInfo library postfix" FORCE) +endif() + + +# OS Detection +include(CheckTypeSize) +find_package(Cygwin) + +if(WIN32) + add_definitions( -DPOCO_OS_FAMILY_WINDOWS -DUNICODE -D_UNICODE -D__LCC__) #__LCC__ define used by MySQL.h +endif(WIN32) + +if (UNIX AND NOT ANDROID ) + add_definitions( -DPOCO_OS_FAMILY_UNIX ) + # Standard 'must be' defines + if (APPLE) + add_definitions( -DPOCO_HAVE_IPv6 -DPOCO_NO_STAT64) + set(SYSLIBS dl) + else (APPLE) + add_definitions( -D_XOPEN_SOURCE=500 -D_REENTRANT -D_THREAD_SAFE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64) + set(SYSLIBS pthread dl rt) + endif (APPLE) +endif(UNIX AND NOT ANDROID ) + +if (CMAKE_SYSTEM MATCHES "SunOS") + add_definitions( -DPOCO_OS_FAMILY_UNIX ) + # Standard 'must be' defines + add_definitions( -D_XOPEN_SOURCE=500 -D_REENTRANT -D_THREAD_SAFE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 ) + set(SYSLIBS pthread socket xnet nsl resolv rt dl) +endif(CMAKE_SYSTEM MATCHES "SunOS") + +if (CMAKE_COMPILER_IS_MINGW) + add_definitions(-DWC_NO_BEST_FIT_CHARS=0x400 -DPOCO_WIN32_UTF8) + add_definitions(-D_WIN32 -DMINGW32 -DWINVER=0x500 -DODBCVER=0x0300 -DPOCO_THREAD_STACK_SIZE) +endif (CMAKE_COMPILER_IS_MINGW) + +if (CYGWIN) +# add_definitions(-DWC_NO_BEST_FIT_CHARS=0x400 -DPOCO_WIN32_UTF8) +endif (CYGWIN) + +# SunPro C++ +if (${CMAKE_CXX_COMPILER_ID} MATCHES "SunPro") + add_definitions( -D_BSD_SOURCE -library=stlport4) +endif (${CMAKE_CXX_COMPILER_ID} MATCHES "SunPro") + +# iOS +if (IOS) + add_definitions( -DPOCO_HAVE_IPv6 -DPOCO_NO_FPENVIRONMENT -DPOCO_NO_STAT64 -DPOCO_NO_SHAREDLIBS -DPOCO_NO_NET_IFTYPES ) +endif(IOS) + +#Android +if (ANDROID) + add_definitions( -DPOCO_ANDROID -DPOCO_NO_FPENVIRONMENT -DPOCO_NO_WSTRING -DPOCO_NO_SHAREDMEMORY ) +endif(ANDROID) \ No newline at end of file diff --git a/cmake/FindMySQL.cmake b/cmake/FindMySQL.cmake index c8a9b1b8c..64763d8bb 100644 --- a/cmake/FindMySQL.cmake +++ b/cmake/FindMySQL.cmake @@ -1,3 +1,6 @@ +SET(BINDIR32_ENV_NAME "ProgramFiles(x86)") +SET(BINDIR32 $ENV{${BINDIR32_ENV_NAME}}) + find_path(MYSQL_INCLUDE_DIR mysql.h /usr/include/mysql /usr/local/include/mysql @@ -8,6 +11,7 @@ find_path(MYSQL_INCLUDE_DIR mysql.h $ENV{MYSQL_INCLUDE_DIR} $ENV{MYSQL_DIR}/include $ENV{ProgramFiles}/MySQL/*/include + ${BINDIR32}/MySQL/include $ENV{SystemDrive}/MySQL/*/include) if (WIN32) @@ -26,6 +30,7 @@ if (WIN32) $ENV{MYSQL_DIR}/libmysql/${libsuffixBuild} $ENV{MYSQL_DIR}/client/${libsuffixBuild} $ENV{ProgramFiles}/MySQL/*/lib/${libsuffixDist} + ${BINDIR32}/MySQL/lib $ENV{SystemDrive}/MySQL/*/lib/${libsuffixDist}) else (WIN32) find_library(MYSQL_LIB NAMES mysqlclient_r