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