Bug Summary

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