Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

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