Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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