aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRoland Knall <rknall@gmail.com>2019-08-29 17:30:29 +0200
committerAnders Broman <a.broman58@gmail.com>2019-09-01 09:02:51 +0000
commit743f8598cd0b156c195b906400cdd0d3fcdeafe3 (patch)
tree7d99b7d258fda9ef9a4e14eb021eb38ade38720a
parentb28952afd401926849a03b9537d08a989284bc25 (diff)
Qt: Rework Resolved Addresses dialog
This is a refactoring/redesign of the "Resolved Addresses" dialog, allowing for sorting/filtering and searching within the addresses and ports. Change-Id: I5071e92ff699323b6c93fc533eeaf92e0db334de Reviewed-on: https://code.wireshark.org/review/34398 Reviewed-by: Roland Knall <rknall@gmail.com> Petri-Dish: Roland Knall <rknall@gmail.com> Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman <a.broman58@gmail.com>
-rw-r--r--ui/qt/CMakeLists.txt2
-rw-r--r--ui/qt/models/astringlist_list_model.cpp114
-rw-r--r--ui/qt/models/astringlist_list_model.h19
-rw-r--r--ui/qt/models/resolved_addresses_models.cpp253
-rw-r--r--ui/qt/models/resolved_addresses_models.h61
-rw-r--r--ui/qt/resolved_addresses_dialog.cpp426
-rw-r--r--ui/qt/resolved_addresses_dialog.h33
-rw-r--r--ui/qt/resolved_addresses_dialog.ui91
8 files changed, 609 insertions, 390 deletions
diff --git a/ui/qt/CMakeLists.txt b/ui/qt/CMakeLists.txt
index ea68c240b8..fe29e9bcd0 100644
--- a/ui/qt/CMakeLists.txt
+++ b/ui/qt/CMakeLists.txt
@@ -94,6 +94,7 @@ set(WIRESHARK_MODEL_HEADERS
models/profile_model.h
models/proto_tree_model.h
models/related_packet_delegate.h
+ models/resolved_addresses_models.h
models/sparkline_delegate.h
models/supported_protocols_model.h
models/timeline_delegate.h
@@ -320,6 +321,7 @@ set(WIRESHARK_MODEL_SRCS
models/profile_model.cpp
models/proto_tree_model.cpp
models/related_packet_delegate.cpp
+ models/resolved_addresses_models.cpp
models/sparkline_delegate.cpp
models/supported_protocols_model.cpp
models/timeline_delegate.cpp
diff --git a/ui/qt/models/astringlist_list_model.cpp b/ui/qt/models/astringlist_list_model.cpp
index 2e6ef7cde9..04ea879b99 100644
--- a/ui/qt/models/astringlist_list_model.cpp
+++ b/ui/qt/models/astringlist_list_model.cpp
@@ -87,13 +87,21 @@ AStringListListSortFilterProxyModel::AStringListListSortFilterProxyModel(QObject
: QSortFilterProxyModel(parent)
{
filter_ = QString();
- type_ = FilterByContains;
+ types_[-1] = FilterByContains;
}
bool AStringListListSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
{
- QString leftData = sourceModel()->data(left).toStringList().join(",");
- QString rightData = sourceModel()->data(right).toStringList().join(",");
+ QString leftData = left.data().toString();
+ QString rightData = right.data().toString();
+
+ if ( numericColumns_.contains(left.column()) || numericColumns_.contains(right.column() ) )
+ {
+ float left = leftData.toFloat();
+ float right = rightData.toFloat();
+
+ return left < right;
+ }
return leftData.compare(rightData, sortCaseSensitivity()) < 0;
}
@@ -104,14 +112,23 @@ void AStringListListSortFilterProxyModel::setFilter(const QString & filter)
invalidateFilter();
}
-static bool AContainsB(const QString &a, const QString &b, Qt::CaseSensitivity cs)
+static bool AContainsB(const QVariant &a, const QVariant &b, Qt::CaseSensitivity cs)
{
- return a.contains(b, cs);
+ if ( ! a.canConvert(QVariant::String) || ! b.canConvert(QVariant::String) )
+ return false;
+ return a.toString().contains(b.toString(), cs);
}
-static bool AStartsWithB(const QString &a, const QString &b, Qt::CaseSensitivity cs)
+static bool AStartsWithB(const QVariant &a, const QVariant &b, Qt::CaseSensitivity cs)
{
- return a.startsWith(b, cs);
+ if ( ! a.canConvert(QVariant::String) || ! b.canConvert(QVariant::String) )
+ return false;
+ return a.toString().startsWith(b.toString(), cs);
+}
+
+static bool AIsEquivalentToB(const QVariant &a, const QVariant &b, Qt::CaseSensitivity)
+{
+ return a == b;
}
bool AStringListListSortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
@@ -125,12 +142,28 @@ bool AStringListListSortFilterProxyModel::filterAcceptsRow(int sourceRow, const
continue;
QModelIndex chkIdx = sourceModel()->index(sourceRow, column, sourceParent);
- QString dataString = sourceModel()->data(chkIdx).toString();
+ QString dataString = chkIdx.data().toString();
/* Default is filter by string a contains string b */
- bool (*compareFunc)(const QString&, const QString&, Qt::CaseSensitivity) = AContainsB;
- if ( type_ == FilterByStart )
- compareFunc = AStartsWithB;
+ bool (*compareFunc)(const QVariant&, const QVariant&, Qt::CaseSensitivity) = AContainsB;
+ if ( types_.keys().contains(column) )
+ {
+ switch (types_.value(column, FilterByContains))
+ {
+ case FilterByStart:
+ compareFunc = AStartsWithB;
+ break;
+ case FilterByEquivalent:
+ compareFunc = AIsEquivalentToB;
+ break;
+ case FilterNone:
+ return true;
+ break;
+ default:
+ compareFunc = AContainsB;
+ break;
+ }
+ }
if ( compareFunc(dataString, filter_, filterCaseSensitivity()) )
return true;
@@ -139,12 +172,20 @@ bool AStringListListSortFilterProxyModel::filterAcceptsRow(int sourceRow, const
return false;
}
-void AStringListListSortFilterProxyModel::setFilterType(AStringListListFilterType type)
+void AStringListListSortFilterProxyModel::setFilterType(AStringListListFilterType type, int column)
{
- if ( type != type_ )
+ if ( column >= -1 && column < columnCount() )
{
- type_ = type;
- invalidateFilter();
+ if ( ! types_.keys().contains(column) )
+ {
+ types_.insert(column, type);
+ invalidateFilter();
+ }
+ else if ( types_.keys().contains(column) && type != types_[column] )
+ {
+ types_[column] = type;
+ invalidateFilter();
+ }
}
}
@@ -163,6 +204,49 @@ void AStringListListSortFilterProxyModel::clearColumnsToFilter()
invalidateFilter();
}
+void AStringListListSortFilterProxyModel::clearHiddenColumns()
+{
+ hiddenColumns_.clear();
+ invalidateFilter();
+}
+
+void AStringListListSortFilterProxyModel::setColumnToHide(int col)
+{
+ if ( ! hiddenColumns_.contains(col) && col > -1 && sourceModel() && sourceModel()->columnCount() > col )
+ {
+ hiddenColumns_ << col;
+ invalidateFilter();
+ }
+}
+
+bool AStringListListSortFilterProxyModel::filterAcceptsColumn(int sourceColumn, const QModelIndex &sourceParent) const
+{
+ QModelIndex realIndex = sourceModel()->index(0, sourceColumn, sourceParent);
+
+ if ( ! realIndex.isValid() )
+ return false;
+
+ if ( hiddenColumns_.contains(sourceColumn) )
+ return false;
+
+ return true;
+}
+
+void AStringListListSortFilterProxyModel::clearNumericColumns()
+{
+ numericColumns_.clear();
+ invalidateFilter();
+}
+
+void AStringListListSortFilterProxyModel::setColumnAsNumeric(int col)
+{
+ if ( ! numericColumns_.contains(col) && col > -1 && sourceModel() && sourceModel()->columnCount() > col )
+ {
+ numericColumns_ << col;
+ invalidateFilter();
+ }
+}
+
AStringListListUrlProxyModel::AStringListListUrlProxyModel(QObject * parent):
QIdentityProxyModel(parent)
{}
diff --git a/ui/qt/models/astringlist_list_model.h b/ui/qt/models/astringlist_list_model.h
index 516540b36b..d21fe31a5a 100644
--- a/ui/qt/models/astringlist_list_model.h
+++ b/ui/qt/models/astringlist_list_model.h
@@ -50,27 +50,38 @@ public:
enum AStringListListFilterType
{
FilterByContains = 0,
- FilterByStart = 1
+ FilterByStart,
+ FilterByEquivalent,
+ FilterNone
};
+ Q_ENUM(AStringListListFilterType)
explicit AStringListListSortFilterProxyModel(QObject * parent = Q_NULLPTR);
virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const;
virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
+ virtual bool filterAcceptsColumn(int column, const QModelIndex &sourceParent) const;
- void setFilterType(AStringListListFilterType type);
+ void setFilterType(AStringListListFilterType type, int column = -1);
void setColumnToFilter(int);
void clearColumnsToFilter();
+ void clearHiddenColumns();
+ void setColumnToHide(int col);
+
+ void clearNumericColumns();
+ void setColumnAsNumeric(int col);
+
public slots:
void setFilter(const QString&);
private:
-
QString filter_;
- AStringListListFilterType type_;
+ QMap<int, AStringListListFilterType> types_;
QList<int> columnsToFilter_;
+ QList<int> hiddenColumns_;
+ QList<int> numericColumns_;
};
class AStringListListUrlProxyModel : public QIdentityProxyModel
diff --git a/ui/qt/models/resolved_addresses_models.cpp b/ui/qt/models/resolved_addresses_models.cpp
new file mode 100644
index 0000000000..a802991118
--- /dev/null
+++ b/ui/qt/models/resolved_addresses_models.cpp
@@ -0,0 +1,253 @@
+/* resolved_addresses_models.cpp
+ *
+ * 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/models/resolved_addresses_models.h>
+
+#include <glib.h>
+
+#include "file.h"
+
+#include "epan/addr_resolv.h"
+#include <wiretap/wtap.h>
+
+extern "C"
+{
+
+static void
+serv_port_hash_to_qstringlist(gpointer key, gpointer value, gpointer sl_ptr)
+{
+ QStringList *string_list = (QStringList *) sl_ptr;
+ serv_port_t *serv_port = (serv_port_t *)value;
+ guint port = GPOINTER_TO_UINT(key);
+
+ QStringList entries;
+
+ if (serv_port->tcp_name) entries << QString("%1 %2 tcp").arg(serv_port->tcp_name).arg(port);
+ if (serv_port->udp_name) entries << QString("%1 %2 udp").arg(serv_port->udp_name).arg(port);
+ if (serv_port->sctp_name) entries << QString("%1 %2 sctp").arg(serv_port->sctp_name).arg(port);
+ if (serv_port->dccp_name) entries << QString("%1 %2 dccp").arg(serv_port->dccp_name).arg(port);
+
+ if (!entries.isEmpty()) *string_list << entries.join("\n");
+}
+
+static void
+ipv4_hash_table_resolved_to_qstringlist(gpointer, gpointer value, gpointer sl_ptr)
+{
+ QStringList *string_list = (QStringList *) sl_ptr;
+ hashipv4_t *ipv4_hash_table_entry = (hashipv4_t *) value;
+
+ if((ipv4_hash_table_entry->flags & NAME_RESOLVED)) {
+ QString entry = QString("%1\t%2")
+ .arg(ipv4_hash_table_entry->ip)
+ .arg(ipv4_hash_table_entry->name);
+ *string_list << entry;
+ }
+}
+
+static void
+ipv6_hash_table_resolved_to_qstringlist(gpointer, gpointer value, gpointer sl_ptr)
+{
+ QStringList *string_list = (QStringList *) sl_ptr;
+ hashipv6_t *ipv6_hash_table_entry = (hashipv6_t *) value;
+
+ if((ipv6_hash_table_entry->flags & NAME_RESOLVED)) {
+ QString entry = QString("%1\t%2")
+ .arg(ipv6_hash_table_entry->ip6)
+ .arg(ipv6_hash_table_entry->name);
+ *string_list << entry;
+ }
+}
+
+static void
+ipv4_hash_table_to_qstringlist(gpointer key, gpointer value, gpointer sl_ptr)
+{
+ QStringList *string_list = (QStringList *) sl_ptr;
+ hashipv4_t *ipv4_hash_table_entry = (hashipv4_t *)value;
+ guint addr = GPOINTER_TO_UINT(key);
+
+ QString entry = QString("Key: 0x%1 IPv4: %2, Name: %3")
+ .arg(QString::number(addr, 16))
+ .arg(ipv4_hash_table_entry->ip)
+ .arg(ipv4_hash_table_entry->name);
+
+ *string_list << entry;
+}
+
+static void
+ipv6_hash_table_to_qstringlist(gpointer key, gpointer value, gpointer sl_ptr)
+{
+ QStringList *string_list = (QStringList *) sl_ptr;
+ hashipv6_t *ipv6_hash_table_entry = (hashipv6_t *)value;
+ guint addr = GPOINTER_TO_UINT(key);
+
+ QString entry = QString("Key: 0x%1 IPv4: %2, Name: %3")
+ .arg(QString::number(addr, 16))
+ .arg(ipv6_hash_table_entry->ip6)
+ .arg(ipv6_hash_table_entry->name);
+
+ *string_list << entry;
+}
+
+static void
+eth_hash_to_qstringlist(gpointer, gpointer value, gpointer sl_ptr)
+{
+ QStringList *string_list = (QStringList *) sl_ptr;
+ hashether_t* tp = (hashether_t*)value;
+
+ QString entry = QString("%1 %2")
+ .arg(get_hash_ether_hexaddr(tp))
+ .arg(get_hash_ether_resolved_name(tp));
+
+ *string_list << entry;
+}
+
+static void
+manuf_hash_to_qstringlist(gpointer key, gpointer value, gpointer sl_ptr)
+{
+ QStringList *string_list = (QStringList *) sl_ptr;
+ hashmanuf_t *manuf = (hashmanuf_t*)value;
+ guint eth_as_guint = GPOINTER_TO_UINT(key);
+
+ QString entry = QString("%1:%2:%3 %4")
+ .arg((eth_as_guint >> 16 & 0xff), 2, 16, QChar('0'))
+ .arg((eth_as_guint >> 8 & 0xff), 2, 16, QChar('0'))
+ .arg((eth_as_guint & 0xff), 2, 16, QChar('0'))
+ .arg(get_hash_manuf_resolved_name(manuf));
+
+ *string_list << entry;
+}
+
+static void
+wka_hash_to_qstringlist(gpointer key, gpointer value, gpointer sl_ptr)
+{
+ QStringList *string_list = (QStringList *) sl_ptr;
+ gchar *name = (gchar *)value;
+ guint8 *eth_addr = (guint8*)key;
+
+ QString entry = QString("%1:%2:%3:%4:%5:%6 %7")
+ .arg(eth_addr[0], 2, 16, QChar('0'))
+ .arg(eth_addr[1], 2, 16, QChar('0'))
+ .arg(eth_addr[2], 2, 16, QChar('0'))
+ .arg(eth_addr[3], 2, 16, QChar('0'))
+ .arg(eth_addr[4], 2, 16, QChar('0'))
+ .arg(eth_addr[5], 2, 16, QChar('0'))
+ .arg(name);
+
+ *string_list << entry;
+}
+
+}
+
+EthernetAddressModel::EthernetAddressModel(QObject * parent):
+ AStringListListModel(parent)
+{
+ populate();
+}
+
+QStringList EthernetAddressModel::headerColumns() const
+{
+ return QStringList() << tr("Type") << tr("Mac Address") << tr("Name");
+}
+
+QStringList EthernetAddressModel::filterValues() const
+{
+ return QStringList()
+ << tr("All entries")
+ << tr("IPv4 Hosts") << tr("IPv4 Hash Table")
+ << tr("IPv6 Hosts") << tr("IPv6 Hash Table")
+ << tr("Ethernet Addresses") << tr("Ethernet Manufacturers")
+ << tr("Ethernet Well-Known Addresses");
+}
+
+void EthernetAddressModel::populate()
+{
+ QStringList values;
+ wmem_map_t *ipv4_hash_table = get_ipv4_hash_table();
+ if (ipv4_hash_table) {
+ wmem_map_foreach(ipv4_hash_table, ipv4_hash_table_resolved_to_qstringlist, &values);
+ foreach(QString line, values)
+ appendRow(QStringList() << tr("IPv4 Hosts") << line.split(" "));
+ wmem_map_foreach(ipv4_hash_table, ipv4_hash_table_to_qstringlist, &values);
+ foreach(QString line, values)
+ appendRow(QStringList() << tr("IPv4 Hash Table") << line.split(" "));
+ }
+
+ wmem_map_t *ipv6_hash_table = get_ipv6_hash_table();
+ if (ipv6_hash_table) {
+ wmem_map_foreach(ipv6_hash_table, ipv6_hash_table_resolved_to_qstringlist, &values);
+ foreach(QString line, values)
+ appendRow(QStringList() << tr("IPv6 Hosts") << line.split(" "));
+ wmem_map_foreach(ipv6_hash_table, ipv6_hash_table_to_qstringlist, &values);
+ foreach(QString line, values)
+ appendRow(QStringList() << tr("IPv6 Hash Table") << line.split(" "));
+ }
+
+ wmem_map_t *eth_hashtable = get_eth_hashtable();
+ if (eth_hashtable)
+ wmem_map_foreach(eth_hashtable, eth_hash_to_qstringlist, &values);
+ foreach(QString line, values)
+ appendRow(QStringList() << tr("Ethernet Addresses") << line.split(" "));
+
+ eth_hashtable = get_manuf_hashtable();
+ if (eth_hashtable)
+ wmem_map_foreach(eth_hashtable, manuf_hash_to_qstringlist, &values);
+
+ foreach(QString line, values)
+ appendRow(QStringList() << tr("Ethernet Manufacturers") << line.split(" "));
+
+ eth_hashtable = get_wka_hashtable();
+ if (eth_hashtable)
+ wmem_map_foreach(eth_hashtable, wka_hash_to_qstringlist, &values);
+
+ foreach(QString line, values)
+ appendRow(QStringList() << tr("Ethernet Well-Known Addresses") << line.split(" "));
+}
+
+PortsModel::PortsModel(QObject * parent):
+ AStringListListModel(parent)
+{
+ populate();
+}
+
+QStringList PortsModel::filterValues() const
+{
+ return QStringList()
+ << tr("All entries") << tr("tcp") << tr("udp") << tr("sctp") << tr("dccp");
+}
+
+QStringList PortsModel::headerColumns() const
+{
+ return QStringList() << tr("Name") << tr("Port") << tr("Type");
+}
+
+void PortsModel::populate()
+{
+ QStringList values;
+
+ wmem_map_t *serv_port_hashtable = get_serv_port_hashtable();
+ if(serv_port_hashtable){
+ wmem_map_foreach(serv_port_hashtable, serv_port_hash_to_qstringlist, &values);
+ }
+
+ foreach(QString line, values)
+ appendRow(QStringList() << line.split(" "));
+}
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/ui/qt/models/resolved_addresses_models.h b/ui/qt/models/resolved_addresses_models.h
new file mode 100644
index 0000000000..852d371e48
--- /dev/null
+++ b/ui/qt/models/resolved_addresses_models.h
@@ -0,0 +1,61 @@
+/* resolved_addresses_models.h
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef RESOLVED_ADDRESSES_MODELS_H
+#define RESOLVED_ADDRESSES_MODELS_H
+
+#include <ui/qt/models/astringlist_list_model.h>
+
+#include <QAbstractListModel>
+#include <QSortFilterProxyModel>
+
+class EthernetAddressModel : public AStringListListModel
+{
+ Q_OBJECT
+
+public:
+ EthernetAddressModel(QObject * parent = Q_NULLPTR);
+
+ QStringList filterValues() const;
+
+protected:
+ QStringList headerColumns() const override;
+ void populate();
+
+};
+
+class PortsModel : public AStringListListModel
+{
+ Q_OBJECT
+
+public:
+ PortsModel(QObject * parent = Q_NULLPTR);
+
+ QStringList filterValues() const;
+
+protected:
+ QStringList headerColumns() const override;
+ void populate();
+
+};
+
+#endif // RESOLVED_ADDRESSES_MODELS_H
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */
diff --git a/ui/qt/resolved_addresses_dialog.cpp b/ui/qt/resolved_addresses_dialog.cpp
index 6ac7c17965..c6c669cccc 100644
--- a/ui/qt/resolved_addresses_dialog.cpp
+++ b/ui/qt/resolved_addresses_dialog.cpp
@@ -22,150 +22,23 @@
#include <QMenu>
#include <QPushButton>
#include <QTextCursor>
+#include <QSortFilterProxyModel>
#include "capture_file.h"
#include "wireshark_application.h"
-// To do:
-// - We do a *lot* of string copying.
-// - We end up with a lot of numeric entries here.
+#include <ui/qt/models/astringlist_list_model.h>
+#include <ui/qt/models/resolved_addresses_models.h>
-extern "C" {
-
-static void
-ipv4_hash_table_resolved_to_qstringlist(gpointer, gpointer value, gpointer sl_ptr)
-{
- QStringList *string_list = (QStringList *) sl_ptr;
- hashipv4_t *ipv4_hash_table_entry = (hashipv4_t *) value;
-
- if((ipv4_hash_table_entry->flags & NAME_RESOLVED)) {
- QString entry = QString("%1\t%2")
- .arg(ipv4_hash_table_entry->ip)
- .arg(ipv4_hash_table_entry->name);
- *string_list << entry;
- }
-}
-
-static void
-ipv6_hash_table_resolved_to_qstringlist(gpointer, gpointer value, gpointer sl_ptr)
-{
- QStringList *string_list = (QStringList *) sl_ptr;
- hashipv6_t *ipv6_hash_table_entry = (hashipv6_t *) value;
-
- if((ipv6_hash_table_entry->flags & NAME_RESOLVED)) {
- QString entry = QString("%1\t%2")
- .arg(ipv6_hash_table_entry->ip6)
- .arg(ipv6_hash_table_entry->name);
- *string_list << entry;
- }
-}
-
-static void
-ipv4_hash_table_to_qstringlist(gpointer key, gpointer value, gpointer sl_ptr)
-{
- QStringList *string_list = (QStringList *) sl_ptr;
- hashipv4_t *ipv4_hash_table_entry = (hashipv4_t *)value;
- guint addr = GPOINTER_TO_UINT(key);
-
- QString entry = QString("Key: 0x%1 IPv4: %2, Name: %3")
- .arg(QString::number(addr, 16))
- .arg(ipv4_hash_table_entry->ip)
- .arg(ipv4_hash_table_entry->name);
-
- *string_list << entry;
-}
-
-static void
-ipv6_hash_table_to_qstringlist(gpointer key, gpointer value, gpointer sl_ptr)
-{
- QStringList *string_list = (QStringList *) sl_ptr;
- hashipv6_t *ipv6_hash_table_entry = (hashipv6_t *)value;
- guint addr = GPOINTER_TO_UINT(key);
-
- QString entry = QString("Key: 0x%1 IPv4: %2, Name: %3")
- .arg(QString::number(addr, 16))
- .arg(ipv6_hash_table_entry->ip6)
- .arg(ipv6_hash_table_entry->name);
-
- *string_list << entry;
-}
-
-static void
-serv_port_hash_to_qstringlist(gpointer key, gpointer value, gpointer sl_ptr)
-{
- QStringList *string_list = (QStringList *) sl_ptr;
- serv_port_t *serv_port = (serv_port_t *)value;
- guint port = GPOINTER_TO_UINT(key);
-
- QStringList entries;
-
- if (serv_port->tcp_name) entries << QString("%1\t%2/tcp").arg(serv_port->tcp_name).arg(port);
- if (serv_port->udp_name) entries << QString("%1\t%2/udp").arg(serv_port->udp_name).arg(port);
- if (serv_port->sctp_name) entries << QString("%1\t%2/sctp").arg(serv_port->sctp_name).arg(port);
- if (serv_port->dccp_name) entries << QString("%1\t%2/dccp").arg(serv_port->dccp_name).arg(port);
-
- if (!entries.isEmpty()) *string_list << entries.join("\n");
-}
-
-static void
-eth_hash_to_qstringlist(gpointer, gpointer value, gpointer sl_ptr)
-{
- QStringList *string_list = (QStringList *) sl_ptr;
- hashether_t* tp = (hashether_t*)value;
-
- QString entry = QString("%1 %2")
- .arg(get_hash_ether_hexaddr(tp))
- .arg(get_hash_ether_resolved_name(tp));
-
- *string_list << entry;
-}
-
-static void
-manuf_hash_to_qstringlist(gpointer key, gpointer value, gpointer sl_ptr)
-{
- QStringList *string_list = (QStringList *) sl_ptr;
- hashmanuf_t *manuf = (hashmanuf_t*)value;
- guint eth_as_guint = GPOINTER_TO_UINT(key);
-
- QString entry = QString("%1:%2:%3 %4")
- .arg((eth_as_guint >> 16 & 0xff), 2, 16, QChar('0'))
- .arg((eth_as_guint >> 8 & 0xff), 2, 16, QChar('0'))
- .arg((eth_as_guint & 0xff), 2, 16, QChar('0'))
- .arg(get_hash_manuf_resolved_name(manuf));
-
- *string_list << entry;
-}
-
-static void
-wka_hash_to_qstringlist(gpointer key, gpointer value, gpointer sl_ptr)
-{
- QStringList *string_list = (QStringList *) sl_ptr;
- gchar *name = (gchar *)value;
- guint8 *eth_addr = (guint8*)key;
-
- QString entry = QString("%1:%2:%3:%4:%5:%6 %7")
- .arg(eth_addr[0], 2, 16, QChar('0'))
- .arg(eth_addr[1], 2, 16, QChar('0'))
- .arg(eth_addr[2], 2, 16, QChar('0'))
- .arg(eth_addr[3], 2, 16, QChar('0'))
- .arg(eth_addr[4], 2, 16, QChar('0'))
- .arg(eth_addr[5], 2, 16, QChar('0'))
- .arg(name);
-
- *string_list << entry;
-}
-
-}
const QString no_entries_ = QObject::tr("No entries.");
const QString entry_count_ = QObject::tr("%1 entries.");
ResolvedAddressesDialog::ResolvedAddressesDialog(QWidget *parent, CaptureFile *capture_file) :
- GeometryStateDialog(NULL),
+ GeometryStateDialog(parent),
ui(new Ui::ResolvedAddressesDialog),
file_name_(tr("[no file]"))
{
ui->setupUi(this);
- if (parent) loadGeometry(parent->width() * 2 / 3, parent->height());
setAttribute(Qt::WA_DeleteOnClose, true);
QStringList title_parts = QStringList() << tr("Resolved Addresses");
@@ -203,45 +76,92 @@ ResolvedAddressesDialog::ResolvedAddressesDialog(QWidget *parent, CaptureFile *c
}
}
- wmem_map_t *ipv4_hash_table = get_ipv4_hash_table();
- if (ipv4_hash_table) {
- wmem_map_foreach(ipv4_hash_table, ipv4_hash_table_resolved_to_qstringlist, &host_addresses_);
- wmem_map_foreach(ipv4_hash_table, ipv4_hash_table_to_qstringlist, &v4_hash_addrs_);
- }
+ fillBlocks();
- wmem_map_t *ipv6_hash_table = get_ipv6_hash_table();
- if (ipv6_hash_table) {
- wmem_map_foreach(ipv6_hash_table, ipv6_hash_table_resolved_to_qstringlist, &host_addresses_);
- wmem_map_foreach(ipv6_hash_table, ipv6_hash_table_to_qstringlist, &v6_hash_addrs_);
- }
+ ethSortModel = new AStringListListSortFilterProxyModel(this);
+ ethTypeModel = new AStringListListSortFilterProxyModel(this);
+ EthernetAddressModel * ethModel = new EthernetAddressModel(this);
+ ethSortModel->setSourceModel(ethModel);
+ ethSortModel->setColumnToFilter(1);
+ ethSortModel->setColumnToFilter(2);
+ ethSortModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
+ ethTypeModel->setSourceModel(ethSortModel);
+ ethTypeModel->setColumnToFilter(0);
+ ethTypeModel->setColumnToHide(0);
+ ui->tblAddresses->setModel(ethTypeModel);
+ ui->tblAddresses->resizeColumnsToContents();
+ ui->tblAddresses->horizontalHeader()->setStretchLastSection(true);
+ ui->tblAddresses->sortByColumn(1, Qt::AscendingOrder);
+ ui->cmbDataType->addItems(ethModel->filterValues());
+
+ portSortModel = new AStringListListSortFilterProxyModel(this);
+ portTypeModel = new AStringListListSortFilterProxyModel(this);
+ PortsModel * portModel = new PortsModel(this);
+ portSortModel->setSourceModel(portModel);
+ portSortModel->setColumnAsNumeric(1);
+ portSortModel->setColumnToFilter(0);
+ portSortModel->setColumnToFilter(1);
+ portSortModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
+ portTypeModel->setSourceModel(portSortModel);
+ portTypeModel->setColumnToFilter(2);
+ ui->tblPorts->setModel(portTypeModel);
+ ui->tblPorts->resizeColumnsToContents();
+ ui->tblPorts->horizontalHeader()->setStretchLastSection(true);
+ ui->tblPorts->sortByColumn(1, Qt::AscendingOrder);
+ ui->cmbPortFilterType->addItems(portModel->filterValues());
+}
- wmem_map_t *serv_port_hashtable = get_serv_port_hashtable();
- if(serv_port_hashtable){
- wmem_map_foreach(serv_port_hashtable, serv_port_hash_to_qstringlist, &service_ports_);
- }
+ResolvedAddressesDialog::~ResolvedAddressesDialog()
+{
+ delete ui;
+}
- wmem_map_t *eth_hashtable = get_eth_hashtable();
- if (eth_hashtable){
- wmem_map_foreach(eth_hashtable, eth_hash_to_qstringlist, &ethernet_addresses_);
- }
+void ResolvedAddressesDialog::on_cmbDataType_currentIndexChanged(QString)
+{
+ if ( ! ethSortModel )
+ return;
- wmem_map_t *manuf_hashtable = get_manuf_hashtable();
- if (manuf_hashtable){
- wmem_map_foreach(manuf_hashtable, manuf_hash_to_qstringlist, &ethernet_manufacturers_);
+ QString filter = ui->cmbDataType->currentText();
+ if ( ui->cmbDataType->currentIndex() == 0 )
+ {
+ filter.clear();
+ ethTypeModel->setFilterType(AStringListListSortFilterProxyModel::FilterNone, 0);
}
+ else
+ ethTypeModel->setFilterType(AStringListListSortFilterProxyModel::FilterByEquivalent, 0);
+ ethTypeModel->setFilter(filter);
+}
- wmem_map_t *wka_hashtable = get_wka_hashtable();
- if(wka_hashtable){
- wmem_map_foreach(wka_hashtable, wka_hash_to_qstringlist, &ethernet_well_known_);
- }
+void ResolvedAddressesDialog::on_txtSearchFilter_textChanged(QString)
+{
+ if ( ! ethSortModel || ui->txtSearchFilter->text().length() < 3 )
+ return;
- fillShowMenu();
- fillBlocks();
+ ethSortModel->setFilter(ui->txtSearchFilter->text());
}
-ResolvedAddressesDialog::~ResolvedAddressesDialog()
+void ResolvedAddressesDialog::on_cmbPortFilterType_currentIndexChanged(QString)
{
- delete ui;
+ if ( ! portSortModel )
+ return;
+
+ QString filter = ui->cmbPortFilterType->currentText();
+ if ( ui->cmbPortFilterType->currentIndex() == 0 )
+ {
+ filter.clear();
+ portTypeModel->setFilterType(AStringListListSortFilterProxyModel::FilterNone, 2);
+ }
+ else
+ portTypeModel->setFilterType(AStringListListSortFilterProxyModel::FilterByEquivalent, 2);
+ portTypeModel->setFilter(filter);
+}
+
+void ResolvedAddressesDialog::on_txtPortFilter_textChanged(QString val)
+{
+ if ( ! portSortModel )
+ return;
+
+ portSortModel->setFilter(val);
}
void ResolvedAddressesDialog::changeEvent(QEvent *event)
@@ -252,7 +172,6 @@ void ResolvedAddressesDialog::changeEvent(QEvent *event)
{
case QEvent::LanguageChange:
ui->retranslateUi(this);
- fillShowMenu();
fillBlocks();
break;
default:
@@ -262,32 +181,6 @@ void ResolvedAddressesDialog::changeEvent(QEvent *event)
QDialog::changeEvent(event);
}
-void ResolvedAddressesDialog::fillShowMenu()
-{
- QPushButton *show_bt = ui->buttonBox->button(QDialogButtonBox::Apply);
- show_bt->setText(tr("Show"));
-
- if (!show_bt->menu()) {
- show_bt->setMenu(new QMenu(show_bt));
- }
-
- QMenu *show_menu = show_bt->menu();
- show_menu->clear();
-
- show_menu->addAction(ui->actionAddressesHosts);
- show_menu->addAction(ui->actionComment);
- show_menu->addAction(ui->actionIPv4HashTable);
- show_menu->addAction(ui->actionIPv6HashTable);
- show_menu->addAction(ui->actionPortNames);
- show_menu->addAction(ui->actionEthernetAddresses);
- show_menu->addAction(ui->actionEthernetManufacturers);
- show_menu->addAction(ui->actionEthernetWKA);
-
- show_menu->addSeparator();
- show_menu->addAction(ui->actionShowAll);
- show_menu->addAction(ui->actionHideAll);
-}
-
void ResolvedAddressesDialog::fillBlocks()
{
setUpdatesEnabled(false);
@@ -309,169 +202,10 @@ void ResolvedAddressesDialog::fillBlocks()
ui->plainTextEdit->appendPlainText(lines);
}
- if (ui->actionAddressesHosts->isChecked()) {
- lines = "\n";
- lines.append(tr("# Hosts\n#\n# "));
- if (!host_addresses_.isEmpty()) {
- lines.append(entry_count_.arg(host_addresses_.length()));
- lines.append("\n\n");
- lines.append(host_addresses_.join("\n"));
- } else {
- lines.append(no_entries_);
- }
- ui->plainTextEdit->appendPlainText(lines);
- }
-
- if (ui->actionIPv4HashTable->isChecked()) {
- lines = "\n";
- lines.append(tr("# IPv4 Hash Table\n#\n# "));
- if (!v4_hash_addrs_.isEmpty()) {
- lines.append(entry_count_.arg(v4_hash_addrs_.length()));
- lines.append(tr("\n\n"));
- lines.append(v4_hash_addrs_.join("\n"));
- } else {
- lines.append(no_entries_);
- }
- ui->plainTextEdit->appendPlainText(lines);
- }
-
- if (ui->actionIPv6HashTable->isChecked()) {
- lines = "\n";
- lines.append(tr("# IPv6 Hash Table\n#\n# "));
- if (!v6_hash_addrs_.isEmpty()) {
- lines.append(entry_count_.arg(v6_hash_addrs_.length()));
- lines.append(tr("\n\n"));
- lines.append(v6_hash_addrs_.join("\n"));
- } else {
- lines.append(no_entries_);
- }
- ui->plainTextEdit->appendPlainText(lines);
- }
-
- if (ui->actionPortNames->isChecked()) {
- lines = "\n";
- lines.append(tr("# Services\n#\n# "));
- if (!service_ports_.isEmpty()) {
- lines.append(entry_count_.arg(service_ports_.length()));
- lines.append(tr("\n\n"));
- lines.append(service_ports_.join("\n"));
- } else {
- lines.append(no_entries_);
- }
- ui->plainTextEdit->appendPlainText(lines);
- }
-
- if (ui->actionEthernetAddresses->isChecked()) {
- lines = "\n";
- lines.append(tr("# Ethernet addresses\n#\n# "));
- if (!ethernet_addresses_.isEmpty()) {
- lines.append(entry_count_.arg(ethernet_addresses_.length()));
- lines.append(tr("\n\n"));
- lines.append(ethernet_addresses_.join("\n"));
- } else {
- lines.append(no_entries_);
- }
- ui->plainTextEdit->appendPlainText(lines);
- }
-
- if (ui->actionEthernetManufacturers->isChecked()) {
- lines = "\n";
- lines.append(tr("# Ethernet manufacturers\n#\n# "));
- if (!ethernet_manufacturers_.isEmpty()) {
- lines.append(entry_count_.arg(ethernet_manufacturers_.length()));
- lines.append(tr("\n\n"));
- lines.append(ethernet_manufacturers_.join("\n"));
- } else {
- lines.append(no_entries_);
- }
- ui->plainTextEdit->appendPlainText(lines);
- }
-
- if (ui->actionEthernetWKA->isChecked()) {
- lines = "\n";
- lines.append(tr("# Well known Ethernet addresses\n#\n# "));
- if (!ethernet_well_known_.isEmpty()) {
- lines.append(entry_count_.arg(ethernet_well_known_.length()));
- lines.append(tr("\n\n"));
- lines.append(ethernet_well_known_.join("\n"));
- } else {
- lines.append(no_entries_);
- }
- ui->plainTextEdit->appendPlainText(lines);
- }
-
ui->plainTextEdit->moveCursor(QTextCursor::Start);
setUpdatesEnabled(true);
}
-void ResolvedAddressesDialog::on_actionAddressesHosts_triggered()
-{
- fillBlocks();
-}
-
-void ResolvedAddressesDialog::on_actionComment_triggered()
-{
- fillBlocks();
-}
-
-void ResolvedAddressesDialog::on_actionIPv4HashTable_triggered()
-{
- fillBlocks();
-}
-
-void ResolvedAddressesDialog::on_actionIPv6HashTable_triggered()
-{
- fillBlocks();
-}
-
-void ResolvedAddressesDialog::on_actionPortNames_triggered()
-{
- fillBlocks();
-}
-
-void ResolvedAddressesDialog::on_actionEthernetAddresses_triggered()
-{
- fillBlocks();
-}
-
-void ResolvedAddressesDialog::on_actionEthernetManufacturers_triggered()
-{
- fillBlocks();
-}
-
-void ResolvedAddressesDialog::on_actionEthernetWKA_triggered()
-{
- fillBlocks();
-}
-
-void ResolvedAddressesDialog::on_actionShowAll_triggered()
-{
- ui->actionAddressesHosts->setChecked(true);
- ui->actionComment->setChecked(true);
- ui->actionIPv4HashTable->setChecked(true);
- ui->actionIPv6HashTable->setChecked(true);
- ui->actionPortNames->setChecked(true);
- ui->actionEthernetAddresses->setChecked(true);
- ui->actionEthernetManufacturers->setChecked(true);
- ui->actionEthernetWKA->setChecked(true);
-
- fillBlocks();
-}
-
-void ResolvedAddressesDialog::on_actionHideAll_triggered()
-{
- ui->actionAddressesHosts->setChecked(false);
- ui->actionComment->setChecked(false);
- ui->actionIPv4HashTable->setChecked(false);
- ui->actionIPv6HashTable->setChecked(false);
- ui->actionPortNames->setChecked(false);
- ui->actionEthernetAddresses->setChecked(false);
- ui->actionEthernetManufacturers->setChecked(false);
- ui->actionEthernetWKA->setChecked(false);
-
- fillBlocks();
-}
-
/*
* Editor modelines
*
diff --git a/ui/qt/resolved_addresses_dialog.h b/ui/qt/resolved_addresses_dialog.h
index 99735ca3c1..58272d55f1 100644
--- a/ui/qt/resolved_addresses_dialog.h
+++ b/ui/qt/resolved_addresses_dialog.h
@@ -13,7 +13,7 @@
#include "geometry_state_dialog.h"
class CaptureFile;
-class QTextBlock;
+class AStringListListSortFilterProxyModel;
namespace Ui {
class ResolvedAddressesDialog;
@@ -28,34 +28,23 @@ public:
~ResolvedAddressesDialog();
protected slots:
- void changeEvent(QEvent* event);
-
-private slots:
- void on_actionAddressesHosts_triggered();
- void on_actionComment_triggered();
- void on_actionIPv4HashTable_triggered();
- void on_actionIPv6HashTable_triggered();
- void on_actionPortNames_triggered();
- void on_actionEthernetAddresses_triggered();
- void on_actionEthernetManufacturers_triggered();
- void on_actionEthernetWKA_triggered();
+ void on_cmbDataType_currentIndexChanged(QString val);
+ void on_txtSearchFilter_textChanged(QString text);
+ void on_cmbPortFilterType_currentIndexChanged(QString val);
+ void on_txtPortFilter_textChanged(QString text);
- void on_actionShowAll_triggered();
- void on_actionHideAll_triggered();
+ void changeEvent(QEvent* event);
private:
Ui::ResolvedAddressesDialog *ui;
QString file_name_;
QString comment_;
- QStringList host_addresses_;
- QStringList v4_hash_addrs_;
- QStringList v6_hash_addrs_;
- QStringList service_ports_;
- QStringList ethernet_addresses_;
- QStringList ethernet_manufacturers_;
- QStringList ethernet_well_known_;
- void fillShowMenu();
+ AStringListListSortFilterProxyModel * ethSortModel;
+ AStringListListSortFilterProxyModel * ethTypeModel;
+ AStringListListSortFilterProxyModel * portSortModel;
+ AStringListListSortFilterProxyModel * portTypeModel;
+
void fillBlocks();
};
diff --git a/ui/qt/resolved_addresses_dialog.ui b/ui/qt/resolved_addresses_dialog.ui
index c5ab5c6946..a1a194e9d4 100644
--- a/ui/qt/resolved_addresses_dialog.ui
+++ b/ui/qt/resolved_addresses_dialog.ui
@@ -13,9 +13,94 @@
<property name="windowTitle">
<string>Dialog</string>
</property>
- <layout class="QVBoxLayout" name="verticalLayout">
+ <layout class="QVBoxLayout" name="verticalLayout_2">
<item>
- <widget class="QPlainTextEdit" name="plainTextEdit"/>
+ <widget class="QTabWidget" name="tabWidget">
+ <property name="currentIndex">
+ <number>0</number>
+ </property>
+ <widget class="QWidget" name="tab">
+ <attribute name="title">
+ <string>Hosts</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLineEdit" name="txtSearchFilter">
+ <property name="placeholderText">
+ <string>Search for entry (min 3 characters)</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="cmbDataType"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QTableView" name="tblAddresses">
+ <property name="editTriggers">
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </property>
+ <property name="alternatingRowColors">
+ <bool>true</bool>
+ </property>
+ <property name="sortingEnabled">
+ <bool>true</bool>
+ </property>
+ <attribute name="horizontalHeaderShowSortIndicator" stdset="0">
+ <bool>true</bool>
+ </attribute>
+ <attribute name="verticalHeaderVisible">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_3">
+ <attribute name="title">
+ <string>Ports</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <item>
+ <widget class="QLineEdit" name="txtPortFilter">
+ <property name="placeholderText">
+ <string>Search for port or name</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="cmbPortFilterType"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QTableView" name="tblPorts">
+ <property name="sortingEnabled">
+ <bool>true</bool>
+ </property>
+ <attribute name="verticalHeaderVisible">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWidget" name="tab_2">
+ <attribute name="title">
+ <string>Capture File Comments</string>
+ </attribute>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <widget class="QPlainTextEdit" name="plainTextEdit"/>
+ </item>
+ </layout>
+ </widget>
+ </widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
@@ -23,7 +108,7 @@
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
- <set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ <set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>