diff --git a/plugins/libzipplugin/CMakeLists.txt b/plugins/libzipplugin/CMakeLists.txt --- a/plugins/libzipplugin/CMakeLists.txt +++ b/plugins/libzipplugin/CMakeLists.txt @@ -15,13 +15,19 @@ # double-quotes of the last mime must NOT be escaped. set(SUPPORTED_MIMETYPES "application/zip") +find_package(ZLIB REQUIRED) +set_package_properties(ZLIB PROPERTIES + URL "http://www.zlib.net/" + DESCRIPTION "The Zlib compression library" + PURPOSE "Required for integrity check in libzip plugin") + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/kerfuffle_libzip.json.cmake ${CMAKE_CURRENT_BINARY_DIR}/kerfuffle_libzip.json) kerfuffle_add_plugin(kerfuffle_libzip ${kerfuffle_libzip_SRCS}) -target_link_libraries(kerfuffle_libzip KF5::KIOCore ${LibZip_LIBRARIES}) +target_link_libraries(kerfuffle_libzip KF5::KIOCore ${LibZip_LIBRARIES} ${ZLIB_LIBRARIES}) set(INSTALLED_LIBZIP_PLUGINS "${INSTALLED_LIBZIP_PLUGINS}kerfuffle_libzip;") diff --git a/plugins/libzipplugin/libzipplugin.cpp b/plugins/libzipplugin/libzipplugin.cpp --- a/plugins/libzipplugin/libzipplugin.cpp +++ b/plugins/libzipplugin/libzipplugin.cpp @@ -39,6 +39,7 @@ #include #include +#include K_PLUGIN_FACTORY_WITH_JSON(LibZipPluginFactory, "kerfuffle_libzip.json", registerPlugin();) @@ -423,6 +424,33 @@ qCCritical(ARK) << "Failed to open archive:" << zip_error_strerror(&err); return false; } + + // Check CRC-32 for each archive entry. + const int nofEntries = zip_get_num_entries(archive, 0); + for (int i = 0; i < nofEntries; i++) { + + // Get statistic for entry. Used to get entry size. + zip_stat_t sb; + if (zip_stat_index(archive, i, 0, &sb) != 0) { + qCCritical(ARK) << "Failed to read stat for" << sb.name; + return false; + } + + zip_file *zf = zip_fopen_index(archive, i, 0); + QScopedPointer buf(new uchar[sb.size]); + const int len = zip_fread(zf, buf.data(), sb.size); + if (len == -1 || uint(len) != sb.size) { + qCCritical(ARK) << "Failed to read data for" << sb.name; + return false; + } + if (sb.crc != crc32(0, &buf.data()[0], len)) { + qCCritical(ARK) << "CRC check failed for" << sb.name; + return false; + } + + emit progress(float(i) / nofEntries); + } + zip_close(archive); emit testSuccess();