Bug Summary

File:epan/prefs.c
Warning:line 4782, column 21
Value of 'errno' was not checked and may be overwritten by function 'getc_unlocked'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name prefs.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-21/lib/clang/21 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/epan -isystem /builds/wireshark/wireshark/build/epan -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /usr/include/lua5.4 -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -D epan_EXPORTS -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -I /builds/wireshark/wireshark/wiretap -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-truncation -Wno-format-nonliteral -Wno-pointer-sign -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2025-11-07-100324-3624-1 -x c /builds/wireshark/wireshark/epan/prefs.c
1/* prefs.c
2 * Routines for handling preferences
3 *
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
7 *
8 * SPDX-License-Identifier: GPL-2.0-or-later
9 */
10
11#include "config.h"
12#define WS_LOG_DOMAIN"Epan" LOG_DOMAIN_EPAN"Epan"
13
14#include "ws_diag_control.h"
15
16#include <stdlib.h>
17#include <string.h>
18#include <errno(*__errno_location ()).h>
19#ifdef _WIN32
20#include <windows.h>
21#endif
22
23#include <glib.h>
24
25#include <stdio.h>
26#include <wsutil/filesystem.h>
27#include <epan/addr_resolv.h>
28#include <epan/oids.h>
29#include <epan/maxmind_db.h>
30#include <epan/packet.h>
31#include <epan/prefs.h>
32#include <epan/proto.h>
33#include <epan/strutil.h>
34#include <epan/column.h>
35#include <epan/decode_as.h>
36#include <ui/capture_opts.h>
37#include <wsutil/file_util.h>
38#include <wsutil/report_message.h>
39#include <wsutil/wslog.h>
40#include <wsutil/ws_assert.h>
41#include <wsutil/array.h>
42
43#include <epan/prefs-int.h>
44#include <epan/uat-int.h>
45
46#include "epan/filter_expressions.h"
47#include "epan/aggregation_fields.h"
48
49#include "epan/wmem_scopes.h"
50#include <epan/stats_tree.h>
51
52#define REG_HKCU_WIRESHARK_KEY"Software\\Wireshark" "Software\\Wireshark"
53
54/*
55 * Module alias.
56 */
57typedef struct pref_module_alias {
58 const char *name; /**< name of module alias */
59 module_t *module; /**< module for which it's an alias */
60} module_alias_t;
61
62/* Internal functions */
63static module_t *find_subtree(module_t *parent, const char *tilte);
64static module_t *prefs_register_module_or_subtree(module_t *parent,
65 const char *name, const char *title, const char *description, const char *help,
66 bool_Bool is_subtree, void (*apply_cb)(void), bool_Bool use_gui);
67static void prefs_register_modules(void);
68static module_t *prefs_find_module_alias(const char *name);
69static prefs_set_pref_e set_pref(char*, const char*, void *, bool_Bool);
70static void free_col_info(GList *);
71static void prefs_set_global_defaults(const char** col_fmt, int num_cols);
72static bool_Bool prefs_is_column_visible(const char *cols_hidden, int col);
73static bool_Bool prefs_is_column_fmt_visible(const char *cols_hidden, fmt_data *cfmt);
74static unsigned prefs_module_list_foreach(wmem_tree_t *module_list, module_cb callback,
75 void *user_data, bool_Bool skip_obsolete);
76static int find_val_for_string(const char *needle, const enum_val_t *haystack, int default_value);
77
78#define PF_NAME"preferences" "preferences"
79#define OLD_GPF_NAME"wireshark.conf" "wireshark.conf" /* old name for global preferences file */
80
81static char *gpf_path;
82static char *cols_hidden_list;
83static char *cols_hidden_fmt_list;
84static bool_Bool gui_theme_is_dark;
85
86/*
87 * XXX - variables to allow us to attempt to interpret the first
88 * "mgcp.{tcp,udp}.port" in a preferences file as
89 * "mgcp.{tcp,udp}.gateway_port" and the second as
90 * "mgcp.{tcp,udp}.callagent_port".
91 */
92static int mgcp_tcp_port_count;
93static int mgcp_udp_port_count;
94
95e_prefs prefs;
96
97static const enum_val_t gui_console_open_type[] = {
98 {"NEVER", "NEVER", LOG_CONSOLE_OPEN_NEVER},
99 {"AUTOMATIC", "AUTOMATIC", LOG_CONSOLE_OPEN_AUTO},
100 {"ALWAYS", "ALWAYS", LOG_CONSOLE_OPEN_ALWAYS},
101 {NULL((void*)0), NULL((void*)0), -1}
102};
103
104static const enum_val_t gui_version_placement_type[] = {
105 {"WELCOME", "WELCOME", version_welcome_only},
106 {"TITLE", "TITLE", version_title_only},
107 {"BOTH", "BOTH", version_both},
108 {"NEITHER", "NEITHER", version_neither},
109 {NULL((void*)0), NULL((void*)0), -1}
110};
111
112static const enum_val_t gui_fileopen_style[] = {
113 {"LAST_OPENED", "LAST_OPENED", FO_STYLE_LAST_OPENED0},
114 {"SPECIFIED", "SPECIFIED", FO_STYLE_SPECIFIED1},
115 {"CWD", "CWD", FO_STYLE_CWD2},
116 {NULL((void*)0), NULL((void*)0), -1}
117};
118
119static const enum_val_t gui_toolbar_style[] = {
120 {"ICONS", "ICONS", 0},
121 {"TEXT", "TEXT", 1},
122 {"BOTH", "BOTH", 2},
123 {NULL((void*)0), NULL((void*)0), -1}
124};
125
126static const enum_val_t gui_layout_content[] = {
127 {"NONE", "NONE", 0},
128 {"PLIST", "PLIST", 1},
129 {"PDETAILS", "PDETAILS", 2},
130 {"PBYTES", "PBYTES", 3},
131 {"PDIAGRAM", "PDIAGRAM", 4},
132 {NULL((void*)0), NULL((void*)0), -1}
133};
134
135static const enum_val_t gui_packet_dialog_layout[] = {
136 {"vertical", "Vertical (Stacked)", layout_vertical},
137 {"horizontal", "Horizontal (Side-by-side)", layout_horizontal},
138 {NULL((void*)0), NULL((void*)0), -1}
139};
140
141static const enum_val_t gui_update_channel[] = {
142 {"DEVELOPMENT", "DEVELOPMENT", UPDATE_CHANNEL_DEVELOPMENT},
143 {"STABLE", "STABLE", UPDATE_CHANNEL_STABLE},
144 {NULL((void*)0), NULL((void*)0), -1}
145};
146
147static const enum_val_t gui_selection_style[] = {
148 {"DEFAULT", "DEFAULT", COLOR_STYLE_DEFAULT0},
149 {"FLAT", "FLAT", COLOR_STYLE_FLAT1},
150 {"GRADIENT", "GRADIENT", COLOR_STYLE_GRADIENT2},
151 {NULL((void*)0), NULL((void*)0), -1}
152};
153
154static const enum_val_t gui_color_scheme[] = {
155 {"system", "System Default", COLOR_SCHEME_DEFAULT0},
156 {"light", "Light Mode", COLOR_SCHEME_LIGHT1},
157 {"dark", "Dark Mode", COLOR_SCHEME_DARK2},
158 {NULL((void*)0), NULL((void*)0), -1}
159};
160
161static const enum_val_t gui_packet_list_copy_format_options_for_keyboard_shortcut[] = {
162 {"TEXT", "Text", COPY_FORMAT_TEXT},
163 {"CSV", "CSV", COPY_FORMAT_CSV},
164 {"YAML", "YAML", COPY_FORMAT_YAML},
165 {"HTML", "HTML", COPY_FORMAT_HTML},
166 {NULL((void*)0), NULL((void*)0), -1}
167};
168
169/* None : Historical behavior, no deinterlacing */
170#define CONV_DEINT_CHOICE_NONE0 0
171/* MI : MAC & Interface */
172#define CONV_DEINT_CHOICE_MI0x04 + 0x02 CONV_DEINT_KEY_MAC0x04 + CONV_DEINT_KEY_INTERFACE0x02
173/* VM : VLAN & MAC */
174#define CONV_DEINT_CHOICE_VM0x08 + 0x04 CONV_DEINT_KEY_VLAN0x08 + CONV_DEINT_KEY_MAC0x04
175/* VMI : VLAN & MAC & Interface */
176#define CONV_DEINT_CHOICE_VMI0x08 + 0x04 + 0x02 CONV_DEINT_KEY_VLAN0x08 + CONV_DEINT_KEY_MAC0x04 + CONV_DEINT_KEY_INTERFACE0x02
177
178static const enum_val_t conv_deint_options[] = {
179 {"NONE", "NONE", CONV_DEINT_CHOICE_NONE0},
180 {".MI", ".MI", CONV_DEINT_CHOICE_MI0x04 + 0x02 },
181 {"VM.", "VM.", CONV_DEINT_CHOICE_VM0x08 + 0x04 },
182 {"VMI", "VMI", CONV_DEINT_CHOICE_VMI0x08 + 0x04 + 0x02 },
183 {NULL((void*)0), NULL((void*)0), -1}
184};
185
186static const enum_val_t abs_time_format_options[] = {
187 {"NEVER", "Never", ABS_TIME_ASCII_NEVER},
188 {"TREE", "Protocol tree only", ABS_TIME_ASCII_TREE},
189 {"COLUMN", "Protocol tree and columns", ABS_TIME_ASCII_COLUMN},
190 {"ALWAYS", "Always", ABS_TIME_ASCII_ALWAYS},
191 {NULL((void*)0), NULL((void*)0), -1}
192};
193
194static int num_capture_cols = 7;
195static const char *capture_cols[7] = {
196 "INTERFACE",
197 "LINK",
198 "PMODE",
199 "SNAPLEN",
200 "MONITOR",
201 "BUFFER",
202 "FILTER"
203};
204#define CAPTURE_COL_TYPE_DESCRIPTION"Possible values: INTERFACE, LINK, PMODE, SNAPLEN, MONITOR, BUFFER, FILTER\n" \
205 "Possible values: INTERFACE, LINK, PMODE, SNAPLEN, MONITOR, BUFFER, FILTER\n"
206
207static const enum_val_t gui_packet_list_elide_mode[] = {
208 {"LEFT", "LEFT", ELIDE_LEFT},
209 {"RIGHT", "RIGHT", ELIDE_RIGHT},
210 {"MIDDLE", "MIDDLE", ELIDE_MIDDLE},
211 {"NONE", "NONE", ELIDE_NONE},
212 {NULL((void*)0), NULL((void*)0), -1}
213};
214
215/** Struct to hold preference data */
216struct preference {
217 const char *name; /**< name of preference */
218 const char *title; /**< title to use in GUI */
219 const char *description; /**< human-readable description of preference */
220 int ordinal; /**< ordinal number of this preference */
221 pref_type_e type; /**< type of that preference */
222 bool_Bool obsolete; /**< obsolete preference flag */
223 unsigned int effect_flags; /**< Flags of types effected by preference (PREF_TYPE_DISSECTION, PREF_EFFECT_CAPTURE, etc).
224 Flags must be non-zero to ensure saving to disk */
225 union { /* The Qt preference code assumes that these will all be pointers (and unique) */
226 unsigned *uint;
227 bool_Bool *boolp;
228 int *enump;
229 char **string;
230 range_t **range;
231 struct epan_uat* uat;
232 color_t *colorp;
233 GList** list;
234 } varp; /**< pointer to variable storing the value */
235 union {
236 unsigned uint;
237 bool_Bool boolval;
238 int enumval;
239 char *string;
240 range_t *range;
241 color_t color;
242 GList* list;
243 } stashed_val; /**< original value, when editing from the GUI */
244 union {
245 unsigned uint;
246 bool_Bool boolval;
247 int enumval;
248 char *string;
249 range_t *range;
250 color_t color;
251 GList* list;
252 } default_val; /**< the default value of the preference */
253 union {
254 unsigned base; /**< input/output base, for PREF_UINT */
255 uint32_t max_value; /**< maximum value of a range */
256 struct {
257 const enum_val_t *enumvals; /**< list of name & values */
258 bool_Bool radio_buttons; /**< true if it should be shown as
259 radio buttons rather than as an
260 option menu or combo box in
261 the preferences tab */
262 } enum_info; /**< for PREF_ENUM */
263 } info; /**< display/text file information */
264 struct pref_custom_cbs custom_cbs; /**< for PREF_CUSTOM */
265 const char *dissector_table; /**< for PREF_DECODE_AS_RANGE */
266 const char *dissector_desc; /**< for PREF_DECODE_AS_RANGE */
267};
268
269const char* prefs_get_description(pref_t *pref)
270{
271 return pref->description;
272}
273
274const char* prefs_get_title(pref_t *pref)
275{
276 return pref->title;
277}
278
279int prefs_get_type(pref_t *pref)
280{
281 return pref->type;
282}
283
284const char* prefs_get_name(pref_t *pref)
285{
286 return pref->name;
287}
288
289uint32_t prefs_get_max_value(pref_t *pref)
290{
291 return pref->info.max_value;
292}
293
294const char* prefs_get_dissector_table(pref_t *pref)
295{
296 return pref->dissector_table;
297}
298
299static const char* prefs_get_dissector_description(pref_t *pref)
300{
301 return pref->dissector_desc;
302}
303
304/*
305 * List of all modules with preference settings.
306 */
307static wmem_tree_t *prefs_modules;
308
309/*
310 * List of all modules that should show up at the top level of the
311 * tree in the preference dialog box.
312 */
313static wmem_tree_t *prefs_top_level_modules;
314
315/*
316 * List of aliases for modules.
317 */
318static wmem_tree_t *prefs_module_aliases;
319
320/** Sets up memory used by proto routines. Called at program startup */
321void
322prefs_init(const char** col_fmt, int num_cols)
323{
324 memset(&prefs, 0, sizeof(prefs));
325 prefs_modules = wmem_tree_new(wmem_epan_scope());
326 prefs_top_level_modules = wmem_tree_new(wmem_epan_scope());
327 prefs_module_aliases = wmem_tree_new(wmem_epan_scope());
328
329 prefs_set_global_defaults(col_fmt, num_cols);
330 prefs_register_modules();
331}
332
333/*
334 * Free the strings for a string-like preference.
335 */
336static void
337free_string_like_preference(pref_t *pref)
338{
339 g_free(*pref->varp.string);
340 *pref->varp.string = NULL((void*)0);
341 g_free(pref->default_val.string);
342 pref->default_val.string = NULL((void*)0);
343}
344
345static void
346free_pref(void *data, void *user_data _U___attribute__((unused)))
347{
348 pref_t *pref = (pref_t *)data;
349
350 switch (pref->type) {
351 case PREF_BOOL:
352 case PREF_ENUM:
353 case PREF_UINT:
354 case PREF_STATIC_TEXT:
355 case PREF_UAT:
356 case PREF_COLOR:
357 break;
358 case PREF_STRING:
359 case PREF_SAVE_FILENAME:
360 case PREF_OPEN_FILENAME:
361 case PREF_DIRNAME:
362 case PREF_PASSWORD:
363 case PREF_DISSECTOR:
364 free_string_like_preference(pref);
365 break;
366 case PREF_RANGE:
367 case PREF_DECODE_AS_RANGE:
368 wmem_free(wmem_epan_scope(), *pref->varp.range);
369 *pref->varp.range = NULL((void*)0);
370 wmem_free(wmem_epan_scope(), pref->default_val.range);
371 pref->default_val.range = NULL((void*)0);
372 break;
373 case PREF_CUSTOM:
374 if (strcmp(pref->name, "columns") == 0)
375 pref->stashed_val.boolval = true1;
376 pref->custom_cbs.free_cb(pref);
377 break;
378 /* non-generic preferences */
379 case PREF_PROTO_TCP_SNDAMB_ENUM:
380 break;
381 }
382
383 g_free(pref);
384}
385
386static unsigned
387free_module_prefs(module_t *module, void *data _U___attribute__((unused)))
388{
389 if (module->prefs) {
390 g_list_foreach(module->prefs, free_pref, NULL((void*)0));
391 g_list_free(module->prefs);
392 }
393 module->prefs = NULL((void*)0);
394 module->numprefs = 0;
395 if (module->submodules) {
396 prefs_module_list_foreach(module->submodules, free_module_prefs, NULL((void*)0), false0);
397 }
398 /* We don't free the actual module: its submodules pointer points to
399 a wmem_tree and the module itself is stored in a wmem_tree
400 */
401
402 return 0;
403}
404
405/** Frees memory used by proto routines. Called at program shutdown */
406void
407prefs_cleanup(void)
408{
409 /* This isn't strictly necessary since we're exiting anyway, but let's
410 * do what clean up we can.
411 */
412 prefs_module_list_foreach(prefs_modules, free_module_prefs, NULL((void*)0), false0);
413
414 /* Clean the uats */
415 uat_cleanup();
416
417 /* Shut down mmdbresolve */
418 maxmind_db_pref_cleanup();
419
420 g_free(prefs.saved_at_version);
421 g_free(gpf_path);
422 gpf_path = NULL((void*)0);
423}
424
425void prefs_set_gui_theme_is_dark(bool_Bool is_dark)
426{
427 gui_theme_is_dark = is_dark;
428}
429
430/*
431 * Register a module that will have preferences.
432 * Specify the module under which to register it or NULL to register it
433 * at the top level, the name used for the module in the preferences file,
434 * the title used in the tab for it in a preferences dialog box, and a
435 * routine to call back when we apply the preferences.
436 */
437static module_t *
438prefs_register_module(module_t *parent, const char *name, const char *title,
439 const char *description, const char *help, void (*apply_cb)(void),
440 const bool_Bool use_gui)
441{
442 return prefs_register_module_or_subtree(parent, name, title, description, help,
443 false0, apply_cb, use_gui);
444}
445
446static void
447prefs_deregister_module(module_t *parent, const char *name, const char *title)
448{
449 /* Remove this module from the list of all modules */
450 module_t *module = (module_t *)wmem_tree_remove_string(prefs_modules, name, WMEM_TREE_STRING_NOCASE0x00000001);
451
452 if (!module)
453 return;
454
455 if (parent == NULL((void*)0)) {
456 /* Remove from top */
457 wmem_tree_remove_string(prefs_top_level_modules, title, WMEM_TREE_STRING_NOCASE0x00000001);
458 } else if (parent->submodules) {
459 /* Remove from parent */
460 wmem_tree_remove_string(parent->submodules, title, WMEM_TREE_STRING_NOCASE0x00000001);
461 }
462
463 free_module_prefs(module, NULL((void*)0));
464 wmem_free(wmem_epan_scope(), module);
465}
466
467/*
468 * Register a subtree that will have modules under it.
469 * Specify the module under which to register it or NULL to register it
470 * at the top level and the title used in the tab for it in a preferences
471 * dialog box.
472 */
473static module_t *
474prefs_register_subtree(module_t *parent, const char *title, const char *description,
475 void (*apply_cb)(void))
476{
477 return prefs_register_module_or_subtree(parent, NULL((void*)0), title, description, NULL((void*)0),
478 true1, apply_cb,
479 parent ? parent->use_gui : false0);
480}
481
482static module_t *
483prefs_register_module_or_subtree(module_t *parent, const char *name,
484 const char *title, const char *description,
485 const char *help,
486 bool_Bool is_subtree, void (*apply_cb)(void),
487 bool_Bool use_gui)
488{
489 module_t *module;
490
491 /* this module may have been created as a subtree item previously */
492 if ((module = find_subtree(parent, title))) {
493 /* the module is currently a subtree */
494 module->name = name;
495 module->apply_cb = apply_cb;
496 module->description = description;
497 module->help = help;
498
499 /* Registering it as a module (not just as a subtree) twice is an
500 * error in the code for the same reason as below. */
501 if (prefs_find_module(name) != NULL((void*)0)) {
502 ws_error("Preference module \"%s\" is being registered twice", name)ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 502
, __func__, "Preference module \"%s\" is being registered twice"
, name)
;
503 }
504 wmem_tree_insert_string(prefs_modules, name, module,
505 WMEM_TREE_STRING_NOCASE0x00000001);
506
507 return module;
508 }
509
510 module = wmem_new(wmem_epan_scope(), module_t)((module_t*)wmem_alloc((wmem_epan_scope()), sizeof(module_t))
)
;
511 module->name = name;
512 module->title = title;
513 module->description = description;
514 module->help = help;
515 module->apply_cb = apply_cb;
516 module->prefs = NULL((void*)0); /* no preferences, to start */
517 module->parent = parent;
518 module->submodules = NULL((void*)0); /* no submodules, to start */
519 module->numprefs = 0;
520 module->prefs_changed_flags = 0;
521 module->obsolete = false0;
522 module->use_gui = use_gui;
523 /* A module's preferences affects dissection unless otherwise told */
524 module->effect_flags = PREF_EFFECT_DISSECTION(1u << 0);
525
526 /*
527 * Do we have a module name?
528 */
529 if (name != NULL((void*)0)) {
530
531 /* Accept any letter case to conform with protocol names. ASN1 protocols
532 * don't use lower case names, so we can't require lower case. */
533 if (module_check_valid_name(name, false0) != '\0') {
534 ws_error("Preference module \"%s\" contains invalid characters", name)ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 534
, __func__, "Preference module \"%s\" contains invalid characters"
, name)
;
535 }
536
537 /*
538 * Make sure there's not already a module with that
539 * name. Crash if there is, as that's an error in the
540 * code, and the code has to be fixed not to register
541 * more than one module with the same name.
542 *
543 * We search the list of all modules; the subtree stuff
544 * doesn't require preferences in subtrees to have names
545 * that reflect the subtree they're in (that would require
546 * protocol preferences to have a bogus "protocol.", or
547 * something such as that, to be added to all their names).
548 */
549 if (prefs_find_module(name) != NULL((void*)0))
550 ws_error("Preference module \"%s\" is being registered twice", name)ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 550
, __func__, "Preference module \"%s\" is being registered twice"
, name)
;
551
552 /*
553 * Insert this module in the list of all modules.
554 */
555 wmem_tree_insert_string(prefs_modules, name, module, WMEM_TREE_STRING_NOCASE0x00000001);
556 } else {
557 /*
558 * This has no name, just a title; check to make sure it's a
559 * subtree, and crash if it's not.
560 */
561 if (!is_subtree)
562 ws_error("Preferences module with no name is being registered at the top level")ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 562
, __func__, "Preferences module with no name is being registered at the top level"
)
;
563 }
564
565 /*
566 * Insert this module into the appropriate place in the display
567 * tree.
568 */
569 if (parent == NULL((void*)0)) {
570 /*
571 * It goes at the top.
572 */
573 wmem_tree_insert_string(prefs_top_level_modules, title, module, WMEM_TREE_STRING_NOCASE0x00000001);
574 } else {
575 /*
576 * It goes into the list for this module.
577 */
578
579 if (parent->submodules == NULL((void*)0))
580 parent->submodules = wmem_tree_new(wmem_epan_scope());
581
582 wmem_tree_insert_string(parent->submodules, title, module, WMEM_TREE_STRING_NOCASE0x00000001);
583 }
584
585 return module;
586}
587
588void
589prefs_register_module_alias(const char *name, module_t *module)
590{
591 module_alias_t *alias;
592
593 /*
594 * Accept any name that can occur in protocol names. We allow upper-case
595 * letters, to handle the Diameter dissector having used "Diameter" rather
596 * than "diameter" as its preference module name in the past.
597 *
598 * Crash if the name is invalid, as that's an error in the code, but the name
599 * can be used on the command line, and shouldn't require quoting, etc.
600 */
601 if (module_check_valid_name(name, false0) != '\0') {
602 ws_error("Preference module alias \"%s\" contains invalid characters", name)ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 602
, __func__, "Preference module alias \"%s\" contains invalid characters"
, name)
;
603 }
604
605 /*
606 * Make sure there's not already an alias with that
607 * name. Crash if there is, as that's an error in the
608 * code, and the code has to be fixed not to register
609 * more than one alias with the same name.
610 *
611 * We search the list of all aliases.
612 */
613 if (prefs_find_module_alias(name) != NULL((void*)0))
614 ws_error("Preference module alias \"%s\" is being registered twice", name)ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 614
, __func__, "Preference module alias \"%s\" is being registered twice"
, name)
;
615
616 alias = wmem_new(wmem_epan_scope(), module_alias_t)((module_alias_t*)wmem_alloc((wmem_epan_scope()), sizeof(module_alias_t
)))
;
617 alias->name = name;
618 alias->module = module;
619
620 /*
621 * Insert this module in the list of all modules.
622 */
623 wmem_tree_insert_string(prefs_module_aliases, name, alias, WMEM_TREE_STRING_NOCASE0x00000001);
624}
625
626/*
627 * Register that a protocol has preferences.
628 */
629static module_t *protocols_module;
630
631module_t *
632prefs_register_protocol(int id, void (*apply_cb)(void))
633{
634 protocol_t *protocol = find_protocol_by_id(id);
635 if (protocol == NULL((void*)0))
636 ws_error("Protocol preferences being registered with an invalid protocol ID")ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 636
, __func__, "Protocol preferences being registered with an invalid protocol ID"
)
;
637 return prefs_register_module(protocols_module,
638 proto_get_protocol_filter_name(id),
639 proto_get_protocol_short_name(protocol),
640 proto_get_protocol_name(id), NULL((void*)0), apply_cb, true1);
641}
642
643void
644prefs_deregister_protocol (int id)
645{
646 protocol_t *protocol = find_protocol_by_id(id);
647 if (protocol == NULL((void*)0))
648 ws_error("Protocol preferences being de-registered with an invalid protocol ID")ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 648
, __func__, "Protocol preferences being de-registered with an invalid protocol ID"
)
;
649 prefs_deregister_module (protocols_module,
650 proto_get_protocol_filter_name(id),
651 proto_get_protocol_short_name(protocol));
652}
653
654module_t *
655prefs_register_protocol_subtree(const char *subtree, int id, void (*apply_cb)(void))
656{
657 protocol_t *protocol;
658 module_t *subtree_module;
659 module_t *new_module;
660 char *sep = NULL((void*)0), *ptr = NULL((void*)0), *orig = NULL((void*)0);
661
662 subtree_module = protocols_module;
663
664 if (subtree) {
665 /* take a copy of the buffer, orig keeps a base pointer while ptr
666 * walks through the string */
667 orig = ptr = g_strdup(subtree)g_strdup_inline (subtree);
668
669 while (ptr && *ptr) {
670
671 if ((sep = strchr(ptr, '/')))
672 *sep++ = '\0';
673
674 if (!(new_module = find_subtree(subtree_module, ptr))) {
675 /*
676 * There's no such module; create it, with the description
677 * being the name (if it's later registered explicitly
678 * with a description, that will override it).
679 */
680 ptr = wmem_strdup(wmem_epan_scope(), ptr);
681 new_module = prefs_register_subtree(subtree_module, ptr, ptr, NULL((void*)0));
682 }
683
684 subtree_module = new_module;
685 ptr = sep;
686
687 }
688
689 g_free(orig);
690 }
691
692 protocol = find_protocol_by_id(id);
693 if (protocol == NULL((void*)0))
694 ws_error("Protocol subtree being registered with an invalid protocol ID")ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 694
, __func__, "Protocol subtree being registered with an invalid protocol ID"
)
;
695 return prefs_register_module(subtree_module,
696 proto_get_protocol_filter_name(id),
697 proto_get_protocol_short_name(protocol),
698 proto_get_protocol_name(id), NULL((void*)0), apply_cb, true1);
699}
700
701
702/*
703 * Register that a protocol used to have preferences but no longer does,
704 * by creating an "obsolete" module for it.
705 */
706module_t *
707prefs_register_protocol_obsolete(int id)
708{
709 module_t *module;
710 protocol_t *protocol = find_protocol_by_id(id);
711 if (protocol == NULL((void*)0))
712 ws_error("Protocol being registered with an invalid protocol ID")ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 712
, __func__, "Protocol being registered with an invalid protocol ID"
)
;
713 module = prefs_register_module(protocols_module,
714 proto_get_protocol_filter_name(id),
715 proto_get_protocol_short_name(protocol),
716 proto_get_protocol_name(id), NULL((void*)0), NULL((void*)0), true1);
717 module->obsolete = true1;
718 return module;
719}
720
721/*
722 * Register that a statistical tap has preferences.
723 *
724 * "name" is a name for the tap to use on the command line with "-o"
725 * and in preference files.
726 *
727 * "title" is a short human-readable name for the tap.
728 *
729 * "description" is a longer human-readable description of the tap.
730 */
731module_t *stats_module;
732
733module_t *
734prefs_register_stat(const char *name, const char *title,
735 const char *description, void (*apply_cb)(void))
736{
737 return prefs_register_module(stats_module, name, title, description, NULL((void*)0),
738 apply_cb, true1);
739}
740
741/*
742 * Register that a codec has preferences.
743 *
744 * "name" is a name for the codec to use on the command line with "-o"
745 * and in preference files.
746 *
747 * "title" is a short human-readable name for the codec.
748 *
749 * "description" is a longer human-readable description of the codec.
750 */
751module_t *codecs_module;
752
753module_t *
754prefs_register_codec(const char *name, const char *title,
755 const char *description, void (*apply_cb)(void))
756{
757 return prefs_register_module(codecs_module, name, title, description, NULL((void*)0),
758 apply_cb, true1);
759}
760
761module_t *
762prefs_find_module(const char *name)
763{
764 return (module_t *)wmem_tree_lookup_string(prefs_modules, name, WMEM_TREE_STRING_NOCASE0x00000001);
765}
766
767static module_t *
768find_subtree(module_t *parent, const char *name)
769{
770 return (module_t *)wmem_tree_lookup_string(parent ? parent->submodules : prefs_top_level_modules, name, WMEM_TREE_STRING_NOCASE0x00000001);
771}
772
773/*
774 * Call a callback function, with a specified argument, for each module
775 * in a list of modules. If the list is NULL, searches the top-level
776 * list in the display tree of modules. If any callback returns a
777 * non-zero value, we stop and return that value, otherwise we
778 * return 0.
779 *
780 * Normally "obsolete" modules are ignored; their sole purpose is to allow old
781 * preferences for dissectors that no longer have preferences to be
782 * silently ignored in preference files. Does not ignore subtrees,
783 * as this can be used when walking the display tree of modules.
784 */
785
786typedef struct {
787 module_cb callback;
788 void *user_data;
789 unsigned ret;
790 bool_Bool skip_obsolete;
791} call_foreach_t;
792
793static bool_Bool
794call_foreach_cb(const void *key _U___attribute__((unused)), void *value, void *data)
795{
796 module_t *module = (module_t*)value;
797 call_foreach_t *call_data = (call_foreach_t*)data;
798
799 if (!call_data->skip_obsolete || !module->obsolete)
800 call_data->ret = (*call_data->callback)(module, call_data->user_data);
801
802 return (call_data->ret != 0);
803}
804
805static unsigned
806prefs_module_list_foreach(wmem_tree_t *module_list, module_cb callback,
807 void *user_data, bool_Bool skip_obsolete)
808{
809 call_foreach_t call_data;
810
811 if (module_list == NULL((void*)0))
812 module_list = prefs_top_level_modules;
813
814 call_data.callback = callback;
815 call_data.user_data = user_data;
816 call_data.ret = 0;
817 call_data.skip_obsolete = skip_obsolete;
818 wmem_tree_foreach(module_list, call_foreach_cb, &call_data);
819 return call_data.ret;
820}
821
822/*
823 * Returns true if module has any submodules
824 */
825bool_Bool
826prefs_module_has_submodules(module_t *module)
827{
828 if (module->submodules == NULL((void*)0)) {
829 return false0;
830 }
831
832 if (wmem_tree_is_empty(module->submodules)) {
833 return false0;
834 }
835
836 return true1;
837}
838
839/*
840 * Call a callback function, with a specified argument, for each module
841 * in the list of all modules. (This list does not include subtrees.)
842 *
843 * Ignores "obsolete" modules; their sole purpose is to allow old
844 * preferences for dissectors that no longer have preferences to be
845 * silently ignored in preference files.
846 */
847unsigned
848prefs_modules_foreach(module_cb callback, void *user_data)
849{
850 return prefs_module_list_foreach(prefs_modules, callback, user_data, true1);
851}
852
853/*
854 * Call a callback function, with a specified argument, for each submodule
855 * of specified modules. If the module is NULL, goes through the top-level
856 * list in the display tree of modules.
857 *
858 * Ignores "obsolete" modules; their sole purpose is to allow old
859 * preferences for dissectors that no longer have preferences to be
860 * silently ignored in preference files. Does not ignore subtrees,
861 * as this can be used when walking the display tree of modules.
862 */
863unsigned
864prefs_modules_foreach_submodules(module_t *module, module_cb callback,
865 void *user_data)
866{
867 return prefs_module_list_foreach((module)?module->submodules:prefs_top_level_modules, callback, user_data, true1);
868}
869
870static bool_Bool
871call_apply_cb(const void *key _U___attribute__((unused)), void *value, void *data _U___attribute__((unused)))
872{
873 module_t *module = (module_t *)value;
874
875 if (module->obsolete)
876 return false0;
877 if (module->prefs_changed_flags) {
878 if (module->apply_cb != NULL((void*)0))
879 (*module->apply_cb)();
880 module->prefs_changed_flags = 0;
881 }
882 if (module->submodules)
883 wmem_tree_foreach(module->submodules, call_apply_cb, NULL((void*)0));
884 return false0;
885}
886
887/*
888 * Call the "apply" callback function for each module if any of its
889 * preferences have changed, and then clear the flag saying its
890 * preferences have changed, as the module has been notified of that
891 * fact.
892 */
893void
894prefs_apply_all(void)
895{
896 wmem_tree_foreach(prefs_modules, call_apply_cb, NULL((void*)0));
897}
898
899/*
900 * Call the "apply" callback function for a specific module if any of
901 * its preferences have changed, and then clear the flag saying its
902 * preferences have changed, as the module has been notified of that
903 * fact.
904 */
905void
906prefs_apply(module_t *module)
907{
908 if (module && module->prefs_changed_flags)
909 call_apply_cb(NULL((void*)0), module, NULL((void*)0));
910}
911
912static module_t *
913prefs_find_module_alias(const char *name)
914{
915 module_alias_t *alias;
916
917 alias = (module_alias_t *)wmem_tree_lookup_string(prefs_module_aliases, name, WMEM_TREE_STRING_NOCASE0x00000001);
918 if (alias == NULL((void*)0))
919 return NULL((void*)0);
920 return alias->module;
921}
922
923/*
924 * Register a preference in a module's list of preferences.
925 * If it has a title, give it an ordinal number; otherwise, it's a
926 * preference that won't show up in the UI, so it shouldn't get an
927 * ordinal number (the ordinal should be the ordinal in the set of
928 * *visible* preferences).
929 */
930static pref_t *
931register_preference(module_t *module, const char *name, const char *title,
932 const char *description, pref_type_e type, bool_Bool obsolete)
933{
934 pref_t *preference;
935 const char *p;
936 const char *name_prefix = (module->name != NULL((void*)0)) ? module->name : module->parent->name;
937
938 preference = g_new(pref_t,1)((pref_t *) g_malloc_n ((1), sizeof (pref_t)));
939 preference->name = name;
940 preference->title = title;
941 preference->description = description;
942 preference->type = type;
943 preference->obsolete = obsolete;
944 /* Default to module's preference effects */
945 preference->effect_flags = module->effect_flags;
946
947 if (title != NULL((void*)0))
948 preference->ordinal = module->numprefs;
949 else
950 preference->ordinal = -1; /* no ordinal for you */
951
952 /*
953 * Make sure that only lower-case ASCII letters, numbers,
954 * underscores, and dots appear in the preference name.
955 *
956 * Crash if there is, as that's an error in the code;
957 * you can make the title and description nice strings
958 * with capitalization, white space, punctuation, etc.,
959 * but the name can be used on the command line,
960 * and shouldn't require quoting, shifting, etc.
961 */
962 for (p = name; *p != '\0'; p++)
963 if (!(g_ascii_islower(*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_LOWER) != 0) || g_ascii_isdigit(*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_DIGIT) != 0) || *p == '_' || *p == '.'))
964 ws_error("Preference \"%s.%s\" contains invalid characters", module->name, name)ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 964
, __func__, "Preference \"%s.%s\" contains invalid characters"
, module->name, name)
;
965
966 /*
967 * Make sure there's not already a preference with that
968 * name. Crash if there is, as that's an error in the
969 * code, and the code has to be fixed not to register
970 * more than one preference with the same name.
971 */
972 if (prefs_find_preference(module, name) != NULL((void*)0))
973 ws_error("Preference %s has already been registered", name)ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 973
, __func__, "Preference %s has already been registered", name
)
;
974
975 if ((!preference->obsolete) &&
976 /* Don't compare if it's a subtree */
977 (module->name != NULL((void*)0))) {
978 /*
979 * Make sure the preference name doesn't begin with the
980 * module name, as that's redundant and Just Silly.
981 */
982 if (!((strncmp(name, module->name, strlen(module->name)) != 0) ||
983 (((name[strlen(module->name)]) != '.') && ((name[strlen(module->name)]) != '_'))))
984 ws_error("Preference %s begins with the module name", name)ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 984
, __func__, "Preference %s begins with the module name", name
)
;
985 }
986
987 /* The title shows up in the preferences dialog. Make sure it's UI-friendly. */
988 if (preference->title) {
989 const char *cur_char;
990 if (preference->type != PREF_STATIC_TEXT && g_utf8_strlen(preference->title, -1) > 80) { // Arbitrary.
991 ws_error("Title for preference %s.%s is too long: %s", name_prefix, preference->name, preference->title)ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 991
, __func__, "Title for preference %s.%s is too long: %s", name_prefix
, preference->name, preference->title)
;
992 }
993
994 if (!g_utf8_validate(preference->title, -1, NULL((void*)0))) {
995 ws_error("Title for preference %s.%s isn't valid UTF-8.", name_prefix, preference->name)ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 995
, __func__, "Title for preference %s.%s isn't valid UTF-8.", name_prefix
, preference->name)
;
996 }
997
998 for (cur_char = preference->title; *cur_char; cur_char = g_utf8_next_char(cur_char)(char *)((cur_char) + g_utf8_skip[*(const guchar *)(cur_char)
])
) {
999 if (!g_unichar_isprint(g_utf8_get_char(cur_char))) {
1000 ws_error("Title for preference %s.%s isn't printable UTF-8.", name_prefix, preference->name)ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 1000
, __func__, "Title for preference %s.%s isn't printable UTF-8."
, name_prefix, preference->name)
;
1001 }
1002 }
1003 }
1004
1005 if (preference->description) {
1006 if (!g_utf8_validate(preference->description, -1, NULL((void*)0))) {
1007 ws_error("Description for preference %s.%s isn't valid UTF-8.", name_prefix, preference->name)ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 1007
, __func__, "Description for preference %s.%s isn't valid UTF-8."
, name_prefix, preference->name)
;
1008 }
1009 }
1010
1011 /*
1012 * We passed all of our checks. Add the preference.
1013 */
1014 module->prefs = g_list_append(module->prefs, preference);
1015 if (title != NULL((void*)0))
1016 module->numprefs++;
1017
1018 return preference;
1019}
1020
1021/*
1022 * Find a preference in a module's list of preferences, given the module
1023 * and the preference's name.
1024 */
1025typedef struct {
1026 GList *list_entry;
1027 const char *name;
1028 module_t *submodule;
1029} find_pref_arg_t;
1030
1031static int
1032preference_match(const void *a, const void *b)
1033{
1034 const pref_t *pref = (const pref_t *)a;
1035 const char *name = (const char *)b;
1036
1037 return strcmp(name, pref->name);
1038}
1039
1040static bool_Bool
1041module_find_pref_cb(const void *key _U___attribute__((unused)), void *value, void *data)
1042{
1043 find_pref_arg_t* arg = (find_pref_arg_t*)data;
1044 GList *list_entry;
1045 module_t *module = (module_t *)value;
1046
1047 if (module == NULL((void*)0))
1048 return false0;
1049
1050 list_entry = g_list_find_custom(module->prefs, arg->name,
1051 preference_match);
1052
1053 if (list_entry == NULL((void*)0))
1054 return false0;
1055
1056 arg->list_entry = list_entry;
1057 arg->submodule = module;
1058 return true1;
1059}
1060
1061/* Tries to find a preference, setting containing_module to the (sub)module
1062 * holding this preference. */
1063static pref_t *
1064prefs_find_preference_with_submodule(module_t *module, const char *name,
1065 module_t **containing_module)
1066{
1067 find_pref_arg_t arg;
1068 GList *list_entry;
1069
1070 if (module == NULL((void*)0))
1071 return NULL((void*)0); /* invalid parameters */
1072
1073 list_entry = g_list_find_custom(module->prefs, name,
1074 preference_match);
1075 arg.submodule = NULL((void*)0);
1076
1077 if (list_entry == NULL((void*)0))
1078 {
1079 arg.list_entry = NULL((void*)0);
1080 if (module->submodules != NULL((void*)0))
1081 {
1082 arg.name = name;
1083 wmem_tree_foreach(module->submodules, module_find_pref_cb, &arg);
1084 }
1085
1086 list_entry = arg.list_entry;
1087 }
1088
1089 if (list_entry == NULL((void*)0))
1090 return NULL((void*)0); /* no such preference */
1091
1092 if (containing_module)
1093 *containing_module = arg.submodule ? arg.submodule : module;
1094
1095 return (pref_t *) list_entry->data;
1096}
1097
1098pref_t *
1099prefs_find_preference(module_t *module, const char *name)
1100{
1101 return prefs_find_preference_with_submodule(module, name, NULL((void*)0));
1102}
1103
1104/*
1105 * Returns true if the given protocol has registered preferences
1106 */
1107bool_Bool
1108prefs_is_registered_protocol(const char *name)
1109{
1110 module_t *m = prefs_find_module(name);
1111
1112 return (m != NULL((void*)0) && !m->obsolete);
1113}
1114
1115/*
1116 * Returns the module title of a registered protocol
1117 */
1118const char *
1119prefs_get_title_by_name(const char *name)
1120{
1121 module_t *m = prefs_find_module(name);
1122
1123 return (m != NULL((void*)0) && !m->obsolete) ? m->title : NULL((void*)0);
1124}
1125
1126/*
1127 * Register a preference with an unsigned integral value.
1128 */
1129void
1130prefs_register_uint_preference(module_t *module, const char *name,
1131 const char *title, const char *description,
1132 unsigned base, unsigned *var)
1133{
1134 pref_t *preference;
1135
1136 preference = register_preference(module, name, title, description,
1137 PREF_UINT, false0);
1138 preference->varp.uint = var;
1139 preference->default_val.uint = *var;
1140 ws_assert(base > 0 && base != 1 && base < 37)do { if ((1) && !(base > 0 && base != 1 &&
base < 37)) ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c"
, 1140, __func__, "assertion failed: %s", "base > 0 && base != 1 && base < 37"
); } while (0)
;
1141 preference->info.base = base;
1142}
1143
1144/*
1145 * XXX Add a prefs_register_{uint16|port}_preference which sets max_value?
1146 */
1147
1148
1149/*
1150 * Register a "custom" preference with a unsigned integral value.
1151 * XXX - This should be temporary until we can find a better way
1152 * to do "custom" preferences
1153 */
1154static void
1155prefs_register_uint_custom_preference(module_t *module, const char *name,
1156 const char *title, const char *description,
1157 struct pref_custom_cbs* custom_cbs, unsigned *var)
1158{
1159 pref_t *preference;
1160
1161 preference = register_preference(module, name, title, description,
1162 PREF_CUSTOM, false0);
1163
1164 preference->custom_cbs = *custom_cbs;
1165 preference->varp.uint = var;
1166 preference->default_val.uint = *var;
1167}
1168
1169/*
1170 * Register a preference with an Boolean value.
1171 */
1172void
1173prefs_register_bool_preference(module_t *module, const char *name,
1174 const char *title, const char *description,
1175 bool_Bool *var)
1176{
1177 pref_t *preference;
1178
1179 preference = register_preference(module, name, title, description,
1180 PREF_BOOL, false0);
1181 preference->varp.boolp = var;
1182 preference->default_val.boolval = *var;
1183}
1184
1185unsigned int prefs_set_bool_value(pref_t *pref, bool_Bool value, pref_source_t source)
1186{
1187 unsigned int changed = 0;
1188
1189 switch (source)
1190 {
1191 case pref_default:
1192 if (pref->default_val.boolval != value) {
1193 pref->default_val.boolval = value;
1194 changed = prefs_get_effect_flags(pref);
1195 }
1196 break;
1197 case pref_stashed:
1198 if (pref->stashed_val.boolval != value) {
1199 pref->stashed_val.boolval = value;
1200 changed = prefs_get_effect_flags(pref);
1201 }
1202 break;
1203 case pref_current:
1204 if (*pref->varp.boolp != value) {
1205 *pref->varp.boolp = value;
1206 changed = prefs_get_effect_flags(pref);
1207 }
1208 break;
1209 default:
1210 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 1210
, __func__, "assertion \"not reached\" failed")
;
1211 break;
1212 }
1213
1214 return changed;
1215}
1216
1217void prefs_invert_bool_value(pref_t *pref, pref_source_t source)
1218{
1219 switch (source)
1220 {
1221 case pref_default:
1222 pref->default_val.boolval = !pref->default_val.boolval;
1223 break;
1224 case pref_stashed:
1225 pref->stashed_val.boolval = !pref->stashed_val.boolval;
1226 break;
1227 case pref_current:
1228 *pref->varp.boolp = !(*pref->varp.boolp);
1229 break;
1230 default:
1231 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 1231
, __func__, "assertion \"not reached\" failed")
;
1232 break;
1233 }
1234}
1235
1236bool_Bool prefs_get_bool_value(pref_t *pref, pref_source_t source)
1237{
1238 switch (source)
1239 {
1240 case pref_default:
1241 return pref->default_val.boolval;
1242 case pref_stashed:
1243 return pref->stashed_val.boolval;
1244 case pref_current:
1245 return *pref->varp.boolp;
1246 default:
1247 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 1247
, __func__, "assertion \"not reached\" failed")
;
1248 break;
1249 }
1250
1251 return false0;
1252}
1253
1254/*
1255 * Register a preference with an enumerated value.
1256 */
1257/*
1258 * XXX Should we get rid of the radio_buttons parameter and make that
1259 * behavior automatic depending on the number of items?
1260 */
1261void
1262prefs_register_enum_preference(module_t *module, const char *name,
1263 const char *title, const char *description,
1264 int *var, const enum_val_t *enumvals,
1265 bool_Bool radio_buttons)
1266{
1267 pref_t *preference;
1268
1269 /* Validate that the "name one would use on the command line for the value"
1270 * doesn't require quoting, etc. It's all treated case-insensitively so we
1271 * don't care about upper vs lower case.
1272 */
1273 for (size_t i = 0; enumvals[i].name != NULL((void*)0); i++) {
1274 for (const char *p = enumvals[i].name; *p != '\0'; p++)
1275 if (!(g_ascii_isalnum(*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_ALNUM) != 0) || *p == '_' || *p == '.' || *p == '-'))
1276 ws_error("Preference \"%s.%s\" enum value name \"%s\" contains invalid characters",ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 1277
, __func__, "Preference \"%s.%s\" enum value name \"%s\" contains invalid characters"
, module->name, name, enumvals[i].name)
1277 module->name, name, enumvals[i].name)ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 1277
, __func__, "Preference \"%s.%s\" enum value name \"%s\" contains invalid characters"
, module->name, name, enumvals[i].name)
;
1278 }
1279
1280
1281 preference = register_preference(module, name, title, description,
1282 PREF_ENUM, false0);
1283 preference->varp.enump = var;
1284 preference->default_val.enumval = *var;
1285 preference->info.enum_info.enumvals = enumvals;
1286 preference->info.enum_info.radio_buttons = radio_buttons;
1287}
1288
1289unsigned int prefs_set_enum_value(pref_t *pref, int value, pref_source_t source)
1290{
1291 unsigned int changed = 0;
1292
1293 switch (source)
1294 {
1295 case pref_default:
1296 if (pref->default_val.enumval != value) {
1297 pref->default_val.enumval = value;
1298 changed = prefs_get_effect_flags(pref);
1299 }
1300 break;
1301 case pref_stashed:
1302 if (pref->stashed_val.enumval != value) {
1303 pref->stashed_val.enumval = value;
1304 changed = prefs_get_effect_flags(pref);
1305 }
1306 break;
1307 case pref_current:
1308 if (*pref->varp.enump != value) {
1309 *pref->varp.enump = value;
1310 changed = prefs_get_effect_flags(pref);
1311 }
1312 break;
1313 default:
1314 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 1314
, __func__, "assertion \"not reached\" failed")
;
1315 break;
1316 }
1317
1318 return changed;
1319}
1320
1321unsigned int prefs_set_enum_string_value(pref_t *pref, const char *value, pref_source_t source)
1322{
1323 int enum_val = find_val_for_string(value, pref->info.enum_info.enumvals, *pref->varp.enump);
1324
1325 return prefs_set_enum_value(pref, enum_val, source);
1326}
1327
1328int prefs_get_enum_value(pref_t *pref, pref_source_t source)
1329{
1330 switch (source)
1331 {
1332 case pref_default:
1333 return pref->default_val.enumval;
1334 case pref_stashed:
1335 return pref->stashed_val.enumval;
1336 case pref_current:
1337 return *pref->varp.enump;
1338 default:
1339 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 1339
, __func__, "assertion \"not reached\" failed")
;
1340 break;
1341 }
1342
1343 return 0;
1344}
1345
1346const enum_val_t* prefs_get_enumvals(pref_t *pref)
1347{
1348 return pref->info.enum_info.enumvals;
1349}
1350
1351bool_Bool prefs_get_enum_radiobuttons(pref_t *pref)
1352{
1353 return pref->info.enum_info.radio_buttons;
1354}
1355
1356/*
1357 * For use by UI code that sets preferences.
1358 */
1359unsigned int
1360prefs_set_custom_value(pref_t *pref, const char *value, pref_source_t source _U___attribute__((unused)))
1361{
1362 /* XXX - support pref source for custom preferences */
1363 unsigned int changed = 0;
1364 pref->custom_cbs.set_cb(pref, value, &changed);
1365 return changed;
1366}
1367
1368static void
1369register_string_like_preference(module_t *module, const char *name,
1370 const char *title, const char *description,
1371 char **var, pref_type_e type,
1372 struct pref_custom_cbs* custom_cbs,
1373 bool_Bool free_tmp)
1374{
1375 pref_t *pref;
1376 char *tmp;
1377
1378 pref = register_preference(module, name, title, description, type, false0);
1379
1380 /*
1381 * String preference values should be non-null (as you can't
1382 * keep them null after using the preferences GUI, you can at best
1383 * have them be null strings) and freeable (as we free them
1384 * if we change them).
1385 *
1386 * If the value is a null pointer, make it a copy of a null
1387 * string, otherwise make it a copy of the value.
1388 */
1389 tmp = *var;
1390 if (*var == NULL((void*)0)) {
1391 *var = g_strdup("")g_strdup_inline ("");
1392 } else {
1393 *var = g_strdup(*var)g_strdup_inline (*var);
1394 }
1395 if (free_tmp) {
1396 g_free(tmp);
1397 }
1398 pref->varp.string = var;
1399 pref->default_val.string = g_strdup(*var)g_strdup_inline (*var);
1400 pref->stashed_val.string = NULL((void*)0);
1401 if (type == PREF_CUSTOM) {
1402 ws_assert(custom_cbs)do { if ((1) && !(custom_cbs)) ws_log_fatal_full("Epan"
, LOG_LEVEL_ERROR, "epan/prefs.c", 1402, __func__, "assertion failed: %s"
, "custom_cbs"); } while (0)
;
1403 pref->custom_cbs = *custom_cbs;
1404 }
1405}
1406
1407/*
1408 * Assign to a string preference.
1409 */
1410static void
1411pref_set_string_like_pref_value(pref_t *pref, const char *value)
1412{
1413DIAG_OFF(cast-qual)clang diagnostic push clang diagnostic ignored "-Wcast-qual"
1414 g_free((void *)*pref->varp.string);
1415DIAG_ON(cast-qual)clang diagnostic pop
1416 *pref->varp.string = g_strdup(value)g_strdup_inline (value);
1417}
1418
1419/*
1420 * For use by UI code that sets preferences.
1421 */
1422unsigned int
1423prefs_set_string_value(pref_t *pref, const char* value, pref_source_t source)
1424{
1425 unsigned int changed = 0;
1426
1427 switch (source)
1428 {
1429 case pref_default:
1430 if (*pref->default_val.string) {
1431 if (strcmp(pref->default_val.string, value) != 0) {
1432 changed = prefs_get_effect_flags(pref);
1433 g_free(pref->default_val.string);
1434 pref->default_val.string = g_strdup(value)g_strdup_inline (value);
1435 }
1436 } else if (value) {
1437 pref->default_val.string = g_strdup(value)g_strdup_inline (value);
1438 }
1439 break;
1440 case pref_stashed:
1441 if (pref->stashed_val.string) {
1442 if (strcmp(pref->stashed_val.string, value) != 0) {
1443 changed = prefs_get_effect_flags(pref);
1444 g_free(pref->stashed_val.string);
1445 pref->stashed_val.string = g_strdup(value)g_strdup_inline (value);
1446 }
1447 } else if (value) {
1448 pref->stashed_val.string = g_strdup(value)g_strdup_inline (value);
1449 }
1450 break;
1451 case pref_current:
1452 if (*pref->varp.string) {
1453 if (strcmp(*pref->varp.string, value) != 0) {
1454 changed = prefs_get_effect_flags(pref);
1455 pref_set_string_like_pref_value(pref, value);
1456 }
1457 } else if (value) {
1458 pref_set_string_like_pref_value(pref, value);
1459 }
1460 break;
1461 default:
1462 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 1462
, __func__, "assertion \"not reached\" failed")
;
1463 break;
1464 }
1465
1466 return changed;
1467}
1468
1469char* prefs_get_string_value(pref_t *pref, pref_source_t source)
1470{
1471 switch (source)
1472 {
1473 case pref_default:
1474 return pref->default_val.string;
1475 case pref_stashed:
1476 return pref->stashed_val.string;
1477 case pref_current:
1478 return *pref->varp.string;
1479 default:
1480 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 1480
, __func__, "assertion \"not reached\" failed")
;
1481 break;
1482 }
1483
1484 return NULL((void*)0);
1485}
1486
1487/*
1488 * Reset the value of a string-like preference.
1489 */
1490static void
1491reset_string_like_preference(pref_t *pref)
1492{
1493 g_free(*pref->varp.string);
1494 *pref->varp.string = g_strdup(pref->default_val.string)g_strdup_inline (pref->default_val.string);
1495}
1496
1497/*
1498 * Register a preference with a character-string value.
1499 */
1500void
1501prefs_register_string_preference(module_t *module, const char *name,
1502 const char *title, const char *description,
1503 const char **var)
1504{
1505DIAG_OFF(cast-qual)clang diagnostic push clang diagnostic ignored "-Wcast-qual"
1506 register_string_like_preference(module, name, title, description,
1507 (char **)var, PREF_STRING, NULL((void*)0), false0);
1508DIAG_ON(cast-qual)clang diagnostic pop
1509}
1510
1511/*
1512 * Register a preference with a file name (string) value.
1513 */
1514void
1515prefs_register_filename_preference(module_t *module, const char *name,
1516 const char *title, const char *description,
1517 const char **var, bool_Bool for_writing)
1518{
1519DIAG_OFF(cast-qual)clang diagnostic push clang diagnostic ignored "-Wcast-qual"
1520 register_string_like_preference(module, name, title, description, (char **)var,
1521 for_writing ? PREF_SAVE_FILENAME : PREF_OPEN_FILENAME, NULL((void*)0), false0);
1522DIAG_ON(cast-qual)clang diagnostic pop
1523}
1524
1525/*
1526 * Register a preference with a directory name (string) value.
1527 */
1528void
1529prefs_register_directory_preference(module_t *module, const char *name,
1530 const char *title, const char *description,
1531 const char **var)
1532{
1533DIAG_OFF(cast-qual)clang diagnostic push clang diagnostic ignored "-Wcast-qual"
1534 register_string_like_preference(module, name, title, description,
1535 (char **)var, PREF_DIRNAME, NULL((void*)0), false0);
1536DIAG_ON(cast-qual)clang diagnostic pop
1537}
1538
1539/* Refactoring to handle both PREF_RANGE and PREF_DECODE_AS_RANGE */
1540static pref_t*
1541prefs_register_range_preference_common(module_t *module, const char *name,
1542 const char *title, const char *description,
1543 range_t **var, uint32_t max_value, pref_type_e type)
1544{
1545 pref_t *preference;
1546
1547 preference = register_preference(module, name, title, description, type, false0);
1548 preference->info.max_value = max_value;
1549
1550 /*
1551 * Range preference values should be non-null (as you can't
1552 * keep them null after using the preferences GUI, you can at best
1553 * have them be empty ranges) and freeable (as we free them
1554 * if we change them).
1555 *
1556 * If the value is a null pointer, make it an empty range.
1557 */
1558 if (*var == NULL((void*)0))
1559 *var = range_empty(wmem_epan_scope());
1560 preference->varp.range = var;
1561 preference->default_val.range = range_copy(wmem_epan_scope(), *var);
1562 preference->stashed_val.range = NULL((void*)0);
1563
1564 return preference;
1565}
1566
1567/*
1568 * Register a preference with a ranged value.
1569 */
1570void
1571prefs_register_range_preference(module_t *module, const char *name,
1572 const char *title, const char *description,
1573 range_t **var, uint32_t max_value)
1574{
1575 prefs_register_range_preference_common(module, name, title,
1576 description, var, max_value, PREF_RANGE);
1577}
1578
1579bool_Bool
1580prefs_set_range_value_work(pref_t *pref, const char *value,
1581 bool_Bool return_range_errors, unsigned int *changed_flags)
1582{
1583 range_t *newrange;
1584
1585 if (range_convert_str_work(wmem_epan_scope(), &newrange, value, pref->info.max_value,
1586 return_range_errors) != CVT_NO_ERROR) {
1587 return false0; /* number was bad */
1588 }
1589
1590 if (!ranges_are_equal(*pref->varp.range, newrange)) {
1591 *changed_flags |= prefs_get_effect_flags(pref);
1592 wmem_free(wmem_epan_scope(), *pref->varp.range);
1593 *pref->varp.range = newrange;
1594 } else {
1595 wmem_free(wmem_epan_scope(), newrange);
1596 }
1597 return true1;
1598}
1599
1600/*
1601 * For use by UI code that sets preferences.
1602 */
1603unsigned int
1604prefs_set_stashed_range_value(pref_t *pref, const char *value)
1605{
1606 range_t *newrange;
1607
1608 if (range_convert_str_work(wmem_epan_scope(), &newrange, value, pref->info.max_value,
1609 true1) != CVT_NO_ERROR) {
1610 return 0; /* number was bad */
1611 }
1612
1613 if (!ranges_are_equal(pref->stashed_val.range, newrange)) {
1614 wmem_free(wmem_epan_scope(), pref->stashed_val.range);
1615 pref->stashed_val.range = newrange;
1616 } else {
1617 wmem_free(wmem_epan_scope(), newrange);
1618 }
1619 return prefs_get_effect_flags(pref);
1620
1621}
1622
1623bool_Bool prefs_add_list_value(pref_t *pref, void* value, pref_source_t source)
1624{
1625 switch (source)
1626 {
1627 case pref_default:
1628 pref->default_val.list = g_list_prepend(pref->default_val.list, value);
1629 break;
1630 case pref_stashed:
1631 pref->stashed_val.list = g_list_prepend(pref->stashed_val.list, value);
1632 break;
1633 case pref_current:
1634 *pref->varp.list = g_list_prepend(*pref->varp.list, value);
1635 break;
1636 default:
1637 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 1637
, __func__, "assertion \"not reached\" failed")
;
1638 break;
1639 }
1640
1641 return true1;
1642}
1643
1644GList* prefs_get_list_value(pref_t *pref, pref_source_t source)
1645{
1646 switch (source)
1647 {
1648 case pref_default:
1649 return pref->default_val.list;
1650 case pref_stashed:
1651 return pref->stashed_val.list;
1652 case pref_current:
1653 return *pref->varp.list;
1654 default:
1655 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 1655
, __func__, "assertion \"not reached\" failed")
;
1656 break;
1657 }
1658
1659 return NULL((void*)0);
1660}
1661
1662bool_Bool prefs_set_range_value(pref_t *pref, range_t *value, pref_source_t source)
1663{
1664 bool_Bool changed = false0;
1665
1666 switch (source)
1667 {
1668 case pref_default:
1669 if (!ranges_are_equal(pref->default_val.range, value)) {
1670 wmem_free(wmem_epan_scope(), pref->default_val.range);
1671 pref->default_val.range = range_copy(wmem_epan_scope(), value);
1672 changed = true1;
1673 }
1674 break;
1675 case pref_stashed:
1676 if (!ranges_are_equal(pref->stashed_val.range, value)) {
1677 wmem_free(wmem_epan_scope(), pref->stashed_val.range);
1678 pref->stashed_val.range = range_copy(wmem_epan_scope(), value);
1679 changed = true1;
1680 }
1681 break;
1682 case pref_current:
1683 if (!ranges_are_equal(*pref->varp.range, value)) {
1684 wmem_free(wmem_epan_scope(), *pref->varp.range);
1685 *pref->varp.range = range_copy(wmem_epan_scope(), value);
1686 changed = true1;
1687 }
1688 break;
1689 default:
1690 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 1690
, __func__, "assertion \"not reached\" failed")
;
1691 break;
1692 }
1693
1694 return changed;
1695}
1696
1697range_t* prefs_get_range_value_real(pref_t *pref, pref_source_t source)
1698{
1699 switch (source)
1700 {
1701 case pref_default:
1702 return pref->default_val.range;
1703 case pref_stashed:
1704 return pref->stashed_val.range;
1705 case pref_current:
1706 return *pref->varp.range;
1707 default:
1708 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 1708
, __func__, "assertion \"not reached\" failed")
;
1709 break;
1710 }
1711
1712 return NULL((void*)0);
1713}
1714
1715range_t* prefs_get_range_value(const char *module_name, const char* pref_name)
1716{
1717 pref_t *pref = prefs_find_preference(prefs_find_module(module_name), pref_name);
1718 if (pref == NULL((void*)0)) {
1719 return NULL((void*)0);
1720 }
1721 return prefs_get_range_value_real(pref, pref_current);
1722}
1723
1724void
1725prefs_range_add_value(pref_t *pref, uint32_t val)
1726{
1727 range_add_value(wmem_epan_scope(), pref->varp.range, val);
1728}
1729
1730void
1731prefs_range_remove_value(pref_t *pref, uint32_t val)
1732{
1733 range_remove_value(wmem_epan_scope(), pref->varp.range, val);
1734}
1735
1736/*
1737 * Register a static text 'preference'. It can be used to add explanatory
1738 * text inline with other preferences in the GUI.
1739 * Note: Static preferences are not saved to the preferences file.
1740 */
1741void
1742prefs_register_static_text_preference(module_t *module, const char *name,
1743 const char *title,
1744 const char *description)
1745{
1746 register_preference(module, name, title, description, PREF_STATIC_TEXT, false0);
1747}
1748
1749/*
1750 * Register a uat 'preference'. It adds a button that opens the uat's window in the
1751 * preferences tab of the module.
1752 */
1753extern void
1754prefs_register_uat_preference(module_t *module, const char *name,
1755 const char *title, const char *description,
1756 uat_t* uat)
1757{
1758 pref_t* preference = register_preference(module, name, title, description, PREF_UAT, false0);
1759
1760 preference->varp.uat = uat;
1761}
1762
1763struct epan_uat* prefs_get_uat_value(pref_t *pref)
1764{
1765 return pref->varp.uat;
1766}
1767
1768/*
1769 * Register a color preference.
1770 */
1771void
1772prefs_register_color_preference(module_t *module, const char *name,
1773 const char *title, const char *description,
1774 color_t *color)
1775{
1776 pref_t* preference = register_preference(module, name, title, description, PREF_COLOR, false0);
1777
1778 preference->varp.colorp = color;
1779 preference->default_val.color = *color;
1780}
1781
1782bool_Bool prefs_set_color_value(pref_t *pref, color_t value, pref_source_t source)
1783{
1784 bool_Bool changed = false0;
1785
1786 switch (source)
1787 {
1788 case pref_default:
1789 if ((pref->default_val.color.red != value.red) ||
1790 (pref->default_val.color.green != value.green) ||
1791 (pref->default_val.color.blue != value.blue)) {
1792 changed = true1;
1793 pref->default_val.color = value;
1794 }
1795 break;
1796 case pref_stashed:
1797 if ((pref->stashed_val.color.red != value.red) ||
1798 (pref->stashed_val.color.green != value.green) ||
1799 (pref->stashed_val.color.blue != value.blue)) {
1800 changed = true1;
1801 pref->stashed_val.color = value;
1802 }
1803 break;
1804 case pref_current:
1805 if ((pref->varp.colorp->red != value.red) ||
1806 (pref->varp.colorp->green != value.green) ||
1807 (pref->varp.colorp->blue != value.blue)) {
1808 changed = true1;
1809 *pref->varp.colorp = value;
1810 }
1811 break;
1812 default:
1813 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 1813
, __func__, "assertion \"not reached\" failed")
;
1814 break;
1815 }
1816
1817 return changed;
1818}
1819
1820color_t* prefs_get_color_value(pref_t *pref, pref_source_t source)
1821{
1822 switch (source)
1823 {
1824 case pref_default:
1825 return &pref->default_val.color;
1826 case pref_stashed:
1827 return &pref->stashed_val.color;
1828 case pref_current:
1829 return pref->varp.colorp;
1830 default:
1831 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 1831
, __func__, "assertion \"not reached\" failed")
;
1832 break;
1833 }
1834
1835 return NULL((void*)0);
1836}
1837
1838/*
1839 * Register a "custom" preference with a list.
1840 * XXX - This should be temporary until we can find a better way
1841 * to do "custom" preferences
1842 */
1843typedef void (*pref_custom_list_init_cb) (pref_t* pref, GList** value);
1844
1845static void
1846prefs_register_list_custom_preference(module_t *module, const char *name,
1847 const char *title, const char *description,
1848 struct pref_custom_cbs* custom_cbs,
1849 pref_custom_list_init_cb init_cb,
1850 GList** list)
1851{
1852 pref_t* preference = register_preference(module, name, title, description, PREF_CUSTOM, false0);
1853
1854 preference->custom_cbs = *custom_cbs;
1855 init_cb(preference, list);
1856}
1857
1858/*
1859 * Register a custom preference.
1860 */
1861void
1862prefs_register_custom_preference(module_t *module, const char *name,
1863 const char *title, const char *description,
1864 struct pref_custom_cbs* custom_cbs,
1865 void **custom_data _U___attribute__((unused)))
1866{
1867 pref_t* preference = register_preference(module, name, title, description, PREF_CUSTOM, false0);
1868
1869 preference->custom_cbs = *custom_cbs;
1870 /* XXX - wait until we can handle void** pointers
1871 preference->custom_cbs.init_cb(preference, custom_data);
1872 */
1873}
1874
1875/*
1876 * Register a dedicated TCP preference for SEQ analysis overriding.
1877 * This is similar to the data structure from enum preference, except
1878 * that when a preference dialog is used, the stashed value is the list
1879 * of frame data pointers whose sequence analysis override will be set
1880 * to the current value if the dialog is accepted.
1881 *
1882 * We don't need to read or write the value from the preferences file
1883 * (or command line), because the override is reset to the default (0)
1884 * for each frame when a new capture file is loaded.
1885 */
1886void
1887prefs_register_custom_preference_TCP_Analysis(module_t *module, const char *name,
1888 const char *title, const char *description,
1889 int *var, const enum_val_t *enumvals,
1890 bool_Bool radio_buttons)
1891{
1892 pref_t *preference;
1893
1894 preference = register_preference(module, name, title, description,
1895 PREF_PROTO_TCP_SNDAMB_ENUM, false0);
1896 preference->varp.enump = var;
1897 preference->default_val.enumval = *var;
1898 preference->stashed_val.list = NULL((void*)0);
1899 preference->info.enum_info.enumvals = enumvals;
1900 preference->info.enum_info.radio_buttons = radio_buttons;
1901}
1902
1903/*
1904 * Register a (internal) "Decode As" preference with a ranged value.
1905 */
1906void prefs_register_decode_as_range_preference(module_t *module, const char *name,
1907 const char *title, const char *description, range_t **var,
1908 uint32_t max_value, const char *dissector_table, const char *dissector_description)
1909{
1910 pref_t *preference;
1911
1912 preference = prefs_register_range_preference_common(module, name, title,
1913 description, var, max_value, PREF_DECODE_AS_RANGE);
1914 preference->dissector_desc = dissector_description;
1915 preference->dissector_table = dissector_table;
1916}
1917
1918/*
1919 * Register a preference with password value.
1920 */
1921void
1922prefs_register_password_preference(module_t *module, const char *name,
1923 const char *title, const char *description,
1924 const char **var)
1925{
1926DIAG_OFF(cast-qual)clang diagnostic push clang diagnostic ignored "-Wcast-qual"
1927 register_string_like_preference(module, name, title, description,
1928 (char **)var, PREF_PASSWORD, NULL((void*)0), false0);
1929DIAG_ON(cast-qual)clang diagnostic pop
1930}
1931
1932/*
1933 * Register a preference with a dissector name.
1934 */
1935void
1936prefs_register_dissector_preference(module_t *module, const char *name,
1937 const char *title, const char *description,
1938 const char **var)
1939{
1940DIAG_OFF(cast-qual)clang diagnostic push clang diagnostic ignored "-Wcast-qual"
1941 register_string_like_preference(module, name, title, description,
1942 (char **)var, PREF_DISSECTOR, NULL((void*)0), false0);
1943DIAG_ON(cast-qual)clang diagnostic pop
1944}
1945
1946bool_Bool prefs_add_decode_as_value(pref_t *pref, unsigned value, bool_Bool replace)
1947{
1948 switch(pref->type)
1949 {
1950 case PREF_DECODE_AS_RANGE:
1951 if (replace)
1952 {
1953 /* If range has single value, replace it */
1954 if (((*pref->varp.range)->nranges == 1) &&
1955 ((*pref->varp.range)->ranges[0].low == (*pref->varp.range)->ranges[0].high)) {
1956 wmem_free(wmem_epan_scope(), *pref->varp.range);
1957 *pref->varp.range = range_empty(wmem_epan_scope());
1958 }
1959 }
1960
1961 prefs_range_add_value(pref, value);
1962 break;
1963 default:
1964 /* XXX - Worth asserting over? */
1965 break;
1966 }
1967
1968 return true1;
1969}
1970
1971bool_Bool prefs_remove_decode_as_value(pref_t *pref, unsigned value, bool_Bool set_default _U___attribute__((unused)))
1972{
1973 switch(pref->type)
1974 {
1975 case PREF_DECODE_AS_RANGE:
1976 /* XXX - We could set to the default if the value is the only one
1977 * in the range.
1978 */
1979 prefs_range_remove_value(pref, value);
1980 break;
1981 default:
1982 break;
1983 }
1984
1985 return true1;
1986}
1987
1988/*
1989 * Register a preference that used to be supported but no longer is.
1990 */
1991void
1992prefs_register_obsolete_preference(module_t *module, const char *name)
1993{
1994 register_preference(module, name, NULL((void*)0), NULL((void*)0), PREF_STATIC_TEXT, true1);
1995}
1996
1997bool_Bool
1998prefs_is_preference_obsolete(pref_t *pref)
1999{
2000 return pref->obsolete;
2001}
2002
2003void
2004prefs_set_preference_effect_fields(module_t *module, const char *name)
2005{
2006 prefs_set_preference_effect(module, name, PREF_EFFECT_FIELDS(1u << 3));
2007}
2008
2009void prefs_set_preference_effect(module_t* module, const char* name, unsigned flags) {
2010 pref_t* pref = prefs_find_preference(module, name);
2011 if (pref) {
2012 prefs_set_effect_flags(pref, prefs_get_effect_flags(pref) | flags);
2013 }
2014}
2015
2016unsigned
2017pref_stash(pref_t *pref, void *unused _U___attribute__((unused)))
2018{
2019 ws_assert(!pref->obsolete)do { if ((1) && !(!pref->obsolete)) ws_log_fatal_full
("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 2019, __func__, "assertion failed: %s"
, "!pref->obsolete"); } while (0)
;
2020
2021 switch (pref->type) {
2022
2023 case PREF_UINT:
2024 pref->stashed_val.uint = *pref->varp.uint;
2025 break;
2026
2027 case PREF_BOOL:
2028 pref->stashed_val.boolval = *pref->varp.boolp;
2029 break;
2030
2031 case PREF_ENUM:
2032 pref->stashed_val.enumval = *pref->varp.enump;
2033 break;
2034
2035 case PREF_STRING:
2036 case PREF_SAVE_FILENAME:
2037 case PREF_OPEN_FILENAME:
2038 case PREF_DIRNAME:
2039 case PREF_PASSWORD:
2040 case PREF_DISSECTOR:
2041 g_free(pref->stashed_val.string);
2042 pref->stashed_val.string = g_strdup(*pref->varp.string)g_strdup_inline (*pref->varp.string);
2043 break;
2044
2045 case PREF_DECODE_AS_RANGE:
2046 case PREF_RANGE:
2047 wmem_free(wmem_epan_scope(), pref->stashed_val.range);
2048 pref->stashed_val.range = range_copy(wmem_epan_scope(), *pref->varp.range);
2049 break;
2050
2051 case PREF_COLOR:
2052 pref->stashed_val.color = *pref->varp.colorp;
2053 break;
2054
2055 case PREF_STATIC_TEXT:
2056 case PREF_UAT:
2057 case PREF_CUSTOM:
2058 case PREF_PROTO_TCP_SNDAMB_ENUM:
2059 break;
2060
2061 default:
2062 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 2062
, __func__, "assertion \"not reached\" failed")
;
2063 break;
2064 }
2065 return 0;
2066}
2067
2068unsigned
2069pref_unstash(pref_t *pref, void *unstash_data_p)
2070{
2071 pref_unstash_data_t *unstash_data = (pref_unstash_data_t *)unstash_data_p;
2072 dissector_table_t sub_dissectors = NULL((void*)0);
2073 dissector_handle_t handle = NULL((void*)0);
2074
2075 ws_assert(!pref->obsolete)do { if ((1) && !(!pref->obsolete)) ws_log_fatal_full
("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 2075, __func__, "assertion failed: %s"
, "!pref->obsolete"); } while (0)
;
2076
2077 /* Revert the preference to its saved value. */
2078 switch (pref->type) {
2079
2080 case PREF_UINT:
2081 if (*pref->varp.uint != pref->stashed_val.uint) {
2082 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2083 *pref->varp.uint = pref->stashed_val.uint;
2084 }
2085 break;
2086
2087 case PREF_BOOL:
2088 if (*pref->varp.boolp != pref->stashed_val.boolval) {
2089 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2090 *pref->varp.boolp = pref->stashed_val.boolval;
2091 }
2092 break;
2093
2094 case PREF_ENUM:
2095 if (*pref->varp.enump != pref->stashed_val.enumval) {
2096 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2097 *pref->varp.enump = pref->stashed_val.enumval;
2098 }
2099 break;
2100
2101 case PREF_PROTO_TCP_SNDAMB_ENUM:
2102 {
2103 /* The preference dialogs are modal so the frame_data pointers should
2104 * still be valid; otherwise we could store the frame numbers to
2105 * change.
2106 */
2107 frame_data *fdata;
2108 for (GList* elem = pref->stashed_val.list; elem != NULL((void*)0); elem = elem->next) {
2109 fdata = (frame_data*)elem->data;
2110 if (fdata->tcp_snd_manual_analysis != *pref->varp.enump) {
2111 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2112 fdata->tcp_snd_manual_analysis = *pref->varp.enump;
2113 }
2114 }
2115 break;
2116 }
2117 case PREF_STRING:
2118 case PREF_SAVE_FILENAME:
2119 case PREF_OPEN_FILENAME:
2120 case PREF_DIRNAME:
2121 case PREF_PASSWORD:
2122 case PREF_DISSECTOR:
2123 if (strcmp(*pref->varp.string, pref->stashed_val.string) != 0) {
2124 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2125 g_free(*pref->varp.string);
2126 *pref->varp.string = g_strdup(pref->stashed_val.string)g_strdup_inline (pref->stashed_val.string);
2127 }
2128 break;
2129
2130 case PREF_DECODE_AS_RANGE:
2131 {
2132 const char* table_name = prefs_get_dissector_table(pref);
2133 if (!ranges_are_equal(*pref->varp.range, pref->stashed_val.range)) {
2134 uint32_t i, j;
2135 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2136
2137 if (unstash_data->handle_decode_as) {
2138 sub_dissectors = find_dissector_table(table_name);
2139 if (sub_dissectors != NULL((void*)0)) {
2140 const char *handle_desc = prefs_get_dissector_description(pref);
2141 // It should perhaps be possible to get this via dissector name.
2142 handle = dissector_table_get_dissector_handle(sub_dissectors, handle_desc);
2143 if (handle != NULL((void*)0)) {
2144 /* Set the current handle to NULL for all the old values
2145 * in the dissector table. If there isn't an initial
2146 * handle, this actually deletes the entry. (If there
2147 * is an initial entry, keep it around so that the
2148 * user can see the original value.)
2149 *
2150 * XXX - If there's an initial handle which is not this,
2151 * reset it instead? At least this leaves the initial
2152 * handle visible in the Decode As table.
2153 */
2154 for (i = 0; i < (*pref->varp.range)->nranges; i++) {
2155 for (j = (*pref->varp.range)->ranges[i].low; j < (*pref->varp.range)->ranges[i].high; j++) {
2156 dissector_change_uint(table_name, j, NULL((void*)0));
2157 decode_build_reset_list(table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(j)((gpointer) (gulong) (j)), NULL((void*)0), NULL((void*)0));
2158 }
2159
2160 dissector_change_uint(table_name, (*pref->varp.range)->ranges[i].high, NULL((void*)0));
2161 decode_build_reset_list(table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER((*pref->varp.range)->ranges[i].high)((gpointer) (gulong) ((*pref->varp.range)->ranges[i].high
))
, NULL((void*)0), NULL((void*)0));
2162 }
2163 }
2164 }
2165 }
2166
2167 wmem_free(wmem_epan_scope(), *pref->varp.range);
2168 *pref->varp.range = range_copy(wmem_epan_scope(), pref->stashed_val.range);
2169
2170 if (unstash_data->handle_decode_as) {
2171 if ((sub_dissectors != NULL((void*)0)) && (handle != NULL((void*)0))) {
2172
2173 /* Add new values to the dissector table */
2174 for (i = 0; i < (*pref->varp.range)->nranges; i++) {
2175
2176 for (j = (*pref->varp.range)->ranges[i].low; j < (*pref->varp.range)->ranges[i].high; j++) {
2177 dissector_change_uint(table_name, j, handle);
2178 decode_build_reset_list(table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(j)((gpointer) (gulong) (j)), NULL((void*)0), NULL((void*)0));
2179 }
2180
2181 dissector_change_uint(table_name, (*pref->varp.range)->ranges[i].high, handle);
2182 decode_build_reset_list(table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER((*pref->varp.range)->ranges[i].high)((gpointer) (gulong) ((*pref->varp.range)->ranges[i].high
))
, NULL((void*)0), NULL((void*)0));
2183 }
2184 }
2185 }
2186 }
2187 break;
2188 }
2189 case PREF_RANGE:
2190 if (!ranges_are_equal(*pref->varp.range, pref->stashed_val.range)) {
2191 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2192 wmem_free(wmem_epan_scope(), *pref->varp.range);
2193 *pref->varp.range = range_copy(wmem_epan_scope(), pref->stashed_val.range);
2194 }
2195 break;
2196
2197 case PREF_COLOR:
2198 if ((pref->varp.colorp->blue != pref->stashed_val.color.blue) ||
2199 (pref->varp.colorp->red != pref->stashed_val.color.red) ||
2200 (pref->varp.colorp->green != pref->stashed_val.color.green)) {
2201 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2202 *pref->varp.colorp = pref->stashed_val.color;
2203 }
2204 break;
2205 case PREF_UAT:
2206 if (pref->varp.uat && pref->varp.uat->changed) {
2207 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2208 }
2209 break;
2210 case PREF_STATIC_TEXT:
2211 case PREF_CUSTOM:
2212 break;
2213
2214 default:
2215 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 2215
, __func__, "assertion \"not reached\" failed")
;
2216 break;
2217 }
2218 return 0;
2219}
2220
2221void
2222reset_stashed_pref(pref_t *pref) {
2223
2224 ws_assert(!pref->obsolete)do { if ((1) && !(!pref->obsolete)) ws_log_fatal_full
("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 2224, __func__, "assertion failed: %s"
, "!pref->obsolete"); } while (0)
;
2225
2226 switch (pref->type) {
2227
2228 case PREF_UINT:
2229 pref->stashed_val.uint = pref->default_val.uint;
2230 break;
2231
2232 case PREF_BOOL:
2233 pref->stashed_val.boolval = pref->default_val.boolval;
2234 break;
2235
2236 case PREF_ENUM:
2237 pref->stashed_val.enumval = pref->default_val.enumval;
2238 break;
2239
2240 case PREF_STRING:
2241 case PREF_SAVE_FILENAME:
2242 case PREF_OPEN_FILENAME:
2243 case PREF_DIRNAME:
2244 case PREF_PASSWORD:
2245 case PREF_DISSECTOR:
2246 g_free(pref->stashed_val.string);
2247 pref->stashed_val.string = g_strdup(pref->default_val.string)g_strdup_inline (pref->default_val.string);
2248 break;
2249
2250 case PREF_DECODE_AS_RANGE:
2251 case PREF_RANGE:
2252 wmem_free(wmem_epan_scope(), pref->stashed_val.range);
2253 pref->stashed_val.range = range_copy(wmem_epan_scope(), pref->default_val.range);
2254 break;
2255
2256 case PREF_PROTO_TCP_SNDAMB_ENUM:
2257 if (pref->stashed_val.list != NULL((void*)0)) {
2258 g_list_free(pref->stashed_val.list);
2259 pref->stashed_val.list = NULL((void*)0);
2260 }
2261 break;
2262
2263 case PREF_COLOR:
2264 memcpy(&pref->stashed_val.color, &pref->default_val.color, sizeof(color_t));
2265 break;
2266
2267 case PREF_STATIC_TEXT:
2268 case PREF_UAT:
2269 case PREF_CUSTOM:
2270 break;
2271
2272 default:
2273 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 2273
, __func__, "assertion \"not reached\" failed")
;
2274 break;
2275 }
2276}
2277
2278unsigned
2279pref_clean_stash(pref_t *pref, void *unused _U___attribute__((unused)))
2280{
2281 ws_assert(!pref->obsolete)do { if ((1) && !(!pref->obsolete)) ws_log_fatal_full
("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 2281, __func__, "assertion failed: %s"
, "!pref->obsolete"); } while (0)
;
2282
2283 switch (pref->type) {
2284
2285 case PREF_UINT:
2286 break;
2287
2288 case PREF_BOOL:
2289 break;
2290
2291 case PREF_ENUM:
2292 break;
2293
2294 case PREF_STRING:
2295 case PREF_SAVE_FILENAME:
2296 case PREF_OPEN_FILENAME:
2297 case PREF_DIRNAME:
2298 case PREF_PASSWORD:
2299 case PREF_DISSECTOR:
2300 if (pref->stashed_val.string != NULL((void*)0)) {
2301 g_free(pref->stashed_val.string);
2302 pref->stashed_val.string = NULL((void*)0);
2303 }
2304 break;
2305
2306 case PREF_DECODE_AS_RANGE:
2307 case PREF_RANGE:
2308 if (pref->stashed_val.range != NULL((void*)0)) {
2309 wmem_free(wmem_epan_scope(), pref->stashed_val.range);
2310 pref->stashed_val.range = NULL((void*)0);
2311 }
2312 break;
2313
2314 case PREF_STATIC_TEXT:
2315 case PREF_UAT:
2316 case PREF_COLOR:
2317 case PREF_CUSTOM:
2318 break;
2319
2320 case PREF_PROTO_TCP_SNDAMB_ENUM:
2321 if (pref->stashed_val.list != NULL((void*)0)) {
2322 g_list_free(pref->stashed_val.list);
2323 pref->stashed_val.list = NULL((void*)0);
2324 }
2325 break;
2326
2327 default:
2328 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 2328
, __func__, "assertion \"not reached\" failed")
;
2329 break;
2330 }
2331 return 0;
2332}
2333
2334/*
2335 * Call a callback function, with a specified argument, for each preference
2336 * in a given module.
2337 *
2338 * If any of the callbacks return a non-zero value, stop and return that
2339 * value, otherwise return 0.
2340 */
2341unsigned
2342prefs_pref_foreach(module_t *module, pref_cb callback, void *user_data)
2343{
2344 GList *elem;
2345 pref_t *pref;
2346 unsigned ret;
2347
2348 for (elem = g_list_first(module->prefs); elem != NULL((void*)0); elem = g_list_next(elem)((elem) ? (((GList *)(elem))->next) : ((void*)0))) {
2349 pref = (pref_t *)elem->data;
2350 if (!pref || pref->obsolete) {
2351 /*
2352 * This preference is no longer supported; it's
2353 * not a real preference, so we don't call the
2354 * callback for it (i.e., we treat it as if it
2355 * weren't found in the list of preferences,
2356 * and we weren't called in the first place).
2357 */
2358 continue;
2359 }
2360
2361 ret = (*callback)(pref, user_data);
2362 if (ret != 0)
2363 return ret;
2364 }
2365 return 0;
2366}
2367
2368static const enum_val_t st_sort_col_vals[] = {
2369 { "name", "Node name (topic/item)", ST_SORT_COL_NAME1 },
2370 { "count", "Item count", ST_SORT_COL_COUNT2 },
2371 { "average", "Average value of the node", ST_SORT_COL_AVG3 },
2372 { "min", "Minimum value of the node", ST_SORT_COL_MIN4 },
2373 { "max", "Maximum value of the node", ST_SORT_COL_MAX5 },
2374 { "burst", "Burst rate of the node", ST_SORT_COL_BURSTRATE6 },
2375 { NULL((void*)0), NULL((void*)0), 0 }
2376};
2377
2378static const enum_val_t st_format_vals[] = {
2379 { "text", "Plain text", ST_FORMAT_PLAIN },
2380 { "csv", "Comma separated values", ST_FORMAT_CSV },
2381 { "xml", "XML document", ST_FORMAT_XML },
2382 { "yaml", "YAML document", ST_FORMAT_YAML },
2383 { NULL((void*)0), NULL((void*)0), 0 }
2384};
2385
2386static void
2387stats_callback(void)
2388{
2389 /* Test for a sane tap update interval */
2390 if (prefs.tap_update_interval < 100 || prefs.tap_update_interval > 10000)
2391 prefs.tap_update_interval = TAP_UPDATE_DEFAULT_INTERVAL3000;
2392
2393 /* burst resolution can't be less than 1 (ms) */
2394 if (prefs.st_burst_resolution < 1) {
2395 prefs.st_burst_resolution = 1;
2396 }
2397 else if (prefs.st_burst_resolution > ST_MAX_BURSTRES600000) {
2398 prefs.st_burst_resolution = ST_MAX_BURSTRES600000;
2399 }
2400 /* make sure burst window value makes sense */
2401 if (prefs.st_burst_windowlen < prefs.st_burst_resolution) {
2402 prefs.st_burst_windowlen = prefs.st_burst_resolution;
2403 }
2404 /* round burst window down to multiple of resolution */
2405 prefs.st_burst_windowlen -= prefs.st_burst_windowlen%prefs.st_burst_resolution;
2406 if ((prefs.st_burst_windowlen/prefs.st_burst_resolution) > ST_MAX_BURSTBUCKETS100) {
2407 prefs.st_burst_windowlen = prefs.st_burst_resolution*ST_MAX_BURSTBUCKETS100;
2408 }
2409}
2410
2411static void
2412gui_callback(void)
2413{
2414 /* Ensure there is at least one file count */
2415 if (prefs.gui_recent_files_count_max == 0)
2416 prefs.gui_recent_files_count_max = 10;
2417
2418 /* Ensure there is at least one display filter entry */
2419 if (prefs.gui_recent_df_entries_max == 0)
2420 prefs.gui_recent_df_entries_max = 10;
2421
2422 /* number of decimal places should be between 2 and 10 */
2423 if (prefs.gui_decimal_places1 < 2) {
2424 prefs.gui_decimal_places1 = 2;
2425 } else if (prefs.gui_decimal_places1 > 10) {
2426 prefs.gui_decimal_places1 = 10;
2427 }
2428 /* number of decimal places should be between 2 and 10 */
2429 if (prefs.gui_decimal_places2 < 2) {
2430 prefs.gui_decimal_places2 = 2;
2431 } else if (prefs.gui_decimal_places2 > 10) {
2432 prefs.gui_decimal_places2 = 10;
2433 }
2434 /* number of decimal places should be between 2 and 10 */
2435 if (prefs.gui_decimal_places3 < 2) {
2436 prefs.gui_decimal_places3 = 2;
2437 } else if (prefs.gui_decimal_places3 > 10) {
2438 prefs.gui_decimal_places3 = 10;
2439 }
2440}
2441
2442static void
2443gui_layout_callback(void)
2444{
2445 if (prefs.gui_layout_type == layout_unused ||
2446 prefs.gui_layout_type >= layout_type_max) {
2447 /* XXX - report an error? It's not a syntax error - we'd need to
2448 add a way of reporting a *semantic* error. */
2449 prefs.gui_layout_type = layout_type_2;
2450 }
2451}
2452
2453/******************************************************
2454 * All custom preference function callbacks
2455 ******************************************************/
2456static void custom_pref_no_cb(pref_t* pref _U___attribute__((unused))) {}
2457
2458/*
2459 * Column preference functions
2460 */
2461#define PRS_COL_HIDDEN_FMT"column.hidden" "column.hidden"
2462#define PRS_COL_HIDDEN"column.hide" "column.hide"
2463#define PRS_COL_FMT"column.format" "column.format"
2464#define PRS_COL_NUM"column.number" "column.number"
2465static module_t *gui_column_module;
2466
2467static prefs_set_pref_e
2468column_hidden_set_cb(pref_t* pref, const char* value, unsigned int* changed_flags)
2469{
2470 GList *clp;
2471 fmt_data *cfmt;
2472 pref_t *format_pref;
2473
2474 /*
2475 * Prefer the new preference to the old format-based preference if we've
2476 * read it. (We probably could just compare the string to NULL and "".)
2477 */
2478 prefs.cols_hide_new = true1;
2479
2480 (*changed_flags) |= prefs_set_string_value(pref, value, pref_current);
2481
2482 /*
2483 * Set the "visible" flag for the existing columns; we need to
2484 * do this if we set PRS_COL_HIDDEN but don't set PRS_COL_FMT
2485 * after setting it (which might be the case if, for example, we
2486 * set PRS_COL_HIDDEN on the command line).
2487 */
2488 format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT"column.format");
2489 clp = (format_pref) ? *format_pref->varp.list : NULL((void*)0);
2490 int cidx = 1;
2491 while (clp) {
2492 cfmt = (fmt_data *)clp->data;
2493 cfmt->visible = prefs_is_column_visible(*pref->varp.string, cidx);
2494 cidx++;
2495 clp = clp->next;
2496 }
2497
2498 return PREFS_SET_OK;
2499}
2500
2501static const char *
2502column_hidden_type_name_cb(void)
2503{
2504 return "Packet list hidden columns";
2505}
2506
2507static char *
2508column_hidden_type_description_cb(void)
2509{
2510 return g_strdup("List all column indices (1-indexed) to hide in the packet list.")g_strdup_inline ("List all column indices (1-indexed) to hide in the packet list."
)
;
2511}
2512
2513static char *
2514column_hidden_to_str_cb(pref_t* pref, bool_Bool default_val)
2515{
2516 GString *cols_hidden;
2517 GList *clp;
2518 fmt_data *cfmt;
2519 pref_t *format_pref;
2520 int cidx = 1;
2521
2522 if (default_val)
2523 return g_strdup(pref->default_val.string)g_strdup_inline (pref->default_val.string);
2524
2525 cols_hidden = g_string_new("");
2526 format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT"column.format");
2527 clp = (format_pref) ? *format_pref->varp.list : NULL((void*)0);
2528 while (clp) {
2529 cfmt = (fmt_data *) clp->data;
2530 if (!cfmt->visible) {
2531 if (cols_hidden->len)
2532 g_string_append (cols_hidden, ",")(__builtin_constant_p (",") ? __extension__ ({ const char * const
__val = (","); g_string_append_len_inline (cols_hidden, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (cols_hidden
, ",", (gssize) -1))
;
2533 g_string_append_printf (cols_hidden, "%i", cidx);
2534 }
2535 clp = clp->next;
2536 cidx++;
2537 }
2538
2539 return g_string_free (cols_hidden, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((cols_hidden
), ((0))) : g_string_free_and_steal (cols_hidden)) : (g_string_free
) ((cols_hidden), ((0))))
;
2540}
2541
2542static bool_Bool
2543column_hidden_is_default_cb(pref_t* pref)
2544{
2545 char *cur_hidden_str = column_hidden_to_str_cb(pref, false0);
2546 bool_Bool is_default = g_strcmp0(cur_hidden_str, pref->default_val.string) == 0;
2547
2548 g_free(cur_hidden_str);
2549 return is_default;
2550}
2551
2552static prefs_set_pref_e
2553column_hidden_fmt_set_cb(pref_t* pref, const char* value, unsigned int* changed_flags)
2554{
2555 GList *clp;
2556 fmt_data *cfmt;
2557 pref_t *format_pref;
2558
2559 (*changed_flags) |= prefs_set_string_value(pref, value, pref_current);
2560
2561 /*
2562 * Set the "visible" flag for the existing columns; we need to
2563 * do this if we set PRS_COL_HIDDEN_FMT but don't set PRS_COL_FMT
2564 * after setting it (which might be the case if, for example, we
2565 * set PRS_COL_HIDDEN_FMT on the command line; it shouldn't happen
2566 * when reading the configuration file because we write (both of)
2567 * the hidden column prefs before the column format prefs.)
2568 */
2569 format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT"column.format");
2570 clp = (format_pref) ? *format_pref->varp.list : NULL((void*)0);
2571 while (clp) {
2572 cfmt = (fmt_data *)clp->data;
2573 cfmt->visible = prefs_is_column_fmt_visible(*pref->varp.string, cfmt);
2574 clp = clp->next;
2575 }
2576
2577 return PREFS_SET_OK;
2578}
2579
2580static const char *
2581column_hidden_fmt_type_name_cb(void)
2582{
2583 return "Packet list hidden column formats (deprecated)";
2584}
2585
2586static char *
2587column_hidden_fmt_type_description_cb(void)
2588{
2589 return g_strdup("List all column formats to hide in the packet list. Deprecated in favor of the index-based preference.")g_strdup_inline ("List all column formats to hide in the packet list. Deprecated in favor of the index-based preference."
)
;
2590}
2591
2592static char *
2593column_hidden_fmt_to_str_cb(pref_t* pref, bool_Bool default_val)
2594{
2595 GString *cols_hidden;
2596 GList *clp;
2597 fmt_data *cfmt;
2598 pref_t *format_pref;
2599
2600 if (default_val)
2601 return g_strdup(pref->default_val.string)g_strdup_inline (pref->default_val.string);
2602
2603 cols_hidden = g_string_new("");
2604 format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT"column.format");
2605 clp = (format_pref) ? *format_pref->varp.list : NULL((void*)0);
2606 while (clp) {
2607 char *prefs_fmt;
2608 cfmt = (fmt_data *) clp->data;
2609 if (!cfmt->visible) {
2610 if (cols_hidden->len)
2611 g_string_append (cols_hidden, ",")(__builtin_constant_p (",") ? __extension__ ({ const char * const
__val = (","); g_string_append_len_inline (cols_hidden, __val
, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val
))) : (gssize) -1); }) : g_string_append_len_inline (cols_hidden
, ",", (gssize) -1))
;
2612 prefs_fmt = column_fmt_data_to_str(cfmt);
2613 g_string_append(cols_hidden, prefs_fmt)(__builtin_constant_p (prefs_fmt) ? __extension__ ({ const char
* const __val = (prefs_fmt); g_string_append_len_inline (cols_hidden
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (cols_hidden
, prefs_fmt, (gssize) -1))
;
2614 g_free(prefs_fmt);
2615 }
2616 clp = clp->next;
2617 }
2618
2619 return g_string_free (cols_hidden, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((cols_hidden
), ((0))) : g_string_free_and_steal (cols_hidden)) : (g_string_free
) ((cols_hidden), ((0))))
;
2620}
2621
2622static bool_Bool
2623column_hidden_fmt_is_default_cb(pref_t* pref)
2624{
2625 char *cur_hidden_str = column_hidden_fmt_to_str_cb(pref, false0);
2626 bool_Bool is_default = g_strcmp0(cur_hidden_str, pref->default_val.string) == 0;
2627
2628 g_free(cur_hidden_str);
2629 return is_default;
2630}
2631
2632/* Number of columns "preference". This is only used internally and is not written to the
2633 * preference file
2634 */
2635static void
2636column_num_reset_cb(pref_t* pref)
2637{
2638 *pref->varp.uint = pref->default_val.uint;
2639}
2640
2641static prefs_set_pref_e
2642column_num_set_cb(pref_t* pref _U___attribute__((unused)), const char* value _U___attribute__((unused)), unsigned int* changed_flags _U___attribute__((unused)))
2643{
2644 /* Don't write this to the preferences file */
2645 return PREFS_SET_OK;
2646}
2647
2648static const char *
2649column_num_type_name_cb(void)
2650{
2651 return NULL((void*)0);
2652}
2653
2654static char *
2655column_num_type_description_cb(void)
2656{
2657 return g_strdup("")g_strdup_inline ("");
2658}
2659
2660static bool_Bool
2661column_num_is_default_cb(pref_t* pref _U___attribute__((unused)))
2662{
2663 return true1;
2664}
2665
2666static char *
2667column_num_to_str_cb(pref_t* pref _U___attribute__((unused)), bool_Bool default_val _U___attribute__((unused)))
2668{
2669 return g_strdup("")g_strdup_inline ("");
2670}
2671
2672/*
2673 * Column format custom preference functions
2674 */
2675static void
2676column_format_init_cb(pref_t* pref, GList** value)
2677{
2678 fmt_data *src_cfmt, *dest_cfmt;
2679 GList *entry;
2680
2681 pref->varp.list = value;
2682
2683 pref->default_val.list = NULL((void*)0);
2684 for (entry = *pref->varp.list; entry != NULL((void*)0); entry = g_list_next(entry)((entry) ? (((GList *)(entry))->next) : ((void*)0))) {
2685 src_cfmt = (fmt_data *)entry->data;
2686 dest_cfmt = g_new(fmt_data,1)((fmt_data *) g_malloc_n ((1), sizeof (fmt_data)));
2687 dest_cfmt->title = g_strdup(src_cfmt->title)g_strdup_inline (src_cfmt->title);
2688 dest_cfmt->fmt = src_cfmt->fmt;
2689 if (src_cfmt->custom_fields) {
2690 dest_cfmt->custom_fields = g_strdup(src_cfmt->custom_fields)g_strdup_inline (src_cfmt->custom_fields);
2691 dest_cfmt->custom_occurrence = src_cfmt->custom_occurrence;
2692 } else {
2693 dest_cfmt->custom_fields = NULL((void*)0);
2694 dest_cfmt->custom_occurrence = 0;
2695 }
2696 dest_cfmt->visible = src_cfmt->visible;
2697 dest_cfmt->display = src_cfmt->display;
2698 pref->default_val.list = g_list_append(pref->default_val.list, dest_cfmt);
2699 }
2700
2701 column_register_fields();
2702}
2703
2704static void
2705column_format_free_cb(pref_t* pref)
2706{
2707 free_col_info(*pref->varp.list);
2708 free_col_info(pref->default_val.list);
2709}
2710
2711static void
2712column_format_reset_cb(pref_t* pref)
2713{
2714 fmt_data *src_cfmt, *dest_cfmt;
2715 GList *entry;
2716 pref_t *col_num_pref;
2717
2718 free_col_info(*pref->varp.list);
2719 *pref->varp.list = NULL((void*)0);
2720
2721 for (entry = pref->default_val.list; entry != NULL((void*)0); entry = g_list_next(entry)((entry) ? (((GList *)(entry))->next) : ((void*)0))) {
2722 src_cfmt = (fmt_data *)entry->data;
2723 dest_cfmt = g_new(fmt_data,1)((fmt_data *) g_malloc_n ((1), sizeof (fmt_data)));
2724 dest_cfmt->title = g_strdup(src_cfmt->title)g_strdup_inline (src_cfmt->title);
2725 dest_cfmt->fmt = src_cfmt->fmt;
2726 if (src_cfmt->custom_fields) {
2727 dest_cfmt->custom_fields = g_strdup(src_cfmt->custom_fields)g_strdup_inline (src_cfmt->custom_fields);
2728 dest_cfmt->custom_occurrence = src_cfmt->custom_occurrence;
2729 } else {
2730 dest_cfmt->custom_fields = NULL((void*)0);
2731 dest_cfmt->custom_occurrence = 0;
2732 }
2733 dest_cfmt->visible = src_cfmt->visible;
2734 dest_cfmt->display = src_cfmt->display;
2735 *pref->varp.list = g_list_append(*pref->varp.list, dest_cfmt);
2736 }
2737
2738 col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM"column.number");
2739 ws_assert(col_num_pref != NULL)do { if ((1) && !(col_num_pref != ((void*)0))) ws_log_fatal_full
("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 2739, __func__, "assertion failed: %s"
, "col_num_pref != ((void*)0)"); } while (0)
; /* Should never happen */
2740 column_num_reset_cb(col_num_pref);
2741}
2742
2743static prefs_set_pref_e
2744column_format_set_cb(pref_t* pref, const char* value, unsigned int* changed_flags _U___attribute__((unused)))
2745{
2746 GList *col_l, *col_l_elt;
2747 fmt_data *cfmt;
2748 int llen;
2749 pref_t *hidden_pref, *col_num_pref;
2750
2751 col_l = prefs_get_string_list(value);
2752 if (col_l == NULL((void*)0))
2753 return PREFS_SET_SYNTAX_ERR;
2754 if ((g_list_length(col_l) % 2) != 0) {
2755 /* A title didn't have a matching format. */
2756 prefs_clear_string_list(col_l);
2757 return PREFS_SET_SYNTAX_ERR;
2758 }
2759 /* Check to make sure all column formats are valid. */
2760 col_l_elt = g_list_first(col_l);
2761 while (col_l_elt) {
2762 fmt_data cfmt_check;
2763
2764 /* Go past the title. */
2765 col_l_elt = col_l_elt->next;
2766
2767 /* Some predefined columns have been migrated to use custom columns.
2768 * We'll convert these silently here */
2769 try_convert_to_custom_column((char **)&col_l_elt->data);
2770
2771 /* Parse the format to see if it's valid. */
2772 if (!parse_column_format(&cfmt_check, (char *)col_l_elt->data)) {
2773 /* It's not a valid column format. */
2774 prefs_clear_string_list(col_l);
2775 return PREFS_SET_SYNTAX_ERR;
2776 }
2777 if (cfmt_check.fmt == COL_CUSTOM) {
2778 /* We don't need the custom column field on this pass. */
2779 g_free(cfmt_check.custom_fields);
2780 }
2781
2782 /* Go past the format. */
2783 col_l_elt = col_l_elt->next;
2784 }
2785
2786 /* They're all valid; process them. */
2787 free_col_info(*pref->varp.list);
2788 *pref->varp.list = NULL((void*)0);
2789 if (prefs.cols_hide_new) {
2790 hidden_pref = prefs_find_preference(gui_column_module, PRS_COL_HIDDEN"column.hide");
2791 } else {
2792 hidden_pref = prefs_find_preference(gui_column_module, PRS_COL_HIDDEN_FMT"column.hidden");
2793 }
2794 ws_assert(hidden_pref != NULL)do { if ((1) && !(hidden_pref != ((void*)0))) ws_log_fatal_full
("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 2794, __func__, "assertion failed: %s"
, "hidden_pref != ((void*)0)"); } while (0)
; /* Should never happen */
2795 col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM"column.number");
2796 ws_assert(col_num_pref != NULL)do { if ((1) && !(col_num_pref != ((void*)0))) ws_log_fatal_full
("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 2796, __func__, "assertion failed: %s"
, "col_num_pref != ((void*)0)"); } while (0)
; /* Should never happen */
2797 llen = g_list_length(col_l);
2798 *col_num_pref->varp.uint = llen / 2;
2799 col_l_elt = g_list_first(col_l);
2800 int cidx = 1;
2801 while (col_l_elt) {
2802 cfmt = g_new(fmt_data,1)((fmt_data *) g_malloc_n ((1), sizeof (fmt_data)));
2803 cfmt->title = g_strdup((char *)col_l_elt->data)g_strdup_inline ((char *)col_l_elt->data);
2804 col_l_elt = col_l_elt->next;
2805 parse_column_format(cfmt, (char *)col_l_elt->data);
2806 if (prefs.cols_hide_new) {
2807 cfmt->visible = prefs_is_column_visible(*hidden_pref->varp.string, cidx);
2808 } else {
2809 cfmt->visible = prefs_is_column_fmt_visible(*hidden_pref->varp.string, cfmt);
2810 }
2811 col_l_elt = col_l_elt->next;
2812 *pref->varp.list = g_list_append(*pref->varp.list, cfmt);
2813 cidx++;
2814 }
2815
2816 prefs_clear_string_list(col_l);
2817 free_string_like_preference(hidden_pref);
2818 column_register_fields();
2819 return PREFS_SET_OK;
2820}
2821
2822
2823static const char *
2824column_format_type_name_cb(void)
2825{
2826 return "Packet list column format";
2827}
2828
2829static char *
2830column_format_type_description_cb(void)
2831{
2832 return g_strdup("Each pair of strings consists of a column title and its format")g_strdup_inline ("Each pair of strings consists of a column title and its format"
)
;
2833}
2834
2835static bool_Bool
2836column_format_is_default_cb(pref_t* pref)
2837{
2838 GList *clp = *pref->varp.list,
2839 *pref_col = g_list_first(clp),
2840 *def_col = g_list_first(pref->default_val.list);
2841 fmt_data *cfmt, *def_cfmt;
2842 bool_Bool is_default = true1;
2843 pref_t *col_num_pref;
2844
2845 /* See if the column data has changed from the default */
2846 col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM"column.number");
2847 if (col_num_pref && *col_num_pref->varp.uint != col_num_pref->default_val.uint) {
2848 is_default = false0;
2849 } else {
2850 while (pref_col && def_col) {
2851 cfmt = (fmt_data *) pref_col->data;
2852 def_cfmt = (fmt_data *) def_col->data;
2853 if ((g_strcmp0(cfmt->title, def_cfmt->title) != 0) ||
2854 (cfmt->fmt != def_cfmt->fmt) ||
2855 (((cfmt->fmt == COL_CUSTOM) && (cfmt->custom_fields)) &&
2856 ((g_strcmp0(cfmt->custom_fields, def_cfmt->custom_fields) != 0) ||
2857 (cfmt->display != def_cfmt->display)))) {
2858 is_default = false0;
2859 break;
2860 }
2861
2862 pref_col = pref_col->next;
2863 def_col = def_col->next;
2864 }
2865 }
2866
2867 return is_default;
2868}
2869
2870static char *
2871column_format_to_str_cb(pref_t* pref, bool_Bool default_val)
2872{
2873 GList *pref_l = default_val ? pref->default_val.list : *pref->varp.list;
2874 GList *clp = g_list_first(pref_l);
2875 GList *col_l;
2876 fmt_data *cfmt;
2877 char *column_format_str;
2878
2879 col_l = NULL((void*)0);
2880 while (clp) {
2881 cfmt = (fmt_data *) clp->data;
2882 col_l = g_list_append(col_l, g_strdup(cfmt->title)g_strdup_inline (cfmt->title));
2883 col_l = g_list_append(col_l, column_fmt_data_to_str(cfmt));
2884 clp = clp->next;
2885 }
2886
2887 column_format_str = join_string_list(col_l);
2888 prefs_clear_string_list(col_l);
2889 return column_format_str;
2890}
2891
2892
2893/****** Capture column custom preference functions ******/
2894
2895/* This routine is only called when Wireshark is started, NOT when another profile is selected.
2896 Copy the pref->capture_columns list (just loaded with the capture_cols[] struct values)
2897 to prefs->default_val.list.
2898*/
2899static void
2900capture_column_init_cb(pref_t* pref, GList** capture_cols_values)
2901{
2902 GList *ccv_list = *capture_cols_values,
2903 *dlist = NULL((void*)0);
2904
2905 /* */
2906 while (ccv_list) {
2907 dlist = g_list_append(dlist, g_strdup((char *)ccv_list->data)g_strdup_inline ((char *)ccv_list->data));
2908 ccv_list = ccv_list->next;
2909 }
2910
2911 pref->default_val.list = dlist;
2912 pref->varp.list = &prefs.capture_columns;
2913 pref->stashed_val.boolval = false0;
2914}
2915
2916/* Free the prefs->capture_columns list strings and remove the list entries.
2917 Note that since pref->varp.list points to &prefs.capture_columns, it is
2918 also freed.
2919*/
2920static void
2921capture_column_free_cb(pref_t* pref)
2922{
2923 prefs_clear_string_list(prefs.capture_columns);
2924 prefs.capture_columns = NULL((void*)0);
2925
2926 if (pref->stashed_val.boolval == true1) {
2927 prefs_clear_string_list(pref->default_val.list);
2928 pref->default_val.list = NULL((void*)0);
2929 }
2930}
2931
2932/* Copy pref->default_val.list to *pref->varp.list.
2933*/
2934static void
2935capture_column_reset_cb(pref_t* pref)
2936{
2937 GList *vlist = NULL((void*)0), *dlist;
2938
2939 /* Free the column name strings and remove the links from *pref->varp.list */
2940 prefs_clear_string_list(*pref->varp.list);
2941
2942 for (dlist = pref->default_val.list; dlist != NULL((void*)0); dlist = g_list_next(dlist)((dlist) ? (((GList *)(dlist))->next) : ((void*)0))) {
2943 vlist = g_list_append(vlist, g_strdup((char *)dlist->data)g_strdup_inline ((char *)dlist->data));
2944 }
2945 *pref->varp.list = vlist;
2946}
2947
2948static prefs_set_pref_e
2949capture_column_set_cb(pref_t* pref, const char* value, unsigned int* changed_flags _U___attribute__((unused)))
2950{
2951 GList *col_l = prefs_get_string_list(value);
2952 GList *col_l_elt;
2953 char *col_name;
2954 int i;
2955
2956 if (col_l == NULL((void*)0))
2957 return PREFS_SET_SYNTAX_ERR;
2958
2959 capture_column_free_cb(pref);
2960
2961 /* If value (the list of capture.columns read from preferences) is empty, set capture.columns
2962 to the full list of valid capture column names. */
2963 col_l_elt = g_list_first(col_l);
2964 if (!(*(char *)col_l_elt->data)) {
2965 for (i = 0; i < num_capture_cols; i++) {
2966 col_name = g_strdup(capture_cols[i])g_strdup_inline (capture_cols[i]);
2967 prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
2968 }
2969 }
2970
2971 /* Verify that all the column names are valid. If not, use the entire list of valid columns.
2972 */
2973 while (col_l_elt) {
2974 bool_Bool found_match = false0;
2975 col_name = (char *)col_l_elt->data;
2976
2977 for (i = 0; i < num_capture_cols; i++) {
2978 if (strcmp(col_name, capture_cols[i])==0) {
2979 found_match = true1;
2980 break;
2981 }
2982 }
2983 if (!found_match) {
2984 /* One or more cols are invalid so use the entire list of valid cols. */
2985 for (i = 0; i < num_capture_cols; i++) {
2986 col_name = g_strdup(capture_cols[i])g_strdup_inline (capture_cols[i]);
2987 prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
2988 }
2989 pref->varp.list = &prefs.capture_columns;
2990 prefs_clear_string_list(col_l);
2991 return PREFS_SET_SYNTAX_ERR;
2992 }
2993 col_l_elt = col_l_elt->next;
2994 }
2995
2996 col_l_elt = g_list_first(col_l);
2997 while (col_l_elt) {
2998 col_name = (char *)col_l_elt->data;
2999 prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
3000 col_l_elt = col_l_elt->next;
3001 }
3002 pref->varp.list = &prefs.capture_columns;
3003 g_list_free(col_l);
3004 return PREFS_SET_OK;
3005}
3006
3007
3008static const char *
3009capture_column_type_name_cb(void)
3010{
3011 return "Column list";
3012}
3013
3014static char *
3015capture_column_type_description_cb(void)
3016{
3017 return g_strdup(g_strdup_inline ("List of columns to be displayed in the capture options dialog.\n"
"Possible values: INTERFACE, LINK, PMODE, SNAPLEN, MONITOR, BUFFER, FILTER\n"
)
3018 "List of columns to be displayed in the capture options dialog.\n"g_strdup_inline ("List of columns to be displayed in the capture options dialog.\n"
"Possible values: INTERFACE, LINK, PMODE, SNAPLEN, MONITOR, BUFFER, FILTER\n"
)
3019 CAPTURE_COL_TYPE_DESCRIPTION)g_strdup_inline ("List of columns to be displayed in the capture options dialog.\n"
"Possible values: INTERFACE, LINK, PMODE, SNAPLEN, MONITOR, BUFFER, FILTER\n"
)
;
3020}
3021
3022static bool_Bool
3023capture_column_is_default_cb(pref_t* pref)
3024{
3025 GList *pref_col = g_list_first(prefs.capture_columns),
3026 *def_col = g_list_first(pref->default_val.list);
3027 bool_Bool is_default = true1;
3028
3029 /* See if the column data has changed from the default */
3030 while (pref_col && def_col) {
3031 if (strcmp((char *)pref_col->data, (char *)def_col->data) != 0) {
3032 is_default = false0;
3033 break;
3034 }
3035 pref_col = pref_col->next;
3036 def_col = def_col->next;
3037 }
3038
3039 /* Ensure the same column count */
3040 if (((pref_col == NULL((void*)0)) && (def_col != NULL((void*)0))) ||
3041 ((pref_col != NULL((void*)0)) && (def_col == NULL((void*)0))))
3042 is_default = false0;
3043
3044 return is_default;
3045}
3046
3047static char *
3048capture_column_to_str_cb(pref_t* pref, bool_Bool default_val)
3049{
3050
3051 GList *pref_l = default_val ? pref->default_val.list : prefs.capture_columns;
3052 GList *clp = g_list_first(pref_l);
3053 GList *col_l = NULL((void*)0);
3054 char *col;
3055 char *capture_column_str;
3056
3057 while (clp) {
3058 col = (char *) clp->data;
3059 col_l = g_list_append(col_l, g_strdup(col)g_strdup_inline (col));
3060 clp = clp->next;
3061 }
3062
3063 capture_column_str = join_string_list(col_l);
3064 prefs_clear_string_list(col_l);
3065 return capture_column_str;
3066}
3067
3068static prefs_set_pref_e
3069colorized_frame_set_cb(pref_t* pref, const char* value, unsigned int* changed_flags)
3070{
3071 (*changed_flags) |= prefs_set_string_value(pref, value, pref_current);
3072 return PREFS_SET_OK;
3073}
3074
3075static const char *
3076colorized_frame_type_name_cb(void)
3077{
3078 /* Don't write the colors of the 10 easy-access-colorfilters to the preferences
3079 * file until the colors can be changed in the GUI. Currently this is not really
3080 * possible since the STOCK-icons for these colors are hardcoded.
3081 *
3082 * XXX Find a way to change the colors of the STOCK-icons on the fly and then
3083 * add these 10 colors to the list of colors that can be changed through
3084 * the preferences.
3085 *
3086 */
3087 return NULL((void*)0);
3088}
3089
3090static char *
3091colorized_frame_type_description_cb(void)
3092{
3093 return g_strdup("")g_strdup_inline ("");
3094}
3095
3096static bool_Bool
3097colorized_frame_is_default_cb(pref_t* pref _U___attribute__((unused)))
3098{
3099 return true1;
3100}
3101
3102static char *
3103colorized_frame_to_str_cb(pref_t* pref _U___attribute__((unused)), bool_Bool default_val _U___attribute__((unused)))
3104{
3105 return g_strdup("")g_strdup_inline ("");
3106}
3107
3108/*
3109 * Register all non-dissector modules' preferences.
3110 */
3111static module_t *gui_module;
3112static module_t *gui_color_module;
3113static module_t *nameres_module;
3114
3115static void
3116prefs_register_modules(void)
3117{
3118 module_t *printing, *capture_module, *console_module,
3119 *gui_layout_module, *gui_font_module;
3120 module_t *extcap_module;
3121 unsigned int layout_gui_flags;
3122 struct pref_custom_cbs custom_cbs;
3123
3124 if (protocols_module != NULL((void*)0)) {
3125 /* Already setup preferences */
3126 return;
3127 }
3128
3129 /* GUI
3130 * These are "simple" GUI preferences that can be read/written using the
3131 * preference module API. These preferences still use their own
3132 * configuration screens for access, but this cuts down on the
3133 * preference "string compare list" in set_pref()
3134 */
3135 extcap_module = prefs_register_module(NULL((void*)0), "extcap", "Extcap Utilities",
3136 "Extcap Utilities", NULL((void*)0), NULL((void*)0), false0);
3137
3138 /* Setting default value to true */
3139 prefs.extcap_save_on_start = true1;
3140 prefs_register_bool_preference(extcap_module, "gui_save_on_start",
3141 "Save arguments on start of capture",
3142 "Save arguments on start of capture",
3143 &prefs.extcap_save_on_start);
3144
3145 /* GUI
3146 * These are "simple" GUI preferences that can be read/written using the
3147 * preference module API. These preferences still use their own
3148 * configuration screens for access, but this cuts down on the
3149 * preference "string compare list" in set_pref()
3150 */
3151 gui_module = prefs_register_module(NULL((void*)0), "gui", "User Interface",
3152 "User Interface", NULL((void*)0), &gui_callback, false0);
3153 /*
3154 * The GUI preferences don't affect dissection in general.
3155 * Any changes are signaled in other ways, so PREF_EFFECT_GUI doesn't
3156 * explicitly do anything, but wslua_set_preference expects *some*
3157 * effect flag to be set if the preference was changed.
3158 * We have to do this again for all the submodules (except for the
3159 * layout submodule, which has its own effect flag).
3160 */
3161 unsigned gui_effect_flags = prefs_get_module_effect_flags(gui_module);
3162 gui_effect_flags |= PREF_EFFECT_GUI(1u << 4);
3163 gui_effect_flags &= (~PREF_EFFECT_DISSECTION(1u << 0));
3164 prefs_set_module_effect_flags(gui_module, gui_effect_flags);
3165
3166 /*
3167 * gui.console_open is stored in the registry in addition to the
3168 * preferences file. It is also read independently by ws_log_init()
3169 * for early log initialization of the console.
3170 */
3171 prefs_register_enum_preference(gui_module, "console_open",
3172 "Open a console window",
3173 "Open a console window (Windows only)",
3174 (int *)&ws_log_console_open, gui_console_open_type, false0);
3175
3176 prefs_register_obsolete_preference(gui_module, "scrollbar_on_right");
3177 prefs_register_obsolete_preference(gui_module, "packet_list_sel_browse");
3178 prefs_register_obsolete_preference(gui_module, "protocol_tree_sel_browse");
3179 prefs_register_obsolete_preference(gui_module, "tree_view_altern_colors");
3180 prefs_register_obsolete_preference(gui_module, "expert_composite_eyecandy");
3181 prefs_register_obsolete_preference(gui_module, "filter_toolbar_show_in_statusbar");
3182
3183 prefs_register_bool_preference(gui_module, "restore_filter_after_following_stream",
3184 "Restore current display filter after following a stream",
3185 "Restore current display filter after following a stream?",
3186 &prefs.restore_filter_after_following_stream);
3187
3188 prefs_register_obsolete_preference(gui_module, "protocol_tree_line_style");
3189
3190 prefs_register_obsolete_preference(gui_module, "protocol_tree_expander_style");
3191
3192 prefs_register_obsolete_preference(gui_module, "hex_dump_highlight_style");
3193
3194 prefs_register_obsolete_preference(gui_module, "packet_editor.enabled");
3195
3196 gui_column_module = prefs_register_subtree(gui_module, "Columns", "Columns", NULL((void*)0));
3197 prefs_set_module_effect_flags(gui_column_module, gui_effect_flags);
3198 /* For reading older preference files with "column." preferences */
3199 prefs_register_module_alias("column", gui_column_module);
3200
3201
3202 custom_cbs.free_cb = free_string_like_preference;
3203 custom_cbs.reset_cb = reset_string_like_preference;
3204 custom_cbs.set_cb = column_hidden_set_cb;
3205 custom_cbs.type_name_cb = column_hidden_type_name_cb;
3206 custom_cbs.type_description_cb = column_hidden_type_description_cb;
3207 custom_cbs.is_default_cb = column_hidden_is_default_cb;
3208 custom_cbs.to_str_cb = column_hidden_to_str_cb;
3209 register_string_like_preference(gui_column_module, PRS_COL_HIDDEN"column.hide", "Packet list hidden columns",
3210 "List all column indices (1-indexed) to hide in the packet list",
3211 &cols_hidden_list, PREF_CUSTOM, &custom_cbs, false0);
3212
3213 custom_cbs.set_cb = column_hidden_fmt_set_cb;
3214 custom_cbs.type_name_cb = column_hidden_fmt_type_name_cb;
3215 custom_cbs.type_description_cb = column_hidden_fmt_type_description_cb;
3216 custom_cbs.is_default_cb = column_hidden_fmt_is_default_cb;
3217 custom_cbs.to_str_cb = column_hidden_fmt_to_str_cb;
3218
3219 register_string_like_preference(gui_column_module, PRS_COL_HIDDEN_FMT"column.hidden", "Packet list hidden column formats (deprecated)",
3220 "List all column formats to hide in the packet list; deprecated in favor of the index-based preference",
3221 &cols_hidden_fmt_list, PREF_CUSTOM, &custom_cbs, false0);
3222
3223 custom_cbs.free_cb = column_format_free_cb;
3224 custom_cbs.reset_cb = column_format_reset_cb;
3225 custom_cbs.set_cb = column_format_set_cb;
3226 custom_cbs.type_name_cb = column_format_type_name_cb;
3227 custom_cbs.type_description_cb = column_format_type_description_cb;
3228 custom_cbs.is_default_cb = column_format_is_default_cb;
3229 custom_cbs.to_str_cb = column_format_to_str_cb;
3230
3231 prefs_register_list_custom_preference(gui_column_module, PRS_COL_FMT"column.format", "Packet list column format",
3232 "Each pair of strings consists of a column title and its format", &custom_cbs,
3233 column_format_init_cb, &prefs.col_list);
3234
3235 /* Number of columns. This is only used internally and is not written to the
3236 * preference file
3237 */
3238 custom_cbs.free_cb = custom_pref_no_cb;
3239 custom_cbs.reset_cb = column_num_reset_cb;
3240 custom_cbs.set_cb = column_num_set_cb;
3241 custom_cbs.type_name_cb = column_num_type_name_cb;
3242 custom_cbs.type_description_cb = column_num_type_description_cb;
3243 custom_cbs.is_default_cb = column_num_is_default_cb;
3244 custom_cbs.to_str_cb = column_num_to_str_cb;
3245 prefs_register_uint_custom_preference(gui_column_module, PRS_COL_NUM"column.number", "Number of columns",
3246 "Number of columns in col_list", &custom_cbs, &prefs.num_cols);
3247
3248 /* User Interface : Font */
3249 gui_font_module = prefs_register_subtree(gui_module, "Font", "Font", NULL((void*)0));
3250 prefs_set_module_effect_flags(gui_font_module, gui_effect_flags);
3251
3252 prefs_register_obsolete_preference(gui_font_module, "font_name");
3253
3254 prefs_register_obsolete_preference(gui_font_module, "gtk2.font_name");
3255
3256 register_string_like_preference(gui_font_module, "qt.font_name", "Font name",
3257 "Font name for packet list, protocol tree, and hex dump panes. (Qt)",
3258 &prefs.gui_font_name, PREF_STRING, NULL((void*)0), true1);
3259
3260 /* User Interface : Colors */
3261 gui_color_module = prefs_register_subtree(gui_module, "Colors", "Colors", NULL((void*)0));
3262 unsigned gui_color_effect_flags = gui_effect_flags | PREF_EFFECT_GUI_COLOR(1u << 5);
3263 prefs_set_module_effect_flags(gui_color_module, gui_color_effect_flags);
3264
3265 prefs_register_enum_preference(gui_color_module, "color_scheme", "Color scheme", "Color scheme",
3266 &prefs.gui_color_scheme, gui_color_scheme, false0);
3267
3268 prefs_register_color_preference(gui_color_module, "active_frame.fg", "Foreground color for an active selected item",
3269 "Foreground color for an active selected item", &prefs.gui_active_fg);
3270
3271 prefs_register_color_preference(gui_color_module, "active_frame.bg", "Background color for an active selected item",
3272 "Background color for an active selected item", &prefs.gui_active_bg);
3273
3274 prefs_register_enum_preference(gui_color_module, "active_frame.style", "Color style for an active selected item",
3275 "Color style for an active selected item", &prefs.gui_active_style, gui_selection_style, false0);
3276
3277 prefs_register_color_preference(gui_color_module, "inactive_frame.fg", "Foreground color for an inactive selected item",
3278 "Foreground color for an inactive selected item", &prefs.gui_inactive_fg);
3279
3280 prefs_register_color_preference(gui_color_module, "inactive_frame.bg", "Background color for an inactive selected item",
3281 "Background color for an inactive selected item", &prefs.gui_inactive_bg);
3282
3283 prefs_register_enum_preference(gui_color_module, "inactive_frame.style", "Color style for an inactive selected item",
3284 "Color style for an inactive selected item", &prefs.gui_inactive_style, gui_selection_style, false0);
3285
3286 prefs_register_color_preference(gui_color_module, "marked_frame.fg", "Color preferences for a marked frame",
3287 "Color preferences for a marked frame", &prefs.gui_marked_fg);
3288
3289 prefs_register_color_preference(gui_color_module, "marked_frame.bg", "Color preferences for a marked frame",
3290 "Color preferences for a marked frame", &prefs.gui_marked_bg);
3291
3292 prefs_register_color_preference(gui_color_module, "ignored_frame.fg", "Color preferences for a ignored frame",
3293 "Color preferences for a ignored frame", &prefs.gui_ignored_fg);
3294
3295 prefs_register_color_preference(gui_color_module, "ignored_frame.bg", "Color preferences for a ignored frame",
3296 "Color preferences for a ignored frame", &prefs.gui_ignored_bg);
3297
3298 prefs_register_color_preference(gui_color_module, "stream.client.fg", "TCP stream window color preference",
3299 "TCP stream window color preference", &prefs.st_client_fg);
3300
3301 prefs_register_color_preference(gui_color_module, "stream.client.bg", "TCP stream window color preference",
3302 "TCP stream window color preference", &prefs.st_client_bg);
3303
3304 prefs_register_color_preference(gui_color_module, "stream.server.fg", "TCP stream window color preference",
3305 "TCP stream window color preference", &prefs.st_server_fg);
3306
3307 prefs_register_color_preference(gui_color_module, "stream.server.bg", "TCP stream window color preference",
3308 "TCP stream window color preference", &prefs.st_server_bg);
3309
3310 custom_cbs.free_cb = free_string_like_preference;
3311 custom_cbs.reset_cb = reset_string_like_preference;
3312 custom_cbs.set_cb = colorized_frame_set_cb;
3313 custom_cbs.type_name_cb = colorized_frame_type_name_cb;
3314 custom_cbs.type_description_cb = colorized_frame_type_description_cb;
3315 custom_cbs.is_default_cb = colorized_frame_is_default_cb;
3316 custom_cbs.to_str_cb = colorized_frame_to_str_cb;
3317 register_string_like_preference(gui_column_module, "colorized_frame.fg", "Colorized Foreground",
3318 "Filter Colorized Foreground",
3319 &prefs.gui_colorized_fg, PREF_CUSTOM, &custom_cbs, true1);
3320
3321 custom_cbs.free_cb = free_string_like_preference;
3322 custom_cbs.reset_cb = reset_string_like_preference;
3323 custom_cbs.set_cb = colorized_frame_set_cb;
3324 custom_cbs.type_name_cb = colorized_frame_type_name_cb;
3325 custom_cbs.type_description_cb = colorized_frame_type_description_cb;
3326 custom_cbs.is_default_cb = colorized_frame_is_default_cb;
3327 custom_cbs.to_str_cb = colorized_frame_to_str_cb;
3328 register_string_like_preference(gui_column_module, "colorized_frame.bg", "Colorized Background",
3329 "Filter Colorized Background",
3330 &prefs.gui_colorized_bg, PREF_CUSTOM, &custom_cbs, true1);
3331
3332 prefs_register_color_preference(gui_color_module, "color_filter_fg.valid", "Valid color filter foreground",
3333 "Valid color filter foreground", &prefs.gui_filter_valid_fg);
3334 prefs_register_color_preference(gui_color_module, "color_filter_bg.valid", "Valid color filter background",
3335 "Valid color filter background", &prefs.gui_filter_valid_bg);
3336
3337 prefs_register_color_preference(gui_color_module, "color_filter_fg.invalid", "Invalid color filter foreground",
3338 "Invalid color filter foreground", &prefs.gui_filter_invalid_fg);
3339 prefs_register_color_preference(gui_color_module, "color_filter_bg.invalid", "Invalid color filter background",
3340 "Invalid color filter background", &prefs.gui_filter_invalid_bg);
3341
3342 prefs_register_color_preference(gui_color_module, "color_filter_fg.deprecated", "Deprecated color filter foreground",
3343 "Deprecated color filter foreground", &prefs.gui_filter_deprecated_fg);
3344 prefs_register_color_preference(gui_color_module, "color_filter_bg.deprecated", "Deprecated color filter background",
3345 "Deprecated color filter background", &prefs.gui_filter_deprecated_bg);
3346
3347 prefs_register_enum_preference(gui_module, "fileopen.style",
3348 "Where to start the File Open dialog box",
3349 "Where to start the File Open dialog box",
3350 &prefs.gui_fileopen_style, gui_fileopen_style, false0);
3351
3352 prefs_register_uint_preference(gui_module, "recent_files_count.max",
3353 "The max. number of items in the open recent files list",
3354 "The max. number of items in the open recent files list",
3355 10,
3356 &prefs.gui_recent_files_count_max);
3357
3358 prefs_register_uint_preference(gui_module, "recent_display_filter_entries.max",
3359 "The max. number of entries in the display filter list",
3360 "The max. number of entries in the display filter list",
3361 10,
3362 &prefs.gui_recent_df_entries_max);
3363
3364 register_string_like_preference(gui_module, "fileopen.dir", "Start Directory",
3365 "Directory to start in when opening File Open dialog.",
3366 &prefs.gui_fileopen_dir, PREF_DIRNAME, NULL((void*)0), true1);
3367
3368 prefs_register_obsolete_preference(gui_module, "fileopen.remembered_dir");
3369
3370 prefs_register_uint_preference(gui_module, "fileopen.preview",
3371 "The preview timeout in the File Open dialog",
3372 "The preview timeout in the File Open dialog",
3373 10,
3374 &prefs.gui_fileopen_preview);
3375
3376 register_string_like_preference(gui_module, "tlskeylog_command", "Program to launch with TLS Keylog",
3377 "Program path or command line to launch with SSLKEYLOGFILE",
3378 &prefs.gui_tlskeylog_command, PREF_STRING, NULL((void*)0), true1);
3379
3380 prefs_register_bool_preference(gui_module, "ask_unsaved",
3381 "Ask to save unsaved capture files",
3382 "Ask to save unsaved capture files?",
3383 &prefs.gui_ask_unsaved);
3384
3385 prefs_register_bool_preference(gui_module, "autocomplete_filter",
3386 "Display autocompletion for filter text",
3387 "Display an autocomplete suggestion for display and capture filter controls",
3388 &prefs.gui_autocomplete_filter);
3389
3390 prefs_register_bool_preference(gui_module, "find_wrap",
3391 "Wrap to beginning/end of file during search",
3392 "Wrap to beginning/end of file during search?",
3393 &prefs.gui_find_wrap);
3394
3395 prefs_register_obsolete_preference(gui_module, "use_pref_save");
3396
3397 prefs_register_bool_preference(gui_module, "geometry.save.position",
3398 "Save window position at exit",
3399 "Save window position at exit?",
3400 &prefs.gui_geometry_save_position);
3401
3402 prefs_register_bool_preference(gui_module, "geometry.save.size",
3403 "Save window size at exit",
3404 "Save window size at exit?",
3405 &prefs.gui_geometry_save_size);
3406
3407 prefs_register_bool_preference(gui_module, "geometry.save.maximized",
3408 "Save window maximized state at exit",
3409 "Save window maximized state at exit?",
3410 &prefs.gui_geometry_save_maximized);
3411
3412 prefs_register_obsolete_preference(gui_module, "macosx_style");
3413
3414 prefs_register_obsolete_preference(gui_module, "geometry.main.x");
3415 prefs_register_obsolete_preference(gui_module, "geometry.main.y");
3416 prefs_register_obsolete_preference(gui_module, "geometry.main.width");
3417 prefs_register_obsolete_preference(gui_module, "geometry.main.height");
3418 prefs_register_obsolete_preference(gui_module, "toolbar_main_show");
3419
3420 prefs_register_enum_preference(gui_module, "toolbar_main_style",
3421 "Main Toolbar style",
3422 "Main Toolbar style",
3423 &prefs.gui_toolbar_main_style, gui_toolbar_style, false0);
3424
3425 prefs_register_obsolete_preference(gui_module, "toolbar_filter_style");
3426 prefs_register_obsolete_preference(gui_module, "webbrowser");
3427
3428 prefs_register_bool_preference(gui_module, "update.enabled",
3429 "Check for updates",
3430 "Check for updates (Windows and macOS only)",
3431 &prefs.gui_update_enabled);
3432
3433 prefs_register_enum_preference(gui_module, "update.channel",
3434 "Update channel",
3435 "The type of update to fetch. You should probably leave this set to STABLE.",
3436 (int*)(void*)(&prefs.gui_update_channel), gui_update_channel, false0);
3437
3438 prefs_register_uint_preference(gui_module, "update.interval",
3439 "How often to check for software updates",
3440 "How often to check for software updates in seconds",
3441 10,
3442 &prefs.gui_update_interval);
3443
3444 prefs_register_uint_preference(gui_module, "debounce.timer",
3445 "How long to wait before processing computationally intensive user input",
3446 "How long to wait (in milliseconds) before processing "
3447 "computationally intensive user input. "
3448 "If you type quickly, consider lowering the value for a 'snappier' "
3449 "experience. "
3450 "If you type slowly, consider increasing the value to avoid performance issues. "
3451 "This is currently used to delay searches in View -> Internals -> Supported Protocols "
3452 "and Preferences -> Advanced menu.",
3453 10,
3454 &prefs.gui_debounce_timer);
3455
3456 register_string_like_preference(gui_module, "window_title", "Custom window title",
3457 "Custom window title to be appended to the existing title\n"
3458 "%C = capture comment from command line\n"
3459 "%F = file path of the capture file\n"
3460 "%P = profile name\n"
3461 "%S = a conditional separator (\" - \") that only shows when surrounded by variables with values or static text\n"
3462 "%V = version info",
3463 &prefs.gui_window_title, PREF_STRING, NULL((void*)0), true1);
3464
3465 register_string_like_preference(gui_module, "prepend_window_title", "Custom window title prefix",
3466 "Custom window title to be prepended to the existing title\n"
3467 "%C = capture comment from command line\n"
3468 "%F = file path of the capture file\n"
3469 "%P = profile name\n"
3470 "%S = a conditional separator (\" - \") that only shows when surrounded by variables with values or static text\n"
3471 "%V = version info",
3472 &prefs.gui_prepend_window_title, PREF_STRING, NULL((void*)0), true1);
3473
3474 register_string_like_preference(gui_module, "start_title", "Custom start page title",
3475 "Custom start page title",
3476 &prefs.gui_start_title, PREF_STRING, NULL((void*)0), true1);
3477
3478 prefs_register_enum_preference(gui_module, "version_placement",
3479 "Show version in the start page and/or main screen's title bar",
3480 "Show version in the start page and/or main screen's title bar",
3481 (int*)(void*)(&prefs.gui_version_placement), gui_version_placement_type, false0);
3482
3483 prefs_register_obsolete_preference(gui_module, "auto_scroll_on_expand");
3484 prefs_register_obsolete_preference(gui_module, "auto_scroll_percentage");
3485
3486 prefs_register_uint_preference(gui_module, "max_export_objects",
3487 "Maximum number of exported objects",
3488 "The maximum number of objects that can be exported",
3489 10,
3490 &prefs.gui_max_export_objects);
3491 prefs_register_uint_preference(gui_module, "max_tree_items",
3492 "Maximum number of tree items",
3493 "The maximum number of items that can be added to the dissection tree (Increase with caution)",
3494 10,
3495 &prefs.gui_max_tree_items);
3496 /*
3497 * Used independently by proto_tree_add_node, call_dissector*, dissector_try_heuristic,
3498 * and increment_dissection_depth.
3499 */
3500 prefs_register_uint_preference(gui_module, "max_tree_depth",
3501 "Maximum dissection depth",
3502 "The maximum depth for dissection tree and protocol layer checks. (Increase with caution)",
3503 10,
3504 &prefs.gui_max_tree_depth);
3505
3506 prefs_register_bool_preference(gui_module, "welcome_page.show_recent",
3507 "Show recent files on the welcome page",
3508 "This will enable or disable the 'Open' list on the welcome page.",
3509 &prefs.gui_welcome_page_show_recent);
3510
3511 /* User Interface : Layout */
3512 gui_layout_module = prefs_register_subtree(gui_module, "Layout", "Layout", gui_layout_callback);
3513 /* Adjust the preference effects of layout GUI for better handling of preferences at Wireshark (GUI) level */
3514 layout_gui_flags = prefs_get_module_effect_flags(gui_layout_module);
3515 layout_gui_flags |= PREF_EFFECT_GUI_LAYOUT(1u << 2);
3516 layout_gui_flags &= (~PREF_EFFECT_DISSECTION(1u << 0));
3517
3518 prefs_register_uint_preference(gui_layout_module, "layout_type",
3519 "Layout type",
3520 "Layout type (1-6)",
3521 10,
3522 (unsigned*)(void*)(&prefs.gui_layout_type));
3523 prefs_set_effect_flags_by_name(gui_layout_module, "layout_type", layout_gui_flags);
3524
3525 prefs_register_enum_preference(gui_layout_module, "layout_content_1",
3526 "Layout content of the pane 1",
3527 "Layout content of the pane 1",
3528 (int*)(void*)(&prefs.gui_layout_content_1), gui_layout_content, false0);
3529 prefs_set_effect_flags_by_name(gui_layout_module, "layout_content_1", layout_gui_flags);
3530
3531 prefs_register_enum_preference(gui_layout_module, "layout_content_2",
3532 "Layout content of the pane 2",
3533 "Layout content of the pane 2",
3534 (int*)(void*)(&prefs.gui_layout_content_2), gui_layout_content, false0);
3535 prefs_set_effect_flags_by_name(gui_layout_module, "layout_content_2", layout_gui_flags);
3536
3537 prefs_register_enum_preference(gui_layout_module, "layout_content_3",
3538 "Layout content of the pane 3",
3539 "Layout content of the pane 3",
3540 (int*)(void*)(&prefs.gui_layout_content_3), gui_layout_content, false0);
3541 prefs_set_effect_flags_by_name(gui_layout_module, "layout_content_3", layout_gui_flags);
3542
3543 prefs_register_bool_preference(gui_layout_module, "packet_list_separator.enabled",
3544 "Enable Packet List Separator",
3545 "Enable Packet List Separator",
3546 &prefs.gui_packet_list_separator);
3547
3548 prefs_register_bool_preference(gui_layout_module, "packet_header_column_definition.enabled",
3549 "Show column definition in packet list header",
3550 "Show column definition in packet list header",
3551 &prefs.gui_packet_header_column_definition);
3552
3553 /* packet_list_hover_style affects the colors, not the layout.
3554 * It's in the layout module to group it with the other packet list
3555 * preferences for the user's benefit with the dialog.
3556 */
3557 prefs_register_bool_preference(gui_layout_module, "packet_list_hover_style.enabled",
3558 "Enable Packet List mouse-over colorization",
3559 "Enable Packet List mouse-over colorization",
3560 &prefs.gui_packet_list_hover_style);
3561 prefs_set_effect_flags_by_name(gui_layout_module, "packet_list_hover_style.enabled", gui_color_effect_flags);
3562
3563 prefs_register_bool_preference(gui_layout_module, "show_selected_packet.enabled",
3564 "Show selected packet in the Status Bar",
3565 "Show selected packet in the Status Bar",
3566 &prefs.gui_show_selected_packet);
3567
3568 prefs_register_bool_preference(gui_layout_module, "show_file_load_time.enabled",
3569 "Show file load time in the Status Bar",
3570 "Show file load time in the Status Bar",
3571 &prefs.gui_show_file_load_time);
3572
3573 prefs_register_enum_preference(gui_layout_module, "packet_dialog_layout",
3574 "Packet Dialog layout",
3575 "Packet Dialog layout",
3576 (unsigned*)(void*)(&prefs.gui_packet_dialog_layout), gui_packet_dialog_layout, false0);
3577
3578 prefs_register_enum_preference(gui_module, "packet_list_elide_mode",
3579 "Elide mode",
3580 "The position of \"...\" (ellipsis) in packet list text.",
3581 (int*)(void*)(&prefs.gui_packet_list_elide_mode), gui_packet_list_elide_mode, false0);
3582 prefs_register_uint_preference(gui_module, "decimal_places1",
3583 "Count of decimal places for values of type 1",
3584 "Sets the count of decimal places for values of type 1."
3585 "Type 1 values are defined by authors."
3586 "Value can be in range 2 to 10.",
3587 10,&prefs.gui_decimal_places1);
3588
3589 prefs_register_uint_preference(gui_module, "decimal_places2",
3590 "Count of decimal places for values of type 2",
3591 "Sets the count of decimal places for values of type 2."
3592 "Type 2 values are defined by authors."
3593 "Value can be in range 2 to 10.",
3594 10,&prefs.gui_decimal_places2);
3595
3596 prefs_register_uint_preference(gui_module, "decimal_places3",
3597 "Count of decimal places for values of type 3",
3598 "Sets the count of decimal places for values of type 3."
3599 "Type 3 values are defined by authors."
3600 "Value can be in range 2 to 10.",
3601 10,&prefs.gui_decimal_places3);
3602
3603 prefs_register_bool_preference(gui_module, "rtp_player_use_disk1",
3604 "RTP Player saves temporary data to disk",
3605 "If set to true, RTP Player saves temporary data to "
3606 "temp files on disk. If not set, it uses memory."
3607 "Every stream uses one file therefore you might touch "
3608 "OS limit for count of opened files."
3609 "When ui.rtp_player_use_disk2 is set to true too, it uses "
3610 " two files per RTP stream together."
3611 ,&prefs.gui_rtp_player_use_disk1);
3612
3613 prefs_register_bool_preference(gui_module, "rtp_player_use_disk2",
3614 "RTP Player saves temporary dictionary for data to disk",
3615 "If set to true, RTP Player saves temporary dictionary to "
3616 "temp files on disk. If not set, it uses memory."
3617 "Every stream uses one file therefore you might touch "
3618 "OS limit for count of opened files."
3619 "When ui.rtp_player_use_disk1 is set to true too, it uses "
3620 " two files per RTP stream."
3621 ,&prefs.gui_rtp_player_use_disk2);
3622
3623 prefs_register_enum_preference(gui_layout_module, "gui_packet_list_copy_format_options_for_keyboard_shortcut",
3624 "Allows text to be copied with selected format",
3625 "Allows text to be copied with selected format when copied via keyboard",
3626 (int*)(void*)(&prefs.gui_packet_list_copy_format_options_for_keyboard_shortcut),
3627 gui_packet_list_copy_format_options_for_keyboard_shortcut, false0);
3628
3629 prefs_register_bool_preference(gui_layout_module, "gui_packet_list_copy_text_with_aligned_columns",
3630 "Allows text to be copied with aligned columns",
3631 "Allows text to be copied with aligned columns when copied via menu or keyboard",
3632 &prefs.gui_packet_list_copy_text_with_aligned_columns);
3633
3634 prefs_register_bool_preference(gui_layout_module, "packet_list_show_related",
3635 "Show Related Packets",
3636 "Show related packet indicators in the first column",
3637 &prefs.gui_packet_list_show_related);
3638
3639 prefs_register_bool_preference(gui_layout_module, "packet_list_show_minimap",
3640 "Enable Intelligent Scroll Bar",
3641 "Show the intelligent scroll bar (a minimap of packet list colors in the scrollbar)",
3642 &prefs.gui_packet_list_show_minimap);
3643
3644 prefs_register_bool_preference(gui_module, "packet_list_is_sortable",
3645 "Allow packet list to be sortable",
3646 "To prevent sorting by mistake (which can take some time to calculate), it can be disabled",
3647 &prefs.gui_packet_list_sortable);
3648
3649 prefs_register_uint_preference(gui_module, "packet_list_cached_rows_max",
3650 "Maximum cached rows",
3651 "Maximum number of rows that can be sorted by columns that require dissection. Increasing this increases memory consumption by caching column text",
3652 10,
3653 &prefs.gui_packet_list_cached_rows_max);
3654
3655 prefs_register_bool_preference(gui_module, "interfaces_show_hidden",
3656 "Show hidden interfaces",
3657 "Show all interfaces, including interfaces marked as hidden",
3658 &prefs.gui_interfaces_show_hidden);
3659
3660 prefs_register_bool_preference(gui_module, "interfaces_remote_display",
3661 "Show Remote interfaces",
3662 "Show remote interfaces in the interface selection",
3663 &prefs.gui_interfaces_remote_display);
3664
3665 register_string_like_preference(gui_module, "interfaces_hidden_types", "Hide interface types in list",
3666 "Hide the given interface types in the startup list.\n"
3667 "A comma-separated string of interface type values (e.g. 5,9).\n"
3668 "0 = Wired,\n"
3669 "1 = AirPCAP,\n"
3670 "2 = Pipe,\n"
3671 "3 = STDIN,\n"
3672 "4 = Bluetooth,\n"
3673 "5 = Wireless,\n"
3674 "6 = Dial-Up,\n"
3675 "7 = USB,\n"
3676 "8 = External Capture,\n"
3677 "9 = Virtual",
3678 &prefs.gui_interfaces_hide_types, PREF_STRING, NULL((void*)0), true1);
3679
3680 prefs_register_bool_preference(gui_module, "io_graph_automatic_update",
3681 "Enables automatic updates for IO Graph",
3682 "Enables automatic updates for IO Graph",
3683 &prefs.gui_io_graph_automatic_update);
3684
3685 prefs_register_bool_preference(gui_module, "io_graph_enable_legend",
3686 "Enables the legend of IO Graph",
3687 "Enables the legend of IO Graph",
3688 &prefs.gui_io_graph_enable_legend);
3689
3690 prefs_register_bool_preference(gui_module, "plot_automatic_update",
3691 "Enables automatic updates for Plot",
3692 "Enables automatic updates for Plot",
3693 &prefs.gui_plot_automatic_update);
3694
3695 prefs_register_bool_preference(gui_module, "plot_enable_legend",
3696 "Enables the legend of Plot",
3697 "Enables the legend of Plot",
3698 &prefs.gui_plot_enable_legend);
3699
3700 prefs_register_bool_preference(gui_module, "plot_enable_auto_scroll",
3701 "Enables auto scroll of Plot",
3702 "Enables auto scroll of Plot",
3703 &prefs.gui_plot_enable_auto_scroll);
3704
3705 prefs_register_bool_preference(gui_module, "show_byteview_in_dialog",
3706 "Show the byte view in the packet details dialog",
3707 "Show the byte view in the packet details dialog",
3708 &prefs.gui_packet_details_show_byteview);
3709
3710 /* Console
3711 * These are preferences that can be read/written using the
3712 * preference module API. These preferences still use their own
3713 * configuration screens for access, but this cuts down on the
3714 * preference "string compare list" in set_pref()
3715 */
3716 console_module = prefs_register_module(NULL((void*)0), "console", "Console",
3717 "Console logging and debugging output", NULL((void*)0), NULL((void*)0), false0);
3718
3719 prefs_register_obsolete_preference(console_module, "log.level");
3720
3721 prefs_register_bool_preference(console_module, "incomplete_dissectors_check_debug",
3722 "Print debug line for incomplete dissectors",
3723 "Look for dissectors that left some bytes undecoded (debug)",
3724 &prefs.incomplete_dissectors_check_debug);
3725
3726 /* Display filter Expressions
3727 * This used to be an array of individual fields that has now been
3728 * converted to a UAT. Just make it part of the GUI category even
3729 * though the name of the preference will never be seen in preference
3730 * file
3731 */
3732 filter_expression_register_uat(gui_module);
3733
3734 /* Capture
3735 * These are preferences that can be read/written using the
3736 * preference module API. These preferences still use their own
3737 * configuration screens for access, but this cuts down on the
3738 * preference "string compare list" in set_pref()
3739 */
3740 capture_module = prefs_register_module(NULL((void*)0), "capture", "Capture",
3741 "Capture preferences", NULL((void*)0), apply_aggregation_prefs, false0);
3742 /* Capture preferences don't affect dissection */
3743 prefs_set_module_effect_flags(capture_module, PREF_EFFECT_CAPTURE(1u << 1));
3744
3745 register_string_like_preference(capture_module, "device", "Default capture device",
3746 "Default capture device",
3747 &prefs.capture_device, PREF_STRING, NULL((void*)0), false0);
3748
3749 register_string_like_preference(capture_module, "devices_linktypes", "Interface link-layer header type",
3750 "Interface link-layer header types (Ex: en0(1),en1(143),...)",
3751 &prefs.capture_devices_linktypes, PREF_STRING, NULL((void*)0), false0);
3752
3753 register_string_like_preference(capture_module, "devices_descr", "Interface descriptions",
3754 "Interface descriptions (Ex: eth0(eth0 descr),eth1(eth1 descr),...)",
3755 &prefs.capture_devices_descr, PREF_STRING, NULL((void*)0), false0);
3756
3757 register_string_like_preference(capture_module, "devices_hide", "Hide interface",
3758 "Hide interface? (Ex: eth0,eth3,...)",
3759 &prefs.capture_devices_hide, PREF_STRING, NULL((void*)0), false0);
3760
3761 register_string_like_preference(capture_module, "devices_monitor_mode", "Capture in monitor mode",
3762 "By default, capture in monitor mode on interface? (Ex: eth0,eth3,...)",
3763 &prefs.capture_devices_monitor_mode, PREF_STRING, NULL((void*)0), false0);
3764
3765 register_string_like_preference(capture_module, "devices_buffersize", "Interface buffer size",
3766 "Interface buffer size (Ex: en0(1),en1(143),...)",
3767 &prefs.capture_devices_buffersize, PREF_STRING, NULL((void*)0), false0);
3768
3769 register_string_like_preference(capture_module, "devices_snaplen", "Interface snap length",
3770 "Interface snap length (Ex: en0(65535),en1(1430),...)",
3771 &prefs.capture_devices_snaplen, PREF_STRING, NULL((void*)0), false0);
3772
3773 register_string_like_preference(capture_module, "devices_pmode", "Interface promiscuous mode",
3774 "Interface promiscuous mode (Ex: en0(0),en1(1),...)",
3775 &prefs.capture_devices_pmode, PREF_STRING, NULL((void*)0), false0);
3776
3777 prefs_register_bool_preference(capture_module, "prom_mode", "Capture in promiscuous mode",
3778 "Capture in promiscuous mode?", &prefs.capture_prom_mode);
3779
3780 prefs_register_bool_preference(capture_module, "monitor_mode", "Capture in monitor mode on 802.11 devices",
3781 "Capture in monitor mode on all 802.11 devices that support it?", &prefs.capture_monitor_mode);
3782
3783 register_string_like_preference(capture_module, "devices_filter", "Interface capture filter",
3784 "Interface capture filter (Ex: en0(tcp),en1(udp),...)",
3785 &prefs.capture_devices_filter, PREF_STRING, NULL((void*)0), false0);
3786
3787 prefs_register_bool_preference(capture_module, "pcap_ng", "Capture in pcapng format",
3788 "Capture in pcapng format?", &prefs.capture_pcap_ng);
3789
3790 prefs_register_bool_preference(capture_module, "real_time_update", "Update packet list in real time during capture",
3791 "Update packet list in real time during capture?", &prefs.capture_real_time);
3792
3793 prefs_register_uint_preference(capture_module, "update_interval",
3794 "Capture update interval",
3795 "Capture update interval in ms",
3796 10,
3797 &prefs.capture_update_interval);
3798
3799 prefs_register_bool_preference(capture_module, "enable_aggregation_view", "Enable aggregation view",
3800 "Enable Aggregation View for real-time capturing", &prefs.enable_aggregation);
3801
3802 prefs_register_bool_preference(capture_module, "no_interface_load", "Don't load interfaces on startup",
3803 "Don't automatically load capture interfaces on startup", &prefs.capture_no_interface_load);
3804
3805 prefs_register_bool_preference(capture_module, "no_extcap", "Disable external capture interfaces",
3806 "Disable external capture modules (extcap)", &prefs.capture_no_extcap);
3807
3808 prefs_register_obsolete_preference(capture_module, "auto_scroll");
3809
3810 prefs_register_bool_preference(capture_module, "show_info", "Show capture information dialog while capturing",
3811 "Show capture information dialog while capturing?", &prefs.capture_show_info);
3812
3813 prefs_register_obsolete_preference(capture_module, "syntax_check_filter");
3814
3815 custom_cbs.free_cb = capture_column_free_cb;
3816 custom_cbs.reset_cb = capture_column_reset_cb;
3817 custom_cbs.set_cb = capture_column_set_cb;
3818 custom_cbs.type_name_cb = capture_column_type_name_cb;
3819 custom_cbs.type_description_cb = capture_column_type_description_cb;
3820 custom_cbs.is_default_cb = capture_column_is_default_cb;
3821 custom_cbs.to_str_cb = capture_column_to_str_cb;
3822 prefs_register_list_custom_preference(capture_module, "columns", "Capture options dialog column list",
3823 "List of columns to be displayed", &custom_cbs, capture_column_init_cb, &prefs.capture_columns);
3824 aggregation_field_register_uat(capture_module);
3825
3826 /* Name Resolution */
3827 nameres_module = prefs_register_module(NULL((void*)0), "nameres", "Name Resolution",
3828 "Name Resolution", "ChCustPreferencesSection.html#ChCustPrefsNameSection", addr_resolve_pref_apply, true1);
3829 addr_resolve_pref_init(nameres_module);
3830 oid_pref_init(nameres_module);
3831 maxmind_db_pref_init(nameres_module);
3832
3833 /* Printing
3834 * None of these have any effect; we keep them as obsolete preferences
3835 * in order to avoid errors when reading older preference files.
3836 */
3837 printing = prefs_register_module(NULL((void*)0), "print", "Printing",
3838 "Printing", NULL((void*)0), NULL((void*)0), false0);
3839 prefs_register_obsolete_preference(printing, "format");
3840 prefs_register_obsolete_preference(printing, "command");
3841 prefs_register_obsolete_preference(printing, "file");
3842
3843 /* Codecs */
3844 codecs_module = prefs_register_module(NULL((void*)0), "codecs", "Codecs",
3845 "Codecs", NULL((void*)0), NULL((void*)0), true1);
3846
3847 /* Statistics */
3848 stats_module = prefs_register_module(NULL((void*)0), "statistics", "Statistics",
3849 "Statistics", "ChCustPreferencesSection.html#_statistics", &stats_callback, true1);
3850
3851 prefs_register_uint_preference(stats_module, "update_interval",
3852 "Tap update interval in ms",
3853 "Determines time between tap updates",
3854 10,
3855 &prefs.tap_update_interval);
3856
3857 prefs_register_uint_preference(stats_module, "flow_graph_max_export_items",
3858 "Maximum Flow Graph items to export as image",
3859 "The maximum number of Flow Graph items (frames) "
3860 "to include when exporting the graph as an image. "
3861 "Note that some formats (e.g., JPEG) have inherent "
3862 "pixel limits and image viewers might be unable to "
3863 "handle very large images.",
3864 10,
3865 &prefs.flow_graph_max_export_items);
3866
3867 prefs_register_bool_preference(stats_module, "st_enable_burstinfo",
3868 "Enable the calculation of burst information",
3869 "If enabled burst rates will be calculated for statistics that use the stats_tree system. "
3870 "Burst rates are calculated over a much shorter time interval than the rate column.",
3871 &prefs.st_enable_burstinfo);
3872
3873 prefs_register_bool_preference(stats_module, "st_burst_showcount",
3874 "Show burst count for item rather than rate",
3875 "If selected the stats_tree statistics nodes will show the count of events "
3876 "within the burst window instead of a burst rate. Burst rate is calculated "
3877 "as number of events within burst window divided by the burst windown length.",
3878 &prefs.st_burst_showcount);
3879
3880 prefs_register_uint_preference(stats_module, "st_burst_resolution",
3881 "Burst rate resolution (ms)",
3882 "Sets the duration of the time interval into which events are grouped when calculating "
3883 "the burst rate. Higher resolution (smaller number) increases processing overhead.",
3884 10,&prefs.st_burst_resolution);
3885
3886 prefs_register_uint_preference(stats_module, "st_burst_windowlen",
3887 "Burst rate window size (ms)",
3888 "Sets the duration of the sliding window during which the burst rate is "
3889 "measured. Longer window relative to burst rate resolution increases "
3890 "processing overhead. Will be truncated to a multiple of burst resolution.",
3891 10,&prefs.st_burst_windowlen);
3892
3893 prefs_register_enum_preference(stats_module, "st_sort_defcolflag",
3894 "Default sort column for stats_tree stats",
3895 "Sets the default column by which stats based on the stats_tree "
3896 "system is sorted.",
3897 &prefs.st_sort_defcolflag, st_sort_col_vals, false0);
3898
3899 prefs_register_bool_preference(stats_module, "st_sort_defdescending",
3900 "Default stats_tree sort order is descending",
3901 "When selected, statistics based on the stats_tree system will by default "
3902 "be sorted in descending order.",
3903 &prefs.st_sort_defdescending);
3904
3905 prefs_register_bool_preference(stats_module, "st_sort_casesensitve",
3906 "Case sensitive sort of stats_tree item names",
3907 "When selected, the item/node names of statistics based on the stats_tree "
3908 "system will be sorted taking case into account. Else the case of the name "
3909 "will be ignored.",
3910 &prefs.st_sort_casesensitve);
3911
3912 prefs_register_bool_preference(stats_module, "st_sort_rng_nameonly",
3913 "Always sort 'range' nodes by name",
3914 "When selected, the stats_tree nodes representing a range of values "
3915 "(0-49, 50-100, etc.) will always be sorted by name (the range of the "
3916 "node). Else range nodes are sorted by the same column as the rest of "
3917 " the tree.",
3918 &prefs.st_sort_rng_nameonly);
3919
3920 prefs_register_bool_preference(stats_module, "st_sort_rng_fixorder",
3921 "Always sort 'range' nodes in ascending order",
3922 "When selected, the stats_tree nodes representing a range of values "
3923 "(0-49, 50-100, etc.) will always be sorted ascending; else it follows "
3924 "the sort direction of the tree. Only effective if \"Always sort "
3925 "'range' nodes by name\" is also selected.",
3926 &prefs.st_sort_rng_fixorder);
3927
3928 prefs_register_bool_preference(stats_module, "st_sort_showfullname",
3929 "Display the full stats_tree plug-in name",
3930 "When selected, the full name (including menu path) of the stats_tree "
3931 "plug-in is show in windows. If cleared the plug-in name is shown "
3932 "without menu path (only the part of the name after last '/' character.)",
3933 &prefs.st_sort_showfullname);
3934
3935 prefs_register_enum_preference(stats_module, "output_format",
3936 "Default output format",
3937 "Sets the default output format for statistical data. Only supported "
3938 "by taps using the stats_tree system currently; other taps may honor "
3939 "this preference in the future. ",
3940 &prefs.st_format, st_format_vals, false0);
3941
3942 module_t *conv_module;
3943 // avoid using prefs_register_stat to prevent lint complaint about recursion
3944 conv_module = prefs_register_module(stats_module, "conv", "Conversations",
3945 "Conversations & Endpoints", NULL((void*)0), NULL((void*)0), true1);
3946 prefs_register_bool_preference(conv_module, "machine_readable",
3947 "Display exact (machine-readable) byte counts",
3948 "When enabled, exact machine-readable byte counts are displayed. "
3949 "When disabled, human readable numbers with SI prefixes are displayed.",
3950 &prefs.conv_machine_readable);
3951
3952 /* Protocols */
3953 protocols_module = prefs_register_module(NULL((void*)0), "protocols", "Protocols",
3954 "Protocols", "ChCustPreferencesSection.html#ChCustPrefsProtocolsSection", NULL((void*)0), true1);
3955
3956 prefs_register_bool_preference(protocols_module, "display_hidden_proto_items",
3957 "Display hidden protocol items",
3958 "Display all hidden protocol items in the packet list.",
3959 &prefs.display_hidden_proto_items);
3960
3961 prefs_register_bool_preference(protocols_module, "display_byte_fields_with_spaces",
3962 "Display byte fields with a space character between bytes",
3963 "Display all byte fields with a space character between each byte in the packet list.",
3964 &prefs.display_byte_fields_with_spaces);
3965
3966 /*
3967 * Note the -t / option only affects the display of the packet timestamp
3968 * in the default time column; this is for all other absolute times.
3969 */
3970 prefs_register_enum_preference(protocols_module, "display_abs_time_ascii",
3971 "Format absolute times like asctime",
3972 "When to format absolute times similar to asctime instead of ISO 8601, for backwards compatibility with older Wireshark.",
3973 (int*)&prefs.display_abs_time_ascii, abs_time_format_options, false0);
3974
3975 prefs_register_bool_preference(protocols_module, "enable_incomplete_dissectors_check",
3976 "Look for incomplete dissectors",
3977 "Look for dissectors that left some bytes undecoded.",
3978 &prefs.enable_incomplete_dissectors_check);
3979
3980 prefs_register_bool_preference(protocols_module, "strict_conversation_tracking_heuristics",
3981 "Enable stricter conversation tracking heuristics",
3982 "Protocols may use things like VLAN ID or interface ID to narrow the potential for duplicate conversations. "
3983 "Currently ICMP and ICMPv6 use this preference to add VLAN ID to conversation tracking, and IPv4 uses this preference to take VLAN ID into account during reassembly",
3984 &prefs.strict_conversation_tracking_heuristics);
3985
3986 prefs_register_bool_preference(protocols_module, "ignore_dup_frames",
3987 "Ignore duplicate frames",
3988 "Ignore frames that are exact duplicates of any previous frame.",
3989 &prefs.ignore_dup_frames);
3990
3991 prefs_register_enum_preference(protocols_module, "conversation_deinterlacing_key",
3992 "Deinterlacing conversations key",
3993 "Separate into different conversations frames that look like duplicates but have different Interface, MAC, or VLAN field values.",
3994 (int *)&prefs.conversation_deinterlacing_key, conv_deint_options, false0);
3995
3996 prefs_register_uint_preference(protocols_module, "ignore_dup_frames_cache_entries",
3997 "The max number of hashes to keep in memory for determining duplicates frames",
3998 "If \"Ignore duplicate frames\" is set, this setting sets the maximum number "
3999 "of cache entries to maintain. A 0 means no limit.",
4000 10, &prefs.ignore_dup_frames_cache_entries);
4001
4002
4003 /* Obsolete preferences
4004 * These "modules" were reorganized/renamed to correspond to their GUI
4005 * configuration screen within the preferences dialog
4006 */
4007
4008 /* taps is now part of the stats module */
4009 prefs_register_module(NULL((void*)0), "taps", "TAPS", "TAPS", NULL((void*)0), NULL((void*)0), false0);
4010 /* packet_list is now part of the protocol (parent) module */
4011 prefs_register_module(NULL((void*)0), "packet_list", "PACKET_LIST", "PACKET_LIST", NULL((void*)0), NULL((void*)0), false0);
4012 /* stream is now part of the gui module */
4013 prefs_register_module(NULL((void*)0), "stream", "STREAM", "STREAM", NULL((void*)0), NULL((void*)0), false0);
4014
4015}
4016
4017/* Parse through a list of comma-separated, possibly quoted strings.
4018 Return a list of the string data. */
4019GList *
4020prefs_get_string_list(const char *str)
4021{
4022 enum { PRE_STRING, IN_QUOT, NOT_IN_QUOT };
4023
4024 int state = PRE_STRING, i = 0;
4025 bool_Bool backslash = false0;
4026 unsigned char cur_c;
4027 const size_t default_size = 64;
4028 GString *slstr = NULL((void*)0);
4029 GList *sl = NULL((void*)0);
4030
4031 /* Allocate a buffer for the first string. */
4032 slstr = g_string_sized_new(default_size);
4033
4034 for (;;) {
4035 cur_c = str[i];
4036 if (cur_c == '\0') {
4037 /* It's the end of the input, so it's the end of the string we
4038 were working on, and there's no more input. */
4039 if (state == IN_QUOT || backslash) {
4040 /* We were in the middle of a quoted string or backslash escape,
4041 and ran out of characters; that's an error. */
4042 g_string_free(slstr, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(slstr), ((!(0)))) : g_string_free_and_steal (slstr)) : (g_string_free
) ((slstr), ((!(0)))))
;
4043 prefs_clear_string_list(sl);
4044 return NULL((void*)0);
4045 }
4046 if (slstr->len > 0)
4047 sl = g_list_append(sl, g_string_free(slstr, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((slstr
), ((0))) : g_string_free_and_steal (slstr)) : (g_string_free
) ((slstr), ((0))))
);
4048 else
4049 g_string_free(slstr, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(slstr), ((!(0)))) : g_string_free_and_steal (slstr)) : (g_string_free
) ((slstr), ((!(0)))))
;
4050 break;
4051 }
4052 if (cur_c == '"' && !backslash) {
4053 switch (state) {
4054 case PRE_STRING:
4055 /* We hadn't yet started processing a string; this starts the
4056 string, and we're now quoting. */
4057 state = IN_QUOT;
4058 break;
4059 case IN_QUOT:
4060 /* We're in the middle of a quoted string, and we saw a quotation
4061 mark; we're no longer quoting. */
4062 state = NOT_IN_QUOT;
4063 break;
4064 case NOT_IN_QUOT:
4065 /* We're working on a string, but haven't seen a quote; we're
4066 now quoting. */
4067 state = IN_QUOT;
4068 break;
4069 default:
4070 break;
4071 }
4072 } else if (cur_c == '\\' && !backslash) {
4073 /* We saw a backslash, and the previous character wasn't a
4074 backslash; escape the next character.
4075
4076 This also means we've started a new string. */
4077 backslash = true1;
4078 if (state == PRE_STRING)
4079 state = NOT_IN_QUOT;
4080 } else if (cur_c == ',' && state != IN_QUOT && !backslash) {
4081 /* We saw a comma, and we're not in the middle of a quoted string
4082 and it wasn't preceded by a backslash; it's the end of
4083 the string we were working on... */
4084 if (slstr->len > 0) {
4085 sl = g_list_append(sl, g_string_free(slstr, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((slstr
), ((0))) : g_string_free_and_steal (slstr)) : (g_string_free
) ((slstr), ((0))))
);
4086 slstr = g_string_sized_new(default_size);
4087 }
4088
4089 /* ...and the beginning of a new string. */
4090 state = PRE_STRING;
4091 } else if (!g_ascii_isspace(cur_c)((g_ascii_table[(guchar) (cur_c)] & G_ASCII_SPACE) != 0) || state != PRE_STRING) {
4092 /* Either this isn't a white-space character, or we've started a
4093 string (i.e., already seen a non-white-space character for that
4094 string and put it into the string).
4095
4096 The character is to be put into the string; do so. */
4097 g_string_append_c(slstr, cur_c)g_string_append_c_inline (slstr, cur_c);
4098
4099 /* If it was backslash-escaped, we're done with the backslash escape. */
4100 backslash = false0;
4101 }
4102 i++;
4103 }
4104 return(sl);
4105}
4106
4107char *join_string_list(GList *sl)
4108{
4109 GString *joined_str = g_string_new("");
4110 GList *cur, *first;
4111 char *str;
4112 unsigned item_count = 0;
4113
4114 cur = first = g_list_first(sl);
4115 while (cur) {
4116 item_count++;
4117 str = (char *)cur->data;
4118
4119 if (cur != first)
4120 g_string_append_c(joined_str, ',')g_string_append_c_inline (joined_str, ',');
4121
4122 if (item_count % 2) {
4123 /* Wrap the line. */
4124 g_string_append(joined_str, "\n\t")(__builtin_constant_p ("\n\t") ? __extension__ ({ const char *
const __val = ("\n\t"); g_string_append_len_inline (joined_str
, __val, (__val != ((void*)0)) ? (gssize) strlen (((__val) + !
(__val))) : (gssize) -1); }) : g_string_append_len_inline (joined_str
, "\n\t", (gssize) -1))
;
4125 } else
4126 g_string_append_c(joined_str, ' ')g_string_append_c_inline (joined_str, ' ');
4127
4128 g_string_append_c(joined_str, '"')g_string_append_c_inline (joined_str, '"');
4129 while (*str) {
4130 gunichar uc = g_utf8_get_char (str);
4131
4132 if (uc == '"' || uc == '\\')
4133 g_string_append_c(joined_str, '\\')g_string_append_c_inline (joined_str, '\\');
4134
4135 if (g_unichar_isprint(uc))
4136 g_string_append_unichar (joined_str, uc);
4137
4138 str = g_utf8_next_char (str)(char *)((str) + g_utf8_skip[*(const guchar *)(str)]);
4139 }
4140
4141 g_string_append_c(joined_str, '"')g_string_append_c_inline (joined_str, '"');
4142
4143 cur = cur->next;
4144 }
4145 return g_string_free(joined_str, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((joined_str
), ((0))) : g_string_free_and_steal (joined_str)) : (g_string_free
) ((joined_str), ((0))))
;
4146}
4147
4148void
4149prefs_clear_string_list(GList *sl)
4150{
4151 g_list_free_full(sl, g_free);
4152}
4153
4154/*
4155 * Takes a string, a pointer to an array of "enum_val_t"s, and a default int
4156 * value.
4157 * The array must be terminated by an entry with a null "name" string.
4158 *
4159 * If the string matches a "name" string in an entry, the value from that
4160 * entry is returned.
4161 *
4162 * Otherwise, if a string matches a "description" string in an entry, the
4163 * value from that entry is returned; we do that for backwards compatibility,
4164 * as we used to have only a "name" string that was used both for command-line
4165 * and configuration-file values and in the GUI (which meant either that
4166 * the GUI had what might be somewhat cryptic values to select from or that
4167 * the "-o" flag took long strings, often with spaces in them).
4168 *
4169 * Otherwise, the default value that was passed as the third argument is
4170 * returned.
4171 */
4172static int
4173find_val_for_string(const char *needle, const enum_val_t *haystack,
4174 int default_value)
4175{
4176 int i;
4177
4178 for (i = 0; haystack[i].name != NULL((void*)0); i++) {
4179 if (g_ascii_strcasecmp(needle, haystack[i].name) == 0) {
4180 return haystack[i].value;
4181 }
4182 }
4183 for (i = 0; haystack[i].name != NULL((void*)0); i++) {
4184 if (g_ascii_strcasecmp(needle, haystack[i].description) == 0) {
4185 return haystack[i].value;
4186 }
4187 }
4188 return default_value;
4189}
4190
4191/* Preferences file format:
4192 * - Configuration directives start at the beginning of the line, and
4193 * are terminated with a colon.
4194 * - Directives can be continued on the next line by preceding them with
4195 * whitespace.
4196 *
4197 * Example:
4198
4199# This is a comment line
4200print.command: lpr
4201print.file: /a/very/long/path/
4202 to/wireshark-out.ps
4203 *
4204 */
4205
4206/*
4207 * Initialize non-dissector preferences used by the "register preference" API
4208 * to default values so the default values can be used when registered.
4209 *
4210 * String, filename, and directory preferences will be g_freed so they must
4211 * be g_mallocated.
4212 */
4213static void
4214prefs_set_global_defaults(const char** col_fmt, int num_cols)
4215{
4216 int i;
4217 char *col_name;
4218 fmt_data *cfmt;
4219
4220 prefs.restore_filter_after_following_stream = false0;
4221 prefs.gui_toolbar_main_style = TB_STYLE_ICONS0;
4222 /* We try to find the best font in the Qt code */
4223 g_free(prefs.gui_font_name);
4224 prefs.gui_font_name = g_strdup("")g_strdup_inline ("");
4225 prefs.gui_active_fg.red = 0;
4226 prefs.gui_active_fg.green = 0;
4227 prefs.gui_active_fg.blue = 0;
4228 prefs.gui_active_bg.red = 52223;
4229 prefs.gui_active_bg.green = 59647;
4230 prefs.gui_active_bg.blue = 65535;
4231 prefs.gui_active_style = COLOR_STYLE_DEFAULT0;
4232 prefs.gui_inactive_fg.red = 0;
4233 prefs.gui_inactive_fg.green = 0;
4234 prefs.gui_inactive_fg.blue = 0;
4235 prefs.gui_inactive_bg.red = 61439;
4236 prefs.gui_inactive_bg.green = 61439;
4237 prefs.gui_inactive_bg.blue = 61439;
4238 prefs.gui_inactive_style = COLOR_STYLE_DEFAULT0;
4239 prefs.gui_marked_fg.red = 65535;
4240 prefs.gui_marked_fg.green = 65535;
4241 prefs.gui_marked_fg.blue = 65535;
4242 prefs.gui_marked_bg.red = 0;
4243 prefs.gui_marked_bg.green = 8224;
4244 prefs.gui_marked_bg.blue = 10794;
4245 prefs.gui_ignored_fg.red = 32767;
4246 prefs.gui_ignored_fg.green = 32767;
4247 prefs.gui_ignored_fg.blue = 32767;
4248 prefs.gui_ignored_bg.red = 65535;
4249 prefs.gui_ignored_bg.green = 65535;
4250 prefs.gui_ignored_bg.blue = 65535;
4251 g_free(prefs.gui_colorized_fg);
4252 prefs.gui_colorized_fg = g_strdup("000000,000000,000000,000000,000000,000000,000000,000000,000000,000000")g_strdup_inline ("000000,000000,000000,000000,000000,000000,000000,000000,000000,000000"
)
;
4253 g_free(prefs.gui_colorized_bg);
4254 prefs.gui_colorized_bg = g_strdup("ffc0c0,ffc0ff,e0c0e0,c0c0ff,c0e0e0,c0ffff,c0ffc0,ffffc0,e0e0c0,e0e0e0")g_strdup_inline ("ffc0c0,ffc0ff,e0c0e0,c0c0ff,c0e0e0,c0ffff,c0ffc0,ffffc0,e0e0c0,e0e0e0"
)
;
4255 prefs.st_client_fg.red = 32767;
4256 prefs.st_client_fg.green = 0;
4257 prefs.st_client_fg.blue = 0;
4258 prefs.st_client_bg.red = 64507;
4259 prefs.st_client_bg.green = 60909;
4260 prefs.st_client_bg.blue = 60909;
4261 prefs.st_server_fg.red = 0;
4262 prefs.st_server_fg.green = 0;
4263 prefs.st_server_fg.blue = 32767;
4264 prefs.st_server_bg.red = 60909;
4265 prefs.st_server_bg.green = 60909;
4266 prefs.st_server_bg.blue = 64507;
4267
4268 if (gui_theme_is_dark) {
4269 // Green, red and yellow with HSV V = 84
4270 prefs.gui_filter_valid_bg.red = 0x0000; /* dark green */
4271 prefs.gui_filter_valid_bg.green = 0x66ff;
4272 prefs.gui_filter_valid_bg.blue = 0x0000;
4273 prefs.gui_filter_valid_fg.red = 0xFFFF;
4274 prefs.gui_filter_valid_fg.green = 0xFFFF;
4275 prefs.gui_filter_valid_fg.blue = 0xFFFF;
4276 prefs.gui_filter_invalid_bg.red = 0x66FF; /* dark red */
4277 prefs.gui_filter_invalid_bg.green = 0x0000;
4278 prefs.gui_filter_invalid_bg.blue = 0x0000;
4279 prefs.gui_filter_invalid_fg.red = 0xFFFF;
4280 prefs.gui_filter_invalid_fg.green = 0xFFFF;
4281 prefs.gui_filter_invalid_fg.blue = 0xFFFF;
4282 prefs.gui_filter_deprecated_bg.red = 0x66FF; /* dark yellow / olive */
4283 prefs.gui_filter_deprecated_bg.green = 0x66FF;
4284 prefs.gui_filter_deprecated_bg.blue = 0x0000;
4285 prefs.gui_filter_deprecated_fg.red = 0xFFFF;
4286 prefs.gui_filter_deprecated_fg.green = 0xFFFF;
4287 prefs.gui_filter_deprecated_fg.blue = 0xFFFF;
4288 } else {
4289 // Green, red and yellow with HSV V = 20
4290 prefs.gui_filter_valid_bg.red = 0xAFFF; /* light green */
4291 prefs.gui_filter_valid_bg.green = 0xFFFF;
4292 prefs.gui_filter_valid_bg.blue = 0xAFFF;
4293 prefs.gui_filter_valid_fg.red = 0x0000;
4294 prefs.gui_filter_valid_fg.green = 0x0000;
4295 prefs.gui_filter_valid_fg.blue = 0x0000;
4296 prefs.gui_filter_invalid_bg.red = 0xFFFF; /* light red */
4297 prefs.gui_filter_invalid_bg.green = 0xAFFF;
4298 prefs.gui_filter_invalid_bg.blue = 0xAFFF;
4299 prefs.gui_filter_invalid_fg.red = 0x0000;
4300 prefs.gui_filter_invalid_fg.green = 0x0000;
4301 prefs.gui_filter_invalid_fg.blue = 0x0000;
4302 prefs.gui_filter_deprecated_bg.red = 0xFFFF; /* light yellow */
4303 prefs.gui_filter_deprecated_bg.green = 0xFFFF;
4304 prefs.gui_filter_deprecated_bg.blue = 0xAFFF;
4305 prefs.gui_filter_deprecated_fg.red = 0x0000;
4306 prefs.gui_filter_deprecated_fg.green = 0x0000;
4307 prefs.gui_filter_deprecated_fg.blue = 0x0000;
4308 }
4309
4310 prefs.gui_geometry_save_position = true1;
4311 prefs.gui_geometry_save_size = true1;
4312 prefs.gui_geometry_save_maximized= true1;
4313 prefs.gui_fileopen_style = FO_STYLE_LAST_OPENED0;
4314 prefs.gui_recent_df_entries_max = 10;
4315 prefs.gui_recent_files_count_max = 10;
4316 g_free(prefs.gui_fileopen_dir);
4317 prefs.gui_fileopen_dir = g_strdup(get_persdatafile_dir())g_strdup_inline (get_persdatafile_dir());
4318 prefs.gui_fileopen_preview = 3;
4319 g_free(prefs.gui_tlskeylog_command);
4320 prefs.gui_tlskeylog_command = g_strdup("")g_strdup_inline ("");
4321 prefs.gui_ask_unsaved = true1;
4322 prefs.gui_autocomplete_filter = true1;
4323 prefs.gui_find_wrap = true1;
4324 prefs.gui_update_enabled = true1;
4325 prefs.gui_update_channel = UPDATE_CHANNEL_STABLE;
4326 prefs.gui_update_interval = 60*60*24; /* Seconds */
4327 prefs.gui_debounce_timer = 400; /* milliseconds */
4328 g_free(prefs.gui_window_title);
4329 prefs.gui_window_title = g_strdup("")g_strdup_inline ("");
4330 g_free(prefs.gui_prepend_window_title);
4331 prefs.gui_prepend_window_title = g_strdup("")g_strdup_inline ("");
4332 g_free(prefs.gui_start_title);
4333 prefs.gui_start_title = g_strdup("The World's Most Popular Network Protocol Analyzer")g_strdup_inline ("The World's Most Popular Network Protocol Analyzer"
)
;
4334 prefs.gui_version_placement = version_both;
4335 prefs.gui_welcome_page_show_recent = true1;
4336 prefs.gui_layout_type = layout_type_2;
4337 prefs.gui_layout_content_1 = layout_pane_content_plist;
4338 prefs.gui_layout_content_2 = layout_pane_content_pdetails;
4339 prefs.gui_layout_content_3 = layout_pane_content_pbytes;
4340 prefs.gui_packet_list_elide_mode = ELIDE_RIGHT;
4341 prefs.gui_packet_list_copy_format_options_for_keyboard_shortcut = COPY_FORMAT_TEXT;
4342 prefs.gui_packet_list_copy_text_with_aligned_columns = false0;
4343 prefs.gui_packet_list_show_related = true1;
4344 prefs.gui_packet_list_show_minimap = true1;
4345 prefs.gui_packet_list_sortable = true1;
4346 prefs.gui_packet_list_cached_rows_max = 10000;
4347 g_free (prefs.gui_interfaces_hide_types);
4348 prefs.gui_interfaces_hide_types = g_strdup("")g_strdup_inline ("");
4349 prefs.gui_interfaces_show_hidden = false0;
4350 prefs.gui_interfaces_remote_display = true1;
4351 prefs.gui_packet_list_separator = false0;
4352 prefs.gui_packet_header_column_definition = true1;
4353 prefs.gui_packet_list_hover_style = true1;
4354 prefs.gui_show_selected_packet = false0;
4355 prefs.gui_show_file_load_time = false0;
4356 prefs.gui_max_export_objects = 1000;
4357 prefs.gui_max_tree_items = 1 * 1000 * 1000;
4358 prefs.gui_max_tree_depth = 5 * 100;
4359 prefs.gui_decimal_places1 = DEF_GUI_DECIMAL_PLACES12;
4360 prefs.gui_decimal_places2 = DEF_GUI_DECIMAL_PLACES24;
4361 prefs.gui_decimal_places3 = DEF_GUI_DECIMAL_PLACES36;
4362
4363 if (prefs.col_list) {
4364 free_col_info(prefs.col_list);
4365 prefs.col_list = NULL((void*)0);
4366 }
4367 for (i = 0; i < num_cols; i++) {
4368 cfmt = g_new0(fmt_data,1)((fmt_data *) g_malloc0_n ((1), sizeof (fmt_data)));
4369 cfmt->title = g_strdup(col_fmt[i * 2])g_strdup_inline (col_fmt[i * 2]);
4370 cfmt->visible = true1;
4371 cfmt->display = COLUMN_DISPLAY_STRINGS'R';
4372 parse_column_format(cfmt, col_fmt[(i * 2) + 1]);
4373 prefs.col_list = g_list_append(prefs.col_list, cfmt);
4374 }
4375 prefs.num_cols = num_cols;
4376
4377/* set the default values for the capture dialog box */
4378 prefs.capture_prom_mode = true1;
4379 prefs.capture_monitor_mode = false0;
4380 prefs.capture_pcap_ng = true1;
4381 prefs.capture_real_time = true1;
4382 prefs.capture_update_interval = DEFAULT_UPDATE_INTERVAL100;
4383 prefs.capture_no_extcap = false0;
4384 prefs.capture_show_info = false0;
4385 prefs.enable_aggregation = false0;
4386
4387 if (!prefs.capture_columns) {
4388 /* First time through */
4389 for (i = 0; i < num_capture_cols; i++) {
4390 col_name = g_strdup(capture_cols[i])g_strdup_inline (capture_cols[i]);
4391 prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
4392 }
4393 }
4394
4395/* set the default values for the tap/statistics dialog box */
4396 prefs.tap_update_interval = TAP_UPDATE_DEFAULT_INTERVAL3000;
4397 prefs.flow_graph_max_export_items = 1000;
4398 prefs.st_enable_burstinfo = true1;
4399 prefs.st_burst_showcount = false0;
4400 prefs.st_burst_resolution = ST_DEF_BURSTRES5;
4401 prefs.st_burst_windowlen = ST_DEF_BURSTLEN100;
4402 prefs.st_sort_casesensitve = true1;
4403 prefs.st_sort_rng_fixorder = true1;
4404 prefs.st_sort_rng_nameonly = true1;
4405 prefs.st_sort_defcolflag = ST_SORT_COL_COUNT2;
4406 prefs.st_sort_defdescending = true1;
4407 prefs.st_sort_showfullname = false0;
4408 prefs.conv_machine_readable = false0;
4409
4410 /* protocols */
4411 prefs.display_hidden_proto_items = false0;
4412 prefs.display_byte_fields_with_spaces = false0;
4413 prefs.display_abs_time_ascii = ABS_TIME_ASCII_TREE;
4414 prefs.ignore_dup_frames = false0;
4415 prefs.ignore_dup_frames_cache_entries = 10000;
4416
4417 /* set the default values for the io graph dialog */
4418 prefs.gui_io_graph_automatic_update = true1;
4419 prefs.gui_io_graph_enable_legend = true1;
4420
4421 /* set the default values for the plot dialog */
4422 prefs.gui_plot_automatic_update = true1;
4423 prefs.gui_plot_enable_legend = true1;
4424 prefs.gui_plot_enable_auto_scroll = false0;
4425
4426 /* set the default values for the packet dialog */
4427 prefs.gui_packet_dialog_layout = layout_vertical;
4428 prefs.gui_packet_details_show_byteview = true1;
4429}
4430
4431/*
4432 * Reset a single dissector preference.
4433 */
4434void
4435reset_pref(pref_t *pref)
4436{
4437 if (!pref) return;
4438
4439 /*
4440 * This preference is no longer supported; it's not a
4441 * real preference, so we don't reset it (i.e., we
4442 * treat it as if it weren't found in the list of
4443 * preferences, and we weren't called in the first place).
4444 */
4445 if (pref->obsolete)
4446 return;
4447
4448 switch (pref->type) {
4449
4450 case PREF_UINT:
4451 *pref->varp.uint = pref->default_val.uint;
4452 break;
4453
4454 case PREF_BOOL:
4455 *pref->varp.boolp = pref->default_val.boolval;
4456 break;
4457
4458 case PREF_ENUM:
4459 case PREF_PROTO_TCP_SNDAMB_ENUM:
4460 *pref->varp.enump = pref->default_val.enumval;
4461 break;
4462
4463 case PREF_STRING:
4464 case PREF_SAVE_FILENAME:
4465 case PREF_OPEN_FILENAME:
4466 case PREF_DIRNAME:
4467 case PREF_PASSWORD:
4468 case PREF_DISSECTOR:
4469 reset_string_like_preference(pref);
4470 break;
4471
4472 case PREF_RANGE:
4473 case PREF_DECODE_AS_RANGE:
4474 wmem_free(wmem_epan_scope(), *pref->varp.range);
4475 *pref->varp.range = range_copy(wmem_epan_scope(), pref->default_val.range);
4476 break;
4477
4478 case PREF_STATIC_TEXT:
4479 case PREF_UAT:
4480 /* Nothing to do */
4481 break;
4482
4483 case PREF_COLOR:
4484 *pref->varp.colorp = pref->default_val.color;
4485 break;
4486
4487 case PREF_CUSTOM:
4488 pref->custom_cbs.reset_cb(pref);
4489 break;
4490 }
4491}
4492
4493static void
4494reset_pref_cb(void *data, void *user_data)
4495{
4496 pref_t *pref = (pref_t *) data;
4497 module_t *module = (module_t *)user_data;
4498
4499 if (pref && (pref->type == PREF_RANGE || pref->type == PREF_DECODE_AS_RANGE)) {
4500 /*
4501 * Some dissectors expect the range (returned via prefs_get_range_value)
4502 * to remain valid if it has not changed. If it did change, then we
4503 * should set "prefs_changed_flags" to ensure that the preference apply
4504 * callback is invoked. That callback will notify dissectors that it
4505 * should no longer assume the range to be valid.
4506 */
4507 if (ranges_are_equal(*pref->varp.range, pref->default_val.range)) {
4508 /* Optimization: do not invoke apply callback if nothing changed. */
4509 return;
4510 }
4511 module->prefs_changed_flags |= prefs_get_effect_flags(pref);
4512 }
4513 reset_pref(pref);
4514}
4515
4516/*
4517 * Reset all preferences for a module.
4518 */
4519static bool_Bool
4520reset_module_prefs(const void *key _U___attribute__((unused)), void *value, void *data _U___attribute__((unused)))
4521{
4522 module_t *module = (module_t *)value;
4523 g_list_foreach(module->prefs, reset_pref_cb, module);
4524 return false0;
4525}
4526
4527/* Reset preferences */
4528void
4529prefs_reset(const char* app_env_var_prefix, const char** col_fmt, int num_cols)
4530{
4531 g_free(prefs.saved_at_version);
4532 prefs.saved_at_version = NULL((void*)0);
4533
4534 /*
4535 * Unload all UAT preferences.
4536 */
4537 uat_unload_all();
4538
4539 /*
4540 * Unload any loaded MIBs.
4541 */
4542 oids_cleanup();
4543
4544 /*
4545 * Reload all UAT preferences.
4546 */
4547 uat_load_all(app_env_var_prefix);
4548
4549 /*
4550 * Reset the non-dissector preferences.
4551 */
4552 prefs_set_global_defaults(col_fmt, num_cols);
4553
4554 /*
4555 * Reset the non-UAT dissector preferences.
4556 */
4557 wmem_tree_foreach(prefs_modules, reset_module_prefs, NULL((void*)0));
4558}
4559
4560#ifdef _WIN32
4561static void
4562read_registry(void)
4563{
4564 HKEY hTestKey;
4565 DWORD data;
4566 DWORD data_size = sizeof(DWORD);
4567 DWORD ret;
4568
4569 ret = RegOpenKeyExA(HKEY_CURRENT_USER, REG_HKCU_WIRESHARK_KEY"Software\\Wireshark", 0, KEY_READ, &hTestKey);
4570 if (ret != ERROR_SUCCESS && ret != ERROR_FILE_NOT_FOUND) {
4571 ws_noisy("Cannot open HKCU "REG_HKCU_WIRESHARK_KEY": 0x%lx", ret)do { if (1) { ws_log_full("Epan", LOG_LEVEL_NOISY, "epan/prefs.c"
, 4571, __func__, "Cannot open HKCU ""Software\\Wireshark"": 0x%lx"
, ret); } } while (0)
;
4572 return;
4573 }
4574
4575 ret = RegQueryValueExA(hTestKey, LOG_HKCU_CONSOLE_OPEN"ConsoleOpen", NULL((void*)0), NULL((void*)0), (LPBYTE)&data, &data_size);
4576 if (ret == ERROR_SUCCESS) {
4577 ws_log_console_open = (ws_log_console_open_pref)data;
4578 ws_noisy("Got "LOG_HKCU_CONSOLE_OPEN" from Windows registry: %d", ws_log_console_open)do { if (1) { ws_log_full("Epan", LOG_LEVEL_NOISY, "epan/prefs.c"
, 4578, __func__, "Got ""ConsoleOpen"" from Windows registry: %d"
, ws_log_console_open); } } while (0)
;
4579 }
4580 else if (ret != ERROR_FILE_NOT_FOUND) {
4581 ws_noisy("Error reading registry key "LOG_HKCU_CONSOLE_OPEN": 0x%lx", ret)do { if (1) { ws_log_full("Epan", LOG_LEVEL_NOISY, "epan/prefs.c"
, 4581, __func__, "Error reading registry key ""ConsoleOpen"": 0x%lx"
, ret); } } while (0)
;
4582 }
4583
4584 RegCloseKey(hTestKey);
4585}
4586#endif
4587
4588void
4589prefs_read_module(const char *module, const char* app_env_var_prefix)
4590{
4591 int err;
4592 char *pf_path;
4593 FILE *pf;
4594
4595 module_t *target_module = prefs_find_module(module);
4596 if (!target_module) {
4597 return;
4598 }
4599
4600 /* Construct the pathname of the user's preferences file for the module. */
4601 char *pf_name = wmem_strdup_printf(NULL((void*)0), "%s.cfg", module);
4602 pf_path = get_persconffile_path(pf_name, true1, app_env_var_prefix);
4603 wmem_free(NULL((void*)0), pf_name);
4604
4605 /* Read the user's module preferences file, if it exists and is not a dir. */
4606 if (!test_for_regular_file(pf_path) || ((pf = ws_fopenfopen(pf_path, "r")) == NULL((void*)0))) {
4607 g_free(pf_path);
4608 /* Fall back to the user's generic preferences file. */
4609 pf_path = get_persconffile_path(PF_NAME"preferences", true1, app_env_var_prefix);
4610 pf = ws_fopenfopen(pf_path, "r");
4611 }
4612
4613 if (pf != NULL((void*)0)) {
4614 /* We succeeded in opening it; read it. */
4615 err = read_prefs_file(pf_path, pf, set_pref, target_module);
4616 if (err != 0) {
4617 /* We had an error reading the file; report it. */
4618 report_warning("Error reading your preferences file \"%s\": %s.",
4619 pf_path, g_strerror(err));
4620 } else
4621 g_free(pf_path);
4622 fclose(pf);
4623 } else {
4624 /* We failed to open it. If we failed for some reason other than
4625 "it doesn't exist", return the errno and the pathname, so our
4626 caller can report the error. */
4627 if (errno(*__errno_location ()) != ENOENT2) {
4628 report_warning("Can't open your preferences file \"%s\": %s.",
4629 pf_path, g_strerror(errno(*__errno_location ())));
4630 } else
4631 g_free(pf_path);
4632 }
4633
4634 return;
4635}
4636
4637/* Read the preferences file, fill in "prefs", and return a pointer to it.
4638
4639 If we got an error (other than "it doesn't exist") we report it through
4640 the UI. */
4641e_prefs *
4642read_prefs(const char* app_env_var_prefix)
4643{
4644 int err;
4645 char *pf_path;
4646 FILE *pf;
4647
4648 /* clean up libsmi structures before reading prefs */
4649 oids_cleanup();
4650
4651#ifdef _WIN32
4652 read_registry();
4653#endif
4654
4655 /*
4656 * If we don't already have the pathname of the global preferences
4657 * file, construct it. Then, in either case, try to open the file.
4658 */
4659 if (gpf_path == NULL((void*)0)) {
4660 /*
4661 * We don't have the path; try the new path first, and, if that
4662 * file doesn't exist, try the old path.
4663 */
4664 gpf_path = get_datafile_path(PF_NAME"preferences", app_env_var_prefix);
4665 if ((pf = ws_fopenfopen(gpf_path, "r")) == NULL((void*)0) && errno(*__errno_location ()) == ENOENT2) {
4666 /*
4667 * It doesn't exist by the new name; try the old name.
4668 */
4669 g_free(gpf_path);
4670 gpf_path = get_datafile_path(OLD_GPF_NAME"wireshark.conf", app_env_var_prefix);
4671 pf = ws_fopenfopen(gpf_path, "r");
4672 }
4673 } else {
4674 /*
4675 * We have the path; try it.
4676 */
4677 pf = ws_fopenfopen(gpf_path, "r");
4678 }
4679
4680 /*
4681 * If we were able to open the file, read it.
4682 * XXX - if it failed for a reason other than "it doesn't exist",
4683 * report the error.
4684 */
4685 if (pf != NULL((void*)0)) {
4686 /*
4687 * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
4688 * seen.
4689 */
4690 mgcp_tcp_port_count = 0;
4691 mgcp_udp_port_count = 0;
4692
4693 /* We succeeded in opening it; read it. */
4694 err = read_prefs_file(gpf_path, pf, set_pref, NULL((void*)0));
4695 if (err != 0) {
4696 /* We had an error reading the file; report it. */
4697 report_warning("Error reading global preferences file \"%s\": %s.",
4698 gpf_path, g_strerror(err));
4699 }
4700 fclose(pf);
4701 } else {
4702 /* We failed to open it. If we failed for some reason other than
4703 "it doesn't exist", report the error. */
4704 if (errno(*__errno_location ()) != ENOENT2) {
4705 if (errno(*__errno_location ()) != 0) {
4706 report_warning("Can't open global preferences file \"%s\": %s.",
4707 gpf_path, g_strerror(errno(*__errno_location ())));
4708 }
4709 }
4710 }
4711
4712 /* Construct the pathname of the user's preferences file. */
4713 pf_path = get_persconffile_path(PF_NAME"preferences", true1, app_env_var_prefix);
4714
4715 /* Read the user's preferences file, if it exists. */
4716 if ((pf = ws_fopenfopen(pf_path, "r")) != NULL((void*)0)) {
4717 /*
4718 * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
4719 * seen.
4720 */
4721 mgcp_tcp_port_count = 0;
4722 mgcp_udp_port_count = 0;
4723
4724 /* We succeeded in opening it; read it. */
4725 err = read_prefs_file(pf_path, pf, set_pref, NULL((void*)0));
4726 if (err != 0) {
4727 /* We had an error reading the file; report it. */
4728 report_warning("Error reading your preferences file \"%s\": %s.",
4729 pf_path, g_strerror(err));
4730 } else
4731 g_free(pf_path);
4732 fclose(pf);
4733 } else {
4734 /* We failed to open it. If we failed for some reason other than
4735 "it doesn't exist", return the errno and the pathname, so our
4736 caller can report the error. */
4737 if (errno(*__errno_location ()) != ENOENT2) {
4738 report_warning("Can't open your preferences file \"%s\": %s.",
4739 pf_path, g_strerror(errno(*__errno_location ())));
4740 } else
4741 g_free(pf_path);
4742 }
4743
4744 /* load SMI modules if needed */
4745 oids_init(app_env_var_prefix);
4746
4747 return &prefs;
4748}
4749
4750/* read the preferences file (or similar) and call the callback
4751 * function to set each key/value pair found */
4752int
4753read_prefs_file(const char *pf_path, FILE *pf,
4754 pref_set_pair_cb pref_set_pair_fct, void *private_data)
4755{
4756 enum {
4757 START, /* beginning of a line */
4758 IN_VAR, /* processing key name */
4759 PRE_VAL, /* finished processing key name, skipping white space before value */
4760 IN_VAL, /* processing value */
4761 IN_SKIP /* skipping to the end of the line */
4762 } state = START;
4763 int got_c;
4764 GString *cur_val;
4765 GString *cur_var;
4766 bool_Bool got_val = false0;
4767 int fline = 1, pline = 1;
4768 char hint[] = "(save preferences to remove this warning)";
4769 char ver[128];
4770
4771 cur_val = g_string_new("");
4772 cur_var = g_string_new("");
4773
4774 /* Try to read in the profile name in the first line of the preferences file. */
4775 if (fscanf(pf, "# Configuration file for %127[^\r\n]", ver) == 1) {
1
Assuming the condition is false
2
Taking false branch
4776 /* Assume trailing period and remove it */
4777 g_free(prefs.saved_at_version);
4778 prefs.saved_at_version = g_strndup(ver, strlen(ver) - 1);
4779 }
4780 rewind(pf);
3
After calling 'rewind' reading 'errno' is required to find out if the call has failed
4781
4782 while ((got_c = ws_getc_unlockedgetc_unlocked(pf)) != EOF(-1)) {
4
Value of 'errno' was not checked and may be overwritten by function 'getc_unlocked'
4783 if (got_c == '\r') {
4784 /* Treat CR-LF at the end of a line like LF, so that if we're reading
4785 * a Windows-format file on UN*X, we handle it the same way we'd handle
4786 * a UN*X-format file. */
4787 got_c = ws_getc_unlockedgetc_unlocked(pf);
4788 if (got_c == EOF(-1))
4789 break;
4790 if (got_c != '\n') {
4791 /* Put back the character after the CR, and process the CR normally. */
4792 ungetc(got_c, pf);
4793 got_c = '\r';
4794 }
4795 }
4796 if (got_c == '\n') {
4797 state = START;
4798 fline++;
4799 continue;
4800 }
4801
4802 switch (state) {
4803 case START:
4804 if (g_ascii_isalnum(got_c)((g_ascii_table[(guchar) (got_c)] & G_ASCII_ALNUM) != 0)) {
4805 if (cur_var->len > 0) {
4806 if (got_val) {
4807 if (cur_val->len > 0) {
4808 if (cur_val->str[cur_val->len-1] == ',') {
4809 /*
4810 * If the pref has a trailing comma, eliminate it.
4811 */
4812 cur_val->str[cur_val->len-1] = '\0';
4813 ws_warning("%s line %d: trailing comma in \"%s\" %s", pf_path, pline, cur_var->str, hint)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 4813, __func__, "%s line %d: trailing comma in \"%s\" %s", pf_path
, pline, cur_var->str, hint); } } while (0)
;
4814 }
4815 }
4816 /* Call the routine to set the preference; it will parse
4817 the value as appropriate.
4818
4819 Since we're reading a file, rather than processing
4820 explicit user input, for range preferences, silently
4821 lower values in excess of the range's maximum, rather
4822 than reporting errors and failing. */
4823 switch (pref_set_pair_fct(cur_var->str, cur_val->str, private_data, false0)) {
4824
4825 case PREFS_SET_OK:
4826 break;
4827
4828 case PREFS_SET_SYNTAX_ERR:
4829 report_warning("Syntax error in preference \"%s\" at line %d of\n%s %s",
4830 cur_var->str, pline, pf_path, hint);
4831 break;
4832
4833 case PREFS_SET_NO_SUCH_PREF:
4834 ws_warning("No such preference \"%s\" at line %d of\n%s %s",do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 4835, __func__, "No such preference \"%s\" at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
4835 cur_var->str, pline, pf_path, hint)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 4835, __func__, "No such preference \"%s\" at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
;
4836 prefs.unknown_prefs = true1;
4837 break;
4838
4839 case PREFS_SET_OBSOLETE:
4840 /*
4841 * If an attempt is made to save the
4842 * preferences, a popup warning will be
4843 * displayed stating that obsolete prefs
4844 * have been detected and the user will
4845 * be given the opportunity to save these
4846 * prefs under a different profile name.
4847 * The prefs in question need to be listed
4848 * in the console window so that the
4849 * user can make an informed choice.
4850 */
4851 ws_warning("Obsolete preference \"%s\" at line %d of\n%s %s",do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 4852, __func__, "Obsolete preference \"%s\" at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
4852 cur_var->str, pline, pf_path, hint)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 4852, __func__, "Obsolete preference \"%s\" at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
;
4853 prefs.unknown_prefs = true1;
4854 break;
4855 }
4856 } else {
4857 ws_warning("Incomplete preference at line %d: of\n%s %s", pline, pf_path, hint)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 4857, __func__, "Incomplete preference at line %d: of\n%s %s"
, pline, pf_path, hint); } } while (0)
;
4858 }
4859 }
4860 state = IN_VAR;
4861 got_val = false0;
4862 g_string_truncate(cur_var, 0)g_string_truncate_inline (cur_var, 0);
4863 g_string_append_c(cur_var, (char) got_c)g_string_append_c_inline (cur_var, (char) got_c);
4864 pline = fline;
4865 } else if (g_ascii_isspace(got_c)((g_ascii_table[(guchar) (got_c)] & G_ASCII_SPACE) != 0) && cur_var->len > 0 && got_val) {
4866 state = PRE_VAL;
4867 } else if (got_c == '#') {
4868 state = IN_SKIP;
4869 } else {
4870 ws_warning("Malformed preference at line %d of\n%s %s", fline, pf_path, hint)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 4870, __func__, "Malformed preference at line %d of\n%s %s"
, fline, pf_path, hint); } } while (0)
;
4871 }
4872 break;
4873 case IN_VAR:
4874 if (got_c != ':') {
4875 g_string_append_c(cur_var, (char) got_c)g_string_append_c_inline (cur_var, (char) got_c);
4876 } else {
4877 /* This is a colon (':') */
4878 state = PRE_VAL;
4879 g_string_truncate(cur_val, 0)g_string_truncate_inline (cur_val, 0);
4880 /*
4881 * Set got_val to true to accommodate prefs such as
4882 * "gui.fileopen.dir" that do not require a value.
4883 */
4884 got_val = true1;
4885 }
4886 break;
4887 case PRE_VAL:
4888 if (!g_ascii_isspace(got_c)((g_ascii_table[(guchar) (got_c)] & G_ASCII_SPACE) != 0)) {
4889 state = IN_VAL;
4890 g_string_append_c(cur_val, (char) got_c)g_string_append_c_inline (cur_val, (char) got_c);
4891 }
4892 break;
4893 case IN_VAL:
4894 g_string_append_c(cur_val, (char) got_c)g_string_append_c_inline (cur_val, (char) got_c);
4895 break;
4896 case IN_SKIP:
4897 break;
4898 }
4899 }
4900 if (cur_var->len > 0) {
4901 if (got_val) {
4902 /* Call the routine to set the preference; it will parse
4903 the value as appropriate.
4904
4905 Since we're reading a file, rather than processing
4906 explicit user input, for range preferences, silently
4907 lower values in excess of the range's maximum, rather
4908 than reporting errors and failing. */
4909 switch (pref_set_pair_fct(cur_var->str, cur_val->str, private_data, false0)) {
4910
4911 case PREFS_SET_OK:
4912 break;
4913
4914 case PREFS_SET_SYNTAX_ERR:
4915 ws_warning("Syntax error in preference %s at line %d of\n%s %s",do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 4916, __func__, "Syntax error in preference %s at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
4916 cur_var->str, pline, pf_path, hint)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 4916, __func__, "Syntax error in preference %s at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
;
4917 break;
4918
4919 case PREFS_SET_NO_SUCH_PREF:
4920 ws_warning("No such preference \"%s\" at line %d of\n%s %s",do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 4921, __func__, "No such preference \"%s\" at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
4921 cur_var->str, pline, pf_path, hint)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 4921, __func__, "No such preference \"%s\" at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
;
4922 prefs.unknown_prefs = true1;
4923 break;
4924
4925 case PREFS_SET_OBSOLETE:
4926 prefs.unknown_prefs = true1;
4927 break;
4928 }
4929 } else {
4930 ws_warning("Incomplete preference at line %d of\n%s %s",do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 4931, __func__, "Incomplete preference at line %d of\n%s %s"
, pline, pf_path, hint); } } while (0)
4931 pline, pf_path, hint)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 4931, __func__, "Incomplete preference at line %d of\n%s %s"
, pline, pf_path, hint); } } while (0)
;
4932 }
4933 }
4934
4935 g_string_free(cur_val, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(cur_val), ((!(0)))) : g_string_free_and_steal (cur_val)) : (
g_string_free) ((cur_val), ((!(0)))))
;
4936 g_string_free(cur_var, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(cur_var), ((!(0)))) : g_string_free_and_steal (cur_var)) : (
g_string_free) ((cur_var), ((!(0)))))
;
4937
4938 if (ferror(pf))
4939 return errno(*__errno_location ());
4940 else
4941 return 0;
4942}
4943
4944/*
4945 * If we were handed a preference starting with "uat:", try to turn it into
4946 * a valid uat entry.
4947 */
4948static bool_Bool
4949prefs_set_uat_pref(char *uat_entry, char **errmsg) {
4950 char *p, *colonp;
4951 uat_t *uat;
4952 bool_Bool ret;
4953
4954 colonp = strchr(uat_entry, ':');
4955 if (colonp == NULL((void*)0))
4956 return false0;
4957
4958 p = colonp;
4959 *p++ = '\0';
4960
4961 /*
4962 * Skip over any white space (there probably won't be any, but
4963 * as we allow it in the preferences file, we might as well
4964 * allow it here).
4965 */
4966 while (g_ascii_isspace(*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0))
4967 p++;
4968 if (*p == '\0') {
4969 /*
4970 * Put the colon back, so if our caller uses, in an
4971 * error message, the string they passed us, the message
4972 * looks correct.
4973 */
4974 *colonp = ':';
4975 return false0;
4976 }
4977
4978 uat = uat_find(uat_entry);
4979 *colonp = ':';
4980 if (uat == NULL((void*)0)) {
4981 *errmsg = g_strdup("Unknown preference")g_strdup_inline ("Unknown preference");
4982 return false0;
4983 }
4984
4985 ret = uat_load_str(uat, p, errmsg);
4986 return ret;
4987}
4988
4989/*
4990 * Given a string of the form "<pref name>:<pref value>", as might appear
4991 * as an argument to a "-o" option, parse it and set the preference in
4992 * question. Return an indication of whether it succeeded or failed
4993 * in some fashion.
4994 */
4995prefs_set_pref_e
4996prefs_set_pref(char *prefarg, char **errmsg)
4997{
4998 char *p, *colonp;
4999 prefs_set_pref_e ret;
5000
5001 /*
5002 * Set the counters of "mgcp.{tcp,udp}.port" entries we've
5003 * seen to values that keep us from trying to interpret them
5004 * as "mgcp.{tcp,udp}.gateway_port" or "mgcp.{tcp,udp}.callagent_port",
5005 * as, from the command line, we have no way of guessing which
5006 * the user had in mind.
5007 */
5008 mgcp_tcp_port_count = -1;
5009 mgcp_udp_port_count = -1;
5010
5011 *errmsg = NULL((void*)0);
5012
5013 colonp = strchr(prefarg, ':');
5014 if (colonp == NULL((void*)0))
5015 return PREFS_SET_SYNTAX_ERR;
5016
5017 p = colonp;
5018 *p++ = '\0';
5019
5020 /*
5021 * Skip over any white space (there probably won't be any, but
5022 * as we allow it in the preferences file, we might as well
5023 * allow it here).
5024 */
5025 while (g_ascii_isspace(*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0))
5026 p++;
5027 /* The empty string is a legal value for range preferences (PREF_RANGE,
5028 * PREF_DECODE_AS_RANGE), and string-like preferences (PREF_STRING,
5029 * PREF_SAVE_FILENAME, PREF_OPEN_FILENAME, PREF_DIRNAME), indeed often
5030 * not just useful but the default. A user might have a value saved
5031 * to their preference file but want to override it to default behavior.
5032 * Individual preference handlers of those types should be prepared to
5033 * deal with an empty string. For other types, it is up to set_pref() to
5034 * test for the empty string and set PREFS_SET_SYNTAX_ERROR there.
5035 */
5036 if (strcmp(prefarg, "uat")) {
5037 ret = set_pref(prefarg, p, NULL((void*)0), true1);
5038 } else {
5039 ret = prefs_set_uat_pref(p, errmsg) ? PREFS_SET_OK : PREFS_SET_SYNTAX_ERR;
5040 }
5041 *colonp = ':'; /* put the colon back */
5042 return ret;
5043}
5044
5045unsigned prefs_get_uint_value(pref_t *pref, pref_source_t source)
5046{
5047 switch (source)
5048 {
5049 case pref_default:
5050 return pref->default_val.uint;
5051 case pref_stashed:
5052 return pref->stashed_val.uint;
5053 case pref_current:
5054 return *pref->varp.uint;
5055 default:
5056 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 5056
, __func__, "assertion \"not reached\" failed")
;
5057 break;
5058 }
5059
5060 return 0;
5061}
5062
5063char* prefs_get_password_value(pref_t *pref, pref_source_t source)
5064{
5065 return prefs_get_string_value(pref, source);
5066}
5067
5068
5069unsigned int prefs_set_uint_value(pref_t *pref, unsigned value, pref_source_t source)
5070{
5071 unsigned int changed = 0;
5072 switch (source)
5073 {
5074 case pref_default:
5075 if (pref->default_val.uint != value) {
5076 pref->default_val.uint = value;
5077 changed = prefs_get_effect_flags(pref);
5078 }
5079 break;
5080 case pref_stashed:
5081 if (pref->stashed_val.uint != value) {
5082 pref->stashed_val.uint = value;
5083 changed = prefs_get_effect_flags(pref);
5084 }
5085 break;
5086 case pref_current:
5087 if (*pref->varp.uint != value) {
5088 *pref->varp.uint = value;
5089 changed = prefs_get_effect_flags(pref);
5090 }
5091 break;
5092 default:
5093 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 5093
, __func__, "assertion \"not reached\" failed")
;
5094 break;
5095 }
5096
5097 return changed;
5098}
5099
5100/*
5101 * For use by UI code that sets preferences.
5102 */
5103unsigned int
5104prefs_set_password_value(pref_t *pref, const char* value, pref_source_t source)
5105{
5106 return prefs_set_string_value(pref, value, source);
5107}
5108
5109
5110unsigned prefs_get_uint_base(pref_t *pref)
5111{
5112 return pref->info.base;
5113}
5114
5115/*
5116 * Returns true if the given device is hidden
5117 */
5118bool_Bool
5119prefs_is_capture_device_hidden(const char *name)
5120{
5121 char *tok, *devices;
5122 size_t len;
5123
5124 if (prefs.capture_devices_hide && name) {
5125 devices = g_strdup (prefs.capture_devices_hide)g_strdup_inline (prefs.capture_devices_hide);
5126 len = strlen (name);
5127 for (tok = strtok (devices, ","); tok; tok = strtok(NULL((void*)0), ",")) {
5128 if (strlen (tok) == len && strcmp (name, tok) == 0) {
5129 g_free (devices);
5130 return true1;
5131 }
5132 }
5133 g_free (devices);
5134 }
5135
5136 return false0;
5137}
5138
5139/*
5140 * Returns true if the given column is visible (not hidden)
5141 */
5142static bool_Bool
5143prefs_is_column_visible(const char *cols_hidden, int col)
5144{
5145 char *tok, *cols, *p;
5146 int cidx;
5147
5148 /*
5149 * Do we have a list of hidden columns?
5150 */
5151 if (cols_hidden) {
5152 /*
5153 * Yes - check the column against each of the ones in the
5154 * list.
5155 */
5156 cols = g_strdup(cols_hidden)g_strdup_inline (cols_hidden);
5157 for (tok = strtok(cols, ","); tok; tok = strtok(NULL((void*)0), ",")) {
5158 tok = g_strstrip(tok)g_strchomp (g_strchug (tok));
5159
5160 cidx = (int)strtol(tok, &p, 10);
5161 if (p == tok || *p != '\0') {
5162 continue;
5163 }
5164 if (cidx != col) {
5165 continue;
5166 }
5167 /*
5168 * OK, they match, so it's one of the hidden fields,
5169 * hence not visible.
5170 */
5171 g_free(cols);
5172 return false0;
5173 }
5174 g_free(cols);
5175 }
5176
5177 /*
5178 * No - either there are no hidden columns or this isn't one
5179 * of them - so it is visible.
5180 */
5181 return true1;
5182}
5183
5184/*
5185 * Returns true if the given column is visible (not hidden)
5186 */
5187static bool_Bool
5188prefs_is_column_fmt_visible(const char *cols_hidden, fmt_data *cfmt)
5189{
5190 char *tok, *cols;
5191 fmt_data cfmt_hidden;
5192
5193 /*
5194 * Do we have a list of hidden columns?
5195 */
5196 if (cols_hidden) {
5197 /*
5198 * Yes - check the column against each of the ones in the
5199 * list.
5200 */
5201 cols = g_strdup(cols_hidden)g_strdup_inline (cols_hidden);
5202 for (tok = strtok(cols, ","); tok; tok = strtok(NULL((void*)0), ",")) {
5203 tok = g_strstrip(tok)g_strchomp (g_strchug (tok));
5204
5205 /*
5206 * Parse this column format.
5207 */
5208 if (!parse_column_format(&cfmt_hidden, tok)) {
5209 /*
5210 * It's not valid; ignore it.
5211 */
5212 continue;
5213 }
5214
5215 /*
5216 * Does it match the column?
5217 */
5218 if (cfmt->fmt != cfmt_hidden.fmt) {
5219 /* No. */
5220 g_free(cfmt_hidden.custom_fields);
5221 cfmt_hidden.custom_fields = NULL((void*)0);
5222 continue;
5223 }
5224 if (cfmt->fmt == COL_CUSTOM) {
5225 /*
5226 * A custom column has to have the same custom field
5227 * and occurrence.
5228 */
5229 if (cfmt_hidden.custom_fields && cfmt->custom_fields) {
5230 if (strcmp(cfmt->custom_fields,
5231 cfmt_hidden.custom_fields) != 0) {
5232 /* Different fields. */
5233 g_free(cfmt_hidden.custom_fields);
5234 cfmt_hidden.custom_fields = NULL((void*)0);
5235 continue;
5236 }
5237 if (cfmt->custom_occurrence != cfmt_hidden.custom_occurrence) {
5238 /* Different occurrences settings. */
5239 g_free(cfmt_hidden.custom_fields);
5240 cfmt_hidden.custom_fields = NULL((void*)0);
5241 continue;
5242 }
5243 }
5244 }
5245
5246 /*
5247 * OK, they match, so it's one of the hidden fields,
5248 * hence not visible.
5249 */
5250 g_free(cfmt_hidden.custom_fields);
5251 g_free(cols);
5252 return false0;
5253 }
5254 g_free(cols);
5255 }
5256
5257 /*
5258 * No - either there are no hidden columns or this isn't one
5259 * of them - so it is visible.
5260 */
5261 return true1;
5262}
5263
5264/*
5265 * Returns true if the given device should capture in monitor mode by default
5266 */
5267bool_Bool
5268prefs_capture_device_monitor_mode(const char *name)
5269{
5270 char *tok, *devices;
5271 size_t len;
5272
5273 if (prefs.capture_devices_monitor_mode && name) {
5274 devices = g_strdup (prefs.capture_devices_monitor_mode)g_strdup_inline (prefs.capture_devices_monitor_mode);
5275 len = strlen (name);
5276 for (tok = strtok (devices, ","); tok; tok = strtok(NULL((void*)0), ",")) {
5277 if (strlen (tok) == len && strcmp (name, tok) == 0) {
5278 g_free (devices);
5279 return true1;
5280 }
5281 }
5282 g_free (devices);
5283 }
5284
5285 return false0;
5286}
5287
5288/*
5289 * Returns true if the user has marked this column as visible
5290 */
5291bool_Bool
5292prefs_capture_options_dialog_column_is_visible(const char *column)
5293{
5294 GList *curr;
5295 char *col;
5296
5297 for (curr = g_list_first(prefs.capture_columns); curr; curr = g_list_next(curr)((curr) ? (((GList *)(curr))->next) : ((void*)0))) {
5298 col = (char *)curr->data;
5299 if (col && (g_ascii_strcasecmp(col, column) == 0)) {
5300 return true1;
5301 }
5302 }
5303 return false0;
5304}
5305
5306bool_Bool
5307prefs_has_layout_pane_content (layout_pane_content_e layout_pane_content)
5308{
5309 return ((prefs.gui_layout_content_1 == layout_pane_content) ||
5310 (prefs.gui_layout_content_2 == layout_pane_content) ||
5311 (prefs.gui_layout_content_3 == layout_pane_content));
5312}
5313
5314#define PRS_GUI_FILTER_LABEL"gui.filter_expressions.label" "gui.filter_expressions.label"
5315#define PRS_GUI_FILTER_EXPR"gui.filter_expressions.expr" "gui.filter_expressions.expr"
5316#define PRS_GUI_FILTER_ENABLED"gui.filter_expressions.enabled" "gui.filter_expressions.enabled"
5317
5318/*
5319 * Extract the red, green, and blue components of a 24-bit RGB value
5320 * and convert them from [0,255] to [0,65535].
5321 */
5322#define RED_COMPONENT(x)(uint16_t) (((((x) >> 16) & 0xff) * 65535 / 255)) (uint16_t) (((((x) >> 16) & 0xff) * 65535 / 255))
5323#define GREEN_COMPONENT(x)(uint16_t) (((((x) >> 8) & 0xff) * 65535 / 255)) (uint16_t) (((((x) >> 8) & 0xff) * 65535 / 255))
5324#define BLUE_COMPONENT(x)(uint16_t) ( (((x) & 0xff) * 65535 / 255)) (uint16_t) ( (((x) & 0xff) * 65535 / 255))
5325
5326char
5327string_to_name_resolve(const char *string, e_addr_resolve *name_resolve)
5328{
5329 char c;
5330
5331 memset(name_resolve, 0, sizeof(e_addr_resolve));
5332 while ((c = *string++) != '\0') {
5333 switch (c) {
5334 case 'g':
5335 name_resolve->maxmind_geoip = true1;
5336 break;
5337 case 'm':
5338 name_resolve->mac_name = true1;
5339 break;
5340 case 'n':
5341 name_resolve->network_name = true1;
5342 break;
5343 case 'N':
5344 name_resolve->use_external_net_name_resolver = true1;
5345 break;
5346 case 't':
5347 name_resolve->transport_name = true1;
5348 break;
5349 case 'd':
5350 name_resolve->dns_pkt_addr_resolution = true1;
5351 break;
5352 case 's':
5353 name_resolve->handshake_sni_addr_resolution = true1;
5354 break;
5355 case 'v':
5356 name_resolve->vlan_name = true1;
5357 break;
5358 default:
5359 /*
5360 * Unrecognized letter.
5361 */
5362 return c;
5363 }
5364 }
5365 return '\0';
5366}
5367
5368static bool_Bool
5369deprecated_heur_dissector_pref(char *pref_name, const char *value)
5370{
5371 struct heur_pref_name
5372 {
5373 const char* pref_name;
5374 const char* short_name;
5375 bool_Bool more_dissectors; /* For multiple dissectors controlled by the same preference */
5376 };
5377
5378 struct heur_pref_name heur_prefs[] = {
5379 {"acn.heuristic_acn", "acn_udp", 0},
5380 {"bfcp.enable", "bfcp_tcp", 1},
5381 {"bfcp.enable", "bfcp_udp", 0},
5382 {"bt-dht.enable", "bittorrent_dht_udp", 0},
5383 {"bt-utp.enable", "bt_utp_udp", 0},
5384 {"cattp.enable", "cattp_udp", 0},
5385 {"cfp.enable", "fp_eth", 0},
5386 {"dicom.heuristic", "dicom_tcp", 0},
5387 {"dnp3.heuristics", "dnp3_tcp", 1},
5388 {"dnp3.heuristics", "dnp3_udp", 0},
5389 {"dvb-s2_modeadapt.enable", "dvb_s2_udp", 0},
5390 {"esl.enable", "esl_eth", 0},
5391 {"fp.udp_heur", "fp_udp", 0},
5392 {"gvsp.enable_heuristic", "gvsp_udp", 0},
5393 {"hdcp2.enable", "hdcp2_tcp", 0},
5394 {"hislip.enable_heuristic", "hislip_tcp", 0},
5395 {"infiniband.dissect_eoib", "mellanox_eoib", 1},
5396 {"infiniband.identify_payload", "eth_over_ib", 0},
5397 {"jxta.udp.heuristic", "jxta_udp", 0},
5398 {"jxta.tcp.heuristic", "jxta_tcp", 0},
5399 {"jxta.sctp.heuristic", "jxta_sctp", 0},
5400 {"mac-lte.heuristic_mac_lte_over_udp", "mac_lte_udp", 0},
5401 {"mbim.bulk_heuristic", "mbim_usb_bulk", 0},
5402 {"norm.heuristic_norm", "rmt_norm_udp", 0},
5403 {"openflow.heuristic", "openflow_tcp", 0},
5404 {"pdcp-lte.heuristic_pdcp_lte_over_udp", "pdcp_lte_udp", 0},
5405 {"rlc.heuristic_rlc_over_udp", "rlc_udp", 0},
5406 {"rlc-lte.heuristic_rlc_lte_over_udp", "rlc_lte_udp", 0},
5407 {"rtcp.heuristic_rtcp", "rtcp_udp", 1},
5408 {"rtcp.heuristic_rtcp", "rtcp_stun", 0},
5409 {"rtp.heuristic_rtp", "rtp_udp", 1},
5410 {"rtp.heuristic_rtp", "rtp_stun", 0},
5411 {"teredo.heuristic_teredo", "teredo_udp", 0},
5412 {"vssmonitoring.use_heuristics", "vssmonitoring_eth", 0},
5413 {"xml.heuristic", "xml_http", 1},
5414 {"xml.heuristic", "xml_sip", 1},
5415 {"xml.heuristic", "xml_media", 0},
5416 {"xml.heuristic_tcp", "xml_tcp", 0},
5417 {"xml.heuristic_udp", "xml_udp", 0},
5418 };
5419
5420 unsigned int i;
5421 heur_dtbl_entry_t* heuristic;
5422
5423
5424 for (i = 0; i < array_length(heur_prefs)(sizeof (heur_prefs) / sizeof (heur_prefs)[0]); i++)
5425 {
5426 if (strcmp(pref_name, heur_prefs[i].pref_name) == 0)
5427 {
5428 heuristic = find_heur_dissector_by_unique_short_name(heur_prefs[i].short_name);
5429 if (heuristic != NULL((void*)0)) {
5430 heuristic->enabled = ((g_ascii_strcasecmp(value, "true") == 0) ? true1 : false0);
5431 }
5432
5433 if (!heur_prefs[i].more_dissectors)
5434 return true1;
5435 }
5436 }
5437
5438
5439 return false0;
5440}
5441
5442static bool_Bool
5443deprecated_enable_dissector_pref(char *pref_name, const char *value)
5444{
5445 struct dissector_pref_name
5446 {
5447 const char* pref_name;
5448 const char* short_name;
5449 };
5450
5451 struct dissector_pref_name dissector_prefs[] = {
5452 {"transum.tsumenabled", "TRANSUM"},
5453 {"snort.enable_snort_dissector", "Snort"},
5454 {"prp.enable", "PRP"},
5455 };
5456
5457 unsigned int i;
5458 int proto_id;
5459
5460 for (i = 0; i < array_length(dissector_prefs)(sizeof (dissector_prefs) / sizeof (dissector_prefs)[0]); i++)
5461 {
5462 if (strcmp(pref_name, dissector_prefs[i].pref_name) == 0)
5463 {
5464 proto_id = proto_get_id_by_short_name(dissector_prefs[i].short_name);
5465 if (proto_id >= 0)
5466 proto_set_decoding(proto_id, ((g_ascii_strcasecmp(value, "true") == 0) ? true1 : false0));
5467 return true1;
5468 }
5469 }
5470
5471 return false0;
5472}
5473
5474static bool_Bool
5475deprecated_port_pref(char *pref_name, const char *value)
5476{
5477 struct port_pref_name
5478 {
5479 const char* pref_name;
5480 const char* module_name; /* the protocol filter name */
5481 const char* table_name;
5482 unsigned base;
5483 };
5484
5485 struct obsolete_pref_name
5486 {
5487 const char* pref_name;
5488 };
5489
5490 /* For now this is only supporting TCP/UDP port and RTP payload
5491 * types dissector preferences, which are assumed to be decimal */
5492 /* module_name is the filter name of the destination port preference,
5493 * which is usually the same as the original module but not
5494 * necessarily (e.g., if the preference is for what is now a PINO.)
5495 * XXX: Most of these were changed pre-2.0. Can we end support
5496 * for migrating legacy preferences at some point?
5497 */
5498 struct port_pref_name port_prefs[] = {
5499 /* TCP */
5500 {"cmp.tcp_alternate_port", "cmp", "tcp.port", 10},
5501 {"h248.tcp_port", "h248", "tcp.port", 10},
5502 {"cops.tcp.cops_port", "cops", "tcp.port", 10},
5503 {"dhcpfo.tcp_port", "dhcpfo", "tcp.port", 10},
5504 {"enttec.tcp_port", "enttec", "tcp.port", 10},
5505 {"forces.tcp_alternate_port", "forces", "tcp.port", 10},
5506 {"ged125.tcp_port", "ged125", "tcp.port", 10},
5507 {"hpfeeds.dissector_port", "hpfeeds", "tcp.port", 10},
5508 {"lsc.port", "lsc", "tcp.port", 10},
5509 {"megaco.tcp.txt_port", "megaco", "tcp.port", 10},
5510 {"netsync.tcp_port", "netsync", "tcp.port", 10},
5511 {"osi.tpkt_port", "osi", "tcp.port", 10},
5512 {"rsync.tcp_port", "rsync", "tcp.port", 10},
5513 {"sametime.tcp_port", "sametime", "tcp.port", 10},
5514 {"sigcomp.tcp.port2", "sigcomp", "tcp.port", 10},
5515 {"synphasor.tcp_port", "synphasor", "tcp.port", 10},
5516 {"tipc.alternate_port", "tipc", "tcp.port", 10},
5517 {"vnc.alternate_port", "vnc", "tcp.port", 10},
5518 {"scop.port", "scop", "tcp.port", 10},
5519 {"scop.port_secure", "scop", "tcp.port", 10},
5520 {"tpncp.tcp.trunkpack_port", "tpncp", "tcp.port", 10},
5521 /* UDP */
5522 {"h248.udp_port", "h248", "udp.port", 10},
5523 {"actrace.udp_port", "actrace", "udp.port", 10},
5524 {"brp.port", "brp", "udp.port", 10},
5525 {"bvlc.additional_udp_port", "bvlc", "udp.port", 10},
5526 {"capwap.udp.port.control", "capwap", "udp.port", 10},
5527 {"capwap.udp.port.data", "capwap", "udp.port", 10},
5528 {"coap.udp_port", "coap", "udp.port", 10},
5529 {"enttec.udp_port", "enttec", "udp.port", 10},
5530 {"forces.udp_alternate_port", "forces", "udp.port", 10},
5531 {"ldss.udp_port", "ldss", "udp.port", 10},
5532 {"lmp.udp_port", "lmp", "udp.port", 10},
5533 {"ltp.port", "ltp", "udp.port", 10},
5534 {"lwres.udp.lwres_port", "lwres", "udp.port", 10},
5535 {"megaco.udp.txt_port", "megaco", "udp.port", 10},
5536 {"pfcp.port_pfcp", "pfcp", "udp.port", 10},
5537 {"pgm.udp.encap_ucast_port", "pgm", "udp.port", 10},
5538 {"pgm.udp.encap_mcast_port", "pgm", "udp.port", 10},
5539 {"quic.udp.quic.port", "quic", "udp.port", 10},
5540 {"quic.udp.quics.port", "quic", "udp.port", 10},
5541 {"radius.alternate_port", "radius", "udp.port", 10},
5542 {"rdt.default_udp_port", "rdt", "udp.port", 10},
5543 {"alc.default.udp_port", "alc", "udp.port", 10},
5544 {"sigcomp.udp.port2", "sigcomp", "udp.port", 10},
5545 {"synphasor.udp_port", "synphasor", "udp.port", 10},
5546 {"tdmop.udpport", "tdmop", "udp.port", 10},
5547 {"uaudp.port1", "uaudp", "udp.port", 10},
5548 {"uaudp.port2", "uaudp", "udp.port", 10},
5549 {"uaudp.port3", "uaudp", "udp.port", 10},
5550 {"uaudp.port4", "uaudp", "udp.port", 10},
5551 {"uhd.dissector_port", "uhd", "udp.port", 10},
5552 {"vrt.dissector_port", "vrt", "udp.port", 10},
5553 {"tpncp.udp.trunkpack_port", "tpncp", "udp.port", 10},
5554 /* SCTP */
5555 {"hnbap.port", "hnbap", "sctp.port", 10},
5556 {"m2pa.port", "m2pa", "sctp.port", 10},
5557 {"megaco.sctp.txt_port", "megaco", "sctp.port", 10},
5558 {"rua.port", "rua", "sctp.port", 10},
5559 /* SCTP PPI */
5560 {"lapd.sctp_payload_protocol_identifier", "lapd", "sctp.ppi", 10},
5561 /* SCCP SSN */
5562 {"ranap.sccp_ssn", "ranap", "sccp.ssn", 10},
5563 };
5564
5565 struct port_pref_name port_range_prefs[] = {
5566 /* TCP */
5567 {"couchbase.tcp.ports", "couchbase", "tcp.port", 10},
5568 {"gsm_ipa.tcp_ports", "gsm_ipa", "tcp.port", 10},
5569 {"kafka.tcp.ports", "kafka", "tcp.port", 10},
5570 {"kt.tcp.ports", "kt", "tcp.port", 10},
5571 {"memcache.tcp.ports", "memcache", "tcp.port", 10},
5572 {"mrcpv2.tcp.port_range", "mrcpv2", "tcp.port", 10},
5573 {"pdu_transport.ports.tcp", "pdu_transport", "tcp.port", 10},
5574 {"rtsp.tcp.port_range", "rtsp", "tcp.port", 10},
5575 {"sip.tcp.ports", "sip", "tcp.port", 10},
5576 {"someip.ports.tcp", "someip", "tcp.port", 10},
5577 {"tds.tcp_ports", "tds", "tcp.port", 10},
5578 {"tpkt.tcp.ports", "tpkt", "tcp.port", 10},
5579 {"uma.tcp.ports", "uma", "tcp.port", 10},
5580 /* UDP */
5581 {"aruba_erm.udp.ports", "arubs_erm", "udp.port", 10},
5582 {"diameter.udp.ports", "diameter", "udp.port", 10},
5583 {"dmp.udp_ports", "dmp", "udp.port", 10},
5584 {"dns.udp.ports", "dns", "udp.port", 10},
5585 {"gsm_ipa.udp_ports", "gsm_ipa", "udp.port", 10},
5586 {"hcrt.dissector_udp_port", "hcrt", "udp.port", 10},
5587 {"memcache.udp.ports", "memcache", "udp.port", 10},
5588 {"nb_rtpmux.udp_ports", "nb_rtpmux", "udp.port", 10},
5589 {"gprs-ns.udp.ports", "gprs-ns", "udp.port", 10},
5590 {"p_mul.udp_ports", "p_mul", "udp.port", 10},
5591 {"pdu_transport.ports.udp", "pdu_transport", "udp.port", 10},
5592 {"radius.ports", "radius", "udp.port", 10},
5593 {"sflow.ports", "sflow", "udp.port", 10},
5594 {"someip.ports.udp", "someip", "udp.port", 10},
5595 {"sscop.udp.ports", "sscop", "udp.port", 10},
5596 {"tftp.udp_ports", "tftp", "udp.port", 10},
5597 {"tipc.udp.ports", "tipc", "udp.port", 10},
5598 /* RTP */
5599 {"amr.dynamic.payload.type", "amr", "rtp.pt", 10},
5600 {"amr.wb.dynamic.payload.type", "amr_wb", "rtp.pt", 10},
5601 {"dvb-s2_modeadapt.dynamic.payload.type", "dvb-s2_modeadapt", "rtp.pt", 10},
5602 {"evs.dynamic.payload.type", "evs", "rtp.pt", 10},
5603 {"h263p.dynamic.payload.type", "h263p", "rtp.pt", 10},
5604 {"h264.dynamic.payload.type", "h264", "rtp.pt", 10},
5605 {"h265.dynamic.payload.type", "h265", "rtp.pt", 10},
5606 {"ismacryp.dynamic.payload.type", "ismacryp", "rtp.pt", 10},
5607 {"iuup.dynamic.payload.type", "iuup", "rtp.pt", 10},
5608 {"lapd.rtp_payload_type", "lapd", "rtp.pt", 10},
5609 {"mp4ves.dynamic.payload.type", "mp4ves", "rtp.pt", 10},
5610 {"mtp2.rtp_payload_type", "mtp2", "rtp.pt", 10},
5611 {"opus.dynamic.payload.type", "opus", "rtp.pt", 10},
5612 {"rtp.rfc2198_payload_type", "rtp_rfc2198", "rtp.pt", 10},
5613 {"rtpevent.event_payload_type_value", "rtpevent", "rtp.pt", 10},
5614 {"rtpevent.cisco_nse_payload_type_value", "rtpevent", "rtp.pt", 10},
5615 {"rtpmidi.midi_payload_type_value", "rtpmidi", "rtp.pt", 10},
5616 {"vp8.dynamic.payload.type", "vp8", "rtp.pt", 10},
5617 /* SCTP */
5618 {"diameter.sctp.ports", "diameter", "sctp.port", 10},
5619 {"sgsap.sctp_ports", "sgsap", "sctp.port", 10},
5620 /* SCCP SSN */
5621 {"pcap.ssn", "pcap", "sccp.ssn", 10},
5622 };
5623
5624 /* These are subdissectors of TPKT/OSITP that used to have a
5625 TCP port preference even though they were never
5626 directly on TCP. Convert them to use Decode As
5627 with the TPKT dissector handle */
5628 struct port_pref_name tpkt_subdissector_port_prefs[] = {
5629 {"dap.tcp.port", "dap", "tcp.port", 10},
5630 {"disp.tcp.port", "disp", "tcp.port", 10},
5631 {"dop.tcp.port", "dop", "tcp.port", 10},
5632 {"dsp.tcp.port", "dsp", "tcp.port", 10},
5633 {"p1.tcp.port", "p1", "tcp.port", 10},
5634 {"p7.tcp.port", "p7", "tcp.port", 10},
5635 {"rdp.tcp.port", "rdp", "tcp.port", 10},
5636 };
5637
5638 /* These are obsolete preferences from the dissectors' view,
5639 (typically because of a switch from a single value to a
5640 range value) but the name of the preference conflicts
5641 with the generated preference name from the dissector table.
5642 Don't allow the obsolete preference through to be handled */
5643 struct obsolete_pref_name obsolete_prefs[] = {
5644 {"diameter.tcp.port"},
5645 {"kafka.tcp.port"},
5646 {"mrcpv2.tcp.port"},
5647 {"rtsp.tcp.port"},
5648 {"sip.tcp.port"},
5649 {"t38.tcp.port"},
5650 };
5651
5652 unsigned int i;
5653 unsigned uval;
5654 dissector_table_t sub_dissectors;
5655 dissector_handle_t handle, tpkt_handle;
5656 module_t *module;
5657 pref_t *pref;
5658
5659 static bool_Bool sanity_checked;
5660 if (!sanity_checked) {
5661 sanity_checked = true1;
5662 for (i = 0; i < G_N_ELEMENTS(port_prefs)(sizeof (port_prefs) / sizeof ((port_prefs)[0])); i++) {
5663 module = prefs_find_module(port_prefs[i].module_name);
5664 if (!module) {
5665 ws_warning("Deprecated ports pref check - module '%s' not found", port_prefs[i].module_name)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 5665, __func__, "Deprecated ports pref check - module '%s' not found"
, port_prefs[i].module_name); } } while (0)
;
5666 continue;
5667 }
5668 pref = prefs_find_preference(module, port_prefs[i].table_name);
5669 if (!pref) {
5670 ws_warning("Deprecated ports pref '%s.%s' not found", module->name, port_prefs[i].table_name)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 5670, __func__, "Deprecated ports pref '%s.%s' not found", module
->name, port_prefs[i].table_name); } } while (0)
;
5671 continue;
5672 }
5673 if (pref->type != PREF_DECODE_AS_RANGE) {
5674 ws_warning("Deprecated ports pref '%s.%s' has wrong type: %#x (%s)", module->name, port_prefs[i].table_name, pref->type, prefs_pref_type_name(pref))do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 5674, __func__, "Deprecated ports pref '%s.%s' has wrong type: %#x (%s)"
, module->name, port_prefs[i].table_name, pref->type, prefs_pref_type_name
(pref)); } } while (0)
;
5675 }
5676 }
5677 }
5678
5679 for (i = 0; i < G_N_ELEMENTS(port_prefs)(sizeof (port_prefs) / sizeof ((port_prefs)[0])); i++) {
5680 if (strcmp(pref_name, port_prefs[i].pref_name) == 0) {
5681 if (!ws_basestrtou32(value, NULL((void*)0), &uval, port_prefs[i].base))
5682 return false0; /* number was bad */
5683
5684 module = prefs_find_module(port_prefs[i].module_name);
5685 pref = prefs_find_preference(module, port_prefs[i].table_name);
5686 if (pref != NULL((void*)0)) {
5687 module->prefs_changed_flags |= prefs_get_effect_flags(pref);
5688 if (pref->type == PREF_DECODE_AS_RANGE) {
5689 // The legacy preference was a port number, but the new
5690 // preference is a port range. Add to existing range.
5691 if (uval) {
5692 prefs_range_add_value(pref, uval);
5693 }
5694 }
5695 }
5696
5697 /* If the value is zero, it wouldn't add to the Decode As tables */
5698 if (uval != 0)
5699 {
5700 sub_dissectors = find_dissector_table(port_prefs[i].table_name);
5701 if (sub_dissectors != NULL((void*)0)) {
5702 handle = dissector_table_get_dissector_handle(sub_dissectors, module->title);
5703 if (handle != NULL((void*)0)) {
5704 dissector_change_uint(port_prefs[i].table_name, uval, handle);
5705 decode_build_reset_list(port_prefs[i].table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(uval)((gpointer) (gulong) (uval)), NULL((void*)0), NULL((void*)0));
5706 }
5707 }
5708 }
5709
5710 return true1;
5711 }
5712 }
5713
5714 for (i = 0; i < array_length(port_range_prefs)(sizeof (port_range_prefs) / sizeof (port_range_prefs)[0]); i++)
5715 {
5716 if (strcmp(pref_name, port_range_prefs[i].pref_name) == 0)
5717 {
5718 uint32_t range_i, range_j;
5719
5720 sub_dissectors = find_dissector_table(port_range_prefs[i].table_name);
5721 if (sub_dissectors != NULL((void*)0)) {
5722 switch (dissector_table_get_type(sub_dissectors)) {
5723 case FT_UINT8:
5724 case FT_UINT16:
5725 case FT_UINT24:
5726 case FT_UINT32:
5727 break;
5728
5729 default:
5730 ws_error("The dissector table %s (%s) is not an integer type - are you using a buggy plugin?", port_range_prefs[i].table_name, get_dissector_table_ui_name(port_range_prefs[i].table_name))ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 5730
, __func__, "The dissector table %s (%s) is not an integer type - are you using a buggy plugin?"
, port_range_prefs[i].table_name, get_dissector_table_ui_name
(port_range_prefs[i].table_name))
;
5731 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 5731
, __func__, "assertion \"not reached\" failed")
;
5732 }
5733
5734 module = prefs_find_module(port_range_prefs[i].module_name);
5735 pref = prefs_find_preference(module, port_range_prefs[i].table_name);
5736 if (pref != NULL((void*)0))
5737 {
5738 if (!prefs_set_range_value_work(pref, value, true1, &module->prefs_changed_flags))
5739 {
5740 return false0; /* number was bad */
5741 }
5742
5743 handle = dissector_table_get_dissector_handle(sub_dissectors, module->title);
5744 if (handle != NULL((void*)0)) {
5745
5746 for (range_i = 0; range_i < (*pref->varp.range)->nranges; range_i++) {
5747 for (range_j = (*pref->varp.range)->ranges[range_i].low; range_j < (*pref->varp.range)->ranges[range_i].high; range_j++) {
5748 dissector_change_uint(port_range_prefs[i].table_name, range_j, handle);
5749 decode_build_reset_list(port_range_prefs[i].table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(range_j)((gpointer) (gulong) (range_j)), NULL((void*)0), NULL((void*)0));
5750 }
5751
5752 dissector_change_uint(port_range_prefs[i].table_name, (*pref->varp.range)->ranges[range_i].high, handle);
5753 decode_build_reset_list(port_range_prefs[i].table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER((*pref->varp.range)->ranges[range_i].high)((gpointer) (gulong) ((*pref->varp.range)->ranges[range_i
].high))
, NULL((void*)0), NULL((void*)0));
5754 }
5755 }
5756 }
5757 }
5758
5759 return true1;
5760 }
5761 }
5762
5763 for (i = 0; i < array_length(tpkt_subdissector_port_prefs)(sizeof (tpkt_subdissector_port_prefs) / sizeof (tpkt_subdissector_port_prefs
)[0])
; i++)
5764 {
5765 if (strcmp(pref_name, tpkt_subdissector_port_prefs[i].pref_name) == 0)
5766 {
5767 /* XXX - give an error if it doesn't fit in a unsigned? */
5768 if (!ws_basestrtou32(value, NULL((void*)0), &uval, tpkt_subdissector_port_prefs[i].base))
5769 return false0; /* number was bad */
5770
5771 /* If the value is 0 or 102 (default TPKT port), don't add to the Decode As tables */
5772 if ((uval != 0) && (uval != 102))
5773 {
5774 tpkt_handle = find_dissector("tpkt");
5775 if (tpkt_handle != NULL((void*)0)) {
5776 dissector_change_uint(tpkt_subdissector_port_prefs[i].table_name, uval, tpkt_handle);
5777 }
5778 }
5779
5780 return true1;
5781 }
5782 }
5783
5784 for (i = 0; i < array_length(obsolete_prefs)(sizeof (obsolete_prefs) / sizeof (obsolete_prefs)[0]); i++)
5785 {
5786 if (strcmp(pref_name, obsolete_prefs[i].pref_name) == 0)
5787 {
5788 /* Just ignore the preference */
5789 return true1;
5790 }
5791 }
5792 return false0;
5793}
5794
5795static prefs_set_pref_e
5796set_pref(char *pref_name, const char *value, void *private_data,
5797 bool_Bool return_range_errors)
5798{
5799 unsigned cval;
5800 unsigned uval;
5801 bool_Bool bval;
5802 int enum_val;
5803 char *dotp, *last_dotp;
5804 static char *filter_label = NULL((void*)0);
5805 static bool_Bool filter_enabled = false0;
5806 module_t *module, *containing_module, *target_module;
5807 pref_t *pref;
5808 bool_Bool converted_pref = false0;
5809
5810 target_module = (module_t*)private_data;
5811
5812 //The PRS_GUI field names are here for backwards compatibility
5813 //display filters have been converted to a UAT.
5814 if (strcmp(pref_name, PRS_GUI_FILTER_LABEL"gui.filter_expressions.label") == 0) {
5815 /* Assume that PRS_GUI_FILTER_EXPR follows this preference. In case of
5816 * malicious preference files, free the previous value to limit the size
5817 * of leaked memory. */
5818 g_free(filter_label);
5819 filter_label = g_strdup(value)g_strdup_inline (value);
5820 } else if (strcmp(pref_name, PRS_GUI_FILTER_ENABLED"gui.filter_expressions.enabled") == 0) {
5821 filter_enabled = (strcmp(value, "TRUE") == 0) ? true1 : false0;
5822 } else if (strcmp(pref_name, PRS_GUI_FILTER_EXPR"gui.filter_expressions.expr") == 0) {
5823 /* Comments not supported for "old" preference style */
5824 filter_expression_new(filter_label, value, "", filter_enabled);
5825 g_free(filter_label);
5826 filter_label = NULL((void*)0);
5827 /* Remember to save the new UAT to file. */
5828 prefs.filter_expressions_old = true1;
5829 } else if (strcmp(pref_name, "gui.version_in_start_page") == 0) {
5830 /* Convert deprecated value to closest current equivalent */
5831 if (g_ascii_strcasecmp(value, "true") == 0) {
5832 prefs.gui_version_placement = version_both;
5833 } else {
5834 prefs.gui_version_placement = version_neither;
5835 }
5836 } else if (strcmp(pref_name, "name_resolve") == 0 ||
5837 strcmp(pref_name, "capture.name_resolve") == 0) {
5838 /*
5839 * Handle the deprecated name resolution options.
5840 *
5841 * "TRUE" and "FALSE", for backwards compatibility, are synonyms for
5842 * RESOLV_ALL and RESOLV_NONE.
5843 *
5844 * Otherwise, we treat it as a list of name types we want to resolve.
5845 */
5846 if (g_ascii_strcasecmp(value, "true") == 0) {
5847 gbl_resolv_flags.mac_name = true1;
5848 gbl_resolv_flags.network_name = true1;
5849 gbl_resolv_flags.transport_name = true1;
5850 }
5851 else if (g_ascii_strcasecmp(value, "false") == 0) {
5852 disable_name_resolution();
5853 }
5854 else {
5855 /* start out with none set */
5856 disable_name_resolution();
5857 if (string_to_name_resolve(value, &gbl_resolv_flags) != '\0')
5858 return PREFS_SET_SYNTAX_ERR;
5859 }
5860 } else if (deprecated_heur_dissector_pref(pref_name, value)) {
5861 /* Handled within deprecated_heur_dissector_pref() if found */
5862 } else if (deprecated_enable_dissector_pref(pref_name, value)) {
5863 /* Handled within deprecated_enable_dissector_pref() if found */
5864 } else if (deprecated_port_pref(pref_name, value)) {
5865 /* Handled within deprecated_port_pref() if found */
5866 } else if (strcmp(pref_name, "console.log.level") == 0) {
5867 /* Handled on the command line within ws_log_parse_args() */
5868 return PREFS_SET_OK;
5869 } else {
5870 /* Handle deprecated "global" options that don't have a module
5871 * associated with them
5872 */
5873 if ((strcmp(pref_name, "name_resolve_concurrency") == 0) ||
5874 (strcmp(pref_name, "name_resolve_load_smi_modules") == 0) ||
5875 (strcmp(pref_name, "name_resolve_suppress_smi_errors") == 0)) {
5876 module = nameres_module;
5877 dotp = pref_name;
5878 } else {
5879 /* To which module does this preference belong? */
5880 module = NULL((void*)0);
5881 last_dotp = pref_name;
5882 while (!module) {
5883 dotp = strchr(last_dotp, '.');
5884 if (dotp == NULL((void*)0)) {
5885 /* Either there's no such module, or no module was specified.
5886 In either case, that means there's no such preference. */
5887 return PREFS_SET_NO_SUCH_PREF;
5888 }
5889 *dotp = '\0'; /* separate module and preference name */
5890 module = prefs_find_module(pref_name);
5891
5892 /*
5893 * XXX - "Diameter" rather than "diameter" was used in earlier
5894 * versions of Wireshark; if we didn't find the module, and its name
5895 * was "Diameter", look for "diameter" instead.
5896 *
5897 * In addition, the BEEP protocol used to be the BXXP protocol,
5898 * so if we didn't find the module, and its name was "bxxp",
5899 * look for "beep" instead.
5900 *
5901 * Also, the preferences for GTP v0 and v1 were combined under
5902 * a single "gtp" heading, and the preferences for SMPP were
5903 * moved to "smpp-gsm-sms" and then moved to "gsm-sms-ud".
5904 * However, SMPP now has its own preferences, so we just map
5905 * "smpp-gsm-sms" to "gsm-sms-ud", and then handle SMPP below.
5906 *
5907 * We also renamed "dcp" to "dccp", "x.25" to "x25", "x411" to "p1"
5908 * and "nsip" to "gprs_ns".
5909 *
5910 * The SynOptics Network Management Protocol (SONMP) is now known by
5911 * its modern name, the Nortel Discovery Protocol (NDP).
5912 */
5913 if (module == NULL((void*)0)) {
5914 /*
5915 * See if there's a backwards-compatibility name
5916 * that maps to this module.
5917 */
5918 module = prefs_find_module_alias(pref_name);
5919 if (module == NULL((void*)0)) {
5920 /*
5921 * There's no alias for the module; see if the
5922 * module name matches any protocol aliases.
5923 */
5924 header_field_info *hfinfo = proto_registrar_get_byalias(pref_name);
5925 if (hfinfo) {
5926 module = (module_t *) wmem_tree_lookup_string(prefs_modules, hfinfo->abbrev, WMEM_TREE_STRING_NOCASE0x00000001);
5927 }
5928 }
5929 if (module == NULL((void*)0)) {
5930 /*
5931 * There aren't any aliases. Was the module
5932 * removed rather than renamed?
5933 */
5934 if (strcmp(pref_name, "etheric") == 0 ||
5935 strcmp(pref_name, "isup_thin") == 0) {
5936 /*
5937 * The dissectors for these protocols were
5938 * removed as obsolete on 2009-07-70 in change
5939 * 739bfc6ff035583abb9434e0e988048de38a8d9a.
5940 */
5941 return PREFS_SET_OBSOLETE;
5942 }
5943 }
5944 if (module) {
5945 converted_pref = true1;
5946 prefs.unknown_prefs = true1;
5947 }
5948 }
5949 *dotp = '.'; /* put the preference string back */
5950 dotp++; /* skip past separator to preference name */
5951 last_dotp = dotp;
5952 }
5953 }
5954
5955 /* The pref is located in the module or a submodule.
5956 * Assume module, then search for a submodule holding the pref. */
5957 containing_module = module;
5958 pref = prefs_find_preference_with_submodule(module, dotp, &containing_module);
5959
5960 if (pref == NULL((void*)0)) {
5961 prefs.unknown_prefs = true1;
5962
5963 /* "gui" prefix was added to column preferences for better organization
5964 * within the preferences file
5965 */
5966 if (module == gui_column_module) {
5967 /* While this has a subtree, there is no apply callback, so no
5968 * need to use prefs_find_preference_with_submodule to update
5969 * containing_module. It would not be useful. */
5970 pref = prefs_find_preference(module, pref_name);
5971 }
5972 else if (strcmp(module->name, "mgcp") == 0) {
5973 /*
5974 * XXX - "mgcp.display raw text toggle" and "mgcp.display dissect tree"
5975 * rather than "mgcp.display_raw_text" and "mgcp.display_dissect_tree"
5976 * were used in earlier versions of Wireshark; if we didn't find the
5977 * preference, it was an MGCP preference, and its name was
5978 * "display raw text toggle" or "display dissect tree", look for
5979 * "display_raw_text" or "display_dissect_tree" instead.
5980 *
5981 * "mgcp.tcp.port" and "mgcp.udp.port" are harder to handle, as both
5982 * the gateway and callagent ports were given those names; we interpret
5983 * the first as "mgcp.{tcp,udp}.gateway_port" and the second as
5984 * "mgcp.{tcp,udp}.callagent_port", as that's the order in which
5985 * they were registered by the MCCP dissector and thus that's the
5986 * order in which they were written to the preferences file. (If
5987 * we're not reading the preferences file, but are handling stuff
5988 * from a "-o" command-line option, we have no clue which the user
5989 * had in mind - they should have used "mgcp.{tcp,udp}.gateway_port"
5990 * or "mgcp.{tcp,udp}.callagent_port" instead.)
5991 */
5992 if (strcmp(dotp, "display raw text toggle") == 0)
5993 pref = prefs_find_preference(module, "display_raw_text");
5994 else if (strcmp(dotp, "display dissect tree") == 0)
5995 pref = prefs_find_preference(module, "display_dissect_tree");
5996 else if (strcmp(dotp, "tcp.port") == 0) {
5997 mgcp_tcp_port_count++;
5998 if (mgcp_tcp_port_count == 1) {
5999 /* It's the first one */
6000 pref = prefs_find_preference(module, "tcp.gateway_port");
6001 } else if (mgcp_tcp_port_count == 2) {
6002 /* It's the second one */
6003 pref = prefs_find_preference(module, "tcp.callagent_port");
6004 }
6005 /* Otherwise it's from the command line, and we don't bother
6006 mapping it. */
6007 } else if (strcmp(dotp, "udp.port") == 0) {
6008 mgcp_udp_port_count++;
6009 if (mgcp_udp_port_count == 1) {
6010 /* It's the first one */
6011 pref = prefs_find_preference(module, "udp.gateway_port");
6012 } else if (mgcp_udp_port_count == 2) {
6013 /* It's the second one */
6014 pref = prefs_find_preference(module, "udp.callagent_port");
6015 }
6016 /* Otherwise it's from the command line, and we don't bother
6017 mapping it. */
6018 }
6019 } else if (strcmp(module->name, "smb") == 0) {
6020 /* Handle old names for SMB preferences. */
6021 if (strcmp(dotp, "smb.trans.reassembly") == 0)
6022 pref = prefs_find_preference(module, "trans_reassembly");
6023 else if (strcmp(dotp, "smb.dcerpc.reassembly") == 0)
6024 pref = prefs_find_preference(module, "dcerpc_reassembly");
6025 } else if (strcmp(module->name, "ndmp") == 0) {
6026 /* Handle old names for NDMP preferences. */
6027 if (strcmp(dotp, "ndmp.desegment") == 0)
6028 pref = prefs_find_preference(module, "desegment");
6029 } else if (strcmp(module->name, "diameter") == 0) {
6030 /* Handle old names for Diameter preferences. */
6031 if (strcmp(dotp, "diameter.desegment") == 0)
6032 pref = prefs_find_preference(module, "desegment");
6033 } else if (strcmp(module->name, "pcli") == 0) {
6034 /* Handle old names for PCLI preferences. */
6035 if (strcmp(dotp, "pcli.udp_port") == 0)
6036 pref = prefs_find_preference(module, "udp_port");
6037 } else if (strcmp(module->name, "artnet") == 0) {
6038 /* Handle old names for ARTNET preferences. */
6039 if (strcmp(dotp, "artnet.udp_port") == 0)
6040 pref = prefs_find_preference(module, "udp_port");
6041 } else if (strcmp(module->name, "mapi") == 0) {
6042 /* Handle old names for MAPI preferences. */
6043 if (strcmp(dotp, "mapi_decrypt") == 0)
6044 pref = prefs_find_preference(module, "decrypt");
6045 } else if (strcmp(module->name, "fc") == 0) {
6046 /* Handle old names for Fibre Channel preferences. */
6047 if (strcmp(dotp, "reassemble_fc") == 0)
6048 pref = prefs_find_preference(module, "reassemble");
6049 else if (strcmp(dotp, "fc_max_frame_size") == 0)
6050 pref = prefs_find_preference(module, "max_frame_size");
6051 } else if (strcmp(module->name, "fcip") == 0) {
6052 /* Handle old names for Fibre Channel-over-IP preferences. */
6053 if (strcmp(dotp, "desegment_fcip_messages") == 0)
6054 pref = prefs_find_preference(module, "desegment");
6055 else if (strcmp(dotp, "fcip_port") == 0)
6056 pref = prefs_find_preference(module, "target_port");
6057 } else if (strcmp(module->name, "gtp") == 0) {
6058 /* Handle old names for GTP preferences. */
6059 if (strcmp(dotp, "gtpv0_port") == 0)
6060 pref = prefs_find_preference(module, "v0_port");
6061 else if (strcmp(dotp, "gtpv1c_port") == 0)
6062 pref = prefs_find_preference(module, "v1c_port");
6063 else if (strcmp(dotp, "gtpv1u_port") == 0)
6064 pref = prefs_find_preference(module, "v1u_port");
6065 else if (strcmp(dotp, "gtp_dissect_tpdu") == 0)
6066 pref = prefs_find_preference(module, "dissect_tpdu");
6067 else if (strcmp(dotp, "gtpv0_dissect_cdr_as") == 0)
6068 pref = prefs_find_preference(module, "v0_dissect_cdr_as");
6069 else if (strcmp(dotp, "gtpv0_check_etsi") == 0)
6070 pref = prefs_find_preference(module, "v0_check_etsi");
6071 else if (strcmp(dotp, "gtpv1_check_etsi") == 0)
6072 pref = prefs_find_preference(module, "v1_check_etsi");
6073 } else if (strcmp(module->name, "ip") == 0) {
6074 /* Handle old names for IP preferences. */
6075 if (strcmp(dotp, "ip_summary_in_tree") == 0)
6076 pref = prefs_find_preference(module, "summary_in_tree");
6077 } else if (strcmp(module->name, "iscsi") == 0) {
6078 /* Handle old names for iSCSI preferences. */
6079 if (strcmp(dotp, "iscsi_port") == 0)
6080 pref = prefs_find_preference(module, "target_port");
6081 } else if (strcmp(module->name, "lmp") == 0) {
6082 /* Handle old names for LMP preferences. */
6083 if (strcmp(dotp, "lmp_version") == 0)
6084 pref = prefs_find_preference(module, "version");
6085 } else if (strcmp(module->name, "mtp3") == 0) {
6086 /* Handle old names for MTP3 preferences. */
6087 if (strcmp(dotp, "mtp3_standard") == 0)
6088 pref = prefs_find_preference(module, "standard");
6089 else if (strcmp(dotp, "net_addr_format") == 0)
6090 pref = prefs_find_preference(module, "addr_format");
6091 } else if (strcmp(module->name, "nlm") == 0) {
6092 /* Handle old names for NLM preferences. */
6093 if (strcmp(dotp, "nlm_msg_res_matching") == 0)
6094 pref = prefs_find_preference(module, "msg_res_matching");
6095 } else if (strcmp(module->name, "ppp") == 0) {
6096 /* Handle old names for PPP preferences. */
6097 if (strcmp(dotp, "ppp_fcs") == 0)
6098 pref = prefs_find_preference(module, "fcs_type");
6099 else if (strcmp(dotp, "ppp_vj") == 0)
6100 pref = prefs_find_preference(module, "decompress_vj");
6101 } else if (strcmp(module->name, "rsvp") == 0) {
6102 /* Handle old names for RSVP preferences. */
6103 if (strcmp(dotp, "rsvp_process_bundle") == 0)
6104 pref = prefs_find_preference(module, "process_bundle");
6105 } else if (strcmp(module->name, "tcp") == 0) {
6106 /* Handle old names for TCP preferences. */
6107 if (strcmp(dotp, "tcp_summary_in_tree") == 0)
6108 pref = prefs_find_preference(module, "summary_in_tree");
6109 else if (strcmp(dotp, "tcp_analyze_sequence_numbers") == 0)
6110 pref = prefs_find_preference(module, "analyze_sequence_numbers");
6111 else if (strcmp(dotp, "tcp_relative_sequence_numbers") == 0)
6112 pref = prefs_find_preference(module, "relative_sequence_numbers");
6113 else if (strcmp(dotp, "dissect_experimental_options_with_magic") == 0)
6114 pref = prefs_find_preference(module, "dissect_experimental_options_rfc6994");
6115 } else if (strcmp(module->name, "udp") == 0) {
6116 /* Handle old names for UDP preferences. */
6117 if (strcmp(dotp, "udp_summary_in_tree") == 0)
6118 pref = prefs_find_preference(module, "summary_in_tree");
6119 } else if (strcmp(module->name, "ndps") == 0) {
6120 /* Handle old names for NDPS preferences. */
6121 if (strcmp(dotp, "desegment_ndps") == 0)
6122 pref = prefs_find_preference(module, "desegment_tcp");
6123 } else if (strcmp(module->name, "http") == 0) {
6124 /* Handle old names for HTTP preferences. */
6125 if (strcmp(dotp, "desegment_http_headers") == 0)
6126 pref = prefs_find_preference(module, "desegment_headers");
6127 else if (strcmp(dotp, "desegment_http_body") == 0)
6128 pref = prefs_find_preference(module, "desegment_body");
6129 } else if (strcmp(module->name, "smpp") == 0) {
6130 /* Handle preferences that moved from SMPP. */
6131 module_t *new_module = prefs_find_module("gsm-sms-ud");
6132 if (new_module) {
6133 if (strcmp(dotp, "port_number_udh_means_wsp") == 0) {
6134 pref = prefs_find_preference(new_module, "port_number_udh_means_wsp");
6135 containing_module = new_module;
6136 } else if (strcmp(dotp, "try_dissect_1st_fragment") == 0) {
6137 pref = prefs_find_preference(new_module, "try_dissect_1st_fragment");
6138 containing_module = new_module;
6139 }
6140 }
6141 } else if (strcmp(module->name, "asn1") == 0) {
6142 /* Handle old generic ASN.1 preferences (it's not really a
6143 rename, as the new preferences support multiple ports,
6144 but we might as well copy them over). */
6145 if (strcmp(dotp, "tcp_port") == 0)
6146 pref = prefs_find_preference(module, "tcp_ports");
6147 else if (strcmp(dotp, "udp_port") == 0)
6148 pref = prefs_find_preference(module, "udp_ports");
6149 else if (strcmp(dotp, "sctp_port") == 0)
6150 pref = prefs_find_preference(module, "sctp_ports");
6151 } else if (strcmp(module->name, "llcgprs") == 0) {
6152 if (strcmp(dotp, "ignore_cipher_bit") == 0)
6153 pref = prefs_find_preference(module, "autodetect_cipher_bit");
6154 } else if (strcmp(module->name, "erf") == 0) {
6155 if (strcmp(dotp, "erfeth") == 0) {
6156 /* Handle the old "erfeth" preference; map it to the new
6157 "ethfcs" preference, and map the values to those for
6158 the new preference. */
6159 pref = prefs_find_preference(module, "ethfcs");
6160 if (strcmp(value, "ethfcs") == 0 || strcmp(value, "Ethernet with FCS") == 0)
6161 value = "TRUE";
6162 else if (strcmp(value, "eth") == 0 || strcmp(value, "Ethernet") == 0)
6163 value = "FALSE";
6164 else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
6165 value = "TRUE";
6166 } else if (strcmp(dotp, "erfatm") == 0) {
6167 /* Handle the old "erfatm" preference; map it to the new
6168 "aal5_type" preference, and map the values to those for
6169 the new preference. */
6170 pref = prefs_find_preference(module, "aal5_type");
6171 if (strcmp(value, "atm") == 0 || strcmp(value, "ATM") == 0)
6172 value = "guess";
6173 else if (strcmp(value, "llc") == 0 || strcmp(value, "LLC") == 0)
6174 value = "llc";
6175 else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
6176 value = "guess";
6177 } else if (strcmp(dotp, "erfhdlc") == 0) {
6178 /* Handle the old "erfhdlc" preference; map it to the new
6179 "hdlc_type" preference, and map the values to those for
6180 the new preference. */
6181 pref = prefs_find_preference(module, "hdlc_type");
6182 if (strcmp(value, "chdlc") == 0 || strcmp(value, "Cisco HDLC") == 0)
6183 value = "chdlc";
6184 else if (strcmp(value, "ppp") == 0 || strcmp(value, "PPP serial") == 0)
6185 value = "ppp";
6186 else if (strcmp(value, "fr") == 0 || strcmp(value, "Frame Relay") == 0)
6187 value = "frelay";
6188 else if (strcmp(value, "mtp2") == 0 || strcmp(value, "SS7 MTP2") == 0)
6189 value = "mtp2";
6190 else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
6191 value = "guess";
6192 }
6193 } else if (strcmp(module->name, "eth") == 0) {
6194 /* "eth.qinq_ethertype" has been changed(restored) to "vlan.qinq.ethertype" */
6195 if (strcmp(dotp, "qinq_ethertype") == 0) {
6196 module_t *new_module = prefs_find_module("vlan");
6197 if (new_module) {
6198 pref = prefs_find_preference(new_module, "qinq_ethertype");
6199 containing_module = new_module;
6200 }
6201 }
6202 } else if (strcmp(module->name, "taps") == 0) {
6203 /* taps preferences moved to "statistics" module */
6204 if (strcmp(dotp, "update_interval") == 0)
6205 pref = prefs_find_preference(stats_module, dotp);
6206 } else if (strcmp(module->name, "packet_list") == 0) {
6207 /* packet_list preferences moved to protocol module */
6208 if (strcmp(dotp, "display_hidden_proto_items") == 0)
6209 pref = prefs_find_preference(protocols_module, dotp);
6210 } else if (strcmp(module->name, "stream") == 0) {
6211 /* stream preferences moved to gui color module */
6212 if ((strcmp(dotp, "client.fg") == 0) ||
6213 (strcmp(dotp, "client.bg") == 0) ||
6214 (strcmp(dotp, "server.fg") == 0) ||
6215 (strcmp(dotp, "server.bg") == 0))
6216 pref = prefs_find_preference(gui_color_module, pref_name);
6217 } else if (strcmp(module->name, "nameres") == 0) {
6218 if (strcmp(pref_name, "name_resolve_concurrency") == 0) {
6219 pref = prefs_find_preference(nameres_module, pref_name);
6220 } else if (strcmp(pref_name, "name_resolve_load_smi_modules") == 0) {
6221 pref = prefs_find_preference(nameres_module, "load_smi_modules");
6222 } else if (strcmp(pref_name, "name_resolve_suppress_smi_errors") == 0) {
6223 pref = prefs_find_preference(nameres_module, "suppress_smi_errors");
6224 }
6225 } else if (strcmp(module->name, "extcap") == 0) {
6226 /* Handle the old "sshdump.remotesudo" preference; map it to the new
6227 "sshdump.remotepriv" preference, and map the boolean values to the
6228 appropriate strings of the new preference. */
6229 if (strcmp(dotp, "sshdump.remotesudo") == 0) {
6230 pref = prefs_find_preference(module, "sshdump.remotepriv");
6231 if (g_ascii_strcasecmp(value, "true") == 0)
6232 value = "sudo";
6233 else
6234 value = "none";
6235 }
6236 }
6237 if (pref) {
6238 converted_pref = true1;
6239 }
6240 }
6241 if (pref == NULL((void*)0) ) {
6242 if (strcmp(module->name, "extcap") == 0 && g_list_length(module->prefs) <= 1) {
6243 /*
6244 * Assume that we've skipped extcap preference registration
6245 * and that only extcap.gui_save_on_start is loaded.
6246 */
6247 return PREFS_SET_OK;
6248 }
6249 return PREFS_SET_NO_SUCH_PREF; /* no such preference */
6250 }
6251
6252 if (target_module && target_module != containing_module) {
6253 /* Ignore */
6254 return PREFS_SET_OK;
6255 }
6256
6257 if (pref->obsolete)
6258 return PREFS_SET_OBSOLETE; /* no such preference any more */
6259
6260 if (converted_pref) {
6261 ws_warning("Preference \"%s\" has been converted to \"%s.%s\"\n"do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 6263, __func__, "Preference \"%s\" has been converted to \"%s.%s\"\n"
"Save your preferences to make this change permanent.", pref_name
, module->name ? module->name : module->parent->name
, prefs_get_name(pref)); } } while (0)
6262 "Save your preferences to make this change permanent.",do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 6263, __func__, "Preference \"%s\" has been converted to \"%s.%s\"\n"
"Save your preferences to make this change permanent.", pref_name
, module->name ? module->name : module->parent->name
, prefs_get_name(pref)); } } while (0)
6263 pref_name, module->name ? module->name : module->parent->name, prefs_get_name(pref))do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 6263, __func__, "Preference \"%s\" has been converted to \"%s.%s\"\n"
"Save your preferences to make this change permanent.", pref_name
, module->name ? module->name : module->parent->name
, prefs_get_name(pref)); } } while (0)
;
6264 }
6265
6266 switch (pref->type) {
6267
6268 case PREF_UINT:
6269 if (!ws_basestrtou32(value, NULL((void*)0), &uval, pref->info.base))
6270 return PREFS_SET_SYNTAX_ERR; /* number was bad */
6271 if (*pref->varp.uint != uval) {
6272 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
6273 *pref->varp.uint = uval;
6274 }
6275 break;
6276 case PREF_BOOL:
6277 /* XXX - give an error if it's neither "true" nor "false"? */
6278 if (g_ascii_strcasecmp(value, "true") == 0)
6279 bval = true1;
6280 else
6281 bval = false0;
6282 if (*pref->varp.boolp != bval) {
6283 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
6284 *pref->varp.boolp = bval;
6285 }
6286 break;
6287
6288 case PREF_ENUM:
6289 /* XXX - give an error if it doesn't match? */
6290 enum_val = find_val_for_string(value, pref->info.enum_info.enumvals,
6291 *pref->varp.enump);
6292 if (*pref->varp.enump != enum_val) {
6293 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
6294 *pref->varp.enump = enum_val;
6295 }
6296 break;
6297
6298 case PREF_STRING:
6299 case PREF_SAVE_FILENAME:
6300 case PREF_OPEN_FILENAME:
6301 case PREF_DIRNAME:
6302 case PREF_DISSECTOR:
6303 containing_module->prefs_changed_flags |= prefs_set_string_value(pref, value, pref_current);
6304 break;
6305
6306 case PREF_PASSWORD:
6307 /* Read value is every time empty */
6308 containing_module->prefs_changed_flags |= prefs_set_string_value(pref, "", pref_current);
6309 break;
6310
6311 case PREF_RANGE:
6312 {
6313 if (!prefs_set_range_value_work(pref, value, return_range_errors,
6314 &containing_module->prefs_changed_flags))
6315 return PREFS_SET_SYNTAX_ERR; /* number was bad */
6316 break;
6317 }
6318 case PREF_DECODE_AS_RANGE:
6319 {
6320 /* This is for backwards compatibility in case any of the preferences
6321 that shared the "Decode As" preference name and used to be PREF_RANGE
6322 are now applied directly to the Decode As functionality */
6323 range_t *newrange;
6324 dissector_table_t sub_dissectors;
6325 dissector_handle_t handle;
6326 uint32_t i, j;
6327
6328 if (range_convert_str_work(wmem_epan_scope(), &newrange, value, pref->info.max_value,
6329 return_range_errors) != CVT_NO_ERROR) {
6330 return PREFS_SET_SYNTAX_ERR; /* number was bad */
6331 }
6332
6333 if (!ranges_are_equal(*pref->varp.range, newrange)) {
6334 wmem_free(wmem_epan_scope(), *pref->varp.range);
6335 *pref->varp.range = newrange;
6336 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
6337
6338 const char* table_name = prefs_get_dissector_table(pref);
6339 sub_dissectors = find_dissector_table(table_name);
6340 if (sub_dissectors != NULL((void*)0)) {
6341 handle = dissector_table_get_dissector_handle(sub_dissectors, module->title);
6342 if (handle != NULL((void*)0)) {
6343 /* Delete all of the old values from the dissector table */
6344 for (i = 0; i < (*pref->varp.range)->nranges; i++) {
6345 for (j = (*pref->varp.range)->ranges[i].low; j < (*pref->varp.range)->ranges[i].high; j++) {
6346 dissector_delete_uint(table_name, j, handle);
6347 decode_build_reset_list(table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(j)((gpointer) (gulong) (j)), NULL((void*)0), NULL((void*)0));
6348 }
6349
6350 dissector_delete_uint(table_name, (*pref->varp.range)->ranges[i].high, handle);
6351 decode_build_reset_list(table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER((*pref->varp.range)->ranges[i].high)((gpointer) (gulong) ((*pref->varp.range)->ranges[i].high
))
, NULL((void*)0), NULL((void*)0));
6352 }
6353
6354 /* Add new values to the dissector table */
6355 for (i = 0; i < newrange->nranges; i++) {
6356 for (j = newrange->ranges[i].low; j < newrange->ranges[i].high; j++) {
6357 dissector_change_uint(table_name, j, handle);
6358 decode_build_reset_list(table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(j)((gpointer) (gulong) (j)), NULL((void*)0), NULL((void*)0));
6359 }
6360
6361 dissector_change_uint(table_name, newrange->ranges[i].high, handle);
6362 decode_build_reset_list(table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(newrange->ranges[i].high)((gpointer) (gulong) (newrange->ranges[i].high)), NULL((void*)0), NULL((void*)0));
6363 }
6364
6365 /* XXX - Do we save the decode_as_entries file here? */
6366 }
6367 }
6368 } else {
6369 wmem_free(wmem_epan_scope(), newrange);
6370 }
6371 break;
6372 }
6373
6374 case PREF_COLOR:
6375 {
6376 if (!ws_hexstrtou32(value, NULL((void*)0), &cval))
6377 return PREFS_SET_SYNTAX_ERR; /* number was bad */
6378 if ((pref->varp.colorp->red != RED_COMPONENT(cval)(uint16_t) (((((cval) >> 16) & 0xff) * 65535 / 255)
)
) ||
6379 (pref->varp.colorp->green != GREEN_COMPONENT(cval)(uint16_t) (((((cval) >> 8) & 0xff) * 65535 / 255))) ||
6380 (pref->varp.colorp->blue != BLUE_COMPONENT(cval)(uint16_t) ( (((cval) & 0xff) * 65535 / 255)))) {
6381 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
6382 pref->varp.colorp->red = RED_COMPONENT(cval)(uint16_t) (((((cval) >> 16) & 0xff) * 65535 / 255)
)
;
6383 pref->varp.colorp->green = GREEN_COMPONENT(cval)(uint16_t) (((((cval) >> 8) & 0xff) * 65535 / 255));
6384 pref->varp.colorp->blue = BLUE_COMPONENT(cval)(uint16_t) ( (((cval) & 0xff) * 65535 / 255));
6385 }
6386 break;
6387 }
6388
6389 case PREF_CUSTOM:
6390 return pref->custom_cbs.set_cb(pref, value, &containing_module->prefs_changed_flags);
6391
6392 case PREF_STATIC_TEXT:
6393 case PREF_UAT:
6394 break;
6395
6396 case PREF_PROTO_TCP_SNDAMB_ENUM:
6397 {
6398 /* There's no point in setting the TCP sequence override
6399 * value from the command line, because the pref is different
6400 * for each frame and reset to the default (0) for each new
6401 * file.
6402 */
6403 break;
6404 }
6405 }
6406 }
6407
6408 return PREFS_SET_OK;
6409}
6410
6411typedef struct {
6412 FILE *pf;
6413 bool_Bool is_gui_module;
6414} write_gui_pref_arg_t;
6415
6416const char *
6417prefs_pref_type_name(pref_t *pref)
6418{
6419 const char *type_name = "[Unknown]";
6420
6421 if (!pref) {
6422 return type_name; /* ...or maybe assert? */
6423 }
6424
6425 if (pref->obsolete) {
6426 type_name = "Obsolete";
6427 } else {
6428 switch (pref->type) {
6429
6430 case PREF_UINT:
6431 switch (pref->info.base) {
6432
6433 case 10:
6434 type_name = "Decimal";
6435 break;
6436
6437 case 8:
6438 type_name = "Octal";
6439 break;
6440
6441 case 16:
6442 type_name = "Hexadecimal";
6443 break;
6444 }
6445 break;
6446
6447 case PREF_BOOL:
6448 type_name = "Boolean";
6449 break;
6450
6451 case PREF_ENUM:
6452 case PREF_PROTO_TCP_SNDAMB_ENUM:
6453 type_name = "Choice";
6454 break;
6455
6456 case PREF_STRING:
6457 type_name = "String";
6458 break;
6459
6460 case PREF_SAVE_FILENAME:
6461 case PREF_OPEN_FILENAME:
6462 type_name = "Filename";
6463 break;
6464
6465 case PREF_DIRNAME:
6466 type_name = "Directory";
6467 break;
6468
6469 case PREF_RANGE:
6470 type_name = "Range";
6471 break;
6472
6473 case PREF_COLOR:
6474 type_name = "Color";
6475 break;
6476
6477 case PREF_CUSTOM:
6478 if (pref->custom_cbs.type_name_cb)
6479 return pref->custom_cbs.type_name_cb();
6480 type_name = "Custom";
6481 break;
6482
6483 case PREF_DECODE_AS_RANGE:
6484 type_name = "Range (for Decode As)";
6485 break;
6486
6487 case PREF_STATIC_TEXT:
6488 type_name = "Static text";
6489 break;
6490
6491 case PREF_UAT:
6492 type_name = "UAT";
6493 break;
6494
6495 case PREF_PASSWORD:
6496 type_name = "Password";
6497 break;
6498
6499 case PREF_DISSECTOR:
6500 type_name = "Dissector";
6501 break;
6502 }
6503 }
6504
6505 return type_name;
6506}
6507
6508unsigned int
6509prefs_get_effect_flags(pref_t *pref)
6510{
6511 if (pref == NULL((void*)0))
6512 return 0;
6513
6514 return pref->effect_flags;
6515}
6516
6517void
6518prefs_set_effect_flags(pref_t *pref, unsigned int flags)
6519{
6520 if (pref != NULL((void*)0)) {
6521 if (flags == 0) {
6522 ws_error("Setting \"%s\" preference effect flags to 0", pref->name)ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 6522
, __func__, "Setting \"%s\" preference effect flags to 0", pref
->name)
;
6523 }
6524 pref->effect_flags = flags;
6525 }
6526}
6527
6528void
6529prefs_set_effect_flags_by_name(module_t * module, const char *pref, unsigned int flags)
6530{
6531 prefs_set_effect_flags(prefs_find_preference(module, pref), flags);
6532}
6533
6534unsigned int
6535prefs_get_module_effect_flags(module_t * module)
6536{
6537 if (module == NULL((void*)0))
6538 return 0;
6539
6540 return module->effect_flags;
6541}
6542
6543void
6544prefs_set_module_effect_flags(module_t * module, unsigned int flags)
6545{
6546 if (module != NULL((void*)0)) {
6547 if (flags == 0) {
6548 ws_error("Setting module \"%s\" preference effect flags to 0", module->name)ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 6548
, __func__, "Setting module \"%s\" preference effect flags to 0"
, module->name)
;
6549 }
6550 module->effect_flags = flags;
6551 }
6552}
6553
6554char *
6555prefs_pref_type_description(pref_t *pref)
6556{
6557 const char *type_desc = "An unknown preference type";
6558
6559 if (!pref) {
6560 return ws_strdup_printf("%s.", type_desc)wmem_strdup_printf(((void*)0), "%s.", type_desc); /* ...or maybe assert? */
6561 }
6562
6563 if (pref->obsolete) {
6564 type_desc = "An obsolete preference";
6565 } else {
6566 switch (pref->type) {
6567
6568 case PREF_UINT:
6569 switch (pref->info.base) {
6570
6571 case 10:
6572 type_desc = "A decimal number";
6573 break;
6574
6575 case 8:
6576 type_desc = "An octal number";
6577 break;
6578
6579 case 16:
6580 type_desc = "A hexadecimal number";
6581 break;
6582 }
6583 break;
6584
6585 case PREF_BOOL:
6586 type_desc = "true or false (case-insensitive)";
6587 break;
6588
6589 case PREF_ENUM:
6590 case PREF_PROTO_TCP_SNDAMB_ENUM:
6591 {
6592 const enum_val_t *enum_valp = pref->info.enum_info.enumvals;
6593 GString *enum_str = g_string_new("One of: ");
6594 GString *desc_str = g_string_new("\nEquivalently, one of: ");
6595 bool_Bool distinct = false0;
6596 while (enum_valp->name != NULL((void*)0)) {
6597 g_string_append(enum_str, enum_valp->name)(__builtin_constant_p (enum_valp->name) ? __extension__ ({
const char * const __val = (enum_valp->name); g_string_append_len_inline
(enum_str, __val, (__val != ((void*)0)) ? (gssize) strlen ((
(__val) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(enum_str, enum_valp->name, (gssize) -1))
;
6598 g_string_append(desc_str, enum_valp->description)(__builtin_constant_p (enum_valp->description) ? __extension__
({ const char * const __val = (enum_valp->description); g_string_append_len_inline
(desc_str, __val, (__val != ((void*)0)) ? (gssize) strlen ((
(__val) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(desc_str, enum_valp->description, (gssize) -1))
;
6599 if (g_strcmp0(enum_valp->name, enum_valp->description) != 0) {
6600 distinct = true1;
6601 }
6602 enum_valp++;
6603 if (enum_valp->name != NULL((void*)0)) {
6604 g_string_append(enum_str, ", ")(__builtin_constant_p (", ") ? __extension__ ({ const char * const
__val = (", "); g_string_append_len_inline (enum_str, __val,
(__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val)
)) : (gssize) -1); }) : g_string_append_len_inline (enum_str,
", ", (gssize) -1))
;
6605 g_string_append(desc_str, ", ")(__builtin_constant_p (", ") ? __extension__ ({ const char * const
__val = (", "); g_string_append_len_inline (desc_str, __val,
(__val != ((void*)0)) ? (gssize) strlen (((__val) + !(__val)
)) : (gssize) -1); }) : g_string_append_len_inline (desc_str,
", ", (gssize) -1))
;
6606 }
6607 }
6608 if (distinct) {
6609 g_string_append(enum_str, desc_str->str)(__builtin_constant_p (desc_str->str) ? __extension__ ({ const
char * const __val = (desc_str->str); g_string_append_len_inline
(enum_str, __val, (__val != ((void*)0)) ? (gssize) strlen ((
(__val) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(enum_str, desc_str->str, (gssize) -1))
;
6610 }
6611 g_string_free(desc_str, TRUE)(__builtin_constant_p ((!(0))) ? (((!(0))) ? (g_string_free) (
(desc_str), ((!(0)))) : g_string_free_and_steal (desc_str)) :
(g_string_free) ((desc_str), ((!(0)))))
;
6612 g_string_append(enum_str, "\n(case-insensitive).")(__builtin_constant_p ("\n(case-insensitive).") ? __extension__
({ const char * const __val = ("\n(case-insensitive)."); g_string_append_len_inline
(enum_str, __val, (__val != ((void*)0)) ? (gssize) strlen ((
(__val) + !(__val))) : (gssize) -1); }) : g_string_append_len_inline
(enum_str, "\n(case-insensitive).", (gssize) -1))
;
6613 return g_string_free(enum_str, FALSE)(__builtin_constant_p ((0)) ? (((0)) ? (g_string_free) ((enum_str
), ((0))) : g_string_free_and_steal (enum_str)) : (g_string_free
) ((enum_str), ((0))))
;
6614 }
6615
6616 case PREF_STRING:
6617 type_desc = "A string";
6618 break;
6619
6620 case PREF_SAVE_FILENAME:
6621 case PREF_OPEN_FILENAME:
6622 type_desc = "A path to a file";
6623 break;
6624
6625 case PREF_DIRNAME:
6626 type_desc = "A path to a directory";
6627 break;
6628
6629 case PREF_RANGE:
6630 {
6631 type_desc = "A string denoting an positive integer range (e.g., \"1-20,30-40\")";
6632 break;
6633 }
6634
6635 case PREF_COLOR:
6636 {
6637 type_desc = "A six-digit hexadecimal RGB color triplet (e.g. fce94f)";
6638 break;
6639 }
6640
6641 case PREF_CUSTOM:
6642 if (pref->custom_cbs.type_description_cb)
6643 return pref->custom_cbs.type_description_cb();
6644 type_desc = "A custom value";
6645 break;
6646
6647 case PREF_DECODE_AS_RANGE:
6648 type_desc = "A string denoting an positive integer range for Decode As";
6649 break;
6650
6651 case PREF_STATIC_TEXT:
6652 type_desc = "[Static text]";
6653 break;
6654
6655 case PREF_UAT:
6656 type_desc = "Configuration data stored in its own file";
6657 break;
6658
6659 case PREF_PASSWORD:
6660 type_desc = "Password (never stored on disk)";
6661 break;
6662
6663 case PREF_DISSECTOR:
6664 type_desc = "A dissector name";
6665 break;
6666
6667 default:
6668 break;
6669 }
6670 }
6671
6672 return g_strdup(type_desc)g_strdup_inline (type_desc);
6673}
6674
6675bool_Bool
6676prefs_pref_is_default(pref_t *pref)
6677{
6678 if (!pref) return false0;
6679
6680 if (pref->obsolete) {
6681 return false0;
6682 }
6683
6684 switch (pref->type) {
6685
6686 case PREF_UINT:
6687 if (pref->default_val.uint == *pref->varp.uint)
6688 return true1;
6689 break;
6690
6691 case PREF_BOOL:
6692 if (pref->default_val.boolval == *pref->varp.boolp)
6693 return true1;
6694 break;
6695
6696 case PREF_ENUM:
6697 case PREF_PROTO_TCP_SNDAMB_ENUM:
6698 if (pref->default_val.enumval == *pref->varp.enump)
6699 return true1;
6700 break;
6701
6702 case PREF_STRING:
6703 case PREF_SAVE_FILENAME:
6704 case PREF_OPEN_FILENAME:
6705 case PREF_DIRNAME:
6706 case PREF_PASSWORD:
6707 case PREF_DISSECTOR:
6708 if (!(g_strcmp0(pref->default_val.string, *pref->varp.string)))
6709 return true1;
6710 break;
6711
6712 case PREF_DECODE_AS_RANGE:
6713 case PREF_RANGE:
6714 {
6715 if ((ranges_are_equal(pref->default_val.range, *pref->varp.range)))
6716 return true1;
6717 break;
6718 }
6719
6720 case PREF_COLOR:
6721 {
6722 if ((pref->default_val.color.red == pref->varp.colorp->red) &&
6723 (pref->default_val.color.green == pref->varp.colorp->green) &&
6724 (pref->default_val.color.blue == pref->varp.colorp->blue))
6725 return true1;
6726 break;
6727 }
6728
6729 case PREF_CUSTOM:
6730 return pref->custom_cbs.is_default_cb(pref);
6731
6732 case PREF_STATIC_TEXT:
6733 case PREF_UAT:
6734 return false0;
6735 /* ws_assert_not_reached(); */
6736 break;
6737 }
6738
6739 return false0;
6740}
6741
6742char *
6743prefs_pref_to_str(pref_t *pref, pref_source_t source)
6744{
6745 const char *pref_text = "[Unknown]";
6746 void *valp; /* pointer to preference value */
6747 color_t *pref_color;
6748 char *tmp_value, *ret_value;
6749
6750 if (!pref) {
6751 return g_strdup(pref_text)g_strdup_inline (pref_text);
6752 }
6753
6754 switch (source) {
6755 case pref_default:
6756 valp = &pref->default_val;
6757 /* valp = &boolval, &enumval, etc. are implied by union property */
6758 pref_color = &pref->default_val.color;
6759 break;
6760 case pref_stashed:
6761 valp = &pref->stashed_val;
6762 /* valp = &boolval, &enumval, etc. are implied by union property */
6763 pref_color = &pref->stashed_val.color;
6764 break;
6765 case pref_current:
6766 valp = pref->varp.uint;
6767 /* valp = boolval, enumval, etc. are implied by union property */
6768 pref_color = pref->varp.colorp;
6769 break;
6770 default:
6771 return g_strdup(pref_text)g_strdup_inline (pref_text);
6772 }
6773
6774 if (pref->obsolete) {
6775 pref_text = "[Obsolete]";
6776 } else {
6777 switch (pref->type) {
6778
6779 case PREF_UINT:
6780 {
6781 unsigned pref_uint = *(unsigned *) valp;
6782 switch (pref->info.base) {
6783
6784 case 10:
6785 return ws_strdup_printf("%u", pref_uint)wmem_strdup_printf(((void*)0), "%u", pref_uint);
6786
6787 case 8:
6788 return ws_strdup_printf("%#o", pref_uint)wmem_strdup_printf(((void*)0), "%#o", pref_uint);
6789
6790 case 16:
6791 return ws_strdup_printf("%#x", pref_uint)wmem_strdup_printf(((void*)0), "%#x", pref_uint);
6792 }
6793 break;
6794 }
6795
6796 case PREF_BOOL:
6797 return g_strdup((*(bool *) valp) ? "TRUE" : "FALSE")g_strdup_inline ((*(_Bool *) valp) ? "TRUE" : "FALSE");
6798
6799 case PREF_ENUM:
6800 case PREF_PROTO_TCP_SNDAMB_ENUM:
6801 {
6802 int pref_enumval = *(int *) valp;
6803 const enum_val_t *enum_valp = pref->info.enum_info.enumvals;
6804 /*
6805 * TODO - We write the "description" value, because the "name" values
6806 * weren't validated to be command line friendly until 5.0, and a few
6807 * of them had to be changed. This allows older versions of Wireshark
6808 * to read preferences that they supported, as we supported either
6809 * the short name or the description when reading the preference files
6810 * or an "-o" option. Once 5.0 is the oldest supported version, switch
6811 * to writing the name below.
6812 */
6813 while (enum_valp->name != NULL((void*)0)) {
6814 if (enum_valp->value == pref_enumval)
6815 return g_strdup(enum_valp->description)g_strdup_inline (enum_valp->description);
6816 enum_valp++;
6817 }
6818 break;
6819 }
6820
6821 case PREF_STRING:
6822 case PREF_SAVE_FILENAME:
6823 case PREF_OPEN_FILENAME:
6824 case PREF_DIRNAME:
6825 case PREF_PASSWORD:
6826 case PREF_DISSECTOR:
6827 return g_strdup(*(const char **) valp)g_strdup_inline (*(const char **) valp);
6828
6829 case PREF_DECODE_AS_RANGE:
6830 case PREF_RANGE:
6831 /* Convert wmem to g_alloc memory */
6832 tmp_value = range_convert_range(NULL((void*)0), *(range_t **) valp);
6833 ret_value = g_strdup(tmp_value)g_strdup_inline (tmp_value);
6834 wmem_free(NULL((void*)0), tmp_value);
6835 return ret_value;
6836
6837 case PREF_COLOR:
6838 return ws_strdup_printf("%02x%02x%02x",wmem_strdup_printf(((void*)0), "%02x%02x%02x", (pref_color->
red * 255 / 65535), (pref_color->green * 255 / 65535), (pref_color
->blue * 255 / 65535))
6839 (pref_color->red * 255 / 65535),wmem_strdup_printf(((void*)0), "%02x%02x%02x", (pref_color->
red * 255 / 65535), (pref_color->green * 255 / 65535), (pref_color
->blue * 255 / 65535))
6840 (pref_color->green * 255 / 65535),wmem_strdup_printf(((void*)0), "%02x%02x%02x", (pref_color->
red * 255 / 65535), (pref_color->green * 255 / 65535), (pref_color
->blue * 255 / 65535))
6841 (pref_color->blue * 255 / 65535))wmem_strdup_printf(((void*)0), "%02x%02x%02x", (pref_color->
red * 255 / 65535), (pref_color->green * 255 / 65535), (pref_color
->blue * 255 / 65535))
;
6842
6843 case PREF_CUSTOM:
6844 if (pref->custom_cbs.to_str_cb)
6845 return pref->custom_cbs.to_str_cb(pref, source == pref_default ? true1 : false0);
6846 pref_text = "[Custom]";
6847 break;
6848
6849 case PREF_STATIC_TEXT:
6850 pref_text = "[Static text]";
6851 break;
6852
6853 case PREF_UAT:
6854 {
6855 uat_t *uat = pref->varp.uat;
6856 if (uat && uat->filename)
6857 return ws_strdup_printf("[Managed in the file \"%s\"]", uat->filename)wmem_strdup_printf(((void*)0), "[Managed in the file \"%s\"]"
, uat->filename)
;
6858 else
6859 pref_text = "[Managed in an unknown file]";
6860 break;
6861 }
6862
6863 default:
6864 break;
6865 }
6866 }
6867
6868 return g_strdup(pref_text)g_strdup_inline (pref_text);
6869}
6870
6871/*
6872 * Write out a single dissector preference.
6873 */
6874static void
6875write_pref(void *data, void *user_data)
6876{
6877 pref_t *pref = (pref_t *)data;
6878 write_pref_arg_t *arg = (write_pref_arg_t *)user_data;
6879 char **desc_lines;
6880 int i;
6881
6882 if (!pref || pref->obsolete) {
6883 /*
6884 * This preference is no longer supported; it's not a
6885 * real preference, so we don't write it out (i.e., we
6886 * treat it as if it weren't found in the list of
6887 * preferences, and we weren't called in the first place).
6888 */
6889 return;
6890 }
6891
6892 switch (pref->type) {
6893
6894 case PREF_STATIC_TEXT:
6895 case PREF_UAT:
6896 /* Nothing to do; don't bother printing the description */
6897 return;
6898 case PREF_DECODE_AS_RANGE:
6899 /* Data is saved through Decode As mechanism and not part of preferences file */
6900 return;
6901 case PREF_PROTO_TCP_SNDAMB_ENUM:
6902 /* Not written to the preference file because the override is only
6903 * for the lifetime of the capture file and there is no single
6904 * value to write.
6905 */
6906 return;
6907 default:
6908 break;
6909 }
6910
6911 if (pref->type != PREF_CUSTOM || pref->custom_cbs.type_name_cb() != NULL((void*)0)) {
6912 /*
6913 * The prefix will either be the module name or the parent
6914 * name if it's a subtree
6915 */
6916 const char *name_prefix = (arg->module->name != NULL((void*)0)) ? arg->module->name : arg->module->parent->name;
6917 char *type_desc, *pref_text;
6918 const char * def_prefix = prefs_pref_is_default(pref) ? "#" : "";
6919
6920 if (pref->type == PREF_CUSTOM)
6921 fprintf(arg->pf, "\n# %s", pref->custom_cbs.type_name_cb());
6922 fprintf(arg->pf, "\n");
6923 if (pref->description &&
6924 (g_ascii_strncasecmp(pref->description,"", 2) != 0)) {
6925 if (pref->type != PREF_CUSTOM) {
6926 /* We get duplicate lines otherwise. */
6927
6928 desc_lines = g_strsplit(pref->description, "\n", 0);
6929 for (i = 0; desc_lines[i] != NULL((void*)0); ++i) {
6930 fprintf(arg->pf, "# %s\n", desc_lines[i]);
6931 }
6932 g_strfreev(desc_lines);
6933 }
6934 } else {
6935 fprintf(arg->pf, "# No description\n");
6936 }
6937
6938 type_desc = prefs_pref_type_description(pref);
6939 desc_lines = g_strsplit(type_desc, "\n", 0);
6940 for (i = 0; desc_lines[i] != NULL((void*)0); ++i) {
6941 fprintf(arg->pf, "# %s\n", desc_lines[i]);
6942 }
6943 g_strfreev(desc_lines);
6944 g_free(type_desc);
6945
6946 pref_text = prefs_pref_to_str(pref, pref_current);
6947 fprintf(arg->pf, "%s%s.%s: ", def_prefix, name_prefix, pref->name);
6948 if (pref->type != PREF_PASSWORD)
6949 {
6950 desc_lines = g_strsplit(pref_text, "\n", 0);
6951 for (i = 0; desc_lines[i] != NULL((void*)0); ++i) {
6952 fprintf(arg->pf, "%s%s\n", i == 0 ? "" : def_prefix, desc_lines[i]);
6953 }
6954 if (i == 0)
6955 fprintf(arg->pf, "\n");
6956 g_strfreev(desc_lines);
6957 } else {
6958 /* We never store password value */
6959 fprintf(arg->pf, "\n");
6960 }
6961 g_free(pref_text);
6962 }
6963
6964}
6965
6966static void
6967count_non_uat_pref(void *data, void *user_data)
6968{
6969 pref_t *pref = (pref_t *)data;
6970 int *arg = (int *)user_data;
6971
6972 switch (pref->type)
6973 {
6974 case PREF_UAT:
6975 case PREF_DECODE_AS_RANGE:
6976 case PREF_PROTO_TCP_SNDAMB_ENUM:
6977 //These types are not written in preference file
6978 break;
6979 default:
6980 (*arg)++;
6981 break;
6982 }
6983}
6984
6985static int num_non_uat_prefs(module_t *module)
6986{
6987 int num = 0;
6988
6989 g_list_foreach(module->prefs, count_non_uat_pref, &num);
6990
6991 return num;
6992}
6993
6994/*
6995 * Write out all preferences for a module.
6996 */
6997static unsigned
6998write_module_prefs(module_t *module, void *user_data)
6999{
7000 write_gui_pref_arg_t *gui_pref_arg = (write_gui_pref_arg_t*)user_data;
7001 write_pref_arg_t arg;
7002
7003 /* The GUI module needs to be explicitly called out so it
7004 can be written out of order */
7005 if ((module == gui_module) && (gui_pref_arg->is_gui_module != true1))
7006 return 0;
7007
7008 /* Write a header for the main modules and GUI sub-modules */
7009 if (((module->parent == NULL((void*)0)) || (module->parent == gui_module)) &&
7010 ((prefs_module_has_submodules(module)) ||
7011 (num_non_uat_prefs(module) > 0) ||
7012 (module->name == NULL((void*)0)))) {
7013 if ((module->name == NULL((void*)0)) && (module->parent != NULL((void*)0))) {
7014 fprintf(gui_pref_arg->pf, "\n####### %s: %s ########\n", module->parent->title, module->title);
7015 } else {
7016 fprintf(gui_pref_arg->pf, "\n####### %s ########\n", module->title);
7017 }
7018 }
7019
7020 arg.module = module;
7021 arg.pf = gui_pref_arg->pf;
7022 g_list_foreach(arg.module->prefs, write_pref, &arg);
7023
7024 if (prefs_module_has_submodules(module))
7025 return prefs_modules_foreach_submodules(module, write_module_prefs, user_data);
7026
7027 return 0;
7028}
7029
7030#ifdef _WIN32
7031static void
7032write_registry(void)
7033{
7034 HKEY hTestKey;
7035 DWORD data;
7036 DWORD data_size;
7037 DWORD ret;
7038
7039 ret = RegCreateKeyExA(HKEY_CURRENT_USER, REG_HKCU_WIRESHARK_KEY"Software\\Wireshark", 0, NULL((void*)0),
7040 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL((void*)0),
7041 &hTestKey, NULL((void*)0));
7042 if (ret != ERROR_SUCCESS) {
7043 ws_noisy("Cannot open HKCU "REG_HKCU_WIRESHARK_KEY": 0x%lx", ret)do { if (1) { ws_log_full("Epan", LOG_LEVEL_NOISY, "epan/prefs.c"
, 7043, __func__, "Cannot open HKCU ""Software\\Wireshark"": 0x%lx"
, ret); } } while (0)
;
7044 return;
7045 }
7046
7047 data = ws_log_console_open;
7048 data_size = sizeof(DWORD);
7049 ret = RegSetValueExA(hTestKey, LOG_HKCU_CONSOLE_OPEN"ConsoleOpen", 0, REG_DWORD, (const BYTE *)&data, data_size);
7050 if (ret == ERROR_SUCCESS) {
7051 ws_noisy("Wrote "LOG_HKCU_CONSOLE_OPEN" to Windows registry: 0x%lu", data)do { if (1) { ws_log_full("Epan", LOG_LEVEL_NOISY, "epan/prefs.c"
, 7051, __func__, "Wrote ""ConsoleOpen"" to Windows registry: 0x%lu"
, data); } } while (0)
;
7052 }
7053 else {
7054 ws_noisy("Error writing registry key "LOG_HKCU_CONSOLE_OPEN": 0x%lx", ret)do { if (1) { ws_log_full("Epan", LOG_LEVEL_NOISY, "epan/prefs.c"
, 7054, __func__, "Error writing registry key ""ConsoleOpen"": 0x%lx"
, ret); } } while (0)
;
7055 }
7056
7057 RegCloseKey(hTestKey);
7058}
7059#endif
7060
7061/* Write out "prefs" to the user's preferences file, and return 0.
7062
7063 If the preferences file path is NULL, write to stdout.
7064
7065 If we got an error, stuff a pointer to the path of the preferences file
7066 into "*pf_path_return", and return the errno. */
7067int
7068write_prefs(const char* app_env_var_prefix, char **pf_path_return)
7069{
7070 char *pf_path;
7071 FILE *pf;
7072 write_gui_pref_arg_t write_gui_pref_info;
7073
7074#ifdef _WIN32
7075 write_registry();
7076#endif
7077
7078 /* To do:
7079 * - Split output lines longer than MAX_VAL_LEN
7080 * - Create a function for the preference directory check/creation
7081 * so that duplication can be avoided with filter.c
7082 */
7083
7084 if (pf_path_return != NULL((void*)0)) {
7085 pf_path = get_persconffile_path(PF_NAME"preferences", true1, app_env_var_prefix);
7086 if ((pf = ws_fopenfopen(pf_path, "w")) == NULL((void*)0)) {
7087 *pf_path_return = pf_path;
7088 return errno(*__errno_location ());
7089 }
7090 g_free(pf_path);
7091 } else {
7092 pf = stdoutstdout;
7093 }
7094
7095 /*
7096 * If the preferences file is being written, be sure to write UAT files
7097 * first that were migrated from the preferences file.
7098 */
7099 if (pf_path_return != NULL((void*)0)) {
7100 if (prefs.filter_expressions_old) {
7101 char *err = NULL((void*)0);
7102 prefs.filter_expressions_old = false0;
7103 if (!uat_save(uat_get_table_by_name("Display expressions"), app_env_var_prefix, &err)) {
7104 ws_warning("Unable to save Display expressions: %s", err)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 7104, __func__, "Unable to save Display expressions: %s", err
); } } while (0)
;
7105 g_free(err);
7106 }
7107 }
7108
7109 module_t *extcap_module = prefs_find_module("extcap");
7110 if (extcap_module && !prefs.capture_no_extcap) {
7111 char *ext_path = get_persconffile_path("extcap.cfg", true1, app_env_var_prefix);
7112 FILE *extf;
7113 if ((extf = ws_fopenfopen(ext_path, "w")) == NULL((void*)0)) {
7114 if (errno(*__errno_location ()) != EISDIR21) {
7115 ws_warning("Unable to save extcap preferences \"%s\": %s",do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 7116, __func__, "Unable to save extcap preferences \"%s\": %s"
, ext_path, g_strerror((*__errno_location ()))); } } while (0
)
7116 ext_path, g_strerror(errno))do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 7116, __func__, "Unable to save extcap preferences \"%s\": %s"
, ext_path, g_strerror((*__errno_location ()))); } } while (0
)
;
7117 }
7118 g_free(ext_path);
7119 } else {
7120 g_free(ext_path);
7121
7122 fputs("# Extcap configuration file for Wireshark " VERSION"4.7.0" ".\n"
7123 "#\n"
7124 "# This file is regenerated each time preferences are saved within\n"
7125 "# Wireshark. Making manual changes should be safe, however.\n"
7126 "# Preferences that have been commented out have not been\n"
7127 "# changed from their default value.\n", extf);
7128
7129 write_gui_pref_info.pf = extf;
7130 write_gui_pref_info.is_gui_module = false0;
7131
7132 write_module_prefs(extcap_module, &write_gui_pref_info);
7133
7134 fclose(extf);
7135 }
7136 }
7137 }
7138
7139 fputs("# Configuration file for Wireshark " VERSION"4.7.0" ".\n"
7140 "#\n"
7141 "# This file is regenerated each time preferences are saved within\n"
7142 "# Wireshark. Making manual changes should be safe, however.\n"
7143 "# Preferences that have been commented out have not been\n"
7144 "# changed from their default value.\n", pf);
7145
7146 /*
7147 * For "backwards compatibility" the GUI module is written first as it's
7148 * at the top of the file. This is followed by all modules that can't
7149 * fit into the preferences read/write API. Finally the remaining modules
7150 * are written in alphabetical order (including of course the protocol preferences)
7151 */
7152 write_gui_pref_info.pf = pf;
7153 write_gui_pref_info.is_gui_module = true1;
7154
7155 write_module_prefs(gui_module, &write_gui_pref_info);
7156
7157 write_gui_pref_info.is_gui_module = false0;
7158 prefs_modules_foreach_submodules(NULL((void*)0), write_module_prefs, &write_gui_pref_info);
7159
7160 fclose(pf);
7161
7162 /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
7163 an error indication, or maybe write to a new preferences file and
7164 rename that file on top of the old one only if there are not I/O
7165 errors. */
7166 return 0;
7167}
7168
7169/** The col_list is only partly managed by the custom preference API
7170 * because its data is shared between multiple preferences, so
7171 * it's freed here
7172 */
7173static void
7174free_col_info(GList *list)
7175{
7176 fmt_data *cfmt;
7177 GList *list_head = list;
7178
7179 while (list != NULL((void*)0)) {
7180 cfmt = (fmt_data *)list->data;
7181
7182 g_free(cfmt->title);
7183 g_free(cfmt->custom_fields);
7184 g_free(cfmt);
7185 list = g_list_next(list)((list) ? (((GList *)(list))->next) : ((void*)0));
7186 }
7187 g_list_free(list_head);
7188}
7189
7190/*
7191 * Editor modelines
7192 *
7193 * Local Variables:
7194 * c-basic-offset: 4
7195 * tab-width: 8
7196 * indent-tabs-mode: nil
7197 * End:
7198 *
7199 * ex: set shiftwidth=4 tabstop=8 expandtab:
7200 * :indentSize=4:tabSize=8:noTabs=true:
7201 */