Bug Summary

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