Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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