File: | builds/wireshark/wireshark/ui/qt/models/dissector_tables_model.cpp |
Warning: | line 246, column 1 Potential leak of memory pointed to by 'ti' |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* dissector_tables_model.cpp | |||
2 | * | |||
3 | * Wireshark - Network traffic analyzer | |||
4 | * By Gerald Combs <gerald@wireshark.org> | |||
5 | * Copyright 1998 Gerald Combs | |||
6 | * | |||
7 | * SPDX-License-Identifier: GPL-2.0-or-later | |||
8 | */ | |||
9 | ||||
10 | #include <ui/qt/models/dissector_tables_model.h> | |||
11 | #include <epan/ftypes/ftypes.h> | |||
12 | #include <epan/packet.h> | |||
13 | ||||
14 | #include <ui/qt/utils/qt_ui_utils.h> | |||
15 | #include <ui/qt/utils/variant_pointer.h> | |||
16 | #include "main_application.h" | |||
17 | ||||
18 | static const char* CUSTOM_TABLE_NAME = "Custom Tables"; | |||
19 | static const char* INTEGER_TABLE_NAME = "Integer Tables"; | |||
20 | static const char* STRING_TABLE_NAME = "String Tables"; | |||
21 | static const char* HEURISTIC_TABLE_NAME = "Heuristic Tables"; | |||
22 | ||||
23 | class IntegerTablesItem : public DissectorTablesItem | |||
24 | { | |||
25 | public: | |||
26 | IntegerTablesItem(unsigned int value, ftenum_t type, int display, QString dissectorDescription, DissectorTablesItem* parent); | |||
27 | virtual ~IntegerTablesItem(); | |||
28 | ||||
29 | virtual bool lessThan(DissectorTablesItem &right) const; | |||
30 | ||||
31 | protected: | |||
32 | unsigned int value_; | |||
33 | }; | |||
34 | ||||
35 | ||||
36 | DissectorTablesItem::DissectorTablesItem(QString tableName, QString dissectorDescription, DissectorTablesItem* parent) : | |||
37 | ModelHelperTreeItem<DissectorTablesItem>(parent), | |||
38 | tableName_(tableName), | |||
39 | dissectorDescription_(dissectorDescription) | |||
40 | { | |||
41 | } | |||
42 | ||||
43 | DissectorTablesItem::~DissectorTablesItem() | |||
44 | { | |||
45 | } | |||
46 | ||||
47 | bool DissectorTablesItem::lessThan(DissectorTablesItem &right) const | |||
48 | { | |||
49 | if (tableName().compare(right.tableName(), Qt::CaseInsensitive) < 0) | |||
50 | return true; | |||
51 | ||||
52 | return false; | |||
53 | } | |||
54 | ||||
55 | ||||
56 | IntegerTablesItem::IntegerTablesItem(unsigned int value, ftenum_t type, int display, QString dissectorDescription, DissectorTablesItem* parent) | |||
57 | : DissectorTablesItem(QString(), dissectorDescription, parent) | |||
58 | , value_(value) | |||
59 | { | |||
60 | switch (display) | |||
61 | { | |||
62 | case BASE_OCT: | |||
63 | tableName_ = QStringLiteral("0%1")(QString(QtPrivate::qMakeStringPrivate(u"" "0%1"))).arg(value, 0, 8); | |||
64 | break; | |||
65 | case BASE_HEX: | |||
66 | int field_width; | |||
67 | ||||
68 | switch (type) | |||
69 | { | |||
70 | case FT_UINT8: | |||
71 | field_width = 2; | |||
72 | break; | |||
73 | case FT_UINT16: | |||
74 | field_width = 4; | |||
75 | break; | |||
76 | case FT_UINT24: | |||
77 | field_width = 6; | |||
78 | break; | |||
79 | case FT_UINT32: | |||
80 | default: | |||
81 | field_width = 8; | |||
82 | break; | |||
83 | } | |||
84 | ||||
85 | tableName_ = int_to_qstring(value, field_width, 16); | |||
86 | break; | |||
87 | case BASE_DEC: | |||
88 | default: | |||
89 | tableName_ = QString::number(value); | |||
90 | break; | |||
91 | } | |||
92 | } | |||
93 | ||||
94 | IntegerTablesItem::~IntegerTablesItem() | |||
95 | { | |||
96 | } | |||
97 | ||||
98 | bool IntegerTablesItem::lessThan(DissectorTablesItem &right) const | |||
99 | { | |||
100 | if (value_ == ((IntegerTablesItem&)right).value_) { | |||
101 | return DissectorTablesItem::lessThan(right); | |||
102 | } | |||
103 | ||||
104 | if (value_ < ((IntegerTablesItem&)right).value_) { | |||
105 | return true; | |||
106 | } | |||
107 | ||||
108 | return false; | |||
109 | } | |||
110 | ||||
111 | DissectorTablesModel::DissectorTablesModel(QObject *parent) : | |||
112 | QAbstractItemModel(parent), | |||
113 | root_(new DissectorTablesItem(QStringLiteral("ROOT")(QString(QtPrivate::qMakeStringPrivate(u"" "ROOT"))), QStringLiteral("ROOT")(QString(QtPrivate::qMakeStringPrivate(u"" "ROOT"))), NULL__null)) | |||
114 | { | |||
115 | populate(); | |||
116 | } | |||
117 | ||||
118 | DissectorTablesModel::~DissectorTablesModel() | |||
119 | { | |||
120 | delete root_; | |||
121 | } | |||
122 | ||||
123 | int DissectorTablesModel::rowCount(const QModelIndex &parent) const | |||
124 | { | |||
125 | DissectorTablesItem *parent_item; | |||
126 | if (parent.column() > 0) | |||
127 | return 0; | |||
128 | ||||
129 | if (!parent.isValid()) | |||
130 | parent_item = root_; | |||
131 | else | |||
132 | parent_item = static_cast<DissectorTablesItem*>(parent.internalPointer()); | |||
133 | ||||
134 | if (parent_item == NULL__null) | |||
135 | return 0; | |||
136 | ||||
137 | return parent_item->childCount(); | |||
138 | } | |||
139 | ||||
140 | int DissectorTablesModel::columnCount(const QModelIndex&) const | |||
141 | { | |||
142 | return colLast; | |||
143 | } | |||
144 | ||||
145 | QModelIndex DissectorTablesModel::parent(const QModelIndex& index) const | |||
146 | { | |||
147 | if (!index.isValid()) | |||
148 | return QModelIndex(); | |||
149 | ||||
150 | DissectorTablesItem* item = static_cast<DissectorTablesItem*>(index.internalPointer()); | |||
151 | if (item != NULL__null) { | |||
152 | DissectorTablesItem* parent_item = item->parentItem(); | |||
153 | if (parent_item != NULL__null) { | |||
154 | if (parent_item == root_) | |||
155 | return QModelIndex(); | |||
156 | ||||
157 | return createIndex(parent_item->row(), 0, parent_item); | |||
158 | } | |||
159 | } | |||
160 | ||||
161 | return QModelIndex(); | |||
162 | } | |||
163 | ||||
164 | QModelIndex DissectorTablesModel::index(int row, int column, const QModelIndex& parent) const | |||
165 | { | |||
166 | if (!hasIndex(row, column, parent)) | |||
167 | return QModelIndex(); | |||
168 | ||||
169 | DissectorTablesItem *parent_item, *child_item; | |||
170 | ||||
171 | if (!parent.isValid()) | |||
172 | parent_item = root_; | |||
173 | else | |||
174 | parent_item = static_cast<DissectorTablesItem*>(parent.internalPointer()); | |||
175 | ||||
176 | Q_ASSERT(parent_item)((parent_item) ? static_cast<void>(0) : qt_assert("parent_item" , "ui/qt/models/dissector_tables_model.cpp", 176)); | |||
177 | ||||
178 | child_item = parent_item->child(row); | |||
179 | if (child_item) { | |||
180 | return createIndex(row, column, child_item); | |||
181 | } | |||
182 | ||||
183 | return QModelIndex(); | |||
184 | } | |||
185 | ||||
186 | QVariant DissectorTablesModel::data(const QModelIndex &index, int role) const | |||
187 | { | |||
188 | if ((!index.isValid()) || (role != Qt::DisplayRole)) | |||
189 | return QVariant(); | |||
190 | ||||
191 | DissectorTablesItem* item = static_cast<DissectorTablesItem*>(index.internalPointer()); | |||
192 | if (item == NULL__null) | |||
193 | return QVariant(); | |||
194 | ||||
195 | switch ((enum DissectorTablesColumn)index.column()) | |||
196 | { | |||
197 | case colTableName: | |||
198 | return item->tableName(); | |||
199 | case colDissectorDescription: | |||
200 | return item->dissectorDescription(); | |||
201 | default: | |||
202 | break; | |||
203 | } | |||
204 | ||||
205 | return QVariant(); | |||
206 | } | |||
207 | ||||
208 | static void gatherProtocolDecodes(const char *short_name, ftenum_t selector_type, void *key, void *value, void *item_ptr) | |||
209 | { | |||
210 | DissectorTablesItem* pdl_ptr = (DissectorTablesItem*)item_ptr; | |||
211 | if (pdl_ptr == NULL__null) | |||
| ||||
212 | return; | |||
213 | ||||
214 | dtbl_entry_t *dtbl_entry = (dtbl_entry_t*)value; | |||
215 | dissector_handle_t handle = dtbl_entry_get_handle(dtbl_entry); | |||
216 | const QString dissector_description = dissector_handle_get_description(handle); | |||
217 | int display = get_dissector_table_param(short_name); | |||
218 | DissectorTablesItem *ti = NULL__null; | |||
219 | ||||
220 | switch (selector_type) { | |||
221 | case FT_UINT8: | |||
222 | case FT_UINT16: | |||
223 | case FT_UINT24: | |||
224 | case FT_UINT32: | |||
225 | ti = new IntegerTablesItem(GPOINTER_TO_UINT(key)((guint) (gulong) (key)), selector_type, display, dissector_description, pdl_ptr); | |||
226 | pdl_ptr->prependChild(ti); | |||
227 | break; | |||
228 | ||||
229 | case FT_STRING: | |||
230 | case FT_STRINGZ: | |||
231 | case FT_UINT_STRING: | |||
232 | case FT_STRINGZPAD: | |||
233 | case FT_STRINGZTRUNC: | |||
234 | ti = new DissectorTablesItem((const char *)key, dissector_description, pdl_ptr); | |||
235 | pdl_ptr->prependChild(ti); | |||
236 | break; | |||
237 | ||||
238 | case FT_BYTES: | |||
239 | ti = new DissectorTablesItem(dissector_handle_get_description(handle), dissector_description, pdl_ptr); | |||
240 | pdl_ptr->prependChild(ti); | |||
241 | break; | |||
242 | ||||
243 | default: | |||
244 | break; | |||
245 | } | |||
246 | } | |||
| ||||
247 | ||||
248 | struct tables_root | |||
249 | { | |||
250 | DissectorTablesItem* custom_table; | |||
251 | DissectorTablesItem* integer_table; | |||
252 | DissectorTablesItem* string_table; | |||
253 | }; | |||
254 | ||||
255 | static void gatherTableNames(const char *short_name, const char *table_name, void *model_ptr) | |||
256 | { | |||
257 | struct tables_root* tables = (struct tables_root*)model_ptr; | |||
258 | if (model_ptr == NULL__null) | |||
259 | return; | |||
260 | ||||
261 | ftenum_t selector_type = get_dissector_table_selector_type(short_name); | |||
262 | DissectorTablesItem *dt_ti = NULL__null; | |||
263 | ||||
264 | switch (selector_type) { | |||
265 | case FT_UINT8: | |||
266 | case FT_UINT16: | |||
267 | case FT_UINT24: | |||
268 | case FT_UINT32: | |||
269 | dt_ti = new DissectorTablesItem(table_name, short_name, tables->integer_table); | |||
270 | tables->integer_table->prependChild(dt_ti); | |||
271 | break; | |||
272 | case FT_STRING: | |||
273 | case FT_STRINGZ: | |||
274 | case FT_UINT_STRING: | |||
275 | case FT_STRINGZPAD: | |||
276 | case FT_STRINGZTRUNC: | |||
277 | dt_ti = new DissectorTablesItem(table_name, short_name, tables->string_table); | |||
278 | tables->string_table->prependChild(dt_ti); | |||
279 | break; | |||
280 | case FT_BYTES: | |||
281 | dt_ti = new DissectorTablesItem(table_name, short_name, tables->custom_table); | |||
282 | tables->custom_table->prependChild(dt_ti); | |||
283 | break; | |||
284 | default: | |||
285 | // Assert? | |||
286 | return; | |||
287 | } | |||
288 | ||||
289 | dissector_table_foreach(short_name, gatherProtocolDecodes, dt_ti); | |||
290 | } | |||
291 | ||||
292 | static void gatherHeurProtocolDecodes(const char *, struct heur_dtbl_entry *dtbl_entry, void *list_ptr) | |||
293 | { | |||
294 | DissectorTablesItem* hdl_ptr = (DissectorTablesItem*)list_ptr; | |||
295 | if (hdl_ptr == NULL__null) | |||
296 | return; | |||
297 | ||||
298 | if (dtbl_entry->protocol) { | |||
299 | QString longName = proto_get_protocol_long_name(dtbl_entry->protocol); | |||
300 | QString heurDisplayName = dtbl_entry->display_name; | |||
301 | if (! heurDisplayName.isEmpty()) | |||
302 | longName.append(QStringLiteral(" (%1)")(QString(QtPrivate::qMakeStringPrivate(u"" " (%1)"))).arg(heurDisplayName)); | |||
303 | ||||
304 | DissectorTablesItem *heur = new DissectorTablesItem(longName, proto_get_protocol_short_name(dtbl_entry->protocol), hdl_ptr); | |||
305 | hdl_ptr->prependChild(heur); | |||
306 | } | |||
307 | } | |||
308 | ||||
309 | static void gatherHeurTableNames(const char *table_name, heur_dissector_list *list, void *heur_tables) | |||
310 | { | |||
311 | DissectorTablesItem* table = (DissectorTablesItem*)heur_tables; | |||
312 | if (table == NULL__null) | |||
313 | return; | |||
314 | ||||
315 | QString desc_name = table_name; | |||
316 | if (list) { | |||
317 | const char *desc = heur_dissector_list_get_description(list); | |||
318 | if (desc) desc_name = desc; | |||
319 | } | |||
320 | DissectorTablesItem *heur = new DissectorTablesItem(desc_name, table_name, table); | |||
321 | table->prependChild(heur); | |||
322 | ||||
323 | if (list) { | |||
324 | heur_dissector_table_foreach(table_name, gatherHeurProtocolDecodes, heur); | |||
325 | } | |||
326 | } | |||
327 | ||||
328 | void DissectorTablesModel::populate() | |||
329 | { | |||
330 | beginResetModel(); | |||
331 | ||||
332 | struct tables_root tables; | |||
333 | ||||
334 | tables.custom_table = new DissectorTablesItem(tr(CUSTOM_TABLE_NAME), QString(""), root_); | |||
335 | root_->prependChild(tables.custom_table); | |||
336 | tables.integer_table = new DissectorTablesItem(tr(INTEGER_TABLE_NAME), QString(""), root_); | |||
337 | root_->prependChild(tables.integer_table); | |||
338 | tables.string_table = new DissectorTablesItem(tr(STRING_TABLE_NAME), QString(""), root_); | |||
339 | root_->prependChild(tables.string_table); | |||
340 | ||||
341 | dissector_all_tables_foreach_table(gatherTableNames, &tables, NULL__null); | |||
342 | ||||
343 | DissectorTablesItem* heuristic_table = new DissectorTablesItem(tr(HEURISTIC_TABLE_NAME), QString(""), root_); | |||
344 | root_->prependChild(heuristic_table); | |||
345 | ||||
346 | dissector_all_heur_tables_foreach_table(gatherHeurTableNames, heuristic_table, NULL__null); | |||
347 | ||||
348 | endResetModel(); | |||
349 | } | |||
350 | ||||
351 | ||||
352 | ||||
353 | ||||
354 | ||||
355 | DissectorTablesProxyModel::DissectorTablesProxyModel(QObject * parent) | |||
356 | : QSortFilterProxyModel(parent), | |||
357 | tableName_(tr("Table Type")), | |||
358 | dissectorDescription_(), | |||
359 | filter_() | |||
360 | { | |||
361 | } | |||
362 | ||||
363 | QVariant DissectorTablesProxyModel::headerData(int section, Qt::Orientation orientation, int role) const | |||
364 | { | |||
365 | if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { | |||
366 | ||||
367 | switch ((enum DissectorTablesModel::DissectorTablesColumn)section) { | |||
368 | case DissectorTablesModel::colTableName: | |||
369 | return tableName_; | |||
370 | case DissectorTablesModel::colDissectorDescription: | |||
371 | return dissectorDescription_; | |||
372 | default: | |||
373 | break; | |||
374 | } | |||
375 | } | |||
376 | return QVariant(); | |||
377 | } | |||
378 | ||||
379 | bool DissectorTablesProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const | |||
380 | { | |||
381 | //Use DissectorTablesItem directly for better performance | |||
382 | DissectorTablesItem* left_item = static_cast<DissectorTablesItem*>(left.internalPointer()); | |||
383 | DissectorTablesItem* right_item = static_cast<DissectorTablesItem*>(right.internalPointer()); | |||
384 | ||||
385 | if ((left_item != NULL__null) && (right_item != NULL__null)) { | |||
386 | return left_item->lessThan(*right_item); | |||
387 | } | |||
388 | ||||
389 | return false; | |||
390 | } | |||
391 | ||||
392 | // NOLINTNEXTLINE(misc-no-recursion) | |||
393 | bool DissectorTablesProxyModel::filterAcceptItem(DissectorTablesItem& item) const | |||
394 | { | |||
395 | if (filter_.isEmpty()) | |||
396 | return true; | |||
397 | ||||
398 | if (item.tableName().contains(filter_, Qt::CaseInsensitive) || item.dissectorDescription().contains(filter_, Qt::CaseInsensitive)) | |||
399 | return true; | |||
400 | ||||
401 | DissectorTablesItem *child_item; | |||
402 | for (int child_row = 0; child_row < item.childCount(); child_row++) | |||
403 | { | |||
404 | child_item = item.child(child_row); | |||
405 | // We recurse here, but the tree is only three levels deep | |||
406 | if ((child_item != NULL__null) && (filterAcceptItem(*child_item))) | |||
407 | return true; | |||
408 | } | |||
409 | ||||
410 | return false; | |||
411 | } | |||
412 | ||||
413 | bool DissectorTablesProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const | |||
414 | { | |||
415 | QModelIndex nameIdx = sourceModel()->index(sourceRow, DissectorTablesModel::colTableName, sourceParent); | |||
416 | DissectorTablesItem* item = static_cast<DissectorTablesItem*>(nameIdx.internalPointer()); | |||
417 | if (item == NULL__null) | |||
418 | return false; | |||
419 | ||||
420 | if (filterAcceptItem(*item)) | |||
421 | return true; | |||
422 | ||||
423 | return false; | |||
424 | } | |||
425 | ||||
426 | void DissectorTablesProxyModel::setFilter(const QString& filter) | |||
427 | { | |||
428 | #if QT_VERSION((6<<16)|(4<<8)|(2)) >= QT_VERSION_CHECK(6, 9, 0)((6<<16)|(9<<8)|(0)) | |||
429 | beginFilterChange(); | |||
430 | #endif | |||
431 | filter_ = filter; | |||
432 | #if QT_VERSION((6<<16)|(4<<8)|(2)) >= QT_VERSION_CHECK(6, 10, 0)((6<<16)|(10<<8)|(0)) | |||
433 | endFilterChange(QSortFilterProxyModel::Direction::Rows); | |||
434 | #else | |||
435 | invalidateFilter(); | |||
436 | #endif | |||
437 | } | |||
438 | ||||
439 | void DissectorTablesProxyModel::adjustHeader(const QModelIndex ¤tIndex) | |||
440 | { | |||
441 | tableName_ = tr("Table Type"); | |||
442 | dissectorDescription_ = QString(); | |||
443 | if (currentIndex.isValid() && currentIndex.parent().isValid()) { | |||
444 | QString table; | |||
445 | ||||
446 | if (currentIndex.parent().parent().isValid()) { | |||
447 | table = data(index(currentIndex.parent().parent().row(), DissectorTablesModel::colTableName), Qt::DisplayRole).toString(); | |||
448 | if ((table.compare(CUSTOM_TABLE_NAME) == 0) || | |||
449 | (table.compare(STRING_TABLE_NAME) == 0)) { | |||
450 | tableName_ = tr("String"); | |||
451 | dissectorDescription_ = tr("Dissector Description"); | |||
452 | } else if (table.compare(INTEGER_TABLE_NAME) == 0) { | |||
453 | tableName_ = tr("Integer"); | |||
454 | dissectorDescription_ = tr("Dissector Description"); | |||
455 | } else if (table.compare(HEURISTIC_TABLE_NAME) == 0) { | |||
456 | tableName_ = tr("Protocol"); | |||
457 | dissectorDescription_ = tr("Short Name"); | |||
458 | } | |||
459 | } else { | |||
460 | table = data(index(currentIndex.parent().row(), DissectorTablesModel::colTableName), Qt::DisplayRole).toString(); | |||
461 | if ((table.compare(CUSTOM_TABLE_NAME) == 0) || | |||
462 | (table.compare(INTEGER_TABLE_NAME) == 0) || | |||
463 | (table.compare(STRING_TABLE_NAME) == 0)) { | |||
464 | tableName_ = tr("Table Name"); | |||
465 | dissectorDescription_ = tr("Selector Name"); | |||
466 | } else if (table.compare(HEURISTIC_TABLE_NAME) == 0) { | |||
467 | tableName_ = tr("Protocol"); | |||
468 | dissectorDescription_ = tr("Short Name"); | |||
469 | } | |||
470 | } | |||
471 | } | |||
472 | ||||
473 | ||||
474 | emit headerDataChanged(Qt::Vertical, 0, 1); | |||
475 | } |