Qt: Import Profile information

Allow easy import of profiles. Profiles must be stored inside
a zip file, with no additional hierarchy.

Change-Id: I0ae77460c20ef6b3e447906e671b0cefa6b9b032
Reviewed-on: https://code.wireshark.org/review/33881
Petri-Dish: Roland Knall <rknall@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Roland Knall <rknall@gmail.com>
This commit is contained in:
Roland Knall 2019-07-11 00:25:45 +02:00
parent 0696d93495
commit 390071ed0b
19 changed files with 422 additions and 41 deletions

View File

@ -1126,6 +1126,9 @@ ws_find_package(CARES ENABLE_CARES HAVE_C_ARES "1.5.0")
# Zlib compression
ws_find_package(ZLIB ENABLE_ZLIB HAVE_ZLIB)
# Minizip compression
ws_find_package(Minizip ENABLE_MINIZIP HAVE_MINIZIP)
# Brotli compression
ws_find_package(BROTLI ENABLE_BROTLI HAVE_BROTLI)
@ -1173,6 +1176,15 @@ if(NOT WIN32)
find_package(SETCAP)
endif()
# Include minizip include directories
if(MINIZIP_FOUND)
include_directories(
${MINIZIP_INCLUDE_DIRS}
)
else()
set(MINIZIP_LIBRARY "")
endif()
# Windows version updates
ws_find_package(WINSPARKLE ENABLE_WINSPARKLE HAVE_SOFTWARE_UPDATE)
@ -1608,6 +1620,11 @@ set_package_properties(SpeexDSP PROPERTIES
DESCRIPTION "SpeexDSP is a patent-free, Open Source/Free Software DSP library"
PURPOSE "RTP audio resampling"
)
set_package_properties(Minizip PROPERTIES
URL "https://www.winimage.com/zLibDll/minizip.html"
DESCRIPTION "C library for supporting zip/unzip functionality"
PURPOSE "Support for profiles import/export"
)
string(TOUPPER "${CMAKE_BUILD_TYPE}" _build_type)
message(STATUS "C-Flags: ${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${_build_type}}")
@ -2232,6 +2249,7 @@ if(BUILD_wireshark AND QT_FOUND)
${WINSPARKLE_LIBRARIES}
$<$<BOOL:${WIN32}>:UxTheme.lib>
${SPEEXDSP_LIBRARIES}
${MINIZIP_LIBRARIES}
)
add_executable(wireshark WIN32 MACOSX_BUNDLE ${wireshark_FILES} ${EXTRA_BUNDLE_FILES})

View File

@ -65,6 +65,7 @@ option(ENABLE_PLUGIN_IFDEMO "Build with plugin interface demo" OFF)
option(ENABLE_PCAP_NG_DEFAULT "Enable pcapng as default file format" ON)
option(ENABLE_ZLIB "Build with zlib compression support" ON)
option(ENABLE_MINIZIP "Build with zip file compression support" ON)
option(ENABLE_LZ4 "Build with LZ4 compression support" ON)
option(ENABLE_BROTLI "Build with brotli compression support" ON)
option(ENABLE_SNAPPY "Build with Snappy compression support" ON)

View File

@ -0,0 +1,52 @@
#
# - Find minizip libraries
#
# MINIZIP_INCLUDE_DIRS - where to find minizip headers.
# MINIZIP_LIBRARIES - List of libraries when using minizip.
# MINIZIP_FOUND - True if minizip is found.
FindWSWinLibs( "minizip-*" "MINIZIP_HINTS" )
if(NOT WIN32)
find_package(PkgConfig QUIET)
pkg_search_module(MINIZIP QUIET minizip)
endif()
find_path(MINIZIP_INCLUDE_DIR
NAMES
unzip.h
minizip/unzip.h
HINTS
${MINIZIP_INCLUDE_DIRS}
"${MINIZIP_HINTS}/include"
)
get_filename_component(MINIZIP_PARENT_DIR ${MINIZIP_INCLUDE_DIR} DIRECTORY)
if(EXISTS "${MINIZIP_PARENT_DIR}/minizip/unzip.h")
set(MINIZIP_INCLUDE_DIR "${MINIZIP_PARENT_DIR}")
endif()
find_library(MINIZIP_LIBRARY
NAMES
minizip
HINTS
${MINIZIP_LIBRARY_DIRS}
"${MINIZIP_HINTS}/lib"
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(MINIZIP
REQUIRED_VARS MINIZIP_LIBRARY MINIZIP_INCLUDE_DIR
VERSION_VAR MINIZIP_VERSION)
if(MINIZIP_FOUND)
set(MINIZIP_LIBRARIES ${MINIZIP_LIBRARY})
set(MINIZIP_INCLUDE_DIRS ${MINIZIP_INCLUDE_DIR})
SET(HAVE_MINIZIP ON)
else()
set(MINIZIP_LIBRARIES)
set(MINIZIP_INCLUDE_DIRS)
endif()
mark_as_advanced(MINIZIP_LIBRARIES MINIZIP_INCLUDE_DIRS)

View File

@ -136,6 +136,9 @@
/* Define to use zlib library */
#cmakedefine HAVE_ZLIB 1
/* Define to use the minizip library */
#cmakedefine HAVE_MINIZIP 1
/* Define to use brotli library */
#cmakedefine HAVE_BROTLI 1

View File

@ -74,6 +74,7 @@ ADDITIONAL_LIST="
lua5.2-dev \
libnl3-dev \
sbc-dev \
minizip-dev \
speexdsp-dev \
"

View File

@ -78,6 +78,7 @@ ADDITIONAL_LIST="libnl-3-dev \
libsnappy-dev \
libspandsp-dev \
libxml2-dev \
libminizip-dev \
git \
ninja-build \
doxygen \

View File

@ -13,7 +13,7 @@
brew update
#install some libs needed by Wireshark
brew install c-ares glib libgcrypt gnutls lua@5.1 cmake python nghttp2 snappy lz4 libxml2 ninja libmaxminddb doxygen libsmi spandsp brotli
brew install c-ares glib libgcrypt gnutls lua@5.1 cmake python nghttp2 snappy lz4 libxml2 ninja libmaxminddb doxygen libsmi spandsp brotli minizip
#install Qt5
brew install qt5

View File

@ -59,6 +59,7 @@ ADDITIONAL_LIST="libnl3-devel \
sbc-devel \
libsmi-devel \
snappy-devel \
minizip-devel \
lz4 \
doxygen \
libxml2-devel \

View File

@ -69,8 +69,8 @@ Param(
# trouble instead of trying to catch exceptions everywhere.
$ErrorActionPreference = "Stop"
$Win64CurrentTag = "2019-07-03"
$Win32CurrentTag = "2019-07-03"
$Win64CurrentTag = "2019-07-17"
$Win32CurrentTag = "2019-07-17"
# Archive file / SHA256
$Win64Archives = @{
@ -86,6 +86,7 @@ $Win64Archives = @{
"lua-5.2.4-unicode-win64-vc14.zip" = "e8968d2c7871ce1ea82cbd29ac1b3a2c59d3dec25e483c5e12de85df66f5d928";
"lz4-1.8.3-win64ws.zip" = "2634ed7c132f50e8cf6dc25e9f1b6f2a3b3e4980b812cada7ef42b20fc1fba17";
"MaxMindDB-1.3.2-win64ws.zip" = "9025c43e9b21ff0bfbaf206b8ed96e2920ef1434107f789e4c7c0c1d8b508952";
"minizip-1.2.11-4-win64ws.zip" = "dd6bf24e2d946465ad19aa4f8c38e0db91da6585887935de68011982cd6fb2cb";
"nghttp2-1.14.0-1-win64ws.zip" = "a4f15854f30b4fbb65cbf150011612e4580683dc9bbb339c632c37e414c938cb";
"sbc-1.3-1-win64ws.zip" = "08cef6898c421277a6582ef3225d8820f74a037cbd5b6e673a4d8f4593ce80a1";
"snappy-1.1.3-1-win64ws.zip" = "692a15e70f2cdeca621988a46e936d3651e7feb5176981f2656a5e913c394bcc";
@ -108,6 +109,7 @@ $Win32Archives = @{
"lua-5.2.4-unicode-win32-vc14.zip" = "ca2368a83f623674178e9441f71fb791e3c0b46f208e3dac28c6ac735f034bff";
"lz4-1.8.3-win32ws.zip" = "6f77128f901d480ee0b82ab4fe5956e0f02fdcb2198d6d349e0b2fa1ac77c805";
"MaxMindDB-1.3.2-win32ws.zip" = "5c8b4bf3092da8fad6edb005a5283c6a74b7e115a50da010953eed77d33c11b7";
"minizip-1.2.11-4-win32ws.zip" = "41e113930902c2519c4644e8307a0cc51c5855e001e1e69768c48deb376142d0";
"nghttp2-1.14.0-1-win32ws.zip" = "939ec18c81fed2e44270dc924fad8beffe90a74300cc98360442300fb0a5c292";
"sbc-1.3-1-win32ws.zip" = "ad37825e9ace4b849a5442c08f1ed7e30634e6b774bba4307fb86f35f82e71ba";
"snappy-1.1.3-1-win32ws.zip" = "2508ef7c5d27655c356d7b86a00ac887fc178eab5df63595b8793953dae5c379";
@ -167,6 +169,7 @@ $CleanupItems = @(
"lua-5.?.?-unicode-win??-vc??"
"lz4-*-win??ws"
"MaxMindDB-1.3.2-win??ws"
"minizip-*-win??ws"
"nghttp2-*-win??ws"
"portaudio_v19"
"portaudio_v19_2"

View File

@ -262,6 +262,8 @@ empty_profile_list(gboolean edit_list)
}
g_assert(g_list_length(*flpp) == 0);
if ( ! edited_profiles )
edited_profiles = NULL;
}
flpp = &current_profiles;
@ -271,6 +273,8 @@ empty_profile_list(gboolean edit_list)
}
g_assert(g_list_length(*flpp) == 0);
if ( ! current_profiles )
current_profiles = NULL;
}
void

View File

@ -63,6 +63,7 @@ set(WIRESHARK_UTILS_HEADERS
utils/tango_colors.h
utils/variant_pointer.h
utils/wireshark_mime_data.h
utils/wireshark_zip_helper.h
)
set(WIRESHARK_MODEL_HEADERS
@ -90,7 +91,7 @@ set(WIRESHARK_MODEL_HEADERS
models/percent_bar_delegate.h
models/pref_delegate.h
models/pref_models.h
models/profile_model.h
models/profile_model.h
models/proto_tree_model.h
models/related_packet_delegate.h
models/sparkline_delegate.h
@ -288,6 +289,7 @@ set(WIRESHARK_UTILS_SRCS
utils/qt_ui_utils.cpp
utils/stock_icon.cpp
utils/wireshark_mime_data.cpp
utils/wireshark_zip_helper.cpp
)
set(WIRESHARK_MODEL_SRCS

View File

@ -591,6 +591,9 @@ void MainStatusBar::showProfileMenu(const QPoint &global_pos, Qt::MouseButton bu
QAction * action = ctx_menu_.addAction(tr("Manage Profiles" UTF8_HORIZONTAL_ELLIPSIS));
action->setProperty("dialog_action_", (int)ProfileDialog::ShowProfiles);
connect(action, SIGNAL(triggered()), this, SLOT(manageProfile()));
action = ctx_menu_.addAction(tr("Import" UTF8_HORIZONTAL_ELLIPSIS));
action->setProperty("dialog_action_", (int)ProfileDialog::ImportProfile);
connect(action, SIGNAL(triggered()), this, SLOT(manageProfile()));
ctx_menu_.addSeparator();
action = ctx_menu_.addAction(tr("New" UTF8_HORIZONTAL_ELLIPSIS));
action->setProperty("dialog_action_", (int)ProfileDialog::NewProfile);

View File

@ -7,6 +7,7 @@
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "config.h"
#include "glib.h"
#include "ui/profile.h"
@ -17,9 +18,11 @@
#include <ui/qt/utils/color_utils.h>
#include <ui/qt/utils/qt_ui_utils.h>
#include <ui/qt/utils/wireshark_zip_helper.h>
#include <QDir>
#include <QFont>
#include <QTemporaryDir>
#define gxx_list_next(list) ((list) ? ((reinterpret_cast<GList *>(list))->next) : Q_NULLPTR)
@ -114,14 +117,14 @@ ProfileModel::ProfileModel(QObject * parent) :
void ProfileModel::loadProfiles()
{
emit beginResetModel();
bool refresh = profiles_.count() > 0;
if ( refresh )
profiles_.clear();
else
init_profile_list();
emit beginResetModel();
if ( refresh )
profiles_.clear();
else
init_profile_list();
GList *fl_entry = edited_profile_list();
while (fl_entry && fl_entry->data)
@ -166,6 +169,20 @@ int ProfileModel::columnCount(const QModelIndex &) const
return static_cast<int>(_LAST_ENTRY);
}
profile_def * ProfileModel::guard(int row) const
{
if ( profiles_.count() <= row )
return Q_NULLPTR;
if ( ! edited_profile_list() )
{
static_cast<QList<profile_def *>>(profiles_).clear();
return Q_NULLPTR;
}
return profiles_.at(row);
}
QVariant ProfileModel::data(const QModelIndex &index, int role) const
{
QString msg;
@ -173,7 +190,7 @@ QVariant ProfileModel::data(const QModelIndex &index, int role) const
if ( ! index.isValid() || profiles_.count() <= index.row() )
return QVariant();
profile_def * prof = profiles_.at(index.row());
profile_def * prof = guard(index.row());
if ( ! prof )
return QVariant();
@ -225,7 +242,7 @@ QVariant ProfileModel::data(const QModelIndex &index, int role) const
if ( set_profile_.compare(prof->name) == 0 )
{
profile_def * act = profiles_.at(activeProfile().row());
profile_def * act = guard(activeProfile().row());
if ( act->is_global == prof->is_global )
font.setBold(true);
}
@ -316,7 +333,7 @@ QVariant ProfileModel::data(const QModelIndex &index, int role) const
case ProfileModel::DATA_IS_SELECTED:
{
QModelIndex selected = activeProfile();
profile_def * selprof = profiles_.at(selected.row());
profile_def * selprof = guard(selected.row());
if ( selprof )
{
if ( selprof->is_global != prof->is_global )
@ -388,7 +405,7 @@ Qt::ItemFlags ProfileModel::flags(const QModelIndex &index) const
if ( ! index.isValid() || profiles_.count() <= index.row() )
return fl;
profile_def * prof = profiles_.at(index.row());
profile_def * prof = guard(index.row());
if ( ! prof )
return fl;
@ -419,7 +436,7 @@ QList<int> ProfileModel::findAllByNameAndVisibility(QString name, bool isGlobal)
for ( int cnt = 0; cnt < profiles_.count(); cnt++ )
{
profile_def * prof = profiles_.at(cnt);
profile_def * prof = guard(cnt);
if ( prof && static_cast<bool>(prof->is_global) == isGlobal && name.compare(prof->name) == 0 )
result << cnt;
}
@ -441,7 +458,7 @@ QModelIndex ProfileModel::duplicateEntry(QModelIndex idx)
if ( ! idx.isValid() || profiles_.count() <= idx.row() )
return QModelIndex();
profile_def * prof = profiles_.at(idx.row());
profile_def * prof = guard(idx.row());
if ( ! prof )
return QModelIndex();
@ -476,7 +493,7 @@ void ProfileModel::deleteEntry(QModelIndex idx)
if ( ! idx.isValid() )
return;
profile_def * prof = profiles_.at(idx.row());
profile_def * prof = guard(idx.row());
if ( ! prof )
return;
@ -530,7 +547,7 @@ bool ProfileModel::setData(const QModelIndex &idx, const QVariant &value, int ro
if ( ! value.isValid() || value.toString().isEmpty() )
return false;
profile_def * prof = profiles_.at(idx.row());
profile_def * prof = guard(idx.row());
if ( ! prof || prof->status == PROF_STAT_DEFAULT )
return false;
@ -552,6 +569,82 @@ bool ProfileModel::setData(const QModelIndex &idx, const QVariant &value, int ro
return true;
}
#ifdef HAVE_MINIZIP
/* This check runs BEFORE the file has been unzipped! */
bool ProfileModel::acceptFile(QString fileName, int fileSize)
{
if ( fileName.contains(".") || fileName.startsWith("_") )
return false;
if ( fileSize > 1024 * 512 )
return false;
/* config_file_exists_with_entries cannot be used, due to the fact, that the file has not been extracted yet */
return true;
}
int ProfileModel::unzipProfiles(QString filename)
{
int count = 0;
QDir profileDir(get_profiles_dir());
QTemporaryDir dir;
#if 0
dir.setAutoRemove(false);
#endif
if ( dir.isValid() )
{
WireSharkZipHelper::unzip(filename, dir.path(), &ProfileModel::acceptFile);
QDir temp(dir.path());
temp.setSorting(QDir::Name);
temp.setFilter(QDir::Dirs | QDir::NoSymLinks | QDir::NoDotAndDotDot);
QFileInfoList entries = temp.entryInfoList();
foreach ( QFileInfo fentry, entries )
{
QString profilePath = profileDir.absolutePath() + QDir::separator() + fentry.fileName();
QString tempPath = fentry.absoluteFilePath();
if ( QFile::exists(profilePath) )
continue;
QDir profileDir(profilePath);
if ( ! profileDir.mkpath(profilePath) || ! QFile::exists(tempPath) )
continue;
QDir tempProfile(tempPath);
tempProfile.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
QFileInfoList files = tempProfile.entryInfoList();
if ( files.count() <= 0 )
continue;
int created = 0;
foreach ( QFileInfo finfo, files)
{
QString tempFile = finfo.absoluteFilePath();
QString profileFile = profilePath + QDir::separator() + finfo.fileName();
if ( ! QFile::exists(tempFile) || QFile::exists(profileFile) )
continue;
if ( QFile::copy(tempFile, profileFile) )
created++;
}
if ( created > 0 )
count++;
}
}
if ( count > 0 )
loadProfiles();
return count;
}
#endif
bool ProfileModel::checkNameValidity(QString name, QString *msg)
{
QString message;

View File

@ -10,6 +10,7 @@
#ifndef PROFILE_MODEL_H
#define PROFILE_MODEL_H
#include "config.h"
#include "glib.h"
#include <ui/profile.h>
@ -88,6 +89,10 @@ public:
GList * at(int row) const;
#ifdef HAVE_MINIZIP
int unzipProfiles(QString filename);
#endif
static bool checkNameValidity(QString name, QString *msg = Q_NULLPTR);
QList<int> findAllByNameAndVisibility(QString name, bool isGlobal = false);
@ -97,9 +102,14 @@ private:
bool reset_default_;
void loadProfiles();
profile_def * guard(int row) const;
GList * entry(profile_def *) const;
int findByNameAndVisibility(QString name, bool isGlobal = false);
#ifdef HAVE_MINIZIP
static bool acceptFile(QString fileName, int fileSize);
#endif
};
#endif

View File

@ -25,6 +25,7 @@
#include <ui_profile_dialog.h>
#include "wireshark_application.h"
#include <ui/qt/utils/color_utils.h>
#include <ui/qt/simple_dialog.h>
#include <QBrush>
#include <QDir>
@ -35,6 +36,8 @@
#include <QUrl>
#include <QComboBox>
#include <QLineEdit>
#include <QFileDialog>
#include <QStandardPaths>
ProfileDialog::ProfileDialog(QWidget *parent) :
GeometryStateDialog(parent),
@ -59,7 +62,11 @@ ProfileDialog::ProfileDialog(QWidget *parent) :
pd_ui_->newToolButton->setAttribute(Qt::WA_MacSmallSize, true);
pd_ui_->deleteToolButton->setAttribute(Qt::WA_MacSmallSize, true);
pd_ui_->copyToolButton->setAttribute(Qt::WA_MacSmallSize, true);
pd_ui_->infoLabel->setAttribute(Qt::WA_MacSmallSize, true);
pd_ui_->btnImport->setAttribute(Qt::WA_MacSmallSize, true);
#endif
#ifndef HAVE_MINIZIP
pd_ui_->btnImport->setVisible(false);
#endif
model_ = new ProfileModel(this);
@ -118,6 +125,11 @@ int ProfileDialog::execAction(ProfileDialog::ProfileAction profile_action)
on_newToolButton_clicked();
ret = exec();
break;
case ImportProfile:
#ifdef HAVE_MINIZIP
on_btnImport_clicked();
#endif
break;
case EditCurrentProfile:
item = pd_ui_->profileTreeView->currentIndex();
if (item.isValid()) {
@ -315,6 +327,30 @@ void ProfileDialog::filterChanged(const QString &text)
pd_ui_->profileTreeView->setCurrentIndex(active);
}
#ifdef HAVE_MINIZIP
void ProfileDialog::on_btnImport_clicked()
{
QString docDir = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
QString zipFile = QFileDialog::getOpenFileName(this, tr("Select zip file for import"),
docDir, tr("Zip File (*.zip)"));
QFileInfo fi(zipFile);
if ( ! fi.exists() )
return;
int count = 0;
if ( ( count = model_->unzipProfiles(zipFile) ) == 0 )
{
QString msg = tr("An error occured, while importing profiles from %1").arg(fi.fileName());
QMessageBox::warning(this, tr("Error importing profiles"), msg );
}
else {
QString msg = tr("%1 profiles have been imported").arg(QString::number(count));
QMessageBox::information(this, tr("Importing profiles"), msg );
}
}
#endif
/*
* Editor modelines
*

View File

@ -10,6 +10,8 @@
#ifndef PROFILE_DIALOG_H
#define PROFILE_DIALOG_H
#include "config.h"
#include <ui/qt/geometry_state_dialog.h>
#include <ui/qt/models/profile_model.h>
#include <ui/qt/widgets/profile_tree_view.h>
@ -26,7 +28,7 @@ class ProfileDialog : public GeometryStateDialog
Q_OBJECT
public:
enum ProfileAction { ShowProfiles, NewProfile, EditCurrentProfile, DeleteCurrentProfile };
enum ProfileAction { ShowProfiles, NewProfile, ImportProfile, EditCurrentProfile, DeleteCurrentProfile };
explicit ProfileDialog(QWidget *parent = Q_NULLPTR);
~ProfileDialog();
@ -52,6 +54,9 @@ private:
private slots:
void currentItemChanged();
#ifdef HAVE_MINIZIP
void on_btnImport_clicked();
#endif
void on_newToolButton_clicked();
void on_deleteToolButton_clicked();

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>470</width>
<width>557</width>
<height>386</height>
</rect>
</property>
@ -51,7 +51,7 @@
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0,0,0">
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0,0,0,0,0">
<item>
<widget class="StockIconToolButton" name="newToolButton">
<property name="toolTip">
@ -93,21 +93,9 @@
</spacer>
</item>
<item>
<widget class="ElidedLabel" name="infoLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>1</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<widget class="QPushButton" name="btnImport">
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="openExternalLinks">
<bool>true</bool>
<string>Import</string>
</property>
</widget>
</item>
@ -126,11 +114,6 @@
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ElidedLabel</class>
<extends>QLabel</extends>
<header>widgets/elided_label.h</header>
</customwidget>
<customwidget>
<class>StockIconToolButton</class>
<extends>QToolButton</extends>

View File

@ -0,0 +1,123 @@
/* wireshark_zip_helper.cpp
*
* Definitions for zip / unzip of files
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <ui/qt/utils/wireshark_zip_helper.h>
#ifdef HAVE_MINIZIP
#include "config.h"
#include "glib.h"
#include <iosfwd>
#include <iostream>
#include <minizip/unzip.h>
#include "epan/prefs.h"
#include "wsutil/file_util.h"
#include <QDataStream>
#include <QDir>
#include <QFileInfo>
bool WireSharkZipHelper::unzip(QString zipFile, QString directory, bool (*fileCheck)(QString, int))
{
unzFile uf = Q_NULLPTR;
QFileInfo fi(zipFile);
QDir di(directory);
int files = 0;
if ( ! fi.exists() || ! di.exists() )
return false;
if ( ( uf = unzOpen64(zipFile.toUtf8().constData()) ) == Q_NULLPTR )
return false;
unz_global_info64 gi;
int err = unzGetGlobalInfo64(uf,&gi);
unsigned int nmbr = static_cast<unsigned int>(gi.number_entry);
if (nmbr <= 0)
return false;
for ( unsigned int cnt = 0; cnt < nmbr; cnt++ )
{
char filename_inzip[256];
unz_file_info64 file_info;
err = unzGetCurrentFileInfo64(uf, &file_info, filename_inzip, sizeof(filename_inzip),
Q_NULLPTR, 0, Q_NULLPTR, 0);
if ( err == UNZ_OK )
{
QString fileInZip(filename_inzip);
int fileSize = static_cast<int>(file_info.uncompressed_size);
/* Sanity check for the filenames as well as the file size (max 512kb) */
if ( fileCheck && fileCheck(fileInZip, fileSize) && di.exists() )
{
QFileInfo fi(di.path() + QDir::separator() + fileInZip);
QDir tP(fi.absolutePath());
if ( ! tP.exists() )
di.mkpath(fi.absolutePath());
if ( fileInZip.contains("/") )
{
QString filePath = fi.absoluteFilePath();
err = unzOpenCurrentFile(uf);
if ( err == UNZ_OK )
{
char * buf = static_cast<char *>(malloc(IO_BUF_SIZE));
QFile file(filePath);
if ( file.open(QIODevice::WriteOnly) )
{
QDataStream out(&file);
while ( ( err = unzReadCurrentFile(uf, buf, IO_BUF_SIZE) ) != UNZ_EOF )
{
QByteArray buffer(buf, err);
out << buffer;
}
file.close();
}
unzCloseCurrentFile(uf);
files++;
}
}
}
}
if ((cnt+1) < nmbr)
{
err = unzGoToNextFile(uf);
if (err!=UNZ_OK)
{
break;
}
}
}
unzClose(uf);
return files > 0 ? true : false;
}
#endif
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/

View File

@ -0,0 +1,42 @@
/* wireshark_zip_helper.h
*
* Definitions for zip / unzip of files
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef WS_ZIP_HELPER_H
#define WS_ZIP_HELPER_H
#include "config.h"
#include <QDir>
#ifdef HAVE_MINIZIP
class WireSharkZipHelper
{
public:
static bool unzip(QString zipFile, QString directory, bool (*fileCheck)(QString fileName, int fileSize) );
};
#endif
#endif // WS_ZIP_HELPER_H
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/