Bug Summary

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

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name prefs.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-20/lib/clang/20 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/epan -isystem /builds/wireshark/wireshark/build/epan -isystem /usr/include/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-20/lib/clang/20/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-truncation -Wno-format-nonliteral -Wno-pointer-sign -std=gnu11 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /builds/wireshark/wireshark/sbout/2025-09-11-100357-3933-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 pref->varp.uat->changed = false0;
2272 }
2273 break;
2274 case PREF_STATIC_TEXT:
2275 case PREF_CUSTOM:
2276 break;
2277
2278 default:
2279 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 2279
, __func__, "assertion \"not reached\" failed")
;
2280 break;
2281 }
2282 return 0;
2283}
2284
2285void
2286reset_stashed_pref(pref_t *pref) {
2287
2288 ws_assert(!pref->obsolete)do { if ((1) && !(!pref->obsolete)) ws_log_fatal_full
("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 2288, __func__, "assertion failed: %s"
, "!pref->obsolete"); } while (0)
;
2289
2290 switch (pref->type) {
2291
2292 case PREF_UINT:
2293 pref->stashed_val.uint = pref->default_val.uint;
2294 break;
2295
2296 case PREF_BOOL:
2297 pref->stashed_val.boolval = pref->default_val.boolval;
2298 break;
2299
2300 case PREF_ENUM:
2301 pref->stashed_val.enumval = pref->default_val.enumval;
2302 break;
2303
2304 case PREF_STRING:
2305 case PREF_SAVE_FILENAME:
2306 case PREF_OPEN_FILENAME:
2307 case PREF_DIRNAME:
2308 case PREF_PASSWORD:
2309 case PREF_DISSECTOR:
2310 g_free(pref->stashed_val.string);
2311 pref->stashed_val.string = g_strdup(pref->default_val.string)g_strdup_inline (pref->default_val.string);
2312 break;
2313
2314 case PREF_DECODE_AS_RANGE:
2315 case PREF_RANGE:
2316 wmem_free(wmem_epan_scope(), pref->stashed_val.range);
2317 pref->stashed_val.range = range_copy(wmem_epan_scope(), pref->default_val.range);
2318 break;
2319
2320 case PREF_PROTO_TCP_SNDAMB_ENUM:
2321 if (pref->stashed_val.list != NULL((void*)0)) {
2322 g_list_free(pref->stashed_val.list);
2323 pref->stashed_val.list = NULL((void*)0);
2324 }
2325 break;
2326
2327 case PREF_COLOR:
2328 memcpy(&pref->stashed_val.color, &pref->default_val.color, sizeof(color_t));
2329 break;
2330
2331 case PREF_STATIC_TEXT:
2332 case PREF_UAT:
2333 case PREF_CUSTOM:
2334 break;
2335
2336 default:
2337 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 2337
, __func__, "assertion \"not reached\" failed")
;
2338 break;
2339 }
2340}
2341
2342unsigned
2343pref_clean_stash(pref_t *pref, void *unused _U___attribute__((unused)))
2344{
2345 ws_assert(!pref->obsolete)do { if ((1) && !(!pref->obsolete)) ws_log_fatal_full
("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 2345, __func__, "assertion failed: %s"
, "!pref->obsolete"); } while (0)
;
2346
2347 switch (pref->type) {
2348
2349 case PREF_UINT:
2350 break;
2351
2352 case PREF_BOOL:
2353 break;
2354
2355 case PREF_ENUM:
2356 break;
2357
2358 case PREF_STRING:
2359 case PREF_SAVE_FILENAME:
2360 case PREF_OPEN_FILENAME:
2361 case PREF_DIRNAME:
2362 case PREF_PASSWORD:
2363 case PREF_DISSECTOR:
2364 if (pref->stashed_val.string != NULL((void*)0)) {
2365 g_free(pref->stashed_val.string);
2366 pref->stashed_val.string = NULL((void*)0);
2367 }
2368 break;
2369
2370 case PREF_DECODE_AS_RANGE:
2371 case PREF_RANGE:
2372 if (pref->stashed_val.range != NULL((void*)0)) {
2373 wmem_free(wmem_epan_scope(), pref->stashed_val.range);
2374 pref->stashed_val.range = NULL((void*)0);
2375 }
2376 break;
2377
2378 case PREF_STATIC_TEXT:
2379 case PREF_UAT:
2380 case PREF_COLOR:
2381 case PREF_CUSTOM:
2382 break;
2383
2384 case PREF_PROTO_TCP_SNDAMB_ENUM:
2385 if (pref->stashed_val.list != NULL((void*)0)) {
2386 g_list_free(pref->stashed_val.list);
2387 pref->stashed_val.list = NULL((void*)0);
2388 }
2389 break;
2390
2391 default:
2392 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 2392
, __func__, "assertion \"not reached\" failed")
;
2393 break;
2394 }
2395 return 0;
2396}
2397
2398/*
2399 * Call a callback function, with a specified argument, for each preference
2400 * in a given module.
2401 *
2402 * If any of the callbacks return a non-zero value, stop and return that
2403 * value, otherwise return 0.
2404 */
2405unsigned
2406prefs_pref_foreach(module_t *module, pref_cb callback, void *user_data)
2407{
2408 GList *elem;
2409 pref_t *pref;
2410 unsigned ret;
2411
2412 for (elem = g_list_first(module->prefs); elem != NULL((void*)0); elem = g_list_next(elem)((elem) ? (((GList *)(elem))->next) : ((void*)0))) {
2413 pref = (pref_t *)elem->data;
2414 if (!pref || pref->obsolete) {
2415 /*
2416 * This preference is no longer supported; it's
2417 * not a real preference, so we don't call the
2418 * callback for it (i.e., we treat it as if it
2419 * weren't found in the list of preferences,
2420 * and we weren't called in the first place).
2421 */
2422 continue;
2423 }
2424
2425 ret = (*callback)(pref, user_data);
2426 if (ret != 0)
2427 return ret;
2428 }
2429 return 0;
2430}
2431
2432static const enum_val_t st_sort_col_vals[] = {
2433 { "name", "Node name (topic/item)", ST_SORT_COL_NAME1 },
2434 { "count", "Item count", ST_SORT_COL_COUNT2 },
2435 { "average", "Average value of the node", ST_SORT_COL_AVG3 },
2436 { "min", "Minimum value of the node", ST_SORT_COL_MIN4 },
2437 { "max", "Maximum value of the node", ST_SORT_COL_MAX5 },
2438 { "burst", "Burst rate of the node", ST_SORT_COL_BURSTRATE6 },
2439 { NULL((void*)0), NULL((void*)0), 0 }
2440};
2441
2442static const enum_val_t st_format_vals[] = {
2443 { "text", "Plain text", ST_FORMAT_PLAIN },
2444 { "csv", "Comma separated values", ST_FORMAT_CSV },
2445 { "xml", "XML document", ST_FORMAT_XML },
2446 { "yaml", "YAML document", ST_FORMAT_YAML },
2447 { NULL((void*)0), NULL((void*)0), 0 }
2448};
2449
2450static void
2451stats_callback(void)
2452{
2453 /* Test for a sane tap update interval */
2454 if (prefs.tap_update_interval < 100 || prefs.tap_update_interval > 10000)
2455 prefs.tap_update_interval = TAP_UPDATE_DEFAULT_INTERVAL3000;
2456
2457 /* burst resolution can't be less than 1 (ms) */
2458 if (prefs.st_burst_resolution < 1) {
2459 prefs.st_burst_resolution = 1;
2460 }
2461 else if (prefs.st_burst_resolution > ST_MAX_BURSTRES600000) {
2462 prefs.st_burst_resolution = ST_MAX_BURSTRES600000;
2463 }
2464 /* make sure burst window value makes sense */
2465 if (prefs.st_burst_windowlen < prefs.st_burst_resolution) {
2466 prefs.st_burst_windowlen = prefs.st_burst_resolution;
2467 }
2468 /* round burst window down to multiple of resolution */
2469 prefs.st_burst_windowlen -= prefs.st_burst_windowlen%prefs.st_burst_resolution;
2470 if ((prefs.st_burst_windowlen/prefs.st_burst_resolution) > ST_MAX_BURSTBUCKETS100) {
2471 prefs.st_burst_windowlen = prefs.st_burst_resolution*ST_MAX_BURSTBUCKETS100;
2472 }
2473}
2474
2475static void
2476gui_callback(void)
2477{
2478 /* Ensure there is at least one file count */
2479 if (prefs.gui_recent_files_count_max == 0)
2480 prefs.gui_recent_files_count_max = 10;
2481
2482 /* Ensure there is at least one display filter entry */
2483 if (prefs.gui_recent_df_entries_max == 0)
2484 prefs.gui_recent_df_entries_max = 10;
2485
2486 /* number of decimal places should be between 2 and 10 */
2487 if (prefs.gui_decimal_places1 < 2) {
2488 prefs.gui_decimal_places1 = 2;
2489 } else if (prefs.gui_decimal_places1 > 10) {
2490 prefs.gui_decimal_places1 = 10;
2491 }
2492 /* number of decimal places should be between 2 and 10 */
2493 if (prefs.gui_decimal_places2 < 2) {
2494 prefs.gui_decimal_places2 = 2;
2495 } else if (prefs.gui_decimal_places2 > 10) {
2496 prefs.gui_decimal_places2 = 10;
2497 }
2498 /* number of decimal places should be between 2 and 10 */
2499 if (prefs.gui_decimal_places3 < 2) {
2500 prefs.gui_decimal_places3 = 2;
2501 } else if (prefs.gui_decimal_places3 > 10) {
2502 prefs.gui_decimal_places3 = 10;
2503 }
2504}
2505
2506static void
2507gui_layout_callback(void)
2508{
2509 if (prefs.gui_layout_type == layout_unused ||
2510 prefs.gui_layout_type >= layout_type_max) {
2511 /* XXX - report an error? It's not a syntax error - we'd need to
2512 add a way of reporting a *semantic* error. */
2513 prefs.gui_layout_type = layout_type_2;
2514 }
2515}
2516
2517/******************************************************
2518 * All custom preference function callbacks
2519 ******************************************************/
2520static void custom_pref_no_cb(pref_t* pref _U___attribute__((unused))) {}
2521
2522/*
2523 * Column preference functions
2524 */
2525#define PRS_COL_HIDDEN_FMT"column.hidden" "column.hidden"
2526#define PRS_COL_HIDDEN"column.hide" "column.hide"
2527#define PRS_COL_FMT"column.format" "column.format"
2528#define PRS_COL_NUM"column.number" "column.number"
2529static module_t *gui_column_module;
2530
2531static prefs_set_pref_e
2532column_hidden_set_cb(pref_t* pref, const char* value, unsigned int* changed_flags)
2533{
2534 GList *clp;
2535 fmt_data *cfmt;
2536 pref_t *format_pref;
2537
2538 /*
2539 * Prefer the new preference to the old format-based preference if we've
2540 * read it. (We probably could just compare the string to NULL and "".)
2541 */
2542 prefs.cols_hide_new = true1;
2543
2544 (*changed_flags) |= prefs_set_string_value(pref, value, pref_current);
2545
2546 /*
2547 * Set the "visible" flag for the existing columns; we need to
2548 * do this if we set PRS_COL_HIDDEN but don't set PRS_COL_FMT
2549 * after setting it (which might be the case if, for example, we
2550 * set PRS_COL_HIDDEN on the command line).
2551 */
2552 format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT"column.format");
2553 clp = (format_pref) ? *format_pref->varp.list : NULL((void*)0);
2554 int cidx = 1;
2555 while (clp) {
2556 cfmt = (fmt_data *)clp->data;
2557 cfmt->visible = prefs_is_column_visible(*pref->varp.string, cidx);
2558 cidx++;
2559 clp = clp->next;
2560 }
2561
2562 return PREFS_SET_OK;
2563}
2564
2565static const char *
2566column_hidden_type_name_cb(void)
2567{
2568 return "Packet list hidden columns";
2569}
2570
2571static char *
2572column_hidden_type_description_cb(void)
2573{
2574 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."
)
;
2575}
2576
2577static char *
2578column_hidden_to_str_cb(pref_t* pref, bool_Bool default_val)
2579{
2580 GString *cols_hidden;
2581 GList *clp;
2582 fmt_data *cfmt;
2583 pref_t *format_pref;
2584 int cidx = 1;
2585
2586 if (default_val)
2587 return g_strdup(pref->default_val.string)g_strdup_inline (pref->default_val.string);
2588
2589 cols_hidden = g_string_new("");
2590 format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT"column.format");
2591 clp = (format_pref) ? *format_pref->varp.list : NULL((void*)0);
2592 while (clp) {
2593 cfmt = (fmt_data *) clp->data;
2594 if (!cfmt->visible) {
2595 if (cols_hidden->len)
2596 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))
;
2597 g_string_append_printf (cols_hidden, "%i", cidx);
2598 }
2599 clp = clp->next;
2600 cidx++;
2601 }
2602
2603 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))))
;
2604}
2605
2606static bool_Bool
2607column_hidden_is_default_cb(pref_t* pref)
2608{
2609 char *cur_hidden_str = column_hidden_to_str_cb(pref, false0);
2610 bool_Bool is_default = g_strcmp0(cur_hidden_str, pref->default_val.string) == 0;
2611
2612 g_free(cur_hidden_str);
2613 return is_default;
2614}
2615
2616static prefs_set_pref_e
2617column_hidden_fmt_set_cb(pref_t* pref, const char* value, unsigned int* changed_flags)
2618{
2619 GList *clp;
2620 fmt_data *cfmt;
2621 pref_t *format_pref;
2622
2623 (*changed_flags) |= prefs_set_string_value(pref, value, pref_current);
2624
2625 /*
2626 * Set the "visible" flag for the existing columns; we need to
2627 * do this if we set PRS_COL_HIDDEN_FMT but don't set PRS_COL_FMT
2628 * after setting it (which might be the case if, for example, we
2629 * set PRS_COL_HIDDEN_FMT on the command line; it shouldn't happen
2630 * when reading the configuration file because we write (both of)
2631 * the hidden column prefs before the column format prefs.)
2632 */
2633 format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT"column.format");
2634 clp = (format_pref) ? *format_pref->varp.list : NULL((void*)0);
2635 while (clp) {
2636 cfmt = (fmt_data *)clp->data;
2637 cfmt->visible = prefs_is_column_fmt_visible(*pref->varp.string, cfmt);
2638 clp = clp->next;
2639 }
2640
2641 return PREFS_SET_OK;
2642}
2643
2644static const char *
2645column_hidden_fmt_type_name_cb(void)
2646{
2647 return "Packet list hidden column formats (deprecated)";
2648}
2649
2650static char *
2651column_hidden_fmt_type_description_cb(void)
2652{
2653 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."
)
;
2654}
2655
2656static char *
2657column_hidden_fmt_to_str_cb(pref_t* pref, bool_Bool default_val)
2658{
2659 GString *cols_hidden;
2660 GList *clp;
2661 fmt_data *cfmt;
2662 pref_t *format_pref;
2663
2664 if (default_val)
2665 return g_strdup(pref->default_val.string)g_strdup_inline (pref->default_val.string);
2666
2667 cols_hidden = g_string_new("");
2668 format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT"column.format");
2669 clp = (format_pref) ? *format_pref->varp.list : NULL((void*)0);
2670 while (clp) {
2671 char *prefs_fmt;
2672 cfmt = (fmt_data *) clp->data;
2673 if (!cfmt->visible) {
2674 if (cols_hidden->len)
2675 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))
;
2676 prefs_fmt = column_fmt_data_to_str(cfmt);
2677 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))
;
2678 g_free(prefs_fmt);
2679 }
2680 clp = clp->next;
2681 }
2682
2683 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))))
;
2684}
2685
2686static bool_Bool
2687column_hidden_fmt_is_default_cb(pref_t* pref)
2688{
2689 char *cur_hidden_str = column_hidden_fmt_to_str_cb(pref, false0);
2690 bool_Bool is_default = g_strcmp0(cur_hidden_str, pref->default_val.string) == 0;
2691
2692 g_free(cur_hidden_str);
2693 return is_default;
2694}
2695
2696/* Number of columns "preference". This is only used internally and is not written to the
2697 * preference file
2698 */
2699static void
2700column_num_reset_cb(pref_t* pref)
2701{
2702 *pref->varp.uint = pref->default_val.uint;
2703}
2704
2705static prefs_set_pref_e
2706column_num_set_cb(pref_t* pref _U___attribute__((unused)), const char* value _U___attribute__((unused)), unsigned int* changed_flags _U___attribute__((unused)))
2707{
2708 /* Don't write this to the preferences file */
2709 return PREFS_SET_OK;
2710}
2711
2712static const char *
2713column_num_type_name_cb(void)
2714{
2715 return NULL((void*)0);
2716}
2717
2718static char *
2719column_num_type_description_cb(void)
2720{
2721 return g_strdup("")g_strdup_inline ("");
2722}
2723
2724static bool_Bool
2725column_num_is_default_cb(pref_t* pref _U___attribute__((unused)))
2726{
2727 return true1;
2728}
2729
2730static char *
2731column_num_to_str_cb(pref_t* pref _U___attribute__((unused)), bool_Bool default_val _U___attribute__((unused)))
2732{
2733 return g_strdup("")g_strdup_inline ("");
2734}
2735
2736/*
2737 * Column format custom preference functions
2738 */
2739static void
2740column_format_init_cb(pref_t* pref, GList** value)
2741{
2742 fmt_data *src_cfmt, *dest_cfmt;
2743 GList *entry;
2744
2745 pref->varp.list = value;
2746
2747 pref->default_val.list = NULL((void*)0);
2748 for (entry = *pref->varp.list; entry != NULL((void*)0); entry = g_list_next(entry)((entry) ? (((GList *)(entry))->next) : ((void*)0))) {
2749 src_cfmt = (fmt_data *)entry->data;
2750 dest_cfmt = g_new(fmt_data,1)((fmt_data *) g_malloc_n ((1), sizeof (fmt_data)));
2751 dest_cfmt->title = g_strdup(src_cfmt->title)g_strdup_inline (src_cfmt->title);
2752 dest_cfmt->fmt = src_cfmt->fmt;
2753 if (src_cfmt->custom_fields) {
2754 dest_cfmt->custom_fields = g_strdup(src_cfmt->custom_fields)g_strdup_inline (src_cfmt->custom_fields);
2755 dest_cfmt->custom_occurrence = src_cfmt->custom_occurrence;
2756 } else {
2757 dest_cfmt->custom_fields = NULL((void*)0);
2758 dest_cfmt->custom_occurrence = 0;
2759 }
2760 dest_cfmt->visible = src_cfmt->visible;
2761 dest_cfmt->display = src_cfmt->display;
2762 pref->default_val.list = g_list_append(pref->default_val.list, dest_cfmt);
2763 }
2764
2765 column_register_fields();
2766}
2767
2768static void
2769column_format_free_cb(pref_t* pref)
2770{
2771 free_col_info(*pref->varp.list);
2772 free_col_info(pref->default_val.list);
2773}
2774
2775static void
2776column_format_reset_cb(pref_t* pref)
2777{
2778 fmt_data *src_cfmt, *dest_cfmt;
2779 GList *entry;
2780 pref_t *col_num_pref;
2781
2782 free_col_info(*pref->varp.list);
2783 *pref->varp.list = NULL((void*)0);
2784
2785 for (entry = pref->default_val.list; entry != NULL((void*)0); entry = g_list_next(entry)((entry) ? (((GList *)(entry))->next) : ((void*)0))) {
2786 src_cfmt = (fmt_data *)entry->data;
2787 dest_cfmt = g_new(fmt_data,1)((fmt_data *) g_malloc_n ((1), sizeof (fmt_data)));
2788 dest_cfmt->title = g_strdup(src_cfmt->title)g_strdup_inline (src_cfmt->title);
2789 dest_cfmt->fmt = src_cfmt->fmt;
2790 if (src_cfmt->custom_fields) {
2791 dest_cfmt->custom_fields = g_strdup(src_cfmt->custom_fields)g_strdup_inline (src_cfmt->custom_fields);
2792 dest_cfmt->custom_occurrence = src_cfmt->custom_occurrence;
2793 } else {
2794 dest_cfmt->custom_fields = NULL((void*)0);
2795 dest_cfmt->custom_occurrence = 0;
2796 }
2797 dest_cfmt->visible = src_cfmt->visible;
2798 dest_cfmt->display = src_cfmt->display;
2799 *pref->varp.list = g_list_append(*pref->varp.list, dest_cfmt);
2800 }
2801
2802 col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM"column.number");
2803 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", 2803, __func__, "assertion failed: %s"
, "col_num_pref != ((void*)0)"); } while (0)
; /* Should never happen */
2804 column_num_reset_cb(col_num_pref);
2805}
2806
2807static prefs_set_pref_e
2808column_format_set_cb(pref_t* pref, const char* value, unsigned int* changed_flags _U___attribute__((unused)))
2809{
2810 GList *col_l, *col_l_elt;
2811 fmt_data *cfmt;
2812 int llen;
2813 pref_t *hidden_pref, *col_num_pref;
2814
2815 col_l = prefs_get_string_list(value);
2816 if (col_l == NULL((void*)0))
2817 return PREFS_SET_SYNTAX_ERR;
2818 if ((g_list_length(col_l) % 2) != 0) {
2819 /* A title didn't have a matching format. */
2820 prefs_clear_string_list(col_l);
2821 return PREFS_SET_SYNTAX_ERR;
2822 }
2823 /* Check to make sure all column formats are valid. */
2824 col_l_elt = g_list_first(col_l);
2825 while (col_l_elt) {
2826 fmt_data cfmt_check;
2827
2828 /* Go past the title. */
2829 col_l_elt = col_l_elt->next;
2830
2831 /* Some predefined columns have been migrated to use custom columns.
2832 * We'll convert these silently here */
2833 try_convert_to_custom_column((char **)&col_l_elt->data);
2834
2835 /* Parse the format to see if it's valid. */
2836 if (!parse_column_format(&cfmt_check, (char *)col_l_elt->data)) {
2837 /* It's not a valid column format. */
2838 prefs_clear_string_list(col_l);
2839 return PREFS_SET_SYNTAX_ERR;
2840 }
2841 if (cfmt_check.fmt == COL_CUSTOM) {
2842 /* We don't need the custom column field on this pass. */
2843 g_free(cfmt_check.custom_fields);
2844 }
2845
2846 /* Go past the format. */
2847 col_l_elt = col_l_elt->next;
2848 }
2849
2850 /* They're all valid; process them. */
2851 free_col_info(*pref->varp.list);
2852 *pref->varp.list = NULL((void*)0);
2853 if (prefs.cols_hide_new) {
2854 hidden_pref = prefs_find_preference(gui_column_module, PRS_COL_HIDDEN"column.hide");
2855 } else {
2856 hidden_pref = prefs_find_preference(gui_column_module, PRS_COL_HIDDEN_FMT"column.hidden");
2857 }
2858 ws_assert(hidden_pref != NULL)do { if ((1) && !(hidden_pref != ((void*)0))) ws_log_fatal_full
("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 2858, __func__, "assertion failed: %s"
, "hidden_pref != ((void*)0)"); } while (0)
; /* Should never happen */
2859 col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM"column.number");
2860 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", 2860, __func__, "assertion failed: %s"
, "col_num_pref != ((void*)0)"); } while (0)
; /* Should never happen */
2861 llen = g_list_length(col_l);
2862 *col_num_pref->varp.uint = llen / 2;
2863 col_l_elt = g_list_first(col_l);
2864 int cidx = 1;
2865 while (col_l_elt) {
2866 cfmt = g_new(fmt_data,1)((fmt_data *) g_malloc_n ((1), sizeof (fmt_data)));
2867 cfmt->title = g_strdup((char *)col_l_elt->data)g_strdup_inline ((char *)col_l_elt->data);
2868 col_l_elt = col_l_elt->next;
2869 parse_column_format(cfmt, (char *)col_l_elt->data);
2870 if (prefs.cols_hide_new) {
2871 cfmt->visible = prefs_is_column_visible(*hidden_pref->varp.string, cidx);
2872 } else {
2873 cfmt->visible = prefs_is_column_fmt_visible(*hidden_pref->varp.string, cfmt);
2874 }
2875 col_l_elt = col_l_elt->next;
2876 *pref->varp.list = g_list_append(*pref->varp.list, cfmt);
2877 cidx++;
2878 }
2879
2880 prefs_clear_string_list(col_l);
2881 free_string_like_preference(hidden_pref);
2882 column_register_fields();
2883 return PREFS_SET_OK;
2884}
2885
2886
2887static const char *
2888column_format_type_name_cb(void)
2889{
2890 return "Packet list column format";
2891}
2892
2893static char *
2894column_format_type_description_cb(void)
2895{
2896 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"
)
;
2897}
2898
2899static bool_Bool
2900column_format_is_default_cb(pref_t* pref)
2901{
2902 GList *clp = *pref->varp.list,
2903 *pref_col = g_list_first(clp),
2904 *def_col = g_list_first(pref->default_val.list);
2905 fmt_data *cfmt, *def_cfmt;
2906 bool_Bool is_default = true1;
2907 pref_t *col_num_pref;
2908
2909 /* See if the column data has changed from the default */
2910 col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM"column.number");
2911 if (col_num_pref && *col_num_pref->varp.uint != col_num_pref->default_val.uint) {
2912 is_default = false0;
2913 } else {
2914 while (pref_col && def_col) {
2915 cfmt = (fmt_data *) pref_col->data;
2916 def_cfmt = (fmt_data *) def_col->data;
2917 if ((g_strcmp0(cfmt->title, def_cfmt->title) != 0) ||
2918 (cfmt->fmt != def_cfmt->fmt) ||
2919 (((cfmt->fmt == COL_CUSTOM) && (cfmt->custom_fields)) &&
2920 ((g_strcmp0(cfmt->custom_fields, def_cfmt->custom_fields) != 0) ||
2921 (cfmt->display != def_cfmt->display)))) {
2922 is_default = false0;
2923 break;
2924 }
2925
2926 pref_col = pref_col->next;
2927 def_col = def_col->next;
2928 }
2929 }
2930
2931 return is_default;
2932}
2933
2934static char *
2935column_format_to_str_cb(pref_t* pref, bool_Bool default_val)
2936{
2937 GList *pref_l = default_val ? pref->default_val.list : *pref->varp.list;
2938 GList *clp = g_list_first(pref_l);
2939 GList *col_l;
2940 fmt_data *cfmt;
2941 char *column_format_str;
2942
2943 col_l = NULL((void*)0);
2944 while (clp) {
2945 cfmt = (fmt_data *) clp->data;
2946 col_l = g_list_append(col_l, g_strdup(cfmt->title)g_strdup_inline (cfmt->title));
2947 col_l = g_list_append(col_l, column_fmt_data_to_str(cfmt));
2948 clp = clp->next;
2949 }
2950
2951 column_format_str = join_string_list(col_l);
2952 prefs_clear_string_list(col_l);
2953 return column_format_str;
2954}
2955
2956
2957/****** Capture column custom preference functions ******/
2958
2959/* This routine is only called when Wireshark is started, NOT when another profile is selected.
2960 Copy the pref->capture_columns list (just loaded with the capture_cols[] struct values)
2961 to prefs->default_val.list.
2962*/
2963static void
2964capture_column_init_cb(pref_t* pref, GList** capture_cols_values)
2965{
2966 GList *ccv_list = *capture_cols_values,
2967 *dlist = NULL((void*)0);
2968
2969 /* */
2970 while (ccv_list) {
2971 dlist = g_list_append(dlist, g_strdup((char *)ccv_list->data)g_strdup_inline ((char *)ccv_list->data));
2972 ccv_list = ccv_list->next;
2973 }
2974
2975 pref->default_val.list = dlist;
2976 pref->varp.list = &prefs.capture_columns;
2977 pref->stashed_val.boolval = false0;
2978}
2979
2980/* Free the prefs->capture_columns list strings and remove the list entries.
2981 Note that since pref->varp.list points to &prefs.capture_columns, it is
2982 also freed.
2983*/
2984static void
2985capture_column_free_cb(pref_t* pref)
2986{
2987 prefs_clear_string_list(prefs.capture_columns);
2988 prefs.capture_columns = NULL((void*)0);
2989
2990 if (pref->stashed_val.boolval == true1) {
2991 prefs_clear_string_list(pref->default_val.list);
2992 pref->default_val.list = NULL((void*)0);
2993 }
2994}
2995
2996/* Copy pref->default_val.list to *pref->varp.list.
2997*/
2998static void
2999capture_column_reset_cb(pref_t* pref)
3000{
3001 GList *vlist = NULL((void*)0), *dlist;
3002
3003 /* Free the column name strings and remove the links from *pref->varp.list */
3004 prefs_clear_string_list(*pref->varp.list);
3005
3006 for (dlist = pref->default_val.list; dlist != NULL((void*)0); dlist = g_list_next(dlist)((dlist) ? (((GList *)(dlist))->next) : ((void*)0))) {
3007 vlist = g_list_append(vlist, g_strdup((char *)dlist->data)g_strdup_inline ((char *)dlist->data));
3008 }
3009 *pref->varp.list = vlist;
3010}
3011
3012static prefs_set_pref_e
3013capture_column_set_cb(pref_t* pref, const char* value, unsigned int* changed_flags _U___attribute__((unused)))
3014{
3015 GList *col_l = prefs_get_string_list(value);
3016 GList *col_l_elt;
3017 char *col_name;
3018 int i;
3019
3020 if (col_l == NULL((void*)0))
3021 return PREFS_SET_SYNTAX_ERR;
3022
3023 capture_column_free_cb(pref);
3024
3025 /* If value (the list of capture.columns read from preferences) is empty, set capture.columns
3026 to the full list of valid capture column names. */
3027 col_l_elt = g_list_first(col_l);
3028 if (!(*(char *)col_l_elt->data)) {
3029 for (i = 0; i < num_capture_cols; i++) {
3030 col_name = g_strdup(capture_cols[i])g_strdup_inline (capture_cols[i]);
3031 prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
3032 }
3033 }
3034
3035 /* Verify that all the column names are valid. If not, use the entire list of valid columns.
3036 */
3037 while (col_l_elt) {
3038 bool_Bool found_match = false0;
3039 col_name = (char *)col_l_elt->data;
3040
3041 for (i = 0; i < num_capture_cols; i++) {
3042 if (strcmp(col_name, capture_cols[i])==0) {
3043 found_match = true1;
3044 break;
3045 }
3046 }
3047 if (!found_match) {
3048 /* One or more cols are invalid so use the entire list of valid cols. */
3049 for (i = 0; i < num_capture_cols; i++) {
3050 col_name = g_strdup(capture_cols[i])g_strdup_inline (capture_cols[i]);
3051 prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
3052 }
3053 pref->varp.list = &prefs.capture_columns;
3054 prefs_clear_string_list(col_l);
3055 return PREFS_SET_SYNTAX_ERR;
3056 }
3057 col_l_elt = col_l_elt->next;
3058 }
3059
3060 col_l_elt = g_list_first(col_l);
3061 while (col_l_elt) {
3062 col_name = (char *)col_l_elt->data;
3063 prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
3064 col_l_elt = col_l_elt->next;
3065 }
3066 pref->varp.list = &prefs.capture_columns;
3067 g_list_free(col_l);
3068 return PREFS_SET_OK;
3069}
3070
3071
3072static const char *
3073capture_column_type_name_cb(void)
3074{
3075 return "Column list";
3076}
3077
3078static char *
3079capture_column_type_description_cb(void)
3080{
3081 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"
)
3082 "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"
)
3083 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"
)
;
3084}
3085
3086static bool_Bool
3087capture_column_is_default_cb(pref_t* pref)
3088{
3089 GList *pref_col = g_list_first(prefs.capture_columns),
3090 *def_col = g_list_first(pref->default_val.list);
3091 bool_Bool is_default = true1;
3092
3093 /* See if the column data has changed from the default */
3094 while (pref_col && def_col) {
3095 if (strcmp((char *)pref_col->data, (char *)def_col->data) != 0) {
3096 is_default = false0;
3097 break;
3098 }
3099 pref_col = pref_col->next;
3100 def_col = def_col->next;
3101 }
3102
3103 /* Ensure the same column count */
3104 if (((pref_col == NULL((void*)0)) && (def_col != NULL((void*)0))) ||
3105 ((pref_col != NULL((void*)0)) && (def_col == NULL((void*)0))))
3106 is_default = false0;
3107
3108 return is_default;
3109}
3110
3111static char *
3112capture_column_to_str_cb(pref_t* pref, bool_Bool default_val)
3113{
3114
3115 GList *pref_l = default_val ? pref->default_val.list : prefs.capture_columns;
3116 GList *clp = g_list_first(pref_l);
3117 GList *col_l = NULL((void*)0);
3118 char *col;
3119 char *capture_column_str;
3120
3121 while (clp) {
3122 col = (char *) clp->data;
3123 col_l = g_list_append(col_l, g_strdup(col)g_strdup_inline (col));
3124 clp = clp->next;
3125 }
3126
3127 capture_column_str = join_string_list(col_l);
3128 prefs_clear_string_list(col_l);
3129 return capture_column_str;
3130}
3131
3132static prefs_set_pref_e
3133colorized_frame_set_cb(pref_t* pref, const char* value, unsigned int* changed_flags)
3134{
3135 (*changed_flags) |= prefs_set_string_value(pref, value, pref_current);
3136 return PREFS_SET_OK;
3137}
3138
3139static const char *
3140colorized_frame_type_name_cb(void)
3141{
3142 /* Don't write the colors of the 10 easy-access-colorfilters to the preferences
3143 * file until the colors can be changed in the GUI. Currently this is not really
3144 * possible since the STOCK-icons for these colors are hardcoded.
3145 *
3146 * XXX Find a way to change the colors of the STOCK-icons on the fly and then
3147 * add these 10 colors to the list of colors that can be changed through
3148 * the preferences.
3149 *
3150 */
3151 return NULL((void*)0);
3152}
3153
3154static char *
3155colorized_frame_type_description_cb(void)
3156{
3157 return g_strdup("")g_strdup_inline ("");
3158}
3159
3160static bool_Bool
3161colorized_frame_is_default_cb(pref_t* pref _U___attribute__((unused)))
3162{
3163 return true1;
3164}
3165
3166static char *
3167colorized_frame_to_str_cb(pref_t* pref _U___attribute__((unused)), bool_Bool default_val _U___attribute__((unused)))
3168{
3169 return g_strdup("")g_strdup_inline ("");
3170}
3171
3172/*
3173 * Register all non-dissector modules' preferences.
3174 */
3175static module_t *gui_module;
3176static module_t *gui_color_module;
3177static module_t *nameres_module;
3178
3179static void
3180prefs_register_modules(void)
3181{
3182 module_t *printing, *capture_module, *console_module,
3183 *gui_layout_module, *gui_font_module;
3184 module_t *extcap_module;
3185 unsigned int layout_gui_flags;
3186 struct pref_custom_cbs custom_cbs;
3187
3188 if (protocols_module != NULL((void*)0)) {
3189 /* Already setup preferences */
3190 return;
3191 }
3192
3193 /* GUI
3194 * These are "simple" GUI preferences that can be read/written using the
3195 * preference module API. These preferences still use their own
3196 * configuration screens for access, but this cuts down on the
3197 * preference "string compare list" in set_pref()
3198 */
3199 extcap_module = prefs_register_module(NULL((void*)0), "extcap", "Extcap Utilities",
3200 "Extcap Utilities", NULL((void*)0), NULL((void*)0), false0);
3201
3202 /* Setting default value to true */
3203 prefs.extcap_save_on_start = true1;
3204 prefs_register_bool_preference(extcap_module, "gui_save_on_start",
3205 "Save arguments on start of capture",
3206 "Save arguments on start of capture",
3207 &prefs.extcap_save_on_start);
3208
3209 /* GUI
3210 * These are "simple" GUI preferences that can be read/written using the
3211 * preference module API. These preferences still use their own
3212 * configuration screens for access, but this cuts down on the
3213 * preference "string compare list" in set_pref()
3214 */
3215 gui_module = prefs_register_module(NULL((void*)0), "gui", "User Interface",
3216 "User Interface", NULL((void*)0), &gui_callback, false0);
3217 /*
3218 * The GUI preferences don't affect dissection in general.
3219 * Any changes are signaled in other ways, so PREF_EFFECT_GUI doesn't
3220 * explicitly do anything, but wslua_set_preference expects *some*
3221 * effect flag to be set if the preference was changed.
3222 * We have to do this again for all the submodules (except for the
3223 * layout submodule, which has its own effect flag).
3224 */
3225 unsigned gui_effect_flags = prefs_get_module_effect_flags(gui_module);
3226 gui_effect_flags |= PREF_EFFECT_GUI(1u << 4);
3227 gui_effect_flags &= (~PREF_EFFECT_DISSECTION(1u << 0));
3228 prefs_set_module_effect_flags(gui_module, gui_effect_flags);
3229
3230 /*
3231 * gui.console_open is stored in the registry in addition to the
3232 * preferences file. It is also read independently by ws_log_init()
3233 * for early log initialization of the console.
3234 */
3235 prefs_register_enum_preference(gui_module, "console_open",
3236 "Open a console window",
3237 "Open a console window (Windows only)",
3238 (int *)&ws_log_console_open, gui_console_open_type, false0);
3239
3240 prefs_register_obsolete_preference(gui_module, "scrollbar_on_right");
3241 prefs_register_obsolete_preference(gui_module, "packet_list_sel_browse");
3242 prefs_register_obsolete_preference(gui_module, "protocol_tree_sel_browse");
3243 prefs_register_obsolete_preference(gui_module, "tree_view_altern_colors");
3244 prefs_register_obsolete_preference(gui_module, "expert_composite_eyecandy");
3245 prefs_register_obsolete_preference(gui_module, "filter_toolbar_show_in_statusbar");
3246
3247 prefs_register_bool_preference(gui_module, "restore_filter_after_following_stream",
3248 "Restore current display filter after following a stream",
3249 "Restore current display filter after following a stream?",
3250 &prefs.restore_filter_after_following_stream);
3251
3252 prefs_register_obsolete_preference(gui_module, "protocol_tree_line_style");
3253
3254 prefs_register_obsolete_preference(gui_module, "protocol_tree_expander_style");
3255
3256 prefs_register_obsolete_preference(gui_module, "hex_dump_highlight_style");
3257
3258 prefs_register_obsolete_preference(gui_module, "packet_editor.enabled");
3259
3260 gui_column_module = prefs_register_subtree(gui_module, "Columns", "Columns", NULL((void*)0));
3261 prefs_set_module_effect_flags(gui_column_module, gui_effect_flags);
3262 /* For reading older preference files with "column." preferences */
3263 prefs_register_module_alias("column", gui_column_module);
3264
3265
3266 custom_cbs.free_cb = free_string_like_preference;
3267 custom_cbs.reset_cb = reset_string_like_preference;
3268 custom_cbs.set_cb = column_hidden_set_cb;
3269 custom_cbs.type_name_cb = column_hidden_type_name_cb;
3270 custom_cbs.type_description_cb = column_hidden_type_description_cb;
3271 custom_cbs.is_default_cb = column_hidden_is_default_cb;
3272 custom_cbs.to_str_cb = column_hidden_to_str_cb;
3273 register_string_like_preference(gui_column_module, PRS_COL_HIDDEN"column.hide", "Packet list hidden columns",
3274 "List all column indices (1-indexed) to hide in the packet list",
3275 &cols_hidden_list, PREF_CUSTOM, &custom_cbs, false0);
3276
3277 custom_cbs.set_cb = column_hidden_fmt_set_cb;
3278 custom_cbs.type_name_cb = column_hidden_fmt_type_name_cb;
3279 custom_cbs.type_description_cb = column_hidden_fmt_type_description_cb;
3280 custom_cbs.is_default_cb = column_hidden_fmt_is_default_cb;
3281 custom_cbs.to_str_cb = column_hidden_fmt_to_str_cb;
3282
3283 register_string_like_preference(gui_column_module, PRS_COL_HIDDEN_FMT"column.hidden", "Packet list hidden column formats (deprecated)",
3284 "List all column formats to hide in the packet list; deprecated in favor of the index-based preference",
3285 &cols_hidden_fmt_list, PREF_CUSTOM, &custom_cbs, false0);
3286
3287 custom_cbs.free_cb = column_format_free_cb;
3288 custom_cbs.reset_cb = column_format_reset_cb;
3289 custom_cbs.set_cb = column_format_set_cb;
3290 custom_cbs.type_name_cb = column_format_type_name_cb;
3291 custom_cbs.type_description_cb = column_format_type_description_cb;
3292 custom_cbs.is_default_cb = column_format_is_default_cb;
3293 custom_cbs.to_str_cb = column_format_to_str_cb;
3294
3295 prefs_register_list_custom_preference(gui_column_module, PRS_COL_FMT"column.format", "Packet list column format",
3296 "Each pair of strings consists of a column title and its format", &custom_cbs,
3297 column_format_init_cb, &prefs.col_list);
3298
3299 /* Number of columns. This is only used internally and is not written to the
3300 * preference file
3301 */
3302 custom_cbs.free_cb = custom_pref_no_cb;
3303 custom_cbs.reset_cb = column_num_reset_cb;
3304 custom_cbs.set_cb = column_num_set_cb;
3305 custom_cbs.type_name_cb = column_num_type_name_cb;
3306 custom_cbs.type_description_cb = column_num_type_description_cb;
3307 custom_cbs.is_default_cb = column_num_is_default_cb;
3308 custom_cbs.to_str_cb = column_num_to_str_cb;
3309 prefs_register_uint_custom_preference(gui_column_module, PRS_COL_NUM"column.number", "Number of columns",
3310 "Number of columns in col_list", &custom_cbs, &prefs.num_cols);
3311
3312 /* User Interface : Font */
3313 gui_font_module = prefs_register_subtree(gui_module, "Font", "Font", NULL((void*)0));
3314 prefs_set_module_effect_flags(gui_font_module, gui_effect_flags);
3315
3316 prefs_register_obsolete_preference(gui_font_module, "font_name");
3317
3318 prefs_register_obsolete_preference(gui_font_module, "gtk2.font_name");
3319
3320 register_string_like_preference(gui_font_module, "qt.font_name", "Font name",
3321 "Font name for packet list, protocol tree, and hex dump panes. (Qt)",
3322 &prefs.gui_font_name, PREF_STRING, NULL((void*)0), true1);
3323
3324 /* User Interface : Colors */
3325 gui_color_module = prefs_register_subtree(gui_module, "Colors", "Colors", NULL((void*)0));
3326 unsigned gui_color_effect_flags = gui_effect_flags | PREF_EFFECT_GUI_COLOR(1u << 5);
3327 prefs_set_module_effect_flags(gui_color_module, gui_color_effect_flags);
3328
3329 prefs_register_enum_preference(gui_color_module, "color_scheme", "Color scheme", "Color scheme",
3330 &prefs.gui_color_scheme, gui_color_scheme, false0);
3331
3332 prefs_register_color_preference(gui_color_module, "active_frame.fg", "Foreground color for an active selected item",
3333 "Foreground color for an active selected item", &prefs.gui_active_fg);
3334
3335 prefs_register_color_preference(gui_color_module, "active_frame.bg", "Background color for an active selected item",
3336 "Background color for an active selected item", &prefs.gui_active_bg);
3337
3338 prefs_register_enum_preference(gui_color_module, "active_frame.style", "Color style for an active selected item",
3339 "Color style for an active selected item", &prefs.gui_active_style, gui_selection_style, false0);
3340
3341 prefs_register_color_preference(gui_color_module, "inactive_frame.fg", "Foreground color for an inactive selected item",
3342 "Foreground color for an inactive selected item", &prefs.gui_inactive_fg);
3343
3344 prefs_register_color_preference(gui_color_module, "inactive_frame.bg", "Background color for an inactive selected item",
3345 "Background color for an inactive selected item", &prefs.gui_inactive_bg);
3346
3347 prefs_register_enum_preference(gui_color_module, "inactive_frame.style", "Color style for an inactive selected item",
3348 "Color style for an inactive selected item", &prefs.gui_inactive_style, gui_selection_style, false0);
3349
3350 prefs_register_color_preference(gui_color_module, "marked_frame.fg", "Color preferences for a marked frame",
3351 "Color preferences for a marked frame", &prefs.gui_marked_fg);
3352
3353 prefs_register_color_preference(gui_color_module, "marked_frame.bg", "Color preferences for a marked frame",
3354 "Color preferences for a marked frame", &prefs.gui_marked_bg);
3355
3356 prefs_register_color_preference(gui_color_module, "ignored_frame.fg", "Color preferences for a ignored frame",
3357 "Color preferences for a ignored frame", &prefs.gui_ignored_fg);
3358
3359 prefs_register_color_preference(gui_color_module, "ignored_frame.bg", "Color preferences for a ignored frame",
3360 "Color preferences for a ignored frame", &prefs.gui_ignored_bg);
3361
3362 prefs_register_color_preference(gui_color_module, "stream.client.fg", "TCP stream window color preference",
3363 "TCP stream window color preference", &prefs.st_client_fg);
3364
3365 prefs_register_color_preference(gui_color_module, "stream.client.bg", "TCP stream window color preference",
3366 "TCP stream window color preference", &prefs.st_client_bg);
3367
3368 prefs_register_color_preference(gui_color_module, "stream.server.fg", "TCP stream window color preference",
3369 "TCP stream window color preference", &prefs.st_server_fg);
3370
3371 prefs_register_color_preference(gui_color_module, "stream.server.bg", "TCP stream window color preference",
3372 "TCP stream window color preference", &prefs.st_server_bg);
3373
3374 custom_cbs.free_cb = free_string_like_preference;
3375 custom_cbs.reset_cb = reset_string_like_preference;
3376 custom_cbs.set_cb = colorized_frame_set_cb;
3377 custom_cbs.type_name_cb = colorized_frame_type_name_cb;
3378 custom_cbs.type_description_cb = colorized_frame_type_description_cb;
3379 custom_cbs.is_default_cb = colorized_frame_is_default_cb;
3380 custom_cbs.to_str_cb = colorized_frame_to_str_cb;
3381 register_string_like_preference(gui_column_module, "colorized_frame.fg", "Colorized Foreground",
3382 "Filter Colorized Foreground",
3383 &prefs.gui_colorized_fg, PREF_CUSTOM, &custom_cbs, true1);
3384
3385 custom_cbs.free_cb = free_string_like_preference;
3386 custom_cbs.reset_cb = reset_string_like_preference;
3387 custom_cbs.set_cb = colorized_frame_set_cb;
3388 custom_cbs.type_name_cb = colorized_frame_type_name_cb;
3389 custom_cbs.type_description_cb = colorized_frame_type_description_cb;
3390 custom_cbs.is_default_cb = colorized_frame_is_default_cb;
3391 custom_cbs.to_str_cb = colorized_frame_to_str_cb;
3392 register_string_like_preference(gui_column_module, "colorized_frame.bg", "Colorized Background",
3393 "Filter Colorized Background",
3394 &prefs.gui_colorized_bg, PREF_CUSTOM, &custom_cbs, true1);
3395
3396 prefs_register_color_preference(gui_color_module, "color_filter_fg.valid", "Valid color filter foreground",
3397 "Valid color filter foreground", &prefs.gui_filter_valid_fg);
3398 prefs_register_color_preference(gui_color_module, "color_filter_bg.valid", "Valid color filter background",
3399 "Valid color filter background", &prefs.gui_filter_valid_bg);
3400
3401 prefs_register_color_preference(gui_color_module, "color_filter_fg.invalid", "Invalid color filter foreground",
3402 "Invalid color filter foreground", &prefs.gui_filter_invalid_fg);
3403 prefs_register_color_preference(gui_color_module, "color_filter_bg.invalid", "Invalid color filter background",
3404 "Invalid color filter background", &prefs.gui_filter_invalid_bg);
3405
3406 prefs_register_color_preference(gui_color_module, "color_filter_fg.deprecated", "Deprecated color filter foreground",
3407 "Deprecated color filter foreground", &prefs.gui_filter_deprecated_fg);
3408 prefs_register_color_preference(gui_color_module, "color_filter_bg.deprecated", "Deprecated color filter background",
3409 "Deprecated color filter background", &prefs.gui_filter_deprecated_bg);
3410
3411 prefs_register_enum_preference(gui_module, "fileopen.style",
3412 "Where to start the File Open dialog box",
3413 "Where to start the File Open dialog box",
3414 &prefs.gui_fileopen_style, gui_fileopen_style, false0);
3415
3416 prefs_register_uint_preference(gui_module, "recent_files_count.max",
3417 "The max. number of items in the open recent files list",
3418 "The max. number of items in the open recent files list",
3419 10,
3420 &prefs.gui_recent_files_count_max);
3421
3422 prefs_register_uint_preference(gui_module, "recent_display_filter_entries.max",
3423 "The max. number of entries in the display filter list",
3424 "The max. number of entries in the display filter list",
3425 10,
3426 &prefs.gui_recent_df_entries_max);
3427
3428 register_string_like_preference(gui_module, "fileopen.dir", "Start Directory",
3429 "Directory to start in when opening File Open dialog.",
3430 &prefs.gui_fileopen_dir, PREF_DIRNAME, NULL((void*)0), true1);
3431
3432 prefs_register_obsolete_preference(gui_module, "fileopen.remembered_dir");
3433
3434 prefs_register_uint_preference(gui_module, "fileopen.preview",
3435 "The preview timeout in the File Open dialog",
3436 "The preview timeout in the File Open dialog",
3437 10,
3438 &prefs.gui_fileopen_preview);
3439
3440 register_string_like_preference(gui_module, "tlskeylog_command", "Program to launch with TLS Keylog",
3441 "Program path or command line to launch with SSLKEYLOGFILE",
3442 &prefs.gui_tlskeylog_command, PREF_STRING, NULL((void*)0), true1);
3443
3444 prefs_register_bool_preference(gui_module, "ask_unsaved",
3445 "Ask to save unsaved capture files",
3446 "Ask to save unsaved capture files?",
3447 &prefs.gui_ask_unsaved);
3448
3449 prefs_register_bool_preference(gui_module, "autocomplete_filter",
3450 "Display autocompletion for filter text",
3451 "Display an autocomplete suggestion for display and capture filter controls",
3452 &prefs.gui_autocomplete_filter);
3453
3454 prefs_register_bool_preference(gui_module, "find_wrap",
3455 "Wrap to beginning/end of file during search",
3456 "Wrap to beginning/end of file during search?",
3457 &prefs.gui_find_wrap);
3458
3459 prefs_register_obsolete_preference(gui_module, "use_pref_save");
3460
3461 prefs_register_bool_preference(gui_module, "geometry.save.position",
3462 "Save window position at exit",
3463 "Save window position at exit?",
3464 &prefs.gui_geometry_save_position);
3465
3466 prefs_register_bool_preference(gui_module, "geometry.save.size",
3467 "Save window size at exit",
3468 "Save window size at exit?",
3469 &prefs.gui_geometry_save_size);
3470
3471 prefs_register_bool_preference(gui_module, "geometry.save.maximized",
3472 "Save window maximized state at exit",
3473 "Save window maximized state at exit?",
3474 &prefs.gui_geometry_save_maximized);
3475
3476 prefs_register_obsolete_preference(gui_module, "macosx_style");
3477
3478 prefs_register_obsolete_preference(gui_module, "geometry.main.x");
3479 prefs_register_obsolete_preference(gui_module, "geometry.main.y");
3480 prefs_register_obsolete_preference(gui_module, "geometry.main.width");
3481 prefs_register_obsolete_preference(gui_module, "geometry.main.height");
3482 prefs_register_obsolete_preference(gui_module, "toolbar_main_show");
3483
3484 prefs_register_enum_preference(gui_module, "toolbar_main_style",
3485 "Main Toolbar style",
3486 "Main Toolbar style",
3487 &prefs.gui_toolbar_main_style, gui_toolbar_style, false0);
3488
3489 prefs_register_obsolete_preference(gui_module, "toolbar_filter_style");
3490 prefs_register_obsolete_preference(gui_module, "webbrowser");
3491
3492 prefs_register_bool_preference(gui_module, "update.enabled",
3493 "Check for updates",
3494 "Check for updates (Windows and macOS only)",
3495 &prefs.gui_update_enabled);
3496
3497 prefs_register_enum_preference(gui_module, "update.channel",
3498 "Update channel",
3499 "The type of update to fetch. You should probably leave this set to STABLE.",
3500 (int*)(void*)(&prefs.gui_update_channel), gui_update_channel, false0);
3501
3502 prefs_register_uint_preference(gui_module, "update.interval",
3503 "How often to check for software updates",
3504 "How often to check for software updates in seconds",
3505 10,
3506 &prefs.gui_update_interval);
3507
3508 prefs_register_uint_preference(gui_module, "debounce.timer",
3509 "How long to wait before processing computationally intensive user input",
3510 "How long to wait (in milliseconds) before processing "
3511 "computationally intensive user input. "
3512 "If you type quickly, consider lowering the value for a 'snappier' "
3513 "experience. "
3514 "If you type slowly, consider increasing the value to avoid performance issues. "
3515 "This is currently used to delay searches in View -> Internals -> Supported Protocols "
3516 "and Preferences -> Advanced menu.",
3517 10,
3518 &prefs.gui_debounce_timer);
3519
3520 register_string_like_preference(gui_module, "window_title", "Custom window title",
3521 "Custom window title to be appended to the existing title\n"
3522 "%C = capture comment from command line\n"
3523 "%F = file path of the capture file\n"
3524 "%P = profile name\n"
3525 "%S = a conditional separator (\" - \") that only shows when surrounded by variables with values or static text\n"
3526 "%V = version info",
3527 &prefs.gui_window_title, PREF_STRING, NULL((void*)0), true1);
3528
3529 register_string_like_preference(gui_module, "prepend_window_title", "Custom window title prefix",
3530 "Custom window title to be prepended to the existing title\n"
3531 "%C = capture comment from command line\n"
3532 "%F = file path of the capture file\n"
3533 "%P = profile name\n"
3534 "%S = a conditional separator (\" - \") that only shows when surrounded by variables with values or static text\n"
3535 "%V = version info",
3536 &prefs.gui_prepend_window_title, PREF_STRING, NULL((void*)0), true1);
3537
3538 register_string_like_preference(gui_module, "start_title", "Custom start page title",
3539 "Custom start page title",
3540 &prefs.gui_start_title, PREF_STRING, NULL((void*)0), true1);
3541
3542 prefs_register_enum_preference(gui_module, "version_placement",
3543 "Show version in the start page and/or main screen's title bar",
3544 "Show version in the start page and/or main screen's title bar",
3545 (int*)(void*)(&prefs.gui_version_placement), gui_version_placement_type, false0);
3546
3547 prefs_register_obsolete_preference(gui_module, "auto_scroll_on_expand");
3548 prefs_register_obsolete_preference(gui_module, "auto_scroll_percentage");
3549
3550 prefs_register_uint_preference(gui_module, "max_export_objects",
3551 "Maximum number of exported objects",
3552 "The maximum number of objects that can be exported",
3553 10,
3554 &prefs.gui_max_export_objects);
3555 prefs_register_uint_preference(gui_module, "max_tree_items",
3556 "Maximum number of tree items",
3557 "The maximum number of items that can be added to the dissection tree (Increase with caution)",
3558 10,
3559 &prefs.gui_max_tree_items);
3560 /*
3561 * Used independently by proto_tree_add_node, call_dissector*, dissector_try_heuristic,
3562 * and increment_dissection_depth.
3563 */
3564 prefs_register_uint_preference(gui_module, "max_tree_depth",
3565 "Maximum dissection depth",
3566 "The maximum depth for dissection tree and protocol layer checks. (Increase with caution)",
3567 10,
3568 &prefs.gui_max_tree_depth);
3569
3570 prefs_register_bool_preference(gui_module, "welcome_page.show_recent",
3571 "Show recent files on the welcome page",
3572 "This will enable or disable the 'Open' list on the welcome page.",
3573 &prefs.gui_welcome_page_show_recent);
3574
3575 /* User Interface : Layout */
3576 gui_layout_module = prefs_register_subtree(gui_module, "Layout", "Layout", gui_layout_callback);
3577 /* Adjust the preference effects of layout GUI for better handling of preferences at Wireshark (GUI) level */
3578 layout_gui_flags = prefs_get_module_effect_flags(gui_layout_module);
3579 layout_gui_flags |= PREF_EFFECT_GUI_LAYOUT(1u << 2);
3580 layout_gui_flags &= (~PREF_EFFECT_DISSECTION(1u << 0));
3581
3582 prefs_register_uint_preference(gui_layout_module, "layout_type",
3583 "Layout type",
3584 "Layout type (1-6)",
3585 10,
3586 (unsigned*)(void*)(&prefs.gui_layout_type));
3587 prefs_set_effect_flags_by_name(gui_layout_module, "layout_type", layout_gui_flags);
3588
3589 prefs_register_enum_preference(gui_layout_module, "layout_content_1",
3590 "Layout content of the pane 1",
3591 "Layout content of the pane 1",
3592 (int*)(void*)(&prefs.gui_layout_content_1), gui_layout_content, false0);
3593 prefs_set_effect_flags_by_name(gui_layout_module, "layout_content_1", layout_gui_flags);
3594
3595 prefs_register_enum_preference(gui_layout_module, "layout_content_2",
3596 "Layout content of the pane 2",
3597 "Layout content of the pane 2",
3598 (int*)(void*)(&prefs.gui_layout_content_2), gui_layout_content, false0);
3599 prefs_set_effect_flags_by_name(gui_layout_module, "layout_content_2", layout_gui_flags);
3600
3601 prefs_register_enum_preference(gui_layout_module, "layout_content_3",
3602 "Layout content of the pane 3",
3603 "Layout content of the pane 3",
3604 (int*)(void*)(&prefs.gui_layout_content_3), gui_layout_content, false0);
3605 prefs_set_effect_flags_by_name(gui_layout_module, "layout_content_3", layout_gui_flags);
3606
3607 prefs_register_bool_preference(gui_layout_module, "packet_list_separator.enabled",
3608 "Enable Packet List Separator",
3609 "Enable Packet List Separator",
3610 &prefs.gui_packet_list_separator);
3611
3612 prefs_register_bool_preference(gui_layout_module, "packet_header_column_definition.enabled",
3613 "Show column definition in packet list header",
3614 "Show column definition in packet list header",
3615 &prefs.gui_packet_header_column_definition);
3616
3617 /* packet_list_hover_style affects the colors, not the layout.
3618 * It's in the layout module to group it with the other packet list
3619 * preferences for the user's benefit with the dialog.
3620 */
3621 prefs_register_bool_preference(gui_layout_module, "packet_list_hover_style.enabled",
3622 "Enable Packet List mouse-over colorization",
3623 "Enable Packet List mouse-over colorization",
3624 &prefs.gui_packet_list_hover_style);
3625 prefs_set_effect_flags_by_name(gui_layout_module, "packet_list_hover_style.enabled", gui_color_effect_flags);
3626
3627 prefs_register_bool_preference(gui_layout_module, "show_selected_packet.enabled",
3628 "Show selected packet in the Status Bar",
3629 "Show selected packet in the Status Bar",
3630 &prefs.gui_show_selected_packet);
3631
3632 prefs_register_bool_preference(gui_layout_module, "show_file_load_time.enabled",
3633 "Show file load time in the Status Bar",
3634 "Show file load time in the Status Bar",
3635 &prefs.gui_show_file_load_time);
3636
3637 prefs_register_enum_preference(gui_layout_module, "packet_dialog_layout",
3638 "Packet Dialog layout",
3639 "Packet Dialog layout",
3640 (unsigned*)(void*)(&prefs.gui_packet_dialog_layout), gui_packet_dialog_layout, false0);
3641
3642 prefs_register_enum_preference(gui_module, "packet_list_elide_mode",
3643 "Elide mode",
3644 "The position of \"...\" (ellipsis) in packet list text.",
3645 (int*)(void*)(&prefs.gui_packet_list_elide_mode), gui_packet_list_elide_mode, false0);
3646 prefs_register_uint_preference(gui_module, "decimal_places1",
3647 "Count of decimal places for values of type 1",
3648 "Sets the count of decimal places for values of type 1."
3649 "Type 1 values are defined by authors."
3650 "Value can be in range 2 to 10.",
3651 10,&prefs.gui_decimal_places1);
3652
3653 prefs_register_uint_preference(gui_module, "decimal_places2",
3654 "Count of decimal places for values of type 2",
3655 "Sets the count of decimal places for values of type 2."
3656 "Type 2 values are defined by authors."
3657 "Value can be in range 2 to 10.",
3658 10,&prefs.gui_decimal_places2);
3659
3660 prefs_register_uint_preference(gui_module, "decimal_places3",
3661 "Count of decimal places for values of type 3",
3662 "Sets the count of decimal places for values of type 3."
3663 "Type 3 values are defined by authors."
3664 "Value can be in range 2 to 10.",
3665 10,&prefs.gui_decimal_places3);
3666
3667 prefs_register_bool_preference(gui_module, "rtp_player_use_disk1",
3668 "RTP Player saves temporary data to disk",
3669 "If set to true, RTP Player saves temporary data to "
3670 "temp files on disk. If not set, it uses memory."
3671 "Every stream uses one file therefore you might touch "
3672 "OS limit for count of opened files."
3673 "When ui.rtp_player_use_disk2 is set to true too, it uses "
3674 " two files per RTP stream together."
3675 ,&prefs.gui_rtp_player_use_disk1);
3676
3677 prefs_register_bool_preference(gui_module, "rtp_player_use_disk2",
3678 "RTP Player saves temporary dictionary for data to disk",
3679 "If set to true, RTP Player saves temporary dictionary to "
3680 "temp files on disk. If not set, it uses memory."
3681 "Every stream uses one file therefore you might touch "
3682 "OS limit for count of opened files."
3683 "When ui.rtp_player_use_disk1 is set to true too, it uses "
3684 " two files per RTP stream."
3685 ,&prefs.gui_rtp_player_use_disk2);
3686
3687 prefs_register_enum_preference(gui_layout_module, "gui_packet_list_copy_format_options_for_keyboard_shortcut",
3688 "Allows text to be copied with selected format",
3689 "Allows text to be copied with selected format when copied via keyboard",
3690 (int*)(void*)(&prefs.gui_packet_list_copy_format_options_for_keyboard_shortcut),
3691 gui_packet_list_copy_format_options_for_keyboard_shortcut, false0);
3692
3693 prefs_register_bool_preference(gui_layout_module, "gui_packet_list_copy_text_with_aligned_columns",
3694 "Allows text to be copied with aligned columns",
3695 "Allows text to be copied with aligned columns when copied via menu or keyboard",
3696 &prefs.gui_packet_list_copy_text_with_aligned_columns);
3697
3698 prefs_register_bool_preference(gui_layout_module, "packet_list_show_related",
3699 "Show Related Packets",
3700 "Show related packet indicators in the first column",
3701 &prefs.gui_packet_list_show_related);
3702
3703 prefs_register_bool_preference(gui_layout_module, "packet_list_show_minimap",
3704 "Enable Intelligent Scroll Bar",
3705 "Show the intelligent scroll bar (a minimap of packet list colors in the scrollbar)",
3706 &prefs.gui_packet_list_show_minimap);
3707
3708 prefs_register_bool_preference(gui_module, "packet_list_is_sortable",
3709 "Allow packet list to be sortable",
3710 "To prevent sorting by mistake (which can take some time to calculate), it can be disabled",
3711 &prefs.gui_packet_list_sortable);
3712
3713 prefs_register_uint_preference(gui_module, "packet_list_cached_rows_max",
3714 "Maximum cached rows",
3715 "Maximum number of rows that can be sorted by columns that require dissection. Increasing this increases memory consumption by caching column text",
3716 10,
3717 &prefs.gui_packet_list_cached_rows_max);
3718
3719 prefs_register_bool_preference(gui_module, "interfaces_show_hidden",
3720 "Show hidden interfaces",
3721 "Show all interfaces, including interfaces marked as hidden",
3722 &prefs.gui_interfaces_show_hidden);
3723
3724 prefs_register_bool_preference(gui_module, "interfaces_remote_display",
3725 "Show Remote interfaces",
3726 "Show remote interfaces in the interface selection",
3727 &prefs.gui_interfaces_remote_display);
3728
3729 register_string_like_preference(gui_module, "interfaces_hidden_types", "Hide interface types in list",
3730 "Hide the given interface types in the startup list.\n"
3731 "A comma-separated string of interface type values (e.g. 5,9).\n"
3732 "0 = Wired,\n"
3733 "1 = AirPCAP,\n"
3734 "2 = Pipe,\n"
3735 "3 = STDIN,\n"
3736 "4 = Bluetooth,\n"
3737 "5 = Wireless,\n"
3738 "6 = Dial-Up,\n"
3739 "7 = USB,\n"
3740 "8 = External Capture,\n"
3741 "9 = Virtual",
3742 &prefs.gui_interfaces_hide_types, PREF_STRING, NULL((void*)0), true1);
3743
3744 prefs_register_bool_preference(gui_module, "io_graph_automatic_update",
3745 "Enables automatic updates for IO Graph",
3746 "Enables automatic updates for IO Graph",
3747 &prefs.gui_io_graph_automatic_update);
3748
3749 prefs_register_bool_preference(gui_module, "io_graph_enable_legend",
3750 "Enables the legend of IO Graph",
3751 "Enables the legend of IO Graph",
3752 &prefs.gui_io_graph_enable_legend);
3753
3754 prefs_register_bool_preference(gui_module, "plot_automatic_update",
3755 "Enables automatic updates for Plot",
3756 "Enables automatic updates for Plot",
3757 &prefs.gui_plot_automatic_update);
3758
3759 prefs_register_bool_preference(gui_module, "plot_enable_legend",
3760 "Enables the legend of Plot",
3761 "Enables the legend of Plot",
3762 &prefs.gui_plot_enable_legend);
3763
3764 prefs_register_bool_preference(gui_module, "plot_enable_auto_scroll",
3765 "Enables auto scroll of Plot",
3766 "Enables auto scroll of Plot",
3767 &prefs.gui_plot_enable_auto_scroll);
3768
3769 prefs_register_bool_preference(gui_module, "show_byteview_in_dialog",
3770 "Show the byte view in the packet details dialog",
3771 "Show the byte view in the packet details dialog",
3772 &prefs.gui_packet_details_show_byteview);
3773
3774 /* Console
3775 * These are preferences that can be read/written using the
3776 * preference module API. These preferences still use their own
3777 * configuration screens for access, but this cuts down on the
3778 * preference "string compare list" in set_pref()
3779 */
3780 console_module = prefs_register_module(NULL((void*)0), "console", "Console",
3781 "Console logging and debugging output", NULL((void*)0), NULL((void*)0), false0);
3782
3783 prefs_register_obsolete_preference(console_module, "log.level");
3784
3785 prefs_register_bool_preference(console_module, "incomplete_dissectors_check_debug",
3786 "Print debug line for incomplete dissectors",
3787 "Look for dissectors that left some bytes undecoded (debug)",
3788 &prefs.incomplete_dissectors_check_debug);
3789
3790 /* Display filter Expressions
3791 * This used to be an array of individual fields that has now been
3792 * converted to a UAT. Just make it part of the GUI category even
3793 * though the name of the preference will never be seen in preference
3794 * file
3795 */
3796 filter_expression_register_uat(gui_module);
3797
3798 /* Capture
3799 * These are preferences that can be read/written using the
3800 * preference module API. These preferences still use their own
3801 * configuration screens for access, but this cuts down on the
3802 * preference "string compare list" in set_pref()
3803 */
3804 capture_module = prefs_register_module(NULL((void*)0), "capture", "Capture",
3805 "Capture preferences", NULL((void*)0), apply_aggregation_prefs, false0);
3806 /* Capture preferences don't affect dissection */
3807 prefs_set_module_effect_flags(capture_module, PREF_EFFECT_CAPTURE(1u << 1));
3808
3809 register_string_like_preference(capture_module, "device", "Default capture device",
3810 "Default capture device",
3811 &prefs.capture_device, PREF_STRING, NULL((void*)0), false0);
3812
3813 register_string_like_preference(capture_module, "devices_linktypes", "Interface link-layer header type",
3814 "Interface link-layer header types (Ex: en0(1),en1(143),...)",
3815 &prefs.capture_devices_linktypes, PREF_STRING, NULL((void*)0), false0);
3816
3817 register_string_like_preference(capture_module, "devices_descr", "Interface descriptions",
3818 "Interface descriptions (Ex: eth0(eth0 descr),eth1(eth1 descr),...)",
3819 &prefs.capture_devices_descr, PREF_STRING, NULL((void*)0), false0);
3820
3821 register_string_like_preference(capture_module, "devices_hide", "Hide interface",
3822 "Hide interface? (Ex: eth0,eth3,...)",
3823 &prefs.capture_devices_hide, PREF_STRING, NULL((void*)0), false0);
3824
3825 register_string_like_preference(capture_module, "devices_monitor_mode", "Capture in monitor mode",
3826 "By default, capture in monitor mode on interface? (Ex: eth0,eth3,...)",
3827 &prefs.capture_devices_monitor_mode, PREF_STRING, NULL((void*)0), false0);
3828
3829 register_string_like_preference(capture_module, "devices_buffersize", "Interface buffer size",
3830 "Interface buffer size (Ex: en0(1),en1(143),...)",
3831 &prefs.capture_devices_buffersize, PREF_STRING, NULL((void*)0), false0);
3832
3833 register_string_like_preference(capture_module, "devices_snaplen", "Interface snap length",
3834 "Interface snap length (Ex: en0(65535),en1(1430),...)",
3835 &prefs.capture_devices_snaplen, PREF_STRING, NULL((void*)0), false0);
3836
3837 register_string_like_preference(capture_module, "devices_pmode", "Interface promiscuous mode",
3838 "Interface promiscuous mode (Ex: en0(0),en1(1),...)",
3839 &prefs.capture_devices_pmode, PREF_STRING, NULL((void*)0), false0);
3840
3841 prefs_register_bool_preference(capture_module, "prom_mode", "Capture in promiscuous mode",
3842 "Capture in promiscuous mode?", &prefs.capture_prom_mode);
3843
3844 prefs_register_bool_preference(capture_module, "monitor_mode", "Capture in monitor mode on 802.11 devices",
3845 "Capture in monitor mode on all 802.11 devices that support it?", &prefs.capture_monitor_mode);
3846
3847 register_string_like_preference(capture_module, "devices_filter", "Interface capture filter",
3848 "Interface capture filter (Ex: en0(tcp),en1(udp),...)",
3849 &prefs.capture_devices_filter, PREF_STRING, NULL((void*)0), false0);
3850
3851 prefs_register_bool_preference(capture_module, "pcap_ng", "Capture in pcapng format",
3852 "Capture in pcapng format?", &prefs.capture_pcap_ng);
3853
3854 prefs_register_bool_preference(capture_module, "real_time_update", "Update packet list in real time during capture",
3855 "Update packet list in real time during capture?", &prefs.capture_real_time);
3856
3857 prefs_register_uint_preference(capture_module, "update_interval",
3858 "Capture update interval",
3859 "Capture update interval in ms",
3860 10,
3861 &prefs.capture_update_interval);
3862
3863 prefs_register_bool_preference(capture_module, "enable_aggregation_view", "Enable aggregation view",
3864 "Enable Aggregation View for real-time capturing", &prefs.enable_aggregation);
3865
3866 prefs_register_bool_preference(capture_module, "no_interface_load", "Don't load interfaces on startup",
3867 "Don't automatically load capture interfaces on startup", &prefs.capture_no_interface_load);
3868
3869 prefs_register_bool_preference(capture_module, "no_extcap", "Disable external capture interfaces",
3870 "Disable external capture modules (extcap)", &prefs.capture_no_extcap);
3871
3872 prefs_register_obsolete_preference(capture_module, "auto_scroll");
3873
3874 prefs_register_bool_preference(capture_module, "show_info", "Show capture information dialog while capturing",
3875 "Show capture information dialog while capturing?", &prefs.capture_show_info);
3876
3877 prefs_register_obsolete_preference(capture_module, "syntax_check_filter");
3878
3879 custom_cbs.free_cb = capture_column_free_cb;
3880 custom_cbs.reset_cb = capture_column_reset_cb;
3881 custom_cbs.set_cb = capture_column_set_cb;
3882 custom_cbs.type_name_cb = capture_column_type_name_cb;
3883 custom_cbs.type_description_cb = capture_column_type_description_cb;
3884 custom_cbs.is_default_cb = capture_column_is_default_cb;
3885 custom_cbs.to_str_cb = capture_column_to_str_cb;
3886 prefs_register_list_custom_preference(capture_module, "columns", "Capture options dialog column list",
3887 "List of columns to be displayed", &custom_cbs, capture_column_init_cb, &prefs.capture_columns);
3888 aggregation_field_register_uat(capture_module);
3889
3890 /* Name Resolution */
3891 nameres_module = prefs_register_module(NULL((void*)0), "nameres", "Name Resolution",
3892 "Name Resolution", "ChCustPreferencesSection.html#ChCustPrefsNameSection", addr_resolve_pref_apply, true1);
3893 addr_resolve_pref_init(nameres_module);
3894 oid_pref_init(nameres_module);
3895 maxmind_db_pref_init(nameres_module);
3896
3897 /* Printing
3898 * None of these have any effect; we keep them as obsolete preferences
3899 * in order to avoid errors when reading older preference files.
3900 */
3901 printing = prefs_register_module(NULL((void*)0), "print", "Printing",
3902 "Printing", NULL((void*)0), NULL((void*)0), false0);
3903 prefs_register_obsolete_preference(printing, "format");
3904 prefs_register_obsolete_preference(printing, "command");
3905 prefs_register_obsolete_preference(printing, "file");
3906
3907 /* Codecs */
3908 codecs_module = prefs_register_module(NULL((void*)0), "codecs", "Codecs",
3909 "Codecs", NULL((void*)0), NULL((void*)0), true1);
3910
3911 /* Statistics */
3912 stats_module = prefs_register_module(NULL((void*)0), "statistics", "Statistics",
3913 "Statistics", "ChCustPreferencesSection.html#_statistics", &stats_callback, true1);
3914
3915 prefs_register_uint_preference(stats_module, "update_interval",
3916 "Tap update interval in ms",
3917 "Determines time between tap updates",
3918 10,
3919 &prefs.tap_update_interval);
3920
3921 prefs_register_uint_preference(stats_module, "flow_graph_max_export_items",
3922 "Maximum Flow Graph items to export as image",
3923 "The maximum number of Flow Graph items (frames) "
3924 "to include when exporting the graph as an image. "
3925 "Note that some formats (e.g., JPEG) have inherent "
3926 "pixel limits and image viewers might be unable to "
3927 "handle very large images.",
3928 10,
3929 &prefs.flow_graph_max_export_items);
3930
3931 prefs_register_bool_preference(stats_module, "st_enable_burstinfo",
3932 "Enable the calculation of burst information",
3933 "If enabled burst rates will be calculated for statistics that use the stats_tree system. "
3934 "Burst rates are calculated over a much shorter time interval than the rate column.",
3935 &prefs.st_enable_burstinfo);
3936
3937 prefs_register_bool_preference(stats_module, "st_burst_showcount",
3938 "Show burst count for item rather than rate",
3939 "If selected the stats_tree statistics nodes will show the count of events "
3940 "within the burst window instead of a burst rate. Burst rate is calculated "
3941 "as number of events within burst window divided by the burst windown length.",
3942 &prefs.st_burst_showcount);
3943
3944 prefs_register_uint_preference(stats_module, "st_burst_resolution",
3945 "Burst rate resolution (ms)",
3946 "Sets the duration of the time interval into which events are grouped when calculating "
3947 "the burst rate. Higher resolution (smaller number) increases processing overhead.",
3948 10,&prefs.st_burst_resolution);
3949
3950 prefs_register_uint_preference(stats_module, "st_burst_windowlen",
3951 "Burst rate window size (ms)",
3952 "Sets the duration of the sliding window during which the burst rate is "
3953 "measured. Longer window relative to burst rate resolution increases "
3954 "processing overhead. Will be truncated to a multiple of burst resolution.",
3955 10,&prefs.st_burst_windowlen);
3956
3957 prefs_register_enum_preference(stats_module, "st_sort_defcolflag",
3958 "Default sort column for stats_tree stats",
3959 "Sets the default column by which stats based on the stats_tree "
3960 "system is sorted.",
3961 &prefs.st_sort_defcolflag, st_sort_col_vals, false0);
3962
3963 prefs_register_bool_preference(stats_module, "st_sort_defdescending",
3964 "Default stats_tree sort order is descending",
3965 "When selected, statistics based on the stats_tree system will by default "
3966 "be sorted in descending order.",
3967 &prefs.st_sort_defdescending);
3968
3969 prefs_register_bool_preference(stats_module, "st_sort_casesensitve",
3970 "Case sensitive sort of stats_tree item names",
3971 "When selected, the item/node names of statistics based on the stats_tree "
3972 "system will be sorted taking case into account. Else the case of the name "
3973 "will be ignored.",
3974 &prefs.st_sort_casesensitve);
3975
3976 prefs_register_bool_preference(stats_module, "st_sort_rng_nameonly",
3977 "Always sort 'range' nodes by name",
3978 "When selected, the stats_tree nodes representing a range of values "
3979 "(0-49, 50-100, etc.) will always be sorted by name (the range of the "
3980 "node). Else range nodes are sorted by the same column as the rest of "
3981 " the tree.",
3982 &prefs.st_sort_rng_nameonly);
3983
3984 prefs_register_bool_preference(stats_module, "st_sort_rng_fixorder",
3985 "Always sort 'range' nodes in ascending order",
3986 "When selected, the stats_tree nodes representing a range of values "
3987 "(0-49, 50-100, etc.) will always be sorted ascending; else it follows "
3988 "the sort direction of the tree. Only effective if \"Always sort "
3989 "'range' nodes by name\" is also selected.",
3990 &prefs.st_sort_rng_fixorder);
3991
3992 prefs_register_bool_preference(stats_module, "st_sort_showfullname",
3993 "Display the full stats_tree plug-in name",
3994 "When selected, the full name (including menu path) of the stats_tree "
3995 "plug-in is show in windows. If cleared the plug-in name is shown "
3996 "without menu path (only the part of the name after last '/' character.)",
3997 &prefs.st_sort_showfullname);
3998
3999 prefs_register_enum_preference(stats_module, "output_format",
4000 "Default output format",
4001 "Sets the default output format for statistical data. Only supported "
4002 "by taps using the stats_tree system currently; other taps may honor "
4003 "this preference in the future. ",
4004 &prefs.st_format, st_format_vals, false0);
4005
4006 module_t *conv_module;
4007 // avoid using prefs_register_stat to prevent lint complaint about recursion
4008 conv_module = prefs_register_module(stats_module, "conv", "Conversations",
4009 "Conversations & Endpoints", NULL((void*)0), NULL((void*)0), true1);
4010 prefs_register_bool_preference(conv_module, "machine_readable",
4011 "Display exact (machine-readable) byte counts",
4012 "When enabled, exact machine-readable byte counts are displayed. "
4013 "When disabled, human readable numbers with SI prefixes are displayed.",
4014 &prefs.conv_machine_readable);
4015
4016 /* Protocols */
4017 protocols_module = prefs_register_module(NULL((void*)0), "protocols", "Protocols",
4018 "Protocols", "ChCustPreferencesSection.html#ChCustPrefsProtocolsSection", NULL((void*)0), true1);
4019
4020 prefs_register_bool_preference(protocols_module, "display_hidden_proto_items",
4021 "Display hidden protocol items",
4022 "Display all hidden protocol items in the packet list.",
4023 &prefs.display_hidden_proto_items);
4024
4025 prefs_register_bool_preference(protocols_module, "display_byte_fields_with_spaces",
4026 "Display byte fields with a space character between bytes",
4027 "Display all byte fields with a space character between each byte in the packet list.",
4028 &prefs.display_byte_fields_with_spaces);
4029
4030 /*
4031 * Note the -t / option only affects the display of the packet timestamp
4032 * in the default time column; this is for all other absolute times.
4033 */
4034 prefs_register_enum_preference(protocols_module, "display_abs_time_ascii",
4035 "Format absolute times like asctime",
4036 "When to format absolute times similar to asctime instead of ISO 8601, for backwards compatibility with older Wireshark.",
4037 (int*)&prefs.display_abs_time_ascii, abs_time_format_options, false0);
4038
4039 prefs_register_bool_preference(protocols_module, "enable_incomplete_dissectors_check",
4040 "Look for incomplete dissectors",
4041 "Look for dissectors that left some bytes undecoded.",
4042 &prefs.enable_incomplete_dissectors_check);
4043
4044 prefs_register_bool_preference(protocols_module, "strict_conversation_tracking_heuristics",
4045 "Enable stricter conversation tracking heuristics",
4046 "Protocols may use things like VLAN ID or interface ID to narrow the potential for duplicate conversations. "
4047 "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",
4048 &prefs.strict_conversation_tracking_heuristics);
4049
4050 prefs_register_bool_preference(protocols_module, "ignore_dup_frames",
4051 "Ignore duplicate frames",
4052 "Ignore frames that are exact duplicates of any previous frame.",
4053 &prefs.ignore_dup_frames);
4054
4055 prefs_register_enum_preference(protocols_module, "conversation_deinterlacing_key",
4056 "Deinterlacing conversations key",
4057 "Separate into different conversations frames that look like duplicates but have different Interface, MAC, or VLAN field values.",
4058 (int *)&prefs.conversation_deinterlacing_key, conv_deint_options, false0);
4059
4060 prefs_register_uint_preference(protocols_module, "ignore_dup_frames_cache_entries",
4061 "The max number of hashes to keep in memory for determining duplicates frames",
4062 "If \"Ignore duplicate frames\" is set, this setting sets the maximum number "
4063 "of cache entries to maintain. A 0 means no limit.",
4064 10, &prefs.ignore_dup_frames_cache_entries);
4065
4066
4067 /* Obsolete preferences
4068 * These "modules" were reorganized/renamed to correspond to their GUI
4069 * configuration screen within the preferences dialog
4070 */
4071
4072 /* taps is now part of the stats module */
4073 prefs_register_module(NULL((void*)0), "taps", "TAPS", "TAPS", NULL((void*)0), NULL((void*)0), false0);
4074 /* packet_list is now part of the protocol (parent) module */
4075 prefs_register_module(NULL((void*)0), "packet_list", "PACKET_LIST", "PACKET_LIST", NULL((void*)0), NULL((void*)0), false0);
4076 /* stream is now part of the gui module */
4077 prefs_register_module(NULL((void*)0), "stream", "STREAM", "STREAM", NULL((void*)0), NULL((void*)0), false0);
4078
4079}
4080
4081/* Parse through a list of comma-separated, possibly quoted strings.
4082 Return a list of the string data. */
4083GList *
4084prefs_get_string_list(const char *str)
4085{
4086 enum { PRE_STRING, IN_QUOT, NOT_IN_QUOT };
4087
4088 int state = PRE_STRING, i = 0;
4089 bool_Bool backslash = false0;
4090 unsigned char cur_c;
4091 const size_t default_size = 64;
4092 GString *slstr = NULL((void*)0);
4093 GList *sl = NULL((void*)0);
4094
4095 /* Allocate a buffer for the first string. */
4096 slstr = g_string_sized_new(default_size);
4097
4098 for (;;) {
4099 cur_c = str[i];
4100 if (cur_c == '\0') {
4101 /* It's the end of the input, so it's the end of the string we
4102 were working on, and there's no more input. */
4103 if (state == IN_QUOT || backslash) {
4104 /* We were in the middle of a quoted string or backslash escape,
4105 and ran out of characters; that's an error. */
4106 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)))))
;
4107 prefs_clear_string_list(sl);
4108 return NULL((void*)0);
4109 }
4110 if (slstr->len > 0)
4111 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))))
);
4112 else
4113 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)))))
;
4114 break;
4115 }
4116 if (cur_c == '"' && !backslash) {
4117 switch (state) {
4118 case PRE_STRING:
4119 /* We hadn't yet started processing a string; this starts the
4120 string, and we're now quoting. */
4121 state = IN_QUOT;
4122 break;
4123 case IN_QUOT:
4124 /* We're in the middle of a quoted string, and we saw a quotation
4125 mark; we're no longer quoting. */
4126 state = NOT_IN_QUOT;
4127 break;
4128 case NOT_IN_QUOT:
4129 /* We're working on a string, but haven't seen a quote; we're
4130 now quoting. */
4131 state = IN_QUOT;
4132 break;
4133 default:
4134 break;
4135 }
4136 } else if (cur_c == '\\' && !backslash) {
4137 /* We saw a backslash, and the previous character wasn't a
4138 backslash; escape the next character.
4139
4140 This also means we've started a new string. */
4141 backslash = true1;
4142 if (state == PRE_STRING)
4143 state = NOT_IN_QUOT;
4144 } else if (cur_c == ',' && state != IN_QUOT && !backslash) {
4145 /* We saw a comma, and we're not in the middle of a quoted string
4146 and it wasn't preceded by a backslash; it's the end of
4147 the string we were working on... */
4148 if (slstr->len > 0) {
4149 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))))
);
4150 slstr = g_string_sized_new(default_size);
4151 }
4152
4153 /* ...and the beginning of a new string. */
4154 state = PRE_STRING;
4155 } else if (!g_ascii_isspace(cur_c)((g_ascii_table[(guchar) (cur_c)] & G_ASCII_SPACE) != 0) || state != PRE_STRING) {
4156 /* Either this isn't a white-space character, or we've started a
4157 string (i.e., already seen a non-white-space character for that
4158 string and put it into the string).
4159
4160 The character is to be put into the string; do so. */
4161 g_string_append_c(slstr, cur_c)g_string_append_c_inline (slstr, cur_c);
4162
4163 /* If it was backslash-escaped, we're done with the backslash escape. */
4164 backslash = false0;
4165 }
4166 i++;
4167 }
4168 return(sl);
4169}
4170
4171char *join_string_list(GList *sl)
4172{
4173 GString *joined_str = g_string_new("");
4174 GList *cur, *first;
4175 char *str;
4176 unsigned item_count = 0;
4177
4178 cur = first = g_list_first(sl);
4179 while (cur) {
4180 item_count++;
4181 str = (char *)cur->data;
4182
4183 if (cur != first)
4184 g_string_append_c(joined_str, ',')g_string_append_c_inline (joined_str, ',');
4185
4186 if (item_count % 2) {
4187 /* Wrap the line. */
4188 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))
;
4189 } else
4190 g_string_append_c(joined_str, ' ')g_string_append_c_inline (joined_str, ' ');
4191
4192 g_string_append_c(joined_str, '"')g_string_append_c_inline (joined_str, '"');
4193 while (*str) {
4194 gunichar uc = g_utf8_get_char (str);
4195
4196 if (uc == '"' || uc == '\\')
4197 g_string_append_c(joined_str, '\\')g_string_append_c_inline (joined_str, '\\');
4198
4199 if (g_unichar_isprint(uc))
4200 g_string_append_unichar (joined_str, uc);
4201
4202 str = g_utf8_next_char (str)(char *)((str) + g_utf8_skip[*(const guchar *)(str)]);
4203 }
4204
4205 g_string_append_c(joined_str, '"')g_string_append_c_inline (joined_str, '"');
4206
4207 cur = cur->next;
4208 }
4209 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))))
;
4210}
4211
4212void
4213prefs_clear_string_list(GList *sl)
4214{
4215 g_list_free_full(sl, g_free);
4216}
4217
4218/*
4219 * Takes a string, a pointer to an array of "enum_val_t"s, and a default int
4220 * value.
4221 * The array must be terminated by an entry with a null "name" string.
4222 *
4223 * If the string matches a "name" string in an entry, the value from that
4224 * entry is returned.
4225 *
4226 * Otherwise, if a string matches a "description" string in an entry, the
4227 * value from that entry is returned; we do that for backwards compatibility,
4228 * as we used to have only a "name" string that was used both for command-line
4229 * and configuration-file values and in the GUI (which meant either that
4230 * the GUI had what might be somewhat cryptic values to select from or that
4231 * the "-o" flag took long strings, often with spaces in them).
4232 *
4233 * Otherwise, the default value that was passed as the third argument is
4234 * returned.
4235 */
4236static int
4237find_val_for_string(const char *needle, const enum_val_t *haystack,
4238 int default_value)
4239{
4240 int i;
4241
4242 for (i = 0; haystack[i].name != NULL((void*)0); i++) {
4243 if (g_ascii_strcasecmp(needle, haystack[i].name) == 0) {
4244 return haystack[i].value;
4245 }
4246 }
4247 for (i = 0; haystack[i].name != NULL((void*)0); i++) {
4248 if (g_ascii_strcasecmp(needle, haystack[i].description) == 0) {
4249 return haystack[i].value;
4250 }
4251 }
4252 return default_value;
4253}
4254
4255/* Preferences file format:
4256 * - Configuration directives start at the beginning of the line, and
4257 * are terminated with a colon.
4258 * - Directives can be continued on the next line by preceding them with
4259 * whitespace.
4260 *
4261 * Example:
4262
4263# This is a comment line
4264print.command: lpr
4265print.file: /a/very/long/path/
4266 to/wireshark-out.ps
4267 *
4268 */
4269
4270/* Initialize non-dissector preferences to wired-in default values Called
4271 * at program startup and any time the profile changes. (The dissector
4272 * preferences are assumed to be set to those values by the dissectors.)
4273 * They may be overridden by the global preferences file or the user's
4274 * preferences file.
4275 */
4276static void
4277init_prefs(void)
4278{
4279 if (prefs_initialized)
4280 return;
4281
4282 uat_load_all();
4283
4284 /*
4285 * Ensure the "global" preferences have been initialized so the
4286 * preference API has the proper default values to work from
4287 */
4288 pre_init_prefs();
4289
4290 prefs_register_modules();
4291
4292 prefs_initialized = true1;
4293}
4294
4295/*
4296 * Initialize non-dissector preferences used by the "register preference" API
4297 * to default values so the default values can be used when registered.
4298 *
4299 * String, filename, and directory preferences will be g_freed so they must
4300 * be g_mallocated.
4301 */
4302static void
4303pre_init_prefs(void)
4304{
4305 int i;
4306 char *col_name;
4307 fmt_data *cfmt;
4308 static const char *col_fmt_packets[] = {
4309 "No.", "%m", "Time", "%t",
4310 "Source", "%s", "Destination", "%d",
4311 "Protocol", "%p", "Length", "%L",
4312 "Info", "%i" };
4313 static const char **col_fmt = col_fmt_packets;
4314 int num_cols = 7;
4315
4316 if (application_flavor_is_stratoshark()) {
4317 static const char *col_fmt_logs[] = {
4318 "No.", "%m",
4319 "Time", "%t",
4320 "Event name", "%Cus:sysdig.event_name:0:R",
4321 "Dir", "%Cus:evt.dir:0:R",
4322 "Proc Name", "%Cus:proc.name:0:R",
4323 "PID", "%Cus:proc.pid:0:R",
4324 "TID", "%Cus:thread.tid:0:R",
4325 "FD", "%Cus:fd.num:0:R",
4326 "FD Name", "%Cus:fd.name:0:R",
4327 "Container Name", "%Cus:container.name:0:R",
4328 "Arguments", "%Cus:evt.args:0:R",
4329 "Info", "%i"
4330 };
4331 col_fmt = col_fmt_logs;
4332 num_cols = 12;
4333 }
4334
4335 prefs.restore_filter_after_following_stream = false0;
4336 prefs.gui_toolbar_main_style = TB_STYLE_ICONS0;
4337 /* We try to find the best font in the Qt code */
4338 g_free(prefs.gui_font_name);
4339 prefs.gui_font_name = g_strdup("")g_strdup_inline ("");
4340 prefs.gui_active_fg.red = 0;
4341 prefs.gui_active_fg.green = 0;
4342 prefs.gui_active_fg.blue = 0;
4343 prefs.gui_active_bg.red = 52223;
4344 prefs.gui_active_bg.green = 59647;
4345 prefs.gui_active_bg.blue = 65535;
4346 prefs.gui_active_style = COLOR_STYLE_DEFAULT0;
4347 prefs.gui_inactive_fg.red = 0;
4348 prefs.gui_inactive_fg.green = 0;
4349 prefs.gui_inactive_fg.blue = 0;
4350 prefs.gui_inactive_bg.red = 61439;
4351 prefs.gui_inactive_bg.green = 61439;
4352 prefs.gui_inactive_bg.blue = 61439;
4353 prefs.gui_inactive_style = COLOR_STYLE_DEFAULT0;
4354 prefs.gui_marked_fg.red = 65535;
4355 prefs.gui_marked_fg.green = 65535;
4356 prefs.gui_marked_fg.blue = 65535;
4357 prefs.gui_marked_bg.red = 0;
4358 prefs.gui_marked_bg.green = 8224;
4359 prefs.gui_marked_bg.blue = 10794;
4360 prefs.gui_ignored_fg.red = 32767;
4361 prefs.gui_ignored_fg.green = 32767;
4362 prefs.gui_ignored_fg.blue = 32767;
4363 prefs.gui_ignored_bg.red = 65535;
4364 prefs.gui_ignored_bg.green = 65535;
4365 prefs.gui_ignored_bg.blue = 65535;
4366 g_free(prefs.gui_colorized_fg);
4367 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"
)
;
4368 g_free(prefs.gui_colorized_bg);
4369 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"
)
;
4370 prefs.st_client_fg.red = 32767;
4371 prefs.st_client_fg.green = 0;
4372 prefs.st_client_fg.blue = 0;
4373 prefs.st_client_bg.red = 64507;
4374 prefs.st_client_bg.green = 60909;
4375 prefs.st_client_bg.blue = 60909;
4376 prefs.st_server_fg.red = 0;
4377 prefs.st_server_fg.green = 0;
4378 prefs.st_server_fg.blue = 32767;
4379 prefs.st_server_bg.red = 60909;
4380 prefs.st_server_bg.green = 60909;
4381 prefs.st_server_bg.blue = 64507;
4382
4383 if (gui_theme_is_dark) {
4384 // Green, red and yellow with HSV V = 84
4385 prefs.gui_filter_valid_bg.red = 0x0000; /* dark green */
4386 prefs.gui_filter_valid_bg.green = 0x66ff;
4387 prefs.gui_filter_valid_bg.blue = 0x0000;
4388 prefs.gui_filter_valid_fg.red = 0xFFFF;
4389 prefs.gui_filter_valid_fg.green = 0xFFFF;
4390 prefs.gui_filter_valid_fg.blue = 0xFFFF;
4391 prefs.gui_filter_invalid_bg.red = 0x66FF; /* dark red */
4392 prefs.gui_filter_invalid_bg.green = 0x0000;
4393 prefs.gui_filter_invalid_bg.blue = 0x0000;
4394 prefs.gui_filter_invalid_fg.red = 0xFFFF;
4395 prefs.gui_filter_invalid_fg.green = 0xFFFF;
4396 prefs.gui_filter_invalid_fg.blue = 0xFFFF;
4397 prefs.gui_filter_deprecated_bg.red = 0x66FF; /* dark yellow / olive */
4398 prefs.gui_filter_deprecated_bg.green = 0x66FF;
4399 prefs.gui_filter_deprecated_bg.blue = 0x0000;
4400 prefs.gui_filter_deprecated_fg.red = 0xFFFF;
4401 prefs.gui_filter_deprecated_fg.green = 0xFFFF;
4402 prefs.gui_filter_deprecated_fg.blue = 0xFFFF;
4403 } else {
4404 // Green, red and yellow with HSV V = 20
4405 prefs.gui_filter_valid_bg.red = 0xAFFF; /* light green */
4406 prefs.gui_filter_valid_bg.green = 0xFFFF;
4407 prefs.gui_filter_valid_bg.blue = 0xAFFF;
4408 prefs.gui_filter_valid_fg.red = 0x0000;
4409 prefs.gui_filter_valid_fg.green = 0x0000;
4410 prefs.gui_filter_valid_fg.blue = 0x0000;
4411 prefs.gui_filter_invalid_bg.red = 0xFFFF; /* light red */
4412 prefs.gui_filter_invalid_bg.green = 0xAFFF;
4413 prefs.gui_filter_invalid_bg.blue = 0xAFFF;
4414 prefs.gui_filter_invalid_fg.red = 0x0000;
4415 prefs.gui_filter_invalid_fg.green = 0x0000;
4416 prefs.gui_filter_invalid_fg.blue = 0x0000;
4417 prefs.gui_filter_deprecated_bg.red = 0xFFFF; /* light yellow */
4418 prefs.gui_filter_deprecated_bg.green = 0xFFFF;
4419 prefs.gui_filter_deprecated_bg.blue = 0xAFFF;
4420 prefs.gui_filter_deprecated_fg.red = 0x0000;
4421 prefs.gui_filter_deprecated_fg.green = 0x0000;
4422 prefs.gui_filter_deprecated_fg.blue = 0x0000;
4423 }
4424
4425 prefs.gui_geometry_save_position = true1;
4426 prefs.gui_geometry_save_size = true1;
4427 prefs.gui_geometry_save_maximized= true1;
4428 prefs.gui_fileopen_style = FO_STYLE_LAST_OPENED0;
4429 prefs.gui_recent_df_entries_max = 10;
4430 prefs.gui_recent_files_count_max = 10;
4431 g_free(prefs.gui_fileopen_dir);
4432 prefs.gui_fileopen_dir = g_strdup(get_persdatafile_dir())g_strdup_inline (get_persdatafile_dir());
4433 prefs.gui_fileopen_preview = 3;
4434 g_free(prefs.gui_tlskeylog_command);
4435 prefs.gui_tlskeylog_command = g_strdup("")g_strdup_inline ("");
4436 prefs.gui_ask_unsaved = true1;
4437 prefs.gui_autocomplete_filter = true1;
4438 prefs.gui_find_wrap = true1;
4439 prefs.gui_update_enabled = true1;
4440 prefs.gui_update_channel = UPDATE_CHANNEL_STABLE;
4441 prefs.gui_update_interval = 60*60*24; /* Seconds */
4442 prefs.gui_debounce_timer = 400; /* milliseconds */
4443 g_free(prefs.gui_window_title);
4444 prefs.gui_window_title = g_strdup("")g_strdup_inline ("");
4445 g_free(prefs.gui_prepend_window_title);
4446 prefs.gui_prepend_window_title = g_strdup("")g_strdup_inline ("");
4447 g_free(prefs.gui_start_title);
4448 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"
)
;
4449 prefs.gui_version_placement = version_both;
4450 prefs.gui_welcome_page_show_recent = true1;
4451 prefs.gui_layout_type = layout_type_2;
4452 prefs.gui_layout_content_1 = layout_pane_content_plist;
4453 prefs.gui_layout_content_2 = layout_pane_content_pdetails;
4454 prefs.gui_layout_content_3 = layout_pane_content_pbytes;
4455 prefs.gui_packet_list_elide_mode = ELIDE_RIGHT;
4456 prefs.gui_packet_list_copy_format_options_for_keyboard_shortcut = COPY_FORMAT_TEXT;
4457 prefs.gui_packet_list_copy_text_with_aligned_columns = false0;
4458 prefs.gui_packet_list_show_related = true1;
4459 prefs.gui_packet_list_show_minimap = true1;
4460 prefs.gui_packet_list_sortable = true1;
4461 prefs.gui_packet_list_cached_rows_max = 10000;
4462 g_free (prefs.gui_interfaces_hide_types);
4463 prefs.gui_interfaces_hide_types = g_strdup("")g_strdup_inline ("");
4464 prefs.gui_interfaces_show_hidden = false0;
4465 prefs.gui_interfaces_remote_display = true1;
4466 prefs.gui_packet_list_separator = false0;
4467 prefs.gui_packet_header_column_definition = true1;
4468 prefs.gui_packet_list_hover_style = true1;
4469 prefs.gui_show_selected_packet = false0;
4470 prefs.gui_show_file_load_time = false0;
4471 prefs.gui_max_export_objects = 1000;
4472 prefs.gui_max_tree_items = 1 * 1000 * 1000;
4473 prefs.gui_max_tree_depth = 5 * 100;
4474 prefs.gui_decimal_places1 = DEF_GUI_DECIMAL_PLACES12;
4475 prefs.gui_decimal_places2 = DEF_GUI_DECIMAL_PLACES24;
4476 prefs.gui_decimal_places3 = DEF_GUI_DECIMAL_PLACES36;
4477
4478 if (prefs.col_list) {
4479 free_col_info(prefs.col_list);
4480 prefs.col_list = NULL((void*)0);
4481 }
4482 for (i = 0; i < num_cols; i++) {
4483 cfmt = g_new0(fmt_data,1)((fmt_data *) g_malloc0_n ((1), sizeof (fmt_data)));
4484 cfmt->title = g_strdup(col_fmt[i * 2])g_strdup_inline (col_fmt[i * 2]);
4485 cfmt->visible = true1;
4486 cfmt->display = COLUMN_DISPLAY_STRINGS'R';
4487 parse_column_format(cfmt, col_fmt[(i * 2) + 1]);
4488 prefs.col_list = g_list_append(prefs.col_list, cfmt);
4489 }
4490 prefs.num_cols = num_cols;
4491
4492/* set the default values for the capture dialog box */
4493 prefs.capture_prom_mode = true1;
4494 prefs.capture_monitor_mode = false0;
4495 prefs.capture_pcap_ng = true1;
4496 prefs.capture_real_time = true1;
4497 prefs.capture_update_interval = DEFAULT_UPDATE_INTERVAL100;
4498 prefs.capture_no_extcap = false0;
4499 prefs.capture_show_info = false0;
4500 prefs.enable_aggregation = false0;
4501
4502 if (!prefs.capture_columns) {
4503 /* First time through */
4504 for (i = 0; i < num_capture_cols; i++) {
4505 col_name = g_strdup(capture_cols[i])g_strdup_inline (capture_cols[i]);
4506 prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
4507 }
4508 }
4509
4510/* set the default values for the tap/statistics dialog box */
4511 prefs.tap_update_interval = TAP_UPDATE_DEFAULT_INTERVAL3000;
4512 prefs.flow_graph_max_export_items = 1000;
4513 prefs.st_enable_burstinfo = true1;
4514 prefs.st_burst_showcount = false0;
4515 prefs.st_burst_resolution = ST_DEF_BURSTRES5;
4516 prefs.st_burst_windowlen = ST_DEF_BURSTLEN100;
4517 prefs.st_sort_casesensitve = true1;
4518 prefs.st_sort_rng_fixorder = true1;
4519 prefs.st_sort_rng_nameonly = true1;
4520 prefs.st_sort_defcolflag = ST_SORT_COL_COUNT2;
4521 prefs.st_sort_defdescending = true1;
4522 prefs.st_sort_showfullname = false0;
4523 prefs.conv_machine_readable = false0;
4524
4525 /* protocols */
4526 prefs.display_hidden_proto_items = false0;
4527 prefs.display_byte_fields_with_spaces = false0;
4528 prefs.display_abs_time_ascii = ABS_TIME_ASCII_TREE;
4529 prefs.ignore_dup_frames = false0;
4530 prefs.ignore_dup_frames_cache_entries = 10000;
4531
4532 /* set the default values for the io graph dialog */
4533 prefs.gui_io_graph_automatic_update = true1;
4534 prefs.gui_io_graph_enable_legend = true1;
4535
4536 /* set the default values for the plot dialog */
4537 prefs.gui_plot_automatic_update = true1;
4538 prefs.gui_plot_enable_legend = true1;
4539 prefs.gui_plot_enable_auto_scroll = false0;
4540
4541 /* set the default values for the packet dialog */
4542 prefs.gui_packet_dialog_layout = layout_vertical;
4543 prefs.gui_packet_details_show_byteview = true1;
4544}
4545
4546/*
4547 * Reset a single dissector preference.
4548 */
4549void
4550reset_pref(pref_t *pref)
4551{
4552 if (!pref) return;
4553
4554 /*
4555 * This preference is no longer supported; it's not a
4556 * real preference, so we don't reset it (i.e., we
4557 * treat it as if it weren't found in the list of
4558 * preferences, and we weren't called in the first place).
4559 */
4560 if (pref->obsolete)
4561 return;
4562
4563 switch (pref->type) {
4564
4565 case PREF_UINT:
4566 *pref->varp.uint = pref->default_val.uint;
4567 break;
4568
4569 case PREF_BOOL:
4570 *pref->varp.boolp = pref->default_val.boolval;
4571 break;
4572
4573 case PREF_ENUM:
4574 case PREF_PROTO_TCP_SNDAMB_ENUM:
4575 *pref->varp.enump = pref->default_val.enumval;
4576 break;
4577
4578 case PREF_STRING:
4579 case PREF_SAVE_FILENAME:
4580 case PREF_OPEN_FILENAME:
4581 case PREF_DIRNAME:
4582 case PREF_PASSWORD:
4583 case PREF_DISSECTOR:
4584 reset_string_like_preference(pref);
4585 break;
4586
4587 case PREF_RANGE:
4588 case PREF_DECODE_AS_RANGE:
4589 wmem_free(wmem_epan_scope(), *pref->varp.range);
4590 *pref->varp.range = range_copy(wmem_epan_scope(), pref->default_val.range);
4591 break;
4592
4593 case PREF_STATIC_TEXT:
4594 case PREF_UAT:
4595 /* Nothing to do */
4596 break;
4597
4598 case PREF_COLOR:
4599 *pref->varp.colorp = pref->default_val.color;
4600 break;
4601
4602 case PREF_CUSTOM:
4603 pref->custom_cbs.reset_cb(pref);
4604 break;
4605 }
4606}
4607
4608static void
4609reset_pref_cb(void *data, void *user_data)
4610{
4611 pref_t *pref = (pref_t *) data;
4612 module_t *module = (module_t *)user_data;
4613
4614 if (pref && (pref->type == PREF_RANGE || pref->type == PREF_DECODE_AS_RANGE)) {
4615 /*
4616 * Some dissectors expect the range (returned via prefs_get_range_value)
4617 * to remain valid if it has not changed. If it did change, then we
4618 * should set "prefs_changed_flags" to ensure that the preference apply
4619 * callback is invoked. That callback will notify dissectors that it
4620 * should no longer assume the range to be valid.
4621 */
4622 if (ranges_are_equal(*pref->varp.range, pref->default_val.range)) {
4623 /* Optimization: do not invoke apply callback if nothing changed. */
4624 return;
4625 }
4626 module->prefs_changed_flags |= prefs_get_effect_flags(pref);
4627 }
4628 reset_pref(pref);
4629}
4630
4631/*
4632 * Reset all preferences for a module.
4633 */
4634static bool_Bool
4635reset_module_prefs(const void *key _U___attribute__((unused)), void *value, void *data _U___attribute__((unused)))
4636{
4637 module_t *module = (module_t *)value;
4638 g_list_foreach(module->prefs, reset_pref_cb, module);
4639 return false0;
4640}
4641
4642/* Reset preferences */
4643void
4644prefs_reset(void)
4645{
4646 prefs_initialized = false0;
4647 g_free(prefs.saved_at_version);
4648 prefs.saved_at_version = NULL((void*)0);
4649
4650 /*
4651 * Unload all UAT preferences.
4652 */
4653 uat_unload_all();
4654
4655 /*
4656 * Unload any loaded MIBs.
4657 */
4658 oids_cleanup();
4659
4660 /*
4661 * Reset the non-dissector preferences.
4662 */
4663 init_prefs();
4664
4665 /*
4666 * Reset the non-UAT dissector preferences.
4667 */
4668 wmem_tree_foreach(prefs_modules, reset_module_prefs, NULL((void*)0));
4669}
4670
4671#ifdef _WIN32
4672static void
4673read_registry(void)
4674{
4675 HKEY hTestKey;
4676 DWORD data;
4677 DWORD data_size = sizeof(DWORD);
4678 DWORD ret;
4679
4680 ret = RegOpenKeyExA(HKEY_CURRENT_USER, REG_HKCU_WIRESHARK_KEY"Software\\Wireshark", 0, KEY_READ, &hTestKey);
4681 if (ret != ERROR_SUCCESS && ret != ERROR_FILE_NOT_FOUND) {
4682 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"
, 4682, __func__, "Cannot open HKCU ""Software\\Wireshark"": 0x%lx"
, ret); } } while (0)
;
4683 return;
4684 }
4685
4686 ret = RegQueryValueExA(hTestKey, LOG_HKCU_CONSOLE_OPEN"ConsoleOpen", NULL((void*)0), NULL((void*)0), (LPBYTE)&data, &data_size);
4687 if (ret == ERROR_SUCCESS) {
4688 ws_log_console_open = (ws_log_console_open_pref)data;
4689 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"
, 4689, __func__, "Got ""ConsoleOpen"" from Windows registry: %d"
, ws_log_console_open); } } while (0)
;
4690 }
4691 else if (ret != ERROR_FILE_NOT_FOUND) {
4692 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"
, 4692, __func__, "Error reading registry key ""ConsoleOpen"": 0x%lx"
, ret); } } while (0)
;
4693 }
4694
4695 RegCloseKey(hTestKey);
4696}
4697#endif
4698
4699void
4700prefs_read_module(const char *module)
4701{
4702 int err;
4703 char *pf_path;
4704 FILE *pf;
4705
4706 module_t *target_module = prefs_find_module(module);
4707 if (!target_module) {
4708 return;
4709 }
4710
4711 /* Construct the pathname of the user's preferences file for the module. */
4712 char *pf_name = wmem_strdup_printf(NULL((void*)0), "%s.cfg", module);
4713 pf_path = get_persconffile_path(pf_name, true1);
4714 wmem_free(NULL((void*)0), pf_name);
4715
4716 /* Read the user's module preferences file, if it exists and is not a dir. */
4717 if (!test_for_regular_file(pf_path) || ((pf = ws_fopenfopen(pf_path, "r")) == NULL((void*)0))) {
4718 g_free(pf_path);
4719 /* Fall back to the user's generic preferences file. */
4720 pf_path = get_persconffile_path(PF_NAME"preferences", true1);
4721 pf = ws_fopenfopen(pf_path, "r");
4722 }
4723
4724 if (pf != NULL((void*)0)) {
4725 /* We succeeded in opening it; read it. */
4726 err = read_prefs_file(pf_path, pf, set_pref, target_module);
4727 if (err != 0) {
4728 /* We had an error reading the file; report it. */
4729 report_warning("Error reading your preferences file \"%s\": %s.",
4730 pf_path, g_strerror(err));
4731 } else
4732 g_free(pf_path);
4733 fclose(pf);
4734 } else {
4735 /* We failed to open it. If we failed for some reason other than
4736 "it doesn't exist", return the errno and the pathname, so our
4737 caller can report the error. */
4738 if (errno(*__errno_location ()) != ENOENT2) {
4739 report_warning("Can't open your preferences file \"%s\": %s.",
4740 pf_path, g_strerror(errno(*__errno_location ())));
4741 } else
4742 g_free(pf_path);
4743 }
4744
4745 return;
4746}
4747
4748/* Read the preferences file, fill in "prefs", and return a pointer to it.
4749
4750 If we got an error (other than "it doesn't exist") we report it through
4751 the UI. */
4752e_prefs *
4753read_prefs(void)
4754{
4755 int err;
4756 char *pf_path;
4757 FILE *pf;
4758
4759 /* clean up libsmi structures before reading prefs */
4760 oids_cleanup();
4761
4762 init_prefs();
4763
4764#ifdef _WIN32
4765 read_registry();
4766#endif
4767
4768 /*
4769 * If we don't already have the pathname of the global preferences
4770 * file, construct it. Then, in either case, try to open the file.
4771 */
4772 if (gpf_path == NULL((void*)0)) {
4773 /*
4774 * We don't have the path; try the new path first, and, if that
4775 * file doesn't exist, try the old path.
4776 */
4777 gpf_path = get_datafile_path(PF_NAME"preferences");
4778 if ((pf = ws_fopenfopen(gpf_path, "r")) == NULL((void*)0) && errno(*__errno_location ()) == ENOENT2) {
4779 /*
4780 * It doesn't exist by the new name; try the old name.
4781 */
4782 g_free(gpf_path);
4783 gpf_path = get_datafile_path(OLD_GPF_NAME"wireshark.conf");
4784 pf = ws_fopenfopen(gpf_path, "r");
4785 }
4786 } else {
4787 /*
4788 * We have the path; try it.
4789 */
4790 pf = ws_fopenfopen(gpf_path, "r");
4791 }
4792
4793 /*
4794 * If we were able to open the file, read it.
4795 * XXX - if it failed for a reason other than "it doesn't exist",
4796 * report the error.
4797 */
4798 if (pf != NULL((void*)0)) {
4799 /*
4800 * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
4801 * seen.
4802 */
4803 mgcp_tcp_port_count = 0;
4804 mgcp_udp_port_count = 0;
4805
4806 /* We succeeded in opening it; read it. */
4807 err = read_prefs_file(gpf_path, pf, set_pref, NULL((void*)0));
4808 if (err != 0) {
4809 /* We had an error reading the file; report it. */
4810 report_warning("Error reading global preferences file \"%s\": %s.",
4811 gpf_path, g_strerror(err));
4812 }
4813 fclose(pf);
4814 } else {
4815 /* We failed to open it. If we failed for some reason other than
4816 "it doesn't exist", report the error. */
4817 if (errno(*__errno_location ()) != ENOENT2) {
4818 if (errno(*__errno_location ()) != 0) {
4819 report_warning("Can't open global preferences file \"%s\": %s.",
4820 gpf_path, g_strerror(errno(*__errno_location ())));
4821 }
4822 }
4823 }
4824
4825 /* Construct the pathname of the user's preferences file. */
4826 pf_path = get_persconffile_path(PF_NAME"preferences", true1);
4827
4828 /* Read the user's preferences file, if it exists. */
4829 if ((pf = ws_fopenfopen(pf_path, "r")) != NULL((void*)0)) {
4830 /*
4831 * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
4832 * seen.
4833 */
4834 mgcp_tcp_port_count = 0;
4835 mgcp_udp_port_count = 0;
4836
4837 /* We succeeded in opening it; read it. */
4838 err = read_prefs_file(pf_path, pf, set_pref, NULL((void*)0));
4839 if (err != 0) {
4840 /* We had an error reading the file; report it. */
4841 report_warning("Error reading your preferences file \"%s\": %s.",
4842 pf_path, g_strerror(err));
4843 } else
4844 g_free(pf_path);
4845 fclose(pf);
4846 } else {
4847 /* We failed to open it. If we failed for some reason other than
4848 "it doesn't exist", return the errno and the pathname, so our
4849 caller can report the error. */
4850 if (errno(*__errno_location ()) != ENOENT2) {
4851 report_warning("Can't open your preferences file \"%s\": %s.",
4852 pf_path, g_strerror(errno(*__errno_location ())));
4853 } else
4854 g_free(pf_path);
4855 }
4856
4857 /* load SMI modules if needed */
4858 oids_init();
4859
4860 return &prefs;
4861}
4862
4863/* read the preferences file (or similar) and call the callback
4864 * function to set each key/value pair found */
4865int
4866read_prefs_file(const char *pf_path, FILE *pf,
4867 pref_set_pair_cb pref_set_pair_fct, void *private_data)
4868{
4869 enum {
4870 START, /* beginning of a line */
4871 IN_VAR, /* processing key name */
4872 PRE_VAL, /* finished processing key name, skipping white space before value */
4873 IN_VAL, /* processing value */
4874 IN_SKIP /* skipping to the end of the line */
4875 } state = START;
4876 int got_c;
4877 GString *cur_val;
4878 GString *cur_var;
4879 bool_Bool got_val = false0;
4880 int fline = 1, pline = 1;
4881 char hint[] = "(save preferences to remove this warning)";
4882 char ver[128];
4883
4884 cur_val = g_string_new("");
4885 cur_var = g_string_new("");
4886
4887 /* Try to read in the profile name in the first line of the preferences file. */
4888 if (fscanf(pf, "# Configuration file for %127[^\r\n]", ver) == 1) {
1
Assuming the condition is false
2
Taking false branch
4889 /* Assume trailing period and remove it */
4890 g_free(prefs.saved_at_version);
4891 prefs.saved_at_version = g_strndup(ver, strlen(ver) - 1);
4892 }
4893 rewind(pf);
3
After calling 'rewind' reading 'errno' is required to find out if the call has failed
4894
4895 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'
4896 if (got_c == '\r') {
4897 /* Treat CR-LF at the end of a line like LF, so that if we're reading
4898 * a Windows-format file on UN*X, we handle it the same way we'd handle
4899 * a UN*X-format file. */
4900 got_c = ws_getc_unlockedgetc_unlocked(pf);
4901 if (got_c == EOF(-1))
4902 break;
4903 if (got_c != '\n') {
4904 /* Put back the character after the CR, and process the CR normally. */
4905 ungetc(got_c, pf);
4906 got_c = '\r';
4907 }
4908 }
4909 if (got_c == '\n') {
4910 state = START;
4911 fline++;
4912 continue;
4913 }
4914
4915 switch (state) {
4916 case START:
4917 if (g_ascii_isalnum(got_c)((g_ascii_table[(guchar) (got_c)] & G_ASCII_ALNUM) != 0)) {
4918 if (cur_var->len > 0) {
4919 if (got_val) {
4920 if (cur_val->len > 0) {
4921 if (cur_val->str[cur_val->len-1] == ',') {
4922 /*
4923 * If the pref has a trailing comma, eliminate it.
4924 */
4925 cur_val->str[cur_val->len-1] = '\0';
4926 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"
, 4926, __func__, "%s line %d: trailing comma in \"%s\" %s", pf_path
, pline, cur_var->str, hint); } } while (0)
;
4927 }
4928 }
4929 /* Call the routine to set the preference; it will parse
4930 the value as appropriate.
4931
4932 Since we're reading a file, rather than processing
4933 explicit user input, for range preferences, silently
4934 lower values in excess of the range's maximum, rather
4935 than reporting errors and failing. */
4936 switch (pref_set_pair_fct(cur_var->str, cur_val->str, private_data, false0)) {
4937
4938 case PREFS_SET_OK:
4939 break;
4940
4941 case PREFS_SET_SYNTAX_ERR:
4942 report_warning("Syntax error in preference \"%s\" at line %d of\n%s %s",
4943 cur_var->str, pline, pf_path, hint);
4944 break;
4945
4946 case PREFS_SET_NO_SUCH_PREF:
4947 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"
, 4948, __func__, "No such preference \"%s\" at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
4948 cur_var->str, pline, pf_path, hint)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 4948, __func__, "No such preference \"%s\" at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
;
4949 prefs.unknown_prefs = true1;
4950 break;
4951
4952 case PREFS_SET_OBSOLETE:
4953 /*
4954 * If an attempt is made to save the
4955 * preferences, a popup warning will be
4956 * displayed stating that obsolete prefs
4957 * have been detected and the user will
4958 * be given the opportunity to save these
4959 * prefs under a different profile name.
4960 * The prefs in question need to be listed
4961 * in the console window so that the
4962 * user can make an informed choice.
4963 */
4964 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"
, 4965, __func__, "Obsolete preference \"%s\" at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
4965 cur_var->str, pline, pf_path, hint)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 4965, __func__, "Obsolete preference \"%s\" at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
;
4966 prefs.unknown_prefs = true1;
4967 break;
4968 }
4969 } else {
4970 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"
, 4970, __func__, "Incomplete preference at line %d: of\n%s %s"
, pline, pf_path, hint); } } while (0)
;
4971 }
4972 }
4973 state = IN_VAR;
4974 got_val = false0;
4975 g_string_truncate(cur_var, 0)g_string_truncate_inline (cur_var, 0);
4976 g_string_append_c(cur_var, (char) got_c)g_string_append_c_inline (cur_var, (char) got_c);
4977 pline = fline;
4978 } else if (g_ascii_isspace(got_c)((g_ascii_table[(guchar) (got_c)] & G_ASCII_SPACE) != 0) && cur_var->len > 0 && got_val) {
4979 state = PRE_VAL;
4980 } else if (got_c == '#') {
4981 state = IN_SKIP;
4982 } else {
4983 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"
, 4983, __func__, "Malformed preference at line %d of\n%s %s"
, fline, pf_path, hint); } } while (0)
;
4984 }
4985 break;
4986 case IN_VAR:
4987 if (got_c != ':') {
4988 g_string_append_c(cur_var, (char) got_c)g_string_append_c_inline (cur_var, (char) got_c);
4989 } else {
4990 /* This is a colon (':') */
4991 state = PRE_VAL;
4992 g_string_truncate(cur_val, 0)g_string_truncate_inline (cur_val, 0);
4993 /*
4994 * Set got_val to true to accommodate prefs such as
4995 * "gui.fileopen.dir" that do not require a value.
4996 */
4997 got_val = true1;
4998 }
4999 break;
5000 case PRE_VAL:
5001 if (!g_ascii_isspace(got_c)((g_ascii_table[(guchar) (got_c)] & G_ASCII_SPACE) != 0)) {
5002 state = IN_VAL;
5003 g_string_append_c(cur_val, (char) got_c)g_string_append_c_inline (cur_val, (char) got_c);
5004 }
5005 break;
5006 case IN_VAL:
5007 g_string_append_c(cur_val, (char) got_c)g_string_append_c_inline (cur_val, (char) got_c);
5008 break;
5009 case IN_SKIP:
5010 break;
5011 }
5012 }
5013 if (cur_var->len > 0) {
5014 if (got_val) {
5015 /* Call the routine to set the preference; it will parse
5016 the value as appropriate.
5017
5018 Since we're reading a file, rather than processing
5019 explicit user input, for range preferences, silently
5020 lower values in excess of the range's maximum, rather
5021 than reporting errors and failing. */
5022 switch (pref_set_pair_fct(cur_var->str, cur_val->str, private_data, false0)) {
5023
5024 case PREFS_SET_OK:
5025 break;
5026
5027 case PREFS_SET_SYNTAX_ERR:
5028 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"
, 5029, __func__, "Syntax error in preference %s at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
5029 cur_var->str, pline, pf_path, hint)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 5029, __func__, "Syntax error in preference %s at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
;
5030 break;
5031
5032 case PREFS_SET_NO_SUCH_PREF:
5033 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"
, 5034, __func__, "No such preference \"%s\" at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
5034 cur_var->str, pline, pf_path, hint)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 5034, __func__, "No such preference \"%s\" at line %d of\n%s %s"
, cur_var->str, pline, pf_path, hint); } } while (0)
;
5035 prefs.unknown_prefs = true1;
5036 break;
5037
5038 case PREFS_SET_OBSOLETE:
5039 prefs.unknown_prefs = true1;
5040 break;
5041 }
5042 } else {
5043 ws_warning("Incomplete preference at line %d of\n%s %s",do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 5044, __func__, "Incomplete preference at line %d of\n%s %s"
, pline, pf_path, hint); } } while (0)
5044 pline, pf_path, hint)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 5044, __func__, "Incomplete preference at line %d of\n%s %s"
, pline, pf_path, hint); } } while (0)
;
5045 }
5046 }
5047
5048 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)))))
;
5049 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)))))
;
5050
5051 if (ferror(pf))
5052 return errno(*__errno_location ());
5053 else
5054 return 0;
5055}
5056
5057/*
5058 * If we were handed a preference starting with "uat:", try to turn it into
5059 * a valid uat entry.
5060 */
5061static bool_Bool
5062prefs_set_uat_pref(char *uat_entry, char **errmsg) {
5063 char *p, *colonp;
5064 uat_t *uat;
5065 bool_Bool ret;
5066
5067 colonp = strchr(uat_entry, ':');
5068 if (colonp == NULL((void*)0))
5069 return false0;
5070
5071 p = colonp;
5072 *p++ = '\0';
5073
5074 /*
5075 * Skip over any white space (there probably won't be any, but
5076 * as we allow it in the preferences file, we might as well
5077 * allow it here).
5078 */
5079 while (g_ascii_isspace(*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0))
5080 p++;
5081 if (*p == '\0') {
5082 /*
5083 * Put the colon back, so if our caller uses, in an
5084 * error message, the string they passed us, the message
5085 * looks correct.
5086 */
5087 *colonp = ':';
5088 return false0;
5089 }
5090
5091 uat = uat_find(uat_entry);
5092 *colonp = ':';
5093 if (uat == NULL((void*)0)) {
5094 *errmsg = g_strdup("Unknown preference")g_strdup_inline ("Unknown preference");
5095 return false0;
5096 }
5097
5098 ret = uat_load_str(uat, p, errmsg);
5099 return ret;
5100}
5101
5102/*
5103 * Given a string of the form "<pref name>:<pref value>", as might appear
5104 * as an argument to a "-o" option, parse it and set the preference in
5105 * question. Return an indication of whether it succeeded or failed
5106 * in some fashion.
5107 */
5108prefs_set_pref_e
5109prefs_set_pref(char *prefarg, char **errmsg)
5110{
5111 char *p, *colonp;
5112 prefs_set_pref_e ret;
5113
5114 /*
5115 * Set the counters of "mgcp.{tcp,udp}.port" entries we've
5116 * seen to values that keep us from trying to interpret them
5117 * as "mgcp.{tcp,udp}.gateway_port" or "mgcp.{tcp,udp}.callagent_port",
5118 * as, from the command line, we have no way of guessing which
5119 * the user had in mind.
5120 */
5121 mgcp_tcp_port_count = -1;
5122 mgcp_udp_port_count = -1;
5123
5124 *errmsg = NULL((void*)0);
5125
5126 colonp = strchr(prefarg, ':');
5127 if (colonp == NULL((void*)0))
5128 return PREFS_SET_SYNTAX_ERR;
5129
5130 p = colonp;
5131 *p++ = '\0';
5132
5133 /*
5134 * Skip over any white space (there probably won't be any, but
5135 * as we allow it in the preferences file, we might as well
5136 * allow it here).
5137 */
5138 while (g_ascii_isspace(*p)((g_ascii_table[(guchar) (*p)] & G_ASCII_SPACE) != 0))
5139 p++;
5140 /* The empty string is a legal value for range preferences (PREF_RANGE,
5141 * PREF_DECODE_AS_RANGE), and string-like preferences (PREF_STRING,
5142 * PREF_SAVE_FILENAME, PREF_OPEN_FILENAME, PREF_DIRNAME), indeed often
5143 * not just useful but the default. A user might have a value saved
5144 * to their preference file but want to override it to default behavior.
5145 * Individual preference handlers of those types should be prepared to
5146 * deal with an empty string. For other types, it is up to set_pref() to
5147 * test for the empty string and set PREFS_SET_SYNTAX_ERROR there.
5148 */
5149 if (strcmp(prefarg, "uat")) {
5150 ret = set_pref(prefarg, p, NULL((void*)0), true1);
5151 } else {
5152 ret = prefs_set_uat_pref(p, errmsg) ? PREFS_SET_OK : PREFS_SET_SYNTAX_ERR;
5153 }
5154 *colonp = ':'; /* put the colon back */
5155 return ret;
5156}
5157
5158unsigned prefs_get_uint_value(pref_t *pref, pref_source_t source)
5159{
5160 switch (source)
5161 {
5162 case pref_default:
5163 return pref->default_val.uint;
5164 case pref_stashed:
5165 return pref->stashed_val.uint;
5166 case pref_current:
5167 return *pref->varp.uint;
5168 default:
5169 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 5169
, __func__, "assertion \"not reached\" failed")
;
5170 break;
5171 }
5172
5173 return 0;
5174}
5175
5176char* prefs_get_password_value(pref_t *pref, pref_source_t source)
5177{
5178 return prefs_get_string_value(pref, source);
5179}
5180
5181
5182unsigned int prefs_set_uint_value(pref_t *pref, unsigned value, pref_source_t source)
5183{
5184 unsigned int changed = 0;
5185 switch (source)
5186 {
5187 case pref_default:
5188 if (pref->default_val.uint != value) {
5189 pref->default_val.uint = value;
5190 changed = prefs_get_effect_flags(pref);
5191 }
5192 break;
5193 case pref_stashed:
5194 if (pref->stashed_val.uint != value) {
5195 pref->stashed_val.uint = value;
5196 changed = prefs_get_effect_flags(pref);
5197 }
5198 break;
5199 case pref_current:
5200 if (*pref->varp.uint != value) {
5201 *pref->varp.uint = value;
5202 changed = prefs_get_effect_flags(pref);
5203 }
5204 break;
5205 default:
5206 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 5206
, __func__, "assertion \"not reached\" failed")
;
5207 break;
5208 }
5209
5210 return changed;
5211}
5212
5213/*
5214 * For use by UI code that sets preferences.
5215 */
5216unsigned int
5217prefs_set_password_value(pref_t *pref, const char* value, pref_source_t source)
5218{
5219 return prefs_set_string_value(pref, value, source);
5220}
5221
5222
5223unsigned prefs_get_uint_base(pref_t *pref)
5224{
5225 return pref->info.base;
5226}
5227
5228/*
5229 * Returns true if the given device is hidden
5230 */
5231bool_Bool
5232prefs_is_capture_device_hidden(const char *name)
5233{
5234 char *tok, *devices;
5235 size_t len;
5236
5237 if (prefs.capture_devices_hide && name) {
5238 devices = g_strdup (prefs.capture_devices_hide)g_strdup_inline (prefs.capture_devices_hide);
5239 len = strlen (name);
5240 for (tok = strtok (devices, ","); tok; tok = strtok(NULL((void*)0), ",")) {
5241 if (strlen (tok) == len && strcmp (name, tok) == 0) {
5242 g_free (devices);
5243 return true1;
5244 }
5245 }
5246 g_free (devices);
5247 }
5248
5249 return false0;
5250}
5251
5252/*
5253 * Returns true if the given column is visible (not hidden)
5254 */
5255static bool_Bool
5256prefs_is_column_visible(const char *cols_hidden, int col)
5257{
5258 char *tok, *cols, *p;
5259 int cidx;
5260
5261 /*
5262 * Do we have a list of hidden columns?
5263 */
5264 if (cols_hidden) {
5265 /*
5266 * Yes - check the column against each of the ones in the
5267 * list.
5268 */
5269 cols = g_strdup(cols_hidden)g_strdup_inline (cols_hidden);
5270 for (tok = strtok(cols, ","); tok; tok = strtok(NULL((void*)0), ",")) {
5271 tok = g_strstrip(tok)g_strchomp (g_strchug (tok));
5272
5273 cidx = (int)strtol(tok, &p, 10);
5274 if (p == tok || *p != '\0') {
5275 continue;
5276 }
5277 if (cidx != col) {
5278 continue;
5279 }
5280 /*
5281 * OK, they match, so it's one of the hidden fields,
5282 * hence not visible.
5283 */
5284 g_free(cols);
5285 return false0;
5286 }
5287 g_free(cols);
5288 }
5289
5290 /*
5291 * No - either there are no hidden columns or this isn't one
5292 * of them - so it is visible.
5293 */
5294 return true1;
5295}
5296
5297/*
5298 * Returns true if the given column is visible (not hidden)
5299 */
5300static bool_Bool
5301prefs_is_column_fmt_visible(const char *cols_hidden, fmt_data *cfmt)
5302{
5303 char *tok, *cols;
5304 fmt_data cfmt_hidden;
5305
5306 /*
5307 * Do we have a list of hidden columns?
5308 */
5309 if (cols_hidden) {
5310 /*
5311 * Yes - check the column against each of the ones in the
5312 * list.
5313 */
5314 cols = g_strdup(cols_hidden)g_strdup_inline (cols_hidden);
5315 for (tok = strtok(cols, ","); tok; tok = strtok(NULL((void*)0), ",")) {
5316 tok = g_strstrip(tok)g_strchomp (g_strchug (tok));
5317
5318 /*
5319 * Parse this column format.
5320 */
5321 if (!parse_column_format(&cfmt_hidden, tok)) {
5322 /*
5323 * It's not valid; ignore it.
5324 */
5325 continue;
5326 }
5327
5328 /*
5329 * Does it match the column?
5330 */
5331 if (cfmt->fmt != cfmt_hidden.fmt) {
5332 /* No. */
5333 g_free(cfmt_hidden.custom_fields);
5334 cfmt_hidden.custom_fields = NULL((void*)0);
5335 continue;
5336 }
5337 if (cfmt->fmt == COL_CUSTOM) {
5338 /*
5339 * A custom column has to have the same custom field
5340 * and occurrence.
5341 */
5342 if (cfmt_hidden.custom_fields && cfmt->custom_fields) {
5343 if (strcmp(cfmt->custom_fields,
5344 cfmt_hidden.custom_fields) != 0) {
5345 /* Different fields. */
5346 g_free(cfmt_hidden.custom_fields);
5347 cfmt_hidden.custom_fields = NULL((void*)0);
5348 continue;
5349 }
5350 if (cfmt->custom_occurrence != cfmt_hidden.custom_occurrence) {
5351 /* Different occurrences settings. */
5352 g_free(cfmt_hidden.custom_fields);
5353 cfmt_hidden.custom_fields = NULL((void*)0);
5354 continue;
5355 }
5356 }
5357 }
5358
5359 /*
5360 * OK, they match, so it's one of the hidden fields,
5361 * hence not visible.
5362 */
5363 g_free(cfmt_hidden.custom_fields);
5364 g_free(cols);
5365 return false0;
5366 }
5367 g_free(cols);
5368 }
5369
5370 /*
5371 * No - either there are no hidden columns or this isn't one
5372 * of them - so it is visible.
5373 */
5374 return true1;
5375}
5376
5377/*
5378 * Returns true if the given device should capture in monitor mode by default
5379 */
5380bool_Bool
5381prefs_capture_device_monitor_mode(const char *name)
5382{
5383 char *tok, *devices;
5384 size_t len;
5385
5386 if (prefs.capture_devices_monitor_mode && name) {
5387 devices = g_strdup (prefs.capture_devices_monitor_mode)g_strdup_inline (prefs.capture_devices_monitor_mode);
5388 len = strlen (name);
5389 for (tok = strtok (devices, ","); tok; tok = strtok(NULL((void*)0), ",")) {
5390 if (strlen (tok) == len && strcmp (name, tok) == 0) {
5391 g_free (devices);
5392 return true1;
5393 }
5394 }
5395 g_free (devices);
5396 }
5397
5398 return false0;
5399}
5400
5401/*
5402 * Returns true if the user has marked this column as visible
5403 */
5404bool_Bool
5405prefs_capture_options_dialog_column_is_visible(const char *column)
5406{
5407 GList *curr;
5408 char *col;
5409
5410 for (curr = g_list_first(prefs.capture_columns); curr; curr = g_list_next(curr)((curr) ? (((GList *)(curr))->next) : ((void*)0))) {
5411 col = (char *)curr->data;
5412 if (col && (g_ascii_strcasecmp(col, column) == 0)) {
5413 return true1;
5414 }
5415 }
5416 return false0;
5417}
5418
5419bool_Bool
5420prefs_has_layout_pane_content (layout_pane_content_e layout_pane_content)
5421{
5422 return ((prefs.gui_layout_content_1 == layout_pane_content) ||
5423 (prefs.gui_layout_content_2 == layout_pane_content) ||
5424 (prefs.gui_layout_content_3 == layout_pane_content));
5425}
5426
5427#define PRS_GUI_FILTER_LABEL"gui.filter_expressions.label" "gui.filter_expressions.label"
5428#define PRS_GUI_FILTER_EXPR"gui.filter_expressions.expr" "gui.filter_expressions.expr"
5429#define PRS_GUI_FILTER_ENABLED"gui.filter_expressions.enabled" "gui.filter_expressions.enabled"
5430
5431/*
5432 * Extract the red, green, and blue components of a 24-bit RGB value
5433 * and convert them from [0,255] to [0,65535].
5434 */
5435#define RED_COMPONENT(x)(uint16_t) (((((x) >> 16) & 0xff) * 65535 / 255)) (uint16_t) (((((x) >> 16) & 0xff) * 65535 / 255))
5436#define GREEN_COMPONENT(x)(uint16_t) (((((x) >> 8) & 0xff) * 65535 / 255)) (uint16_t) (((((x) >> 8) & 0xff) * 65535 / 255))
5437#define BLUE_COMPONENT(x)(uint16_t) ( (((x) & 0xff) * 65535 / 255)) (uint16_t) ( (((x) & 0xff) * 65535 / 255))
5438
5439char
5440string_to_name_resolve(const char *string, e_addr_resolve *name_resolve)
5441{
5442 char c;
5443
5444 memset(name_resolve, 0, sizeof(e_addr_resolve));
5445 while ((c = *string++) != '\0') {
5446 switch (c) {
5447 case 'g':
5448 name_resolve->maxmind_geoip = true1;
5449 break;
5450 case 'm':
5451 name_resolve->mac_name = true1;
5452 break;
5453 case 'n':
5454 name_resolve->network_name = true1;
5455 break;
5456 case 'N':
5457 name_resolve->use_external_net_name_resolver = true1;
5458 break;
5459 case 't':
5460 name_resolve->transport_name = true1;
5461 break;
5462 case 'd':
5463 name_resolve->dns_pkt_addr_resolution = true1;
5464 break;
5465 case 's':
5466 name_resolve->handshake_sni_addr_resolution = true1;
5467 break;
5468 case 'v':
5469 name_resolve->vlan_name = true1;
5470 break;
5471 default:
5472 /*
5473 * Unrecognized letter.
5474 */
5475 return c;
5476 }
5477 }
5478 return '\0';
5479}
5480
5481static bool_Bool
5482deprecated_heur_dissector_pref(char *pref_name, const char *value)
5483{
5484 struct heur_pref_name
5485 {
5486 const char* pref_name;
5487 const char* short_name;
5488 bool_Bool more_dissectors; /* For multiple dissectors controlled by the same preference */
5489 };
5490
5491 struct heur_pref_name heur_prefs[] = {
5492 {"acn.heuristic_acn", "acn_udp", 0},
5493 {"bfcp.enable", "bfcp_tcp", 1},
5494 {"bfcp.enable", "bfcp_udp", 0},
5495 {"bt-dht.enable", "bittorrent_dht_udp", 0},
5496 {"bt-utp.enable", "bt_utp_udp", 0},
5497 {"cattp.enable", "cattp_udp", 0},
5498 {"cfp.enable", "fp_eth", 0},
5499 {"dicom.heuristic", "dicom_tcp", 0},
5500 {"dnp3.heuristics", "dnp3_tcp", 1},
5501 {"dnp3.heuristics", "dnp3_udp", 0},
5502 {"dvb-s2_modeadapt.enable", "dvb_s2_udp", 0},
5503 {"esl.enable", "esl_eth", 0},
5504 {"fp.udp_heur", "fp_udp", 0},
5505 {"gvsp.enable_heuristic", "gvsp_udp", 0},
5506 {"hdcp2.enable", "hdcp2_tcp", 0},
5507 {"hislip.enable_heuristic", "hislip_tcp", 0},
5508 {"infiniband.dissect_eoib", "mellanox_eoib", 1},
5509 {"infiniband.identify_payload", "eth_over_ib", 0},
5510 {"jxta.udp.heuristic", "jxta_udp", 0},
5511 {"jxta.tcp.heuristic", "jxta_tcp", 0},
5512 {"jxta.sctp.heuristic", "jxta_sctp", 0},
5513 {"mac-lte.heuristic_mac_lte_over_udp", "mac_lte_udp", 0},
5514 {"mbim.bulk_heuristic", "mbim_usb_bulk", 0},
5515 {"norm.heuristic_norm", "rmt_norm_udp", 0},
5516 {"openflow.heuristic", "openflow_tcp", 0},
5517 {"pdcp-lte.heuristic_pdcp_lte_over_udp", "pdcp_lte_udp", 0},
5518 {"rlc.heuristic_rlc_over_udp", "rlc_udp", 0},
5519 {"rlc-lte.heuristic_rlc_lte_over_udp", "rlc_lte_udp", 0},
5520 {"rtcp.heuristic_rtcp", "rtcp_udp", 1},
5521 {"rtcp.heuristic_rtcp", "rtcp_stun", 0},
5522 {"rtp.heuristic_rtp", "rtp_udp", 1},
5523 {"rtp.heuristic_rtp", "rtp_stun", 0},
5524 {"teredo.heuristic_teredo", "teredo_udp", 0},
5525 {"vssmonitoring.use_heuristics", "vssmonitoring_eth", 0},
5526 {"xml.heuristic", "xml_http", 1},
5527 {"xml.heuristic", "xml_sip", 1},
5528 {"xml.heuristic", "xml_media", 0},
5529 {"xml.heuristic_tcp", "xml_tcp", 0},
5530 {"xml.heuristic_udp", "xml_udp", 0},
5531 };
5532
5533 unsigned int i;
5534 heur_dtbl_entry_t* heuristic;
5535
5536
5537 for (i = 0; i < array_length(heur_prefs)(sizeof (heur_prefs) / sizeof (heur_prefs)[0]); i++)
5538 {
5539 if (strcmp(pref_name, heur_prefs[i].pref_name) == 0)
5540 {
5541 heuristic = find_heur_dissector_by_unique_short_name(heur_prefs[i].short_name);
5542 if (heuristic != NULL((void*)0)) {
5543 heuristic->enabled = ((g_ascii_strcasecmp(value, "true") == 0) ? true1 : false0);
5544 }
5545
5546 if (!heur_prefs[i].more_dissectors)
5547 return true1;
5548 }
5549 }
5550
5551
5552 return false0;
5553}
5554
5555static bool_Bool
5556deprecated_enable_dissector_pref(char *pref_name, const char *value)
5557{
5558 struct dissector_pref_name
5559 {
5560 const char* pref_name;
5561 const char* short_name;
5562 };
5563
5564 struct dissector_pref_name dissector_prefs[] = {
5565 {"transum.tsumenabled", "TRANSUM"},
5566 {"snort.enable_snort_dissector", "Snort"},
5567 {"prp.enable", "PRP"},
5568 };
5569
5570 unsigned int i;
5571 int proto_id;
5572
5573 for (i = 0; i < array_length(dissector_prefs)(sizeof (dissector_prefs) / sizeof (dissector_prefs)[0]); i++)
5574 {
5575 if (strcmp(pref_name, dissector_prefs[i].pref_name) == 0)
5576 {
5577 proto_id = proto_get_id_by_short_name(dissector_prefs[i].short_name);
5578 if (proto_id >= 0)
5579 proto_set_decoding(proto_id, ((g_ascii_strcasecmp(value, "true") == 0) ? true1 : false0));
5580 return true1;
5581 }
5582 }
5583
5584 return false0;
5585}
5586
5587static bool_Bool
5588deprecated_port_pref(char *pref_name, const char *value)
5589{
5590 struct port_pref_name
5591 {
5592 const char* pref_name;
5593 const char* module_name; /* the protocol filter name */
5594 const char* table_name;
5595 unsigned base;
5596 };
5597
5598 struct obsolete_pref_name
5599 {
5600 const char* pref_name;
5601 };
5602
5603 /* For now this is only supporting TCP/UDP port and RTP payload
5604 * types dissector preferences, which are assumed to be decimal */
5605 /* module_name is the filter name of the destination port preference,
5606 * which is usually the same as the original module but not
5607 * necessarily (e.g., if the preference is for what is now a PINO.)
5608 * XXX: Most of these were changed pre-2.0. Can we end support
5609 * for migrating legacy preferences at some point?
5610 */
5611 struct port_pref_name port_prefs[] = {
5612 /* TCP */
5613 {"cmp.tcp_alternate_port", "cmp", "tcp.port", 10},
5614 {"h248.tcp_port", "h248", "tcp.port", 10},
5615 {"cops.tcp.cops_port", "cops", "tcp.port", 10},
5616 {"dhcpfo.tcp_port", "dhcpfo", "tcp.port", 10},
5617 {"enttec.tcp_port", "enttec", "tcp.port", 10},
5618 {"forces.tcp_alternate_port", "forces", "tcp.port", 10},
5619 {"ged125.tcp_port", "ged125", "tcp.port", 10},
5620 {"hpfeeds.dissector_port", "hpfeeds", "tcp.port", 10},
5621 {"lsc.port", "lsc", "tcp.port", 10},
5622 {"megaco.tcp.txt_port", "megaco", "tcp.port", 10},
5623 {"netsync.tcp_port", "netsync", "tcp.port", 10},
5624 {"osi.tpkt_port", "osi", "tcp.port", 10},
5625 {"rsync.tcp_port", "rsync", "tcp.port", 10},
5626 {"sametime.tcp_port", "sametime", "tcp.port", 10},
5627 {"sigcomp.tcp.port2", "sigcomp", "tcp.port", 10},
5628 {"synphasor.tcp_port", "synphasor", "tcp.port", 10},
5629 {"tipc.alternate_port", "tipc", "tcp.port", 10},
5630 {"vnc.alternate_port", "vnc", "tcp.port", 10},
5631 {"scop.port", "scop", "tcp.port", 10},
5632 {"scop.port_secure", "scop", "tcp.port", 10},
5633 {"tpncp.tcp.trunkpack_port", "tpncp", "tcp.port", 10},
5634 /* UDP */
5635 {"h248.udp_port", "h248", "udp.port", 10},
5636 {"actrace.udp_port", "actrace", "udp.port", 10},
5637 {"brp.port", "brp", "udp.port", 10},
5638 {"bvlc.additional_udp_port", "bvlc", "udp.port", 10},
5639 {"capwap.udp.port.control", "capwap", "udp.port", 10},
5640 {"capwap.udp.port.data", "capwap", "udp.port", 10},
5641 {"coap.udp_port", "coap", "udp.port", 10},
5642 {"enttec.udp_port", "enttec", "udp.port", 10},
5643 {"forces.udp_alternate_port", "forces", "udp.port", 10},
5644 {"ldss.udp_port", "ldss", "udp.port", 10},
5645 {"lmp.udp_port", "lmp", "udp.port", 10},
5646 {"ltp.port", "ltp", "udp.port", 10},
5647 {"lwres.udp.lwres_port", "lwres", "udp.port", 10},
5648 {"megaco.udp.txt_port", "megaco", "udp.port", 10},
5649 {"pfcp.port_pfcp", "pfcp", "udp.port", 10},
5650 {"pgm.udp.encap_ucast_port", "pgm", "udp.port", 10},
5651 {"pgm.udp.encap_mcast_port", "pgm", "udp.port", 10},
5652 {"quic.udp.quic.port", "quic", "udp.port", 10},
5653 {"quic.udp.quics.port", "quic", "udp.port", 10},
5654 {"radius.alternate_port", "radius", "udp.port", 10},
5655 {"rdt.default_udp_port", "rdt", "udp.port", 10},
5656 {"alc.default.udp_port", "alc", "udp.port", 10},
5657 {"sigcomp.udp.port2", "sigcomp", "udp.port", 10},
5658 {"synphasor.udp_port", "synphasor", "udp.port", 10},
5659 {"tdmop.udpport", "tdmop", "udp.port", 10},
5660 {"uaudp.port1", "uaudp", "udp.port", 10},
5661 {"uaudp.port2", "uaudp", "udp.port", 10},
5662 {"uaudp.port3", "uaudp", "udp.port", 10},
5663 {"uaudp.port4", "uaudp", "udp.port", 10},
5664 {"uhd.dissector_port", "uhd", "udp.port", 10},
5665 {"vrt.dissector_port", "vrt", "udp.port", 10},
5666 {"tpncp.udp.trunkpack_port", "tpncp", "udp.port", 10},
5667 /* SCTP */
5668 {"hnbap.port", "hnbap", "sctp.port", 10},
5669 {"m2pa.port", "m2pa", "sctp.port", 10},
5670 {"megaco.sctp.txt_port", "megaco", "sctp.port", 10},
5671 {"rua.port", "rua", "sctp.port", 10},
5672 /* SCTP PPI */
5673 {"lapd.sctp_payload_protocol_identifier", "lapd", "sctp.ppi", 10},
5674 /* SCCP SSN */
5675 {"ranap.sccp_ssn", "ranap", "sccp.ssn", 10},
5676 };
5677
5678 struct port_pref_name port_range_prefs[] = {
5679 /* TCP */
5680 {"couchbase.tcp.ports", "couchbase", "tcp.port", 10},
5681 {"gsm_ipa.tcp_ports", "gsm_ipa", "tcp.port", 10},
5682 {"kafka.tcp.ports", "kafka", "tcp.port", 10},
5683 {"kt.tcp.ports", "kt", "tcp.port", 10},
5684 {"memcache.tcp.ports", "memcache", "tcp.port", 10},
5685 {"mrcpv2.tcp.port_range", "mrcpv2", "tcp.port", 10},
5686 {"pdu_transport.ports.tcp", "pdu_transport", "tcp.port", 10},
5687 {"rtsp.tcp.port_range", "rtsp", "tcp.port", 10},
5688 {"sip.tcp.ports", "sip", "tcp.port", 10},
5689 {"someip.ports.tcp", "someip", "tcp.port", 10},
5690 {"tds.tcp_ports", "tds", "tcp.port", 10},
5691 {"tpkt.tcp.ports", "tpkt", "tcp.port", 10},
5692 {"uma.tcp.ports", "uma", "tcp.port", 10},
5693 /* UDP */
5694 {"aruba_erm.udp.ports", "arubs_erm", "udp.port", 10},
5695 {"diameter.udp.ports", "diameter", "udp.port", 10},
5696 {"dmp.udp_ports", "dmp", "udp.port", 10},
5697 {"dns.udp.ports", "dns", "udp.port", 10},
5698 {"gsm_ipa.udp_ports", "gsm_ipa", "udp.port", 10},
5699 {"hcrt.dissector_udp_port", "hcrt", "udp.port", 10},
5700 {"memcache.udp.ports", "memcache", "udp.port", 10},
5701 {"nb_rtpmux.udp_ports", "nb_rtpmux", "udp.port", 10},
5702 {"gprs-ns.udp.ports", "gprs-ns", "udp.port", 10},
5703 {"p_mul.udp_ports", "p_mul", "udp.port", 10},
5704 {"pdu_transport.ports.udp", "pdu_transport", "udp.port", 10},
5705 {"radius.ports", "radius", "udp.port", 10},
5706 {"sflow.ports", "sflow", "udp.port", 10},
5707 {"someip.ports.udp", "someip", "udp.port", 10},
5708 {"sscop.udp.ports", "sscop", "udp.port", 10},
5709 {"tftp.udp_ports", "tftp", "udp.port", 10},
5710 {"tipc.udp.ports", "tipc", "udp.port", 10},
5711 /* RTP */
5712 {"amr.dynamic.payload.type", "amr", "rtp.pt", 10},
5713 {"amr.wb.dynamic.payload.type", "amr_wb", "rtp.pt", 10},
5714 {"dvb-s2_modeadapt.dynamic.payload.type", "dvb-s2_modeadapt", "rtp.pt", 10},
5715 {"evs.dynamic.payload.type", "evs", "rtp.pt", 10},
5716 {"h263p.dynamic.payload.type", "h263p", "rtp.pt", 10},
5717 {"h264.dynamic.payload.type", "h264", "rtp.pt", 10},
5718 {"h265.dynamic.payload.type", "h265", "rtp.pt", 10},
5719 {"ismacryp.dynamic.payload.type", "ismacryp", "rtp.pt", 10},
5720 {"iuup.dynamic.payload.type", "iuup", "rtp.pt", 10},
5721 {"lapd.rtp_payload_type", "lapd", "rtp.pt", 10},
5722 {"mp4ves.dynamic.payload.type", "mp4ves", "rtp.pt", 10},
5723 {"mtp2.rtp_payload_type", "mtp2", "rtp.pt", 10},
5724 {"opus.dynamic.payload.type", "opus", "rtp.pt", 10},
5725 {"rtp.rfc2198_payload_type", "rtp_rfc2198", "rtp.pt", 10},
5726 {"rtpevent.event_payload_type_value", "rtpevent", "rtp.pt", 10},
5727 {"rtpevent.cisco_nse_payload_type_value", "rtpevent", "rtp.pt", 10},
5728 {"rtpmidi.midi_payload_type_value", "rtpmidi", "rtp.pt", 10},
5729 {"vp8.dynamic.payload.type", "vp8", "rtp.pt", 10},
5730 /* SCTP */
5731 {"diameter.sctp.ports", "diameter", "sctp.port", 10},
5732 {"sgsap.sctp_ports", "sgsap", "sctp.port", 10},
5733 /* SCCP SSN */
5734 {"pcap.ssn", "pcap", "sccp.ssn", 10},
5735 };
5736
5737 /* These are subdissectors of TPKT/OSITP that used to have a
5738 TCP port preference even though they were never
5739 directly on TCP. Convert them to use Decode As
5740 with the TPKT dissector handle */
5741 struct port_pref_name tpkt_subdissector_port_prefs[] = {
5742 {"dap.tcp.port", "dap", "tcp.port", 10},
5743 {"disp.tcp.port", "disp", "tcp.port", 10},
5744 {"dop.tcp.port", "dop", "tcp.port", 10},
5745 {"dsp.tcp.port", "dsp", "tcp.port", 10},
5746 {"p1.tcp.port", "p1", "tcp.port", 10},
5747 {"p7.tcp.port", "p7", "tcp.port", 10},
5748 {"rdp.tcp.port", "rdp", "tcp.port", 10},
5749 };
5750
5751 /* These are obsolete preferences from the dissectors' view,
5752 (typically because of a switch from a single value to a
5753 range value) but the name of the preference conflicts
5754 with the generated preference name from the dissector table.
5755 Don't allow the obsolete preference through to be handled */
5756 struct obsolete_pref_name obsolete_prefs[] = {
5757 {"diameter.tcp.port"},
5758 {"kafka.tcp.port"},
5759 {"mrcpv2.tcp.port"},
5760 {"rtsp.tcp.port"},
5761 {"sip.tcp.port"},
5762 {"t38.tcp.port"},
5763 };
5764
5765 unsigned int i;
5766 unsigned uval;
5767 dissector_table_t sub_dissectors;
5768 dissector_handle_t handle, tpkt_handle;
5769 module_t *module;
5770 pref_t *pref;
5771
5772 static bool_Bool sanity_checked;
5773 if (!sanity_checked) {
5774 sanity_checked = true1;
5775 for (i = 0; i < G_N_ELEMENTS(port_prefs)(sizeof (port_prefs) / sizeof ((port_prefs)[0])); i++) {
5776 module = prefs_find_module(port_prefs[i].module_name);
5777 if (!module) {
5778 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"
, 5778, __func__, "Deprecated ports pref check - module '%s' not found"
, port_prefs[i].module_name); } } while (0)
;
5779 continue;
5780 }
5781 pref = prefs_find_preference(module, port_prefs[i].table_name);
5782 if (!pref) {
5783 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"
, 5783, __func__, "Deprecated ports pref '%s.%s' not found", module
->name, port_prefs[i].table_name); } } while (0)
;
5784 continue;
5785 }
5786 if (pref->type != PREF_DECODE_AS_RANGE) {
5787 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"
, 5787, __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)
;
5788 }
5789 }
5790 }
5791
5792 for (i = 0; i < G_N_ELEMENTS(port_prefs)(sizeof (port_prefs) / sizeof ((port_prefs)[0])); i++) {
5793 if (strcmp(pref_name, port_prefs[i].pref_name) == 0) {
5794 if (!ws_basestrtou32(value, NULL((void*)0), &uval, port_prefs[i].base))
5795 return false0; /* number was bad */
5796
5797 module = prefs_find_module(port_prefs[i].module_name);
5798 pref = prefs_find_preference(module, port_prefs[i].table_name);
5799 if (pref != NULL((void*)0)) {
5800 module->prefs_changed_flags |= prefs_get_effect_flags(pref);
5801 if (pref->type == PREF_DECODE_AS_RANGE) {
5802 // The legacy preference was a port number, but the new
5803 // preference is a port range. Add to existing range.
5804 if (uval) {
5805 prefs_range_add_value(pref, uval);
5806 }
5807 }
5808 }
5809
5810 /* If the value is zero, it wouldn't add to the Decode As tables */
5811 if (uval != 0)
5812 {
5813 sub_dissectors = find_dissector_table(port_prefs[i].table_name);
5814 if (sub_dissectors != NULL((void*)0)) {
5815 handle = dissector_table_get_dissector_handle(sub_dissectors, module->title);
5816 if (handle != NULL((void*)0)) {
5817 dissector_change_uint(port_prefs[i].table_name, uval, handle);
5818 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));
5819 }
5820 }
5821 }
5822
5823 return true1;
5824 }
5825 }
5826
5827 for (i = 0; i < array_length(port_range_prefs)(sizeof (port_range_prefs) / sizeof (port_range_prefs)[0]); i++)
5828 {
5829 if (strcmp(pref_name, port_range_prefs[i].pref_name) == 0)
5830 {
5831 uint32_t range_i, range_j;
5832
5833 sub_dissectors = find_dissector_table(port_range_prefs[i].table_name);
5834 if (sub_dissectors != NULL((void*)0)) {
5835 switch (dissector_table_get_type(sub_dissectors)) {
5836 case FT_UINT8:
5837 case FT_UINT16:
5838 case FT_UINT24:
5839 case FT_UINT32:
5840 break;
5841
5842 default:
5843 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", 5843
, __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))
;
5844 ws_assert_not_reached()ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 5844
, __func__, "assertion \"not reached\" failed")
;
5845 }
5846
5847 module = prefs_find_module(port_range_prefs[i].module_name);
5848 pref = prefs_find_preference(module, port_range_prefs[i].table_name);
5849 if (pref != NULL((void*)0))
5850 {
5851 if (!prefs_set_range_value_work(pref, value, true1, &module->prefs_changed_flags))
5852 {
5853 return false0; /* number was bad */
5854 }
5855
5856 handle = dissector_table_get_dissector_handle(sub_dissectors, module->title);
5857 if (handle != NULL((void*)0)) {
5858
5859 for (range_i = 0; range_i < (*pref->varp.range)->nranges; range_i++) {
5860 for (range_j = (*pref->varp.range)->ranges[range_i].low; range_j < (*pref->varp.range)->ranges[range_i].high; range_j++) {
5861 dissector_change_uint(port_range_prefs[i].table_name, range_j, handle);
5862 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));
5863 }
5864
5865 dissector_change_uint(port_range_prefs[i].table_name, (*pref->varp.range)->ranges[range_i].high, handle);
5866 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));
5867 }
5868 }
5869 }
5870 }
5871
5872 return true1;
5873 }
5874 }
5875
5876 for (i = 0; i < array_length(tpkt_subdissector_port_prefs)(sizeof (tpkt_subdissector_port_prefs) / sizeof (tpkt_subdissector_port_prefs
)[0])
; i++)
5877 {
5878 if (strcmp(pref_name, tpkt_subdissector_port_prefs[i].pref_name) == 0)
5879 {
5880 /* XXX - give an error if it doesn't fit in a unsigned? */
5881 if (!ws_basestrtou32(value, NULL((void*)0), &uval, tpkt_subdissector_port_prefs[i].base))
5882 return false0; /* number was bad */
5883
5884 /* If the value is 0 or 102 (default TPKT port), don't add to the Decode As tables */
5885 if ((uval != 0) && (uval != 102))
5886 {
5887 tpkt_handle = find_dissector("tpkt");
5888 if (tpkt_handle != NULL((void*)0)) {
5889 dissector_change_uint(tpkt_subdissector_port_prefs[i].table_name, uval, tpkt_handle);
5890 }
5891 }
5892
5893 return true1;
5894 }
5895 }
5896
5897 for (i = 0; i < array_length(obsolete_prefs)(sizeof (obsolete_prefs) / sizeof (obsolete_prefs)[0]); i++)
5898 {
5899 if (strcmp(pref_name, obsolete_prefs[i].pref_name) == 0)
5900 {
5901 /* Just ignore the preference */
5902 return true1;
5903 }
5904 }
5905 return false0;
5906}
5907
5908static prefs_set_pref_e
5909set_pref(char *pref_name, const char *value, void *private_data,
5910 bool_Bool return_range_errors)
5911{
5912 unsigned cval;
5913 unsigned uval;
5914 bool_Bool bval;
5915 int enum_val;
5916 char *dotp, *last_dotp;
5917 static char *filter_label = NULL((void*)0);
5918 static bool_Bool filter_enabled = false0;
5919 module_t *module, *containing_module, *target_module;
5920 pref_t *pref;
5921 bool_Bool converted_pref = false0;
5922
5923 target_module = (module_t*)private_data;
5924
5925 //The PRS_GUI field names are here for backwards compatibility
5926 //display filters have been converted to a UAT.
5927 if (strcmp(pref_name, PRS_GUI_FILTER_LABEL"gui.filter_expressions.label") == 0) {
5928 /* Assume that PRS_GUI_FILTER_EXPR follows this preference. In case of
5929 * malicious preference files, free the previous value to limit the size
5930 * of leaked memory. */
5931 g_free(filter_label);
5932 filter_label = g_strdup(value)g_strdup_inline (value);
5933 } else if (strcmp(pref_name, PRS_GUI_FILTER_ENABLED"gui.filter_expressions.enabled") == 0) {
5934 filter_enabled = (strcmp(value, "TRUE") == 0) ? true1 : false0;
5935 } else if (strcmp(pref_name, PRS_GUI_FILTER_EXPR"gui.filter_expressions.expr") == 0) {
5936 /* Comments not supported for "old" preference style */
5937 filter_expression_new(filter_label, value, "", filter_enabled);
5938 g_free(filter_label);
5939 filter_label = NULL((void*)0);
5940 /* Remember to save the new UAT to file. */
5941 prefs.filter_expressions_old = true1;
5942 } else if (strcmp(pref_name, "gui.version_in_start_page") == 0) {
5943 /* Convert deprecated value to closest current equivalent */
5944 if (g_ascii_strcasecmp(value, "true") == 0) {
5945 prefs.gui_version_placement = version_both;
5946 } else {
5947 prefs.gui_version_placement = version_neither;
5948 }
5949 } else if (strcmp(pref_name, "name_resolve") == 0 ||
5950 strcmp(pref_name, "capture.name_resolve") == 0) {
5951 /*
5952 * Handle the deprecated name resolution options.
5953 *
5954 * "TRUE" and "FALSE", for backwards compatibility, are synonyms for
5955 * RESOLV_ALL and RESOLV_NONE.
5956 *
5957 * Otherwise, we treat it as a list of name types we want to resolve.
5958 */
5959 if (g_ascii_strcasecmp(value, "true") == 0) {
5960 gbl_resolv_flags.mac_name = true1;
5961 gbl_resolv_flags.network_name = true1;
5962 gbl_resolv_flags.transport_name = true1;
5963 }
5964 else if (g_ascii_strcasecmp(value, "false") == 0) {
5965 disable_name_resolution();
5966 }
5967 else {
5968 /* start out with none set */
5969 disable_name_resolution();
5970 if (string_to_name_resolve(value, &gbl_resolv_flags) != '\0')
5971 return PREFS_SET_SYNTAX_ERR;
5972 }
5973 } else if (deprecated_heur_dissector_pref(pref_name, value)) {
5974 /* Handled within deprecated_heur_dissector_pref() if found */
5975 } else if (deprecated_enable_dissector_pref(pref_name, value)) {
5976 /* Handled within deprecated_enable_dissector_pref() if found */
5977 } else if (deprecated_port_pref(pref_name, value)) {
5978 /* Handled within deprecated_port_pref() if found */
5979 } else if (strcmp(pref_name, "console.log.level") == 0) {
5980 /* Handled on the command line within ws_log_parse_args() */
5981 return PREFS_SET_OK;
5982 } else {
5983 /* Handle deprecated "global" options that don't have a module
5984 * associated with them
5985 */
5986 if ((strcmp(pref_name, "name_resolve_concurrency") == 0) ||
5987 (strcmp(pref_name, "name_resolve_load_smi_modules") == 0) ||
5988 (strcmp(pref_name, "name_resolve_suppress_smi_errors") == 0)) {
5989 module = nameres_module;
5990 dotp = pref_name;
5991 } else {
5992 /* To which module does this preference belong? */
5993 module = NULL((void*)0);
5994 last_dotp = pref_name;
5995 while (!module) {
5996 dotp = strchr(last_dotp, '.');
5997 if (dotp == NULL((void*)0)) {
5998 /* Either there's no such module, or no module was specified.
5999 In either case, that means there's no such preference. */
6000 return PREFS_SET_NO_SUCH_PREF;
6001 }
6002 *dotp = '\0'; /* separate module and preference name */
6003 module = prefs_find_module(pref_name);
6004
6005 /*
6006 * XXX - "Diameter" rather than "diameter" was used in earlier
6007 * versions of Wireshark; if we didn't find the module, and its name
6008 * was "Diameter", look for "diameter" instead.
6009 *
6010 * In addition, the BEEP protocol used to be the BXXP protocol,
6011 * so if we didn't find the module, and its name was "bxxp",
6012 * look for "beep" instead.
6013 *
6014 * Also, the preferences for GTP v0 and v1 were combined under
6015 * a single "gtp" heading, and the preferences for SMPP were
6016 * moved to "smpp-gsm-sms" and then moved to "gsm-sms-ud".
6017 * However, SMPP now has its own preferences, so we just map
6018 * "smpp-gsm-sms" to "gsm-sms-ud", and then handle SMPP below.
6019 *
6020 * We also renamed "dcp" to "dccp", "x.25" to "x25", "x411" to "p1"
6021 * and "nsip" to "gprs_ns".
6022 *
6023 * The SynOptics Network Management Protocol (SONMP) is now known by
6024 * its modern name, the Nortel Discovery Protocol (NDP).
6025 */
6026 if (module == NULL((void*)0)) {
6027 /*
6028 * See if there's a backwards-compatibility name
6029 * that maps to this module.
6030 */
6031 module = prefs_find_module_alias(pref_name);
6032 if (module == NULL((void*)0)) {
6033 /*
6034 * There's no alias for the module; see if the
6035 * module name matches any protocol aliases.
6036 */
6037 header_field_info *hfinfo = proto_registrar_get_byalias(pref_name);
6038 if (hfinfo) {
6039 module = (module_t *) wmem_tree_lookup_string(prefs_modules, hfinfo->abbrev, WMEM_TREE_STRING_NOCASE0x00000001);
6040 }
6041 }
6042 if (module == NULL((void*)0)) {
6043 /*
6044 * There aren't any aliases. Was the module
6045 * removed rather than renamed?
6046 */
6047 if (strcmp(pref_name, "etheric") == 0 ||
6048 strcmp(pref_name, "isup_thin") == 0) {
6049 /*
6050 * The dissectors for these protocols were
6051 * removed as obsolete on 2009-07-70 in change
6052 * 739bfc6ff035583abb9434e0e988048de38a8d9a.
6053 */
6054 return PREFS_SET_OBSOLETE;
6055 }
6056 }
6057 if (module) {
6058 converted_pref = true1;
6059 prefs.unknown_prefs = true1;
6060 }
6061 }
6062 *dotp = '.'; /* put the preference string back */
6063 dotp++; /* skip past separator to preference name */
6064 last_dotp = dotp;
6065 }
6066 }
6067
6068 /* The pref is located in the module or a submodule.
6069 * Assume module, then search for a submodule holding the pref. */
6070 containing_module = module;
6071 pref = prefs_find_preference_with_submodule(module, dotp, &containing_module);
6072
6073 if (pref == NULL((void*)0)) {
6074 prefs.unknown_prefs = true1;
6075
6076 /* "gui" prefix was added to column preferences for better organization
6077 * within the preferences file
6078 */
6079 if (module == gui_column_module) {
6080 /* While this has a subtree, there is no apply callback, so no
6081 * need to use prefs_find_preference_with_submodule to update
6082 * containing_module. It would not be useful. */
6083 pref = prefs_find_preference(module, pref_name);
6084 }
6085 else if (strcmp(module->name, "mgcp") == 0) {
6086 /*
6087 * XXX - "mgcp.display raw text toggle" and "mgcp.display dissect tree"
6088 * rather than "mgcp.display_raw_text" and "mgcp.display_dissect_tree"
6089 * were used in earlier versions of Wireshark; if we didn't find the
6090 * preference, it was an MGCP preference, and its name was
6091 * "display raw text toggle" or "display dissect tree", look for
6092 * "display_raw_text" or "display_dissect_tree" instead.
6093 *
6094 * "mgcp.tcp.port" and "mgcp.udp.port" are harder to handle, as both
6095 * the gateway and callagent ports were given those names; we interpret
6096 * the first as "mgcp.{tcp,udp}.gateway_port" and the second as
6097 * "mgcp.{tcp,udp}.callagent_port", as that's the order in which
6098 * they were registered by the MCCP dissector and thus that's the
6099 * order in which they were written to the preferences file. (If
6100 * we're not reading the preferences file, but are handling stuff
6101 * from a "-o" command-line option, we have no clue which the user
6102 * had in mind - they should have used "mgcp.{tcp,udp}.gateway_port"
6103 * or "mgcp.{tcp,udp}.callagent_port" instead.)
6104 */
6105 if (strcmp(dotp, "display raw text toggle") == 0)
6106 pref = prefs_find_preference(module, "display_raw_text");
6107 else if (strcmp(dotp, "display dissect tree") == 0)
6108 pref = prefs_find_preference(module, "display_dissect_tree");
6109 else if (strcmp(dotp, "tcp.port") == 0) {
6110 mgcp_tcp_port_count++;
6111 if (mgcp_tcp_port_count == 1) {
6112 /* It's the first one */
6113 pref = prefs_find_preference(module, "tcp.gateway_port");
6114 } else if (mgcp_tcp_port_count == 2) {
6115 /* It's the second one */
6116 pref = prefs_find_preference(module, "tcp.callagent_port");
6117 }
6118 /* Otherwise it's from the command line, and we don't bother
6119 mapping it. */
6120 } else if (strcmp(dotp, "udp.port") == 0) {
6121 mgcp_udp_port_count++;
6122 if (mgcp_udp_port_count == 1) {
6123 /* It's the first one */
6124 pref = prefs_find_preference(module, "udp.gateway_port");
6125 } else if (mgcp_udp_port_count == 2) {
6126 /* It's the second one */
6127 pref = prefs_find_preference(module, "udp.callagent_port");
6128 }
6129 /* Otherwise it's from the command line, and we don't bother
6130 mapping it. */
6131 }
6132 } else if (strcmp(module->name, "smb") == 0) {
6133 /* Handle old names for SMB preferences. */
6134 if (strcmp(dotp, "smb.trans.reassembly") == 0)
6135 pref = prefs_find_preference(module, "trans_reassembly");
6136 else if (strcmp(dotp, "smb.dcerpc.reassembly") == 0)
6137 pref = prefs_find_preference(module, "dcerpc_reassembly");
6138 } else if (strcmp(module->name, "ndmp") == 0) {
6139 /* Handle old names for NDMP preferences. */
6140 if (strcmp(dotp, "ndmp.desegment") == 0)
6141 pref = prefs_find_preference(module, "desegment");
6142 } else if (strcmp(module->name, "diameter") == 0) {
6143 /* Handle old names for Diameter preferences. */
6144 if (strcmp(dotp, "diameter.desegment") == 0)
6145 pref = prefs_find_preference(module, "desegment");
6146 } else if (strcmp(module->name, "pcli") == 0) {
6147 /* Handle old names for PCLI preferences. */
6148 if (strcmp(dotp, "pcli.udp_port") == 0)
6149 pref = prefs_find_preference(module, "udp_port");
6150 } else if (strcmp(module->name, "artnet") == 0) {
6151 /* Handle old names for ARTNET preferences. */
6152 if (strcmp(dotp, "artnet.udp_port") == 0)
6153 pref = prefs_find_preference(module, "udp_port");
6154 } else if (strcmp(module->name, "mapi") == 0) {
6155 /* Handle old names for MAPI preferences. */
6156 if (strcmp(dotp, "mapi_decrypt") == 0)
6157 pref = prefs_find_preference(module, "decrypt");
6158 } else if (strcmp(module->name, "fc") == 0) {
6159 /* Handle old names for Fibre Channel preferences. */
6160 if (strcmp(dotp, "reassemble_fc") == 0)
6161 pref = prefs_find_preference(module, "reassemble");
6162 else if (strcmp(dotp, "fc_max_frame_size") == 0)
6163 pref = prefs_find_preference(module, "max_frame_size");
6164 } else if (strcmp(module->name, "fcip") == 0) {
6165 /* Handle old names for Fibre Channel-over-IP preferences. */
6166 if (strcmp(dotp, "desegment_fcip_messages") == 0)
6167 pref = prefs_find_preference(module, "desegment");
6168 else if (strcmp(dotp, "fcip_port") == 0)
6169 pref = prefs_find_preference(module, "target_port");
6170 } else if (strcmp(module->name, "gtp") == 0) {
6171 /* Handle old names for GTP preferences. */
6172 if (strcmp(dotp, "gtpv0_port") == 0)
6173 pref = prefs_find_preference(module, "v0_port");
6174 else if (strcmp(dotp, "gtpv1c_port") == 0)
6175 pref = prefs_find_preference(module, "v1c_port");
6176 else if (strcmp(dotp, "gtpv1u_port") == 0)
6177 pref = prefs_find_preference(module, "v1u_port");
6178 else if (strcmp(dotp, "gtp_dissect_tpdu") == 0)
6179 pref = prefs_find_preference(module, "dissect_tpdu");
6180 else if (strcmp(dotp, "gtpv0_dissect_cdr_as") == 0)
6181 pref = prefs_find_preference(module, "v0_dissect_cdr_as");
6182 else if (strcmp(dotp, "gtpv0_check_etsi") == 0)
6183 pref = prefs_find_preference(module, "v0_check_etsi");
6184 else if (strcmp(dotp, "gtpv1_check_etsi") == 0)
6185 pref = prefs_find_preference(module, "v1_check_etsi");
6186 } else if (strcmp(module->name, "ip") == 0) {
6187 /* Handle old names for IP preferences. */
6188 if (strcmp(dotp, "ip_summary_in_tree") == 0)
6189 pref = prefs_find_preference(module, "summary_in_tree");
6190 } else if (strcmp(module->name, "iscsi") == 0) {
6191 /* Handle old names for iSCSI preferences. */
6192 if (strcmp(dotp, "iscsi_port") == 0)
6193 pref = prefs_find_preference(module, "target_port");
6194 } else if (strcmp(module->name, "lmp") == 0) {
6195 /* Handle old names for LMP preferences. */
6196 if (strcmp(dotp, "lmp_version") == 0)
6197 pref = prefs_find_preference(module, "version");
6198 } else if (strcmp(module->name, "mtp3") == 0) {
6199 /* Handle old names for MTP3 preferences. */
6200 if (strcmp(dotp, "mtp3_standard") == 0)
6201 pref = prefs_find_preference(module, "standard");
6202 else if (strcmp(dotp, "net_addr_format") == 0)
6203 pref = prefs_find_preference(module, "addr_format");
6204 } else if (strcmp(module->name, "nlm") == 0) {
6205 /* Handle old names for NLM preferences. */
6206 if (strcmp(dotp, "nlm_msg_res_matching") == 0)
6207 pref = prefs_find_preference(module, "msg_res_matching");
6208 } else if (strcmp(module->name, "ppp") == 0) {
6209 /* Handle old names for PPP preferences. */
6210 if (strcmp(dotp, "ppp_fcs") == 0)
6211 pref = prefs_find_preference(module, "fcs_type");
6212 else if (strcmp(dotp, "ppp_vj") == 0)
6213 pref = prefs_find_preference(module, "decompress_vj");
6214 } else if (strcmp(module->name, "rsvp") == 0) {
6215 /* Handle old names for RSVP preferences. */
6216 if (strcmp(dotp, "rsvp_process_bundle") == 0)
6217 pref = prefs_find_preference(module, "process_bundle");
6218 } else if (strcmp(module->name, "tcp") == 0) {
6219 /* Handle old names for TCP preferences. */
6220 if (strcmp(dotp, "tcp_summary_in_tree") == 0)
6221 pref = prefs_find_preference(module, "summary_in_tree");
6222 else if (strcmp(dotp, "tcp_analyze_sequence_numbers") == 0)
6223 pref = prefs_find_preference(module, "analyze_sequence_numbers");
6224 else if (strcmp(dotp, "tcp_relative_sequence_numbers") == 0)
6225 pref = prefs_find_preference(module, "relative_sequence_numbers");
6226 else if (strcmp(dotp, "dissect_experimental_options_with_magic") == 0)
6227 pref = prefs_find_preference(module, "dissect_experimental_options_rfc6994");
6228 } else if (strcmp(module->name, "udp") == 0) {
6229 /* Handle old names for UDP preferences. */
6230 if (strcmp(dotp, "udp_summary_in_tree") == 0)
6231 pref = prefs_find_preference(module, "summary_in_tree");
6232 } else if (strcmp(module->name, "ndps") == 0) {
6233 /* Handle old names for NDPS preferences. */
6234 if (strcmp(dotp, "desegment_ndps") == 0)
6235 pref = prefs_find_preference(module, "desegment_tcp");
6236 } else if (strcmp(module->name, "http") == 0) {
6237 /* Handle old names for HTTP preferences. */
6238 if (strcmp(dotp, "desegment_http_headers") == 0)
6239 pref = prefs_find_preference(module, "desegment_headers");
6240 else if (strcmp(dotp, "desegment_http_body") == 0)
6241 pref = prefs_find_preference(module, "desegment_body");
6242 } else if (strcmp(module->name, "smpp") == 0) {
6243 /* Handle preferences that moved from SMPP. */
6244 module_t *new_module = prefs_find_module("gsm-sms-ud");
6245 if (new_module) {
6246 if (strcmp(dotp, "port_number_udh_means_wsp") == 0) {
6247 pref = prefs_find_preference(new_module, "port_number_udh_means_wsp");
6248 containing_module = new_module;
6249 } else if (strcmp(dotp, "try_dissect_1st_fragment") == 0) {
6250 pref = prefs_find_preference(new_module, "try_dissect_1st_fragment");
6251 containing_module = new_module;
6252 }
6253 }
6254 } else if (strcmp(module->name, "asn1") == 0) {
6255 /* Handle old generic ASN.1 preferences (it's not really a
6256 rename, as the new preferences support multiple ports,
6257 but we might as well copy them over). */
6258 if (strcmp(dotp, "tcp_port") == 0)
6259 pref = prefs_find_preference(module, "tcp_ports");
6260 else if (strcmp(dotp, "udp_port") == 0)
6261 pref = prefs_find_preference(module, "udp_ports");
6262 else if (strcmp(dotp, "sctp_port") == 0)
6263 pref = prefs_find_preference(module, "sctp_ports");
6264 } else if (strcmp(module->name, "llcgprs") == 0) {
6265 if (strcmp(dotp, "ignore_cipher_bit") == 0)
6266 pref = prefs_find_preference(module, "autodetect_cipher_bit");
6267 } else if (strcmp(module->name, "erf") == 0) {
6268 if (strcmp(dotp, "erfeth") == 0) {
6269 /* Handle the old "erfeth" preference; map it to the new
6270 "ethfcs" preference, and map the values to those for
6271 the new preference. */
6272 pref = prefs_find_preference(module, "ethfcs");
6273 if (strcmp(value, "ethfcs") == 0 || strcmp(value, "Ethernet with FCS") == 0)
6274 value = "TRUE";
6275 else if (strcmp(value, "eth") == 0 || strcmp(value, "Ethernet") == 0)
6276 value = "FALSE";
6277 else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
6278 value = "TRUE";
6279 } else if (strcmp(dotp, "erfatm") == 0) {
6280 /* Handle the old "erfatm" preference; map it to the new
6281 "aal5_type" preference, and map the values to those for
6282 the new preference. */
6283 pref = prefs_find_preference(module, "aal5_type");
6284 if (strcmp(value, "atm") == 0 || strcmp(value, "ATM") == 0)
6285 value = "guess";
6286 else if (strcmp(value, "llc") == 0 || strcmp(value, "LLC") == 0)
6287 value = "llc";
6288 else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
6289 value = "guess";
6290 } else if (strcmp(dotp, "erfhdlc") == 0) {
6291 /* Handle the old "erfhdlc" preference; map it to the new
6292 "hdlc_type" preference, and map the values to those for
6293 the new preference. */
6294 pref = prefs_find_preference(module, "hdlc_type");
6295 if (strcmp(value, "chdlc") == 0 || strcmp(value, "Cisco HDLC") == 0)
6296 value = "chdlc";
6297 else if (strcmp(value, "ppp") == 0 || strcmp(value, "PPP serial") == 0)
6298 value = "ppp";
6299 else if (strcmp(value, "fr") == 0 || strcmp(value, "Frame Relay") == 0)
6300 value = "frelay";
6301 else if (strcmp(value, "mtp2") == 0 || strcmp(value, "SS7 MTP2") == 0)
6302 value = "mtp2";
6303 else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
6304 value = "guess";
6305 }
6306 } else if (strcmp(module->name, "eth") == 0) {
6307 /* "eth.qinq_ethertype" has been changed(restored) to "vlan.qinq.ethertype" */
6308 if (strcmp(dotp, "qinq_ethertype") == 0) {
6309 module_t *new_module = prefs_find_module("vlan");
6310 if (new_module) {
6311 pref = prefs_find_preference(new_module, "qinq_ethertype");
6312 containing_module = new_module;
6313 }
6314 }
6315 } else if (strcmp(module->name, "taps") == 0) {
6316 /* taps preferences moved to "statistics" module */
6317 if (strcmp(dotp, "update_interval") == 0)
6318 pref = prefs_find_preference(stats_module, dotp);
6319 } else if (strcmp(module->name, "packet_list") == 0) {
6320 /* packet_list preferences moved to protocol module */
6321 if (strcmp(dotp, "display_hidden_proto_items") == 0)
6322 pref = prefs_find_preference(protocols_module, dotp);
6323 } else if (strcmp(module->name, "stream") == 0) {
6324 /* stream preferences moved to gui color module */
6325 if ((strcmp(dotp, "client.fg") == 0) ||
6326 (strcmp(dotp, "client.bg") == 0) ||
6327 (strcmp(dotp, "server.fg") == 0) ||
6328 (strcmp(dotp, "server.bg") == 0))
6329 pref = prefs_find_preference(gui_color_module, pref_name);
6330 } else if (strcmp(module->name, "nameres") == 0) {
6331 if (strcmp(pref_name, "name_resolve_concurrency") == 0) {
6332 pref = prefs_find_preference(nameres_module, pref_name);
6333 } else if (strcmp(pref_name, "name_resolve_load_smi_modules") == 0) {
6334 pref = prefs_find_preference(nameres_module, "load_smi_modules");
6335 } else if (strcmp(pref_name, "name_resolve_suppress_smi_errors") == 0) {
6336 pref = prefs_find_preference(nameres_module, "suppress_smi_errors");
6337 }
6338 } else if (strcmp(module->name, "extcap") == 0) {
6339 /* Handle the old "sshdump.remotesudo" preference; map it to the new
6340 "sshdump.remotepriv" preference, and map the boolean values to the
6341 appropriate strings of the new preference. */
6342 if (strcmp(dotp, "sshdump.remotesudo") == 0) {
6343 pref = prefs_find_preference(module, "sshdump.remotepriv");
6344 if (g_ascii_strcasecmp(value, "true") == 0)
6345 value = "sudo";
6346 else
6347 value = "none";
6348 }
6349 }
6350 if (pref) {
6351 converted_pref = true1;
6352 }
6353 }
6354 if (pref == NULL((void*)0) ) {
6355 if (strcmp(module->name, "extcap") == 0 && g_list_length(module->prefs) <= 1) {
6356 /*
6357 * Assume that we've skipped extcap preference registration
6358 * and that only extcap.gui_save_on_start is loaded.
6359 */
6360 return PREFS_SET_OK;
6361 }
6362 return PREFS_SET_NO_SUCH_PREF; /* no such preference */
6363 }
6364
6365 if (target_module && target_module != containing_module) {
6366 /* Ignore */
6367 return PREFS_SET_OK;
6368 }
6369
6370 if (pref->obsolete)
6371 return PREFS_SET_OBSOLETE; /* no such preference any more */
6372
6373 if (converted_pref) {
6374 ws_warning("Preference \"%s\" has been converted to \"%s.%s\"\n"do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 6376, __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 "Save your preferences to make this change permanent.",do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 6376, __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 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"
, 6376, __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)
;
6377 }
6378
6379 switch (pref->type) {
6380
6381 case PREF_UINT:
6382 if (!ws_basestrtou32(value, NULL((void*)0), &uval, pref->info.base))
6383 return PREFS_SET_SYNTAX_ERR; /* number was bad */
6384 if (*pref->varp.uint != uval) {
6385 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
6386 *pref->varp.uint = uval;
6387 }
6388 break;
6389 case PREF_BOOL:
6390 /* XXX - give an error if it's neither "true" nor "false"? */
6391 if (g_ascii_strcasecmp(value, "true") == 0)
6392 bval = true1;
6393 else
6394 bval = false0;
6395 if (*pref->varp.boolp != bval) {
6396 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
6397 *pref->varp.boolp = bval;
6398 }
6399 break;
6400
6401 case PREF_ENUM:
6402 /* XXX - give an error if it doesn't match? */
6403 enum_val = find_val_for_string(value, pref->info.enum_info.enumvals,
6404 *pref->varp.enump);
6405 if (*pref->varp.enump != enum_val) {
6406 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
6407 *pref->varp.enump = enum_val;
6408 }
6409 break;
6410
6411 case PREF_STRING:
6412 case PREF_SAVE_FILENAME:
6413 case PREF_OPEN_FILENAME:
6414 case PREF_DIRNAME:
6415 case PREF_DISSECTOR:
6416 containing_module->prefs_changed_flags |= prefs_set_string_value(pref, value, pref_current);
6417 break;
6418
6419 case PREF_PASSWORD:
6420 /* Read value is every time empty */
6421 containing_module->prefs_changed_flags |= prefs_set_string_value(pref, "", pref_current);
6422 break;
6423
6424 case PREF_RANGE:
6425 {
6426 if (!prefs_set_range_value_work(pref, value, return_range_errors,
6427 &containing_module->prefs_changed_flags))
6428 return PREFS_SET_SYNTAX_ERR; /* number was bad */
6429 break;
6430 }
6431 case PREF_DECODE_AS_RANGE:
6432 {
6433 /* This is for backwards compatibility in case any of the preferences
6434 that shared the "Decode As" preference name and used to be PREF_RANGE
6435 are now applied directly to the Decode As funtionality */
6436 range_t *newrange;
6437 dissector_table_t sub_dissectors;
6438 dissector_handle_t handle;
6439 uint32_t i, j;
6440
6441 if (range_convert_str_work(wmem_epan_scope(), &newrange, value, pref->info.max_value,
6442 return_range_errors) != CVT_NO_ERROR) {
6443 return PREFS_SET_SYNTAX_ERR; /* number was bad */
6444 }
6445
6446 if (!ranges_are_equal(*pref->varp.range, newrange)) {
6447 wmem_free(wmem_epan_scope(), *pref->varp.range);
6448 *pref->varp.range = newrange;
6449 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
6450
6451 const char* table_name = prefs_get_dissector_table(pref);
6452 sub_dissectors = find_dissector_table(table_name);
6453 if (sub_dissectors != NULL((void*)0)) {
6454 handle = dissector_table_get_dissector_handle(sub_dissectors, module->title);
6455 if (handle != NULL((void*)0)) {
6456 /* Delete all of the old values from the dissector table */
6457 for (i = 0; i < (*pref->varp.range)->nranges; i++) {
6458 for (j = (*pref->varp.range)->ranges[i].low; j < (*pref->varp.range)->ranges[i].high; j++) {
6459 dissector_delete_uint(table_name, j, handle);
6460 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));
6461 }
6462
6463 dissector_delete_uint(table_name, (*pref->varp.range)->ranges[i].high, handle);
6464 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));
6465 }
6466
6467 /* Add new values to the dissector table */
6468 for (i = 0; i < newrange->nranges; i++) {
6469 for (j = newrange->ranges[i].low; j < newrange->ranges[i].high; j++) {
6470 dissector_change_uint(table_name, j, handle);
6471 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));
6472 }
6473
6474 dissector_change_uint(table_name, newrange->ranges[i].high, handle);
6475 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));
6476 }
6477
6478 /* XXX - Do we save the decode_as_entries file here? */
6479 }
6480 }
6481 } else {
6482 wmem_free(wmem_epan_scope(), newrange);
6483 }
6484 break;
6485 }
6486
6487 case PREF_COLOR:
6488 {
6489 if (!ws_hexstrtou32(value, NULL((void*)0), &cval))
6490 return PREFS_SET_SYNTAX_ERR; /* number was bad */
6491 if ((pref->varp.colorp->red != RED_COMPONENT(cval)(uint16_t) (((((cval) >> 16) & 0xff) * 65535 / 255)
)
) ||
6492 (pref->varp.colorp->green != GREEN_COMPONENT(cval)(uint16_t) (((((cval) >> 8) & 0xff) * 65535 / 255))) ||
6493 (pref->varp.colorp->blue != BLUE_COMPONENT(cval)(uint16_t) ( (((cval) & 0xff) * 65535 / 255)))) {
6494 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
6495 pref->varp.colorp->red = RED_COMPONENT(cval)(uint16_t) (((((cval) >> 16) & 0xff) * 65535 / 255)
)
;
6496 pref->varp.colorp->green = GREEN_COMPONENT(cval)(uint16_t) (((((cval) >> 8) & 0xff) * 65535 / 255));
6497 pref->varp.colorp->blue = BLUE_COMPONENT(cval)(uint16_t) ( (((cval) & 0xff) * 65535 / 255));
6498 }
6499 break;
6500 }
6501
6502 case PREF_CUSTOM:
6503 return pref->custom_cbs.set_cb(pref, value, &containing_module->prefs_changed_flags);
6504
6505 case PREF_STATIC_TEXT:
6506 case PREF_UAT:
6507 break;
6508
6509 case PREF_PROTO_TCP_SNDAMB_ENUM:
6510 {
6511 /* There's no point in setting the TCP sequence override
6512 * value from the command line, because the pref is different
6513 * for each frame and reset to the default (0) for each new
6514 * file.
6515 */
6516 break;
6517 }
6518 }
6519 }
6520
6521 return PREFS_SET_OK;
6522}
6523
6524typedef struct {
6525 FILE *pf;
6526 bool_Bool is_gui_module;
6527} write_gui_pref_arg_t;
6528
6529const char *
6530prefs_pref_type_name(pref_t *pref)
6531{
6532 const char *type_name = "[Unknown]";
6533
6534 if (!pref) {
6535 return type_name; /* ...or maybe assert? */
6536 }
6537
6538 if (pref->obsolete) {
6539 type_name = "Obsolete";
6540 } else {
6541 switch (pref->type) {
6542
6543 case PREF_UINT:
6544 switch (pref->info.base) {
6545
6546 case 10:
6547 type_name = "Decimal";
6548 break;
6549
6550 case 8:
6551 type_name = "Octal";
6552 break;
6553
6554 case 16:
6555 type_name = "Hexadecimal";
6556 break;
6557 }
6558 break;
6559
6560 case PREF_BOOL:
6561 type_name = "Boolean";
6562 break;
6563
6564 case PREF_ENUM:
6565 case PREF_PROTO_TCP_SNDAMB_ENUM:
6566 type_name = "Choice";
6567 break;
6568
6569 case PREF_STRING:
6570 type_name = "String";
6571 break;
6572
6573 case PREF_SAVE_FILENAME:
6574 case PREF_OPEN_FILENAME:
6575 type_name = "Filename";
6576 break;
6577
6578 case PREF_DIRNAME:
6579 type_name = "Directory";
6580 break;
6581
6582 case PREF_RANGE:
6583 type_name = "Range";
6584 break;
6585
6586 case PREF_COLOR:
6587 type_name = "Color";
6588 break;
6589
6590 case PREF_CUSTOM:
6591 if (pref->custom_cbs.type_name_cb)
6592 return pref->custom_cbs.type_name_cb();
6593 type_name = "Custom";
6594 break;
6595
6596 case PREF_DECODE_AS_RANGE:
6597 type_name = "Range (for Decode As)";
6598 break;
6599
6600 case PREF_STATIC_TEXT:
6601 type_name = "Static text";
6602 break;
6603
6604 case PREF_UAT:
6605 type_name = "UAT";
6606 break;
6607
6608 case PREF_PASSWORD:
6609 type_name = "Password";
6610 break;
6611
6612 case PREF_DISSECTOR:
6613 type_name = "Dissector";
6614 break;
6615 }
6616 }
6617
6618 return type_name;
6619}
6620
6621unsigned int
6622prefs_get_effect_flags(pref_t *pref)
6623{
6624 if (pref == NULL((void*)0))
6625 return 0;
6626
6627 return pref->effect_flags;
6628}
6629
6630void
6631prefs_set_effect_flags(pref_t *pref, unsigned int flags)
6632{
6633 if (pref != NULL((void*)0)) {
6634 if (flags == 0) {
6635 ws_error("Setting \"%s\" preference effect flags to 0", pref->name)ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 6635
, __func__, "Setting \"%s\" preference effect flags to 0", pref
->name)
;
6636 }
6637 pref->effect_flags = flags;
6638 }
6639}
6640
6641void
6642prefs_set_effect_flags_by_name(module_t * module, const char *pref, unsigned int flags)
6643{
6644 prefs_set_effect_flags(prefs_find_preference(module, pref), flags);
6645}
6646
6647unsigned int
6648prefs_get_module_effect_flags(module_t * module)
6649{
6650 if (module == NULL((void*)0))
6651 return 0;
6652
6653 return module->effect_flags;
6654}
6655
6656void
6657prefs_set_module_effect_flags(module_t * module, unsigned int flags)
6658{
6659 if (module != NULL((void*)0)) {
6660 if (flags == 0) {
6661 ws_error("Setting module \"%s\" preference effect flags to 0", module->name)ws_log_fatal_full("Epan", LOG_LEVEL_ERROR, "epan/prefs.c", 6661
, __func__, "Setting module \"%s\" preference effect flags to 0"
, module->name)
;
6662 }
6663 module->effect_flags = flags;
6664 }
6665}
6666
6667char *
6668prefs_pref_type_description(pref_t *pref)
6669{
6670 const char *type_desc = "An unknown preference type";
6671
6672 if (!pref) {
6673 return ws_strdup_printf("%s.", type_desc)wmem_strdup_printf(((void*)0), "%s.", type_desc); /* ...or maybe assert? */
6674 }
6675
6676 if (pref->obsolete) {
6677 type_desc = "An obsolete preference";
6678 } else {
6679 switch (pref->type) {
6680
6681 case PREF_UINT:
6682 switch (pref->info.base) {
6683
6684 case 10:
6685 type_desc = "A decimal number";
6686 break;
6687
6688 case 8:
6689 type_desc = "An octal number";
6690 break;
6691
6692 case 16:
6693 type_desc = "A hexadecimal number";
6694 break;
6695 }
6696 break;
6697
6698 case PREF_BOOL:
6699 type_desc = "true or false (case-insensitive)";
6700 break;
6701
6702 case PREF_ENUM:
6703 case PREF_PROTO_TCP_SNDAMB_ENUM:
6704 {
6705 const enum_val_t *enum_valp = pref->info.enum_info.enumvals;
6706 GString *enum_str = g_string_new("One of: ");
6707 GString *desc_str = g_string_new("\nEquivalently, one of: ");
6708 bool_Bool distinct = false0;
6709 while (enum_valp->name != NULL((void*)0)) {
6710 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))
;
6711 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))
;
6712 if (g_strcmp0(enum_valp->name, enum_valp->description) != 0) {
6713 distinct = true1;
6714 }
6715 enum_valp++;
6716 if (enum_valp->name != NULL((void*)0)) {
6717 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))
;
6718 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))
;
6719 }
6720 }
6721 if (distinct) {
6722 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))
;
6723 }
6724 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)))))
;
6725 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))
;
6726 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))))
;
6727 }
6728
6729 case PREF_STRING:
6730 type_desc = "A string";
6731 break;
6732
6733 case PREF_SAVE_FILENAME:
6734 case PREF_OPEN_FILENAME:
6735 type_desc = "A path to a file";
6736 break;
6737
6738 case PREF_DIRNAME:
6739 type_desc = "A path to a directory";
6740 break;
6741
6742 case PREF_RANGE:
6743 {
6744 type_desc = "A string denoting an positive integer range (e.g., \"1-20,30-40\")";
6745 break;
6746 }
6747
6748 case PREF_COLOR:
6749 {
6750 type_desc = "A six-digit hexadecimal RGB color triplet (e.g. fce94f)";
6751 break;
6752 }
6753
6754 case PREF_CUSTOM:
6755 if (pref->custom_cbs.type_description_cb)
6756 return pref->custom_cbs.type_description_cb();
6757 type_desc = "A custom value";
6758 break;
6759
6760 case PREF_DECODE_AS_RANGE:
6761 type_desc = "A string denoting an positive integer range for Decode As";
6762 break;
6763
6764 case PREF_STATIC_TEXT:
6765 type_desc = "[Static text]";
6766 break;
6767
6768 case PREF_UAT:
6769 type_desc = "Configuration data stored in its own file";
6770 break;
6771
6772 case PREF_PASSWORD:
6773 type_desc = "Password (never stored on disk)";
6774 break;
6775
6776 case PREF_DISSECTOR:
6777 type_desc = "A dissector name";
6778 break;
6779
6780 default:
6781 break;
6782 }
6783 }
6784
6785 return g_strdup(type_desc)g_strdup_inline (type_desc);
6786}
6787
6788bool_Bool
6789prefs_pref_is_default(pref_t *pref)
6790{
6791 if (!pref) return false0;
6792
6793 if (pref->obsolete) {
6794 return false0;
6795 }
6796
6797 switch (pref->type) {
6798
6799 case PREF_UINT:
6800 if (pref->default_val.uint == *pref->varp.uint)
6801 return true1;
6802 break;
6803
6804 case PREF_BOOL:
6805 if (pref->default_val.boolval == *pref->varp.boolp)
6806 return true1;
6807 break;
6808
6809 case PREF_ENUM:
6810 case PREF_PROTO_TCP_SNDAMB_ENUM:
6811 if (pref->default_val.enumval == *pref->varp.enump)
6812 return true1;
6813 break;
6814
6815 case PREF_STRING:
6816 case PREF_SAVE_FILENAME:
6817 case PREF_OPEN_FILENAME:
6818 case PREF_DIRNAME:
6819 case PREF_PASSWORD:
6820 case PREF_DISSECTOR:
6821 if (!(g_strcmp0(pref->default_val.string, *pref->varp.string)))
6822 return true1;
6823 break;
6824
6825 case PREF_DECODE_AS_RANGE:
6826 case PREF_RANGE:
6827 {
6828 if ((ranges_are_equal(pref->default_val.range, *pref->varp.range)))
6829 return true1;
6830 break;
6831 }
6832
6833 case PREF_COLOR:
6834 {
6835 if ((pref->default_val.color.red == pref->varp.colorp->red) &&
6836 (pref->default_val.color.green == pref->varp.colorp->green) &&
6837 (pref->default_val.color.blue == pref->varp.colorp->blue))
6838 return true1;
6839 break;
6840 }
6841
6842 case PREF_CUSTOM:
6843 return pref->custom_cbs.is_default_cb(pref);
6844
6845 case PREF_STATIC_TEXT:
6846 case PREF_UAT:
6847 return false0;
6848 /* ws_assert_not_reached(); */
6849 break;
6850 }
6851
6852 return false0;
6853}
6854
6855char *
6856prefs_pref_to_str(pref_t *pref, pref_source_t source)
6857{
6858 const char *pref_text = "[Unknown]";
6859 void *valp; /* pointer to preference value */
6860 color_t *pref_color;
6861 char *tmp_value, *ret_value;
6862
6863 if (!pref) {
6864 return g_strdup(pref_text)g_strdup_inline (pref_text);
6865 }
6866
6867 switch (source) {
6868 case pref_default:
6869 valp = &pref->default_val;
6870 /* valp = &boolval, &enumval, etc. are implied by union property */
6871 pref_color = &pref->default_val.color;
6872 break;
6873 case pref_stashed:
6874 valp = &pref->stashed_val;
6875 /* valp = &boolval, &enumval, etc. are implied by union property */
6876 pref_color = &pref->stashed_val.color;
6877 break;
6878 case pref_current:
6879 valp = pref->varp.uint;
6880 /* valp = boolval, enumval, etc. are implied by union property */
6881 pref_color = pref->varp.colorp;
6882 break;
6883 default:
6884 return g_strdup(pref_text)g_strdup_inline (pref_text);
6885 }
6886
6887 if (pref->obsolete) {
6888 pref_text = "[Obsolete]";
6889 } else {
6890 switch (pref->type) {
6891
6892 case PREF_UINT:
6893 {
6894 unsigned pref_uint = *(unsigned *) valp;
6895 switch (pref->info.base) {
6896
6897 case 10:
6898 return ws_strdup_printf("%u", pref_uint)wmem_strdup_printf(((void*)0), "%u", pref_uint);
6899
6900 case 8:
6901 return ws_strdup_printf("%#o", pref_uint)wmem_strdup_printf(((void*)0), "%#o", pref_uint);
6902
6903 case 16:
6904 return ws_strdup_printf("%#x", pref_uint)wmem_strdup_printf(((void*)0), "%#x", pref_uint);
6905 }
6906 break;
6907 }
6908
6909 case PREF_BOOL:
6910 return g_strdup((*(bool *) valp) ? "TRUE" : "FALSE")g_strdup_inline ((*(_Bool *) valp) ? "TRUE" : "FALSE");
6911
6912 case PREF_ENUM:
6913 case PREF_PROTO_TCP_SNDAMB_ENUM:
6914 {
6915 int pref_enumval = *(int *) valp;
6916 const enum_val_t *enum_valp = pref->info.enum_info.enumvals;
6917 /*
6918 * TODO - We write the "description" value, because the "name" values
6919 * weren't validated to be command line friendly until 5.0, and a few
6920 * of them had to be changed. This allows older versions of Wireshark
6921 * to read preferences that they supported, as we supported either
6922 * the short name or the description when reading the preference files
6923 * or an "-o" option. Once 5.0 is the oldest supported version, switch
6924 * to writing the name below.
6925 */
6926 while (enum_valp->name != NULL((void*)0)) {
6927 if (enum_valp->value == pref_enumval)
6928 return g_strdup(enum_valp->description)g_strdup_inline (enum_valp->description);
6929 enum_valp++;
6930 }
6931 break;
6932 }
6933
6934 case PREF_STRING:
6935 case PREF_SAVE_FILENAME:
6936 case PREF_OPEN_FILENAME:
6937 case PREF_DIRNAME:
6938 case PREF_PASSWORD:
6939 case PREF_DISSECTOR:
6940 return g_strdup(*(const char **) valp)g_strdup_inline (*(const char **) valp);
6941
6942 case PREF_DECODE_AS_RANGE:
6943 case PREF_RANGE:
6944 /* Convert wmem to g_alloc memory */
6945 tmp_value = range_convert_range(NULL((void*)0), *(range_t **) valp);
6946 ret_value = g_strdup(tmp_value)g_strdup_inline (tmp_value);
6947 wmem_free(NULL((void*)0), tmp_value);
6948 return ret_value;
6949
6950 case PREF_COLOR:
6951 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))
6952 (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))
6953 (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))
6954 (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))
;
6955
6956 case PREF_CUSTOM:
6957 if (pref->custom_cbs.to_str_cb)
6958 return pref->custom_cbs.to_str_cb(pref, source == pref_default ? true1 : false0);
6959 pref_text = "[Custom]";
6960 break;
6961
6962 case PREF_STATIC_TEXT:
6963 pref_text = "[Static text]";
6964 break;
6965
6966 case PREF_UAT:
6967 {
6968 uat_t *uat = pref->varp.uat;
6969 if (uat && uat->filename)
6970 return ws_strdup_printf("[Managed in the file \"%s\"]", uat->filename)wmem_strdup_printf(((void*)0), "[Managed in the file \"%s\"]"
, uat->filename)
;
6971 else
6972 pref_text = "[Managed in an unknown file]";
6973 break;
6974 }
6975
6976 default:
6977 break;
6978 }
6979 }
6980
6981 return g_strdup(pref_text)g_strdup_inline (pref_text);
6982}
6983
6984/*
6985 * Write out a single dissector preference.
6986 */
6987static void
6988write_pref(void *data, void *user_data)
6989{
6990 pref_t *pref = (pref_t *)data;
6991 write_pref_arg_t *arg = (write_pref_arg_t *)user_data;
6992 char **desc_lines;
6993 int i;
6994
6995 if (!pref || pref->obsolete) {
6996 /*
6997 * This preference is no longer supported; it's not a
6998 * real preference, so we don't write it out (i.e., we
6999 * treat it as if it weren't found in the list of
7000 * preferences, and we weren't called in the first place).
7001 */
7002 return;
7003 }
7004
7005 switch (pref->type) {
7006
7007 case PREF_STATIC_TEXT:
7008 case PREF_UAT:
7009 /* Nothing to do; don't bother printing the description */
7010 return;
7011 case PREF_DECODE_AS_RANGE:
7012 /* Data is saved through Decode As mechanism and not part of preferences file */
7013 return;
7014 case PREF_PROTO_TCP_SNDAMB_ENUM:
7015 /* Not written to the preference file because the override is only
7016 * for the lifetime of the capture file and there is no single
7017 * value to write.
7018 */
7019 return;
7020 default:
7021 break;
7022 }
7023
7024 if (pref->type != PREF_CUSTOM || pref->custom_cbs.type_name_cb() != NULL((void*)0)) {
7025 /*
7026 * The prefix will either be the module name or the parent
7027 * name if it's a subtree
7028 */
7029 const char *name_prefix = (arg->module->name != NULL((void*)0)) ? arg->module->name : arg->module->parent->name;
7030 char *type_desc, *pref_text;
7031 const char * def_prefix = prefs_pref_is_default(pref) ? "#" : "";
7032
7033 if (pref->type == PREF_CUSTOM)
7034 fprintf(arg->pf, "\n# %s", pref->custom_cbs.type_name_cb());
7035 fprintf(arg->pf, "\n");
7036 if (pref->description &&
7037 (g_ascii_strncasecmp(pref->description,"", 2) != 0)) {
7038 if (pref->type != PREF_CUSTOM) {
7039 /* We get duplicate lines otherwise. */
7040
7041 desc_lines = g_strsplit(pref->description, "\n", 0);
7042 for (i = 0; desc_lines[i] != NULL((void*)0); ++i) {
7043 fprintf(arg->pf, "# %s\n", desc_lines[i]);
7044 }
7045 g_strfreev(desc_lines);
7046 }
7047 } else {
7048 fprintf(arg->pf, "# No description\n");
7049 }
7050
7051 type_desc = prefs_pref_type_description(pref);
7052 desc_lines = g_strsplit(type_desc, "\n", 0);
7053 for (i = 0; desc_lines[i] != NULL((void*)0); ++i) {
7054 fprintf(arg->pf, "# %s\n", desc_lines[i]);
7055 }
7056 g_strfreev(desc_lines);
7057 g_free(type_desc);
7058
7059 pref_text = prefs_pref_to_str(pref, pref_current);
7060 fprintf(arg->pf, "%s%s.%s: ", def_prefix, name_prefix, pref->name);
7061 if (pref->type != PREF_PASSWORD)
7062 {
7063 desc_lines = g_strsplit(pref_text, "\n", 0);
7064 for (i = 0; desc_lines[i] != NULL((void*)0); ++i) {
7065 fprintf(arg->pf, "%s%s\n", i == 0 ? "" : def_prefix, desc_lines[i]);
7066 }
7067 if (i == 0)
7068 fprintf(arg->pf, "\n");
7069 g_strfreev(desc_lines);
7070 } else {
7071 /* We never store password value */
7072 fprintf(arg->pf, "\n");
7073 }
7074 g_free(pref_text);
7075 }
7076
7077}
7078
7079static void
7080count_non_uat_pref(void *data, void *user_data)
7081{
7082 pref_t *pref = (pref_t *)data;
7083 int *arg = (int *)user_data;
7084
7085 switch (pref->type)
7086 {
7087 case PREF_UAT:
7088 case PREF_DECODE_AS_RANGE:
7089 case PREF_PROTO_TCP_SNDAMB_ENUM:
7090 //These types are not written in preference file
7091 break;
7092 default:
7093 (*arg)++;
7094 break;
7095 }
7096}
7097
7098static int num_non_uat_prefs(module_t *module)
7099{
7100 int num = 0;
7101
7102 g_list_foreach(module->prefs, count_non_uat_pref, &num);
7103
7104 return num;
7105}
7106
7107/*
7108 * Write out all preferences for a module.
7109 */
7110static unsigned
7111write_module_prefs(module_t *module, void *user_data)
7112{
7113 write_gui_pref_arg_t *gui_pref_arg = (write_gui_pref_arg_t*)user_data;
7114 write_pref_arg_t arg;
7115
7116 /* The GUI module needs to be explicitly called out so it
7117 can be written out of order */
7118 if ((module == gui_module) && (gui_pref_arg->is_gui_module != true1))
7119 return 0;
7120
7121 /* Write a header for the main modules and GUI sub-modules */
7122 if (((module->parent == NULL((void*)0)) || (module->parent == gui_module)) &&
7123 ((prefs_module_has_submodules(module)) ||
7124 (num_non_uat_prefs(module) > 0) ||
7125 (module->name == NULL((void*)0)))) {
7126 if ((module->name == NULL((void*)0)) && (module->parent != NULL((void*)0))) {
7127 fprintf(gui_pref_arg->pf, "\n####### %s: %s ########\n", module->parent->title, module->title);
7128 } else {
7129 fprintf(gui_pref_arg->pf, "\n####### %s ########\n", module->title);
7130 }
7131 }
7132
7133 arg.module = module;
7134 arg.pf = gui_pref_arg->pf;
7135 g_list_foreach(arg.module->prefs, write_pref, &arg);
7136
7137 if (prefs_module_has_submodules(module))
7138 return prefs_modules_foreach_submodules(module, write_module_prefs, user_data);
7139
7140 return 0;
7141}
7142
7143#ifdef _WIN32
7144static void
7145write_registry(void)
7146{
7147 HKEY hTestKey;
7148 DWORD data;
7149 DWORD data_size;
7150 DWORD ret;
7151
7152 ret = RegCreateKeyExA(HKEY_CURRENT_USER, REG_HKCU_WIRESHARK_KEY"Software\\Wireshark", 0, NULL((void*)0),
7153 REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL((void*)0),
7154 &hTestKey, NULL((void*)0));
7155 if (ret != ERROR_SUCCESS) {
7156 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"
, 7156, __func__, "Cannot open HKCU ""Software\\Wireshark"": 0x%lx"
, ret); } } while (0)
;
7157 return;
7158 }
7159
7160 data = ws_log_console_open;
7161 data_size = sizeof(DWORD);
7162 ret = RegSetValueExA(hTestKey, LOG_HKCU_CONSOLE_OPEN"ConsoleOpen", 0, REG_DWORD, (const BYTE *)&data, data_size);
7163 if (ret == ERROR_SUCCESS) {
7164 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"
, 7164, __func__, "Wrote ""ConsoleOpen"" to Windows registry: 0x%lu"
, data); } } while (0)
;
7165 }
7166 else {
7167 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"
, 7167, __func__, "Error writing registry key ""ConsoleOpen"": 0x%lx"
, ret); } } while (0)
;
7168 }
7169
7170 RegCloseKey(hTestKey);
7171}
7172#endif
7173
7174/* Write out "prefs" to the user's preferences file, and return 0.
7175
7176 If the preferences file path is NULL, write to stdout.
7177
7178 If we got an error, stuff a pointer to the path of the preferences file
7179 into "*pf_path_return", and return the errno. */
7180int
7181write_prefs(char **pf_path_return)
7182{
7183 char *pf_path;
7184 FILE *pf;
7185 write_gui_pref_arg_t write_gui_pref_info;
7186
7187 /* Needed for "-G defaultprefs" */
7188 init_prefs();
7189
7190#ifdef _WIN32
7191 write_registry();
7192#endif
7193
7194 /* To do:
7195 * - Split output lines longer than MAX_VAL_LEN
7196 * - Create a function for the preference directory check/creation
7197 * so that duplication can be avoided with filter.c
7198 */
7199
7200 if (pf_path_return != NULL((void*)0)) {
7201 pf_path = get_persconffile_path(PF_NAME"preferences", true1);
7202 if ((pf = ws_fopenfopen(pf_path, "w")) == NULL((void*)0)) {
7203 *pf_path_return = pf_path;
7204 return errno(*__errno_location ());
7205 }
7206 g_free(pf_path);
7207 } else {
7208 pf = stdoutstdout;
7209 }
7210
7211 /*
7212 * If the preferences file is being written, be sure to write UAT files
7213 * first that were migrated from the preferences file.
7214 */
7215 if (pf_path_return != NULL((void*)0)) {
7216 if (prefs.filter_expressions_old) {
7217 char *err = NULL((void*)0);
7218 prefs.filter_expressions_old = false0;
7219 if (!uat_save(uat_get_table_by_name("Display expressions"), &err)) {
7220 ws_warning("Unable to save Display expressions: %s", err)do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 7220, __func__, "Unable to save Display expressions: %s", err
); } } while (0)
;
7221 g_free(err);
7222 }
7223 }
7224
7225 module_t *extcap_module = prefs_find_module("extcap");
7226 if (extcap_module && !prefs.capture_no_extcap) {
7227 char *ext_path = get_persconffile_path("extcap.cfg", true1);
7228 FILE *extf;
7229 if ((extf = ws_fopenfopen(ext_path, "w")) == NULL((void*)0)) {
7230 if (errno(*__errno_location ()) != EISDIR21) {
7231 ws_warning("Unable to save extcap preferences \"%s\": %s",do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 7232, __func__, "Unable to save extcap preferences \"%s\": %s"
, ext_path, g_strerror((*__errno_location ()))); } } while (0
)
7232 ext_path, g_strerror(errno))do { if (1) { ws_log_full("Epan", LOG_LEVEL_WARNING, "epan/prefs.c"
, 7232, __func__, "Unable to save extcap preferences \"%s\": %s"
, ext_path, g_strerror((*__errno_location ()))); } } while (0
)
;
7233 }
7234 g_free(ext_path);
7235 } else {
7236 g_free(ext_path);
7237
7238 fputs("# Extcap configuration file for Wireshark " VERSION"4.7.0" ".\n"
7239 "#\n"
7240 "# This file is regenerated each time preferences are saved within\n"
7241 "# Wireshark. Making manual changes should be safe, however.\n"
7242 "# Preferences that have been commented out have not been\n"
7243 "# changed from their default value.\n", extf);
7244
7245 write_gui_pref_info.pf = extf;
7246 write_gui_pref_info.is_gui_module = false0;
7247
7248 write_module_prefs(extcap_module, &write_gui_pref_info);
7249
7250 fclose(extf);
7251 }
7252 }
7253 }
7254
7255 fputs("# Configuration file for Wireshark " VERSION"4.7.0" ".\n"
7256 "#\n"
7257 "# This file is regenerated each time preferences are saved within\n"
7258 "# Wireshark. Making manual changes should be safe, however.\n"
7259 "# Preferences that have been commented out have not been\n"
7260 "# changed from their default value.\n", pf);
7261
7262 /*
7263 * For "backwards compatibility" the GUI module is written first as it's
7264 * at the top of the file. This is followed by all modules that can't
7265 * fit into the preferences read/write API. Finally the remaining modules
7266 * are written in alphabetical order (including of course the protocol preferences)
7267 */
7268 write_gui_pref_info.pf = pf;
7269 write_gui_pref_info.is_gui_module = true1;
7270
7271 write_module_prefs(gui_module, &write_gui_pref_info);
7272
7273 write_gui_pref_info.is_gui_module = false0;
7274 prefs_modules_foreach_submodules(NULL((void*)0), write_module_prefs, &write_gui_pref_info);
7275
7276 fclose(pf);
7277
7278 /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
7279 an error indication, or maybe write to a new preferences file and
7280 rename that file on top of the old one only if there are not I/O
7281 errors. */
7282 return 0;
7283}
7284
7285/** The col_list is only partly managed by the custom preference API
7286 * because its data is shared between multiple preferences, so
7287 * it's freed here
7288 */
7289static void
7290free_col_info(GList *list)
7291{
7292 fmt_data *cfmt;
7293 GList *list_head = list;
7294
7295 while (list != NULL((void*)0)) {
7296 cfmt = (fmt_data *)list->data;
7297
7298 g_free(cfmt->title);
7299 g_free(cfmt->custom_fields);
7300 g_free(cfmt);
7301 list = g_list_next(list)((list) ? (((GList *)(list))->next) : ((void*)0));
7302 }
7303 g_list_free(list_head);
7304}
7305
7306/*
7307 * Editor modelines
7308 *
7309 * Local Variables:
7310 * c-basic-offset: 4
7311 * tab-width: 8
7312 * indent-tabs-mode: nil
7313 * End:
7314 *
7315 * ex: set shiftwidth=4 tabstop=8 expandtab:
7316 * :indentSize=4:tabSize=8:noTabs=true:
7317 */