summaryrefslogtreecommitdiffstats
path: root/ui/qt/models/decode_as_model.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ui/qt/models/decode_as_model.cpp')
-rw-r--r--ui/qt/models/decode_as_model.cpp849
1 files changed, 849 insertions, 0 deletions
diff --git a/ui/qt/models/decode_as_model.cpp b/ui/qt/models/decode_as_model.cpp
new file mode 100644
index 0000000..67e98b7
--- /dev/null
+++ b/ui/qt/models/decode_as_model.cpp
@@ -0,0 +1,849 @@
+/* decode_as_model.cpp
+ * Data model for Decode As records.
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <errno.h>
+
+#include "decode_as_model.h"
+#include <epan/to_str.h>
+#include <epan/decode_as.h>
+#include <epan/epan_dissect.h>
+#include <epan/packet.h>
+#include <epan/prefs.h>
+#include <epan/prefs-int.h>
+#include <epan/dissectors/packet-dcerpc.h>
+
+#include <ui/qt/utils/qt_ui_utils.h>
+#include <ui/qt/utils/variant_pointer.h>
+#include <wsutil/file_util.h>
+#include <wsutil/ws_assert.h>
+
+#include <QVector>
+
+static const char *DEFAULT_TABLE = "tcp.port"; // Arbitrary
+static const char *DEFAULT_UI_TABLE = "TCP port"; // Arbitrary
+
+DecodeAsItem::DecodeAsItem(const char* table_name, gconstpointer selector) :
+ tableName_(DEFAULT_TABLE),
+ tableUIName_(DEFAULT_UI_TABLE),
+ selectorUint_(0),
+ selectorString_(""),
+ selectorDCERPC_(NULL),
+ default_dissector_(DECODE_AS_NONE),
+ current_dissector_(DECODE_AS_NONE),
+ dissector_handle_(NULL)
+{
+ if (table_name == nullptr)
+ return;
+
+ init(table_name, selector);
+}
+
+DecodeAsItem::DecodeAsItem(const decode_as_t *entry, gconstpointer selector) :
+ tableName_(DEFAULT_TABLE),
+ tableUIName_(DEFAULT_UI_TABLE),
+ selectorUint_(0),
+ selectorString_(""),
+ selectorDCERPC_(NULL),
+ default_dissector_(DECODE_AS_NONE),
+ current_dissector_(DECODE_AS_NONE),
+ dissector_handle_(NULL)
+{
+ if (entry == nullptr)
+ return;
+
+ init(entry->table_name, selector);
+}
+
+DecodeAsItem::~DecodeAsItem()
+{
+}
+
+void DecodeAsItem::init(const char* table_name, gconstpointer selector)
+{
+ tableName_ = table_name;
+ tableUIName_ = get_dissector_table_ui_name(tableName_);
+
+ dissector_handle_t default_handle = NULL;
+ ftenum_t selector_type = get_dissector_table_selector_type(tableName_);
+ if (FT_IS_STRING(selector_type)) {
+ if (selector != NULL) {
+ default_handle = dissector_get_default_string_handle(tableName_, (const gchar*)selector);
+ selectorString_ = QString((const char*)selector);
+ }
+ } else if (FT_IS_UINT(selector_type)) {
+ if (selector != NULL) {
+ selectorUint_ = GPOINTER_TO_UINT(selector);
+ default_handle = dissector_get_default_uint_handle(tableName_, selectorUint_);
+ }
+ } else if (selector_type == FT_NONE) {
+ // There is no default for an FT_NONE dissector table
+ } else if (selector_type == FT_GUID) {
+ /* Special handling for DCE/RPC dissectors */
+ if (strcmp(tableName_, DCERPC_TABLE_NAME) == 0) {
+ selectorDCERPC_ = (decode_dcerpc_bind_values_t*)(selector);
+ }
+ }
+
+ if (default_handle != NULL) {
+ default_dissector_ = dissector_handle_get_description(default_handle);
+ // When adding a new record, we set the "current" values equal to
+ // the default, so the user can easily reset the value.
+ // The existing value read from the prefs file should already
+ // be added to the table from reading the prefs file.
+ // When reading existing values the current dissector should be
+ // set explicitly to the actual current value.
+ current_dissector_ = default_dissector_;
+ dissector_handle_ = default_handle;
+ }
+}
+
+void DecodeAsItem::setTable(const decode_as_t *entry)
+{
+ if (entry == nullptr)
+ return;
+
+ tableName_ = entry->table_name;
+ tableUIName_ = get_dissector_table_ui_name(entry->table_name);
+
+ /* XXX: Should the selector values be reset (e.g., to 0 and "")
+ * What if someone tries to change the table to the DCERPC table?
+ * That doesn't really work without the DCERPC special handling.
+ */
+
+ updateHandles();
+}
+
+void DecodeAsItem::setSelector(const QString &value)
+{
+ ftenum_t selector_type = get_dissector_table_selector_type(tableName_);
+
+ if (FT_IS_STRING(selector_type)) {
+ selectorString_ = value;
+ } else if (FT_IS_UINT(selector_type)) {
+ selectorUint_ = value.toUInt(Q_NULLPTR, 0);
+ }
+
+ updateHandles();
+}
+
+void DecodeAsItem::setDissectorHandle(dissector_handle_t handle)
+{
+ dissector_handle_ = handle;
+ if (handle == nullptr) {
+ current_dissector_ = DECODE_AS_NONE;
+ } else {
+ current_dissector_ = dissector_handle_get_description(handle);
+ }
+}
+
+void DecodeAsItem::updateHandles()
+{
+ ftenum_t selector_type = get_dissector_table_selector_type(tableName_);
+ dissector_handle_t default_handle = nullptr;
+
+ if (FT_IS_STRING(selector_type)) {
+ default_handle = dissector_get_default_string_handle(tableName_, qUtf8Printable(selectorString_));
+ } else if (FT_IS_UINT(selector_type)) {
+ default_handle = dissector_get_default_uint_handle(tableName_, selectorUint_);
+ }
+ if (default_handle != nullptr) {
+ default_dissector_ = dissector_handle_get_description(default_handle);
+ } else {
+ default_dissector_ = DECODE_AS_NONE;
+ }
+}
+
+DecodeAsModel::DecodeAsModel(QObject *parent, capture_file *cf) :
+ QAbstractTableModel(parent),
+ cap_file_(cf)
+{
+}
+
+DecodeAsModel::~DecodeAsModel()
+{
+ foreach(DecodeAsItem* item, decode_as_items_)
+ delete item;
+ decode_as_items_.clear();
+}
+
+Qt::ItemFlags DecodeAsModel::flags(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return Qt::ItemFlags();
+
+ DecodeAsItem* item = decode_as_items_[index.row()];
+
+ Qt::ItemFlags flags = QAbstractTableModel::flags(index);
+ switch(index.column())
+ {
+ case DecodeAsModel::colTable:
+ case DecodeAsModel::colProtocol:
+ flags |= Qt::ItemIsEditable;
+ break;
+ case DecodeAsModel::colSelector:
+ {
+ ftenum_t selector_type = get_dissector_table_selector_type(item->tableName());
+ if ((selector_type != FT_NONE) &&
+ (item->selectorDCERPC() == NULL))
+ flags |= Qt::ItemIsEditable;
+ break;
+ }
+ }
+
+ return flags;
+}
+
+QVariant DecodeAsModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid()) {
+ return QVariant();
+ }
+
+ DecodeAsItem* item;
+
+ switch (role)
+ {
+ case Qt::ToolTipRole:
+ switch (index.column())
+ {
+ case colTable:
+ return tr("Match using this field");
+ case colSelector:
+ return tr("Change behavior when the field matches this value");
+ case colType:
+ return tr("Field value type (and base, if Integer)");
+ case colDefault:
+ return tr("Default \"Decode As\" behavior");
+ case colProtocol:
+ return tr("Current\"Decode As\" behavior");
+ }
+ return QVariant();
+ case Qt::DisplayRole:
+ case Qt::EditRole:
+ item = decode_as_items_[index.row()];
+ if (item == NULL)
+ return QVariant();
+
+ switch (index.column())
+ {
+ case colTable:
+ return item->tableUIName();
+ case colSelector:
+ {
+ ftenum_t selector_type = get_dissector_table_selector_type(item->tableName());
+ if (FT_IS_UINT(selector_type)) {
+ return entryString(item->tableName(), GUINT_TO_POINTER(item->selectorUint()));
+ } else if (FT_IS_STRING(selector_type)) {
+ return entryString(item->tableName(), (gconstpointer)item->selectorString().toUtf8().constData());
+ } else if (selector_type == FT_GUID) {
+ if (item->selectorDCERPC() != NULL) {
+ return item->selectorDCERPC()->ctx_id;
+ }
+ }
+
+ return DECODE_AS_NONE;
+ }
+ case colType:
+ {
+ ftenum_t selector_type = get_dissector_table_selector_type(item->tableName());
+
+ if (FT_IS_STRING(selector_type)) {
+ return tr("String");
+ } else if (FT_IS_UINT(selector_type)) {
+ QString type_desc = tr("Integer, base ");
+ switch (get_dissector_table_param(item->tableName())) {
+ case BASE_OCT:
+ type_desc.append("8");
+ break;
+ case BASE_DEC:
+ type_desc.append("10");
+ break;
+ case BASE_HEX:
+ type_desc.append("16");
+ break;
+ default:
+ type_desc.append(tr("unknown"));
+ }
+ return type_desc;
+ } else if (selector_type == FT_NONE) {
+ return tr("<none>");
+ } else if (selector_type == FT_GUID) {
+ if (item->selectorDCERPC() != NULL) {
+ return QString("ctx_id");
+ } else {
+ return tr("GUID");
+ }
+ }
+ break;
+ }
+ case colDefault:
+ return item->defaultDissector();
+ case colProtocol:
+ return item->currentDissector();
+ }
+ return QVariant();
+
+ case Qt::UserRole:
+ item = decode_as_items_[index.row()];
+ return QVariant::fromValue(static_cast<void *>(item));
+ }
+
+ return QVariant();
+}
+
+QVariant DecodeAsModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (role != Qt::DisplayRole || orientation != Qt::Horizontal)
+ return QVariant();
+
+ switch (section) {
+ case colTable:
+ return tr("Field");
+ case colSelector:
+ return tr("Value");
+ case colType:
+ return tr("Type");
+ case colDefault:
+ return tr("Default");
+ case colProtocol:
+ return tr("Current");
+ default:
+ ws_assert_not_reached();
+ }
+
+ return QVariant();
+}
+
+int DecodeAsModel::rowCount(const QModelIndex &parent) const
+{
+ // there are no children
+ if (parent.isValid()) {
+ return 0;
+ }
+
+ return static_cast<int>(decode_as_items_.count());
+}
+
+int DecodeAsModel::columnCount(const QModelIndex &parent) const
+{
+ // there are no children
+ if (parent.isValid()) {
+ return 0;
+ }
+
+ return colDecodeAsMax;
+}
+
+bool DecodeAsModel::setData(const QModelIndex &cur_index, const QVariant &value, int role)
+{
+ if (!cur_index.isValid())
+ return false;
+
+ if (role != Qt::EditRole)
+ return false;
+
+ if (data(cur_index, role) == value) {
+ // Data appears unchanged, do not do additional checks.
+ return true;
+ }
+
+ DecodeAsItem* item = decode_as_items_[cur_index.row()];
+
+ switch(cur_index.column())
+ {
+ case DecodeAsModel::colTable:
+ {
+ QString valueStr = value.toString();
+ //grab the table values from the Decode As list because they are persistent
+ for (GList *cur = decode_as_list; cur; cur = cur->next) {
+ decode_as_t *entry = (decode_as_t *) cur->data;
+ if (valueStr.compare(get_dissector_table_ui_name(entry->table_name)) == 0) {
+ item->setTable(entry);
+ //all other columns affected
+ emit dataChanged(index(cur_index.row(), colSelector),
+ index(cur_index.row(), colProtocol));
+ break;
+ }
+ }
+ }
+ break;
+ case DecodeAsModel::colProtocol:
+ {
+ dissector_handle_t handle = VariantPointer<dissector_handle>::asPtr(value);
+ item->setDissectorHandle(handle);
+ break;
+ }
+ case DecodeAsModel::colSelector:
+ item->setSelector(value.toString());
+ emit dataChanged(index(cur_index.row(), colDefault),
+ index(cur_index.row(), colProtocol));
+ break;
+ }
+
+ return true;
+}
+
+bool DecodeAsModel::insertRows(int row, int count, const QModelIndex &/*parent*/)
+{
+ // support insertion of just one item for now.
+ if (count != 1 || row < 0 || row > rowCount())
+ return false;
+
+ beginInsertRows(QModelIndex(), row, row);
+
+ DecodeAsItem* item = nullptr;
+ const decode_as_t *firstEntry = nullptr;
+
+ if (cap_file_ && cap_file_->edt) {
+ // Populate the new Decode As item with the last protocol layer
+ // that can support Decode As and has a selector field for that
+ // present in the frame.
+ //
+ // XXX: This treats 0 (for UInts) and empty strings the same as
+ // the fields for the tables not being present at all.
+
+ wmem_list_frame_t * protos = wmem_list_tail(cap_file_->edt->pi.layers);
+ gint8 curr_layer_num_saved = cap_file_->edt->pi.curr_layer_num;
+ guint8 curr_layer_num = wmem_list_count(cap_file_->edt->pi.layers);
+
+ while (protos != NULL && item == nullptr) {
+ int proto_id = GPOINTER_TO_INT(wmem_list_frame_data(protos));
+ const gchar * proto_name = proto_get_protocol_filter_name(proto_id);
+ for (GList *cur = decode_as_list; cur; cur = cur->next) {
+ decode_as_t *entry = (decode_as_t *) cur->data;
+ if (g_strcmp0(proto_name, entry->name) == 0) {
+ if (firstEntry == nullptr) {
+ firstEntry = entry;
+ }
+ ftenum_t selector_type = get_dissector_table_selector_type(entry->table_name);
+ // Pick the first value in the packet for the current
+ // layer for the table
+ // XXX: What if the Decode As table supports multiple
+ // values, but the first possible one is 0/NULL?
+ cap_file_->edt->pi.curr_layer_num = curr_layer_num;
+ gpointer selector = entry->values[0].build_values[0](&cap_file_->edt->pi);
+ // FT_NONE tables don't need a value
+ if (selector != NULL || selector_type == FT_NONE) {
+ item = new DecodeAsItem(entry, selector);
+ break;
+ }
+
+ }
+ }
+ protos = wmem_list_frame_prev(protos);
+ curr_layer_num--;
+ }
+
+ cap_file_->edt->pi.curr_layer_num = curr_layer_num_saved;
+ }
+
+ // If we didn't find an entry with a valid selector, create an entry
+ // from the last table with an empty selector, or an empty entry.
+ if (item == nullptr) {
+ item = new DecodeAsItem(firstEntry);
+ }
+ decode_as_items_ << item;
+
+ endInsertRows();
+
+ return true;
+}
+
+bool DecodeAsModel::removeRows(int row, int count, const QModelIndex &/*parent*/)
+{
+ if (count != 1 || row < 0 || row >= rowCount())
+ return false;
+
+ beginRemoveRows(QModelIndex(), row, row);
+ DecodeAsItem* item = decode_as_items_.takeAt(row);
+ delete item;
+ endRemoveRows();
+
+ return true;
+}
+
+void DecodeAsModel::clearAll()
+{
+ if (rowCount() < 1)
+ return;
+
+ beginResetModel();
+ foreach(DecodeAsItem* item, decode_as_items_)
+ delete item;
+ decode_as_items_.clear();
+ endResetModel();
+}
+
+bool DecodeAsModel::copyRow(int dst_row, int src_row)
+{
+ if (src_row < 0 || src_row >= rowCount() || dst_row < 0 || dst_row >= rowCount()) {
+ return false;
+ }
+
+ DecodeAsItem* src = decode_as_items_[src_row];
+ DecodeAsItem* dst = decode_as_items_[dst_row];
+
+ *dst = *src;
+
+ QVector<int> roles;
+ roles << Qt::EditRole << Qt::BackgroundRole;
+ emit dataChanged(index(dst_row, 0), index(dst_row, columnCount()), roles);
+
+ return true;
+}
+
+prefs_set_pref_e DecodeAsModel::readDecodeAsEntry(gchar *key, const gchar *value, void *private_data, gboolean)
+{
+ DecodeAsModel *model = (DecodeAsModel*)private_data;
+ if (model == NULL)
+ return PREFS_SET_OK;
+
+ if (strcmp(key, DECODE_AS_ENTRY) != 0) {
+ return PREFS_SET_NO_SUCH_PREF;
+ }
+
+ /* Parse into table, selector, initial, current */
+ gchar **values = g_strsplit_set(value, ",", 4);
+ DecodeAsItem *item = nullptr;
+
+ dissector_table_t dissector_table = find_dissector_table(values[0]);
+
+ QString tableName(values[0]);
+ // Get the table values from the Decode As list because they are persistent
+ for (GList *cur = decode_as_list; cur; cur = cur->next) {
+ decode_as_t *entry = (decode_as_t *) cur->data;
+ if (tableName.compare(entry->table_name) == 0) {
+ item = new DecodeAsItem(entry);
+ break;
+ }
+ }
+
+ if (item == nullptr) {
+ g_strfreev(values);
+ return PREFS_SET_SYNTAX_ERR;
+ }
+
+ QString selector(values[1]);
+ item->setSelector(selector);
+
+ /* The value for the default dissector in the decode_as_entries file
+ * has no effect other than perhaps making the config file more
+ * informative when edited manually.
+ * We will actually display and reset to the programmatic default value.
+ */
+ item->setDissectorHandle(dissector_table_get_dissector_handle(dissector_table, values[3]));
+
+ model->decode_as_items_ << item;
+ g_strfreev(values);
+
+ return PREFS_SET_OK;
+}
+
+bool DecodeAsModel::copyFromProfile(QString filename, const gchar **err)
+{
+ FILE *fp = ws_fopen(filename.toUtf8().constData(), "r");
+
+ if (fp == NULL) {
+ *err = g_strerror(errno);
+ return false;
+ }
+
+ beginInsertRows(QModelIndex(), rowCount(), rowCount());
+ read_prefs_file(filename.toUtf8().constData(), fp, readDecodeAsEntry, this);
+ endInsertRows();
+
+ fclose(fp);
+
+ return true;
+}
+
+QString DecodeAsModel::entryString(const gchar *table_name, gconstpointer value)
+{
+ QString entry_str;
+ ftenum_t selector_type = get_dissector_table_selector_type(table_name);
+
+ switch (selector_type) {
+
+ case FT_UINT8:
+ case FT_UINT16:
+ case FT_UINT24:
+ case FT_UINT32:
+ {
+ uint num_val = GPOINTER_TO_UINT(value);
+ switch (get_dissector_table_param(table_name)) {
+
+ case BASE_DEC:
+ entry_str = QString::number(num_val);
+ break;
+
+ case BASE_HEX:
+ int width;
+ switch (selector_type) {
+ case FT_UINT8:
+ width = 2;
+ break;
+ case FT_UINT16:
+ width = 4;
+ break;
+ case FT_UINT24:
+ width = 6;
+ break;
+ case FT_UINT32:
+ width = 8;
+ break;
+
+ default:
+ ws_assert_not_reached();
+ break;
+ }
+ entry_str = QString("%1").arg(int_to_qstring(num_val, width, 16));
+ break;
+
+ case BASE_OCT:
+ entry_str = "0" + QString::number(num_val, 8);
+ break;
+ }
+ break;
+ }
+
+ case FT_STRING:
+ case FT_STRINGZ:
+ case FT_UINT_STRING:
+ case FT_STRINGZPAD:
+ case FT_STRINGZTRUNC:
+ entry_str = (const char *)value;
+ break;
+
+ case FT_GUID:
+ //avoid the assert for now
+ break;
+
+ case FT_NONE:
+ //doesn't really matter, just avoiding the assert
+ return "0";
+
+ default:
+ ws_assert_not_reached();
+ break;
+ }
+ return entry_str;
+}
+
+void DecodeAsModel::fillTable()
+{
+ decode_as_items_.clear();
+ beginResetModel();
+
+ dissector_all_tables_foreach_changed(buildChangedList, this);
+ decode_dcerpc_add_show_list(buildDceRpcChangedList, this);
+
+ endResetModel();
+}
+
+void DecodeAsModel::setDissectorHandle(const QModelIndex &index, dissector_handle_t dissector_handle)
+{
+ DecodeAsItem* item = decode_as_items_[index.row()];
+ if (item != NULL)
+ item->setDissectorHandle(dissector_handle);
+}
+
+void DecodeAsModel::buildChangedList(const gchar *table_name, ftenum_t, gpointer key, gpointer value, gpointer user_data)
+{
+ DecodeAsModel *model = (DecodeAsModel*)user_data;
+ if (model == NULL)
+ return;
+
+ dissector_handle_t current_dh;
+ DecodeAsItem* item = new DecodeAsItem(table_name, key);
+
+ current_dh = dtbl_entry_get_handle((dtbl_entry_t *)value);
+ item->setDissectorHandle(current_dh);
+
+ model->decode_as_items_ << item;
+}
+
+void DecodeAsModel::buildDceRpcChangedList(gpointer data, gpointer user_data)
+{
+ dissector_table_t sub_dissectors;
+ guid_key guid_val;
+ decode_dcerpc_bind_values_t *binding = (decode_dcerpc_bind_values_t *)data;
+
+ DecodeAsModel *model = (DecodeAsModel*)user_data;
+ if (model == NULL)
+ return;
+
+ DecodeAsItem* item = new DecodeAsItem(DCERPC_TABLE_NAME, binding);
+
+ sub_dissectors = find_dissector_table(DCERPC_TABLE_NAME);
+
+ guid_val.ver = binding->ver;
+ guid_val.guid = binding->uuid;
+ item->setDissectorHandle(dissector_get_guid_handle(sub_dissectors, &guid_val));
+
+ model->decode_as_items_ << item;
+}
+
+typedef QPair<const char *, guint32> UintPair;
+typedef QPair<const char *, const char *> CharPtrPair;
+
+void DecodeAsModel::gatherChangedEntries(const gchar *table_name,
+ ftenum_t selector_type, gpointer key, gpointer, gpointer user_data)
+{
+ DecodeAsModel *model = qobject_cast<DecodeAsModel*>((DecodeAsModel*)user_data);
+ if (model == NULL)
+ return;
+
+ switch (selector_type) {
+ case FT_UINT8:
+ case FT_UINT16:
+ case FT_UINT24:
+ case FT_UINT32:
+ model->changed_uint_entries_ << UintPair(table_name, GPOINTER_TO_UINT(key));
+ break;
+ case FT_NONE:
+ //need to reset dissector table, so this needs to be in a changed list,
+ //might as well be the uint one.
+ model->changed_uint_entries_ << UintPair(table_name, 0);
+ break;
+
+ case FT_STRING:
+ case FT_STRINGZ:
+ case FT_UINT_STRING:
+ case FT_STRINGZPAD:
+ case FT_STRINGZTRUNC:
+ model->changed_string_entries_ << CharPtrPair(table_name, (const char *) key);
+ break;
+ default:
+ break;
+ }
+}
+
+void DecodeAsModel::applyChanges()
+{
+ dissector_table_t sub_dissectors;
+ module_t *module;
+ pref_t* pref_value;
+ dissector_handle_t handle;
+ // Reset all dissector tables, then apply all rules from model.
+
+ // We can't call g_hash_table_removed from g_hash_table_foreach, which
+ // means we can't call dissector_reset_{string,uint} from
+ // dissector_all_tables_foreach_changed. Collect changed entries in
+ // lists and remove them separately.
+ //
+ // If dissector_all_tables_remove_changed existed we could call it
+ // instead.
+ dissector_all_tables_foreach_changed(gatherChangedEntries, this);
+ foreach (UintPair uint_entry, changed_uint_entries_) {
+ /* Set "Decode As preferences" to default values */
+ sub_dissectors = find_dissector_table(uint_entry.first);
+ handle = dissector_get_uint_handle(sub_dissectors, uint_entry.second);
+ if (handle != NULL) {
+ module = prefs_find_module(proto_get_protocol_filter_name(dissector_handle_get_protocol_index(handle)));
+ pref_value = prefs_find_preference(module, uint_entry.first);
+ if (pref_value != NULL) {
+ module->prefs_changed_flags |= prefs_get_effect_flags(pref_value);
+ reset_pref(pref_value);
+ }
+ }
+
+ dissector_reset_uint(uint_entry.first, uint_entry.second);
+ }
+ changed_uint_entries_.clear();
+ foreach (CharPtrPair char_ptr_entry, changed_string_entries_) {
+ dissector_reset_string(char_ptr_entry.first, char_ptr_entry.second);
+ }
+ changed_string_entries_.clear();
+
+ foreach(DecodeAsItem *item, decode_as_items_) {
+ decode_as_t *decode_as_entry;
+
+ if (item->currentDissector().isEmpty()) {
+ continue;
+ }
+
+ for (GList *cur = decode_as_list; cur; cur = cur->next) {
+ decode_as_entry = (decode_as_t *) cur->data;
+
+ if (!g_strcmp0(decode_as_entry->table_name, item->tableName())) {
+
+ ftenum_t selector_type = get_dissector_table_selector_type(item->tableName());
+ gconstpointer selector_value;
+ QByteArray byteArray;
+
+ switch (selector_type) {
+ case FT_UINT8:
+ case FT_UINT16:
+ case FT_UINT24:
+ case FT_UINT32:
+ selector_value = GUINT_TO_POINTER(item->selectorUint());
+ break;
+ case FT_STRING:
+ case FT_STRINGZ:
+ case FT_UINT_STRING:
+ case FT_STRINGZPAD:
+ case FT_STRINGZTRUNC:
+ byteArray = item->selectorString().toUtf8();
+ selector_value = (gconstpointer) byteArray.constData();
+ break;
+ case FT_NONE:
+ //selector value is ignored, but dissector table needs to happen
+ selector_value = NULL;
+ break;
+ case FT_GUID:
+ if (item->selectorDCERPC() != NULL) {
+ selector_value = (gconstpointer)item->selectorDCERPC();
+ } else {
+ //TODO: Support normal GUID dissector tables
+ selector_value = NULL;
+ }
+ break;
+ default:
+ continue;
+ }
+
+ if ((item->currentDissector() == item->defaultDissector())) {
+ decode_as_entry->reset_value(decode_as_entry->table_name, selector_value);
+ sub_dissectors = find_dissector_table(decode_as_entry->table_name);
+
+ /* For now, only numeric dissector tables can use preferences */
+ if (FT_IS_UINT(dissector_table_get_type(sub_dissectors))) {
+ if (item->dissectorHandle() != NULL) {
+ module = prefs_find_module(proto_get_protocol_filter_name(dissector_handle_get_protocol_index(item->dissectorHandle())));
+ pref_value = prefs_find_preference(module, decode_as_entry->table_name);
+ if (pref_value != NULL) {
+ module->prefs_changed_flags |= prefs_get_effect_flags(pref_value);
+ prefs_remove_decode_as_value(pref_value, item->selectorUint(), TRUE);
+ }
+ }
+ }
+ break;
+ } else {
+ decode_as_entry->change_value(decode_as_entry->table_name, selector_value, item->dissectorHandle(), item->currentDissector().toUtf8().constData());
+ sub_dissectors = find_dissector_table(decode_as_entry->table_name);
+
+ /* For now, only numeric dissector tables can use preferences */
+ if (item->dissectorHandle() != NULL) {
+ if (FT_IS_UINT(dissector_table_get_type(sub_dissectors))) {
+ module = prefs_find_module(proto_get_protocol_filter_name(dissector_handle_get_protocol_index(item->dissectorHandle())));
+ pref_value = prefs_find_preference(module, decode_as_entry->table_name);
+ if (pref_value != NULL) {
+ module->prefs_changed_flags |= prefs_get_effect_flags(pref_value);
+ prefs_add_decode_as_value(pref_value, item->selectorUint(), FALSE);
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ prefs_apply_all();
+}