2 * Routines for handling preferences
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
13 #include "ws_diag_control.h"
22 #include <wsutil/filesystem.h>
23 #include <epan/address.h>
24 #include <epan/addr_resolv.h>
25 #include <epan/oids.h>
26 #include <epan/maxmind_db.h>
27 #include <epan/packet.h>
28 #include <epan/prefs.h>
29 #include <epan/proto.h>
30 #include <epan/strutil.h>
31 #include <epan/column.h>
32 #include <epan/decode_as.h>
34 #include <wsutil/file_util.h>
35 #include <wsutil/report_message.h>
37 #include <epan/prefs-int.h>
38 #include <epan/uat-int.h>
40 #include "epan/filter_expressions.h"
42 #include "epan/wmem/wmem.h"
43 #include <epan/stats_tree.h>
48 typedef struct pref_module_alias {
49 const char *name; /**< name of module alias */
50 module_t *module; /**< module for which it's an alias */
53 /* Internal functions */
54 static module_t *find_subtree(module_t *parent, const char *tilte);
55 static module_t *prefs_register_module_or_subtree(module_t *parent,
56 const char *name, const char *title, const char *description, gboolean is_subtree,
57 void (*apply_cb)(void), gboolean use_gui);
58 static void prefs_register_modules(void);
59 static module_t *prefs_find_module_alias(const char *name);
60 static prefs_set_pref_e set_pref(gchar*, const gchar*, void *, gboolean);
61 static void free_col_info(GList *);
62 static void pre_init_prefs(void);
63 static gboolean prefs_is_column_visible(const gchar *cols_hidden, fmt_data *cfmt);
64 static gboolean parse_column_format(fmt_data *cfmt, const char *fmt);
65 static void try_convert_to_custom_column(gpointer *el_data);
66 static guint prefs_module_list_foreach(wmem_tree_t *module_list, module_cb callback,
67 gpointer user_data, gboolean skip_obsolete);
69 #define IS_PREF_OBSOLETE(p) ((p) & PREF_OBSOLETE)
70 #define SET_PREF_OBSOLETE(p) ((p) |= PREF_OBSOLETE)
71 #define RESET_PREF_OBSOLETE(p) ((p) &= ~PREF_OBSOLETE)
73 #define PF_NAME "preferences"
74 #define OLD_GPF_NAME "wireshark.conf" /* old name for global preferences file */
76 static gboolean prefs_initialized = FALSE;
77 static gchar *gpf_path = NULL;
78 static gchar *cols_hidden_list = NULL;
79 static gboolean gui_theme_is_dark = FALSE;
82 * XXX - variables to allow us to attempt to interpret the first
83 * "mgcp.{tcp,udp}.port" in a preferences file as
84 * "mgcp.{tcp,udp}.gateway_port" and the second as
85 * "mgcp.{tcp,udp}.callagent_port".
87 static int mgcp_tcp_port_count;
88 static int mgcp_udp_port_count;
92 static const enum_val_t gui_console_open_type[] = {
93 {"NEVER", "NEVER", console_open_never},
94 {"AUTOMATIC", "AUTOMATIC", console_open_auto},
95 {"ALWAYS", "ALWAYS", console_open_always},
99 static const enum_val_t gui_version_placement_type[] = {
100 {"WELCOME", "WELCOME", version_welcome_only},
101 {"TITLE", "TITLE", version_title_only},
102 {"BOTH", "BOTH", version_both},
103 {"NEITHER", "NEITHER", version_neither},
107 static const enum_val_t gui_fileopen_style[] = {
108 {"LAST_OPENED", "LAST_OPENED", 0},
109 {"SPECIFIED", "SPECIFIED", 1},
113 static const enum_val_t gui_toolbar_style[] = {
114 {"ICONS", "ICONS", 0},
120 static const enum_val_t gui_layout_content[] = {
122 {"PLIST", "PLIST", 1},
123 {"PDETAILS", "PDETAILS", 2},
124 {"PBYTES", "PBYTES", 3},
128 static const enum_val_t gui_update_channel[] = {
129 {"DEVELOPMENT", "DEVELOPMENT", UPDATE_CHANNEL_DEVELOPMENT},
130 {"STABLE", "STABLE", UPDATE_CHANNEL_STABLE},
134 static const enum_val_t gui_selection_style[] = {
135 {"DEFAULT", "DEFAULT", COLOR_STYLE_DEFAULT},
136 {"FLAT", "FLAT", COLOR_STYLE_FLAT},
137 {"GRADIENT", "GRADIENT", COLOR_STYLE_GRADIENT},
141 #if defined(HAVE_PCAP_CREATE)
142 /* Can set monitor mode and buffer size. */
143 static gint num_capture_cols = 7;
144 static const gchar *capture_cols[7] = {
153 #define CAPTURE_COL_TYPE_DESCRIPTION \
154 "Possible values: INTERFACE, LINK, PMODE, SNAPLEN, MONITOR, BUFFER, FILTER\n"
155 #elif defined(CAN_SET_CAPTURE_BUFFER_SIZE)
156 /* Can set buffer size but not monitor mode. */
157 static gint num_capture_cols = 6;
158 static const gchar *capture_cols[6] = {
166 #define CAPTURE_COL_TYPE_DESCRIPTION \
167 "Possible values: INTERFACE, LINK, PMODE, SNAPLEN, BUFFER, FILTER\n"
169 /* Can neither set buffer size nor monitor mode. */
170 static gint num_capture_cols = 5;
171 static const gchar *capture_cols[5] = {
178 #define CAPTURE_COL_TYPE_DESCRIPTION \
179 "Possible values: INTERFACE, LINK, PMODE, SNAPLEN, FILTER\n"
182 static const enum_val_t gui_packet_list_elide_mode[] = {
183 {"LEFT", "LEFT", ELIDE_LEFT},
184 {"RIGHT", "RIGHT", ELIDE_RIGHT},
185 {"MIDDLE", "MIDDLE", ELIDE_MIDDLE},
186 {"NONE", "NONE", ELIDE_NONE},
190 /** Struct to hold preference data */
192 const char *name; /**< name of preference */
193 const char *title; /**< title to use in GUI */
194 const char *description; /**< human-readable description of preference */
195 int ordinal; /**< ordinal number of this preference */
196 int type; /**< type of that preference */
197 unsigned int effect_flags; /**< Flags of types effected by preference (PREF_TYPE_DISSECTION, PREF_EFFECT_CAPTURE, etc).
198 Flags must be non-zero to ensure saving to disk */
199 gui_type_t gui; /**< type of the GUI (QT, GTK or both) the preference is registered for */
200 union { /* The Qt preference code assumes that these will all be pointers (and unique) */
206 struct epan_uat* uat;
209 } varp; /**< pointer to variable storing the value */
218 } stashed_val; /**< original value, when editing from the GUI */
227 } default_val; /**< the default value of the preference */
229 guint base; /**< input/output base, for PREF_UINT */
230 guint32 max_value; /**< maximum value of a range */
232 const enum_val_t *enumvals; /**< list of name & values */
233 gboolean radio_buttons; /**< TRUE if it should be shown as
234 radio buttons rather than as an
235 option menu or combo box in
236 the preferences tab */
237 } enum_info; /**< for PREF_ENUM */
238 } info; /**< display/text file information */
239 struct pref_custom_cbs custom_cbs; /**< for PREF_CUSTOM */
242 const char* prefs_get_description(pref_t *pref)
244 return pref->description;
247 const char* prefs_get_title(pref_t *pref)
252 int prefs_get_type(pref_t *pref)
257 gui_type_t prefs_get_gui_type(pref_t *pref)
262 const char* prefs_get_name(pref_t *pref)
267 guint32 prefs_get_max_value(pref_t *pref)
269 return pref->info.max_value;
273 * List of all modules with preference settings.
275 static wmem_tree_t *prefs_modules = NULL;
278 * List of all modules that should show up at the top level of the
279 * tree in the preference dialog box.
281 static wmem_tree_t *prefs_top_level_modules = NULL;
284 * List of aliases for modules.
286 static wmem_tree_t *prefs_module_aliases = NULL;
288 /** Sets up memory used by proto routines. Called at program startup */
292 memset(&prefs, 0, sizeof(prefs));
293 prefs_modules = wmem_tree_new(wmem_epan_scope());
294 prefs_top_level_modules = wmem_tree_new(wmem_epan_scope());
295 prefs_module_aliases = wmem_tree_new(wmem_epan_scope());
299 * Free the strings for a string-like preference.
302 free_string_like_preference(pref_t *pref)
304 g_free(*pref->varp.string);
305 *pref->varp.string = NULL;
306 g_free(pref->default_val.string);
307 pref->default_val.string = NULL;
311 free_pref(gpointer data, gpointer user_data _U_)
313 pref_t *pref = (pref_t *)data;
314 int type = pref->type;
316 /* we reset the PREF_OBSOLETE bit in order to allow the original preference to be freed */
317 RESET_PREF_OBSOLETE(type);
323 case PREF_DECODE_AS_UINT:
324 case PREF_STATIC_TEXT:
329 case PREF_SAVE_FILENAME:
330 case PREF_OPEN_FILENAME:
332 free_string_like_preference(pref);
335 case PREF_DECODE_AS_RANGE:
336 wmem_free(wmem_epan_scope(), *pref->varp.range);
337 *pref->varp.range = NULL;
338 wmem_free(wmem_epan_scope(), pref->default_val.range);
339 pref->default_val.range = NULL;
342 if (strcmp(pref->name, "columns") == 0)
343 pref->stashed_val.boolval = TRUE;
344 pref->custom_cbs.free_cb(pref);
352 free_module_prefs(module_t *module, gpointer data _U_)
355 g_list_foreach(module->prefs, free_pref, NULL);
356 g_list_free(module->prefs);
358 module->prefs = NULL;
359 module->numprefs = 0;
360 if (module->submodules) {
361 prefs_module_list_foreach(module->submodules, free_module_prefs, NULL, FALSE);
363 /* We don't free the actual module: its submodules pointer points to
364 a wmem_tree and the module itself is stored in a wmem_tree
370 /** Frees memory used by proto routines. Called at program shutdown */
374 /* This isn't strictly necessary since we're exiting anyway, but let's
375 * do what clean up we can.
377 prefs_module_list_foreach(prefs_modules, free_module_prefs, NULL, FALSE);
382 /* Shut down mmdbresolve */
383 maxmind_db_pref_cleanup();
385 g_free(prefs.saved_at_version);
390 void prefs_set_gui_theme_is_dark(gboolean is_dark)
392 gui_theme_is_dark = is_dark;
396 * Register a module that will have preferences.
397 * Specify the module under which to register it or NULL to register it
398 * at the top level, the name used for the module in the preferences file,
399 * the title used in the tab for it in a preferences dialog box, and a
400 * routine to call back when we apply the preferences.
403 prefs_register_module(module_t *parent, const char *name, const char *title,
404 const char *description, void (*apply_cb)(void),
405 const gboolean use_gui)
407 return prefs_register_module_or_subtree(parent, name, title, description,
408 FALSE, apply_cb, use_gui);
412 prefs_deregister_module(module_t *parent, const char *name, const char *title)
414 /* Remove this module from the list of all modules */
415 module_t *module = (module_t *)wmem_tree_remove_string(prefs_modules, name, WMEM_TREE_STRING_NOCASE);
420 if (parent == NULL) {
421 /* Remove from top */
422 wmem_tree_remove_string(prefs_top_level_modules, title, WMEM_TREE_STRING_NOCASE);
423 } else if (parent->submodules) {
424 /* Remove from parent */
425 wmem_tree_remove_string(parent->submodules, title, WMEM_TREE_STRING_NOCASE);
428 free_module_prefs(module, NULL);
429 wmem_free(wmem_epan_scope(), module);
433 * Register a subtree that will have modules under it.
434 * Specify the module under which to register it or NULL to register it
435 * at the top level and the title used in the tab for it in a preferences
439 prefs_register_subtree(module_t *parent, const char *title, const char *description,
440 void (*apply_cb)(void))
442 return prefs_register_module_or_subtree(parent, NULL, title, description,
444 parent ? parent->use_gui : FALSE);
448 prefs_register_module_or_subtree(module_t *parent, const char *name,
449 const char *title, const char *description,
450 gboolean is_subtree, void (*apply_cb)(void),
457 /* this module may have been created as a subtree item previously */
458 if ((module = find_subtree(parent, title))) {
459 /* the module is currently a subtree */
461 module->apply_cb = apply_cb;
462 module->description = description;
464 if (prefs_find_module(name) == NULL) {
465 wmem_tree_insert_string(prefs_modules, name, module,
466 WMEM_TREE_STRING_NOCASE);
472 module = wmem_new(wmem_epan_scope(), module_t);
474 module->title = title;
475 module->description = description;
476 module->apply_cb = apply_cb;
477 module->prefs = NULL; /* no preferences, to start */
478 module->parent = parent;
479 module->submodules = NULL; /* no submodules, to start */
480 module->numprefs = 0;
481 module->prefs_changed_flags = 0;
482 module->obsolete = FALSE;
483 module->use_gui = use_gui;
484 /* A module's preferences affects dissection unless otherwise told */
485 module->effect_flags = PREF_EFFECT_DISSECTION;
488 * Do we have a module name?
493 * Make sure that only lower-case ASCII letters, numbers,
494 * underscores, hyphens, and dots appear in the name.
496 * Crash if there is, as that's an error in the code;
497 * you can make the title a nice string with capitalization,
498 * white space, punctuation, etc., but the name can be used
499 * on the command line, and shouldn't require quoting,
502 for (p = name; (c = *p) != '\0'; p++) {
503 if (!(g_ascii_islower(c) || g_ascii_isdigit(c) || c == '_' ||
504 c == '-' || c == '.'))
505 g_error("Preference module \"%s\" contains invalid characters", name);
509 * Make sure there's not already a module with that
510 * name. Crash if there is, as that's an error in the
511 * code, and the code has to be fixed not to register
512 * more than one module with the same name.
514 * We search the list of all modules; the subtree stuff
515 * doesn't require preferences in subtrees to have names
516 * that reflect the subtree they're in (that would require
517 * protocol preferences to have a bogus "protocol.", or
518 * something such as that, to be added to all their names).
520 g_assert(prefs_find_module(name) == NULL);
523 * Insert this module in the list of all modules.
525 wmem_tree_insert_string(prefs_modules, name, module, WMEM_TREE_STRING_NOCASE);
528 * This has no name, just a title; check to make sure it's a
529 * subtree, and crash if it's not.
531 g_assert(is_subtree);
535 * Insert this module into the appropriate place in the display
538 if (parent == NULL) {
540 * It goes at the top.
542 wmem_tree_insert_string(prefs_top_level_modules, title, module, WMEM_TREE_STRING_NOCASE);
545 * It goes into the list for this module.
548 if (parent->submodules == NULL)
549 parent->submodules = wmem_tree_new(wmem_epan_scope());
551 wmem_tree_insert_string(parent->submodules, title, module, WMEM_TREE_STRING_NOCASE);
558 prefs_register_module_alias(const char *name, module_t *module)
560 module_alias_t *alias;
566 * Make sure that only ASCII letters, numbers, underscores, hyphens,
567 * and dots appear in the name. We allow upper-case letters, to
568 * handle the Diameter dissector having used "Diameter" rather
569 * than "diameter" as its preference module name in the past.
571 * Crash if there is, as that's an error in the code, but the name
572 * can be used on the command line, and shouldn't require quoting,
575 for (p = name; (c = *p) != '\0'; p++) {
576 if (!(g_ascii_isalpha(c) || g_ascii_isdigit(c) || c == '_' ||
577 c == '-' || c == '.'))
578 g_error("Preference module alias \"%s\" contains invalid characters", name);
582 * Make sure there's not already an alias with that
583 * name. Crash if there is, as that's an error in the
584 * code, and the code has to be fixed not to register
585 * more than one alias with the same name.
587 * We search the list of all aliases.
589 g_assert(prefs_find_module_alias(name) == NULL);
591 alias = wmem_new(wmem_epan_scope(), module_alias_t);
593 alias->module = module;
596 * Insert this module in the list of all modules.
598 wmem_tree_insert_string(prefs_module_aliases, name, alias, WMEM_TREE_STRING_NOCASE);
602 * Register that a protocol has preferences.
604 module_t *protocols_module = NULL;
607 prefs_register_protocol(int id, void (*apply_cb)(void))
609 protocol_t *protocol;
612 * Have we yet created the "Protocols" subtree?
614 if (protocols_module == NULL) {
616 * No. Register Protocols subtree as well as any preferences
617 * for non-dissector modules.
620 prefs_register_modules();
622 protocol = find_protocol_by_id(id);
623 if (protocol == NULL)
624 g_error("Protocol preferences being registered with an invalid protocol ID");
625 return prefs_register_module(protocols_module,
626 proto_get_protocol_filter_name(id),
627 proto_get_protocol_short_name(protocol),
628 proto_get_protocol_name(id), apply_cb, TRUE);
632 prefs_deregister_protocol (int id)
634 protocol_t *protocol = find_protocol_by_id(id);
635 if (protocol == NULL)
636 g_error("Protocol preferences being de-registered with an invalid protocol ID");
637 prefs_deregister_module (protocols_module,
638 proto_get_protocol_filter_name(id),
639 proto_get_protocol_short_name(protocol));
643 prefs_register_protocol_subtree(const char *subtree, int id, void (*apply_cb)(void))
645 protocol_t *protocol;
646 module_t *subtree_module;
647 module_t *new_module;
648 char *sep = NULL, *ptr = NULL, *orig = NULL;
651 * Have we yet created the "Protocols" subtree?
652 * XXX - can we just do this by registering Protocols/{subtree}?
655 if (protocols_module == NULL) {
657 * No. Register Protocols subtree as well as any preferences
658 * for non-dissector modules.
661 prefs_register_modules();
664 subtree_module = protocols_module;
667 /* take a copy of the buffer, orig keeps a base pointer while ptr
668 * walks through the string */
669 orig = ptr = g_strdup(subtree);
671 while (ptr && *ptr) {
673 if ((sep = strchr(ptr, '/')))
676 if (!(new_module = find_subtree(subtree_module, ptr))) {
678 * There's no such module; create it, with the description
679 * being the name (if it's later registered explicitly
680 * with a description, that will override it).
682 ptr = wmem_strdup(wmem_epan_scope(), ptr);
683 new_module = prefs_register_subtree(subtree_module, ptr, ptr, NULL);
686 subtree_module = new_module;
694 protocol = find_protocol_by_id(id);
695 if (protocol == NULL)
696 g_error("Protocol subtree being registered with an invalid protocol ID");
697 return prefs_register_module(subtree_module,
698 proto_get_protocol_filter_name(id),
699 proto_get_protocol_short_name(protocol),
700 proto_get_protocol_name(id), apply_cb, TRUE);
705 * Register that a protocol used to have preferences but no longer does,
706 * by creating an "obsolete" module for it.
709 prefs_register_protocol_obsolete(int id)
712 protocol_t *protocol;
715 * Have we yet created the "Protocols" subtree?
717 if (protocols_module == NULL) {
719 * No. Register Protocols subtree as well as any preferences
720 * for non-dissector modules.
723 prefs_register_modules();
725 protocol = find_protocol_by_id(id);
726 if (protocol == NULL)
727 g_error("Protocol being registered with an invalid protocol ID");
728 module = prefs_register_module(protocols_module,
729 proto_get_protocol_filter_name(id),
730 proto_get_protocol_short_name(protocol),
731 proto_get_protocol_name(id), NULL, TRUE);
732 module->obsolete = TRUE;
737 * Register that a statistical tap has preferences.
739 * "name" is a name for the tap to use on the command line with "-o"
740 * and in preference files.
742 * "title" is a short human-readable name for the tap.
744 * "description" is a longer human-readable description of the tap.
746 module_t *stats_module = NULL;
749 prefs_register_stat(const char *name, const char *title,
750 const char *description, void (*apply_cb)(void))
753 * Have we yet created the "Statistics" subtree?
755 if (stats_module == NULL) {
757 * No. Register Statistics subtree as well as any preferences
758 * for non-dissector modules.
761 prefs_register_modules();
764 return prefs_register_module(stats_module, name, title, description,
769 * Register that a codec has preferences.
771 * "name" is a name for the codec to use on the command line with "-o"
772 * and in preference files.
774 * "title" is a short human-readable name for the codec.
776 * "description" is a longer human-readable description of the codec.
778 module_t *codecs_module = NULL;
781 prefs_register_codec(const char *name, const char *title,
782 const char *description, void (*apply_cb)(void))
785 * Have we yet created the "Codecs" subtree?
787 if (codecs_module == NULL) {
789 * No. Register Codecs subtree as well as any preferences
790 * for non-dissector modules.
793 prefs_register_modules();
796 return prefs_register_module(codecs_module, name, title, description,
801 prefs_find_module(const char *name)
803 return (module_t *)wmem_tree_lookup_string(prefs_modules, name, WMEM_TREE_STRING_NOCASE);
807 find_subtree(module_t *parent, const char *name)
809 return (module_t *)wmem_tree_lookup_string(parent ? parent->submodules : prefs_top_level_modules, name, WMEM_TREE_STRING_NOCASE);
813 * Call a callback function, with a specified argument, for each module
814 * in a list of modules. If the list is NULL, searches the top-level
815 * list in the display tree of modules. If any callback returns a
816 * non-zero value, we stop and return that value, otherwise we
819 * Normally "obsolete" modules are ignored; their sole purpose is to allow old
820 * preferences for dissectors that no longer have preferences to be
821 * silently ignored in preference files. Does not ignore subtrees,
822 * as this can be used when walking the display tree of modules.
829 gboolean skip_obsolete;
833 call_foreach_cb(const void *key _U_, void *value, void *data)
835 module_t *module = (module_t*)value;
836 call_foreach_t *call_data = (call_foreach_t*)data;
838 if (!call_data->skip_obsolete || !module->obsolete)
839 call_data->ret = (*call_data->callback)(module, call_data->user_data);
841 return (call_data->ret != 0);
845 prefs_module_list_foreach(wmem_tree_t *module_list, module_cb callback,
846 gpointer user_data, gboolean skip_obsolete)
848 call_foreach_t call_data;
850 if (module_list == NULL)
851 module_list = prefs_top_level_modules;
853 call_data.callback = callback;
854 call_data.user_data = user_data;
856 call_data.skip_obsolete = skip_obsolete;
857 wmem_tree_foreach(module_list, call_foreach_cb, &call_data);
858 return call_data.ret;
862 * Returns TRUE if module has any submodules
865 prefs_module_has_submodules(module_t *module)
867 if (module->submodules == NULL) {
871 if (wmem_tree_is_empty(module->submodules)) {
879 * Call a callback function, with a specified argument, for each module
880 * in the list of all modules. (This list does not include subtrees.)
882 * Ignores "obsolete" modules; their sole purpose is to allow old
883 * preferences for dissectors that no longer have preferences to be
884 * silently ignored in preference files.
887 prefs_modules_foreach(module_cb callback, gpointer user_data)
889 return prefs_module_list_foreach(prefs_modules, callback, user_data, TRUE);
893 * Call a callback function, with a specified argument, for each submodule
894 * of specified modules. If the module is NULL, goes through the top-level
895 * list in the display tree of modules.
897 * Ignores "obsolete" modules; their sole purpose is to allow old
898 * preferences for dissectors that no longer have preferences to be
899 * silently ignored in preference files. Does not ignore subtrees,
900 * as this can be used when walking the display tree of modules.
903 prefs_modules_foreach_submodules(module_t *module, module_cb callback,
906 return prefs_module_list_foreach((module)?module->submodules:prefs_top_level_modules, callback, user_data, TRUE);
910 call_apply_cb(const void *key _U_, void *value, void *data _U_)
912 module_t *module = (module_t *)value;
914 if (module->obsolete)
916 if (module->prefs_changed_flags) {
917 if (module->apply_cb != NULL)
918 (*module->apply_cb)();
919 module->prefs_changed_flags = 0;
921 if (module->submodules)
922 wmem_tree_foreach(module->submodules, call_apply_cb, NULL);
927 * Call the "apply" callback function for each module if any of its
928 * preferences have changed, and then clear the flag saying its
929 * preferences have changed, as the module has been notified of that
933 prefs_apply_all(void)
935 wmem_tree_foreach(prefs_modules, call_apply_cb, NULL);
939 * Call the "apply" callback function for a specific module if any of
940 * its preferences have changed, and then clear the flag saying its
941 * preferences have changed, as the module has been notified of that
945 prefs_apply(module_t *module)
947 if (module && module->prefs_changed_flags)
948 call_apply_cb(NULL, module, NULL);
952 prefs_find_module_alias(const char *name)
954 module_alias_t *alias;
956 alias = (module_alias_t *)wmem_tree_lookup_string(prefs_module_aliases, name, WMEM_TREE_STRING_NOCASE);
959 return alias->module;
963 * Register a preference in a module's list of preferences.
964 * If it has a title, give it an ordinal number; otherwise, it's a
965 * preference that won't show up in the UI, so it shouldn't get an
966 * ordinal number (the ordinal should be the ordinal in the set of
967 * *visible* preferences).
970 register_preference(module_t *module, const char *name, const char *title,
971 const char *description, int type)
975 const char *name_prefix = (module->name != NULL) ? module->name : module->parent->name;
977 preference = g_new(pref_t,1);
978 preference->name = name;
979 preference->title = title;
980 preference->description = description;
981 preference->type = type;
982 /* Default to module's preference effects */
983 preference->effect_flags = module->effect_flags;
985 preference->gui = GUI_ALL; /* default */
987 preference->ordinal = module->numprefs;
989 preference->ordinal = -1; /* no ordinal for you */
992 * Make sure that only lower-case ASCII letters, numbers,
993 * underscores, and dots appear in the preference name.
995 * Crash if there is, as that's an error in the code;
996 * you can make the title and description nice strings
997 * with capitalization, white space, punctuation, etc.,
998 * but the name can be used on the command line,
999 * and shouldn't require quoting, shifting, etc.
1001 for (p = name; *p != '\0'; p++)
1002 if (!(g_ascii_islower(*p) || g_ascii_isdigit(*p) || *p == '_' || *p == '.'))
1003 g_error("Preference \"%s.%s\" contains invalid characters", module->name, name);
1006 * Make sure there's not already a preference with that
1007 * name. Crash if there is, as that's an error in the
1008 * code, and the code has to be fixed not to register
1009 * more than one preference with the same name.
1011 if (prefs_find_preference(module, name) != NULL)
1012 g_error("Preference %s has already been registered", name);
1014 if ((!IS_PREF_OBSOLETE(type)) &&
1015 /* Don't compare if it's a subtree */
1016 (module->name != NULL)) {
1018 * Make sure the preference name doesn't begin with the
1019 * module name, as that's redundant and Just Silly.
1021 if (!((strncmp(name, module->name, strlen(module->name)) != 0) ||
1022 (((name[strlen(module->name)]) != '.') && ((name[strlen(module->name)]) != '_'))))
1023 g_error("Preference %s begins with the module name", name);
1026 /* The title shows up in the preferences dialog. Make sure it's UI-friendly. */
1027 if (preference->title) {
1028 const char *cur_char;
1029 if (preference->type != PREF_STATIC_TEXT && g_utf8_strlen(preference->title, -1) > 80) { // Arbitrary.
1030 g_error("Title for preference %s.%s is too long: %s", name_prefix, preference->name, preference->title);
1033 if (!g_utf8_validate(preference->title, -1, NULL)) {
1034 g_error("Title for preference %s.%s isn't valid UTF-8.", name_prefix, preference->name);
1037 for (cur_char = preference->title; *cur_char; cur_char = g_utf8_next_char(cur_char)) {
1038 if (!g_unichar_isprint(g_utf8_get_char(cur_char))) {
1039 g_error("Title for preference %s.%s isn't printable UTF-8.", name_prefix, preference->name);
1044 if (preference->description) {
1045 if (!g_utf8_validate(preference->description, -1, NULL)) {
1046 g_error("Description for preference %s.%s isn't valid UTF-8.", name_prefix, preference->name);
1051 * We passed all of our checks. Add the preference.
1053 module->prefs = g_list_append(module->prefs, preference);
1061 * Find a preference in a module's list of preferences, given the module
1062 * and the preference's name.
1067 module_t *submodule;
1071 preference_match(gconstpointer a, gconstpointer b)
1073 const pref_t *pref = (const pref_t *)a;
1074 const char *name = (const char *)b;
1076 return strcmp(name, pref->name);
1080 module_find_pref_cb(const void *key _U_, void *value, void *data)
1082 find_pref_arg_t* arg = (find_pref_arg_t*)data;
1084 module_t *module = (module_t *)value;
1089 list_entry = g_list_find_custom(module->prefs, arg->name,
1092 if (list_entry == NULL)
1095 arg->list_entry = list_entry;
1096 arg->submodule = module;
1100 /* Tries to find a preference, setting containing_module to the (sub)module
1101 * holding this preference. */
1102 static struct preference *
1103 prefs_find_preference_with_submodule(module_t *module, const char *name,
1104 module_t **containing_module)
1106 find_pref_arg_t arg;
1110 return NULL; /* invalid parameters */
1112 list_entry = g_list_find_custom(module->prefs, name,
1114 arg.submodule = NULL;
1116 if (list_entry == NULL)
1118 arg.list_entry = NULL;
1119 if (module->submodules != NULL)
1122 wmem_tree_foreach(module->submodules, module_find_pref_cb, &arg);
1125 list_entry = arg.list_entry;
1128 if (list_entry == NULL)
1129 return NULL; /* no such preference */
1131 if (containing_module)
1132 *containing_module = arg.submodule ? arg.submodule : module;
1134 return (struct preference *) list_entry->data;
1138 prefs_find_preference(module_t *module, const char *name)
1140 return prefs_find_preference_with_submodule(module, name, NULL);
1144 * Returns TRUE if the given protocol has registered preferences
1147 prefs_is_registered_protocol(const char *name)
1149 module_t *m = prefs_find_module(name);
1151 return (m != NULL && !m->obsolete);
1155 * Returns the module title of a registered protocol
1158 prefs_get_title_by_name(const char *name)
1160 module_t *m = prefs_find_module(name);
1162 return (m != NULL && !m->obsolete) ? m->title : NULL;
1166 * Register a preference with an unsigned integral value.
1169 prefs_register_uint_preference(module_t *module, const char *name,
1170 const char *title, const char *description,
1171 guint base, guint *var)
1175 preference = register_preference(module, name, title, description,
1177 preference->varp.uint = var;
1178 preference->default_val.uint = *var;
1179 g_assert(base > 0 && base != 1 && base < 37);
1180 preference->info.base = base;
1184 * XXX Add a prefs_register_{uint16|port}_preference which sets max_value?
1189 * Register a "custom" preference with a unsigned integral value.
1190 * XXX - This should be temporary until we can find a better way
1191 * to do "custom" preferences
1194 prefs_register_uint_custom_preference(module_t *module, const char *name,
1195 const char *title, const char *description,
1196 struct pref_custom_cbs* custom_cbs, guint *var)
1200 preference = register_preference(module, name, title, description,
1203 preference->custom_cbs = *custom_cbs;
1204 preference->varp.uint = var;
1205 preference->default_val.uint = *var;
1209 * Register a preference with an Boolean value.
1212 prefs_register_bool_preference(module_t *module, const char *name,
1213 const char *title, const char *description,
1218 preference = register_preference(module, name, title, description,
1220 preference->varp.boolp = var;
1221 preference->default_val.boolval = *var;
1224 unsigned int prefs_set_bool_value(pref_t *pref, gboolean value, pref_source_t source)
1226 unsigned int changed = 0;
1231 if (pref->default_val.boolval != value) {
1232 pref->default_val.boolval = value;
1233 changed = prefs_get_effect_flags(pref);
1237 if (pref->stashed_val.boolval != value) {
1238 pref->stashed_val.boolval = value;
1239 changed = prefs_get_effect_flags(pref);
1243 if (*pref->varp.boolp != value) {
1244 *pref->varp.boolp = value;
1245 changed = prefs_get_effect_flags(pref);
1249 g_assert_not_reached();
1256 void prefs_invert_bool_value(pref_t *pref, pref_source_t source)
1261 pref->default_val.boolval = !pref->default_val.boolval;
1264 pref->stashed_val.boolval = !pref->stashed_val.boolval;
1267 *pref->varp.boolp = !(*pref->varp.boolp);
1270 g_assert_not_reached();
1275 gboolean prefs_get_bool_value(pref_t *pref, pref_source_t source)
1280 return pref->default_val.boolval;
1283 return pref->stashed_val.boolval;
1286 return *pref->varp.boolp;
1289 g_assert_not_reached();
1297 * Register a preference with an enumerated value.
1300 * XXX Should we get rid of the radio_buttons parameter and make that
1301 * behavior automatic depending on the number of items?
1304 prefs_register_enum_preference(module_t *module, const char *name,
1305 const char *title, const char *description,
1306 gint *var, const enum_val_t *enumvals,
1307 gboolean radio_buttons)
1311 preference = register_preference(module, name, title, description,
1313 preference->varp.enump = var;
1314 preference->default_val.enumval = *var;
1315 preference->info.enum_info.enumvals = enumvals;
1316 preference->info.enum_info.radio_buttons = radio_buttons;
1319 unsigned int prefs_set_enum_value(pref_t *pref, gint value, pref_source_t source)
1321 unsigned int changed = 0;
1326 if (pref->default_val.enumval != value) {
1327 pref->default_val.enumval = value;
1328 changed = prefs_get_effect_flags(pref);
1332 if (pref->stashed_val.enumval != value) {
1333 pref->stashed_val.enumval = value;
1334 changed = prefs_get_effect_flags(pref);
1338 if (*pref->varp.enump != value) {
1339 *pref->varp.enump = value;
1340 changed = prefs_get_effect_flags(pref);
1344 g_assert_not_reached();
1351 gint prefs_get_enum_value(pref_t *pref, pref_source_t source)
1356 return pref->default_val.enumval;
1359 return pref->stashed_val.enumval;
1362 return *pref->varp.enump;
1365 g_assert_not_reached();
1372 const enum_val_t* prefs_get_enumvals(pref_t *pref)
1374 return pref->info.enum_info.enumvals;
1377 gboolean prefs_get_enum_radiobuttons(pref_t *pref)
1379 return pref->info.enum_info.radio_buttons;
1383 register_string_like_preference(module_t *module, const char *name,
1384 const char *title, const char *description,
1385 char **var, int type,
1386 struct pref_custom_cbs* custom_cbs,
1392 pref = register_preference(module, name, title, description, type);
1395 * String preference values should be non-null (as you can't
1396 * keep them null after using the preferences GUI, you can at best
1397 * have them be null strings) and freeable (as we free them
1398 * if we change them).
1400 * If the value is a null pointer, make it a copy of a null
1401 * string, otherwise make it a copy of the value.
1405 *var = g_strdup("");
1407 *var = g_strdup(*var);
1412 pref->varp.string = var;
1413 pref->default_val.string = g_strdup(*var);
1414 pref->stashed_val.string = NULL;
1415 if (type == PREF_CUSTOM) {
1416 g_assert(custom_cbs);
1417 pref->custom_cbs = *custom_cbs;
1422 * Assign to a string preference.
1425 pref_set_string_like_pref_value(pref_t *pref, const gchar *value)
1428 g_free((void *)*pref->varp.string);
1430 *pref->varp.string = g_strdup(value);
1434 * For use by UI code that sets preferences.
1437 prefs_set_string_value(pref_t *pref, const char* value, pref_source_t source)
1439 unsigned int changed = 0;
1444 if (*pref->default_val.string) {
1445 if (strcmp(pref->default_val.string, value) != 0) {
1446 changed = prefs_get_effect_flags(pref);
1447 g_free(pref->default_val.string);
1448 pref->default_val.string = g_strdup(value);
1451 pref->default_val.string = g_strdup(value);
1455 if (pref->stashed_val.string) {
1456 if (strcmp(pref->stashed_val.string, value) != 0) {
1457 changed = prefs_get_effect_flags(pref);
1458 g_free(pref->stashed_val.string);
1459 pref->stashed_val.string = g_strdup(value);
1462 pref->stashed_val.string = g_strdup(value);
1466 if (*pref->varp.string) {
1467 if (strcmp(*pref->varp.string, value) != 0) {
1468 changed = prefs_get_effect_flags(pref);
1469 pref_set_string_like_pref_value(pref, value);
1472 pref_set_string_like_pref_value(pref, value);
1476 g_assert_not_reached();
1483 char* prefs_get_string_value(pref_t *pref, pref_source_t source)
1488 return pref->default_val.string;
1490 return pref->stashed_val.string;
1492 return *pref->varp.string;
1494 g_assert_not_reached();
1502 * Reset the value of a string-like preference.
1505 reset_string_like_preference(pref_t *pref)
1507 g_free(*pref->varp.string);
1508 *pref->varp.string = g_strdup(pref->default_val.string);
1512 * Register a preference with a character-string value.
1515 prefs_register_string_preference(module_t *module, const char *name,
1516 const char *title, const char *description,
1520 register_string_like_preference(module, name, title, description,
1521 (char **)var, PREF_STRING, NULL, FALSE);
1526 * Register a preference with a file name (string) value.
1529 prefs_register_filename_preference(module_t *module, const char *name,
1530 const char *title, const char *description,
1531 const char **var, gboolean for_writing)
1534 register_string_like_preference(module, name, title, description, (char **)var,
1535 for_writing ? PREF_SAVE_FILENAME : PREF_OPEN_FILENAME, NULL, FALSE);
1540 * Register a preference with a directory name (string) value.
1543 prefs_register_directory_preference(module_t *module, const char *name,
1544 const char *title, const char *description,
1548 register_string_like_preference(module, name, title, description,
1549 (char **)var, PREF_DIRNAME, NULL, FALSE);
1553 /* Refactoring to handle both PREF_RANGE and PREF_DECODE_AS_RANGE */
1555 prefs_register_range_preference_common(module_t *module, const char *name,
1556 const char *title, const char *description,
1557 range_t **var, guint32 max_value, int type)
1561 preference = register_preference(module, name, title, description, type);
1562 preference->info.max_value = max_value;
1565 * Range preference values should be non-null (as you can't
1566 * keep them null after using the preferences GUI, you can at best
1567 * have them be empty ranges) and freeable (as we free them
1568 * if we change them).
1570 * If the value is a null pointer, make it an empty range.
1573 *var = range_empty(wmem_epan_scope());
1574 preference->varp.range = var;
1575 preference->default_val.range = range_copy(wmem_epan_scope(), *var);
1576 preference->stashed_val.range = NULL;
1580 * Register a preference with a ranged value.
1583 prefs_register_range_preference(module_t *module, const char *name,
1584 const char *title, const char *description,
1585 range_t **var, guint32 max_value)
1587 prefs_register_range_preference_common(module, name, title,
1588 description, var, max_value, PREF_RANGE);
1592 prefs_set_range_value_work(pref_t *pref, const gchar *value,
1593 gboolean return_range_errors, unsigned int *changed_flags)
1597 if (range_convert_str_work(wmem_epan_scope(), &newrange, value, pref->info.max_value,
1598 return_range_errors) != CVT_NO_ERROR) {
1599 return FALSE; /* number was bad */
1602 if (!ranges_are_equal(*pref->varp.range, newrange)) {
1603 *changed_flags |= prefs_get_effect_flags(pref);
1604 wmem_free(wmem_epan_scope(), *pref->varp.range);
1605 *pref->varp.range = newrange;
1607 wmem_free(wmem_epan_scope(), newrange);
1613 * For use by UI code that sets preferences.
1616 prefs_set_stashed_range_value(pref_t *pref, const gchar *value)
1620 if (range_convert_str_work(wmem_epan_scope(), &newrange, value, pref->info.max_value,
1621 TRUE) != CVT_NO_ERROR) {
1622 return 0; /* number was bad */
1625 if (!ranges_are_equal(pref->stashed_val.range, newrange)) {
1626 wmem_free(wmem_epan_scope(), pref->stashed_val.range);
1627 pref->stashed_val.range = newrange;
1629 wmem_free(wmem_epan_scope(), newrange);
1631 return prefs_get_effect_flags(pref);
1635 gboolean prefs_set_range_value(pref_t *pref, range_t *value, pref_source_t source)
1637 gboolean changed = FALSE;
1642 if (!ranges_are_equal(pref->default_val.range, value)) {
1643 wmem_free(wmem_epan_scope(), pref->default_val.range);
1644 pref->default_val.range = range_copy(wmem_epan_scope(), value);
1649 if (!ranges_are_equal(pref->stashed_val.range, value)) {
1650 wmem_free(wmem_epan_scope(), pref->stashed_val.range);
1651 pref->stashed_val.range = range_copy(wmem_epan_scope(), value);
1656 if (!ranges_are_equal(*pref->varp.range, value)) {
1657 wmem_free(wmem_epan_scope(), *pref->varp.range);
1658 *pref->varp.range = range_copy(wmem_epan_scope(), value);
1663 g_assert_not_reached();
1670 range_t* prefs_get_range_value_real(pref_t *pref, pref_source_t source)
1675 return pref->default_val.range;
1677 return pref->stashed_val.range;
1680 return *pref->varp.range;
1683 g_assert_not_reached();
1690 range_t* prefs_get_range_value(const char *module_name, const char* pref_name)
1692 return prefs_get_range_value_real(prefs_find_preference(prefs_find_module(module_name), pref_name), pref_current);
1696 prefs_range_add_value(pref_t *pref, guint32 val)
1698 range_add_value(wmem_epan_scope(), pref->varp.range, val);
1702 prefs_range_remove_value(pref_t *pref, guint32 val)
1704 range_remove_value(wmem_epan_scope(), pref->varp.range, val);
1708 * Register a static text 'preference'. It can be used to add explanatory
1709 * text inline with other preferences in the GUI.
1710 * Note: Static preferences are not saved to the preferences file.
1713 prefs_register_static_text_preference(module_t *module, const char *name,
1715 const char *description)
1717 register_preference(module, name, title, description, PREF_STATIC_TEXT);
1721 * Register a uat 'preference'. It adds a button that opens the uat's window in the
1722 * preferences tab of the module.
1725 prefs_register_uat_preference(module_t *module, const char *name,
1726 const char *title, const char *description,
1730 pref_t* preference = register_preference(module, name, title, description, PREF_UAT);
1732 preference->varp.uat = uat;
1736 * Register a uat 'preference' for QT only. It adds a button that opens the uat's window in the
1737 * preferences tab of the module.
1740 prefs_register_uat_preference_qt(module_t *module, const char *name,
1741 const char *title, const char *description,
1745 pref_t* preference = register_preference(module, name, title, description, PREF_UAT);
1747 preference->varp.uat = uat;
1749 preference->gui = GUI_QT;
1752 struct epan_uat* prefs_get_uat_value(pref_t *pref)
1754 return pref->varp.uat;
1758 * Register a color preference.
1761 prefs_register_color_preference(module_t *module, const char *name,
1762 const char *title, const char *description,
1765 pref_t* preference = register_preference(module, name, title, description, PREF_COLOR);
1767 preference->varp.colorp = color;
1768 preference->default_val.color = *color;
1771 gboolean prefs_set_color_value(pref_t *pref, color_t value, pref_source_t source)
1773 gboolean changed = FALSE;
1778 if ((pref->default_val.color.red != value.red) ||
1779 (pref->default_val.color.green != value.green) ||
1780 (pref->default_val.color.blue != value.blue)) {
1782 pref->default_val.color = value;
1786 if ((pref->stashed_val.color.red != value.red) ||
1787 (pref->stashed_val.color.green != value.green) ||
1788 (pref->stashed_val.color.blue != value.blue)) {
1790 pref->stashed_val.color = value;
1794 if ((pref->varp.colorp->red != value.red) ||
1795 (pref->varp.colorp->green != value.green) ||
1796 (pref->varp.colorp->blue != value.blue)) {
1798 *pref->varp.colorp = value;
1802 g_assert_not_reached();
1809 color_t* prefs_get_color_value(pref_t *pref, pref_source_t source)
1814 return &pref->default_val.color;
1816 return &pref->stashed_val.color;
1819 return pref->varp.colorp;
1822 g_assert_not_reached();
1830 * Register a "custom" preference with a list.
1831 * XXX - This should be temporary until we can find a better way
1832 * to do "custom" preferences
1834 typedef void (*pref_custom_list_init_cb) (pref_t* pref, GList** value);
1837 prefs_register_list_custom_preference(module_t *module, const char *name,
1838 const char *title, const char *description,
1839 struct pref_custom_cbs* custom_cbs,
1840 pref_custom_list_init_cb init_cb,
1843 pref_t* preference = register_preference(module, name, title, description, PREF_CUSTOM);
1845 preference->custom_cbs = *custom_cbs;
1846 init_cb(preference, list);
1850 * Register a custom preference.
1853 prefs_register_custom_preference(module_t *module, const char *name,
1854 const char *title, const char *description,
1855 struct pref_custom_cbs* custom_cbs,
1856 void **custom_data _U_)
1858 pref_t* preference = register_preference(module, name, title, description, PREF_CUSTOM);
1860 preference->custom_cbs = *custom_cbs;
1861 /* XXX - wait until we can handle void** pointers
1862 preference->custom_cbs.init_cb(preference, custom_data);
1867 * Register a (internal) "Decode As" preference with a ranged value.
1869 void prefs_register_decode_as_range_preference(module_t *module, const char *name,
1870 const char *title, const char *description, range_t **var,
1873 prefs_register_range_preference_common(module, name, title,
1874 description, var, max_value, PREF_DECODE_AS_RANGE);
1878 * Register a (internal) "Decode As" preference with an unsigned integral value
1879 * for a dissector table.
1881 void prefs_register_decode_as_preference(module_t *module, const char *name,
1882 const char *title, const char *description, guint *var)
1886 preference = register_preference(module, name, title, description,
1887 PREF_DECODE_AS_UINT);
1888 preference->varp.uint = var;
1889 preference->default_val.uint = *var;
1890 /* XXX - Presume base 10 for now */
1891 preference->info.base = 10;
1894 gboolean prefs_add_decode_as_value(pref_t *pref, guint value, gboolean replace)
1898 case PREF_DECODE_AS_UINT:
1899 /* This doesn't support multiple values for a dissector in Decode As because the
1900 preference only supports a single value. This leads to a "last port for
1901 dissector in Decode As wins" */
1902 *pref->varp.uint = value;
1904 case PREF_DECODE_AS_RANGE:
1907 /* If range has single value, replace it */
1908 if (((*pref->varp.range)->nranges == 1) &&
1909 ((*pref->varp.range)->ranges[0].low == (*pref->varp.range)->ranges[0].high)) {
1910 wmem_free(wmem_epan_scope(), *pref->varp.range);
1911 *pref->varp.range = range_empty(wmem_epan_scope());
1915 prefs_range_add_value(pref, value);
1918 /* XXX - Worth asserting over? */
1925 gboolean prefs_remove_decode_as_value(pref_t *pref, guint value, gboolean set_default)
1929 case PREF_DECODE_AS_UINT:
1931 *pref->varp.uint = pref->default_val.uint;
1933 *pref->varp.uint = 0;
1936 case PREF_DECODE_AS_RANGE:
1937 prefs_range_remove_value(pref, value);
1947 * Register a preference that used to be supported but no longer is.
1950 prefs_register_obsolete_preference(module_t *module, const char *name)
1952 register_preference(module, name, NULL, NULL, PREF_OBSOLETE);
1956 * Check to see if a preference is obsolete.
1959 prefs_get_preference_obsolete(pref_t *pref)
1962 return (IS_PREF_OBSOLETE(pref->type) ? TRUE : FALSE);
1968 * Make a preference obsolete.
1970 extern prefs_set_pref_e
1971 prefs_set_preference_obsolete(pref_t *pref)
1974 SET_PREF_OBSOLETE(pref->type);
1975 return PREFS_SET_OK;
1977 return PREFS_SET_NO_SUCH_PREF;
1981 pref_stash(pref_t *pref, gpointer unused _U_)
1983 switch (pref->type) {
1985 case PREF_DECODE_AS_UINT:
1986 pref->stashed_val.uint = *pref->varp.uint;
1990 pref->stashed_val.uint = *pref->varp.uint;
1994 pref->stashed_val.boolval = *pref->varp.boolp;
1998 pref->stashed_val.enumval = *pref->varp.enump;
2002 case PREF_SAVE_FILENAME:
2003 case PREF_OPEN_FILENAME:
2005 g_free(pref->stashed_val.string);
2006 pref->stashed_val.string = g_strdup(*pref->varp.string);
2009 case PREF_DECODE_AS_RANGE:
2011 wmem_free(wmem_epan_scope(), pref->stashed_val.range);
2012 pref->stashed_val.range = range_copy(wmem_epan_scope(), *pref->varp.range);
2016 pref->stashed_val.color = *pref->varp.colorp;
2019 case PREF_STATIC_TEXT:
2025 g_assert_not_reached();
2032 pref_unstash(pref_t *pref, gpointer unstash_data_p)
2034 pref_unstash_data_t *unstash_data = (pref_unstash_data_t *)unstash_data_p;
2035 dissector_table_t sub_dissectors = NULL;
2036 dissector_handle_t handle = NULL;
2038 /* Revert the preference to its saved value. */
2039 switch (pref->type) {
2041 case PREF_DECODE_AS_UINT:
2042 if (*pref->varp.uint != pref->stashed_val.uint) {
2043 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2045 if (unstash_data->handle_decode_as) {
2046 if (*pref->varp.uint != pref->default_val.uint) {
2047 dissector_reset_uint(pref->name, *pref->varp.uint);
2051 *pref->varp.uint = pref->stashed_val.uint;
2053 if (unstash_data->handle_decode_as) {
2054 sub_dissectors = find_dissector_table(pref->name);
2055 if (sub_dissectors != NULL) {
2056 handle = dissector_table_get_dissector_handle(sub_dissectors, unstash_data->module->title);
2057 if (handle != NULL) {
2058 dissector_change_uint(pref->name, *pref->varp.uint, handle);
2066 if (*pref->varp.uint != pref->stashed_val.uint) {
2067 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2068 *pref->varp.uint = pref->stashed_val.uint;
2073 if (*pref->varp.boolp != pref->stashed_val.boolval) {
2074 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2075 *pref->varp.boolp = pref->stashed_val.boolval;
2080 if (*pref->varp.enump != pref->stashed_val.enumval) {
2081 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2082 *pref->varp.enump = pref->stashed_val.enumval;
2087 case PREF_SAVE_FILENAME:
2088 case PREF_OPEN_FILENAME:
2090 if (strcmp(*pref->varp.string, pref->stashed_val.string) != 0) {
2091 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2092 g_free(*pref->varp.string);
2093 *pref->varp.string = g_strdup(pref->stashed_val.string);
2097 case PREF_DECODE_AS_RANGE:
2098 if (!ranges_are_equal(*pref->varp.range, pref->stashed_val.range)) {
2100 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2102 if (unstash_data->handle_decode_as) {
2103 sub_dissectors = find_dissector_table(pref->name);
2104 if (sub_dissectors != NULL) {
2105 handle = dissector_table_get_dissector_handle(sub_dissectors, unstash_data->module->title);
2106 if (handle != NULL) {
2107 /* Delete all of the old values from the dissector table */
2108 for (i = 0; i < (*pref->varp.range)->nranges; i++) {
2109 for (j = (*pref->varp.range)->ranges[i].low; j < (*pref->varp.range)->ranges[i].high; j++) {
2110 dissector_delete_uint(pref->name, j, handle);
2111 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(j), NULL, NULL);
2114 dissector_delete_uint(pref->name, (*pref->varp.range)->ranges[i].high, handle);
2115 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER((*pref->varp.range)->ranges[i].high), NULL, NULL);
2121 wmem_free(wmem_epan_scope(), *pref->varp.range);
2122 *pref->varp.range = range_copy(wmem_epan_scope(), pref->stashed_val.range);
2124 if (unstash_data->handle_decode_as) {
2125 if ((sub_dissectors != NULL) && (handle != NULL)) {
2127 /* Add new values to the dissector table */
2128 for (i = 0; i < (*pref->varp.range)->nranges; i++) {
2130 for (j = (*pref->varp.range)->ranges[i].low; j < (*pref->varp.range)->ranges[i].high; j++) {
2131 dissector_change_uint(pref->name, j, handle);
2132 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(j), NULL, NULL);
2135 dissector_change_uint(pref->name, (*pref->varp.range)->ranges[i].high, handle);
2136 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER((*pref->varp.range)->ranges[i].high), NULL, NULL);
2144 if (!ranges_are_equal(*pref->varp.range, pref->stashed_val.range)) {
2145 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2146 wmem_free(wmem_epan_scope(), *pref->varp.range);
2147 *pref->varp.range = range_copy(wmem_epan_scope(), pref->stashed_val.range);
2152 if ((pref->varp.colorp->blue != pref->stashed_val.color.blue) ||
2153 (pref->varp.colorp->red != pref->stashed_val.color.red) ||
2154 (pref->varp.colorp->green != pref->stashed_val.color.green)) {
2155 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2156 *pref->varp.colorp = pref->stashed_val.color;
2160 case PREF_STATIC_TEXT:
2166 g_assert_not_reached();
2173 reset_stashed_pref(pref_t *pref) {
2174 switch (pref->type) {
2176 case PREF_DECODE_AS_UINT:
2177 pref->stashed_val.uint = pref->default_val.uint;
2181 pref->stashed_val.uint = pref->default_val.uint;
2185 pref->stashed_val.boolval = pref->default_val.boolval;
2189 pref->stashed_val.enumval = pref->default_val.enumval;
2193 case PREF_SAVE_FILENAME:
2194 case PREF_OPEN_FILENAME:
2196 g_free(pref->stashed_val.string);
2197 pref->stashed_val.string = g_strdup(pref->default_val.string);
2200 case PREF_DECODE_AS_RANGE:
2202 wmem_free(wmem_epan_scope(), pref->stashed_val.range);
2203 pref->stashed_val.range = range_copy(wmem_epan_scope(), pref->default_val.range);
2207 memcpy(&pref->stashed_val.color, &pref->default_val.color, sizeof(color_t));
2210 case PREF_STATIC_TEXT:
2216 g_assert_not_reached();
2222 pref_clean_stash(pref_t *pref, gpointer unused _U_)
2224 switch (pref->type) {
2227 case PREF_DECODE_AS_UINT:
2237 case PREF_SAVE_FILENAME:
2238 case PREF_OPEN_FILENAME:
2240 if (pref->stashed_val.string != NULL) {
2241 g_free(pref->stashed_val.string);
2242 pref->stashed_val.string = NULL;
2246 case PREF_DECODE_AS_RANGE:
2248 if (pref->stashed_val.range != NULL) {
2249 wmem_free(wmem_epan_scope(), pref->stashed_val.range);
2250 pref->stashed_val.range = NULL;
2254 case PREF_STATIC_TEXT:
2261 g_assert_not_reached();
2268 /* Return the value assigned to the given uint preference. */
2270 prefs_get_uint_preference(pref_t *pref)
2272 if (pref && pref->type == PREF_UINT)
2273 return *pref->varp.uint;
2279 * Call a callback function, with a specified argument, for each preference
2280 * in a given module.
2282 * If any of the callbacks return a non-zero value, stop and return that
2283 * value, otherwise return 0.
2286 prefs_pref_foreach(module_t *module, pref_cb callback, gpointer user_data)
2292 for (elem = g_list_first(module->prefs); elem != NULL; elem = g_list_next(elem)) {
2293 pref = (pref_t *)elem->data;
2294 if (IS_PREF_OBSOLETE(pref->type)) {
2296 * This preference is no longer supported; it's
2297 * not a real preference, so we don't call the
2298 * callback for it (i.e., we treat it as if it
2299 * weren't found in the list of preferences,
2300 * and we weren't called in the first place).
2305 ret = (*callback)(pref, user_data);
2312 static const enum_val_t st_sort_col_vals[] = {
2313 { "name", "Node name (topic/item)", ST_SORT_COL_NAME },
2314 { "count", "Item count", ST_SORT_COL_COUNT },
2315 { "average", "Average value of the node", ST_SORT_COL_AVG },
2316 { "min", "Minimum value of the node", ST_SORT_COL_MIN },
2317 { "max", "Maximum value of the node", ST_SORT_COL_MAX },
2318 { "burst", "Burst rate of the node", ST_SORT_COL_BURSTRATE },
2323 stats_callback(void)
2325 /* Test for a sane tap update interval */
2326 if (prefs.tap_update_interval < 100 || prefs.tap_update_interval > 10000)
2327 prefs.tap_update_interval = TAP_UPDATE_DEFAULT_INTERVAL;
2329 /* burst resolution can't be less than 1 (ms) */
2330 if (prefs.st_burst_resolution < 1) {
2331 prefs.st_burst_resolution = 1;
2333 else if (prefs.st_burst_resolution > ST_MAX_BURSTRES) {
2334 prefs.st_burst_resolution = ST_MAX_BURSTRES;
2336 /* make sure burst window value makes sense */
2337 if (prefs.st_burst_windowlen < prefs.st_burst_resolution) {
2338 prefs.st_burst_windowlen = prefs.st_burst_resolution;
2340 /* round burst window down to multiple of resolution */
2341 prefs.st_burst_windowlen -= prefs.st_burst_windowlen%prefs.st_burst_resolution;
2342 if ((prefs.st_burst_windowlen/prefs.st_burst_resolution) > ST_MAX_BURSTBUCKETS) {
2343 prefs.st_burst_windowlen = prefs.st_burst_resolution*ST_MAX_BURSTBUCKETS;
2350 /* Ensure there is at least one file count */
2351 if (prefs.gui_recent_files_count_max == 0)
2352 prefs.gui_recent_files_count_max = 10;
2354 /* Ensure there is at least one display filter entry */
2355 if (prefs.gui_recent_df_entries_max == 0)
2356 prefs.gui_recent_df_entries_max = 10;
2360 gui_layout_callback(void)
2362 if (prefs.gui_layout_type == layout_unused ||
2363 prefs.gui_layout_type >= layout_type_max) {
2364 /* XXX - report an error? It's not a syntax error - we'd need to
2365 add a way of reporting a *semantic* error. */
2366 prefs.gui_layout_type = layout_type_5;
2370 /******************************************************
2371 * All custom preference function callbacks
2372 ******************************************************/
2373 static void custom_pref_no_cb(pref_t* pref _U_) {}
2377 * Console log level custom preference functions
2380 console_log_level_reset_cb(pref_t* pref)
2382 *pref->varp.uint = pref->default_val.uint;
2385 static prefs_set_pref_e
2386 console_log_level_set_cb(pref_t* pref, const gchar* value, unsigned int* changed_flags)
2390 if (!ws_strtou32(value, NULL, &uval))
2391 return PREFS_SET_SYNTAX_ERR; /* number was bad */
2393 if (*pref->varp.uint != uval) {
2394 *changed_flags = prefs_get_effect_flags(pref);
2395 *pref->varp.uint = uval;
2398 if (*pref->varp.uint & (G_LOG_LEVEL_INFO|G_LOG_LEVEL_DEBUG)) {
2400 * GLib >= 2.32 drops INFO and DEBUG messages by default. Tell
2401 * it not to do that.
2403 g_setenv("G_MESSAGES_DEBUG", "all", TRUE);
2406 return PREFS_SET_OK;
2409 static const char * console_log_level_type_name_cb(void) {
2413 static char * console_log_level_type_description_cb(void) {
2414 return g_strdup_printf(
2415 "Console log level (for debugging)\n"
2416 "A bitmask of log levels:\n"
2425 static gboolean console_log_level_is_default_cb(pref_t* pref) {
2426 return *pref->varp.uint == pref->default_val.uint;
2429 static char * console_log_level_to_str_cb(pref_t* pref, gboolean default_val) {
2430 return g_strdup_printf("%u", default_val ? pref->default_val.uint : *pref->varp.uint);
2434 * Column preference functions
2436 #define PRS_COL_HIDDEN "column.hidden"
2437 #define PRS_COL_FMT "column.format"
2438 #define PRS_COL_NUM "column.number"
2439 static module_t *gui_column_module = NULL;
2441 static prefs_set_pref_e
2442 column_hidden_set_cb(pref_t* pref, const gchar* value, unsigned int* changed_flags)
2446 pref_t *format_pref;
2448 (*changed_flags) |= prefs_set_string_value(pref, value, pref_current);
2451 * Set the "visible" flag for the existing columns; we need to
2452 * do this if we set PRS_COL_HIDDEN but don't set PRS_COL_FMT
2453 * after setting it (which might be the case if, for example, we
2454 * set PRS_COL_HIDDEN on the command line).
2456 format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT);
2457 for (clp = *format_pref->varp.list; clp != NULL; clp = clp->next) {
2458 cfmt = (fmt_data *)clp->data;
2459 cfmt->visible = prefs_is_column_visible(*pref->varp.string, cfmt);
2462 return PREFS_SET_OK;
2466 column_hidden_type_name_cb(void)
2468 return "Packet list hidden columns";
2472 column_hidden_type_description_cb(void)
2474 return g_strdup("List all columns to hide in the packet list.");
2478 column_hidden_to_str_cb(pref_t* pref, gboolean default_val)
2480 GString *cols_hidden = g_string_new ("");
2483 pref_t *format_pref;
2486 return g_strdup(pref->default_val.string);
2488 format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT);
2489 clp = (format_pref) ? *format_pref->varp.list : NULL;
2492 cfmt = (fmt_data *) clp->data;
2493 if ((cfmt->fmt == COL_CUSTOM) && (cfmt->custom_fields)) {
2494 prefs_fmt = g_strdup_printf("%s:%s:%d:%c",
2495 col_format_to_string(cfmt->fmt),
2496 cfmt->custom_fields,
2497 cfmt->custom_occurrence,
2498 cfmt->resolved ? 'R' : 'U');
2500 prefs_fmt = g_strdup(col_format_to_string(cfmt->fmt));
2502 if (!cfmt->visible) {
2503 if (cols_hidden->len)
2504 g_string_append (cols_hidden, ",");
2505 g_string_append (cols_hidden, prefs_fmt);
2511 return g_string_free (cols_hidden, FALSE);
2515 column_hidden_is_default_cb(pref_t* pref)
2517 char *cur_hidden_str = column_hidden_to_str_cb(pref, FALSE);
2518 gboolean is_default = g_strcmp0(cur_hidden_str, pref->default_val.string) == 0;
2520 g_free(cur_hidden_str);
2525 /* Number of columns "preference". This is only used internally and is not written to the
2529 column_num_reset_cb(pref_t* pref)
2531 *pref->varp.uint = pref->default_val.uint;
2534 static prefs_set_pref_e
2535 column_num_set_cb(pref_t* pref _U_, const gchar* value _U_, unsigned int* changed_flags _U_)
2537 /* Don't write this to the preferences file */
2538 return PREFS_SET_OK;
2542 column_num_type_name_cb(void)
2548 column_num_type_description_cb(void)
2550 return g_strdup("");
2554 column_num_is_default_cb(pref_t* pref _U_)
2560 column_num_to_str_cb(pref_t* pref _U_, gboolean default_val _U_)
2562 return g_strdup("");
2566 * Column format custom preference functions
2569 column_format_init_cb(pref_t* pref, GList** value)
2571 fmt_data *src_cfmt, *dest_cfmt;
2574 pref->varp.list = value;
2576 pref->default_val.list = NULL;
2577 for (entry = *pref->varp.list; entry != NULL; entry = g_list_next(entry)) {
2578 src_cfmt = (fmt_data *)entry->data;
2579 dest_cfmt = g_new(fmt_data,1);
2580 dest_cfmt->title = g_strdup(src_cfmt->title);
2581 dest_cfmt->fmt = src_cfmt->fmt;
2582 if (src_cfmt->custom_fields) {
2583 dest_cfmt->custom_fields = g_strdup(src_cfmt->custom_fields);
2584 dest_cfmt->custom_occurrence = src_cfmt->custom_occurrence;
2586 dest_cfmt->custom_fields = NULL;
2587 dest_cfmt->custom_occurrence = 0;
2589 dest_cfmt->visible = src_cfmt->visible;
2590 dest_cfmt->resolved = src_cfmt->resolved;
2591 pref->default_val.list = g_list_append(pref->default_val.list, dest_cfmt);
2596 column_format_free_cb(pref_t* pref)
2598 free_col_info(*pref->varp.list);
2599 free_col_info(pref->default_val.list);
2603 column_format_reset_cb(pref_t* pref)
2605 fmt_data *src_cfmt, *dest_cfmt;
2607 pref_t *col_num_pref;
2609 free_col_info(*pref->varp.list);
2610 *pref->varp.list = NULL;
2612 for (entry = pref->default_val.list; entry != NULL; entry = g_list_next(entry)) {
2613 src_cfmt = (fmt_data *)entry->data;
2614 dest_cfmt = g_new(fmt_data,1);
2615 dest_cfmt->title = g_strdup(src_cfmt->title);
2616 dest_cfmt->fmt = src_cfmt->fmt;
2617 if (src_cfmt->custom_fields) {
2618 dest_cfmt->custom_fields = g_strdup(src_cfmt->custom_fields);
2619 dest_cfmt->custom_occurrence = src_cfmt->custom_occurrence;
2621 dest_cfmt->custom_fields = NULL;
2622 dest_cfmt->custom_occurrence = 0;
2624 dest_cfmt->visible = src_cfmt->visible;
2625 dest_cfmt->resolved = src_cfmt->resolved;
2626 *pref->varp.list = g_list_append(*pref->varp.list, dest_cfmt);
2629 col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM);
2630 g_assert(col_num_pref != NULL); /* Should never happen */
2631 column_num_reset_cb(col_num_pref);
2634 static prefs_set_pref_e
2635 column_format_set_cb(pref_t* pref, const gchar* value, unsigned int* changed_flags _U_)
2637 GList *col_l, *col_l_elt;
2640 pref_t *hidden_pref, *col_num_pref;
2642 col_l = prefs_get_string_list(value);
2644 return PREFS_SET_SYNTAX_ERR;
2645 if ((g_list_length(col_l) % 2) != 0) {
2646 /* A title didn't have a matching format. */
2647 prefs_clear_string_list(col_l);
2648 return PREFS_SET_SYNTAX_ERR;
2650 /* Check to make sure all column formats are valid. */
2651 col_l_elt = g_list_first(col_l);
2653 fmt_data cfmt_check;
2655 /* Go past the title. */
2656 col_l_elt = col_l_elt->next;
2658 /* Parse the format to see if it's valid. */
2659 if (!parse_column_format(&cfmt_check, (char *)col_l_elt->data)) {
2660 /* It's not a valid column format. */
2661 prefs_clear_string_list(col_l);
2662 return PREFS_SET_SYNTAX_ERR;
2664 if (cfmt_check.fmt != COL_CUSTOM) {
2665 /* Some predefined columns have been migrated to use custom columns.
2666 * We'll convert these silently here */
2667 try_convert_to_custom_column(&col_l_elt->data);
2669 /* We don't need the custom column field on this pass. */
2670 g_free(cfmt_check.custom_fields);
2673 /* Go past the format. */
2674 col_l_elt = col_l_elt->next;
2677 /* They're all valid; process them. */
2678 free_col_info(*pref->varp.list);
2679 *pref->varp.list = NULL;
2680 hidden_pref = prefs_find_preference(gui_column_module, PRS_COL_HIDDEN);
2681 g_assert(hidden_pref != NULL); /* Should never happen */
2682 col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM);
2683 g_assert(col_num_pref != NULL); /* Should never happen */
2684 llen = g_list_length(col_l);
2685 *col_num_pref->varp.uint = llen / 2;
2686 col_l_elt = g_list_first(col_l);
2688 cfmt = g_new(fmt_data,1);
2689 cfmt->title = g_strdup((gchar *)col_l_elt->data);
2690 col_l_elt = col_l_elt->next;
2691 parse_column_format(cfmt, (char *)col_l_elt->data);
2692 cfmt->visible = prefs_is_column_visible(*hidden_pref->varp.string, cfmt);
2693 col_l_elt = col_l_elt->next;
2694 *pref->varp.list = g_list_append(*pref->varp.list, cfmt);
2697 prefs_clear_string_list(col_l);
2698 free_string_like_preference(hidden_pref);
2699 return PREFS_SET_OK;
2704 column_format_type_name_cb(void)
2706 return "Packet list column format";
2710 column_format_type_description_cb(void)
2712 return g_strdup("Each pair of strings consists of a column title and its format");
2716 column_format_is_default_cb(pref_t* pref)
2718 GList *clp = *pref->varp.list,
2719 *pref_col = g_list_first(clp),
2720 *def_col = g_list_first(pref->default_val.list);
2721 fmt_data *cfmt, *def_cfmt;
2722 gboolean is_default = TRUE;
2723 pref_t *col_num_pref;
2725 /* See if the column data has changed from the default */
2726 col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM);
2727 if (col_num_pref && *col_num_pref->varp.uint != col_num_pref->default_val.uint) {
2730 while (pref_col && def_col) {
2731 cfmt = (fmt_data *) pref_col->data;
2732 def_cfmt = (fmt_data *) def_col->data;
2733 if ((g_strcmp0(cfmt->title, def_cfmt->title) != 0) ||
2734 (cfmt->fmt != def_cfmt->fmt) ||
2735 (((cfmt->fmt == COL_CUSTOM) && (cfmt->custom_fields)) &&
2736 ((g_strcmp0(cfmt->custom_fields, def_cfmt->custom_fields) != 0) ||
2737 (cfmt->resolved != def_cfmt->resolved)))) {
2742 pref_col = pref_col->next;
2743 def_col = def_col->next;
2751 column_format_to_str_cb(pref_t* pref, gboolean default_val)
2753 GList *pref_l = default_val ? pref->default_val.list : *pref->varp.list;
2754 GList *clp = g_list_first(pref_l);
2758 char *column_format_str;
2762 cfmt = (fmt_data *) clp->data;
2763 col_l = g_list_append(col_l, g_strdup(cfmt->title));
2764 if ((cfmt->fmt == COL_CUSTOM) && (cfmt->custom_fields)) {
2765 prefs_fmt = g_strdup_printf("%s:%s:%d:%c",
2766 col_format_to_string(cfmt->fmt),
2767 cfmt->custom_fields,
2768 cfmt->custom_occurrence,
2769 cfmt->resolved ? 'R' : 'U');
2771 prefs_fmt = g_strdup(col_format_to_string(cfmt->fmt));
2773 col_l = g_list_append(col_l, prefs_fmt);
2777 column_format_str = join_string_list(col_l);
2778 prefs_clear_string_list(col_l);
2779 return column_format_str;
2783 /****** Capture column custom preference functions ******/
2785 /* This routine is only called when Wireshark is started, NOT when another profile is selected.
2786 Copy the pref->capture_columns list (just loaded with the capture_cols[] struct values)
2787 to prefs->default_val.list.
2790 capture_column_init_cb(pref_t* pref, GList** capture_cols_values)
2792 GList *ccv_list = *capture_cols_values,
2797 dlist = g_list_append(dlist, g_strdup((gchar *)ccv_list->data));
2798 ccv_list = ccv_list->next;
2801 pref->default_val.list = dlist;
2802 pref->varp.list = &prefs.capture_columns;
2803 pref->stashed_val.boolval = FALSE;
2806 /* Free the prefs->capture_columns list strings and remove the list entries.
2807 Note that since pref->varp.list points to &prefs.capture_columns, it is
2811 capture_column_free_cb(pref_t* pref)
2813 prefs_clear_string_list(prefs.capture_columns);
2814 prefs.capture_columns = NULL;
2816 if (pref->stashed_val.boolval == TRUE) {
2817 prefs_clear_string_list(pref->default_val.list);
2818 pref->default_val.list = NULL;
2822 /* Copy pref->default_val.list to *pref->varp.list.
2825 capture_column_reset_cb(pref_t* pref)
2827 GList *vlist = NULL, *dlist;
2829 /* Free the column name strings and remove the links from *pref->varp.list */
2830 prefs_clear_string_list(*pref->varp.list);
2832 for (dlist = pref->default_val.list; dlist != NULL; dlist = g_list_next(dlist)) {
2833 vlist = g_list_append(vlist, g_strdup((gchar *)dlist->data));
2835 *pref->varp.list = vlist;
2838 static prefs_set_pref_e
2839 capture_column_set_cb(pref_t* pref, const gchar* value, unsigned int* changed_flags _U_)
2841 GList *col_l = prefs_get_string_list(value);
2847 return PREFS_SET_SYNTAX_ERR;
2849 capture_column_free_cb(pref);
2851 /* If value (the list of capture.columns read from preferences) is empty, set capture.columns
2852 to the full list of valid capture column names. */
2853 col_l_elt = g_list_first(col_l);
2854 if (!(*(gchar *)col_l_elt->data)) {
2855 for (i = 0; i < num_capture_cols; i++) {
2856 col_name = g_strdup(capture_cols[i]);
2857 prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
2861 /* Verify that all the column names are valid. If not, use the entire list of valid columns.
2864 gboolean found_match = FALSE;
2865 col_name = (gchar *)col_l_elt->data;
2867 for (i = 0; i < num_capture_cols; i++) {
2868 if (strcmp(col_name, capture_cols[i])==0) {
2874 /* One or more cols are invalid so use the entire list of valid cols. */
2875 for (i = 0; i < num_capture_cols; i++) {
2876 col_name = g_strdup(capture_cols[i]);
2877 prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
2879 pref->varp.list = &prefs.capture_columns;
2880 prefs_clear_string_list(col_l);
2881 return PREFS_SET_SYNTAX_ERR;
2883 col_l_elt = col_l_elt->next;
2886 col_l_elt = g_list_first(col_l);
2888 col_name = (gchar *)col_l_elt->data;
2889 prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
2890 col_l_elt = col_l_elt->next;
2892 pref->varp.list = &prefs.capture_columns;
2894 return PREFS_SET_OK;
2899 capture_column_type_name_cb(void)
2901 return "Column list";
2905 capture_column_type_description_cb(void)
2908 "List of columns to be displayed in the capture options dialog.\n"
2909 CAPTURE_COL_TYPE_DESCRIPTION);
2913 capture_column_is_default_cb(pref_t* pref)
2915 GList *pref_col = g_list_first(prefs.capture_columns),
2916 *def_col = g_list_first(pref->default_val.list);
2917 gboolean is_default = TRUE;
2919 /* See if the column data has changed from the default */
2920 while (pref_col && def_col) {
2921 if (strcmp((gchar *)pref_col->data, (gchar *)def_col->data) != 0) {
2925 pref_col = pref_col->next;
2926 def_col = def_col->next;
2929 /* Ensure the same column count */
2930 if (((pref_col == NULL) && (def_col != NULL)) ||
2931 ((pref_col != NULL) && (def_col == NULL)))
2938 capture_column_to_str_cb(pref_t* pref, gboolean default_val)
2941 GList *pref_l = default_val ? pref->default_val.list : prefs.capture_columns;
2942 GList *clp = g_list_first(pref_l);
2943 GList *col_l = NULL;
2945 char *capture_column_str;
2948 col = (gchar *) clp->data;
2949 col_l = g_list_append(col_l, g_strdup(col));
2953 capture_column_str = join_string_list(col_l);
2954 prefs_clear_string_list(col_l);
2955 return capture_column_str;
2958 static prefs_set_pref_e
2959 colorized_frame_set_cb(pref_t* pref, const gchar* value, unsigned int* changed_flags)
2961 (*changed_flags) |= prefs_set_string_value(pref, value, pref_current);
2962 return PREFS_SET_OK;
2966 colorized_frame_type_name_cb(void)
2968 /* Don't write the colors of the 10 easy-access-colorfilters to the preferences
2969 * file until the colors can be changed in the GUI. Currently this is not really
2970 * possible since the STOCK-icons for these colors are hardcoded.
2972 * XXX Find a way to change the colors of the STOCK-icons on the fly and then
2973 * add these 10 colors to the list of colors that can be changed through
2981 colorized_frame_type_description_cb(void)
2983 return g_strdup("");
2987 colorized_frame_is_default_cb(pref_t* pref _U_)
2993 colorized_frame_to_str_cb(pref_t* pref _U_, gboolean default_val _U_)
2995 return g_strdup("");
2999 * Register all non-dissector modules' preferences.
3001 static module_t *gui_module = NULL;
3002 static module_t *gui_color_module = NULL;
3003 static module_t *nameres_module = NULL;
3006 prefs_register_modules(void)
3008 module_t *printing, *capture_module, *console_module,
3009 *gui_layout_module, *gui_font_module;
3010 module_t *extcap_module;
3011 unsigned int layout_gui_flags;
3012 struct pref_custom_cbs custom_cbs;
3014 if (protocols_module != NULL) {
3015 /* Already setup preferences */
3020 * These are "simple" GUI preferences that can be read/written using the
3021 * preference module API. These preferences still use their own
3022 * configuration screens for access, but this cuts down on the
3023 * preference "string compare list" in set_pref()
3025 extcap_module = prefs_register_module(NULL, "extcap", "Extcap Utilities",
3026 "Extcap Utilities", NULL, FALSE);
3028 /* Setting default value to true */
3029 prefs.extcap_save_on_start = TRUE;
3030 prefs_register_bool_preference(extcap_module, "gui_save_on_start",
3031 "Save arguments on start of capture",
3032 "Save arguments on start of capture",
3033 &prefs.extcap_save_on_start);
3036 * These are "simple" GUI preferences that can be read/written using the
3037 * preference module API. These preferences still use their own
3038 * configuration screens for access, but this cuts down on the
3039 * preference "string compare list" in set_pref()
3041 gui_module = prefs_register_module(NULL, "gui", "User Interface",
3042 "User Interface", &gui_callback, FALSE);
3044 /* gui.console_open is placed first in the list so that any problems encountered
3045 * in the following prefs can be displayed in the console window.
3047 prefs_register_enum_preference(gui_module, "console_open",
3048 "Open a console window",
3049 "Open a console window (Windows only)",
3050 (gint*)(void*)(&prefs.gui_console_open), gui_console_open_type, FALSE);
3052 prefs_register_obsolete_preference(gui_module, "scrollbar_on_right");
3053 prefs_register_obsolete_preference(gui_module, "packet_list_sel_browse");
3054 prefs_register_obsolete_preference(gui_module, "protocol_tree_sel_browse");
3055 prefs_register_obsolete_preference(gui_module, "tree_view_altern_colors");
3056 prefs_register_obsolete_preference(gui_module, "expert_composite_eyecandy");
3057 prefs_register_obsolete_preference(gui_module, "filter_toolbar_show_in_statusbar");
3059 prefs_register_bool_preference(gui_module, "restore_filter_after_following_stream",
3060 "Restore current display filter after following a stream",
3061 "Restore current display filter after following a stream?",
3062 &prefs.restore_filter_after_following_stream);
3064 prefs_register_obsolete_preference(gui_module, "protocol_tree_line_style");
3066 prefs_register_obsolete_preference(gui_module, "protocol_tree_expander_style");
3068 prefs_register_obsolete_preference(gui_module, "hex_dump_highlight_style");
3070 gui_column_module = prefs_register_subtree(gui_module, "Columns", "Columns", NULL);
3071 /* For reading older preference files with "column." preferences */
3072 prefs_register_module_alias("column", gui_column_module);
3074 custom_cbs.free_cb = free_string_like_preference;
3075 custom_cbs.reset_cb = reset_string_like_preference;
3076 custom_cbs.set_cb = column_hidden_set_cb;
3077 custom_cbs.type_name_cb = column_hidden_type_name_cb;
3078 custom_cbs.type_description_cb = column_hidden_type_description_cb;
3079 custom_cbs.is_default_cb = column_hidden_is_default_cb;
3080 custom_cbs.to_str_cb = column_hidden_to_str_cb;
3081 register_string_like_preference(gui_column_module, PRS_COL_HIDDEN, "Packet list hidden columns",
3082 "List all columns to hide in the packet list",
3083 &cols_hidden_list, PREF_CUSTOM, &custom_cbs, FALSE);
3085 custom_cbs.free_cb = column_format_free_cb;
3086 custom_cbs.reset_cb = column_format_reset_cb;
3087 custom_cbs.set_cb = column_format_set_cb;
3088 custom_cbs.type_name_cb = column_format_type_name_cb;
3089 custom_cbs.type_description_cb = column_format_type_description_cb;
3090 custom_cbs.is_default_cb = column_format_is_default_cb;
3091 custom_cbs.to_str_cb = column_format_to_str_cb;
3093 prefs_register_list_custom_preference(gui_column_module, PRS_COL_FMT, "Packet list column format",
3094 "Each pair of strings consists of a column title and its format", &custom_cbs,
3095 column_format_init_cb, &prefs.col_list);
3097 /* Number of columns. This is only used internally and is not written to the
3100 custom_cbs.free_cb = custom_pref_no_cb;
3101 custom_cbs.reset_cb = column_num_reset_cb;
3102 custom_cbs.set_cb = column_num_set_cb;
3103 custom_cbs.type_name_cb = column_num_type_name_cb;
3104 custom_cbs.type_description_cb = column_num_type_description_cb;
3105 custom_cbs.is_default_cb = column_num_is_default_cb;
3106 custom_cbs.to_str_cb = column_num_to_str_cb;
3107 prefs_register_uint_custom_preference(gui_column_module, PRS_COL_NUM, "Number of columns",
3108 "Number of columns in col_list", &custom_cbs, &prefs.num_cols);
3110 /* User Interface : Font */
3111 gui_font_module = prefs_register_subtree(gui_module, "Font", "Font", NULL);
3113 prefs_register_obsolete_preference(gui_font_module, "font_name");
3115 prefs_register_obsolete_preference(gui_font_module, "gtk2.font_name");
3117 register_string_like_preference(gui_font_module, "qt.font_name", "Font name",
3118 "Font name for packet list, protocol tree, and hex dump panes. (Qt)",
3119 &prefs.gui_qt_font_name, PREF_STRING, NULL, TRUE);
3121 /* User Interface : Colors */
3122 gui_color_module = prefs_register_subtree(gui_module, "Colors", "Colors", NULL);
3124 prefs_register_color_preference(gui_color_module, "active_frame.fg", "Foregound color for an active selected item",
3125 "Foregound color for an active selected item", &prefs.gui_active_fg);
3127 prefs_register_color_preference(gui_color_module, "active_frame.bg", "Backgound color for an active selected item",
3128 "Backgound color for an active selected item", &prefs.gui_active_bg);
3130 prefs_register_enum_preference(gui_color_module, "active_frame.style", "Color style for an active selected item",
3131 "Color style for an active selected item", &prefs.gui_active_style, gui_selection_style, FALSE);
3133 prefs_register_color_preference(gui_color_module, "inactive_frame.fg", "Foregound color for an inactive selected item",
3134 "Foregound color for an inactive selected item", &prefs.gui_inactive_fg);
3136 prefs_register_color_preference(gui_color_module, "inactive_frame.bg", "Backgound color for an inactive selected item",
3137 "Backgound color for an inactive selected item", &prefs.gui_inactive_bg);
3139 prefs_register_enum_preference(gui_color_module, "inactive_frame.style", "Color style for an inactive selected item",
3140 "Color style for an inactive selected item", &prefs.gui_inactive_style, gui_selection_style, FALSE);
3142 prefs_register_color_preference(gui_color_module, "marked_frame.fg", "Color preferences for a marked frame",
3143 "Color preferences for a marked frame", &prefs.gui_marked_fg);
3145 prefs_register_color_preference(gui_color_module, "marked_frame.bg", "Color preferences for a marked frame",
3146 "Color preferences for a marked frame", &prefs.gui_marked_bg);
3148 prefs_register_color_preference(gui_color_module, "ignored_frame.fg", "Color preferences for a ignored frame",
3149 "Color preferences for a ignored frame", &prefs.gui_ignored_fg);
3151 prefs_register_color_preference(gui_color_module, "ignored_frame.bg", "Color preferences for a ignored frame",
3152 "Color preferences for a ignored frame", &prefs.gui_ignored_bg);
3154 prefs_register_color_preference(gui_color_module, "stream.client.fg", "TCP stream window color preference",
3155 "TCP stream window color preference", &prefs.st_client_fg);
3157 prefs_register_color_preference(gui_color_module, "stream.client.bg", "TCP stream window color preference",
3158 "TCP stream window color preference", &prefs.st_client_bg);
3160 prefs_register_color_preference(gui_color_module, "stream.server.fg", "TCP stream window color preference",
3161 "TCP stream window color preference", &prefs.st_server_fg);
3163 prefs_register_color_preference(gui_color_module, "stream.server.bg", "TCP stream window color preference",
3164 "TCP stream window color preference", &prefs.st_server_bg);
3166 custom_cbs.free_cb = free_string_like_preference;
3167 custom_cbs.reset_cb = reset_string_like_preference;
3168 custom_cbs.set_cb = colorized_frame_set_cb;
3169 custom_cbs.type_name_cb = colorized_frame_type_name_cb;
3170 custom_cbs.type_description_cb = colorized_frame_type_description_cb;
3171 custom_cbs.is_default_cb = colorized_frame_is_default_cb;
3172 custom_cbs.to_str_cb = colorized_frame_to_str_cb;
3173 register_string_like_preference(gui_column_module, "colorized_frame.fg", "Colorized Foreground",
3174 "Filter Colorized Foreground",
3175 &prefs.gui_colorized_fg, PREF_CUSTOM, &custom_cbs, TRUE);
3177 custom_cbs.free_cb = free_string_like_preference;
3178 custom_cbs.reset_cb = reset_string_like_preference;
3179 custom_cbs.set_cb = colorized_frame_set_cb;
3180 custom_cbs.type_name_cb = colorized_frame_type_name_cb;
3181 custom_cbs.type_description_cb = colorized_frame_type_description_cb;
3182 custom_cbs.is_default_cb = colorized_frame_is_default_cb;
3183 custom_cbs.to_str_cb = colorized_frame_to_str_cb;
3184 register_string_like_preference(gui_column_module, "colorized_frame.bg", "Colorized Background",
3185 "Filter Colorized Background",
3186 &prefs.gui_colorized_bg, PREF_CUSTOM, &custom_cbs, TRUE);
3188 prefs_register_color_preference(gui_color_module, "color_filter_bg.valid", "Valid color filter background",
3189 "Valid color filter background", &prefs.gui_text_valid);
3191 prefs_register_color_preference(gui_color_module, "color_filter_bg.invalid", "Invalid color filter background",
3192 "Invalid color filter background", &prefs.gui_text_invalid);
3194 prefs_register_color_preference(gui_color_module, "color_filter_bg.deprecated", "Deprecated color filter background",
3195 "Deprecated color filter background", &prefs.gui_text_deprecated);
3197 prefs_register_enum_preference(gui_module, "fileopen.style",
3198 "Where to start the File Open dialog box",
3199 "Where to start the File Open dialog box",
3200 &prefs.gui_fileopen_style, gui_fileopen_style, FALSE);
3202 prefs_register_uint_preference(gui_module, "recent_files_count.max",
3203 "The max. number of items in the open recent files list",
3204 "The max. number of items in the open recent files list",
3206 &prefs.gui_recent_files_count_max);
3208 prefs_register_uint_preference(gui_module, "recent_display_filter_entries.max",
3209 "The max. number of entries in the display filter list",
3210 "The max. number of entries in the display filter list",
3212 &prefs.gui_recent_df_entries_max);
3214 register_string_like_preference(gui_module, "fileopen.dir", "Start Directory",
3215 "Directory to start in when opening File Open dialog.",
3216 &prefs.gui_fileopen_dir, PREF_DIRNAME, NULL, TRUE);
3218 prefs_register_obsolete_preference(gui_module, "fileopen.remembered_dir");
3220 prefs_register_uint_preference(gui_module, "fileopen.preview",
3221 "The preview timeout in the File Open dialog",
3222 "The preview timeout in the File Open dialog",
3224 &prefs.gui_fileopen_preview);
3226 prefs_register_bool_preference(gui_module, "ask_unsaved",
3227 "Ask to save unsaved capture files",
3228 "Ask to save unsaved capture files?",
3229 &prefs.gui_ask_unsaved);
3231 prefs_register_bool_preference(gui_module, "autocomplete_filter",
3232 "Display autocompletion for filter text",
3233 "Display an autocomplete suggestion for display and capture filter controls",
3234 &prefs.gui_autocomplete_filter);
3236 prefs_register_bool_preference(gui_module, "find_wrap",
3237 "Wrap to beginning/end of file during search",
3238 "Wrap to beginning/end of file during search?",
3239 &prefs.gui_find_wrap);
3241 prefs_register_obsolete_preference(gui_module, "use_pref_save");
3243 prefs_register_bool_preference(gui_module, "geometry.save.position",
3244 "Save window position at exit",
3245 "Save window position at exit?",
3246 &prefs.gui_geometry_save_position);
3248 prefs_register_bool_preference(gui_module, "geometry.save.size",
3249 "Save window size at exit",
3250 "Save window size at exit?",
3251 &prefs.gui_geometry_save_size);
3253 prefs_register_bool_preference(gui_module, "geometry.save.maximized",
3254 "Save window maximized state at exit",
3255 "Save window maximized state at exit?",
3256 &prefs.gui_geometry_save_maximized);
3258 prefs_register_obsolete_preference(gui_module, "macosx_style");
3260 prefs_register_obsolete_preference(gui_module, "geometry.main.x");
3261 prefs_register_obsolete_preference(gui_module, "geometry.main.y");
3262 prefs_register_obsolete_preference(gui_module, "geometry.main.width");
3263 prefs_register_obsolete_preference(gui_module, "geometry.main.height");
3264 prefs_register_obsolete_preference(gui_module, "toolbar_main_show");
3266 prefs_register_enum_preference(gui_module, "toolbar_main_style",
3267 "Main Toolbar style",
3268 "Main Toolbar style",
3269 &prefs.gui_toolbar_main_style, gui_toolbar_style, FALSE);
3271 prefs_register_obsolete_preference(gui_module, "toolbar_filter_style");
3272 prefs_register_obsolete_preference(gui_module, "webbrowser");
3274 prefs_register_bool_preference(gui_module, "update.enabled",
3275 "Check for updates",
3276 "Check for updates (Windows only)",
3277 &prefs.gui_update_enabled);
3279 prefs_register_enum_preference(gui_module, "update.channel",
3281 "The type of update to fetch. You should probably leave this set to UPDATE_CHANNEL_STABLE.",
3282 (gint*)(void*)(&prefs.gui_update_channel), gui_update_channel, FALSE);
3284 prefs_register_uint_preference(gui_module, "update.interval",
3285 "How often to check for software updates",
3286 "How often to check for software updates in seconds",
3288 &prefs.gui_update_interval);
3290 register_string_like_preference(gui_module, "window_title", "Custom window title",
3291 "Custom window title to be appended to the existing title\n"
3292 "%F = file path of the capture file\n"
3293 "%P = profile name\n"
3294 "%S = a conditional separator (\" - \") that only shows when surrounded by variables with values or static text\n"
3295 "%V = version info",
3296 &prefs.gui_window_title, PREF_STRING, NULL, TRUE);
3298 register_string_like_preference(gui_module, "prepend_window_title", "Custom window title prefix",
3299 "Custom window title to be prepended to the existing title\n"
3300 "%F = file path of the capture file\n"
3301 "%P = profile name\n"
3302 "%S = a conditional separator (\" - \") that only shows when surrounded by variables with values or static text\n"
3303 "%V = version info",
3304 &prefs.gui_prepend_window_title, PREF_STRING, NULL, TRUE);
3306 register_string_like_preference(gui_module, "start_title", "Custom start page title",
3307 "Custom start page title",
3308 &prefs.gui_start_title, PREF_STRING, NULL, TRUE);
3310 prefs_register_enum_preference(gui_module, "version_placement",
3311 "Show version in the start page and/or main screen's title bar",
3312 "Show version in the start page and/or main screen's title bar",
3313 (gint*)(void*)(&prefs.gui_version_placement), gui_version_placement_type, FALSE);
3315 prefs_register_obsolete_preference(gui_module, "auto_scroll_on_expand");
3316 prefs_register_obsolete_preference(gui_module, "auto_scroll_percentage");
3318 /* User Interface : Layout */
3319 gui_layout_module = prefs_register_subtree(gui_module, "Layout", "Layout", gui_layout_callback);
3320 /* Adjust the preference effects of layout GUI for better handling of preferences at Wireshark (GUI) level */
3321 layout_gui_flags = prefs_get_module_effect_flags(gui_layout_module);
3322 layout_gui_flags |= PREF_EFFECT_GUI_LAYOUT;
3323 layout_gui_flags &= (~PREF_EFFECT_DISSECTION);
3325 prefs_register_uint_preference(gui_layout_module, "layout_type",
3327 "Layout type (1-6)",
3329 (guint*)(void*)(&prefs.gui_layout_type));
3330 prefs_set_effect_flags_by_name(gui_layout_module, "layout_type", layout_gui_flags);
3332 prefs_register_enum_preference(gui_layout_module, "layout_content_1",
3333 "Layout content of the pane 1",
3334 "Layout content of the pane 1",
3335 (gint*)(void*)(&prefs.gui_layout_content_1), gui_layout_content, FALSE);
3336 prefs_set_effect_flags_by_name(gui_layout_module, "layout_content_1", layout_gui_flags);
3338 prefs_register_enum_preference(gui_layout_module, "layout_content_2",
3339 "Layout content of the pane 2",
3340 "Layout content of the pane 2",
3341 (gint*)(void*)(&prefs.gui_layout_content_2), gui_layout_content, FALSE);
3342 prefs_set_effect_flags_by_name(gui_layout_module, "layout_content_2", layout_gui_flags);
3344 prefs_register_enum_preference(gui_layout_module, "layout_content_3",
3345 "Layout content of the pane 3",
3346 "Layout content of the pane 3",
3347 (gint*)(void*)(&prefs.gui_layout_content_3), gui_layout_content, FALSE);
3348 prefs_set_effect_flags_by_name(gui_layout_module, "layout_content_3", layout_gui_flags);
3350 prefs_register_bool_preference(gui_layout_module, "packet_list_separator.enabled",
3351 "Enable Packet List Separator",
3352 "Enable Packet List Separator",
3353 &prefs.gui_qt_packet_list_separator);
3355 prefs_register_bool_preference(gui_layout_module, "show_selected_packet.enabled",
3356 "Show selected packet in the Status Bar",
3357 "Show selected packet in the Status Bar",
3358 &prefs.gui_qt_show_selected_packet);
3360 prefs_register_bool_preference(gui_layout_module, "show_file_load_time.enabled",
3361 "Show file load time in the Status Bar",
3362 "Show file load time in the Status Bar",
3363 &prefs.gui_qt_show_file_load_time);
3365 prefs_register_bool_preference(gui_module, "packet_editor.enabled",
3366 "Enable Packet Editor",
3367 "Enable Packet Editor (Experimental)",
3368 &prefs.gui_packet_editor);
3370 prefs_register_enum_preference(gui_module, "packet_list_elide_mode",
3372 "The position of \"...\" in packet list text.",
3373 (gint*)(void*)(&prefs.gui_packet_list_elide_mode), gui_packet_list_elide_mode, FALSE);
3375 prefs_register_bool_preference(gui_layout_module, "packet_list_show_related",
3376 "Show Related Packets",
3377 "Show related packet indicators in the first column",
3378 &prefs.gui_packet_list_show_related);
3380 prefs_register_bool_preference(gui_layout_module, "packet_list_show_minimap",
3381 "Enable Intelligent Scroll Bar",
3382 "Show the intelligent scroll bar (a minimap of packet list colors in the scrollbar)",
3383 &prefs.gui_packet_list_show_minimap);
3386 prefs_register_bool_preference(gui_module, "interfaces_show_hidden",
3387 "Show hidden interfaces",
3388 "Show all interfaces, including interfaces marked as hidden",
3389 &prefs.gui_interfaces_show_hidden);
3391 prefs_register_bool_preference(gui_module, "interfaces_remote_display",
3392 "Show Remote interfaces",
3393 "Show remote interfaces in the interface selection",
3394 &prefs.gui_interfaces_remote_display);
3396 register_string_like_preference(gui_module, "interfaces_hidden_types", "Hide interface types in list",
3397 "Hide the given interface types in the startup list.\n"
3398 "A commma-separated string of interface type values (e.g. 5,9).\n"
3407 "8 = External Capture,\n"
3409 &prefs.gui_interfaces_hide_types, PREF_STRING, NULL, TRUE);
3412 * These are preferences that can be read/written using the
3413 * preference module API. These preferences still use their own
3414 * configuration screens for access, but this cuts down on the
3415 * preference "string compare list" in set_pref()
3417 console_module = prefs_register_module(NULL, "console", "Console",
3418 "Console logging and debugging output", NULL, FALSE);
3420 custom_cbs.free_cb = custom_pref_no_cb;
3421 custom_cbs.reset_cb = console_log_level_reset_cb;
3422 custom_cbs.set_cb = console_log_level_set_cb;
3423 custom_cbs.type_name_cb = console_log_level_type_name_cb;
3424 custom_cbs.type_description_cb = console_log_level_type_description_cb;
3425 custom_cbs.is_default_cb = console_log_level_is_default_cb;
3426 custom_cbs.to_str_cb = console_log_level_to_str_cb;
3427 prefs_register_uint_custom_preference(console_module, "log.level", "logging level",
3428 "A bitmask of GLib log levels", &custom_cbs, &prefs.console_log_level);
3430 prefs_register_bool_preference(console_module, "incomplete_dissectors_check_debug",
3431 "Print debug line for incomplete dissectors",
3432 "Look for dissectors that left some bytes undecoded (debug)",
3433 &prefs.incomplete_dissectors_check_debug);
3435 /* Display filter Expressions
3436 * This used to be an array of individual fields that has now been
3437 * converted to a UAT. Just make it part of the GUI category even
3438 * though the name of the preference will never be seen in preference
3441 filter_expression_register_uat(gui_module);
3444 * These are preferences that can be read/written using the
3445 * preference module API. These preferences still use their own
3446 * configuration screens for access, but this cuts down on the
3447 * preference "string compare list" in set_pref()
3449 capture_module = prefs_register_module(NULL, "capture", "Capture",
3450 "Capture preferences", NULL, FALSE);
3451 /* Capture preferences don't affect dissection */
3452 prefs_set_module_effect_flags(capture_module, PREF_EFFECT_CAPTURE);
3454 register_string_like_preference(capture_module, "device", "Default capture device",
3455 "Default capture device",
3456 &prefs.capture_device, PREF_STRING, NULL, FALSE);
3458 register_string_like_preference(capture_module, "devices_linktypes", "Interface link-layer header type",
3459 "Interface link-layer header types (Ex: en0(1),en1(143),...)",
3460 &prefs.capture_devices_linktypes, PREF_STRING, NULL, FALSE);
3462 register_string_like_preference(capture_module, "devices_descr", "Interface descriptions",
3463 "Interface descriptions (Ex: eth0(eth0 descr),eth1(eth1 descr),...)",
3464 &prefs.capture_devices_descr, PREF_STRING, NULL, FALSE);
3466 register_string_like_preference(capture_module, "devices_hide", "Hide interface",
3467 "Hide interface? (Ex: eth0,eth3,...)",
3468 &prefs.capture_devices_hide, PREF_STRING, NULL, FALSE);
3470 register_string_like_preference(capture_module, "devices_monitor_mode", "Capture in monitor mode",
3471 "By default, capture in monitor mode on interface? (Ex: eth0,eth3,...)",
3472 &prefs.capture_devices_monitor_mode, PREF_STRING, NULL, FALSE);
3474 register_string_like_preference(capture_module, "devices_buffersize", "Interface buffer size",
3475 "Interface buffer size (Ex: en0(1),en1(143),...)",
3476 &prefs.capture_devices_buffersize, PREF_STRING, NULL, FALSE);
3478 register_string_like_preference(capture_module, "devices_snaplen", "Interface snap length",
3479 "Interface snap length (Ex: en0(65535),en1(1430),...)",
3480 &prefs.capture_devices_snaplen, PREF_STRING, NULL, FALSE);
3482 register_string_like_preference(capture_module, "devices_pmode", "Interface promiscuous mode",
3483 "Interface promiscuous mode (Ex: en0(0),en1(1),...)",
3484 &prefs.capture_devices_pmode, PREF_STRING, NULL, FALSE);
3486 prefs_register_bool_preference(capture_module, "prom_mode", "Capture in promiscuous mode",
3487 "Capture in promiscuous mode?", &prefs.capture_prom_mode);
3489 register_string_like_preference(capture_module, "devices_filter", "Interface capture filter",
3490 "Interface capture filter (Ex: en0(tcp),en1(udp),...)",
3491 &prefs.capture_devices_filter, PREF_STRING, NULL, FALSE);
3493 prefs_register_bool_preference(capture_module, "pcap_ng", "Capture in pcapng format",
3494 "Capture in pcapng format?", &prefs.capture_pcap_ng);
3496 prefs_register_bool_preference(capture_module, "real_time_update", "Update packet list in real time during capture",
3497 "Update packet list in real time during capture?", &prefs.capture_real_time);
3499 prefs_register_bool_preference(capture_module, "no_interface_load", "Don't load interfaces on startup",
3500 "Don't automatically load capture interfaces on startup", &prefs.capture_no_interface_load);
3502 prefs_register_bool_preference(capture_module, "no_extcap", "Disable external capture interfaces",
3503 "Disable external capture modules (extcap)", &prefs.capture_no_extcap);
3505 /* We might want to make this a "recent" setting. */
3506 prefs_register_bool_preference(capture_module, "auto_scroll", "Scroll packet list during capture",
3507 "Scroll packet list during capture?", &prefs.capture_auto_scroll);
3509 prefs_register_bool_preference(capture_module, "show_info", "Show capture information dialog while capturing",
3510 "Show capture information dialog while capturing?", &prefs.capture_show_info);
3512 prefs_register_obsolete_preference(capture_module, "syntax_check_filter");
3514 custom_cbs.free_cb = capture_column_free_cb;
3515 custom_cbs.reset_cb = capture_column_reset_cb;
3516 custom_cbs.set_cb = capture_column_set_cb;
3517 custom_cbs.type_name_cb = capture_column_type_name_cb;
3518 custom_cbs.type_description_cb = capture_column_type_description_cb;
3519 custom_cbs.is_default_cb = capture_column_is_default_cb;
3520 custom_cbs.to_str_cb = capture_column_to_str_cb;
3521 prefs_register_list_custom_preference(capture_module, "columns", "Capture options dialog column list",
3522 "List of columns to be displayed", &custom_cbs, capture_column_init_cb, &prefs.capture_columns);
3524 /* Name Resolution */
3525 nameres_module = prefs_register_module(NULL, "nameres", "Name Resolution",
3526 "Name Resolution", NULL, TRUE);
3527 addr_resolve_pref_init(nameres_module);
3528 oid_pref_init(nameres_module);
3529 maxmind_db_pref_init(nameres_module);
3532 * None of these have any effect; we keep them as obsolete preferences
3533 * in order to avoid errors when reading older preference files.
3535 printing = prefs_register_module(NULL, "print", "Printing",
3536 "Printing", NULL, FALSE);
3537 prefs_register_obsolete_preference(printing, "format");
3538 prefs_register_obsolete_preference(printing, "command");
3539 prefs_register_obsolete_preference(printing, "file");
3542 codecs_module = prefs_register_module(NULL, "codecs", "Codecs",
3543 "Codecs", NULL, TRUE);
3546 stats_module = prefs_register_module(NULL, "statistics", "Statistics",
3547 "Statistics", &stats_callback, TRUE);
3549 prefs_register_uint_preference(stats_module, "update_interval",
3550 "Tap update interval in ms",
3551 "Determines time between tap updates",
3553 &prefs.tap_update_interval);
3555 prefs_register_obsolete_preference(stats_module, "rtp_player_max_visible");
3557 prefs_register_bool_preference(stats_module, "st_enable_burstinfo",
3558 "Enable the calculation of burst information",
3559 "If enabled burst rates will be calcuted for statistics that use the stats_tree system. "
3560 "Burst rates are calculated over a much shorter time interval than the rate column.",
3561 &prefs.st_enable_burstinfo);
3563 prefs_register_bool_preference(stats_module, "st_burst_showcount",
3564 "Show burst count for item rather than rate",
3565 "If selected the stats_tree statistics nodes will show the count of events "
3566 "within the burst window instead of a burst rate. Burst rate is calculated "
3567 "as number of events within burst window divided by the burst windown length.",
3568 &prefs.st_burst_showcount);
3570 prefs_register_uint_preference(stats_module, "st_burst_resolution",
3571 "Burst rate resolution (ms)",
3572 "Sets the duration of the time interval into which events are grouped when calculating "
3573 "the burst rate. Higher resolution (smaller number) increases processing overhead.",
3574 10,&prefs.st_burst_resolution);
3576 prefs_register_uint_preference(stats_module, "st_burst_windowlen",
3577 "Burst rate window size (ms)",
3578 "Sets the duration of the sliding window during which the burst rate is "
3579 "measured. Longer window relative to burst rate resolution increases "
3580 "processing overhead. Will be truncated to a multiple of burst resolution.",
3581 10,&prefs.st_burst_windowlen);
3583 prefs_register_enum_preference(stats_module, "st_sort_defcolflag",
3584 "Default sort column for stats_tree stats",
3585 "Sets the default column by which stats based on the stats_tree "
3586 "system is sorted.",
3587 &prefs.st_sort_defcolflag, st_sort_col_vals, FALSE);
3589 prefs_register_bool_preference(stats_module, "st_sort_defdescending",
3590 "Default stats_tree sort order is descending",
3591 "When selected, statistics based on the stats_tree system will by default "
3592 "be sorted in descending order.",
3593 &prefs.st_sort_defdescending);
3595 prefs_register_bool_preference(stats_module, "st_sort_casesensitve",
3596 "Case sensitive sort of stats_tree item names",
3597 "When selected, the item/node names of statistics based on the stats_tree "
3598 "system will be sorted taking case into account. Else the case of the name "
3600 &prefs.st_sort_casesensitve);
3602 prefs_register_bool_preference(stats_module, "st_sort_rng_nameonly",
3603 "Always sort 'range' nodes by name",
3604 "When selected, the stats_tree nodes representing a range of values "
3605 "(0-49, 50-100, etc.) will always be sorted by name (the range of the "
3606 "node). Else range nodes are sorted by the same column as the rest of "
3608 &prefs.st_sort_rng_nameonly);
3610 prefs_register_bool_preference(stats_module, "st_sort_rng_fixorder",
3611 "Always sort 'range' nodes in ascending order",
3612 "When selected, the stats_tree nodes representing a range of values "
3613 "(0-49, 50-100, etc.) will always be sorted ascending; else it follows "
3614 "the sort direction of the tree. Only effective if \"Always sort "
3615 "'range' nodes by name\" is also selected.",
3616 &prefs.st_sort_rng_fixorder);
3618 prefs_register_bool_preference(stats_module, "st_sort_showfullname",
3619 "Display the full stats_tree plug-in name",
3620 "When selected, the full name (including menu path) of the stats_tree "
3621 "plug-in is show in windows. If cleared the plug-in name is shown "
3622 "without menu path (only the part of the name after last '/' character.)",
3623 &prefs.st_sort_showfullname);
3626 protocols_module = prefs_register_module(NULL, "protocols", "Protocols",
3627 "Protocols", NULL, TRUE);
3629 prefs_register_bool_preference(protocols_module, "display_hidden_proto_items",
3630 "Display hidden protocol items",
3631 "Display all hidden protocol items in the packet list.",
3632 &prefs.display_hidden_proto_items);
3634 prefs_register_bool_preference(protocols_module, "display_byte_fields_with_spaces",
3635 "Display byte fields with a space character between bytes",
3636 "Display all byte fields with a space character between each byte in the packet list.",
3637 &prefs.display_byte_fields_with_spaces);
3639 prefs_register_bool_preference(protocols_module, "enable_incomplete_dissectors_check",
3640 "Look for incomplete dissectors",
3641 "Look for dissectors that left some bytes undecoded.",
3642 &prefs.enable_incomplete_dissectors_check);
3644 prefs_register_bool_preference(protocols_module, "strict_conversation_tracking_heuristics",
3645 "Enable stricter conversation tracking heuristics",
3646 "Protocols may use things like VLAN ID or interface ID to narrow the potential for duplicate conversations."
3647 "Currently only ICMP and ICMPv6 use this preference to add VLAN ID to conversation tracking",
3648 &prefs.strict_conversation_tracking_heuristics);
3650 /* Obsolete preferences
3651 * These "modules" were reorganized/renamed to correspond to their GUI
3652 * configuration screen within the preferences dialog
3655 /* taps is now part of the stats module */
3656 prefs_register_module(NULL, "taps", "TAPS", "TAPS", NULL, FALSE);
3657 /* packet_list is now part of the protocol (parent) module */
3658 prefs_register_module(NULL, "packet_list", "PACKET_LIST", "PACKET_LIST", NULL, FALSE);
3659 /* stream is now part of the gui module */
3660 prefs_register_module(NULL, "stream", "STREAM", "STREAM", NULL, FALSE);
3664 /* Parse through a list of comma-separated, possibly quoted strings.
3665 Return a list of the string data. */
3667 prefs_get_string_list(const gchar *str)
3669 enum { PRE_STRING, IN_QUOT, NOT_IN_QUOT };
3671 gint state = PRE_STRING, i = 0, j = 0;
3672 gboolean backslash = FALSE;
3674 gchar *slstr = NULL;
3677 /* Allocate a buffer for the first string. */
3678 slstr = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
3683 if (cur_c == '\0') {
3684 /* It's the end of the input, so it's the end of the string we
3685 were working on, and there's no more input. */
3686 if (state == IN_QUOT || backslash) {
3687 /* We were in the middle of a quoted string or backslash escape,
3688 and ran out of characters; that's an error. */
3690 prefs_clear_string_list(sl);
3695 sl = g_list_append(sl, slstr);
3700 if (cur_c == '"' && ! backslash) {
3703 /* We hadn't yet started processing a string; this starts the
3704 string, and we're now quoting. */
3708 /* We're in the middle of a quoted string, and we saw a quotation
3709 mark; we're no longer quoting. */
3710 state = NOT_IN_QUOT;
3713 /* We're working on a string, but haven't seen a quote; we're
3720 } else if (cur_c == '\\' && ! backslash) {
3721 /* We saw a backslash, and the previous character wasn't a
3722 backslash; escape the next character.
3724 This also means we've started a new string. */
3726 if (state == PRE_STRING)
3727 state = NOT_IN_QUOT;
3728 } else if (cur_c == ',' && state != IN_QUOT && ! backslash) {
3729 /* We saw a comma, and we're not in the middle of a quoted string
3730 and it wasn't preceded by a backslash; it's the end of
3731 the string we were working on... */
3734 sl = g_list_append(sl, slstr);
3735 slstr = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
3738 /* ...and the beginning of a new string. */
3741 } else if (!g_ascii_isspace(cur_c) || state != PRE_STRING) {
3742 /* Either this isn't a white-space character, or we've started a
3743 string (i.e., already seen a non-white-space character for that
3744 string and put it into the string).
3746 The character is to be put into the string; do so if there's
3748 if (j < COL_MAX_LEN) {
3753 /* If it was backslash-escaped, we're done with the backslash escape. */
3761 char *join_string_list(GList *sl)
3763 GString *joined_str = g_string_new("");
3766 guint item_count = 0;
3768 cur = first = g_list_first(sl);
3771 str = (gchar *)cur->data;
3774 g_string_append_c(joined_str, ',');
3776 if (item_count % 2) {
3777 /* Wrap the line. */
3778 g_string_append(joined_str, "\n\t");
3780 g_string_append_c(joined_str, ' ');
3782 g_string_append_c(joined_str, '"');
3784 gunichar uc = g_utf8_get_char (str);
3786 if (uc == '"' || uc == '\\')
3787 g_string_append_c(joined_str, '\\');
3789 if (g_unichar_isprint(uc))
3790 g_string_append_unichar (joined_str, uc);
3792 str = g_utf8_next_char (str);
3795 g_string_append_c(joined_str, '"');
3799 return g_string_free(joined_str, FALSE);
3803 prefs_clear_string_list(GList *sl)
3805 g_list_free_full(sl, g_free);
3809 * Takes a string, a pointer to an array of "enum_val_t"s, and a default gint
3811 * The array must be terminated by an entry with a null "name" string.
3813 * If the string matches a "name" string in an entry, the value from that
3814 * entry is returned.
3816 * Otherwise, if a string matches a "description" string in an entry, the
3817 * value from that entry is returned; we do that for backwards compatibility,
3818 * as we used to have only a "name" string that was used both for command-line
3819 * and configuration-file values and in the GUI (which meant either that
3820 * the GUI had what might be somewhat cryptic values to select from or that
3821 * the "-o" flag took long strings, often with spaces in them).
3823 * Otherwise, the default value that was passed as the third argument is
3827 find_val_for_string(const char *needle, const enum_val_t *haystack,
3832 for (i = 0; haystack[i].name != NULL; i++) {
3833 if (g_ascii_strcasecmp(needle, haystack[i].name) == 0) {
3834 return haystack[i].value;
3837 for (i = 0; haystack[i].name != NULL; i++) {
3838 if (g_ascii_strcasecmp(needle, haystack[i].description) == 0) {
3839 return haystack[i].value;
3842 return default_value;
3846 /* Array of columns that have been migrated to custom columns */
3847 struct deprecated_columns {
3848 const gchar *col_fmt;
3849 const gchar *col_expr;
3851 static struct deprecated_columns migrated_columns[] = {
3852 { /* COL_COS_VALUE */ "%U", "vlan.priority" },
3853 { /* COL_CIRCUIT_ID */ "%c", "iax2.call" },
3854 { /* COL_BSSGP_TLLI */ "%l", "bssgp.tlli" },
3855 { /* COL_HPUX_SUBSYS */ "%H", "nettl.subsys" },
3856 { /* COL_HPUX_DEVID */ "%P", "nettl.devid" },
3857 { /* COL_FR_DLCI */ "%C", "fr.dlci" },
3858 { /* COL_REL_CONV_TIME */ "%rct", "tcp.time_relative" },
3859 { /* COL_DELTA_CONV_TIME */ "%dct", "tcp.time_delta" },
3860 { /* COL_OXID */ "%XO", "fc.ox_id" },
3861 { /* COL_RXID */ "%XR", "fc.rx_id" },
3862 { /* COL_SRCIDX */ "%Xd", "mdshdr.srcidx" },
3863 { /* COL_DSTIDX */ "%Xs", "mdshdr.dstidx" },
3864 { /* COL_DCE_CTX */ "%z", "dcerpc.cn_ctx_id" }
3868 is_deprecated_column_format(const gchar* fmt)
3872 for (haystack_idx = 0;
3873 haystack_idx < G_N_ELEMENTS(migrated_columns);
3876 if (strcmp(migrated_columns[haystack_idx].col_fmt, fmt) == 0) {
3884 /* Preferences file format:
3885 * - Configuration directives start at the beginning of the line, and
3886 * are terminated with a colon.
3887 * - Directives can be continued on the next line by preceding them with
3892 # This is a comment line
3894 print.file: /a/very/long/path/
3899 #define DEF_NUM_COLS 7
3902 * Parse a column format, filling in the relevant fields of a fmt_data.
3905 parse_column_format(fmt_data *cfmt, const char *fmt)
3907 const gchar *cust_format = col_format_to_string(COL_CUSTOM);
3908 size_t cust_format_len = strlen(cust_format);
3909 gchar **cust_format_info;
3912 gchar *col_custom_fields = NULL;
3913 long col_custom_occurrence = 0;
3914 gboolean col_resolved = TRUE;
3917 * Is this a custom column?
3919 if ((strlen(fmt) > cust_format_len) && (fmt[cust_format_len] == ':') &&
3920 strncmp(fmt, cust_format, cust_format_len) == 0) {
3922 col_fmt = COL_CUSTOM;
3923 cust_format_info = g_strsplit(&fmt[cust_format_len+1],":",3); /* add 1 for ':' */
3924 col_custom_fields = g_strdup(cust_format_info[0]);
3925 if (col_custom_fields && cust_format_info[1]) {
3926 col_custom_occurrence = strtol(cust_format_info[1], &p, 10);
3927 if (p == cust_format_info[1] || *p != '\0') {
3928 /* Not a valid number. */
3929 g_free(col_custom_fields);
3930 g_strfreev(cust_format_info);
3934 if (col_custom_fields && cust_format_info[1] && cust_format_info[2]) {
3935 col_resolved = (cust_format_info[2][0] == 'U') ? FALSE : TRUE;
3937 g_strfreev(cust_format_info);
3939 col_fmt = get_column_format_from_str(fmt);
3940 if ((col_fmt == -1) && (!is_deprecated_column_format(fmt)))
3944 cfmt->fmt = col_fmt;
3945 cfmt->custom_fields = col_custom_fields;
3946 cfmt->custom_occurrence = (int)col_custom_occurrence;
3947 cfmt->resolved = col_resolved;
3951 /* Initialize non-dissector preferences to wired-in default values Called
3952 * at program startup and any time the profile changes. (The dissector
3953 * preferences are assumed to be set to those values by the dissectors.)
3954 * They may be overridden by the global preferences file or the user's
3960 if (prefs_initialized)
3966 * Ensure the "global" preferences have been initialized so the
3967 * preference API has the proper default values to work from
3971 prefs_register_modules();
3973 prefs_initialized = TRUE;
3977 * Initialize non-dissector preferences used by the "register preference" API
3978 * to default values so the default values can be used when registered.
3980 * String, filename, and directory preferences will be g_freed so they must
3984 pre_init_prefs(void)
3989 static const gchar *col_fmt[DEF_NUM_COLS*2] = {
3990 "No.", "%m", "Time", "%t",
3991 "Source", "%s", "Destination", "%d",
3992 "Protocol", "%p", "Length", "%L",
3995 prefs.restore_filter_after_following_stream = FALSE;
3996 prefs.gui_toolbar_main_style = TB_STYLE_ICONS;
3997 /* We try to find the best font in the Qt code */
3998 g_free(prefs.gui_qt_font_name);
3999 prefs.gui_qt_font_name = g_strdup("");
4000 prefs.gui_active_fg.red = 0;
4001 prefs.gui_active_fg.green = 0;
4002 prefs.gui_active_fg.blue = 0;
4003 prefs.gui_active_bg.red = 52223;
4004 prefs.gui_active_bg.green = 59647;
4005 prefs.gui_active_bg.blue = 65535;
4006 prefs.gui_active_style = COLOR_STYLE_DEFAULT;
4007 prefs.gui_inactive_fg.red = 0;
4008 prefs.gui_inactive_fg.green = 0;
4009 prefs.gui_inactive_fg.blue = 0;
4010 prefs.gui_inactive_bg.red = 61439;
4011 prefs.gui_inactive_bg.green = 61439;
4012 prefs.gui_inactive_bg.blue = 61439;
4013 prefs.gui_inactive_style = COLOR_STYLE_DEFAULT;
4014 prefs.gui_marked_fg.red = 65535;
4015 prefs.gui_marked_fg.green = 65535;
4016 prefs.gui_marked_fg.blue = 65535;
4017 prefs.gui_marked_bg.red = 0;
4018 prefs.gui_marked_bg.green = 8224;
4019 prefs.gui_marked_bg.blue = 10794;
4020 prefs.gui_ignored_fg.red = 32767;
4021 prefs.gui_ignored_fg.green = 32767;
4022 prefs.gui_ignored_fg.blue = 32767;
4023 prefs.gui_ignored_bg.red = 65535;
4024 prefs.gui_ignored_bg.green = 65535;
4025 prefs.gui_ignored_bg.blue = 65535;
4026 g_free(prefs.gui_colorized_fg);
4027 prefs.gui_colorized_fg = g_strdup("000000,000000,000000,000000,000000,000000,000000,000000,000000,000000");
4028 g_free(prefs.gui_colorized_bg);
4029 prefs.gui_colorized_bg = g_strdup("ffc0c0,ffc0ff,e0c0e0,c0c0ff,c0e0e0,c0ffff,c0ffc0,ffffc0,e0e0c0,e0e0e0");
4030 prefs.st_client_fg.red = 32767;
4031 prefs.st_client_fg.green = 0;
4032 prefs.st_client_fg.blue = 0;
4033 prefs.st_client_bg.red = 64507;
4034 prefs.st_client_bg.green = 60909;
4035 prefs.st_client_bg.blue = 60909;
4036 prefs.st_server_fg.red = 0;
4037 prefs.st_server_fg.green = 0;
4038 prefs.st_server_fg.blue = 32767;
4039 prefs.st_server_bg.red = 60909;
4040 prefs.st_server_bg.green = 60909;
4041 prefs.st_server_bg.blue = 64507;
4043 if (gui_theme_is_dark) {
4044 // Green, red and yellow with HSV V = 84
4045 prefs.gui_text_valid.red = 0x0000; /* dark green */
4046 prefs.gui_text_valid.green = 0x66ff;
4047 prefs.gui_text_valid.blue = 0x0000;
4048 prefs.gui_text_invalid.red = 0x66FF; /* dark red */
4049 prefs.gui_text_invalid.green = 0x0000;
4050 prefs.gui_text_invalid.blue = 0x0000;
4051 prefs.gui_text_deprecated.red = 0x66FF; /* dark yellow / olive */
4052 prefs.gui_text_deprecated.green = 0x66FF;
4053 prefs.gui_text_deprecated.blue = 0x0000;
4055 // Green, red and yellow with HSV V = 20
4056 prefs.gui_text_valid.red = 0xAFFF; /* light green */
4057 prefs.gui_text_valid.green = 0xFFFF;
4058 prefs.gui_text_valid.blue = 0xAFFF;
4059 prefs.gui_text_invalid.red = 0xFFFF; /* light red */
4060 prefs.gui_text_invalid.green = 0xAFFF;
4061 prefs.gui_text_invalid.blue = 0xAFFF;
4062 prefs.gui_text_deprecated.red = 0xFFFF; /* light yellow */
4063 prefs.gui_text_deprecated.green = 0xFFFF;
4064 prefs.gui_text_deprecated.blue = 0xAFFF;
4067 prefs.gui_geometry_save_position = TRUE;
4068 prefs.gui_geometry_save_size = TRUE;
4069 prefs.gui_geometry_save_maximized= TRUE;
4070 prefs.gui_console_open = console_open_never;
4071 prefs.gui_fileopen_style = FO_STYLE_LAST_OPENED;
4072 prefs.gui_recent_df_entries_max = 10;
4073 prefs.gui_recent_files_count_max = 10;
4074 g_free(prefs.gui_fileopen_dir);
4075 prefs.gui_fileopen_dir = g_strdup(get_persdatafile_dir());
4076 prefs.gui_fileopen_preview = 3;
4077 prefs.gui_ask_unsaved = TRUE;
4078 prefs.gui_autocomplete_filter = TRUE;
4079 prefs.gui_find_wrap = TRUE;
4080 prefs.gui_update_enabled = TRUE;
4081 prefs.gui_update_channel = UPDATE_CHANNEL_STABLE;
4082 prefs.gui_update_interval = 60*60*24; /* Seconds */
4083 g_free(prefs.gui_window_title);
4084 prefs.gui_window_title = g_strdup("");
4085 g_free(prefs.gui_prepend_window_title);
4086 prefs.gui_prepend_window_title = g_strdup("");
4087 g_free(prefs.gui_start_title);
4088 prefs.gui_start_title = g_strdup("The World's Most Popular Network Protocol Analyzer");
4089 prefs.gui_version_placement = version_both;
4090 prefs.gui_layout_type = layout_type_5;
4091 prefs.gui_layout_content_1 = layout_pane_content_plist;
4092 prefs.gui_layout_content_2 = layout_pane_content_pdetails;
4093 prefs.gui_layout_content_3 = layout_pane_content_pbytes;
4094 prefs.gui_packet_editor = FALSE;
4095 prefs.gui_packet_list_elide_mode = ELIDE_RIGHT;
4096 prefs.gui_packet_list_show_related = TRUE;
4097 prefs.gui_packet_list_show_minimap = TRUE;
4098 g_free (prefs.gui_interfaces_hide_types);
4099 prefs.gui_interfaces_hide_types = g_strdup("");
4100 prefs.gui_interfaces_show_hidden = FALSE;
4101 prefs.gui_interfaces_remote_display = TRUE;
4102 prefs.gui_qt_packet_list_separator = FALSE;
4103 prefs.gui_qt_show_selected_packet = FALSE;
4104 prefs.gui_qt_show_file_load_time = FALSE;
4106 if (prefs.col_list) {
4107 free_col_info(prefs.col_list);
4108 prefs.col_list = NULL;
4110 for (i = 0; i < DEF_NUM_COLS; i++) {
4111 cfmt = g_new(fmt_data,1);
4112 cfmt->title = g_strdup(col_fmt[i * 2]);
4113 parse_column_format(cfmt, col_fmt[(i * 2) + 1]);
4114 cfmt->visible = TRUE;
4115 cfmt->resolved = TRUE;
4116 cfmt->custom_fields = NULL;
4117 cfmt->custom_occurrence = 0;
4118 prefs.col_list = g_list_append(prefs.col_list, cfmt);
4120 prefs.num_cols = DEF_NUM_COLS;
4122 /* set the default values for the capture dialog box */
4123 prefs.capture_prom_mode = TRUE;
4124 #ifdef PCAP_NG_DEFAULT
4125 prefs.capture_pcap_ng = TRUE;
4127 prefs.capture_pcap_ng = FALSE;
4129 prefs.capture_real_time = TRUE;
4130 prefs.capture_no_extcap = FALSE;
4131 prefs.capture_auto_scroll = TRUE;
4132 prefs.capture_show_info = FALSE;
4134 if (!prefs.capture_columns) {
4135 /* First time through */
4136 for (i = 0; i < num_capture_cols; i++) {
4137 col_name = g_strdup(capture_cols[i]);
4138 prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
4142 prefs.console_log_level =
4143 G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR;
4145 /* set the default values for the tap/statistics dialog box */
4146 prefs.tap_update_interval = TAP_UPDATE_DEFAULT_INTERVAL;
4147 prefs.st_enable_burstinfo = TRUE;
4148 prefs.st_burst_showcount = FALSE;
4149 prefs.st_burst_resolution = ST_DEF_BURSTRES;
4150 prefs.st_burst_windowlen = ST_DEF_BURSTLEN;
4151 prefs.st_sort_casesensitve = TRUE;
4152 prefs.st_sort_rng_fixorder = TRUE;
4153 prefs.st_sort_rng_nameonly = TRUE;
4154 prefs.st_sort_defcolflag = ST_SORT_COL_COUNT;
4155 prefs.st_sort_defdescending = TRUE;
4156 prefs.st_sort_showfullname = FALSE;
4157 prefs.display_hidden_proto_items = FALSE;
4158 prefs.display_byte_fields_with_spaces = FALSE;
4162 * Reset a single dissector preference.
4165 reset_pref(pref_t *pref)
4173 * This preference is no longer supported; it's not a
4174 * real preference, so we don't reset it (i.e., we
4175 * treat it as if it weren't found in the list of
4176 * preferences, and we weren't called in the first place).
4178 if (IS_PREF_OBSOLETE(type))
4181 RESET_PREF_OBSOLETE(type);
4186 case PREF_DECODE_AS_UINT:
4187 *pref->varp.uint = pref->default_val.uint;
4191 *pref->varp.boolp = pref->default_val.boolval;
4196 * For now, we save the "description" value, so that if we
4197 * save the preferences older versions of Wireshark can at
4198 * least read preferences that they supported; we support
4199 * either the short name or the description when reading
4200 * the preferences file or a "-o" option.
4202 *pref->varp.enump = pref->default_val.enumval;
4206 case PREF_SAVE_FILENAME:
4207 case PREF_OPEN_FILENAME:
4209 reset_string_like_preference(pref);
4213 case PREF_DECODE_AS_RANGE:
4214 wmem_free(wmem_epan_scope(), *pref->varp.range);
4215 *pref->varp.range = range_copy(wmem_epan_scope(), pref->default_val.range);
4218 case PREF_STATIC_TEXT:
4224 *pref->varp.colorp = pref->default_val.color;
4228 pref->custom_cbs.reset_cb(pref);
4234 reset_pref_cb(gpointer data, gpointer user_data)
4236 pref_t *pref = (pref_t *) data;
4237 module_t *module = (module_t *)user_data;
4239 if (pref && (pref->type == PREF_RANGE || pref->type == PREF_DECODE_AS_RANGE)) {
4241 * Some dissectors expect the range (returned via prefs_get_range_value)
4242 * to remain valid if it has not changed. If it did change, then we
4243 * should set "prefs_changed_flags" to ensure that the preference apply
4244 * callback is invoked. That callback will notify dissectors that it
4245 * should no longer assume the range to be valid.
4247 if (ranges_are_equal(*pref->varp.range, pref->default_val.range)) {
4248 /* Optimization: do not invoke apply callback if nothing changed. */
4251 module->prefs_changed_flags |= prefs_get_effect_flags(pref);
4257 * Reset all preferences for a module.
4260 reset_module_prefs(const void *key _U_, void *value, void *data _U_)
4262 module_t *module = (module_t *)value;
4263 g_list_foreach(module->prefs, reset_pref_cb, module);
4267 /* Reset preferences */
4271 prefs_initialized = FALSE;
4272 g_free(prefs.saved_at_version);
4273 prefs.saved_at_version = NULL;
4276 * Unload all UAT preferences.
4281 * Unload any loaded MIBs.
4286 * Reset the non-dissector preferences.
4291 * Reset the non-UAT dissector preferences.
4293 wmem_tree_foreach(prefs_modules, reset_module_prefs, NULL);
4296 /* Read the preferences file, fill in "prefs", and return a pointer to it.
4298 If we got an error (other than "it doesn't exist") we report it through
4307 /* clean up libsmi structures before reading prefs */
4313 * If we don't already have the pathname of the global preferences
4314 * file, construct it. Then, in either case, try to open the file.
4316 if (gpf_path == NULL) {
4318 * We don't have the path; try the new path first, and, if that
4319 * file doesn't exist, try the old path.
4321 gpf_path = get_datafile_path(PF_NAME);
4322 if ((pf = ws_fopen(gpf_path, "r")) == NULL && errno == ENOENT) {
4324 * It doesn't exist by the new name; try the old name.
4327 gpf_path = get_datafile_path(OLD_GPF_NAME);
4328 pf = ws_fopen(gpf_path, "r");
4332 * We have the path; try it.
4334 pf = ws_fopen(gpf_path, "r");
4338 * If we were able to open the file, read it.
4339 * XXX - if it failed for a reason other than "it doesn't exist",
4344 * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
4347 mgcp_tcp_port_count = 0;
4348 mgcp_udp_port_count = 0;
4350 /* We succeeded in opening it; read it. */
4351 err = read_prefs_file(gpf_path, pf, set_pref, NULL);
4353 /* We had an error reading the file; report it. */
4354 report_warning("Error reading global preferences file \"%s\": %s.",
4355 gpf_path, g_strerror(err));
4359 /* We failed to open it. If we failed for some reason other than
4360 "it doesn't exist", report the error. */
4361 if (errno != ENOENT) {
4363 report_warning("Can't open global preferences file \"%s\": %s.",
4364 gpf_path, g_strerror(errno));
4369 /* Construct the pathname of the user's preferences file. */
4370 pf_path = get_persconffile_path(PF_NAME, TRUE);
4372 /* Read the user's preferences file, if it exists. */
4373 if ((pf = ws_fopen(pf_path, "r")) != NULL) {
4375 * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
4378 mgcp_tcp_port_count = 0;
4379 mgcp_udp_port_count = 0;
4381 /* We succeeded in opening it; read it. */
4382 err = read_prefs_file(pf_path, pf, set_pref, NULL);
4384 /* We had an error reading the file; report it. */
4385 report_warning("Error reading your preferences file \"%s\": %s.",
4386 pf_path, g_strerror(err));
4391 /* We failed to open it. If we failed for some reason other than
4392 "it doesn't exist", return the errno and the pathname, so our
4393 caller can report the error. */
4394 if (errno != ENOENT) {
4395 report_warning("Can't open your preferences file \"%s\": %s.",
4396 pf_path, g_strerror(errno));
4401 /* load SMI modules if needed */
4407 /* read the preferences file (or similar) and call the callback
4408 * function to set each key/value pair found */
4410 read_prefs_file(const char *pf_path, FILE *pf,
4411 pref_set_pair_cb pref_set_pair_fct, void *private_data)
4414 START, /* beginning of a line */
4415 IN_VAR, /* processing key name */
4416 PRE_VAL, /* finished processing key name, skipping white space befor evalue */
4417 IN_VAL, /* processing value */
4418 IN_SKIP /* skipping to the end of the line */
4423 gboolean got_val = FALSE;
4424 gint fline = 1, pline = 1;
4425 gchar hint[] = "(save preferences to remove this warning)";
4428 cur_val = g_string_new("");
4429 cur_var = g_string_new("");
4431 /* Try to read in the profile name in the first line of the preferences file. */
4432 if (fscanf(pf, "# Configuration file for %127[^\r\n]", ver) == 1) {
4433 /* Assume trailing period and remove it */
4434 g_free(prefs.saved_at_version);
4435 prefs.saved_at_version = g_strndup(ver, strlen(ver) - 1);
4439 while ((got_c = ws_getc_unlocked(pf)) != EOF) {
4440 if (got_c == '\r') {
4441 /* Treat CR-LF at the end of a line like LF, so that if we're reading
4442 * a Windows-format file on UN*X, we handle it the same way we'd handle
4443 * a UN*X-format file. */
4444 got_c = ws_getc_unlocked(pf);
4447 if (got_c != '\n') {
4448 /* Put back the character after the CR, and process the CR normally. */
4453 if (got_c == '\n') {
4461 if (g_ascii_isalnum(got_c)) {
4462 if (cur_var->len > 0) {
4464 if (cur_val->len > 0) {
4465 if (cur_val->str[cur_val->len-1] == ',') {
4467 * If the pref has a trailing comma, eliminate it.
4469 cur_val->str[cur_val->len-1] = '\0';
4470 g_warning ("%s line %d: trailing comma in \"%s\" %s", pf_path, pline, cur_var->str, hint);
4473 /* Call the routine to set the preference; it will parse
4474 the value as appropriate.
4476 Since we're reading a file, rather than processing
4477 explicit user input, for range preferences, silently
4478 lower values in excess of the range's maximum, rather
4479 than reporting errors and failing. */
4480 switch (pref_set_pair_fct(cur_var->str, cur_val->str, private_data, FALSE)) {
4485 case PREFS_SET_SYNTAX_ERR:
4486 g_warning ("Syntax error in preference \"%s\" at line %d of\n%s %s",
4487 cur_var->str, pline, pf_path, hint);
4490 case PREFS_SET_NO_SUCH_PREF:
4491 g_warning ("No such preference \"%s\" at line %d of\n%s %s",
4492 cur_var->str, pline, pf_path, hint);
4493 prefs.unknown_prefs = TRUE;
4496 case PREFS_SET_OBSOLETE:
4498 * If an attempt is made to save the
4499 * preferences, a popup warning will be
4500 * displayed stating that obsolete prefs
4501 * have been detected and the user will
4502 * be given the opportunity to save these
4503 * prefs under a different profile name.
4504 * The prefs in question need to be listed
4505 * in the console window so that the
4506 * user can make an informed choice.
4508 g_warning ("Obsolete preference \"%s\" at line %d of\n%s %s",
4509 cur_var->str, pline, pf_path, hint);
4510 prefs.unknown_prefs = TRUE;
4514 g_warning ("Incomplete preference at line %d: of\n%s %s", pline, pf_path, hint);
4519 g_string_truncate(cur_var, 0);
4520 g_string_append_c(cur_var, (gchar) got_c);
4522 } else if (g_ascii_isspace(got_c) && cur_var->len > 0 && got_val) {
4524 } else if (got_c == '#') {
4527 g_warning ("Malformed preference at line %d of\n%s %s", fline, pf_path, hint);
4532 g_string_append_c(cur_var, (gchar) got_c);
4534 /* This is a colon (':') */
4536 g_string_truncate(cur_val, 0);
4538 * Set got_val to TRUE to accommodate prefs such as
4539 * "gui.fileopen.dir" that do not require a value.
4545 if (!g_ascii_isspace(got_c)) {
4547 g_string_append_c(cur_val, (gchar) got_c);
4551 g_string_append_c(cur_val, (gchar) got_c);
4557 if (cur_var->len > 0) {
4559 /* Call the routine to set the preference; it will parse
4560 the value as appropriate.
4562 Since we're reading a file, rather than processing
4563 explicit user input, for range preferences, silently
4564 lower values in excess of the range's maximum, rather
4565 than reporting errors and failing. */
4566 switch (pref_set_pair_fct(cur_var->str, cur_val->str, private_data, FALSE)) {
4571 case PREFS_SET_SYNTAX_ERR:
4572 g_warning ("Syntax error in preference %s at line %d of\n%s %s",
4573 cur_var->str, pline, pf_path, hint);
4576 case PREFS_SET_NO_SUCH_PREF:
4577 g_warning ("No such preference \"%s\" at line %d of\n%s %s",
4578 cur_var->str, pline, pf_path, hint);
4579 prefs.unknown_prefs = TRUE;
4582 case PREFS_SET_OBSOLETE:
4583 prefs.unknown_prefs = TRUE;
4587 g_warning("Incomplete preference at line %d of\n%s %s",
4588 pline, pf_path, hint);
4592 g_string_free(cur_val, TRUE);
4593 g_string_free(cur_var, TRUE);
4602 * If we were handed a preference starting with "uat:", try to turn it into
4603 * a valid uat entry.
4606 prefs_set_uat_pref(char *uat_entry, char **errmsg) {
4611 colonp = strchr(uat_entry, ':');
4619 * Skip over any white space (there probably won't be any, but
4620 * as we allow it in the preferences file, we might as well
4623 while (g_ascii_isspace(*p))
4627 * Put the colon back, so if our caller uses, in an
4628 * error message, the string they passed us, the message
4635 uat = uat_find(uat_entry);
4638 *errmsg = g_strdup("Unknown preference");
4642 ret = uat_load_str(uat, p, errmsg);
4647 * Given a string of the form "<pref name>:<pref value>", as might appear
4648 * as an argument to a "-o" option, parse it and set the preference in
4649 * question. Return an indication of whether it succeeded or failed
4653 prefs_set_pref(char *prefarg, char **errmsg)
4656 prefs_set_pref_e ret;
4659 * Set the counters of "mgcp.{tcp,udp}.port" entries we've
4660 * seen to values that keep us from trying to interpret them
4661 * as "mgcp.{tcp,udp}.gateway_port" or "mgcp.{tcp,udp}.callagent_port",
4662 * as, from the command line, we have no way of guessing which
4663 * the user had in mind.
4665 mgcp_tcp_port_count = -1;
4666 mgcp_udp_port_count = -1;
4670 colonp = strchr(prefarg, ':');
4672 return PREFS_SET_SYNTAX_ERR;
4678 * Skip over any white space (there probably won't be any, but
4679 * as we allow it in the preferences file, we might as well
4682 while (g_ascii_isspace(*p))
4686 * Put the colon back, so if our caller uses, in an
4687 * error message, the string they passed us, the message
4691 return PREFS_SET_SYNTAX_ERR;
4693 if (strcmp(prefarg, "uat")) {
4694 ret = set_pref(prefarg, p, NULL, TRUE);
4696 ret = prefs_set_uat_pref(p, errmsg) ? PREFS_SET_OK : PREFS_SET_SYNTAX_ERR;
4698 *colonp = ':'; /* put the colon back */
4702 guint prefs_get_uint_value_real(pref_t *pref, pref_source_t source)
4707 return pref->default_val.uint;
4710 return pref->stashed_val.uint;
4713 return *pref->varp.uint;
4716 g_assert_not_reached();
4723 guint prefs_get_uint_value(const char *module_name, const char* pref_name)
4725 return prefs_get_uint_value_real(prefs_find_preference(prefs_find_module(module_name), pref_name), pref_current);
4728 unsigned int prefs_set_uint_value(pref_t *pref, guint value, pref_source_t source)
4730 unsigned int changed = 0;
4734 if (pref->default_val.uint != value) {
4735 pref->default_val.uint = value;
4736 changed = prefs_get_effect_flags(pref);
4740 if (pref->stashed_val.uint != value) {
4741 pref->stashed_val.uint = value;
4742 changed = prefs_get_effect_flags(pref);
4746 if (*pref->varp.uint != value) {
4747 *pref->varp.uint = value;
4748 changed = prefs_get_effect_flags(pref);
4752 g_assert_not_reached();
4759 guint prefs_get_uint_base(pref_t *pref)
4761 return pref->info.base;
4765 * Returns TRUE if the given device is hidden
4768 prefs_is_capture_device_hidden(const char *name)
4770 gchar *tok, *devices;
4773 if (prefs.capture_devices_hide && name) {
4774 devices = g_strdup (prefs.capture_devices_hide);
4775 len = strlen (name);
4776 for (tok = strtok (devices, ","); tok; tok = strtok(NULL, ",")) {
4777 if (strlen (tok) == len && strcmp (name, tok) == 0) {
4789 * Returns TRUE if the given column is visible (not hidden)
4792 prefs_is_column_visible(const gchar *cols_hidden, fmt_data *cfmt)
4795 fmt_data cfmt_hidden;
4798 * Do we have a list of hidden columns?
4802 * Yes - check the column against each of the ones in the
4805 cols = g_strdup(cols_hidden);
4806 for (tok = strtok(cols, ","); tok; tok = strtok(NULL, ",")) {
4807 tok = g_strstrip(tok);
4810 * Parse this column format.
4812 if (!parse_column_format(&cfmt_hidden, tok)) {
4814 * It's not valid; ignore it.
4820 * Does it match the column?
4822 if (cfmt->fmt != cfmt_hidden.fmt) {
4824 g_free(cfmt_hidden.custom_fields);
4825 cfmt_hidden.custom_fields = NULL;
4828 if (cfmt->fmt == COL_CUSTOM) {
4830 * A custom column has to have the same custom field,
4831 * occurrence and resolved settings.
4833 if (cfmt_hidden.custom_fields && cfmt->custom_fields) {
4834 if (strcmp(cfmt->custom_fields,
4835 cfmt_hidden.custom_fields) != 0) {
4836 /* Different fields. */
4837 g_free(cfmt_hidden.custom_fields);
4838 cfmt_hidden.custom_fields = NULL;
4841 if ((cfmt->custom_occurrence != cfmt_hidden.custom_occurrence) ||
4842 (cfmt->resolved != cfmt_hidden.resolved)) {
4843 /* Different occurrences or resolved settings. */
4844 g_free(cfmt_hidden.custom_fields);
4845 cfmt_hidden.custom_fields = NULL;
4852 * OK, they match, so it's one of the hidden fields,
4853 * hence not visible.
4855 g_free(cfmt_hidden.custom_fields);
4863 * No - either there are no hidden columns or this isn't one
4864 * of them - so it is visible.
4870 * Returns TRUE if the given device should capture in monitor mode by default
4873 prefs_capture_device_monitor_mode(const char *name)
4875 gchar *tok, *devices;
4878 if (prefs.capture_devices_monitor_mode && name) {
4879 devices = g_strdup (prefs.capture_devices_monitor_mode);
4880 len = strlen (name);
4881 for (tok = strtok (devices, ","); tok; tok = strtok(NULL, ",")) {
4882 if (strlen (tok) == len && strcmp (name, tok) == 0) {
4894 * Returns TRUE if the user has marked this column as visible
4897 prefs_capture_options_dialog_column_is_visible(const gchar *column)
4902 for (curr = g_list_first(prefs.capture_columns); curr; curr = g_list_next(curr)) {
4903 col = (gchar *)curr->data;
4904 if (col && (g_ascii_strcasecmp(col, column) == 0)) {
4912 prefs_has_layout_pane_content (layout_pane_content_e layout_pane_content)
4914 return ((prefs.gui_layout_content_1 == layout_pane_content) ||
4915 (prefs.gui_layout_content_2 == layout_pane_content) ||
4916 (prefs.gui_layout_content_3 == layout_pane_content));
4919 #define PRS_GUI_FILTER_LABEL "gui.filter_expressions.label"
4920 #define PRS_GUI_FILTER_EXPR "gui.filter_expressions.expr"
4921 #define PRS_GUI_FILTER_ENABLED "gui.filter_expressions.enabled"
4924 * Extract the red, green, and blue components of a 24-bit RGB value
4925 * and convert them from [0,255] to [0,65535].
4927 #define RED_COMPONENT(x) (guint16) (((((x) >> 16) & 0xff) * 65535 / 255))
4928 #define GREEN_COMPONENT(x) (guint16) (((((x) >> 8) & 0xff) * 65535 / 255))
4929 #define BLUE_COMPONENT(x) (guint16) ( (((x) & 0xff) * 65535 / 255))
4932 string_to_name_resolve(const char *string, e_addr_resolve *name_resolve)
4936 memset(name_resolve, 0, sizeof(e_addr_resolve));
4937 while ((c = *string++) != '\0') {
4940 name_resolve->mac_name = TRUE;
4943 name_resolve->network_name = TRUE;
4946 name_resolve->use_external_net_name_resolver = TRUE;
4949 name_resolve->transport_name = TRUE;
4952 name_resolve->dns_pkt_addr_resolution = TRUE;
4955 name_resolve->vlan_name = TRUE;
4959 * Unrecognized letter.
4968 try_convert_to_custom_column(gpointer *el_data)
4972 gchar **fmt = (gchar **) el_data;
4974 for (haystack_idx = 0;
4975 haystack_idx < G_N_ELEMENTS(migrated_columns);
4978 if (strcmp(migrated_columns[haystack_idx].col_fmt, *fmt) == 0) {
4979 gchar *cust_col = g_strdup_printf("%%Cus:%s:0",
4980 migrated_columns[haystack_idx].col_expr);
4989 deprecated_heur_dissector_pref(gchar *pref_name, const gchar *value)
4991 struct heur_pref_name
4993 const char* pref_name;
4994 const char* short_name;
4995 gboolean more_dissectors; /* For multiple dissectors controlled by the same preference */
4998 struct heur_pref_name heur_prefs[] = {
4999 {"acn.heuristic_acn", "acn_udp", 0},
5000 {"bfcp.enable", "bfcp_tcp", 1},
5001 {"bfcp.enable", "bfcp_udp", 0},
5002 {"bt-dht.enable", "bittorrent_dht_udp", 0},
5003 {"bt-utp.enable", "bt_utp_udp", 0},
5004 {"cattp.enable", "cattp_udp", 0},
5005 {"cfp.enable", "fp_eth", 0},
5006 {"dicom.heuristic", "dicom_tcp", 0},
5007 {"dnp3.heuristics", "dnp3_tcp", 1},
5008 {"dnp3.heuristics", "dnp3_udp", 0},
5009 {"dvb-s2_modeadapt.enable", "dvb_s2_udp", 0},
5010 {"esl.enable", "esl_eth", 0},
5011 {"fp.udp_heur", "fp_udp", 0},
5012 {"gvsp.enable_heuristic", "gvsp_udp", 0},
5013 {"hdcp2.enable", "hdcp2_tcp", 0},
5014 {"hislip.enable_heuristic", "hislip_tcp", 0},
5015 {"infiniband.dissect_eoib", "mellanox_eoib", 1},
5016 {"infiniband.identify_payload", "eth_over_ib", 0},
5017 {"jxta.udp.heuristic", "jxta_udp", 0},
5018 {"jxta.tcp.heuristic", "jxta_tcp", 0},
5019 {"jxta.sctp.heuristic", "jxta_sctp", 0},
5020 {"mac-lte.heuristic_mac_lte_over_udp", "mac_lte_udp", 0},
5021 {"mbim.bulk_heuristic", "mbim_usb_bulk", 0},
5022 {"norm.heuristic_norm", "rmt_norm_udp", 0},
5023 {"openflow.heuristic", "openflow_tcp", 0},
5024 {"pdcp-lte.heuristic_pdcp_lte_over_udp", "pdcp_lte_udp", 0},
5025 {"rlc.heuristic_rlc_over_udp", "rlc_udp", 0},
5026 {"rlc-lte.heuristic_rlc_lte_over_udp", "rlc_lte_udp", 0},
5027 {"rtcp.heuristic_rtcp", "rtcp_udp", 1},
5028 {"rtcp.heuristic_rtcp", "rtcp_stun", 0},
5029 {"rtp.heuristic_rtp", "rtp_udp", 1},
5030 {"rtp.heuristic_rtp", "rtp_stun", 0},
5031 {"teredo.heuristic_teredo", "teredo_udp", 0},
5032 {"vssmonitoring.use_heuristics", "vssmonitoring_eth", 0},
5033 {"xml.heuristic", "xml_http", 1},
5034 {"xml.heuristic", "xml_sip", 1},
5035 {"xml.heuristic", "xml_media", 0},
5036 {"xml.heuristic_tcp", "xml_tcp", 0},
5037 {"xml.heuristic_udp", "xml_udp", 0},
5041 heur_dtbl_entry_t* heuristic;
5044 for (i = 0; i < sizeof(heur_prefs)/sizeof(struct heur_pref_name); i++)
5046 if (strcmp(pref_name, heur_prefs[i].pref_name) == 0)
5048 heuristic = find_heur_dissector_by_unique_short_name(heur_prefs[i].short_name);
5049 if (heuristic != NULL) {
5050 heuristic->enabled = ((g_ascii_strcasecmp(value, "true") == 0) ? TRUE : FALSE);
5053 if (!heur_prefs[i].more_dissectors)
5063 deprecated_enable_dissector_pref(gchar *pref_name, const gchar *value)
5065 struct dissector_pref_name
5067 const char* pref_name;
5068 const char* short_name;
5071 struct dissector_pref_name dissector_prefs[] = {
5072 {"transum.tsumenabled", "TRANSUM"},
5073 {"snort.enable_snort_dissector", "Snort"},
5074 {"prp.enable", "PRP"},
5080 for (i = 0; i < sizeof(dissector_prefs)/sizeof(struct dissector_pref_name); i++)
5082 if (strcmp(pref_name, dissector_prefs[i].pref_name) == 0)
5084 proto_id = proto_get_id_by_short_name(dissector_prefs[i].short_name);
5086 proto_set_decoding(proto_id, ((g_ascii_strcasecmp(value, "true") == 0) ? TRUE : FALSE));
5095 deprecated_port_pref(gchar *pref_name, const gchar *value)
5097 struct port_pref_name
5099 const char* pref_name;
5100 const char* module_name; /* the protocol filter name */
5101 const char* table_name;
5105 struct obsolete_pref_name
5107 const char* pref_name;
5110 /* For now this is only supporting TCP/UDP port dissector preferences
5111 which are assumed to be decimal */
5112 struct port_pref_name port_prefs[] = {
5114 {"cmp.tcp_alternate_port", "CMP", "tcp.port", 10},
5115 {"h248.tcp_port", "H248", "tcp.port", 10},
5116 {"cops.tcp.cops_port", "COPS", "tcp.port", 10},
5117 {"dhcpfo.tcp_port", "DHCPFO", "tcp.port", 10},
5118 {"enttec.tcp_port", "ENTTEC", "tcp.port", 10},
5119 {"forces.tcp_alternate_port", "ForCES", "tcp.port", 10},
5120 {"ged125.tcp_port", "GED125", "tcp.port", 10},
5121 {"hpfeeds.dissector_port", "HPFEEDS", "tcp.port", 10},
5122 {"lsc.port", "LSC", "tcp.port", 10},
5123 {"megaco.tcp.txt_port", "MEGACO", "tcp.port", 10},
5124 {"netsync.tcp_port", "Netsync", "tcp.port", 10},
5125 {"osi.tpkt_port", "OSI", "tcp.port", 10},
5126 {"rsync.tcp_port", "RSYNC", "tcp.port", 10},
5127 {"sametime.tcp_port", "SAMETIME", "tcp.port", 10},
5128 {"sigcomp.tcp.port2", "SIGCOMP", "tcp.port", 10},
5129 {"synphasor.tcp_port", "synphasor", "tcp.port", 10},
5130 {"tipc.alternate_port", "TIPC", "tcp.port", 10},
5131 {"vnc.alternate_port", "VNC", "tcp.port", 10},
5132 {"scop.port", "SCoP", "tcp.port", 10},
5133 {"scop.port_secure", "SCoP", "tcp.port", 10},
5135 {"h248.udp_port", "H248", "udp.port", 10},
5136 {"actrace.udp_port", "ACtrace", "udp.port", 10},
5137 {"brp.port", "BRP", "udp.port", 10},
5138 {"bvlc.additional_udp_port", "BVLC", "udp.port", 10},
5139 {"capwap.udp.port.control", "capwap", "udp.port", 10},
5140 {"capwap.udp.port.data", "capwap", "udp.port", 10},
5141 {"coap.udp_port", "CoAP", "udp.port", 10},
5142 {"enttec.udp_port", "ENTTEC", "udp.port", 10},
5143 {"forces.udp_alternate_port", "ForCES", "udp.port", 10},
5144 {"ldss.udp_port", "LDSS", "udp.port", 10},
5145 {"lmp.udp_port", "LMP", "udp.port", 10},
5146 {"ltp.port", "LTP", "udp.port", 10},
5147 {"lwres.udp.lwres_port", "LWRES", "udp.port", 10},
5148 {"megaco.udp.txt_port", "MEGACO", "udp.port", 10},
5149 {"pgm.udp.encap_ucast_port", "PGM", "udp.port", 10},
5150 {"pgm.udp.encap_mcast_port", "PGM", "udp.port", 10},
5151 {"quic.udp.quic.port", "QUIC", "udp.port", 10},
5152 {"quic.udp.quics.port", "QUIC", "udp.port", 10},
5153 {"radius.alternate_port", "RADIUS", "udp.port", 10},
5154 {"rdt.default_udp_port", "RDT", "udp.port", 10},
5155 {"alc.default.udp_port", "ALC", "udp.port", 10},
5156 {"sigcomp.udp.port2", "SIGCOMP", "udp.port", 10},
5157 {"synphasor.udp_port", "synphasor", "udp.port", 10},
5158 {"tdmop.udpport", "TDMoP", "udp.port", 10},
5159 {"uaudp.port1", "UAUDP", "udp.port", 10},
5160 {"uaudp.port2", "UAUDP", "udp.port", 10},
5161 {"uaudp.port3", "UAUDP", "udp.port", 10},
5162 {"uaudp.port4", "UAUDP", "udp.port", 10},
5163 {"uhd.dissector_port", "UHD", "udp.port", 10},
5164 {"vrt.dissector_port", "vrt", "udp.port", 10},
5167 struct port_pref_name port_range_prefs[] = {
5169 {"couchbase.tcp.ports", "Couchbase", "tcp.port", 10},
5170 {"gsm_ipa.tcp_ports", "GSM over IP", "tcp.port", 10},
5171 {"kafka.tcp.ports", "Kafka", "tcp.port", 10},
5172 {"kt.tcp.ports", "Kyoto Tycoon", "tcp.port", 10},
5173 {"memcache.tcp.ports", "MEMCACHE", "tcp.port", 10},
5174 {"mrcpv2.tcp.port_range", "MRCPv2", "tcp.port", 10},
5175 {"rtsp.tcp.port_range", "RTSP", "tcp.port", 10},
5176 {"sip.tcp.ports", "SIP", "tcp.port", 10},
5177 {"tds.tcp_ports", "TDS", "tcp.port", 10},
5178 {"uma.tcp.ports", "UMA", "tcp.port", 10},
5180 {"aruba_erm.udp.ports", "ARUBA_ERM", "udp.port", 10},
5181 {"diameter.udp.ports", "DIAMETER", "udp.port", 10},
5182 {"dmp.udp_ports", "DMP", "udp.port", 10},
5183 {"dns.udp.ports", "DNS", "udp.port", 10},
5184 {"gsm_ipa.udp_ports", "GSM over IP", "udp.port", 10},
5185 {"hcrt.dissector_udp_port", "HCrt", "udp.port", 10},
5186 {"memcache.udp.ports", "MEMCACHE", "udp.port", 10},
5187 {"nb_rtpmux.udp_ports", "NB_RTPMUX", "udp.port", 10},
5188 {"gprs-ns.udp.ports", "GPRS-NS", "udp.port", 10},
5189 {"p_mul.udp_ports", "P_MUL", "udp.port", 10},
5190 {"radius.ports", "RADIUS", "udp.port", 10},
5191 {"sflow.ports", "sFlow", "udp.port", 10},
5192 {"sscop.udp.ports", "SSCOP", "udp.port", 10},
5193 {"tftp.udp_ports", "TFTP", "udp.port", 10},
5194 {"tipc.udp.ports", "TIPC", "udp.port", 10},
5197 /* These are subdissectors of TPKT/OSITP that used to have a
5198 TCP port preference even though they were never
5199 directly on TCP. Convert them to use Decode As
5200 with the TPKT dissector handle */
5201 struct port_pref_name tpkt_subdissector_port_prefs[] = {
5202 {"dap.tcp.port", "DAP", "tcp.port", 10},
5203 {"disp.tcp.port", "DISP", "tcp.port", 10},
5204 {"dop.tcp.port", "DOP", "tcp.port", 10},
5205 {"dsp.tcp.port", "DSP", "tcp.port", 10},
5206 {"p1.tcp.port", "P1", "tcp.port", 10},
5207 {"p7.tcp.port", "P7", "tcp.port", 10},
5208 {"rdp.tcp.port", "RDP", "tcp.port", 10},
5211 /* These are obsolete preferences from the dissectors' view,
5212 (typically because of a switch from a single value to a
5213 range value) but the name of the preference conflicts
5214 with the generated preference name from the dissector table.
5215 Don't allow the obsolete preference through to be handled */
5216 struct obsolete_pref_name obsolete_prefs[] = {
5217 {"diameter.tcp.port"},
5219 {"mrcpv2.tcp.port"},
5227 dissector_table_t sub_dissectors;
5228 dissector_handle_t handle, tpkt_handle;
5232 static gboolean sanity_checked;
5233 if (!sanity_checked) {
5234 sanity_checked = TRUE;
5235 for (i = 0; i < G_N_ELEMENTS(port_prefs); i++) {
5236 module = prefs_find_module(port_prefs[i].module_name);
5238 g_warning("Deprecated ports pref check - module '%s' not found", port_prefs[i].module_name);
5241 pref = prefs_find_preference(module, port_prefs[i].table_name);
5243 g_warning("Deprecated ports pref '%s.%s' not found", module->name, port_prefs[i].table_name);
5246 if (pref->type != PREF_DECODE_AS_UINT && pref->type != PREF_DECODE_AS_RANGE) {
5247 g_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));
5252 for (i = 0; i < G_N_ELEMENTS(port_prefs); i++) {
5253 if (strcmp(pref_name, port_prefs[i].pref_name) == 0) {
5254 if (!ws_basestrtou32(value, NULL, &uval, port_prefs[i].base))
5255 return FALSE; /* number was bad */
5257 module = prefs_find_module(port_prefs[i].module_name);
5258 pref = prefs_find_preference(module, port_prefs[i].table_name);
5260 module->prefs_changed_flags |= prefs_get_effect_flags(pref);
5261 if (pref->type == PREF_DECODE_AS_UINT) {
5262 *pref->varp.uint = uval;
5263 } else if (pref->type == PREF_DECODE_AS_RANGE) {
5264 // The legacy preference was a port number, but the new
5265 // preference is a port range. Add to existing range.
5267 prefs_range_add_value(pref, uval);
5272 /* If the value is zero, it wouldn't add to the Decode As tables */
5275 sub_dissectors = find_dissector_table(port_prefs[i].table_name);
5276 if (sub_dissectors != NULL) {
5277 handle = dissector_table_get_dissector_handle(sub_dissectors, port_prefs[i].module_name);
5278 if (handle != NULL) {
5279 dissector_change_uint(port_prefs[i].table_name, uval, handle);
5280 decode_build_reset_list(port_prefs[i].table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(uval), NULL, NULL);
5289 for (i = 0; i < sizeof(port_range_prefs)/sizeof(struct port_pref_name); i++)
5291 if (strcmp(pref_name, port_range_prefs[i].pref_name) == 0)
5293 guint32 range_i, range_j;
5295 sub_dissectors = find_dissector_table(port_range_prefs[i].table_name);
5296 if (sub_dissectors != NULL) {
5297 switch (dissector_table_get_type(sub_dissectors)) {
5305 g_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));
5306 g_assert_not_reached();
5309 module = prefs_find_module(port_range_prefs[i].module_name);
5310 pref = prefs_find_preference(module, port_range_prefs[i].table_name);
5313 if (!prefs_set_range_value_work(pref, value, TRUE, &module->prefs_changed_flags))
5315 return FALSE; /* number was bad */
5318 handle = dissector_table_get_dissector_handle(sub_dissectors, port_range_prefs[i].module_name);
5319 if (handle != NULL) {
5321 for (range_i = 0; range_i < (*pref->varp.range)->nranges; range_i++) {
5322 for (range_j = (*pref->varp.range)->ranges[range_i].low; range_j < (*pref->varp.range)->ranges[range_i].high; range_j++) {
5323 dissector_change_uint(port_range_prefs[i].table_name, range_j, handle);
5324 decode_build_reset_list(port_range_prefs[i].table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(range_j), NULL, NULL);
5327 dissector_change_uint(port_range_prefs[i].table_name, (*pref->varp.range)->ranges[range_i].high, handle);
5328 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), NULL, NULL);
5338 for (i = 0; i < sizeof(tpkt_subdissector_port_prefs)/sizeof(struct port_pref_name); i++)
5340 if (strcmp(pref_name, tpkt_subdissector_port_prefs[i].pref_name) == 0)
5342 /* XXX - give an error if it doesn't fit in a guint? */
5343 if (!ws_basestrtou32(value, NULL, &uval, tpkt_subdissector_port_prefs[i].base))
5344 return FALSE; /* number was bad */
5346 /* If the value is 0 or 102 (default TPKT port), don't add to the Decode As tables */
5347 if ((uval != 0) && (uval != 102))
5349 tpkt_handle = find_dissector("tpkt");
5350 if (tpkt_handle != NULL) {
5351 dissector_change_uint(tpkt_subdissector_port_prefs[i].table_name, uval, tpkt_handle);
5359 for (i = 0; i < sizeof(obsolete_prefs)/sizeof(struct obsolete_pref_name); i++)
5361 if (strcmp(pref_name, obsolete_prefs[i].pref_name) == 0)
5363 /* Just ignore the preference */
5370 static prefs_set_pref_e
5371 set_pref(gchar *pref_name, const gchar *value, void *private_data _U_,
5372 gboolean return_range_errors)
5378 gchar *dotp, *last_dotp;
5379 static gchar *filter_label = NULL;
5380 static gboolean filter_enabled = FALSE;
5381 module_t *module, *containing_module;
5385 //The PRS_GUI field names are here for backwards compatibility
5386 //display filters have been converted to a UAT.
5387 if (strcmp(pref_name, PRS_GUI_FILTER_LABEL) == 0) {
5388 /* Assume that PRS_GUI_FILTER_EXPR follows this preference. In case of
5389 * malicious preference files, free the previous value to limit the size
5390 * of leaked memory. */
5391 g_free(filter_label);
5392 filter_label = g_strdup(value);
5393 } else if (strcmp(pref_name, PRS_GUI_FILTER_ENABLED) == 0) {
5394 filter_enabled = (strcmp(value, "TRUE") == 0) ? TRUE : FALSE;
5395 } else if (strcmp(pref_name, PRS_GUI_FILTER_EXPR) == 0) {
5396 /* Comments not supported for "old" preference style */
5397 filter_expression_new(filter_label, value, "", filter_enabled);
5398 g_free(filter_label);
5399 filter_label = NULL;
5400 /* Remember to save the new UAT to file. */
5401 prefs.filter_expressions_old = TRUE;
5402 } else if (strcmp(pref_name, "gui.version_in_start_page") == 0) {
5403 /* Convert deprecated value to closest current equivalent */
5404 if (g_ascii_strcasecmp(value, "true") == 0) {
5405 prefs.gui_version_placement = version_both;
5407 prefs.gui_version_placement = version_neither;
5409 } else if (strcmp(pref_name, "name_resolve") == 0 ||
5410 strcmp(pref_name, "capture.name_resolve") == 0) {
5412 * Handle the deprecated name resolution options.
5414 * "TRUE" and "FALSE", for backwards compatibility, are synonyms for
5415 * RESOLV_ALL and RESOLV_NONE.
5417 * Otherwise, we treat it as a list of name types we want to resolve.
5419 if (g_ascii_strcasecmp(value, "true") == 0) {
5420 gbl_resolv_flags.mac_name = TRUE;
5421 gbl_resolv_flags.network_name = TRUE;
5422 gbl_resolv_flags.transport_name = TRUE;
5424 else if (g_ascii_strcasecmp(value, "false") == 0) {
5425 disable_name_resolution();
5428 /* start out with none set */
5429 disable_name_resolution();
5430 if (string_to_name_resolve(value, &gbl_resolv_flags) != '\0')
5431 return PREFS_SET_SYNTAX_ERR;
5433 } else if (deprecated_heur_dissector_pref(pref_name, value)) {
5434 /* Handled within deprecated_heur_dissector_pref() if found */
5435 } else if (deprecated_enable_dissector_pref(pref_name, value)) {
5436 /* Handled within deprecated_enable_dissector_pref() if found */
5437 } else if (deprecated_port_pref(pref_name, value)) {
5438 /* Handled within deprecated_port_pref() if found */
5440 /* Handle deprecated "global" options that don't have a module
5441 * associated with them
5443 if ((strcmp(pref_name, "name_resolve_concurrency") == 0) ||
5444 (strcmp(pref_name, "name_resolve_load_smi_modules") == 0) ||
5445 (strcmp(pref_name, "name_resolve_suppress_smi_errors") == 0)) {
5446 module = nameres_module;
5449 /* To which module does this preference belong? */
5451 last_dotp = pref_name;
5453 dotp = strchr(last_dotp, '.');
5455 /* Either there's no such module, or no module was specified.
5456 In either case, that means there's no such preference. */
5457 return PREFS_SET_NO_SUCH_PREF;
5459 *dotp = '\0'; /* separate module and preference name */
5460 module = prefs_find_module(pref_name);
5463 * XXX - "Diameter" rather than "diameter" was used in earlier
5464 * versions of Wireshark; if we didn't find the module, and its name
5465 * was "Diameter", look for "diameter" instead.
5467 * In addition, the BEEP protocol used to be the BXXP protocol,
5468 * so if we didn't find the module, and its name was "bxxp",
5469 * look for "beep" instead.
5471 * Also, the preferences for GTP v0 and v1 were combined under
5472 * a single "gtp" heading, and the preferences for SMPP were
5473 * moved to "smpp-gsm-sms" and then moved to "gsm-sms-ud".
5474 * However, SMPP now has its own preferences, so we just map
5475 * "smpp-gsm-sms" to "gsm-sms-ud", and then handle SMPP below.
5477 * We also renamed "dcp" to "dccp", "x.25" to "x25", "x411" to "p1"
5478 * and "nsip" to "gprs_ns".
5480 * The SynOptics Network Management Protocol (SONMP) is now known by
5481 * its modern name, the Nortel Discovery Protocol (NDP).
5483 if (module == NULL) {
5485 * See if there's a backwards-compatibility name
5486 * that maps to this module.
5488 module = prefs_find_module_alias(pref_name);
5489 if (module == NULL) {
5491 * There's no alias for the module; see if the
5492 * module name matches any protocol aliases.
5494 header_field_info *hfinfo = proto_registrar_get_byalias(pref_name);
5496 module = (module_t *) wmem_tree_lookup_string(prefs_modules, hfinfo->abbrev, WMEM_TREE_STRING_NOCASE);
5499 if (module == NULL) {
5501 * There aren't any aliases. Was the module
5502 * removed rather than renamed?
5504 if (strcmp(pref_name, "etheric") == 0 ||
5505 strcmp(pref_name, "isup_thin") == 0) {
5507 * The dissectors for these protocols were
5508 * removed as obsolete on 2009-07-70 in change
5509 * 739bfc6ff035583abb9434e0e988048de38a8d9a.
5511 return PREFS_SET_OBSOLETE;
5515 g_warning ("Preference \"%s.%s\" has been converted to \"%s.%s\"\n"
5516 "Save your preferences to make this change permanent.",
5517 pref_name, dotp+1, module->name, dotp+1);
5518 prefs.unknown_prefs = TRUE;
5521 *dotp = '.'; /* put the preference string back */
5522 dotp++; /* skip past separator to preference name */
5527 /* The pref is located in the module or a submodule.
5528 * Assume module, then search for a submodule holding the pref. */
5529 containing_module = module;
5530 pref = prefs_find_preference_with_submodule(module, dotp, &containing_module);
5533 prefs.unknown_prefs = TRUE;
5535 /* "gui" prefix was added to column preferences for better organization
5536 * within the preferences file
5538 if (module == gui_column_module) {
5539 /* While this has a subtree, there is no apply callback, so no
5540 * need to use prefs_find_preference_with_submodule to update
5541 * containing_module. It would not be useful. */
5542 pref = prefs_find_preference(module, pref_name);
5544 else if (strcmp(module->name, "mgcp") == 0) {
5546 * XXX - "mgcp.display raw text toggle" and "mgcp.display dissect tree"
5547 * rather than "mgcp.display_raw_text" and "mgcp.display_dissect_tree"
5548 * were used in earlier versions of Wireshark; if we didn't find the
5549 * preference, it was an MGCP preference, and its name was
5550 * "display raw text toggle" or "display dissect tree", look for
5551 * "display_raw_text" or "display_dissect_tree" instead.
5553 * "mgcp.tcp.port" and "mgcp.udp.port" are harder to handle, as both
5554 * the gateway and callagent ports were given those names; we interpret
5555 * the first as "mgcp.{tcp,udp}.gateway_port" and the second as
5556 * "mgcp.{tcp,udp}.callagent_port", as that's the order in which
5557 * they were registered by the MCCP dissector and thus that's the
5558 * order in which they were written to the preferences file. (If
5559 * we're not reading the preferences file, but are handling stuff
5560 * from a "-o" command-line option, we have no clue which the user
5561 * had in mind - they should have used "mgcp.{tcp,udp}.gateway_port"
5562 * or "mgcp.{tcp,udp}.callagent_port" instead.)
5564 if (strcmp(dotp, "display raw text toggle") == 0)
5565 pref = prefs_find_preference(module, "display_raw_text");
5566 else if (strcmp(dotp, "display dissect tree") == 0)
5567 pref = prefs_find_preference(module, "display_dissect_tree");
5568 else if (strcmp(dotp, "tcp.port") == 0) {
5569 mgcp_tcp_port_count++;
5570 if (mgcp_tcp_port_count == 1) {
5571 /* It's the first one */
5572 pref = prefs_find_preference(module, "tcp.gateway_port");
5573 } else if (mgcp_tcp_port_count == 2) {
5574 /* It's the second one */
5575 pref = prefs_find_preference(module, "tcp.callagent_port");
5577 /* Otherwise it's from the command line, and we don't bother
5579 } else if (strcmp(dotp, "udp.port") == 0) {
5580 mgcp_udp_port_count++;
5581 if (mgcp_udp_port_count == 1) {
5582 /* It's the first one */
5583 pref = prefs_find_preference(module, "udp.gateway_port");
5584 } else if (mgcp_udp_port_count == 2) {
5585 /* It's the second one */
5586 pref = prefs_find_preference(module, "udp.callagent_port");
5588 /* Otherwise it's from the command line, and we don't bother
5591 } else if (strcmp(module->name, "smb") == 0) {
5592 /* Handle old names for SMB preferences. */
5593 if (strcmp(dotp, "smb.trans.reassembly") == 0)
5594 pref = prefs_find_preference(module, "trans_reassembly");
5595 else if (strcmp(dotp, "smb.dcerpc.reassembly") == 0)
5596 pref = prefs_find_preference(module, "dcerpc_reassembly");
5597 } else if (strcmp(module->name, "ndmp") == 0) {
5598 /* Handle old names for NDMP preferences. */
5599 if (strcmp(dotp, "ndmp.desegment") == 0)
5600 pref = prefs_find_preference(module, "desegment");
5601 } else if (strcmp(module->name, "diameter") == 0) {
5602 /* Handle old names for Diameter preferences. */
5603 if (strcmp(dotp, "diameter.desegment") == 0)
5604 pref = prefs_find_preference(module, "desegment");
5605 } else if (strcmp(module->name, "pcli") == 0) {
5606 /* Handle old names for PCLI preferences. */
5607 if (strcmp(dotp, "pcli.udp_port") == 0)
5608 pref = prefs_find_preference(module, "udp_port");
5609 } else if (strcmp(module->name, "artnet") == 0) {
5610 /* Handle old names for ARTNET preferences. */
5611 if (strcmp(dotp, "artnet.udp_port") == 0)
5612 pref = prefs_find_preference(module, "udp_port");
5613 } else if (strcmp(module->name, "mapi") == 0) {
5614 /* Handle old names for MAPI preferences. */
5615 if (strcmp(dotp, "mapi_decrypt") == 0)
5616 pref = prefs_find_preference(module, "decrypt");
5617 } else if (strcmp(module->name, "fc") == 0) {
5618 /* Handle old names for Fibre Channel preferences. */
5619 if (strcmp(dotp, "reassemble_fc") == 0)
5620 pref = prefs_find_preference(module, "reassemble");
5621 else if (strcmp(dotp, "fc_max_frame_size") == 0)
5622 pref = prefs_find_preference(module, "max_frame_size");
5623 } else if (strcmp(module->name, "fcip") == 0) {
5624 /* Handle old names for Fibre Channel-over-IP preferences. */
5625 if (strcmp(dotp, "desegment_fcip_messages") == 0)
5626 pref = prefs_find_preference(module, "desegment");
5627 else if (strcmp(dotp, "fcip_port") == 0)
5628 pref = prefs_find_preference(module, "target_port");
5629 } else if (strcmp(module->name, "gtp") == 0) {
5630 /* Handle old names for GTP preferences. */
5631 if (strcmp(dotp, "gtpv0_port") == 0)
5632 pref = prefs_find_preference(module, "v0_port");
5633 else if (strcmp(dotp, "gtpv1c_port") == 0)
5634 pref = prefs_find_preference(module, "v1c_port");
5635 else if (strcmp(dotp, "gtpv1u_port") == 0)
5636 pref = prefs_find_preference(module, "v1u_port");
5637 else if (strcmp(dotp, "gtp_dissect_tpdu") == 0)
5638 pref = prefs_find_preference(module, "dissect_tpdu");
5639 else if (strcmp(dotp, "gtpv0_dissect_cdr_as") == 0)
5640 pref = prefs_find_preference(module, "v0_dissect_cdr_as");
5641 else if (strcmp(dotp, "gtpv0_check_etsi") == 0)
5642 pref = prefs_find_preference(module, "v0_check_etsi");
5643 else if (strcmp(dotp, "gtpv1_check_etsi") == 0)
5644 pref = prefs_find_preference(module, "v1_check_etsi");
5645 } else if (strcmp(module->name, "ip") == 0) {
5646 /* Handle old names for IP preferences. */
5647 if (strcmp(dotp, "ip_summary_in_tree") == 0)
5648 pref = prefs_find_preference(module, "summary_in_tree");
5649 } else if (strcmp(module->name, "iscsi") == 0) {
5650 /* Handle old names for iSCSI preferences. */
5651 if (strcmp(dotp, "iscsi_port") == 0)
5652 pref = prefs_find_preference(module, "target_port");
5653 } else if (strcmp(module->name, "lmp") == 0) {
5654 /* Handle old names for LMP preferences. */
5655 if (strcmp(dotp, "lmp_version") == 0)
5656 pref = prefs_find_preference(module, "version");
5657 } else if (strcmp(module->name, "mtp3") == 0) {
5658 /* Handle old names for MTP3 preferences. */
5659 if (strcmp(dotp, "mtp3_standard") == 0)
5660 pref = prefs_find_preference(module, "standard");
5661 else if (strcmp(dotp, "net_addr_format") == 0)
5662 pref = prefs_find_preference(module, "addr_format");
5663 } else if (strcmp(module->name, "nlm") == 0) {
5664 /* Handle old names for NLM preferences. */
5665 if (strcmp(dotp, "nlm_msg_res_matching") == 0)
5666 pref = prefs_find_preference(module, "msg_res_matching");
5667 } else if (strcmp(module->name, "ppp") == 0) {
5668 /* Handle old names for PPP preferences. */
5669 if (strcmp(dotp, "ppp_fcs") == 0)
5670 pref = prefs_find_preference(module, "fcs_type");
5671 else if (strcmp(dotp, "ppp_vj") == 0)
5672 pref = prefs_find_preference(module, "decompress_vj");
5673 } else if (strcmp(module->name, "rsvp") == 0) {
5674 /* Handle old names for RSVP preferences. */
5675 if (strcmp(dotp, "rsvp_process_bundle") == 0)
5676 pref = prefs_find_preference(module, "process_bundle");
5677 } else if (strcmp(module->name, "tcp") == 0) {
5678 /* Handle old names for TCP preferences. */
5679 if (strcmp(dotp, "tcp_summary_in_tree") == 0)
5680 pref = prefs_find_preference(module, "summary_in_tree");
5681 else if (strcmp(dotp, "tcp_analyze_sequence_numbers") == 0)
5682 pref = prefs_find_preference(module, "analyze_sequence_numbers");
5683 else if (strcmp(dotp, "tcp_relative_sequence_numbers") == 0)
5684 pref = prefs_find_preference(module, "relative_sequence_numbers");
5685 } else if (strcmp(module->name, "udp") == 0) {
5686 /* Handle old names for UDP preferences. */
5687 if (strcmp(dotp, "udp_summary_in_tree") == 0)
5688 pref = prefs_find_preference(module, "summary_in_tree");
5689 } else if (strcmp(module->name, "ndps") == 0) {
5690 /* Handle old names for NDPS preferences. */
5691 if (strcmp(dotp, "desegment_ndps") == 0)
5692 pref = prefs_find_preference(module, "desegment_tcp");
5693 } else if (strcmp(module->name, "http") == 0) {
5694 /* Handle old names for HTTP preferences. */
5695 if (strcmp(dotp, "desegment_http_headers") == 0)
5696 pref = prefs_find_preference(module, "desegment_headers");
5697 else if (strcmp(dotp, "desegment_http_body") == 0)
5698 pref = prefs_find_preference(module, "desegment_body");
5699 } else if (strcmp(module->name, "smpp") == 0) {
5700 /* Handle preferences that moved from SMPP. */
5701 module_t *new_module = prefs_find_module("gsm-sms-ud");
5703 if (strcmp(dotp, "port_number_udh_means_wsp") == 0) {
5704 pref = prefs_find_preference(new_module, "port_number_udh_means_wsp");
5705 containing_module = new_module;
5706 } else if (strcmp(dotp, "try_dissect_1st_fragment") == 0) {
5707 pref = prefs_find_preference(new_module, "try_dissect_1st_fragment");
5708 containing_module = new_module;
5711 } else if (strcmp(module->name, "asn1") == 0) {
5712 /* Handle old generic ASN.1 preferences (it's not really a
5713 rename, as the new preferences support multiple ports,
5714 but we might as well copy them over). */
5715 if (strcmp(dotp, "tcp_port") == 0)
5716 pref = prefs_find_preference(module, "tcp_ports");
5717 else if (strcmp(dotp, "udp_port") == 0)
5718 pref = prefs_find_preference(module, "udp_ports");
5719 else if (strcmp(dotp, "sctp_port") == 0)
5720 pref = prefs_find_preference(module, "sctp_ports");
5721 } else if (strcmp(module->name, "llcgprs") == 0) {
5722 if (strcmp(dotp, "ignore_cipher_bit") == 0)
5723 pref = prefs_find_preference(module, "autodetect_cipher_bit");
5724 } else if (strcmp(module->name, "erf") == 0) {
5725 if (strcmp(dotp, "erfeth") == 0) {
5726 /* Handle the old "erfeth" preference; map it to the new
5727 "ethfcs" preference, and map the values to those for
5728 the new preference. */
5729 pref = prefs_find_preference(module, "ethfcs");
5730 if (strcmp(value, "ethfcs") == 0 || strcmp(value, "Ethernet with FCS") == 0)
5732 else if (strcmp(value, "eth") == 0 || strcmp(value, "Ethernet") == 0)
5734 else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
5736 } else if (strcmp(dotp, "erfatm") == 0) {
5737 /* Handle the old "erfatm" preference; map it to the new
5738 "aal5_type" preference, and map the values to those for
5739 the new preference. */
5740 pref = prefs_find_preference(module, "aal5_type");
5741 if (strcmp(value, "atm") == 0 || strcmp(value, "ATM") == 0)
5743 else if (strcmp(value, "llc") == 0 || strcmp(value, "LLC") == 0)
5745 else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
5747 } else if (strcmp(dotp, "erfhdlc") == 0) {
5748 /* Handle the old "erfhdlc" preference; map it to the new
5749 "hdlc_type" preference, and map the values to those for
5750 the new preference. */
5751 pref = prefs_find_preference(module, "hdlc_type");
5752 if (strcmp(value, "chdlc") == 0 || strcmp(value, "Cisco HDLC") == 0)
5754 else if (strcmp(value, "ppp") == 0 || strcmp(value, "PPP serial") == 0)
5756 else if (strcmp(value, "fr") == 0 || strcmp(value, "Frame Relay") == 0)
5758 else if (strcmp(value, "mtp2") == 0 || strcmp(value, "SS7 MTP2") == 0)
5760 else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
5763 } else if (strcmp(module->name, "eth") == 0) {
5764 /* "eth.qinq_ethertype" has been changed(restored) to "vlan.qinq.ethertype" */
5765 if (strcmp(dotp, "qinq_ethertype") == 0) {
5766 module_t *new_module = prefs_find_module("vlan");
5768 pref = prefs_find_preference(new_module, "qinq_ethertype");
5769 containing_module = new_module;
5772 } else if (strcmp(module->name, "taps") == 0) {
5773 /* taps preferences moved to "statistics" module */
5774 if (strcmp(dotp, "update_interval") == 0)
5775 pref = prefs_find_preference(stats_module, dotp);
5776 } else if (strcmp(module->name, "packet_list") == 0) {
5777 /* packet_list preferences moved to protocol module */
5778 if (strcmp(dotp, "display_hidden_proto_items") == 0)
5779 pref = prefs_find_preference(protocols_module, dotp);
5780 } else if (strcmp(module->name, "stream") == 0) {
5781 /* stream preferences moved to gui color module */
5782 if ((strcmp(dotp, "client.fg") == 0) ||
5783 (strcmp(dotp, "client.bg") == 0) ||
5784 (strcmp(dotp, "server.fg") == 0) ||
5785 (strcmp(dotp, "server.bg") == 0))
5786 pref = prefs_find_preference(gui_color_module, pref_name);
5787 } else if (strcmp(module->name, "nameres") == 0) {
5788 if (strcmp(pref_name, "name_resolve_concurrency") == 0) {
5789 pref = prefs_find_preference(nameres_module, pref_name);
5790 } else if (strcmp(pref_name, "name_resolve_load_smi_modules") == 0) {
5791 pref = prefs_find_preference(nameres_module, "load_smi_modules");
5792 } else if (strcmp(pref_name, "name_resolve_suppress_smi_errors") == 0) {
5793 pref = prefs_find_preference(nameres_module, "suppress_smi_errors");
5798 return PREFS_SET_NO_SUCH_PREF; /* no such preference */
5801 if (IS_PREF_OBSOLETE(type)) {
5802 return PREFS_SET_OBSOLETE; /* no such preference any more */
5804 RESET_PREF_OBSOLETE(type);
5810 if (!ws_basestrtou32(value, NULL, &uval, pref->info.base))
5811 return PREFS_SET_SYNTAX_ERR; /* number was bad */
5812 if (*pref->varp.uint != uval) {
5813 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
5814 *pref->varp.uint = uval;
5817 case PREF_DECODE_AS_UINT:
5819 /* This is for backwards compatibility in case any of the preferences
5820 that shared the "Decode As" preference name and used to be PREF_UINT
5821 are now applied directly to the Decode As funtionality */
5823 dissector_table_t sub_dissectors;
5824 dissector_handle_t handle;
5826 if (!ws_basestrtou32(value, NULL, &uval, pref->info.base))
5827 return PREFS_SET_SYNTAX_ERR; /* number was bad */
5829 if (*pref->varp.uint != uval) {
5830 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
5831 *pref->varp.uint = uval;
5833 /* Name of preference is the dissector table */
5834 sub_dissectors = find_dissector_table(pref->name);
5835 if (sub_dissectors != NULL) {
5836 handle = dissector_table_get_dissector_handle(sub_dissectors, module->title);
5837 if (handle != NULL) {
5839 dissector_change_uint(pref->name, uval, handle);
5840 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(uval), NULL, NULL);
5842 dissector_delete_uint(pref->name, *pref->varp.uint, handle);
5843 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), pref->varp.uint, NULL, NULL);
5846 /* XXX - Do we save the decode_as_entries file here? */
5853 /* XXX - give an error if it's neither "true" nor "false"? */
5854 if (g_ascii_strcasecmp(value, "true") == 0)
5858 if (*pref->varp.boolp != bval) {
5859 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
5860 *pref->varp.boolp = bval;
5865 /* XXX - give an error if it doesn't match? */
5866 enum_val = find_val_for_string(value, pref->info.enum_info.enumvals,
5868 if (*pref->varp.enump != enum_val) {
5869 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
5870 *pref->varp.enump = enum_val;
5875 case PREF_SAVE_FILENAME:
5876 case PREF_OPEN_FILENAME:
5878 containing_module->prefs_changed_flags |= prefs_set_string_value(pref, value, pref_current);
5883 if (!prefs_set_range_value_work(pref, value, return_range_errors,
5884 &containing_module->prefs_changed_flags))
5885 return PREFS_SET_SYNTAX_ERR; /* number was bad */
5888 case PREF_DECODE_AS_RANGE:
5890 /* This is for backwards compatibility in case any of the preferences
5891 that shared the "Decode As" preference name and used to be PREF_RANGE
5892 are now applied directly to the Decode As funtionality */
5894 dissector_table_t sub_dissectors;
5895 dissector_handle_t handle;
5898 if (range_convert_str_work(wmem_epan_scope(), &newrange, value, pref->info.max_value,
5899 return_range_errors) != CVT_NO_ERROR) {
5900 return PREFS_SET_SYNTAX_ERR; /* number was bad */
5903 if (!ranges_are_equal(*pref->varp.range, newrange)) {
5904 wmem_free(wmem_epan_scope(), *pref->varp.range);
5905 *pref->varp.range = newrange;
5906 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
5908 /* Name of preference is the dissector table */
5909 sub_dissectors = find_dissector_table(pref->name);
5910 if (sub_dissectors != NULL) {
5911 handle = dissector_table_get_dissector_handle(sub_dissectors, module->title);
5912 if (handle != NULL) {
5913 /* Delete all of the old values from the dissector table */
5914 for (i = 0; i < (*pref->varp.range)->nranges; i++) {
5915 for (j = (*pref->varp.range)->ranges[i].low; j < (*pref->varp.range)->ranges[i].high; j++) {
5916 dissector_delete_uint(pref->name, j, handle);
5917 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(j), NULL, NULL);
5920 dissector_delete_uint(pref->name, (*pref->varp.range)->ranges[i].high, handle);
5921 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER((*pref->varp.range)->ranges[i].high), NULL, NULL);
5924 /* Add new values to the dissector table */
5925 for (i = 0; i < newrange->nranges; i++) {
5926 for (j = newrange->ranges[i].low; j < newrange->ranges[i].high; j++) {
5927 dissector_change_uint(pref->name, j, handle);
5928 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(j), NULL, NULL);
5931 dissector_change_uint(pref->name, newrange->ranges[i].high, handle);
5932 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(newrange->ranges[i].high), NULL, NULL);
5935 /* XXX - Do we save the decode_as_entries file here? */
5939 wmem_free(wmem_epan_scope(), newrange);
5946 if (!ws_hexstrtou32(value, NULL, &cval))
5947 return PREFS_SET_SYNTAX_ERR; /* number was bad */
5948 if ((pref->varp.colorp->red != RED_COMPONENT(cval)) ||
5949 (pref->varp.colorp->green != GREEN_COMPONENT(cval)) ||
5950 (pref->varp.colorp->blue != BLUE_COMPONENT(cval))) {
5951 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
5952 pref->varp.colorp->red = RED_COMPONENT(cval);
5953 pref->varp.colorp->green = GREEN_COMPONENT(cval);
5954 pref->varp.colorp->blue = BLUE_COMPONENT(cval);
5960 return pref->custom_cbs.set_cb(pref, value, &containing_module->prefs_changed_flags);
5962 case PREF_STATIC_TEXT:
5970 return PREFS_SET_OK;
5975 gboolean is_gui_module;
5976 } write_gui_pref_arg_t;
5979 prefs_pref_type_name(pref_t *pref)
5981 const char *type_name = "[Unknown]";
5985 return type_name; /* ...or maybe assert? */
5990 if (IS_PREF_OBSOLETE(type)) {
5991 type_name = "Obsolete";
5993 RESET_PREF_OBSOLETE(type);
5999 switch (pref->info.base) {
6002 type_name = "Decimal";
6006 type_name = "Octal";
6010 type_name = "Hexadecimal";
6016 type_name = "Boolean";
6020 type_name = "Choice";
6024 type_name = "String";
6027 case PREF_SAVE_FILENAME:
6028 case PREF_OPEN_FILENAME:
6029 type_name = "Filename";
6033 type_name = "Directory";
6037 type_name = "Range";
6041 type_name = "Color";
6045 if (pref->custom_cbs.type_name_cb)
6046 return pref->custom_cbs.type_name_cb();
6047 type_name = "Custom";
6050 case PREF_DECODE_AS_UINT:
6051 type_name = "Decode As value";
6054 case PREF_DECODE_AS_RANGE:
6055 type_name = "Range (for Decode As)";
6058 case PREF_STATIC_TEXT:
6059 type_name = "Static text";
6070 prefs_get_effect_flags(pref_t *pref)
6075 return pref->effect_flags;
6079 prefs_set_effect_flags(pref_t *pref, unsigned int flags)
6082 pref->effect_flags = flags;
6087 prefs_set_effect_flags_by_name(module_t * module, const char *pref, unsigned int flags)
6089 prefs_set_effect_flags(prefs_find_preference(module, pref), flags);
6093 prefs_get_module_effect_flags(module_t * module)
6098 return module->effect_flags;
6102 prefs_set_module_effect_flags(module_t * module, unsigned int flags)
6104 if (module != NULL) {
6105 module->effect_flags = flags;
6110 prefs_pref_type_description(pref_t *pref)
6112 const char *type_desc = "An unknown preference type";
6116 return g_strdup_printf("%s.", type_desc); /* ...or maybe assert? */
6121 if (IS_PREF_OBSOLETE(type)) {
6122 type_desc = "An obsolete preference";
6124 RESET_PREF_OBSOLETE(type);
6130 switch (pref->info.base) {
6133 type_desc = "A decimal number";
6137 type_desc = "An octal number";
6141 type_desc = "A hexadecimal number";
6147 type_desc = "TRUE or FALSE (case-insensitive)";
6152 const enum_val_t *enum_valp = pref->info.enum_info.enumvals;
6153 GString *enum_str = g_string_new("One of: ");
6154 while (enum_valp->name != NULL) {
6155 g_string_append(enum_str, enum_valp->description);
6157 if (enum_valp->name != NULL)
6158 g_string_append(enum_str, ", ");
6160 g_string_append(enum_str, "\n(case-insensitive).");
6161 return g_string_free(enum_str, FALSE);
6165 type_desc = "A string";
6168 case PREF_SAVE_FILENAME:
6169 case PREF_OPEN_FILENAME:
6170 type_desc = "A path to a file";
6174 type_desc = "A path to a directory";
6179 type_desc = "A string denoting an positive integer range (e.g., \"1-20,30-40\")";
6185 type_desc = "A six-digit hexadecimal RGB color triplet (e.g. fce94f)";
6190 if (pref->custom_cbs.type_description_cb)
6191 return pref->custom_cbs.type_description_cb();
6192 type_desc = "A custom value";
6195 case PREF_DECODE_AS_UINT:
6196 type_desc = "An integer value used in Decode As";
6199 case PREF_DECODE_AS_RANGE:
6200 type_desc = "A string denoting an positive integer range for Decode As";
6203 case PREF_STATIC_TEXT:
6204 type_desc = "[Static text]";
6208 type_desc = "Configuration data stored in its own file";
6214 return g_strdup(type_desc);
6218 prefs_pref_is_default(pref_t *pref)
6221 if (!pref) return FALSE;
6224 if (IS_PREF_OBSOLETE(type)) {
6227 RESET_PREF_OBSOLETE(type);
6232 case PREF_DECODE_AS_UINT:
6233 if (pref->default_val.uint == *pref->varp.uint)
6238 if (pref->default_val.uint == *pref->varp.uint)
6243 if (pref->default_val.boolval == *pref->varp.boolp)
6248 if (pref->default_val.enumval == *pref->varp.enump)
6253 case PREF_SAVE_FILENAME:
6254 case PREF_OPEN_FILENAME:
6256 if (!(g_strcmp0(pref->default_val.string, *pref->varp.string)))
6260 case PREF_DECODE_AS_RANGE:
6263 if ((ranges_are_equal(pref->default_val.range, *pref->varp.range)))
6270 if ((pref->default_val.color.red == pref->varp.colorp->red) &&
6271 (pref->default_val.color.green == pref->varp.colorp->green) &&
6272 (pref->default_val.color.blue == pref->varp.colorp->blue))
6278 return pref->custom_cbs.is_default_cb(pref);
6280 case PREF_STATIC_TEXT:
6283 /* g_assert_not_reached(); */
6290 prefs_pref_to_str(pref_t *pref, pref_source_t source) {
6291 const char *pref_text = "[Unknown]";
6292 void *valp; /* pointer to preference value */
6293 color_t *pref_color;
6294 gchar *tmp_value, *ret_value;
6298 return g_strdup(pref_text);
6303 valp = &pref->default_val;
6304 /* valp = &boolval, &enumval, etc. are implied by union property */
6305 pref_color = &pref->default_val.color;
6308 valp = &pref->stashed_val;
6309 /* valp = &boolval, &enumval, etc. are implied by union property */
6310 pref_color = &pref->stashed_val.color;
6313 valp = pref->varp.uint;
6314 /* valp = boolval, enumval, etc. are implied by union property */
6315 pref_color = pref->varp.colorp;
6318 return g_strdup(pref_text);
6322 if (IS_PREF_OBSOLETE(type)) {
6323 pref_text = "[Obsolete]";
6325 RESET_PREF_OBSOLETE(type);
6330 case PREF_DECODE_AS_UINT:
6333 guint pref_uint = *(guint *) valp;
6334 switch (pref->info.base) {
6337 return g_strdup_printf("%u", pref_uint);
6340 return g_strdup_printf("%#o", pref_uint);
6343 return g_strdup_printf("%#x", pref_uint);
6349 return g_strdup((*(gboolean *) valp) ? "TRUE" : "FALSE");
6353 gint pref_enumval = *(gint *) valp;
6355 * For now, we return the "description" value, so that if we
6356 * save the preferences older versions of Wireshark can at
6357 * least read preferences that they supported; we support
6358 * either the short name or the description when reading
6359 * the preferences file or a "-o" option.
6361 const enum_val_t *enum_valp = pref->info.enum_info.enumvals;
6362 while (enum_valp->name != NULL) {
6363 if (enum_valp->value == pref_enumval)
6364 return g_strdup(enum_valp->description);
6371 case PREF_SAVE_FILENAME:
6372 case PREF_OPEN_FILENAME:
6374 return g_strdup(*(const char **) valp);
6376 case PREF_DECODE_AS_RANGE:
6378 /* Convert wmem to g_alloc memory */
6379 tmp_value = range_convert_range(NULL, *(range_t **) valp);
6380 ret_value = g_strdup(tmp_value);
6381 wmem_free(NULL, tmp_value);
6385 return g_strdup_printf("%02x%02x%02x",
6386 (pref_color->red * 255 / 65535),
6387 (pref_color->green * 255 / 65535),
6388 (pref_color->blue * 255 / 65535));
6391 if (pref->custom_cbs.to_str_cb)
6392 return pref->custom_cbs.to_str_cb(pref, source == pref_default ? TRUE : FALSE);
6393 pref_text = "[Custom]";
6396 case PREF_STATIC_TEXT:
6397 pref_text = "[Static text]";
6402 uat_t *uat = pref->varp.uat;
6403 if (uat && uat->filename)
6404 return g_strdup_printf("[Managed in the file \"%s\"]", uat->filename);
6406 pref_text = "[Managed in an unknown file]";
6413 return g_strdup(pref_text);
6417 * Write out a single dissector preference.
6420 write_pref(gpointer data, gpointer user_data)
6422 pref_t *pref = (pref_t *)data;
6423 write_pref_arg_t *arg = (write_pref_arg_t *)user_data;
6430 if (IS_PREF_OBSOLETE(type)) {
6432 * This preference is no longer supported; it's not a
6433 * real preference, so we don't write it out (i.e., we
6434 * treat it as if it weren't found in the list of
6435 * preferences, and we weren't called in the first place).
6439 RESET_PREF_OBSOLETE(type);
6444 case PREF_STATIC_TEXT:
6446 /* Nothing to do; don't bother printing the description */
6448 case PREF_DECODE_AS_UINT:
6449 case PREF_DECODE_AS_RANGE:
6450 /* Data is saved through Decode As mechanism and not part of preferences file */
6456 if (pref->type != PREF_CUSTOM || pref->custom_cbs.type_name_cb() != NULL) {
6458 * The prefix will either be the module name or the parent
6459 * name if it's a subtree
6461 const char *name_prefix = (arg->module->name != NULL) ? arg->module->name : arg->module->parent->name;
6462 char *type_desc, *pref_text;
6463 const char * def_prefix = prefs_pref_is_default(pref) ? "#" : "";
6465 if (pref->type == PREF_CUSTOM) fprintf(arg->pf, "\n# %s", pref->custom_cbs.type_name_cb());
6466 fprintf(arg->pf, "\n");
6467 if (pref->description &&
6468 (g_ascii_strncasecmp(pref->description,"", 2) != 0)) {
6469 if (pref->type != PREF_CUSTOM) {
6470 /* We get duplicate lines otherwise. */
6472 desc_lines = g_strsplit(pref->description,"\n",0);
6473 for (i = 0; desc_lines[i] != NULL; ++i) {
6474 fprintf(arg->pf, "# %s\n", desc_lines[i]);
6476 g_strfreev(desc_lines);
6479 fprintf(arg->pf, "# No description\n");
6482 type_desc = prefs_pref_type_description(pref);
6483 desc_lines = g_strsplit(type_desc,"\n",0);
6484 for (i = 0; desc_lines[i] != NULL; ++i) {
6485 fprintf(arg->pf, "# %s\n", desc_lines[i]);
6487 g_strfreev(desc_lines);
6490 pref_text = prefs_pref_to_str(pref, pref_current);
6491 fprintf(arg->pf, "%s%s.%s: ", def_prefix, name_prefix, pref->name);
6492 desc_lines = g_strsplit(pref_text,"\n",0);
6493 for (i = 0; desc_lines[i] != NULL; ++i) {
6494 fprintf(arg->pf, "%s%s\n", i == 0 ? "" : def_prefix, desc_lines[i]);
6496 if (i == 0) fprintf(arg->pf, "\n");
6497 g_strfreev(desc_lines);
6504 count_non_uat_pref(gpointer data, gpointer user_data)
6506 pref_t *pref = (pref_t *)data;
6507 int *arg = (int *)user_data;
6513 case PREF_DECODE_AS_UINT:
6514 case PREF_DECODE_AS_RANGE:
6515 //These types are not written in preference file
6523 static int num_non_uat_prefs(module_t *module)
6527 g_list_foreach(module->prefs, count_non_uat_pref, &num);
6533 * Write out all preferences for a module.
6536 write_module_prefs(module_t *module, gpointer user_data)
6538 write_gui_pref_arg_t *gui_pref_arg = (write_gui_pref_arg_t*)user_data;
6539 write_pref_arg_t arg;
6541 /* The GUI module needs to be explicitly called out so it
6542 can be written out of order */
6543 if ((module == gui_module) && (gui_pref_arg->is_gui_module != TRUE))
6546 /* Write a header for the main modules and GUI sub-modules */
6547 if (((module->parent == NULL) || (module->parent == gui_module)) &&
6548 ((prefs_module_has_submodules(module)) ||
6549 (num_non_uat_prefs(module) > 0) ||
6550 (module->name == NULL))) {
6551 if ((module->name == NULL) && (module->parent != NULL)) {
6552 fprintf(gui_pref_arg->pf, "\n####### %s: %s ########\n", module->parent->title, module->title);
6554 fprintf(gui_pref_arg->pf, "\n####### %s ########\n", module->title);
6558 arg.module = module;
6559 arg.pf = gui_pref_arg->pf;
6560 g_list_foreach(arg.module->prefs, write_pref, &arg);
6562 if (prefs_module_has_submodules(module))
6563 return prefs_modules_foreach_submodules(module, write_module_prefs, user_data);
6568 /* Write out "prefs" to the user's preferences file, and return 0.
6570 If the preferences file path is NULL, write to stdout.
6572 If we got an error, stuff a pointer to the path of the preferences file
6573 into "*pf_path_return", and return the errno. */
6575 write_prefs(char **pf_path_return)
6579 write_gui_pref_arg_t write_gui_pref_info;
6581 /* Needed for "-G defaultprefs" */
6585 * - Split output lines longer than MAX_VAL_LEN
6586 * - Create a function for the preference directory check/creation
6587 * so that duplication can be avoided with filter.c
6590 if (pf_path_return != NULL) {
6591 pf_path = get_persconffile_path(PF_NAME, TRUE);
6592 if ((pf = ws_fopen(pf_path, "w")) == NULL) {
6593 *pf_path_return = pf_path;
6602 * If the preferences file is being written, be sure to write UAT files
6603 * first that were migrated from the preferences file.
6605 if (pf_path_return != NULL) {
6606 if (prefs.filter_expressions_old) {
6608 prefs.filter_expressions_old = FALSE;
6609 if (!uat_save(uat_get_table_by_name("Display expressions"), &err)) {
6610 g_warning("Unable to save Display expressions: %s", err);
6616 fputs("# Configuration file for Wireshark " VERSION ".\n"
6618 "# This file is regenerated each time preferences are saved within\n"
6619 "# Wireshark. Making manual changes should be safe, however.\n"
6620 "# Preferences that have been commented out have not been\n"
6621 "# changed from their default value.\n", pf);
6624 * For "backwards compatibility" the GUI module is written first as it's
6625 * at the top of the file. This is followed by all modules that can't
6626 * fit into the preferences read/write API. Finally the remaining modules
6627 * are written in alphabetical order (including of course the protocol preferences)
6629 write_gui_pref_info.pf = pf;
6630 write_gui_pref_info.is_gui_module = TRUE;
6632 write_module_prefs(gui_module, &write_gui_pref_info);
6634 write_gui_pref_info.is_gui_module = FALSE;
6635 prefs_modules_foreach_submodules(NULL, write_module_prefs, &write_gui_pref_info);
6639 /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
6640 an error indication, or maybe write to a new preferences file and
6641 rename that file on top of the old one only if there are not I/O
6646 /** The col_list is only partly managed by the custom preference API
6647 * because its data is shared between multiple preferences, so
6651 free_col_info(GList *list)
6654 GList *list_head = list;
6656 while (list != NULL) {
6657 cfmt = (fmt_data *)list->data;
6659 g_free(cfmt->title);
6660 g_free(cfmt->custom_fields);
6662 list = g_list_next(list);
6664 g_list_free(list_head);
6673 * indent-tabs-mode: nil
6676 * ex: set shiftwidth=4 tabstop=8 expandtab:
6677 * :indentSize=4:tabSize=8:noTabs=true: