aboutsummaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorRoland Knall <rknall@gmail.com>2019-07-11 00:25:45 +0200
committerRoland Knall <rknall@gmail.com>2019-07-17 18:25:11 +0000
commit390071ed0bc8aaf378c3468989ccde1c93817542 (patch)
tree2e7abfd67e050a42bdd739a105fdf4032782cf9f /ui
parent0696d9349524ae06d17e774f5590a0b94ebae1c9 (diff)
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>
Diffstat (limited to 'ui')
-rw-r--r--ui/profile.c4
-rw-r--r--ui/qt/CMakeLists.txt4
-rw-r--r--ui/qt/main_status_bar.cpp3
-rw-r--r--ui/qt/models/profile_model.cpp121
-rw-r--r--ui/qt/models/profile_model.h10
-rw-r--r--ui/qt/profile_dialog.cpp38
-rw-r--r--ui/qt/profile_dialog.h7
-rw-r--r--ui/qt/profile_dialog.ui25
-rw-r--r--ui/qt/utils/wireshark_zip_helper.cpp123
-rw-r--r--ui/qt/utils/wireshark_zip_helper.h42
10 files changed, 339 insertions, 38 deletions
diff --git a/ui/profile.c b/ui/profile.c
index 786b6bedcb..6b16e4af4f 100644
--- a/ui/profile.c
+++ b/ui/profile.c
@@ -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
diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt
index 1d1ae00a49..8c7c888898 100644
--- a/ui/qt/CMakeLists.txt
+++ b/ui/qt/CMakeLists.txt
@@ -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
diff --git a/ui/qt/main_status_bar.cpp b/ui/qt/main_status_bar.cpp
index 2bd86d1451..2aac68b053 100644
--- a/ui/qt/main_status_bar.cpp
+++ b/ui/qt/main_status_bar.cpp
@@ -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);
diff --git a/ui/qt/models/profile_model.cpp b/ui/qt/models/profile_model.cpp
index 98b1938b44..64360cbcbf 100644
--- a/ui/qt/models/profile_model.cpp
+++ b/ui/qt/models/profile_model.cpp
@@ -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()
{
- bool refresh = profiles_.count() > 0;
+ emit beginResetModel();
- if ( refresh )
- profiles_.clear();
- else
- init_profile_list();
+ bool refresh = profiles_.count() > 0;
- 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;
diff --git a/ui/qt/models/profile_model.h b/ui/qt/models/profile_model.h
index b49b593377..527101c531 100644
--- a/ui/qt/models/profile_model.h
+++ b/ui/qt/models/profile_model.h
@@ -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
diff --git a/ui/qt/profile_dialog.cpp b/ui/qt/profile_dialog.cpp
index 158b6322b2..6bf2e689bc 100644
--- a/ui/qt/profile_dialog.cpp
+++ b/ui/qt/profile_dialog.cpp
@@ -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
*
diff --git a/ui/qt/profile_dialog.h b/ui/qt/profile_dialog.h
index 407ad910e0..05bc708beb 100644
--- a/ui/qt/profile_dialog.h
+++ b/ui/qt/profile_dialog.h
@@ -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();
diff --git a/ui/qt/profile_dialog.ui b/ui/qt/profile_dialog.ui
index 0a4f14716d..63da77d532 100644
--- a/ui/qt/profile_dialog.ui
+++ b/ui/qt/profile_dialog.ui
@@ -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>
@@ -127,11 +115,6 @@
</widget>
<customwidgets>
<customwidget>
- <class>ElidedLabel</class>
- <extends>QLabel</extends>
- <header>widgets/elided_label.h</header>
- </customwidget>
- <customwidget>
<class>StockIconToolButton</class>
<extends>QToolButton</extends>
<header>widgets/stock_icon_tool_button.h</header>
diff --git a/ui/qt/utils/wireshark_zip_helper.cpp b/ui/qt/utils/wireshark_zip_helper.cpp
new file mode 100644
index 0000000000..78dc9949fe
--- /dev/null
+++ b/ui/qt/utils/wireshark_zip_helper.cpp
@@ -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:
+ */
diff --git a/ui/qt/utils/wireshark_zip_helper.h b/ui/qt/utils/wireshark_zip_helper.h
new file mode 100644
index 0000000000..8b232dc966
--- /dev/null
+++ b/ui/qt/utils/wireshark_zip_helper.h
@@ -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:
+ */