Bug Summary

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