Bug Summary

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