Bug Summary

File:epan/prefs.c
Warning:line 4808, 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-30-100332-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 "Dir", "%Cus:evt.dir:0:R",
4234 "Proc Name", "%Cus:proc.name:0:R",
4235 "PID", "%Cus:proc.pid:0:R",
4236 "TID", "%Cus:thread.tid:0:R",
4237 "FD", "%Cus:fd.num:0:R",
4238 "FD Name", "%Cus:fd.name:0:R",
4239 "Container Name", "%Cus:container.name:0:R",
4240 "Arguments", "%Cus:evt.args:0:R",
4241 "Info", "%i"
4242 };
4243 col_fmt = col_fmt_logs;
4244 num_cols = 12;
4245 }
4246
4247 prefs.restore_filter_after_following_stream = false0;
4248 prefs.gui_toolbar_main_style = TB_STYLE_ICONS0;
4249 /* We try to find the best font in the Qt code */
4250 g_free(prefs.gui_font_name);
4251 prefs.gui_font_name = g_strdup("")g_strdup_inline ("");
4252 prefs.gui_active_fg.red = 0;
4253 prefs.gui_active_fg.green = 0;
4254 prefs.gui_active_fg.blue = 0;
4255 prefs.gui_active_bg.red = 52223;
4256 prefs.gui_active_bg.green = 59647;
4257 prefs.gui_active_bg.blue = 65535;
4258 prefs.gui_active_style = COLOR_STYLE_DEFAULT0;
4259 prefs.gui_inactive_fg.red = 0;
4260 prefs.gui_inactive_fg.green = 0;
4261 prefs.gui_inactive_fg.blue = 0;
4262 prefs.gui_inactive_bg.red = 61439;
4263 prefs.gui_inactive_bg.green = 61439;
4264 prefs.gui_inactive_bg.blue = 61439;
4265 prefs.gui_inactive_style = COLOR_STYLE_DEFAULT0;
4266 prefs.gui_marked_fg.red = 65535;
4267 prefs.gui_marked_fg.green = 65535;
4268 prefs.gui_marked_fg.blue = 65535;
4269 prefs.gui_marked_bg.red = 0;
4270 prefs.gui_marked_bg.green = 8224;
4271 prefs.gui_marked_bg.blue = 10794;
4272 prefs.gui_ignored_fg.red = 32767;
4273 prefs.gui_ignored_fg.green = 32767;
4274 prefs.gui_ignored_fg.blue = 32767;
4275 prefs.gui_ignored_bg.red = 65535;
4276 prefs.gui_ignored_bg.green = 65535;
4277 prefs.gui_ignored_bg.blue = 65535;
4278 g_free(prefs.gui_colorized_fg);
4279 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"
)
;
4280 g_free(prefs.gui_colorized_bg);
4281 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"
)
;
4282 prefs.st_client_fg.red = 32767;
4283 prefs.st_client_fg.green = 0;
4284 prefs.st_client_fg.blue = 0;
4285 prefs.st_client_bg.red = 64507;
4286 prefs.st_client_bg.green = 60909;
4287 prefs.st_client_bg.blue = 60909;
4288 prefs.st_server_fg.red = 0;
4289 prefs.st_server_fg.green = 0;
4290 prefs.st_server_fg.blue = 32767;
4291 prefs.st_server_bg.red = 60909;
4292 prefs.st_server_bg.green = 60909;
4293 prefs.st_server_bg.blue = 64507;
4294
4295 if (gui_theme_is_dark) {
4296 // Green, red and yellow with HSV V = 84
4297 prefs.gui_filter_valid_bg.red = 0x0000; /* dark green */
4298 prefs.gui_filter_valid_bg.green = 0x66ff;
4299 prefs.gui_filter_valid_bg.blue = 0x0000;
4300 prefs.gui_filter_valid_fg.red = 0xFFFF;
4301 prefs.gui_filter_valid_fg.green = 0xFFFF;
4302 prefs.gui_filter_valid_fg.blue = 0xFFFF;
4303 prefs.gui_filter_invalid_bg.red = 0x66FF; /* dark red */
4304 prefs.gui_filter_invalid_bg.green = 0x0000;
4305 prefs.gui_filter_invalid_bg.blue = 0x0000;
4306 prefs.gui_filter_invalid_fg.red = 0xFFFF;
4307 prefs.gui_filter_invalid_fg.green = 0xFFFF;
4308 prefs.gui_filter_invalid_fg.blue = 0xFFFF;
4309 prefs.gui_filter_deprecated_bg.red = 0x66FF; /* dark yellow / olive */
4310 prefs.gui_filter_deprecated_bg.green = 0x66FF;
4311 prefs.gui_filter_deprecated_bg.blue = 0x0000;
4312 prefs.gui_filter_deprecated_fg.red = 0xFFFF;
4313 prefs.gui_filter_deprecated_fg.green = 0xFFFF;
4314 prefs.gui_filter_deprecated_fg.blue = 0xFFFF;
4315 } else {
4316 // Green, red and yellow with HSV V = 20
4317 prefs.gui_filter_valid_bg.red = 0xAFFF; /* light green */
4318 prefs.gui_filter_valid_bg.green = 0xFFFF;
4319 prefs.gui_filter_valid_bg.blue = 0xAFFF;
4320 prefs.gui_filter_valid_fg.red = 0x0000;
4321 prefs.gui_filter_valid_fg.green = 0x0000;
4322 prefs.gui_filter_valid_fg.blue = 0x0000;
4323 prefs.gui_filter_invalid_bg.red = 0xFFFF; /* light red */
4324 prefs.gui_filter_invalid_bg.green = 0xAFFF;
4325 prefs.gui_filter_invalid_bg.blue = 0xAFFF;
4326 prefs.gui_filter_invalid_fg.red = 0x0000;
4327 prefs.gui_filter_invalid_fg.green = 0x0000;
4328 prefs.gui_filter_invalid_fg.blue = 0x0000;
4329 prefs.gui_filter_deprecated_bg.red = 0xFFFF; /* light yellow */
4330 prefs.gui_filter_deprecated_bg.green = 0xFFFF;
4331 prefs.gui_filter_deprecated_bg.blue = 0xAFFF;
4332 prefs.gui_filter_deprecated_fg.red = 0x0000;
4333 prefs.gui_filter_deprecated_fg.green = 0x0000;
4334 prefs.gui_filter_deprecated_fg.blue = 0x0000;
4335 }
4336
4337 prefs.gui_geometry_save_position = true1;
4338 prefs.gui_geometry_save_size = true1;
4339 prefs.gui_geometry_save_maximized= true1;
4340 prefs.gui_fileopen_style = FO_STYLE_LAST_OPENED0;
4341 prefs.gui_recent_df_entries_max = 10;
4342 prefs.gui_recent_files_count_max = 10;
4343 g_free(prefs.gui_fileopen_dir);
4344 prefs.gui_fileopen_dir = g_strdup(get_persdatafile_dir())g_strdup_inline (get_persdatafile_dir());
4345 prefs.gui_fileopen_preview = 3;
4346 g_free(prefs.gui_tlskeylog_command);
4347 prefs.gui_tlskeylog_command = g_strdup("")g_strdup_inline ("");
4348 prefs.gui_ask_unsaved = true1;
4349 prefs.gui_autocomplete_filter = true1;
4350 prefs.gui_find_wrap = true1;
4351 prefs.gui_update_enabled = true1;
4352 prefs.gui_update_channel = UPDATE_CHANNEL_STABLE;
4353 prefs.gui_update_interval = 60*60*24; /* Seconds */
4354 prefs.gui_debounce_timer = 400; /* milliseconds */
4355 g_free(prefs.gui_window_title);
4356 prefs.gui_window_title = g_strdup("")g_strdup_inline ("");
4357 g_free(prefs.gui_prepend_window_title);
4358 prefs.gui_prepend_window_title = g_strdup("")g_strdup_inline ("");
4359 g_free(prefs.gui_start_title);
4360 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"
)
;
4361 prefs.gui_version_placement = version_both;
4362 prefs.gui_welcome_page_show_recent = true1;
4363 prefs.gui_layout_type = layout_type_2;
4364 prefs.gui_layout_content_1 = layout_pane_content_plist;
4365 prefs.gui_layout_content_2 = layout_pane_content_pdetails;
4366 prefs.gui_layout_content_3 = layout_pane_content_pbytes;
4367 prefs.gui_packet_list_elide_mode = ELIDE_RIGHT;
4368 prefs.gui_packet_list_copy_format_options_for_keyboard_shortcut = COPY_FORMAT_TEXT;
4369 prefs.gui_packet_list_copy_text_with_aligned_columns = false0;
4370 prefs.gui_packet_list_show_related = true1;
4371 prefs.gui_packet_list_show_minimap = true1;
4372 prefs.gui_packet_list_sortable = true1;
4373 prefs.gui_packet_list_cached_rows_max = 10000;
4374 g_free (prefs.gui_interfaces_hide_types);
4375 prefs.gui_interfaces_hide_types = g_strdup("")g_strdup_inline ("");
4376 prefs.gui_interfaces_show_hidden = false0;
4377 prefs.gui_interfaces_remote_display = true1;
4378 prefs.gui_packet_list_separator = false0;
4379 prefs.gui_packet_header_column_definition = true1;
4380 prefs.gui_packet_list_hover_style = true1;
4381 prefs.gui_show_selected_packet = false0;
4382 prefs.gui_show_file_load_time = false0;
4383 prefs.gui_max_export_objects = 1000;
4384 prefs.gui_max_tree_items = 1 * 1000 * 1000;
4385 prefs.gui_max_tree_depth = 5 * 100;
4386 prefs.gui_decimal_places1 = DEF_GUI_DECIMAL_PLACES12;
4387 prefs.gui_decimal_places2 = DEF_GUI_DECIMAL_PLACES24;
4388 prefs.gui_decimal_places3 = DEF_GUI_DECIMAL_PLACES36;
4389
4390 if (prefs.col_list) {
4391 free_col_info(prefs.col_list);
4392 prefs.col_list = NULL((void*)0);
4393 }
4394 for (i = 0; i < num_cols; i++) {
4395 cfmt = g_new0(fmt_data,1)((fmt_data *) g_malloc0_n ((1), sizeof (fmt_data)));
4396 cfmt->title = g_strdup(col_fmt[i * 2])g_strdup_inline (col_fmt[i * 2]);
4397 cfmt->visible = true1;
4398 cfmt->display = COLUMN_DISPLAY_STRINGS'R';
4399 parse_column_format(cfmt, col_fmt[(i * 2) + 1]);
4400 prefs.col_list = g_list_append(prefs.col_list, cfmt);
4401 }
4402 prefs.num_cols = num_cols;
4403
4404/* set the default values for the capture dialog box */
4405 prefs.capture_prom_mode = true1;
4406 prefs.capture_monitor_mode = false0;
4407 prefs.capture_pcap_ng = true1;
4408 prefs.capture_real_time = true1;
4409 prefs.capture_update_interval = DEFAULT_UPDATE_INTERVAL100;
4410 prefs.capture_no_extcap = false0;
4411 prefs.capture_show_info = false0;
4412 prefs.enable_aggregation = false0;
4413
4414 if (!prefs.capture_columns) {
4415 /* First time through */
4416 for (i = 0; i < num_capture_cols; i++) {
4417 col_name = g_strdup(capture_cols[i])g_strdup_inline (capture_cols[i]);
4418 prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
4419 }
4420 }
4421
4422/* set the default values for the tap/statistics dialog box */
4423 prefs.tap_update_interval = TAP_UPDATE_DEFAULT_INTERVAL3000;
4424 prefs.flow_graph_max_export_items = 1000;
4425 prefs.st_enable_burstinfo = true1;
4426 prefs.st_burst_showcount = false0;
4427 prefs.st_burst_resolution = ST_DEF_BURSTRES5;
4428 prefs.st_burst_windowlen = ST_DEF_BURSTLEN100;
4429 prefs.st_sort_casesensitve = true1;
4430 prefs.st_sort_rng_fixorder = true1;
4431 prefs.st_sort_rng_nameonly = true1;
4432 prefs.st_sort_defcolflag = ST_SORT_COL_COUNT2;
4433 prefs.st_sort_defdescending = true1;
4434 prefs.st_sort_showfullname = false0;
4435 prefs.conv_machine_readable = false0;
4436
4437 /* protocols */
4438 prefs.display_hidden_proto_items = false0;
4439 prefs.display_byte_fields_with_spaces = false0;
4440 prefs.display_abs_time_ascii = ABS_TIME_ASCII_TREE;
4441 prefs.ignore_dup_frames = false0;
4442 prefs.ignore_dup_frames_cache_entries = 10000;
4443
4444 /* set the default values for the io graph dialog */
4445 prefs.gui_io_graph_automatic_update = true1;
4446 prefs.gui_io_graph_enable_legend = true1;
4447
4448 /* set the default values for the plot dialog */
4449 prefs.gui_plot_automatic_update = true1;
4450 prefs.gui_plot_enable_legend = true1;
4451 prefs.gui_plot_enable_auto_scroll = false0;
4452
4453 /* set the default values for the packet dialog */
4454 prefs.gui_packet_dialog_layout = layout_vertical;
4455 prefs.gui_packet_details_show_byteview = true1;
4456}
4457
4458/*
4459 * Reset a single dissector preference.
4460 */
4461void
4462reset_pref(pref_t *pref)
4463{
4464 if (!pref) return;
4465
4466 /*
4467 * This preference is no longer supported; it's not a
4468 * real preference, so we don't reset it (i.e., we
4469 * treat it as if it weren't found in the list of
4470 * preferences, and we weren't called in the first place).
4471 */
4472 if (pref->obsolete)
4473 return;
4474
4475 switch (pref->type) {
4476
4477 case PREF_UINT:
4478 *pref->varp.uint = pref->default_val.uint;
4479 break;
4480
4481 case PREF_BOOL:
4482 *pref->varp.boolp = pref->default_val.boolval;
4483 break;
4484
4485 case PREF_ENUM:
4486 case PREF_PROTO_TCP_SNDAMB_ENUM:
4487 *pref->varp.enump = pref->default_val.enumval;
4488 break;
4489
4490 case PREF_STRING:
4491 case PREF_SAVE_FILENAME:
4492 case PREF_OPEN_FILENAME:
4493 case PREF_DIRNAME:
4494 case PREF_PASSWORD:
4495 case PREF_DISSECTOR:
4496 reset_string_like_preference(pref);
4497 break;
4498
4499 case PREF_RANGE:
4500 case PREF_DECODE_AS_RANGE:
4501 wmem_free(wmem_epan_scope(), *pref->varp.range);
4502 *pref->varp.range = range_copy(wmem_epan_scope(), pref->default_val.range);
4503 break;
4504
4505 case PREF_STATIC_TEXT:
4506 case PREF_UAT:
4507 /* Nothing to do */
4508 break;
4509
4510 case PREF_COLOR:
4511 *pref->varp.colorp = pref->default_val.color;
4512 break;
4513
4514 case PREF_CUSTOM:
4515 pref->custom_cbs.reset_cb(pref);
4516 break;
4517 }
4518}
4519
4520static void
4521reset_pref_cb(void *data, void *user_data)
4522{
4523 pref_t *pref = (pref_t *) data;
4524 module_t *module = (module_t *)user_data;
4525
4526 if (pref && (pref->type == PREF_RANGE || pref->type == PREF_DECODE_AS_RANGE)) {
4527 /*
4528 * Some dissectors expect the range (returned via prefs_get_range_value)
4529 * to remain valid if it has not changed. If it did change, then we
4530 * should set "prefs_changed_flags" to ensure that the preference apply
4531 * callback is invoked. That callback will notify dissectors that it
4532 * should no longer assume the range to be valid.
4533 */
4534 if (ranges_are_equal(*pref->varp.range, pref->default_val.range)) {
4535 /* Optimization: do not invoke apply callback if nothing changed. */
4536 return;
4537 }
4538 module->prefs_changed_flags |= prefs_get_effect_flags(pref);
4539 }
4540 reset_pref(pref);
4541}
4542
4543/*
4544 * Reset all preferences for a module.
4545 */
4546static bool_Bool
4547reset_module_prefs(const void *key _U___attribute__((unused)), void *value, void *data _U___attribute__((unused)))
4548{
4549 module_t *module = (module_t *)value;
4550 g_list_foreach(module->prefs, reset_pref_cb, module);
4551 return false0;
4552}
4553
4554/* Reset preferences */
4555void
4556prefs_reset(void)
4557{
4558 g_free(prefs.saved_at_version);
4559 prefs.saved_at_version = NULL((void*)0);
4560
4561 /*
4562 * Unload all UAT preferences.
4563 */
4564 uat_unload_all();
4565
4566 /*
4567 * Unload any loaded MIBs.
4568 */
4569 oids_cleanup();
4570
4571 /*
4572 * Reload all UAT preferences.
4573 */
4574 uat_load_all();
4575 /*
4576 * Reset the non-dissector preferences.
4577 */
4578 prefs_set_global_defaults();
4579
4580 /*
4581 * Reset the non-UAT dissector preferences.
4582 */
4583 wmem_tree_foreach(prefs_modules, reset_module_prefs, NULL((void*)0));
4584}
4585
4586#ifdef _WIN32
4587static void
4588read_registry(void)
4589{
4590 HKEY hTestKey;
4591 DWORD data;
4592 DWORD data_size = sizeof(DWORD);
4593 DWORD ret;
4594
4595 ret = RegOpenKeyExA(HKEY_CURRENT_USER, REG_HKCU_WIRESHARK_KEY"Software\\Wireshark", 0, KEY_READ, &hTestKey);
4596 if (ret != ERROR_SUCCESS && ret != ERROR_FILE_NOT_FOUND) {
4597 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"
, 4597, __func__, "Cannot open HKCU ""Software\\Wireshark"": 0x%lx"
, ret); } } while (0)
;
4598 return;
4599 }
4600
4601 ret = RegQueryValueExA(hTestKey, LOG_HKCU_CONSOLE_OPEN"ConsoleOpen", NULL((void*)0), NULL((void*)0), (LPBYTE)&data, &data_size);
4602 if (ret == ERROR_SUCCESS) {
4603 ws_log_console_open = (ws_log_console_open_pref)data;
4604 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"
, 4604, __func__, "Got ""ConsoleOpen"" from Windows registry: %d"
, ws_log_console_open); } } while (0)
;
4605 }
4606 else if (ret != ERROR_FILE_NOT_FOUND) {
4607 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"
, 4607, __func__, "Error reading registry key ""ConsoleOpen"": 0x%lx"
, ret); } } while (0)
;
4608 }
4609
4610 RegCloseKey(hTestKey);
4611}
4612#endif
4613
4614void
4615prefs_read_module(const char *module)
4616{
4617 int err;
4618 char *pf_path;
4619 FILE *pf;
4620
4621 module_t *target_module = prefs_find_module(module);
4622 if (!target_module) {
4623 return;
4624 }
4625
4626 /* Construct the pathname of the user's preferences file for the module. */
4627 char *pf_name = wmem_strdup_printf(NULL((void*)0), "%s.cfg", module);
4628 pf_path = get_persconffile_path(pf_name, true1);
4629 wmem_free(NULL((void*)0), pf_name);
4630
4631 /* Read the user's module preferences file, if it exists and is not a dir. */
4632 if (!test_for_regular_file(pf_path) || ((pf = ws_fopenfopen(pf_path, "r")) == NULL((void*)0))) {
4633 g_free(pf_path);
4634 /* Fall back to the user's generic preferences file. */
4635 pf_path = get_persconffile_path(PF_NAME"preferences", true1);
4636 pf = ws_fopenfopen(pf_path, "r");
4637 }
4638
4639 if (pf != NULL((void*)0)) {
4640 /* We succeeded in opening it; read it. */
4641 err = read_prefs_file(pf_path, pf, set_pref, target_module);
4642 if (err != 0) {
4643 /* We had an error reading the file; report it. */
4644 report_warning("Error reading your preferences file \"%s\": %s.",
4645 pf_path, g_strerror(err));
4646 } else
4647 g_free(pf_path);
4648 fclose(pf);
4649 } else {
4650 /* We failed to open it. If we failed for some reason other than
4651 "it doesn't exist", return the errno and the pathname, so our
4652 caller can report the error. */
4653 if (errno(*__errno_location ()) != ENOENT2) {
4654 report_warning("Can't open your preferences file \"%s\": %s.",
4655 pf_path, g_strerror(errno(*__errno_location ())));
4656 } else
4657 g_free(pf_path);
4658 }
4659
4660 return;
4661}
4662
4663/* Read the preferences file, fill in "prefs", and return a pointer to it.
4664
4665 If we got an error (other than "it doesn't exist") we report it through
4666 the UI. */
4667e_prefs *
4668read_prefs(void)
4669{
4670 int err;
4671 char *pf_path;
4672 FILE *pf;
4673
4674 /* clean up libsmi structures before reading prefs */
4675 oids_cleanup();
4676
4677#ifdef _WIN32
4678 read_registry();
4679#endif
4680
4681 /*
4682 * If we don't already have the pathname of the global preferences
4683 * file, construct it. Then, in either case, try to open the file.
4684 */
4685 if (gpf_path == NULL((void*)0)) {
4686 /*
4687 * We don't have the path; try the new path first, and, if that
4688 * file doesn't exist, try the old path.
4689 */
4690 gpf_path = get_datafile_path(PF_NAME"preferences");
4691 if ((pf = ws_fopenfopen(gpf_path, "r")) == NULL((void*)0) && errno(*__errno_location ()) == ENOENT2) {
4692 /*
4693 * It doesn't exist by the new name; try the old name.
4694 */
4695 g_free(gpf_path);
4696 gpf_path = get_datafile_path(OLD_GPF_NAME"wireshark.conf");
4697 pf = ws_fopenfopen(gpf_path, "r");
4698 }
4699 } else {
4700 /*
4701 * We have the path; try it.
4702 */
4703 pf = ws_fopenfopen(gpf_path, "r");
4704 }
4705
4706 /*
4707 * If we were able to open the file, read it.
4708 * XXX - if it failed for a reason other than "it doesn't exist",
4709 * report the error.
4710 */
4711 if (pf != NULL((void*)0)) {
4712 /*
4713 * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
4714 * seen.
4715 */
4716 mgcp_tcp_port_count = 0;
4717 mgcp_udp_port_count = 0;
4718
4719 /* We succeeded in opening it; read it. */
4720 err = read_prefs_file(gpf_path, pf, set_pref, NULL((void*)0));
4721 if (err != 0) {
4722 /* We had an error reading the file; report it. */
4723 report_warning("Error reading global preferences file \"%s\": %s.",
4724 gpf_path, g_strerror(err));
4725 }
4726 fclose(pf);
4727 } else {
4728 /* We failed to open it. If we failed for some reason other than
4729 "it doesn't exist", report the error. */
4730 if (errno(*__errno_location ()) != ENOENT2) {
4731 if (errno(*__errno_location ()) != 0) {
4732 report_warning("Can't open global preferences file \"%s\": %s.",
4733 gpf_path, g_strerror(errno(*__errno_location ())));
4734 }
4735 }
4736 }
4737
4738 /* Construct the pathname of the user's preferences file. */
4739 pf_path = get_persconffile_path(PF_NAME"preferences", true1);
4740
4741 /* Read the user's preferences file, if it exists. */
4742 if ((pf = ws_fopenfopen(pf_path, "r")) != NULL((void*)0)) {
4743 /*
4744 * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
4745 * seen.
4746 */
4747 mgcp_tcp_port_count = 0;
4748 mgcp_udp_port_count = 0;
4749
4750 /* We succeeded in opening it; read it. */
4751 err = read_prefs_file(pf_path, pf, set_pref, NULL((void*)0));
4752 if (err != 0) {
4753 /* We had an error reading the file; report it. */
4754 report_warning("Error reading your preferences file \"%s\": %s.",
4755 pf_path, g_strerror(err));
4756 } else
4757 g_free(pf_path);
4758 fclose(pf);
4759 } else {
4760 /* We failed to open it. If we failed for some reason other than
4761 "it doesn't exist", return the errno and the pathname, so our
4762 caller can report the error. */
4763 if (errno(*__errno_location ()) != ENOENT2) {
4764 report_warning("Can't open your preferences file \"%s\": %s.",
4765 pf_path, g_strerror(errno(*__errno_location ())));
4766 } else
4767 g_free(pf_path);
4768 }
4769
4770 /* load SMI modules if needed */
4771 oids_init();
4772
4773 return &prefs;
4774}
4775
4776/* read the preferences file (or similar) and call the callback
4777 * function to set each key/value pair found */
4778int
4779read_prefs_file(const char *pf_path, FILE *pf,
4780 pref_set_pair_cb pref_set_pair_fct, void *private_data)
4781{
4782 enum {
4783 START, /* beginning of a line */
4784 IN_VAR, /* processing key name */
4785 PRE_VAL, /* finished processing key name, skipping white space before value */
4786 IN_VAL, /* processing value */
4787 IN_SKIP /* skipping to the end of the line */
4788 } state = START;
4789 int got_c;
4790 GString *cur_val;
4791 GString *cur_var;
4792 bool_Bool got_val = false0;
4793 int fline = 1, pline = 1;
4794 char hint[] = "(save preferences to remove this warning)";
4795 char ver[128];
4796
4797 cur_val = g_string_new("");
4798 cur_var = g_string_new("");
4799
4800 /* Try to read in the profile name in the first line of the preferences file. */
4801 if (fscanf(pf, "# Configuration file for %127[^\r\n]", ver) == 1) {
1
Assuming the condition is false
2
Taking false branch
4802 /* Assume trailing period and remove it */
4803 g_free(prefs.saved_at_version);
4804 prefs.saved_at_version = g_strndup(ver, strlen(ver) - 1);
4805 }
4806 rewind(pf);
3
After calling 'rewind' reading 'errno' is required to find out if the call has failed
4807
4808 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'
4809 if (got_c == '\r') {
4810 /* Treat CR-LF at the end of a line like LF, so that if we're reading
4811 * a Windows-format file on UN*X, we handle it the same way we'd handle
4812 * a UN*X-format file. */
4813 got_c = ws_getc_unlockedgetc_unlocked(pf);
4814 if (got_c == EOF(-1))
4815 break;
4816 if (got_c != '\n') {
4817 /* Put back the character after the CR, and process the CR normally. */
4818 ungetc(got_c, pf);
4819 got_c = '\r';
4820 }
4821 }
4822 if (got_c == '\n') {
4823 state = START;
4824 fline++;
4825 continue;
4826 }
4827
4828 switch (state) {
4829 case START:
4830 if (g_ascii_isalnum(got_c)((g_ascii_table[(guchar) (got_c)] & G_ASCII_ALNUM) != 0)) {
4831 if (cur_var->len > 0) {
4832 if (got_val) {
4833 if (cur_val->len > 0) {
4834 if (cur_val->str[cur_val->len-1] == ',') {
4835 /*
4836 * If the pref has a trailing comma, eliminate it.
4837 */
4838 cur_val->str[cur_val->len-1] = '\0';
4839 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"
, 4839, __func__, "%s line %d: trailing comma in \"%s\" %s", pf_path
, pline, cur_var->str, hint); } } while (0)
;
4840 }
4841 }
4842 /* Call the routine to set the preference; it will parse
4843 the value as appropriate.
4844
4845 Since we're reading a file, rather than processing
4846 explicit user input, for range preferences, silently
4847 lower values in excess of the range's maximum, rather
4848 than reporting errors and failing. */
4849 switch (pref_set_pair_fct(cur_var->str, cur_val->str, private_data, false0)) {
4850
4851 case PREFS_SET_OK:
4852 break;
4853
4854 case PREFS_SET_SYNTAX_ERR:
4855 report_warning("Syntax error in preference \"%s\" at line %d of\n%s %s",
4856 cur_var->str, pline, pf_path, hint);
4857 break;
4858
4859 case PREFS_SET_NO_SUCH_PREF:
4860 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"
, 4861, __func__, "No such preference \"%s\" at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
4861 cur_var->str, pline, pf_path, hint)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 4861, __func__, "No such preference \"%s\" at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
;
4862 prefs.unknown_prefs = true1;
4863 break;
4864
4865 case PREFS_SET_OBSOLETE:
4866 /*
4867 * If an attempt is made to save the
4868 * preferences, a popup warning will be
4869 * displayed stating that obsolete prefs
4870 * have been detected and the user will
4871 * be given the opportunity to save these
4872 * prefs under a different profile name.
4873 * The prefs in question need to be listed
4874 * in the console window so that the
4875 * user can make an informed choice.
4876 */
4877 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"
, 4878, __func__, "Obsolete preference \"%s\" at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
4878 cur_var->str, pline, pf_path, hint)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 4878, __func__, "Obsolete preference \"%s\" at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
;
4879 prefs.unknown_prefs = true1;
4880 break;
4881 }
4882 } else {
4883 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"
, 4883, __func__, "Incomplete preference at line %d: of\n%s %s"
, pline, pf_path, hint); } } while (0)
;
4884 }
4885 }
4886 state = IN_VAR;
4887 got_val = false0;
4888 g_string_truncate(cur_var, 0)g_string_truncate_inline (cur_var, 0);
4889 g_string_append_c(cur_var, (char) got_c)g_string_append_c_inline (cur_var, (char) got_c);
4890 pline = fline;
4891 } else if (g_ascii_isspace(got_c)((g_ascii_table[(guchar) (got_c)] & G_ASCII_SPACE) != 0) && cur_var->len > 0 && got_val) {
4892 state = PRE_VAL;
4893 } else if (got_c == '#') {
4894 state = IN_SKIP;
4895 } else {
4896 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"
, 4896, __func__, "Malformed preference at line %d of\n%s %s"
, fline, pf_path, hint); } } while (0)
;
4897 }
4898 break;
4899 case IN_VAR:
4900 if (got_c != ':') {
4901 g_string_append_c(cur_var, (char) got_c)g_string_append_c_inline (cur_var, (char) got_c);
4902 } else {
4903 /* This is a colon (':') */
4904 state = PRE_VAL;
4905 g_string_truncate(cur_val, 0)g_string_truncate_inline (cur_val, 0);
4906 /*
4907 * Set got_val to true to accommodate prefs such as
4908 * "gui.fileopen.dir" that do not require a value.
4909 */
4910 got_val = true1;
4911 }
4912 break;
4913 case PRE_VAL:
4914 if (!g_ascii_isspace(got_c)((g_ascii_table[(guchar) (got_c)] & G_ASCII_SPACE) != 0)) {
4915 state = IN_VAL;
4916 g_string_append_c(cur_val, (char) got_c)g_string_append_c_inline (cur_val, (char) got_c);
4917 }
4918 break;
4919 case IN_VAL:
4920 g_string_append_c(cur_val, (char) got_c)g_string_append_c_inline (cur_val, (char) got_c);
4921 break;
4922 case IN_SKIP:
4923 break;
4924 }
4925 }
4926 if (cur_var->len > 0) {
4927 if (got_val) {
4928 /* Call the routine to set the preference; it will parse
4929 the value as appropriate.
4930
4931 Since we're reading a file, rather than processing
4932 explicit user input, for range preferences, silently
4933 lower values in excess of the range's maximum, rather
4934 than reporting errors and failing. */
4935 switch (pref_set_pair_fct(cur_var->str, cur_val->str, private_data, false0)) {
4936
4937 case PREFS_SET_OK:
4938 break;
4939
4940 case PREFS_SET_SYNTAX_ERR:
4941 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"
, 4942, __func__, "Syntax error in preference %s at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
4942 cur_var->str, pline, pf_path, hint)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 4942, __func__, "Syntax error in preference %s at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
;
4943 break;
4944
4945 case PREFS_SET_NO_SUCH_PREF:
4946 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"
, 4947, __func__, "No such preference \"%s\" at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
4947 cur_var->str, pline, pf_path, hint)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 4947, __func__, "No such preference \"%s\" at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
;
4948 prefs.unknown_prefs = true1;
4949 break;
4950
4951 case PREFS_SET_OBSOLETE:
4952 prefs.unknown_prefs = true1;
4953 break;
4954 }
4955 } else {
4956 ws_warning("Incomplete preference at line %d of\n%s %s",do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 4957, __func__, "Incomplete preference at line %d of\n%s %s"
, pline, pf_path, hint); } } while (0)
4957 pline, pf_path, hint)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 4957, __func__, "Incomplete preference at line %d of\n%s %s"
, pline, pf_path, hint); } } while (0)
;
4958 }
4959 }
4960
4961 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)))))
;
4962 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)))))
;
4963
4964 if (ferror(pf))
4965 return errno(*__errno_location ());
4966 else
4967 return 0;
4968}
4969
4970/*
4971 * If we were handed a preference starting with "uat:", try to turn it into
4972 * a valid uat entry.
4973 */
4974static bool_Bool
4975prefs_set_uat_pref(char *uat_entry, char **errmsg) {
4976 char *p, *colonp;
4977 uat_t *uat;
4978 bool_Bool ret;
4979
4980 colonp = strchr(uat_entry, ':');
4981 if (colonp == NULL((void*)0))
4982 return false0;
4983
4984 p = colonp;
4985 *p++ = '\0';
4986
4987 /*
4988 * Skip over any white space (there probably won't be any, but
4989 * as we allow it in the preferences file, we might as well
4990 * allow it here).
4991 */
4992 while (g_ascii_isspace(*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0))
4993 p++;
4994 if (*p == '\0') {
4995 /*
4996 * Put the colon back, so if our caller uses, in an
4997 * error message, the string they passed us, the message
4998 * looks correct.
4999 */
5000 *colonp = ':';
5001 return false0;
5002 }
5003
5004 uat = uat_find(uat_entry);
5005 *colonp = ':';
5006 if (uat == NULL((void*)0)) {
5007 *errmsg = g_strdup("Unknown preference")g_strdup_inline ("Unknown preference");
5008 return false0;
5009 }
5010
5011 ret = uat_load_str(uat, p, errmsg);
5012 return ret;
5013}
5014
5015/*
5016 * Given a string of the form "<pref name>:<pref value>", as might appear
5017 * as an argument to a "-o" option, parse it and set the preference in
5018 * question. Return an indication of whether it succeeded or failed
5019 * in some fashion.
5020 */
5021prefs_set_pref_e
5022prefs_set_pref(char *prefarg, char **errmsg)
5023{
5024 char *p, *colonp;
5025 prefs_set_pref_e ret;
5026
5027 /*
5028 * Set the counters of "mgcp.{tcp,udp}.port" entries we've
5029 * seen to values that keep us from trying to interpret them
5030 * as "mgcp.{tcp,udp}.gateway_port" or "mgcp.{tcp,udp}.callagent_port",
5031 * as, from the command line, we have no way of guessing which
5032 * the user had in mind.
5033 */
5034 mgcp_tcp_port_count = -1;
5035 mgcp_udp_port_count = -1;
5036
5037 *errmsg = NULL((void*)0);
5038
5039 colonp = strchr(prefarg, ':');
5040 if (colonp == NULL((void*)0))
5041 return PREFS_SET_SYNTAX_ERR;
5042
5043 p = colonp;
5044 *p++ = '\0';
5045
5046 /*
5047 * Skip over any white space (there probably won't be any, but
5048 * as we allow it in the preferences file, we might as well
5049 * allow it here).
5050 */
5051 while (g_ascii_isspace(*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0))
5052 p++;
5053 /* The empty string is a legal value for range preferences (PREF_RANGE,
5054 * PREF_DECODE_AS_RANGE), and string-like preferences (PREF_STRING,
5055 * PREF_SAVE_FILENAME, PREF_OPEN_FILENAME, PREF_DIRNAME), indeed often
5056 * not just useful but the default. A user might have a value saved
5057 * to their preference file but want to override it to default behavior.
5058 * Individual preference handlers of those types should be prepared to
5059 * deal with an empty string. For other types, it is up to set_pref() to
5060 * test for the empty string and set PREFS_SET_SYNTAX_ERROR there.
5061 */
5062 if (strcmp(prefarg, "uat")) {
5063 ret = set_pref(prefarg, p, NULL((void*)0), true1);
5064 } else {
5065 ret = prefs_set_uat_pref(p, errmsg) ? PREFS_SET_OK : PREFS_SET_SYNTAX_ERR;
5066 }
5067 *colonp = ':'; /* put the colon back */
5068 return ret;
5069}
5070
5071unsigned prefs_get_uint_value(pref_t *pref, pref_source_t source)
5072{
5073 switch (source)
5074 {
5075 case pref_default:
5076 return pref->default_val.uint;
5077 case pref_stashed:
5078 return pref->stashed_val.uint;
5079 case pref_current:
5080 return *pref->varp.uint;
5081 default:
5082 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 5082
, __func__, "assertion \"not reached\" failed")
;
5083 break;
5084 }
5085
5086 return 0;
5087}
5088
5089char* prefs_get_password_value(pref_t *pref, pref_source_t source)
5090{
5091 return prefs_get_string_value(pref, source);
5092}
5093
5094
5095unsigned int prefs_set_uint_value(pref_t *pref, unsigned value, pref_source_t source)
5096{
5097 unsigned int changed = 0;
5098 switch (source)
5099 {
5100 case pref_default:
5101 if (pref->default_val.uint != value) {
5102 pref->default_val.uint = value;
5103 changed = prefs_get_effect_flags(pref);
5104 }
5105 break;
5106 case pref_stashed:
5107 if (pref->stashed_val.uint != value) {
5108 pref->stashed_val.uint = value;
5109 changed = prefs_get_effect_flags(pref);
5110 }
5111 break;
5112 case pref_current:
5113 if (*pref->varp.uint != value) {
5114 *pref->varp.uint = value;
5115 changed = prefs_get_effect_flags(pref);
5116 }
5117 break;
5118 default:
5119 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 5119
, __func__, "assertion \"not reached\" failed")
;
5120 break;
5121 }
5122
5123 return changed;
5124}
5125
5126/*
5127 * For use by UI code that sets preferences.
5128 */
5129unsigned int
5130prefs_set_password_value(pref_t *pref, const char* value, pref_source_t source)
5131{
5132 return prefs_set_string_value(pref, value, source);
5133}
5134
5135
5136unsigned prefs_get_uint_base(pref_t *pref)
5137{
5138 return pref->info.base;
5139}
5140
5141/*
5142 * Returns true if the given device is hidden
5143 */
5144bool_Bool
5145prefs_is_capture_device_hidden(const char *name)
5146{
5147 char *tok, *devices;
5148 size_t len;
5149
5150 if (prefs.capture_devices_hide && name) {
5151 devices = g_strdup (prefs.capture_devices_hide)g_strdup_inline (prefs.capture_devices_hide);
5152 len = strlen (name);
5153 for (tok = strtok (devices, ","); tok; tok = strtok(NULL((void*)0), ",")) {
5154 if (strlen (tok) == len && strcmp (name, tok) == 0) {
5155 g_free (devices);
5156 return true1;
5157 }
5158 }
5159 g_free (devices);
5160 }
5161
5162 return false0;
5163}
5164
5165/*
5166 * Returns true if the given column is visible (not hidden)
5167 */
5168static bool_Bool
5169prefs_is_column_visible(const char *cols_hidden, int col)
5170{
5171 char *tok, *cols, *p;
5172 int cidx;
5173
5174 /*
5175 * Do we have a list of hidden columns?
5176 */
5177 if (cols_hidden) {
5178 /*
5179 * Yes - check the column against each of the ones in the
5180 * list.
5181 */
5182 cols = g_strdup(cols_hidden)g_strdup_inline (cols_hidden);
5183 for (tok = strtok(cols, ","); tok; tok = strtok(NULL((void*)0), ",")) {
5184 tok = g_strstrip(tok)g_strchomp (g_strchug (tok));
5185
5186 cidx = (int)strtol(tok, &p, 10);
5187 if (p == tok || *p != '\0') {
5188 continue;
5189 }
5190 if (cidx != col) {
5191 continue;
5192 }
5193 /*
5194 * OK, they match, so it's one of the hidden fields,
5195 * hence not visible.
5196 */
5197 g_free(cols);
5198 return false0;
5199 }
5200 g_free(cols);
5201 }
5202
5203 /*
5204 * No - either there are no hidden columns or this isn't one
5205 * of them - so it is visible.
5206 */
5207 return true1;
5208}
5209
5210/*
5211 * Returns true if the given column is visible (not hidden)
5212 */
5213static bool_Bool
5214prefs_is_column_fmt_visible(const char *cols_hidden, fmt_data *cfmt)
5215{
5216 char *tok, *cols;
5217 fmt_data cfmt_hidden;
5218
5219 /*
5220 * Do we have a list of hidden columns?
5221 */
5222 if (cols_hidden) {
5223 /*
5224 * Yes - check the column against each of the ones in the
5225 * list.
5226 */
5227 cols = g_strdup(cols_hidden)g_strdup_inline (cols_hidden);
5228 for (tok = strtok(cols, ","); tok; tok = strtok(NULL((void*)0), ",")) {
5229 tok = g_strstrip(tok)g_strchomp (g_strchug (tok));
5230
5231 /*
5232 * Parse this column format.
5233 */
5234 if (!parse_column_format(&cfmt_hidden, tok)) {
5235 /*
5236 * It's not valid; ignore it.
5237 */
5238 continue;
5239 }
5240
5241 /*
5242 * Does it match the column?
5243 */
5244 if (cfmt->fmt != cfmt_hidden.fmt) {
5245 /* No. */
5246 g_free(cfmt_hidden.custom_fields);
5247 cfmt_hidden.custom_fields = NULL((void*)0);
5248 continue;
5249 }
5250 if (cfmt->fmt == COL_CUSTOM) {
5251 /*
5252 * A custom column has to have the same custom field
5253 * and occurrence.
5254 */
5255 if (cfmt_hidden.custom_fields && cfmt->custom_fields) {
5256 if (strcmp(cfmt->custom_fields,
5257 cfmt_hidden.custom_fields) != 0) {
5258 /* Different fields. */
5259 g_free(cfmt_hidden.custom_fields);
5260 cfmt_hidden.custom_fields = NULL((void*)0);
5261 continue;
5262 }
5263 if (cfmt->custom_occurrence != cfmt_hidden.custom_occurrence) {
5264 /* Different occurrences settings. */
5265 g_free(cfmt_hidden.custom_fields);
5266 cfmt_hidden.custom_fields = NULL((void*)0);
5267 continue;
5268 }
5269 }
5270 }
5271
5272 /*
5273 * OK, they match, so it's one of the hidden fields,
5274 * hence not visible.
5275 */
5276 g_free(cfmt_hidden.custom_fields);
5277 g_free(cols);
5278 return false0;
5279 }
5280 g_free(cols);
5281 }
5282
5283 /*
5284 * No - either there are no hidden columns or this isn't one
5285 * of them - so it is visible.
5286 */
5287 return true1;
5288}
5289
5290/*
5291 * Returns true if the given device should capture in monitor mode by default
5292 */
5293bool_Bool
5294prefs_capture_device_monitor_mode(const char *name)
5295{
5296 char *tok, *devices;
5297 size_t len;
5298
5299 if (prefs.capture_devices_monitor_mode && name) {
5300 devices = g_strdup (prefs.capture_devices_monitor_mode)g_strdup_inline (prefs.capture_devices_monitor_mode);
5301 len = strlen (name);
5302 for (tok = strtok (devices, ","); tok; tok = strtok(NULL((void*)0), ",")) {
5303 if (strlen (tok) == len && strcmp (name, tok) == 0) {
5304 g_free (devices);
5305 return true1;
5306 }
5307 }
5308 g_free (devices);
5309 }
5310
5311 return false0;
5312}
5313
5314/*
5315 * Returns true if the user has marked this column as visible
5316 */
5317bool_Bool
5318prefs_capture_options_dialog_column_is_visible(const char *column)
5319{
5320 GList *curr;
5321 char *col;
5322
5323 for (curr = g_list_first(prefs.capture_columns); curr; curr = g_list_next(curr)((curr) ? (((GList *)(curr))->next) : ((void*)0))) {
5324 col = (char *)curr->data;
5325 if (col && (g_ascii_strcasecmp(col, column) == 0)) {
5326 return true1;
5327 }
5328 }
5329 return false0;
5330}
5331
5332bool_Bool
5333prefs_has_layout_pane_content (layout_pane_content_e layout_pane_content)
5334{
5335 return ((prefs.gui_layout_content_1 == layout_pane_content) ||
5336 (prefs.gui_layout_content_2 == layout_pane_content) ||
5337 (prefs.gui_layout_content_3 == layout_pane_content));
5338}
5339
5340#define PRS_GUI_FILTER_LABEL"gui.filter_expressions.label" "gui.filter_expressions.label"
5341#define PRS_GUI_FILTER_EXPR"gui.filter_expressions.expr" "gui.filter_expressions.expr"
5342#define PRS_GUI_FILTER_ENABLED"gui.filter_expressions.enabled" "gui.filter_expressions.enabled"
5343
5344/*
5345 * Extract the red, green, and blue components of a 24-bit RGB value
5346 * and convert them from [0,255] to [0,65535].
5347 */
5348#define RED_COMPONENT(x)(uint16_t) (((((x) >> 16) & 0xff) * 65535 / 255)) (uint16_t) (((((x) >> 16) & 0xff) * 65535 / 255))
5349#define GREEN_COMPONENT(x)(uint16_t) (((((x) >> 8) & 0xff) * 65535 / 255)) (uint16_t) (((((x) >> 8) & 0xff) * 65535 / 255))
5350#define BLUE_COMPONENT(x)(uint16_t) ( (((x) & 0xff) * 65535 / 255)) (uint16_t) ( (((x) & 0xff) * 65535 / 255))
5351
5352char
5353string_to_name_resolve(const char *string, e_addr_resolve *name_resolve)
5354{
5355 char c;
5356
5357 memset(name_resolve, 0, sizeof(e_addr_resolve));
5358 while ((c = *string++) != '\0') {
5359 switch (c) {
5360 case 'g':
5361 name_resolve->maxmind_geoip = true1;
5362 break;
5363 case 'm':
5364 name_resolve->mac_name = true1;
5365 break;
5366 case 'n':
5367 name_resolve->network_name = true1;
5368 break;
5369 case 'N':
5370 name_resolve->use_external_net_name_resolver = true1;
5371 break;
5372 case 't':
5373 name_resolve->transport_name = true1;
5374 break;
5375 case 'd':
5376 name_resolve->dns_pkt_addr_resolution = true1;
5377 break;
5378 case 's':
5379 name_resolve->handshake_sni_addr_resolution = true1;
5380 break;
5381 case 'v':
5382 name_resolve->vlan_name = true1;
5383 break;
5384 default:
5385 /*
5386 * Unrecognized letter.
5387 */
5388 return c;
5389 }
5390 }
5391 return '\0';
5392}
5393
5394static bool_Bool
5395deprecated_heur_dissector_pref(char *pref_name, const char *value)
5396{
5397 struct heur_pref_name
5398 {
5399 const char* pref_name;
5400 const char* short_name;
5401 bool_Bool more_dissectors; /* For multiple dissectors controlled by the same preference */
5402 };
5403
5404 struct heur_pref_name heur_prefs[] = {
5405 {"acn.heuristic_acn", "acn_udp", 0},
5406 {"bfcp.enable", "bfcp_tcp", 1},
5407 {"bfcp.enable", "bfcp_udp", 0},
5408 {"bt-dht.enable", "bittorrent_dht_udp", 0},
5409 {"bt-utp.enable", "bt_utp_udp", 0},
5410 {"cattp.enable", "cattp_udp", 0},
5411 {"cfp.enable", "fp_eth", 0},
5412 {"dicom.heuristic", "dicom_tcp", 0},
5413 {"dnp3.heuristics", "dnp3_tcp", 1},
5414 {"dnp3.heuristics", "dnp3_udp", 0},
5415 {"dvb-s2_modeadapt.enable", "dvb_s2_udp", 0},
5416 {"esl.enable", "esl_eth", 0},
5417 {"fp.udp_heur", "fp_udp", 0},
5418 {"gvsp.enable_heuristic", "gvsp_udp", 0},
5419 {"hdcp2.enable", "hdcp2_tcp", 0},
5420 {"hislip.enable_heuristic", "hislip_tcp", 0},
5421 {"infiniband.dissect_eoib", "mellanox_eoib", 1},
5422 {"infiniband.identify_payload", "eth_over_ib", 0},
5423 {"jxta.udp.heuristic", "jxta_udp", 0},
5424 {"jxta.tcp.heuristic", "jxta_tcp", 0},
5425 {"jxta.sctp.heuristic", "jxta_sctp", 0},
5426 {"mac-lte.heuristic_mac_lte_over_udp", "mac_lte_udp", 0},
5427 {"mbim.bulk_heuristic", "mbim_usb_bulk", 0},
5428 {"norm.heuristic_norm", "rmt_norm_udp", 0},
5429 {"openflow.heuristic", "openflow_tcp", 0},
5430 {"pdcp-lte.heuristic_pdcp_lte_over_udp", "pdcp_lte_udp", 0},
5431 {"rlc.heuristic_rlc_over_udp", "rlc_udp", 0},
5432 {"rlc-lte.heuristic_rlc_lte_over_udp", "rlc_lte_udp", 0},
5433 {"rtcp.heuristic_rtcp", "rtcp_udp", 1},
5434 {"rtcp.heuristic_rtcp", "rtcp_stun", 0},
5435 {"rtp.heuristic_rtp", "rtp_udp", 1},
5436 {"rtp.heuristic_rtp", "rtp_stun", 0},
5437 {"teredo.heuristic_teredo", "teredo_udp", 0},
5438 {"vssmonitoring.use_heuristics", "vssmonitoring_eth", 0},
5439 {"xml.heuristic", "xml_http", 1},
5440 {"xml.heuristic", "xml_sip", 1},
5441 {"xml.heuristic", "xml_media", 0},
5442 {"xml.heuristic_tcp", "xml_tcp", 0},
5443 {"xml.heuristic_udp", "xml_udp", 0},
5444 };
5445
5446 unsigned int i;
5447 heur_dtbl_entry_t* heuristic;
5448
5449
5450 for (i = 0; i < array_length(heur_prefs)(sizeof (heur_prefs) / sizeof (heur_prefs)[0]); i++)
5451 {
5452 if (strcmp(pref_name, heur_prefs[i].pref_name) == 0)
5453 {
5454 heuristic = find_heur_dissector_by_unique_short_name(heur_prefs[i].short_name);
5455 if (heuristic != NULL((void*)0)) {
5456 heuristic->enabled = ((g_ascii_strcasecmp(value, "true") == 0) ? true1 : false0);
5457 }
5458
5459 if (!heur_prefs[i].more_dissectors)
5460 return true1;
5461 }
5462 }
5463
5464
5465 return false0;
5466}
5467
5468static bool_Bool
5469deprecated_enable_dissector_pref(char *pref_name, const char *value)
5470{
5471 struct dissector_pref_name
5472 {
5473 const char* pref_name;
5474 const char* short_name;
5475 };
5476
5477 struct dissector_pref_name dissector_prefs[] = {
5478 {"transum.tsumenabled", "TRANSUM"},
5479 {"snort.enable_snort_dissector", "Snort"},
5480 {"prp.enable", "PRP"},
5481 };
5482
5483 unsigned int i;
5484 int proto_id;
5485
5486 for (i = 0; i < array_length(dissector_prefs)(sizeof (dissector_prefs) / sizeof (dissector_prefs)[0]); i++)
5487 {
5488 if (strcmp(pref_name, dissector_prefs[i].pref_name) == 0)
5489 {
5490 proto_id = proto_get_id_by_short_name(dissector_prefs[i].short_name);
5491 if (proto_id >= 0)
5492 proto_set_decoding(proto_id, ((g_ascii_strcasecmp(value, "true") == 0) ? true1 : false0));
5493 return true1;
5494 }
5495 }
5496
5497 return false0;
5498}
5499
5500static bool_Bool
5501deprecated_port_pref(char *pref_name, const char *value)
5502{
5503 struct port_pref_name
5504 {
5505 const char* pref_name;
5506 const char* module_name; /* the protocol filter name */
5507 const char* table_name;
5508 unsigned base;
5509 };
5510
5511 struct obsolete_pref_name
5512 {
5513 const char* pref_name;
5514 };
5515
5516 /* For now this is only supporting TCP/UDP port and RTP payload
5517 * types dissector preferences, which are assumed to be decimal */
5518 /* module_name is the filter name of the destination port preference,
5519 * which is usually the same as the original module but not
5520 * necessarily (e.g., if the preference is for what is now a PINO.)
5521 * XXX: Most of these were changed pre-2.0. Can we end support
5522 * for migrating legacy preferences at some point?
5523 */
5524 struct port_pref_name port_prefs[] = {
5525 /* TCP */
5526 {"cmp.tcp_alternate_port", "cmp", "tcp.port", 10},
5527 {"h248.tcp_port", "h248", "tcp.port", 10},
5528 {"cops.tcp.cops_port", "cops", "tcp.port", 10},
5529 {"dhcpfo.tcp_port", "dhcpfo", "tcp.port", 10},
5530 {"enttec.tcp_port", "enttec", "tcp.port", 10},
5531 {"forces.tcp_alternate_port", "forces", "tcp.port", 10},
5532 {"ged125.tcp_port", "ged125", "tcp.port", 10},
5533 {"hpfeeds.dissector_port", "hpfeeds", "tcp.port", 10},
5534 {"lsc.port", "lsc", "tcp.port", 10},
5535 {"megaco.tcp.txt_port", "megaco", "tcp.port", 10},
5536 {"netsync.tcp_port", "netsync", "tcp.port", 10},
5537 {"osi.tpkt_port", "osi", "tcp.port", 10},
5538 {"rsync.tcp_port", "rsync", "tcp.port", 10},
5539 {"sametime.tcp_port", "sametime", "tcp.port", 10},
5540 {"sigcomp.tcp.port2", "sigcomp", "tcp.port", 10},
5541 {"synphasor.tcp_port", "synphasor", "tcp.port", 10},
5542 {"tipc.alternate_port", "tipc", "tcp.port", 10},
5543 {"vnc.alternate_port", "vnc", "tcp.port", 10},
5544 {"scop.port", "scop", "tcp.port", 10},
5545 {"scop.port_secure", "scop", "tcp.port", 10},
5546 {"tpncp.tcp.trunkpack_port", "tpncp", "tcp.port", 10},
5547 /* UDP */
5548 {"h248.udp_port", "h248", "udp.port", 10},
5549 {"actrace.udp_port", "actrace", "udp.port", 10},
5550 {"brp.port", "brp", "udp.port", 10},
5551 {"bvlc.additional_udp_port", "bvlc", "udp.port", 10},
5552 {"capwap.udp.port.control", "capwap", "udp.port", 10},
5553 {"capwap.udp.port.data", "capwap", "udp.port", 10},
5554 {"coap.udp_port", "coap", "udp.port", 10},
5555 {"enttec.udp_port", "enttec", "udp.port", 10},
5556 {"forces.udp_alternate_port", "forces", "udp.port", 10},
5557 {"ldss.udp_port", "ldss", "udp.port", 10},
5558 {"lmp.udp_port", "lmp", "udp.port", 10},
5559 {"ltp.port", "ltp", "udp.port", 10},
5560 {"lwres.udp.lwres_port", "lwres", "udp.port", 10},
5561 {"megaco.udp.txt_port", "megaco", "udp.port", 10},
5562 {"pfcp.port_pfcp", "pfcp", "udp.port", 10},
5563 {"pgm.udp.encap_ucast_port", "pgm", "udp.port", 10},
5564 {"pgm.udp.encap_mcast_port", "pgm", "udp.port", 10},
5565 {"quic.udp.quic.port", "quic", "udp.port", 10},
5566 {"quic.udp.quics.port", "quic", "udp.port", 10},
5567 {"radius.alternate_port", "radius", "udp.port", 10},
5568 {"rdt.default_udp_port", "rdt", "udp.port", 10},
5569 {"alc.default.udp_port", "alc", "udp.port", 10},
5570 {"sigcomp.udp.port2", "sigcomp", "udp.port", 10},
5571 {"synphasor.udp_port", "synphasor", "udp.port", 10},
5572 {"tdmop.udpport", "tdmop", "udp.port", 10},
5573 {"uaudp.port1", "uaudp", "udp.port", 10},
5574 {"uaudp.port2", "uaudp", "udp.port", 10},
5575 {"uaudp.port3", "uaudp", "udp.port", 10},
5576 {"uaudp.port4", "uaudp", "udp.port", 10},
5577 {"uhd.dissector_port", "uhd", "udp.port", 10},
5578 {"vrt.dissector_port", "vrt", "udp.port", 10},
5579 {"tpncp.udp.trunkpack_port", "tpncp", "udp.port", 10},
5580 /* SCTP */
5581 {"hnbap.port", "hnbap", "sctp.port", 10},
5582 {"m2pa.port", "m2pa", "sctp.port", 10},
5583 {"megaco.sctp.txt_port", "megaco", "sctp.port", 10},
5584 {"rua.port", "rua", "sctp.port", 10},
5585 /* SCTP PPI */
5586 {"lapd.sctp_payload_protocol_identifier", "lapd", "sctp.ppi", 10},
5587 /* SCCP SSN */
5588 {"ranap.sccp_ssn", "ranap", "sccp.ssn", 10},
5589 };
5590
5591 struct port_pref_name port_range_prefs[] = {
5592 /* TCP */
5593 {"couchbase.tcp.ports", "couchbase", "tcp.port", 10},
5594 {"gsm_ipa.tcp_ports", "gsm_ipa", "tcp.port", 10},
5595 {"kafka.tcp.ports", "kafka", "tcp.port", 10},
5596 {"kt.tcp.ports", "kt", "tcp.port", 10},
5597 {"memcache.tcp.ports", "memcache", "tcp.port", 10},
5598 {"mrcpv2.tcp.port_range", "mrcpv2", "tcp.port", 10},
5599 {"pdu_transport.ports.tcp", "pdu_transport", "tcp.port", 10},
5600 {"rtsp.tcp.port_range", "rtsp", "tcp.port", 10},
5601 {"sip.tcp.ports", "sip", "tcp.port", 10},
5602 {"someip.ports.tcp", "someip", "tcp.port", 10},
5603 {"tds.tcp_ports", "tds", "tcp.port", 10},
5604 {"tpkt.tcp.ports", "tpkt", "tcp.port", 10},
5605 {"uma.tcp.ports", "uma", "tcp.port", 10},
5606 /* UDP */
5607 {"aruba_erm.udp.ports", "arubs_erm", "udp.port", 10},
5608 {"diameter.udp.ports", "diameter", "udp.port", 10},
5609 {"dmp.udp_ports", "dmp", "udp.port", 10},
5610 {"dns.udp.ports", "dns", "udp.port", 10},
5611 {"gsm_ipa.udp_ports", "gsm_ipa", "udp.port", 10},
5612 {"hcrt.dissector_udp_port", "hcrt", "udp.port", 10},
5613 {"memcache.udp.ports", "memcache", "udp.port", 10},
5614 {"nb_rtpmux.udp_ports", "nb_rtpmux", "udp.port", 10},
5615 {"gprs-ns.udp.ports", "gprs-ns", "udp.port", 10},
5616 {"p_mul.udp_ports", "p_mul", "udp.port", 10},
5617 {"pdu_transport.ports.udp", "pdu_transport", "udp.port", 10},
5618 {"radius.ports", "radius", "udp.port", 10},
5619 {"sflow.ports", "sflow", "udp.port", 10},
5620 {"someip.ports.udp", "someip", "udp.port", 10},
5621 {"sscop.udp.ports", "sscop", "udp.port", 10},
5622 {"tftp.udp_ports", "tftp", "udp.port", 10},
5623 {"tipc.udp.ports", "tipc", "udp.port", 10},
5624 /* RTP */
5625 {"amr.dynamic.payload.type", "amr", "rtp.pt", 10},
5626 {"amr.wb.dynamic.payload.type", "amr_wb", "rtp.pt", 10},
5627 {"dvb-s2_modeadapt.dynamic.payload.type", "dvb-s2_modeadapt", "rtp.pt", 10},
5628 {"evs.dynamic.payload.type", "evs", "rtp.pt", 10},
5629 {"h263p.dynamic.payload.type", "h263p", "rtp.pt", 10},
5630 {"h264.dynamic.payload.type", "h264", "rtp.pt", 10},
5631 {"h265.dynamic.payload.type", "h265", "rtp.pt", 10},
5632 {"ismacryp.dynamic.payload.type", "ismacryp", "rtp.pt", 10},
5633 {"iuup.dynamic.payload.type", "iuup", "rtp.pt", 10},
5634 {"lapd.rtp_payload_type", "lapd", "rtp.pt", 10},
5635 {"mp4ves.dynamic.payload.type", "mp4ves", "rtp.pt", 10},
5636 {"mtp2.rtp_payload_type", "mtp2", "rtp.pt", 10},
5637 {"opus.dynamic.payload.type", "opus", "rtp.pt", 10},
5638 {"rtp.rfc2198_payload_type", "rtp_rfc2198", "rtp.pt", 10},
5639 {"rtpevent.event_payload_type_value", "rtpevent", "rtp.pt", 10},
5640 {"rtpevent.cisco_nse_payload_type_value", "rtpevent", "rtp.pt", 10},
5641 {"rtpmidi.midi_payload_type_value", "rtpmidi", "rtp.pt", 10},
5642 {"vp8.dynamic.payload.type", "vp8", "rtp.pt", 10},
5643 /* SCTP */
5644 {"diameter.sctp.ports", "diameter", "sctp.port", 10},
5645 {"sgsap.sctp_ports", "sgsap", "sctp.port", 10},
5646 /* SCCP SSN */
5647 {"pcap.ssn", "pcap", "sccp.ssn", 10},
5648 };
5649
5650 /* These are subdissectors of TPKT/OSITP that used to have a
5651 TCP port preference even though they were never
5652 directly on TCP. Convert them to use Decode As
5653 with the TPKT dissector handle */
5654 struct port_pref_name tpkt_subdissector_port_prefs[] = {
5655 {"dap.tcp.port", "dap", "tcp.port", 10},
5656 {"disp.tcp.port", "disp", "tcp.port", 10},
5657 {"dop.tcp.port", "dop", "tcp.port", 10},
5658 {"dsp.tcp.port", "dsp", "tcp.port", 10},
5659 {"p1.tcp.port", "p1", "tcp.port", 10},
5660 {"p7.tcp.port", "p7", "tcp.port", 10},
5661 {"rdp.tcp.port", "rdp", "tcp.port", 10},
5662 };
5663
5664 /* These are obsolete preferences from the dissectors' view,
5665 (typically because of a switch from a single value to a
5666 range value) but the name of the preference conflicts
5667 with the generated preference name from the dissector table.
5668 Don't allow the obsolete preference through to be handled */
5669 struct obsolete_pref_name obsolete_prefs[] = {
5670 {"diameter.tcp.port"},
5671 {"kafka.tcp.port"},
5672 {"mrcpv2.tcp.port"},
5673 {"rtsp.tcp.port"},
5674 {"sip.tcp.port"},
5675 {"t38.tcp.port"},
5676 };
5677
5678 unsigned int i;
5679 unsigned uval;
5680 dissector_table_t sub_dissectors;
5681 dissector_handle_t handle, tpkt_handle;
5682 module_t *module;
5683 pref_t *pref;
5684
5685 static bool_Bool sanity_checked;
5686 if (!sanity_checked) {
5687 sanity_checked = true1;
5688 for (i = 0; i < G_N_ELEMENTS(port_prefs)(sizeof (port_prefs) / sizeof ((port_prefs)[0])); i++) {
5689 module = prefs_find_module(port_prefs[i].module_name);
5690 if (!module) {
5691 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"
, 5691, __func__, "Deprecated ports pref check - module '%s' not found"
, port_prefs[i].module_name); } } while (0)
;
5692 continue;
5693 }
5694 pref = prefs_find_preference(module, port_prefs[i].table_name);
5695 if (!pref) {
5696 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"
, 5696, __func__, "Deprecated ports pref '%s.%s' not found", module
->name, port_prefs[i].table_name); } } while (0)
;
5697 continue;
5698 }
5699 if (pref->type != PREF_DECODE_AS_RANGE) {
5700 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"
, 5700, __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)
;
5701 }
5702 }
5703 }
5704
5705 for (i = 0; i < G_N_ELEMENTS(port_prefs)(sizeof (port_prefs) / sizeof ((port_prefs)[0])); i++) {
5706 if (strcmp(pref_name, port_prefs[i].pref_name) == 0) {
5707 if (!ws_basestrtou32(value, NULL((void*)0), &uval, port_prefs[i].base))
5708 return false0; /* number was bad */
5709
5710 module = prefs_find_module(port_prefs[i].module_name);
5711 pref = prefs_find_preference(module, port_prefs[i].table_name);
5712 if (pref != NULL((void*)0)) {
5713 module->prefs_changed_flags |= prefs_get_effect_flags(pref);
5714 if (pref->type == PREF_DECODE_AS_RANGE) {
5715 // The legacy preference was a port number, but the new
5716 // preference is a port range. Add to existing range.
5717 if (uval) {
5718 prefs_range_add_value(pref, uval);
5719 }
5720 }
5721 }
5722
5723 /* If the value is zero, it wouldn't add to the Decode As tables */
5724 if (uval != 0)
5725 {
5726 sub_dissectors = find_dissector_table(port_prefs[i].table_name);
5727 if (sub_dissectors != NULL((void*)0)) {
5728 handle = dissector_table_get_dissector_handle(sub_dissectors, module->title);
5729 if (handle != NULL((void*)0)) {
5730 dissector_change_uint(port_prefs[i].table_name, uval, handle);
5731 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));
5732 }
5733 }
5734 }
5735
5736 return true1;
5737 }
5738 }
5739
5740 for (i = 0; i < array_length(port_range_prefs)(sizeof (port_range_prefs) / sizeof (port_range_prefs)[0]); i++)
5741 {
5742 if (strcmp(pref_name, port_range_prefs[i].pref_name) == 0)
5743 {
5744 uint32_t range_i, range_j;
5745
5746 sub_dissectors = find_dissector_table(port_range_prefs[i].table_name);
5747 if (sub_dissectors != NULL((void*)0)) {
5748 switch (dissector_table_get_type(sub_dissectors)) {
5749 case FT_UINT8:
5750 case FT_UINT16:
5751 case FT_UINT24:
5752 case FT_UINT32:
5753 break;
5754
5755 default:
5756 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", 5756
, __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))
;
5757 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 5757
, __func__, "assertion \"not reached\" failed")
;
5758 }
5759
5760 module = prefs_find_module(port_range_prefs[i].module_name);
5761 pref = prefs_find_preference(module, port_range_prefs[i].table_name);
5762 if (pref != NULL((void*)0))
5763 {
5764 if (!prefs_set_range_value_work(pref, value, true1, &module->prefs_changed_flags))
5765 {
5766 return false0; /* number was bad */
5767 }
5768
5769 handle = dissector_table_get_dissector_handle(sub_dissectors, module->title);
5770 if (handle != NULL((void*)0)) {
5771
5772 for (range_i = 0; range_i < (*pref->varp.range)->nranges; range_i++) {
5773 for (range_j = (*pref->varp.range)->ranges[range_i].low; range_j < (*pref->varp.range)->ranges[range_i].high; range_j++) {
5774 dissector_change_uint(port_range_prefs[i].table_name, range_j, handle);
5775 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));
5776 }
5777
5778 dissector_change_uint(port_range_prefs[i].table_name, (*pref->varp.range)->ranges[range_i].high, handle);
5779 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));
5780 }
5781 }
5782 }
5783 }
5784
5785 return true1;
5786 }
5787 }
5788
5789 for (i = 0; i < array_length(tpkt_subdissector_port_prefs)(sizeof (tpkt_subdissector_port_prefs) / sizeof (tpkt_subdissector_port_prefs
)[0])
; i++)
5790 {
5791 if (strcmp(pref_name, tpkt_subdissector_port_prefs[i].pref_name) == 0)
5792 {
5793 /* XXX - give an error if it doesn't fit in a unsigned? */
5794 if (!ws_basestrtou32(value, NULL((void*)0), &uval, tpkt_subdissector_port_prefs[i].base))
5795 return false0; /* number was bad */
5796
5797 /* If the value is 0 or 102 (default TPKT port), don't add to the Decode As tables */
5798 if ((uval != 0) && (uval != 102))
5799 {
5800 tpkt_handle = find_dissector("tpkt");
5801 if (tpkt_handle != NULL((void*)0)) {
5802 dissector_change_uint(tpkt_subdissector_port_prefs[i].table_name, uval, tpkt_handle);
5803 }
5804 }
5805
5806 return true1;
5807 }
5808 }
5809
5810 for (i = 0; i < array_length(obsolete_prefs)(sizeof (obsolete_prefs) / sizeof (obsolete_prefs)[0]); i++)
5811 {
5812 if (strcmp(pref_name, obsolete_prefs[i].pref_name) == 0)
5813 {
5814 /* Just ignore the preference */
5815 return true1;
5816 }
5817 }
5818 return false0;
5819}
5820
5821static prefs_set_pref_e
5822set_pref(char *pref_name, const char *value, void *private_data,
5823 bool_Bool return_range_errors)
5824{
5825 unsigned cval;
5826 unsigned uval;
5827 bool_Bool bval;
5828 int enum_val;
5829 char *dotp, *last_dotp;
5830 static char *filter_label = NULL((void*)0);
5831 static bool_Bool filter_enabled = false0;
5832 module_t *module, *containing_module, *target_module;
5833 pref_t *pref;
5834 bool_Bool converted_pref = false0;
5835
5836 target_module = (module_t*)private_data;
5837
5838 //The PRS_GUI field names are here for backwards compatibility
5839 //display filters have been converted to a UAT.
5840 if (strcmp(pref_name, PRS_GUI_FILTER_LABEL"gui.filter_expressions.label") == 0) {
5841 /* Assume that PRS_GUI_FILTER_EXPR follows this preference. In case of
5842 * malicious preference files, free the previous value to limit the size
5843 * of leaked memory. */
5844 g_free(filter_label);
5845 filter_label = g_strdup(value)g_strdup_inline (value);
5846 } else if (strcmp(pref_name, PRS_GUI_FILTER_ENABLED"gui.filter_expressions.enabled") == 0) {
5847 filter_enabled = (strcmp(value, "TRUE") == 0) ? true1 : false0;
5848 } else if (strcmp(pref_name, PRS_GUI_FILTER_EXPR"gui.filter_expressions.expr") == 0) {
5849 /* Comments not supported for "old" preference style */
5850 filter_expression_new(filter_label, value, "", filter_enabled);
5851 g_free(filter_label);
5852 filter_label = NULL((void*)0);
5853 /* Remember to save the new UAT to file. */
5854 prefs.filter_expressions_old = true1;
5855 } else if (strcmp(pref_name, "gui.version_in_start_page") == 0) {
5856 /* Convert deprecated value to closest current equivalent */
5857 if (g_ascii_strcasecmp(value, "true") == 0) {
5858 prefs.gui_version_placement = version_both;
5859 } else {
5860 prefs.gui_version_placement = version_neither;
5861 }
5862 } else if (strcmp(pref_name, "name_resolve") == 0 ||
5863 strcmp(pref_name, "capture.name_resolve") == 0) {
5864 /*
5865 * Handle the deprecated name resolution options.
5866 *
5867 * "TRUE" and "FALSE", for backwards compatibility, are synonyms for
5868 * RESOLV_ALL and RESOLV_NONE.
5869 *
5870 * Otherwise, we treat it as a list of name types we want to resolve.
5871 */
5872 if (g_ascii_strcasecmp(value, "true") == 0) {
5873 gbl_resolv_flags.mac_name = true1;
5874 gbl_resolv_flags.network_name = true1;
5875 gbl_resolv_flags.transport_name = true1;
5876 }
5877 else if (g_ascii_strcasecmp(value, "false") == 0) {
5878 disable_name_resolution();
5879 }
5880 else {
5881 /* start out with none set */
5882 disable_name_resolution();
5883 if (string_to_name_resolve(value, &gbl_resolv_flags) != '\0')
5884 return PREFS_SET_SYNTAX_ERR;
5885 }
5886 } else if (deprecated_heur_dissector_pref(pref_name, value)) {
5887 /* Handled within deprecated_heur_dissector_pref() if found */
5888 } else if (deprecated_enable_dissector_pref(pref_name, value)) {
5889 /* Handled within deprecated_enable_dissector_pref() if found */
5890 } else if (deprecated_port_pref(pref_name, value)) {
5891 /* Handled within deprecated_port_pref() if found */
5892 } else if (strcmp(pref_name, "console.log.level") == 0) {
5893 /* Handled on the command line within ws_log_parse_args() */
5894 return PREFS_SET_OK;
5895 } else {
5896 /* Handle deprecated "global" options that don't have a module
5897 * associated with them
5898 */
5899 if ((strcmp(pref_name, "name_resolve_concurrency") == 0) ||
5900 (strcmp(pref_name, "name_resolve_load_smi_modules") == 0) ||
5901 (strcmp(pref_name, "name_resolve_suppress_smi_errors") == 0)) {
5902 module = nameres_module;
5903 dotp = pref_name;
5904 } else {
5905 /* To which module does this preference belong? */
5906 module = NULL((void*)0);
5907 last_dotp = pref_name;
5908 while (!module) {
5909 dotp = strchr(last_dotp, '.');
5910 if (dotp == NULL((void*)0)) {
5911 /* Either there's no such module, or no module was specified.
5912 In either case, that means there's no such preference. */
5913 return PREFS_SET_NO_SUCH_PREF;
5914 }
5915 *dotp = '\0'; /* separate module and preference name */
5916 module = prefs_find_module(pref_name);
5917
5918 /*
5919 * XXX - "Diameter" rather than "diameter" was used in earlier
5920 * versions of Wireshark; if we didn't find the module, and its name
5921 * was "Diameter", look for "diameter" instead.
5922 *
5923 * In addition, the BEEP protocol used to be the BXXP protocol,
5924 * so if we didn't find the module, and its name was "bxxp",
5925 * look for "beep" instead.
5926 *
5927 * Also, the preferences for GTP v0 and v1 were combined under
5928 * a single "gtp" heading, and the preferences for SMPP were
5929 * moved to "smpp-gsm-sms" and then moved to "gsm-sms-ud".
5930 * However, SMPP now has its own preferences, so we just map
5931 * "smpp-gsm-sms" to "gsm-sms-ud", and then handle SMPP below.
5932 *
5933 * We also renamed "dcp" to "dccp", "x.25" to "x25", "x411" to "p1"
5934 * and "nsip" to "gprs_ns".
5935 *
5936 * The SynOptics Network Management Protocol (SONMP) is now known by
5937 * its modern name, the Nortel Discovery Protocol (NDP).
5938 */
5939 if (module == NULL((void*)0)) {
5940 /*
5941 * See if there's a backwards-compatibility name
5942 * that maps to this module.
5943 */
5944 module = prefs_find_module_alias(pref_name);
5945 if (module == NULL((void*)0)) {
5946 /*
5947 * There's no alias for the module; see if the
5948 * module name matches any protocol aliases.
5949 */
5950 header_field_info *hfinfo = proto_registrar_get_byalias(pref_name);
5951 if (hfinfo) {
5952 module = (module_t *) wmem_tree_lookup_string(prefs_modules, hfinfo->abbrev, WMEM_TREE_STRING_NOCASE0x00000001);
5953 }
5954 }
5955 if (module == NULL((void*)0)) {
5956 /*
5957 * There aren't any aliases. Was the module
5958 * removed rather than renamed?
5959 */
5960 if (strcmp(pref_name, "etheric") == 0 ||
5961 strcmp(pref_name, "isup_thin") == 0) {
5962 /*
5963 * The dissectors for these protocols were
5964 * removed as obsolete on 2009-07-70 in change
5965 * 739bfc6ff035583abb9434e0e988048de38a8d9a.
5966 */
5967 return PREFS_SET_OBSOLETE;
5968 }
5969 }
5970 if (module) {
5971 converted_pref = true1;
5972 prefs.unknown_prefs = true1;
5973 }
5974 }
5975 *dotp = '.'; /* put the preference string back */
5976 dotp++; /* skip past separator to preference name */
5977 last_dotp = dotp;
5978 }
5979 }
5980
5981 /* The pref is located in the module or a submodule.
5982 * Assume module, then search for a submodule holding the pref. */
5983 containing_module = module;
5984 pref = prefs_find_preference_with_submodule(module, dotp, &containing_module);
5985
5986 if (pref == NULL((void*)0)) {
5987 prefs.unknown_prefs = true1;
5988
5989 /* "gui" prefix was added to column preferences for better organization
5990 * within the preferences file
5991 */
5992 if (module == gui_column_module) {
5993 /* While this has a subtree, there is no apply callback, so no
5994 * need to use prefs_find_preference_with_submodule to update
5995 * containing_module. It would not be useful. */
5996 pref = prefs_find_preference(module, pref_name);
5997 }
5998 else if (strcmp(module->name, "mgcp") == 0) {
5999 /*
6000 * XXX - "mgcp.display raw text toggle" and "mgcp.display dissect tree"
6001 * rather than "mgcp.display_raw_text" and "mgcp.display_dissect_tree"
6002 * were used in earlier versions of Wireshark; if we didn't find the
6003 * preference, it was an MGCP preference, and its name was
6004 * "display raw text toggle" or "display dissect tree", look for
6005 * "display_raw_text" or "display_dissect_tree" instead.
6006 *
6007 * "mgcp.tcp.port" and "mgcp.udp.port" are harder to handle, as both
6008 * the gateway and callagent ports were given those names; we interpret
6009 * the first as "mgcp.{tcp,udp}.gateway_port" and the second as
6010 * "mgcp.{tcp,udp}.callagent_port", as that's the order in which
6011 * they were registered by the MCCP dissector and thus that's the
6012 * order in which they were written to the preferences file. (If
6013 * we're not reading the preferences file, but are handling stuff
6014 * from a "-o" command-line option, we have no clue which the user
6015 * had in mind - they should have used "mgcp.{tcp,udp}.gateway_port"
6016 * or "mgcp.{tcp,udp}.callagent_port" instead.)
6017 */
6018 if (strcmp(dotp, "display raw text toggle") == 0)
6019 pref = prefs_find_preference(module, "display_raw_text");
6020 else if (strcmp(dotp, "display dissect tree") == 0)
6021 pref = prefs_find_preference(module, "display_dissect_tree");
6022 else if (strcmp(dotp, "tcp.port") == 0) {
6023 mgcp_tcp_port_count++;
6024 if (mgcp_tcp_port_count == 1) {
6025 /* It's the first one */
6026 pref = prefs_find_preference(module, "tcp.gateway_port");
6027 } else if (mgcp_tcp_port_count == 2) {
6028 /* It's the second one */
6029 pref = prefs_find_preference(module, "tcp.callagent_port");
6030 }
6031 /* Otherwise it's from the command line, and we don't bother
6032 mapping it. */
6033 } else if (strcmp(dotp, "udp.port") == 0) {
6034 mgcp_udp_port_count++;
6035 if (mgcp_udp_port_count == 1) {
6036 /* It's the first one */
6037 pref = prefs_find_preference(module, "udp.gateway_port");
6038 } else if (mgcp_udp_port_count == 2) {
6039 /* It's the second one */
6040 pref = prefs_find_preference(module, "udp.callagent_port");
6041 }
6042 /* Otherwise it's from the command line, and we don't bother
6043 mapping it. */
6044 }
6045 } else if (strcmp(module->name, "smb") == 0) {
6046 /* Handle old names for SMB preferences. */
6047 if (strcmp(dotp, "smb.trans.reassembly") == 0)
6048 pref = prefs_find_preference(module, "trans_reassembly");
6049 else if (strcmp(dotp, "smb.dcerpc.reassembly") == 0)
6050 pref = prefs_find_preference(module, "dcerpc_reassembly");
6051 } else if (strcmp(module->name, "ndmp") == 0) {
6052 /* Handle old names for NDMP preferences. */
6053 if (strcmp(dotp, "ndmp.desegment") == 0)
6054 pref = prefs_find_preference(module, "desegment");
6055 } else if (strcmp(module->name, "diameter") == 0) {
6056 /* Handle old names for Diameter preferences. */
6057 if (strcmp(dotp, "diameter.desegment") == 0)
6058 pref = prefs_find_preference(module, "desegment");
6059 } else if (strcmp(module->name, "pcli") == 0) {
6060 /* Handle old names for PCLI preferences. */
6061 if (strcmp(dotp, "pcli.udp_port") == 0)
6062 pref = prefs_find_preference(module, "udp_port");
6063 } else if (strcmp(module->name, "artnet") == 0) {
6064 /* Handle old names for ARTNET preferences. */
6065 if (strcmp(dotp, "artnet.udp_port") == 0)
6066 pref = prefs_find_preference(module, "udp_port");
6067 } else if (strcmp(module->name, "mapi") == 0) {
6068 /* Handle old names for MAPI preferences. */
6069 if (strcmp(dotp, "mapi_decrypt") == 0)
6070 pref = prefs_find_preference(module, "decrypt");
6071 } else if (strcmp(module->name, "fc") == 0) {
6072 /* Handle old names for Fibre Channel preferences. */
6073 if (strcmp(dotp, "reassemble_fc") == 0)
6074 pref = prefs_find_preference(module, "reassemble");
6075 else if (strcmp(dotp, "fc_max_frame_size") == 0)
6076 pref = prefs_find_preference(module, "max_frame_size");
6077 } else if (strcmp(module->name, "fcip") == 0) {
6078 /* Handle old names for Fibre Channel-over-IP preferences. */
6079 if (strcmp(dotp, "desegment_fcip_messages") == 0)
6080 pref = prefs_find_preference(module, "desegment");
6081 else if (strcmp(dotp, "fcip_port") == 0)
6082 pref = prefs_find_preference(module, "target_port");
6083 } else if (strcmp(module->name, "gtp") == 0) {
6084 /* Handle old names for GTP preferences. */
6085 if (strcmp(dotp, "gtpv0_port") == 0)
6086 pref = prefs_find_preference(module, "v0_port");
6087 else if (strcmp(dotp, "gtpv1c_port") == 0)
6088 pref = prefs_find_preference(module, "v1c_port");
6089 else if (strcmp(dotp, "gtpv1u_port") == 0)
6090 pref = prefs_find_preference(module, "v1u_port");
6091 else if (strcmp(dotp, "gtp_dissect_tpdu") == 0)
6092 pref = prefs_find_preference(module, "dissect_tpdu");
6093 else if (strcmp(dotp, "gtpv0_dissect_cdr_as") == 0)
6094 pref = prefs_find_preference(module, "v0_dissect_cdr_as");
6095 else if (strcmp(dotp, "gtpv0_check_etsi") == 0)
6096 pref = prefs_find_preference(module, "v0_check_etsi");
6097 else if (strcmp(dotp, "gtpv1_check_etsi") == 0)
6098 pref = prefs_find_preference(module, "v1_check_etsi");
6099 } else if (strcmp(module->name, "ip") == 0) {
6100 /* Handle old names for IP preferences. */
6101 if (strcmp(dotp, "ip_summary_in_tree") == 0)
6102 pref = prefs_find_preference(module, "summary_in_tree");
6103 } else if (strcmp(module->name, "iscsi") == 0) {
6104 /* Handle old names for iSCSI preferences. */
6105 if (strcmp(dotp, "iscsi_port") == 0)
6106 pref = prefs_find_preference(module, "target_port");
6107 } else if (strcmp(module->name, "lmp") == 0) {
6108 /* Handle old names for LMP preferences. */
6109 if (strcmp(dotp, "lmp_version") == 0)
6110 pref = prefs_find_preference(module, "version");
6111 } else if (strcmp(module->name, "mtp3") == 0) {
6112 /* Handle old names for MTP3 preferences. */
6113 if (strcmp(dotp, "mtp3_standard") == 0)
6114 pref = prefs_find_preference(module, "standard");
6115 else if (strcmp(dotp, "net_addr_format") == 0)
6116 pref = prefs_find_preference(module, "addr_format");
6117 } else if (strcmp(module->name, "nlm") == 0) {
6118 /* Handle old names for NLM preferences. */
6119 if (strcmp(dotp, "nlm_msg_res_matching") == 0)
6120 pref = prefs_find_preference(module, "msg_res_matching");
6121 } else if (strcmp(module->name, "ppp") == 0) {
6122 /* Handle old names for PPP preferences. */
6123 if (strcmp(dotp, "ppp_fcs") == 0)
6124 pref = prefs_find_preference(module, "fcs_type");
6125 else if (strcmp(dotp, "ppp_vj") == 0)
6126 pref = prefs_find_preference(module, "decompress_vj");
6127 } else if (strcmp(module->name, "rsvp") == 0) {
6128 /* Handle old names for RSVP preferences. */
6129 if (strcmp(dotp, "rsvp_process_bundle") == 0)
6130 pref = prefs_find_preference(module, "process_bundle");
6131 } else if (strcmp(module->name, "tcp") == 0) {
6132 /* Handle old names for TCP preferences. */
6133 if (strcmp(dotp, "tcp_summary_in_tree") == 0)
6134 pref = prefs_find_preference(module, "summary_in_tree");
6135 else if (strcmp(dotp, "tcp_analyze_sequence_numbers") == 0)
6136 pref = prefs_find_preference(module, "analyze_sequence_numbers");
6137 else if (strcmp(dotp, "tcp_relative_sequence_numbers") == 0)
6138 pref = prefs_find_preference(module, "relative_sequence_numbers");
6139 else if (strcmp(dotp, "dissect_experimental_options_with_magic") == 0)
6140 pref = prefs_find_preference(module, "dissect_experimental_options_rfc6994");
6141 } else if (strcmp(module->name, "udp") == 0) {
6142 /* Handle old names for UDP preferences. */
6143 if (strcmp(dotp, "udp_summary_in_tree") == 0)
6144 pref = prefs_find_preference(module, "summary_in_tree");
6145 } else if (strcmp(module->name, "ndps") == 0) {
6146 /* Handle old names for NDPS preferences. */
6147 if (strcmp(dotp, "desegment_ndps") == 0)
6148 pref = prefs_find_preference(module, "desegment_tcp");
6149 } else if (strcmp(module->name, "http") == 0) {
6150 /* Handle old names for HTTP preferences. */
6151 if (strcmp(dotp, "desegment_http_headers") == 0)
6152 pref = prefs_find_preference(module, "desegment_headers");
6153 else if (strcmp(dotp, "desegment_http_body") == 0)
6154 pref = prefs_find_preference(module, "desegment_body");
6155 } else if (strcmp(module->name, "smpp") == 0) {
6156 /* Handle preferences that moved from SMPP. */
6157 module_t *new_module = prefs_find_module("gsm-sms-ud");
6158 if (new_module) {
6159 if (strcmp(dotp, "port_number_udh_means_wsp") == 0) {
6160 pref = prefs_find_preference(new_module, "port_number_udh_means_wsp");
6161 containing_module = new_module;
6162 } else if (strcmp(dotp, "try_dissect_1st_fragment") == 0) {
6163 pref = prefs_find_preference(new_module, "try_dissect_1st_fragment");
6164 containing_module = new_module;
6165 }
6166 }
6167 } else if (strcmp(module->name, "asn1") == 0) {
6168 /* Handle old generic ASN.1 preferences (it's not really a
6169 rename, as the new preferences support multiple ports,
6170 but we might as well copy them over). */
6171 if (strcmp(dotp, "tcp_port") == 0)
6172 pref = prefs_find_preference(module, "tcp_ports");
6173 else if (strcmp(dotp, "udp_port") == 0)
6174 pref = prefs_find_preference(module, "udp_ports");
6175 else if (strcmp(dotp, "sctp_port") == 0)
6176 pref = prefs_find_preference(module, "sctp_ports");
6177 } else if (strcmp(module->name, "llcgprs") == 0) {
6178 if (strcmp(dotp, "ignore_cipher_bit") == 0)
6179 pref = prefs_find_preference(module, "autodetect_cipher_bit");
6180 } else if (strcmp(module->name, "erf") == 0) {
6181 if (strcmp(dotp, "erfeth") == 0) {
6182 /* Handle the old "erfeth" preference; map it to the new
6183 "ethfcs" preference, and map the values to those for
6184 the new preference. */
6185 pref = prefs_find_preference(module, "ethfcs");
6186 if (strcmp(value, "ethfcs") == 0 || strcmp(value, "Ethernet with FCS") == 0)
6187 value = "TRUE";
6188 else if (strcmp(value, "eth") == 0 || strcmp(value, "Ethernet") == 0)
6189 value = "FALSE";
6190 else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
6191 value = "TRUE";
6192 } else if (strcmp(dotp, "erfatm") == 0) {
6193 /* Handle the old "erfatm" preference; map it to the new
6194 "aal5_type" preference, and map the values to those for
6195 the new preference. */
6196 pref = prefs_find_preference(module, "aal5_type");
6197 if (strcmp(value, "atm") == 0 || strcmp(value, "ATM") == 0)
6198 value = "guess";
6199 else if (strcmp(value, "llc") == 0 || strcmp(value, "LLC") == 0)
6200 value = "llc";
6201 else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
6202 value = "guess";
6203 } else if (strcmp(dotp, "erfhdlc") == 0) {
6204 /* Handle the old "erfhdlc" preference; map it to the new
6205 "hdlc_type" preference, and map the values to those for
6206 the new preference. */
6207 pref = prefs_find_preference(module, "hdlc_type");
6208 if (strcmp(value, "chdlc") == 0 || strcmp(value, "Cisco HDLC") == 0)
6209 value = "chdlc";
6210 else if (strcmp(value, "ppp") == 0 || strcmp(value, "PPP serial") == 0)
6211 value = "ppp";
6212 else if (strcmp(value, "fr") == 0 || strcmp(value, "Frame Relay") == 0)
6213 value = "frelay";
6214 else if (strcmp(value, "mtp2") == 0 || strcmp(value, "SS7 MTP2") == 0)
6215 value = "mtp2";
6216 else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
6217 value = "guess";
6218 }
6219 } else if (strcmp(module->name, "eth") == 0) {
6220 /* "eth.qinq_ethertype" has been changed(restored) to "vlan.qinq.ethertype" */
6221 if (strcmp(dotp, "qinq_ethertype") == 0) {
6222 module_t *new_module = prefs_find_module("vlan");
6223 if (new_module) {
6224 pref = prefs_find_preference(new_module, "qinq_ethertype");
6225 containing_module = new_module;
6226 }
6227 }
6228 } else if (strcmp(module->name, "taps") == 0) {
6229 /* taps preferences moved to "statistics" module */
6230 if (strcmp(dotp, "update_interval") == 0)
6231 pref = prefs_find_preference(stats_module, dotp);
6232 } else if (strcmp(module->name, "packet_list") == 0) {
6233 /* packet_list preferences moved to protocol module */
6234 if (strcmp(dotp, "display_hidden_proto_items") == 0)
6235 pref = prefs_find_preference(protocols_module, dotp);
6236 } else if (strcmp(module->name, "stream") == 0) {
6237 /* stream preferences moved to gui color module */
6238 if ((strcmp(dotp, "client.fg") == 0) ||
6239 (strcmp(dotp, "client.bg") == 0) ||
6240 (strcmp(dotp, "server.fg") == 0) ||
6241 (strcmp(dotp, "server.bg") == 0))
6242 pref = prefs_find_preference(gui_color_module, pref_name);
6243 } else if (strcmp(module->name, "nameres") == 0) {
6244 if (strcmp(pref_name, "name_resolve_concurrency") == 0) {
6245 pref = prefs_find_preference(nameres_module, pref_name);
6246 } else if (strcmp(pref_name, "name_resolve_load_smi_modules") == 0) {
6247 pref = prefs_find_preference(nameres_module, "load_smi_modules");
6248 } else if (strcmp(pref_name, "name_resolve_suppress_smi_errors") == 0) {
6249 pref = prefs_find_preference(nameres_module, "suppress_smi_errors");
6250 }
6251 } else if (strcmp(module->name, "extcap") == 0) {
6252 /* Handle the old "sshdump.remotesudo" preference; map it to the new
6253 "sshdump.remotepriv" preference, and map the boolean values to the
6254 appropriate strings of the new preference. */
6255 if (strcmp(dotp, "sshdump.remotesudo") == 0) {
6256 pref = prefs_find_preference(module, "sshdump.remotepriv");
6257 if (g_ascii_strcasecmp(value, "true") == 0)
6258 value = "sudo";
6259 else
6260 value = "none";
6261 }
6262 }
6263 if (pref) {
6264 converted_pref = true1;
6265 }
6266 }
6267 if (pref == NULL((void*)0) ) {
6268 if (strcmp(module->name, "extcap") == 0 && g_list_length(module->prefs) <= 1) {
6269 /*
6270 * Assume that we've skipped extcap preference registration
6271 * and that only extcap.gui_save_on_start is loaded.
6272 */
6273 return PREFS_SET_OK;
6274 }
6275 return PREFS_SET_NO_SUCH_PREF; /* no such preference */
6276 }
6277
6278 if (target_module && target_module != containing_module) {
6279 /* Ignore */
6280 return PREFS_SET_OK;
6281 }
6282
6283 if (pref->obsolete)
6284 return PREFS_SET_OBSOLETE; /* no such preference any more */
6285
6286 if (converted_pref) {
6287 ws_warning("Preference \"%s\" has been converted to \"%s.%s\"\n"do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 6289, __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 "Save your preferences to make this change permanent.",do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 6289, __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 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"
, 6289, __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)
;
6290 }
6291
6292 switch (pref->type) {
6293
6294 case PREF_UINT:
6295 if (!ws_basestrtou32(value, NULL((void*)0), &uval, pref->info.base))
6296 return PREFS_SET_SYNTAX_ERR; /* number was bad */
6297 if (*pref->varp.uint != uval) {
6298 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
6299 *pref->varp.uint = uval;
6300 }
6301 break;
6302 case PREF_BOOL:
6303 /* XXX - give an error if it's neither "true" nor "false"? */
6304 if (g_ascii_strcasecmp(value, "true") == 0)
6305 bval = true1;
6306 else
6307 bval = false0;
6308 if (*pref->varp.boolp != bval) {
6309 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
6310 *pref->varp.boolp = bval;
6311 }
6312 break;
6313
6314 case PREF_ENUM:
6315 /* XXX - give an error if it doesn't match? */
6316 enum_val = find_val_for_string(value, pref->info.enum_info.enumvals,
6317 *pref->varp.enump);
6318 if (*pref->varp.enump != enum_val) {
6319 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
6320 *pref->varp.enump = enum_val;
6321 }
6322 break;
6323
6324 case PREF_STRING:
6325 case PREF_SAVE_FILENAME:
6326 case PREF_OPEN_FILENAME:
6327 case PREF_DIRNAME:
6328 case PREF_DISSECTOR:
6329 containing_module->prefs_changed_flags |= prefs_set_string_value(pref, value, pref_current);
6330 break;
6331
6332 case PREF_PASSWORD:
6333 /* Read value is every time empty */
6334 containing_module->prefs_changed_flags |= prefs_set_string_value(pref, "", pref_current);
6335 break;
6336
6337 case PREF_RANGE:
6338 {
6339 if (!prefs_set_range_value_work(pref, value, return_range_errors,
6340 &containing_module->prefs_changed_flags))
6341 return PREFS_SET_SYNTAX_ERR; /* number was bad */
6342 break;
6343 }
6344 case PREF_DECODE_AS_RANGE:
6345 {
6346 /* This is for backwards compatibility in case any of the preferences
6347 that shared the "Decode As" preference name and used to be PREF_RANGE
6348 are now applied directly to the Decode As functionality */
6349 range_t *newrange;
6350 dissector_table_t sub_dissectors;
6351 dissector_handle_t handle;
6352 uint32_t i, j;
6353
6354 if (range_convert_str_work(wmem_epan_scope(), &newrange, value, pref->info.max_value,
6355 return_range_errors) != CVT_NO_ERROR) {
6356 return PREFS_SET_SYNTAX_ERR; /* number was bad */
6357 }
6358
6359 if (!ranges_are_equal(*pref->varp.range, newrange)) {
6360 wmem_free(wmem_epan_scope(), *pref->varp.range);
6361 *pref->varp.range = newrange;
6362 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
6363
6364 const char* table_name = prefs_get_dissector_table(pref);
6365 sub_dissectors = find_dissector_table(table_name);
6366 if (sub_dissectors != NULL((void*)0)) {
6367 handle = dissector_table_get_dissector_handle(sub_dissectors, module->title);
6368 if (handle != NULL((void*)0)) {
6369 /* Delete all of the old values from the dissector table */
6370 for (i = 0; i < (*pref->varp.range)->nranges; i++) {
6371 for (j = (*pref->varp.range)->ranges[i].low; j < (*pref->varp.range)->ranges[i].high; j++) {
6372 dissector_delete_uint(table_name, j, handle);
6373 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));
6374 }
6375
6376 dissector_delete_uint(table_name, (*pref->varp.range)->ranges[i].high, handle);
6377 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));
6378 }
6379
6380 /* Add new values to the dissector table */
6381 for (i = 0; i < newrange->nranges; i++) {
6382 for (j = newrange->ranges[i].low; j < newrange->ranges[i].high; j++) {
6383 dissector_change_uint(table_name, j, handle);
6384 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));
6385 }
6386
6387 dissector_change_uint(table_name, newrange->ranges[i].high, handle);
6388 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));
6389 }
6390
6391 /* XXX - Do we save the decode_as_entries file here? */
6392 }
6393 }
6394 } else {
6395 wmem_free(wmem_epan_scope(), newrange);
6396 }
6397 break;
6398 }
6399
6400 case PREF_COLOR:
6401 {
6402 if (!ws_hexstrtou32(value, NULL((void*)0), &cval))
6403 return PREFS_SET_SYNTAX_ERR; /* number was bad */
6404 if ((pref->varp.colorp->red != RED_COMPONENT(cval)(uint16_t) (((((cval) >> 16) & 0xff) * 65535 / 255)
)
) ||
6405 (pref->varp.colorp->green != GREEN_COMPONENT(cval)(uint16_t) (((((cval) >> 8) & 0xff) * 65535 / 255))) ||
6406 (pref->varp.colorp->blue != BLUE_COMPONENT(cval)(uint16_t) ( (((cval) & 0xff) * 65535 / 255)))) {
6407 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
6408 pref->varp.colorp->red = RED_COMPONENT(cval)(uint16_t) (((((cval) >> 16) & 0xff) * 65535 / 255)
)
;
6409 pref->varp.colorp->green = GREEN_COMPONENT(cval)(uint16_t) (((((cval) >> 8) & 0xff) * 65535 / 255));
6410 pref->varp.colorp->blue = BLUE_COMPONENT(cval)(uint16_t) ( (((cval) & 0xff) * 65535 / 255));
6411 }
6412 break;
6413 }
6414
6415 case PREF_CUSTOM:
6416 return pref->custom_cbs.set_cb(pref, value, &containing_module->prefs_changed_flags);
6417
6418 case PREF_STATIC_TEXT:
6419 case PREF_UAT:
6420 break;
6421
6422 case PREF_PROTO_TCP_SNDAMB_ENUM:
6423 {
6424 /* There's no point in setting the TCP sequence override
6425 * value from the command line, because the pref is different
6426 * for each frame and reset to the default (0) for each new
6427 * file.
6428 */
6429 break;
6430 }
6431 }
6432 }
6433
6434 return PREFS_SET_OK;
6435}
6436
6437typedef struct {
6438 FILE *pf;
6439 bool_Bool is_gui_module;
6440} write_gui_pref_arg_t;
6441
6442const char *
6443prefs_pref_type_name(pref_t *pref)
6444{
6445 const char *type_name = "[Unknown]";
6446
6447 if (!pref) {
6448 return type_name; /* ...or maybe assert? */
6449 }
6450
6451 if (pref->obsolete) {
6452 type_name = "Obsolete";
6453 } else {
6454 switch (pref->type) {
6455
6456 case PREF_UINT:
6457 switch (pref->info.base) {
6458
6459 case 10:
6460 type_name = "Decimal";
6461 break;
6462
6463 case 8:
6464 type_name = "Octal";
6465 break;
6466
6467 case 16:
6468 type_name = "Hexadecimal";
6469 break;
6470 }
6471 break;
6472
6473 case PREF_BOOL:
6474 type_name = "Boolean";
6475 break;
6476
6477 case PREF_ENUM:
6478 case PREF_PROTO_TCP_SNDAMB_ENUM:
6479 type_name = "Choice";
6480 break;
6481
6482 case PREF_STRING:
6483 type_name = "String";
6484 break;
6485
6486 case PREF_SAVE_FILENAME:
6487 case PREF_OPEN_FILENAME:
6488 type_name = "Filename";
6489 break;
6490
6491 case PREF_DIRNAME:
6492 type_name = "Directory";
6493 break;
6494
6495 case PREF_RANGE:
6496 type_name = "Range";
6497 break;
6498
6499 case PREF_COLOR:
6500 type_name = "Color";
6501 break;
6502
6503 case PREF_CUSTOM:
6504 if (pref->custom_cbs.type_name_cb)
6505 return pref->custom_cbs.type_name_cb();
6506 type_name = "Custom";
6507 break;
6508
6509 case PREF_DECODE_AS_RANGE:
6510 type_name = "Range (for Decode As)";
6511 break;
6512
6513 case PREF_STATIC_TEXT:
6514 type_name = "Static text";
6515 break;
6516
6517 case PREF_UAT:
6518 type_name = "UAT";
6519 break;
6520
6521 case PREF_PASSWORD:
6522 type_name = "Password";
6523 break;
6524
6525 case PREF_DISSECTOR:
6526 type_name = "Dissector";
6527 break;
6528 }
6529 }
6530
6531 return type_name;
6532}
6533
6534unsigned int
6535prefs_get_effect_flags(pref_t *pref)
6536{
6537 if (pref == NULL((void*)0))
6538 return 0;
6539
6540 return pref->effect_flags;
6541}
6542
6543void
6544prefs_set_effect_flags(pref_t *pref, unsigned int flags)
6545{
6546 if (pref != NULL((void*)0)) {
6547 if (flags == 0) {
6548 ws_error("Setting \"%s\" preference effect flags to 0", pref->name)ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 6548
, __func__, "Setting \"%s\" preference effect flags to 0", pref
->name)
;
6549 }
6550 pref->effect_flags = flags;
6551 }
6552}
6553
6554void
6555prefs_set_effect_flags_by_name(module_t * module, const char *pref, unsigned int flags)
6556{
6557 prefs_set_effect_flags(prefs_find_preference(module, pref), flags);
6558}
6559
6560unsigned int
6561prefs_get_module_effect_flags(module_t * module)
6562{
6563 if (module == NULL((void*)0))
6564 return 0;
6565
6566 return module->effect_flags;
6567}
6568
6569void
6570prefs_set_module_effect_flags(module_t * module, unsigned int flags)
6571{
6572 if (module != NULL((void*)0)) {
6573 if (flags == 0) {
6574 ws_error("Setting module \"%s\" preference effect flags to 0", module->name)ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 6574
, __func__, "Setting module \"%s\" preference effect flags to 0"
, module->name)
;
6575 }
6576 module->effect_flags = flags;
6577 }
6578}
6579
6580char *
6581prefs_pref_type_description(pref_t *pref)
6582{
6583 const char *type_desc = "An unknown preference type";
6584
6585 if (!pref) {
6586 return ws_strdup_printf("%s.", type_desc)wmem_strdup_printf(((void*)0), "%s.", type_desc); /* ...or maybe assert? */
6587 }
6588
6589 if (pref->obsolete) {
6590 type_desc = "An obsolete preference";
6591 } else {
6592 switch (pref->type) {
6593
6594 case PREF_UINT:
6595 switch (pref->info.base) {
6596
6597 case 10:
6598 type_desc = "A decimal number";
6599 break;
6600
6601 case 8:
6602 type_desc = "An octal number";
6603 break;
6604
6605 case 16:
6606 type_desc = "A hexadecimal number";
6607 break;
6608 }
6609 break;
6610
6611 case PREF_BOOL:
6612 type_desc = "true or false (case-insensitive)";
6613 break;
6614
6615 case PREF_ENUM:
6616 case PREF_PROTO_TCP_SNDAMB_ENUM:
6617 {
6618 const enum_val_t *enum_valp = pref->info.enum_info.enumvals;
6619 GString *enum_str = g_string_new("One of: ");
6620 GString *desc_str = g_string_new("\nEquivalently, one of: ");
6621 bool_Bool distinct = false0;
6622 while (enum_valp->name != NULL((void*)0)) {
6623 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))
;
6624 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))
;
6625 if (g_strcmp0(enum_valp->name, enum_valp->description) != 0) {
6626 distinct = true1;
6627 }
6628 enum_valp++;
6629 if (enum_valp->name != NULL((void*)0)) {
6630 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))
;
6631 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))
;
6632 }
6633 }
6634 if (distinct) {
6635 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))
;
6636 }
6637 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)))))
;
6638 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))
;
6639 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))))
;
6640 }
6641
6642 case PREF_STRING:
6643 type_desc = "A string";
6644 break;
6645
6646 case PREF_SAVE_FILENAME:
6647 case PREF_OPEN_FILENAME:
6648 type_desc = "A path to a file";
6649 break;
6650
6651 case PREF_DIRNAME:
6652 type_desc = "A path to a directory";
6653 break;
6654
6655 case PREF_RANGE:
6656 {
6657 type_desc = "A string denoting an positive integer range (e.g., \"1-20,30-40\")";
6658 break;
6659 }
6660
6661 case PREF_COLOR:
6662 {
6663 type_desc = "A six-digit hexadecimal RGB color triplet (e.g. fce94f)";
6664 break;
6665 }
6666
6667 case PREF_CUSTOM:
6668 if (pref->custom_cbs.type_description_cb)
6669 return pref->custom_cbs.type_description_cb();
6670 type_desc = "A custom value";
6671 break;
6672
6673 case PREF_DECODE_AS_RANGE:
6674 type_desc = "A string denoting an positive integer range for Decode As";
6675 break;
6676
6677 case PREF_STATIC_TEXT:
6678 type_desc = "[Static text]";
6679 break;
6680
6681 case PREF_UAT:
6682 type_desc = "Configuration data stored in its own file";
6683 break;
6684
6685 case PREF_PASSWORD:
6686 type_desc = "Password (never stored on disk)";
6687 break;
6688
6689 case PREF_DISSECTOR:
6690 type_desc = "A dissector name";
6691 break;
6692
6693 default:
6694 break;
6695 }
6696 }
6697
6698 return g_strdup(type_desc)g_strdup_inline (type_desc);
6699}
6700
6701bool_Bool
6702prefs_pref_is_default(pref_t *pref)
6703{
6704 if (!pref) return false0;
6705
6706 if (pref->obsolete) {
6707 return false0;
6708 }
6709
6710 switch (pref->type) {
6711
6712 case PREF_UINT:
6713 if (pref->default_val.uint == *pref->varp.uint)
6714 return true1;
6715 break;
6716
6717 case PREF_BOOL:
6718 if (pref->default_val.boolval == *pref->varp.boolp)
6719 return true1;
6720 break;
6721
6722 case PREF_ENUM:
6723 case PREF_PROTO_TCP_SNDAMB_ENUM:
6724 if (pref->default_val.enumval == *pref->varp.enump)
6725 return true1;
6726 break;
6727
6728 case PREF_STRING:
6729 case PREF_SAVE_FILENAME:
6730 case PREF_OPEN_FILENAME:
6731 case PREF_DIRNAME:
6732 case PREF_PASSWORD:
6733 case PREF_DISSECTOR:
6734 if (!(g_strcmp0(pref->default_val.string, *pref->varp.string)))
6735 return true1;
6736 break;
6737
6738 case PREF_DECODE_AS_RANGE:
6739 case PREF_RANGE:
6740 {
6741 if ((ranges_are_equal(pref->default_val.range, *pref->varp.range)))
6742 return true1;
6743 break;
6744 }
6745
6746 case PREF_COLOR:
6747 {
6748 if ((pref->default_val.color.red == pref->varp.colorp->red) &&
6749 (pref->default_val.color.green == pref->varp.colorp->green) &&
6750 (pref->default_val.color.blue == pref->varp.colorp->blue))
6751 return true1;
6752 break;
6753 }
6754
6755 case PREF_CUSTOM:
6756 return pref->custom_cbs.is_default_cb(pref);
6757
6758 case PREF_STATIC_TEXT:
6759 case PREF_UAT:
6760 return false0;
6761 /* ws_assert_not_reached(); */
6762 break;
6763 }
6764
6765 return false0;
6766}
6767
6768char *
6769prefs_pref_to_str(pref_t *pref, pref_source_t source)
6770{
6771 const char *pref_text = "[Unknown]";
6772 void *valp; /* pointer to preference value */
6773 color_t *pref_color;
6774 char *tmp_value, *ret_value;
6775
6776 if (!pref) {
6777 return g_strdup(pref_text)g_strdup_inline (pref_text);
6778 }
6779
6780 switch (source) {
6781 case pref_default:
6782 valp = &pref->default_val;
6783 /* valp = &boolval, &enumval, etc. are implied by union property */
6784 pref_color = &pref->default_val.color;
6785 break;
6786 case pref_stashed:
6787 valp = &pref->stashed_val;
6788 /* valp = &boolval, &enumval, etc. are implied by union property */
6789 pref_color = &pref->stashed_val.color;
6790 break;
6791 case pref_current:
6792 valp = pref->varp.uint;
6793 /* valp = boolval, enumval, etc. are implied by union property */
6794 pref_color = pref->varp.colorp;
6795 break;
6796 default:
6797 return g_strdup(pref_text)g_strdup_inline (pref_text);
6798 }
6799
6800 if (pref->obsolete) {
6801 pref_text = "[Obsolete]";
6802 } else {
6803 switch (pref->type) {
6804
6805 case PREF_UINT:
6806 {
6807 unsigned pref_uint = *(unsigned *) valp;
6808 switch (pref->info.base) {
6809
6810 case 10:
6811 return ws_strdup_printf("%u", pref_uint)wmem_strdup_printf(((void*)0), "%u", pref_uint);
6812
6813 case 8:
6814 return ws_strdup_printf("%#o", pref_uint)wmem_strdup_printf(((void*)0), "%#o", pref_uint);
6815
6816 case 16:
6817 return ws_strdup_printf("%#x", pref_uint)wmem_strdup_printf(((void*)0), "%#x", pref_uint);
6818 }
6819 break;
6820 }
6821
6822 case PREF_BOOL:
6823 return g_strdup((*(bool *) valp) ? "TRUE" : "FALSE")g_strdup_inline ((*(_Bool *) valp) ? "TRUE" : "FALSE");
6824
6825 case PREF_ENUM:
6826 case PREF_PROTO_TCP_SNDAMB_ENUM:
6827 {
6828 int pref_enumval = *(int *) valp;
6829 const enum_val_t *enum_valp = pref->info.enum_info.enumvals;
6830 /*
6831 * TODO - We write the "description" value, because the "name" values
6832 * weren't validated to be command line friendly until 5.0, and a few
6833 * of them had to be changed. This allows older versions of Wireshark
6834 * to read preferences that they supported, as we supported either
6835 * the short name or the description when reading the preference files
6836 * or an "-o" option. Once 5.0 is the oldest supported version, switch
6837 * to writing the name below.
6838 */
6839 while (enum_valp->name != NULL((void*)0)) {
6840 if (enum_valp->value == pref_enumval)
6841 return g_strdup(enum_valp->description)g_strdup_inline (enum_valp->description);
6842 enum_valp++;
6843 }
6844 break;
6845 }
6846
6847 case PREF_STRING:
6848 case PREF_SAVE_FILENAME:
6849 case PREF_OPEN_FILENAME:
6850 case PREF_DIRNAME:
6851 case PREF_PASSWORD:
6852 case PREF_DISSECTOR:
6853 return g_strdup(*(const char **) valp)g_strdup_inline (*(const char **) valp);
6854
6855 case PREF_DECODE_AS_RANGE:
6856 case PREF_RANGE:
6857 /* Convert wmem to g_alloc memory */
6858 tmp_value = range_convert_range(NULL((void*)0), *(range_t **) valp);
6859 ret_value = g_strdup(tmp_value)g_strdup_inline (tmp_value);
6860 wmem_free(NULL((void*)0), tmp_value);
6861 return ret_value;
6862
6863 case PREF_COLOR:
6864 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))
6865 (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))
6866 (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))
6867 (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))
;
6868
6869 case PREF_CUSTOM:
6870 if (pref->custom_cbs.to_str_cb)
6871 return pref->custom_cbs.to_str_cb(pref, source == pref_default ? true1 : false0);
6872 pref_text = "[Custom]";
6873 break;
6874
6875 case PREF_STATIC_TEXT:
6876 pref_text = "[Static text]";
6877 break;
6878
6879 case PREF_UAT:
6880 {
6881 uat_t *uat = pref->varp.uat;
6882 if (uat && uat->filename)
6883 return ws_strdup_printf("[Managed in the file \"%s\"]", uat->filename)wmem_strdup_printf(((void*)0), "[Managed in the file \"%s\"]"
, uat->filename)
;
6884 else
6885 pref_text = "[Managed in an unknown file]";
6886 break;
6887 }
6888
6889 default:
6890 break;
6891 }
6892 }
6893
6894 return g_strdup(pref_text)g_strdup_inline (pref_text);
6895}
6896
6897/*
6898 * Write out a single dissector preference.
6899 */
6900static void
6901write_pref(void *data, void *user_data)
6902{
6903 pref_t *pref = (pref_t *)data;
6904 write_pref_arg_t *arg = (write_pref_arg_t *)user_data;
6905 char **desc_lines;
6906 int i;
6907
6908 if (!pref || pref->obsolete) {
6909 /*
6910 * This preference is no longer supported; it's not a
6911 * real preference, so we don't write it out (i.e., we
6912 * treat it as if it weren't found in the list of
6913 * preferences, and we weren't called in the first place).
6914 */
6915 return;
6916 }
6917
6918 switch (pref->type) {
6919
6920 case PREF_STATIC_TEXT:
6921 case PREF_UAT:
6922 /* Nothing to do; don't bother printing the description */
6923 return;
6924 case PREF_DECODE_AS_RANGE:
6925 /* Data is saved through Decode As mechanism and not part of preferences file */
6926 return;
6927 case PREF_PROTO_TCP_SNDAMB_ENUM:
6928 /* Not written to the preference file because the override is only
6929 * for the lifetime of the capture file and there is no single
6930 * value to write.
6931 */
6932 return;
6933 default:
6934 break;
6935 }
6936
6937 if (pref->type != PREF_CUSTOM || pref->custom_cbs.type_name_cb() != NULL((void*)0)) {
6938 /*
6939 * The prefix will either be the module name or the parent
6940 * name if it's a subtree
6941 */
6942 const char *name_prefix = (arg->module->name != NULL((void*)0)) ? arg->module->name : arg->module->parent->name;
6943 char *type_desc, *pref_text;
6944 const char * def_prefix = prefs_pref_is_default(pref) ? "#" : "";
6945
6946 if (pref->type == PREF_CUSTOM)
6947 fprintf(arg->pf, "\n# %s", pref->custom_cbs.type_name_cb());
6948 fprintf(arg->pf, "\n");
6949 if (pref->description &&
6950 (g_ascii_strncasecmp(pref->description,"", 2) != 0)) {
6951 if (pref->type != PREF_CUSTOM) {
6952 /* We get duplicate lines otherwise. */
6953
6954 desc_lines = g_strsplit(pref->description, "\n", 0);
6955 for (i = 0; desc_lines[i] != NULL((void*)0); ++i) {
6956 fprintf(arg->pf, "# %s\n", desc_lines[i]);
6957 }
6958 g_strfreev(desc_lines);
6959 }
6960 } else {
6961 fprintf(arg->pf, "# No description\n");
6962 }
6963
6964 type_desc = prefs_pref_type_description(pref);
6965 desc_lines = g_strsplit(type_desc, "\n", 0);
6966 for (i = 0; desc_lines[i] != NULL((void*)0); ++i) {
6967 fprintf(arg->pf, "# %s\n", desc_lines[i]);
6968 }
6969 g_strfreev(desc_lines);
6970 g_free(type_desc);
6971
6972 pref_text = prefs_pref_to_str(pref, pref_current);
6973 fprintf(arg->pf, "%s%s.%s: ", def_prefix, name_prefix, pref->name);
6974 if (pref->type != PREF_PASSWORD)
6975 {
6976 desc_lines = g_strsplit(pref_text, "\n", 0);
6977 for (i = 0; desc_lines[i] != NULL((void*)0); ++i) {
6978 fprintf(arg->pf, "%s%s\n", i == 0 ? "" : def_prefix, desc_lines[i]);
6979 }
6980 if (i == 0)
6981 fprintf(arg->pf, "\n");
6982 g_strfreev(desc_lines);
6983 } else {
6984 /* We never store password value */
6985 fprintf(arg->pf, "\n");
6986 }
6987 g_free(pref_text);
6988 }
6989
6990}
6991
6992static void
6993count_non_uat_pref(void *data, void *user_data)
6994{
6995 pref_t *pref = (pref_t *)data;
6996 int *arg = (int *)user_data;
6997
6998 switch (pref->type)
6999 {
7000 case PREF_UAT:
7001 case PREF_DECODE_AS_RANGE:
7002 case PREF_PROTO_TCP_SNDAMB_ENUM:
7003 //These types are not written in preference file
7004 break;
7005 default:
7006 (*arg)++;
7007 break;
7008 }
7009}
7010
7011static int num_non_uat_prefs(module_t *module)
7012{
7013 int num = 0;
7014
7015 g_list_foreach(module->prefs, count_non_uat_pref, &num);
7016
7017 return num;
7018}
7019
7020/*
7021 * Write out all preferences for a module.
7022 */
7023static unsigned
7024write_module_prefs(module_t *module, void *user_data)
7025{
7026 write_gui_pref_arg_t *gui_pref_arg = (write_gui_pref_arg_t*)user_data;
7027 write_pref_arg_t arg;
7028
7029 /* The GUI module needs to be explicitly called out so it
7030 can be written out of order */
7031 if ((module == gui_module) && (gui_pref_arg->is_gui_module != true1))
7032 return 0;
7033
7034 /* Write a header for the main modules and GUI sub-modules */
7035 if (((module->parent == NULL((void*)0)) || (module->parent == gui_module)) &&
7036 ((prefs_module_has_submodules(module)) ||
7037 (num_non_uat_prefs(module) > 0) ||
7038 (module->name == NULL((void*)0)))) {
7039 if ((module->name == NULL((void*)0)) && (module->parent != NULL((void*)0))) {
7040 fprintf(gui_pref_arg->pf, "\n####### %s: %s ########\n", module->parent->title, module->title);
7041 } else {
7042 fprintf(gui_pref_arg->pf, "\n####### %s ########\n", module->title);
7043 }
7044 }
7045
7046 arg.module = module;
7047 arg.pf = gui_pref_arg->pf;
7048 g_list_foreach(arg.module->prefs, write_pref, &arg);
7049
7050 if (prefs_module_has_submodules(module))
7051 return prefs_modules_foreach_submodules(module, write_module_prefs, user_data);
7052
7053 return 0;
7054}
7055
7056#ifdef _WIN32
7057static void
7058write_registry(void)
7059{
7060 HKEY hTestKey;
7061 DWORD data;
7062 DWORD data_size;
7063 DWORD ret;
7064
7065 ret = RegCreateKeyExA(HKEY_CURRENT_USER, REG_HKCU_WIRESHARK_KEY"Software\\Wireshark", 0, NULL((void*)0),
7066 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL((void*)0),
7067 &hTestKey, NULL((void*)0));
7068 if (ret != ERROR_SUCCESS) {
7069 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"
, 7069, __func__, "Cannot open HKCU ""Software\\Wireshark"": 0x%lx"
, ret); } } while (0)
;
7070 return;
7071 }
7072
7073 data = ws_log_console_open;
7074 data_size = sizeof(DWORD);
7075 ret = RegSetValueExA(hTestKey, LOG_HKCU_CONSOLE_OPEN"ConsoleOpen", 0, REG_DWORD, (const BYTE *)&data, data_size);
7076 if (ret == ERROR_SUCCESS) {
7077 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"
, 7077, __func__, "Wrote ""ConsoleOpen"" to Windows registry: 0x%lu"
, data); } } while (0)
;
7078 }
7079 else {
7080 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"
, 7080, __func__, "Error writing registry key ""ConsoleOpen"": 0x%lx"
, ret); } } while (0)
;
7081 }
7082
7083 RegCloseKey(hTestKey);
7084}
7085#endif
7086
7087/* Write out "prefs" to the user's preferences file, and return 0.
7088
7089 If the preferences file path is NULL, write to stdout.
7090
7091 If we got an error, stuff a pointer to the path of the preferences file
7092 into "*pf_path_return", and return the errno. */
7093int
7094write_prefs(char **pf_path_return)
7095{
7096 char *pf_path;
7097 FILE *pf;
7098 write_gui_pref_arg_t write_gui_pref_info;
7099
7100#ifdef _WIN32
7101 write_registry();
7102#endif
7103
7104 /* To do:
7105 * - Split output lines longer than MAX_VAL_LEN
7106 * - Create a function for the preference directory check/creation
7107 * so that duplication can be avoided with filter.c
7108 */
7109
7110 if (pf_path_return != NULL((void*)0)) {
7111 pf_path = get_persconffile_path(PF_NAME"preferences", true1);
7112 if ((pf = ws_fopenfopen(pf_path, "w")) == NULL((void*)0)) {
7113 *pf_path_return = pf_path;
7114 return errno(*__errno_location ());
7115 }
7116 g_free(pf_path);
7117 } else {
7118 pf = stdoutstdout;
7119 }
7120
7121 /*
7122 * If the preferences file is being written, be sure to write UAT files
7123 * first that were migrated from the preferences file.
7124 */
7125 if (pf_path_return != NULL((void*)0)) {
7126 if (prefs.filter_expressions_old) {
7127 char *err = NULL((void*)0);
7128 prefs.filter_expressions_old = false0;
7129 if (!uat_save(uat_get_table_by_name("Display expressions"), &err)) {
7130 ws_warning("Unable to save Display expressions: %s", err)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 7130, __func__, "Unable to save Display expressions: %s", err
); } } while (0)
;
7131 g_free(err);
7132 }
7133 }
7134
7135 module_t *extcap_module = prefs_find_module("extcap");
7136 if (extcap_module && !prefs.capture_no_extcap) {
7137 char *ext_path = get_persconffile_path("extcap.cfg", true1);
7138 FILE *extf;
7139 if ((extf = ws_fopenfopen(ext_path, "w")) == NULL((void*)0)) {
7140 if (errno(*__errno_location ()) != EISDIR21) {
7141 ws_warning("Unable to save extcap preferences \"%s\": %s",do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 7142, __func__, "Unable to save extcap preferences \"%s\": %s"
, ext_path, g_strerror((*__errno_location ()))); } } while (0
)
7142 ext_path, g_strerror(errno))do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 7142, __func__, "Unable to save extcap preferences \"%s\": %s"
, ext_path, g_strerror((*__errno_location ()))); } } while (0
)
;
7143 }
7144 g_free(ext_path);
7145 } else {
7146 g_free(ext_path);
7147
7148 fputs("# Extcap configuration file for Wireshark " VERSION"4.7.0" ".\n"
7149 "#\n"
7150 "# This file is regenerated each time preferences are saved within\n"
7151 "# Wireshark. Making manual changes should be safe, however.\n"
7152 "# Preferences that have been commented out have not been\n"
7153 "# changed from their default value.\n", extf);
7154
7155 write_gui_pref_info.pf = extf;
7156 write_gui_pref_info.is_gui_module = false0;
7157
7158 write_module_prefs(extcap_module, &write_gui_pref_info);
7159
7160 fclose(extf);
7161 }
7162 }
7163 }
7164
7165 fputs("# Configuration file for Wireshark " VERSION"4.7.0" ".\n"
7166 "#\n"
7167 "# This file is regenerated each time preferences are saved within\n"
7168 "# Wireshark. Making manual changes should be safe, however.\n"
7169 "# Preferences that have been commented out have not been\n"
7170 "# changed from their default value.\n", pf);
7171
7172 /*
7173 * For "backwards compatibility" the GUI module is written first as it's
7174 * at the top of the file. This is followed by all modules that can't
7175 * fit into the preferences read/write API. Finally the remaining modules
7176 * are written in alphabetical order (including of course the protocol preferences)
7177 */
7178 write_gui_pref_info.pf = pf;
7179 write_gui_pref_info.is_gui_module = true1;
7180
7181 write_module_prefs(gui_module, &write_gui_pref_info);
7182
7183 write_gui_pref_info.is_gui_module = false0;
7184 prefs_modules_foreach_submodules(NULL((void*)0), write_module_prefs, &write_gui_pref_info);
7185
7186 fclose(pf);
7187
7188 /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
7189 an error indication, or maybe write to a new preferences file and
7190 rename that file on top of the old one only if there are not I/O
7191 errors. */
7192 return 0;
7193}
7194
7195/** The col_list is only partly managed by the custom preference API
7196 * because its data is shared between multiple preferences, so
7197 * it's freed here
7198 */
7199static void
7200free_col_info(GList *list)
7201{
7202 fmt_data *cfmt;
7203 GList *list_head = list;
7204
7205 while (list != NULL((void*)0)) {
7206 cfmt = (fmt_data *)list->data;
7207
7208 g_free(cfmt->title);
7209 g_free(cfmt->custom_fields);
7210 g_free(cfmt);
7211 list = g_list_next(list)((list) ? (((GList *)(list))->next) : ((void*)0));
7212 }
7213 g_list_free(list_head);
7214}
7215
7216/*
7217 * Editor modelines
7218 *
7219 * Local Variables:
7220 * c-basic-offset: 4
7221 * tab-width: 8
7222 * indent-tabs-mode: nil
7223 * End:
7224 *
7225 * ex: set shiftwidth=4 tabstop=8 expandtab:
7226 * :indentSize=4:tabSize=8:noTabs=true:
7227 */