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+
20 #include <wsutil/filesystem.h>
21 #include <epan/address.h>
22 #include <epan/addr_resolv.h>
23 #include <epan/oids.h>
25 #include <epan/geoip_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/ws_printf.h> /* ws_g_warning */
36 #include <wsutil/report_message.h>
38 #include <epan/prefs-int.h>
39 #include <epan/uat-int.h>
41 #include "epan/filter_expressions.h"
43 #include "epan/wmem/wmem.h"
44 #include <epan/stats_tree.h>
46 /* Internal functions */
47 static module_t *find_subtree(module_t *parent, const char *tilte);
48 static module_t *prefs_register_module_or_subtree(module_t *parent,
49 const char *name, const char *title, const char *description, gboolean is_subtree,
50 void (*apply_cb)(void), gboolean use_gui);
51 static void prefs_register_modules(void);
52 static prefs_set_pref_e set_pref(gchar*, const gchar*, void *, gboolean);
53 static void free_col_info(GList *);
54 static void pre_init_prefs(void);
55 static gboolean prefs_is_column_visible(const gchar *cols_hidden, fmt_data *cfmt);
56 static gboolean parse_column_format(fmt_data *cfmt, const char *fmt);
57 static void try_convert_to_custom_column(gpointer *el_data);
58 static guint prefs_module_list_foreach(wmem_tree_t *module_list, module_cb callback,
59 gpointer user_data, gboolean skip_obsolete);
61 #define IS_PREF_OBSOLETE(p) ((p) & PREF_OBSOLETE)
62 #define SET_PREF_OBSOLETE(p) ((p) |= PREF_OBSOLETE)
63 #define RESET_PREF_OBSOLETE(p) ((p) &= ~PREF_OBSOLETE)
65 #define PF_NAME "preferences"
66 #define OLD_GPF_NAME "wireshark.conf" /* old name for global preferences file */
68 static gboolean prefs_initialized = FALSE;
69 static gchar *gpf_path = NULL;
70 static gchar *cols_hidden_list = NULL;
71 static gboolean gui_theme_is_dark = FALSE;
74 * XXX - variables to allow us to attempt to interpret the first
75 * "mgcp.{tcp,udp}.port" in a preferences file as
76 * "mgcp.{tcp,udp}.gateway_port" and the second as
77 * "mgcp.{tcp,udp}.callagent_port".
79 static int mgcp_tcp_port_count;
80 static int mgcp_udp_port_count;
84 static const enum_val_t gui_ptree_line_style[] = {
86 {"SOLID", "SOLID", 1},
87 {"DOTTED", "DOTTED", 2},
88 {"TABBED", "TABBED", 3},
92 static const enum_val_t gui_ptree_expander_style[] = {
94 {"SQUARE", "SQUARE", 1},
95 {"TRIANGLE", "TRIANGLE", 2},
96 {"CIRCULAR", "CIRCULAR", 3},
101 static const enum_val_t gui_hex_dump_highlight_style[] = {
103 {"INVERSE", "INVERSE", 1},
107 static const enum_val_t gui_console_open_type[] = {
108 {"NEVER", "NEVER", console_open_never},
109 {"AUTOMATIC", "AUTOMATIC", console_open_auto},
110 {"ALWAYS", "ALWAYS", console_open_always},
114 static const enum_val_t gui_version_placement_type[] = {
115 {"WELCOME", "WELCOME", version_welcome_only},
116 {"TITLE", "TITLE", version_title_only},
117 {"BOTH", "BOTH", version_both},
118 {"NEITHER", "NEITHER", version_neither},
122 static const enum_val_t gui_fileopen_style[] = {
123 {"LAST_OPENED", "LAST_OPENED", 0},
124 {"SPECIFIED", "SPECIFIED", 1},
128 /* GTK knows of two ways representing "both", vertical and horizontal aligned.
129 * as this may not work on other guis, we use only "both" in general here */
130 static const enum_val_t gui_toolbar_style[] = {
131 {"ICONS", "ICONS", 0},
137 static const enum_val_t gui_layout_content[] = {
139 {"PLIST", "PLIST", 1},
140 {"PDETAILS", "PDETAILS", 2},
141 {"PBYTES", "PBYTES", 3},
145 static const enum_val_t gui_update_channel[] = {
146 {"DEVELOPMENT", "DEVELOPMENT", UPDATE_CHANNEL_DEVELOPMENT},
147 {"STABLE", "STABLE", UPDATE_CHANNEL_STABLE},
151 #if defined(HAVE_PCAP_CREATE)
152 /* Can set monitor mode and buffer size. */
153 static gint num_capture_cols = 7;
154 static const gchar *capture_cols[7] = {
163 #define CAPTURE_COL_TYPE_DESCRIPTION \
164 "Possible values: INTERFACE, LINK, PMODE, SNAPLEN, MONITOR, BUFFER, FILTER\n"
165 #elif defined(CAN_SET_CAPTURE_BUFFER_SIZE)
166 /* Can set buffer size but not monitor mode. */
167 static gint num_capture_cols = 6;
168 static const gchar *capture_cols[6] = {
176 #define CAPTURE_COL_TYPE_DESCRIPTION \
177 "Possible values: INTERFACE, LINK, PMODE, SNAPLEN, BUFFER, FILTER\n"
179 /* Can neither set buffer size nor monitor mode. */
180 static gint num_capture_cols = 5;
181 static const gchar *capture_cols[5] = {
188 #define CAPTURE_COL_TYPE_DESCRIPTION \
189 "Possible values: INTERFACE, LINK, PMODE, SNAPLEN, FILTER\n"
192 static const enum_val_t gui_packet_list_elide_mode[] = {
193 {"LEFT", "LEFT", ELIDE_LEFT},
194 {"RIGHT", "RIGHT", ELIDE_RIGHT},
195 {"MIDDLE", "MIDDLE", ELIDE_MIDDLE},
196 {"NONE", "NONE", ELIDE_NONE},
200 /** Struct to hold preference data */
202 const char *name; /**< name of preference */
203 const char *title; /**< title to use in GUI */
204 const char *description; /**< human-readable description of preference */
205 int ordinal; /**< ordinal number of this preference */
206 int type; /**< type of that preference */
207 unsigned int effect_flags; /**< Flags of types effected by preference (PREF_TYPE_DISSECTION, PREF_EFFECT_CAPTURE, etc).
208 Flags must be non-zero to ensure saving to disk */
209 gui_type_t gui; /**< type of the GUI (QT, GTK or both) the preference is registered for */
210 union { /* The Qt preference code assumes that these will all be pointers (and unique) */
216 struct epan_uat* uat;
219 } varp; /**< pointer to variable storing the value */
228 } stashed_val; /**< original value, when editing from the GUI */
237 } default_val; /**< the default value of the preference */
239 guint base; /**< input/output base, for PREF_UINT */
240 guint32 max_value; /**< maximum value of a range */
242 const enum_val_t *enumvals; /**< list of name & values */
243 gboolean radio_buttons; /**< TRUE if it should be shown as
244 radio buttons rather than as an
245 option menu or combo box in
246 the preferences tab */
247 } enum_info; /**< for PREF_ENUM */
248 } info; /**< display/text file information */
249 struct pref_custom_cbs custom_cbs; /**< for PREF_CUSTOM */
250 void *control; /**< handle for GUI control for this preference. GTK+ only? */
253 const char* prefs_get_description(pref_t *pref)
255 return pref->description;
258 const char* prefs_get_title(pref_t *pref)
263 int prefs_get_type(pref_t *pref)
268 gui_type_t prefs_get_gui_type(pref_t *pref)
273 const char* prefs_get_name(pref_t *pref)
278 guint32 prefs_get_max_value(pref_t *pref)
280 return pref->info.max_value;
283 void* prefs_get_control(pref_t *pref)
285 return pref->control;
288 void prefs_set_control(pref_t *pref, void* control)
290 pref->control = control;
293 int prefs_get_ordinal(pref_t *pref)
295 return pref->ordinal;
299 * List of all modules with preference settings.
301 static wmem_tree_t *prefs_modules = NULL;
304 * List of all modules that should show up at the top level of the
305 * tree in the preference dialog box.
307 static wmem_tree_t *prefs_top_level_modules = NULL;
309 /** Sets up memory used by proto routines. Called at program startup */
313 memset(&prefs, 0, sizeof(prefs));
314 prefs_modules = wmem_tree_new(wmem_epan_scope());
315 prefs_top_level_modules = wmem_tree_new(wmem_epan_scope());
319 * Free the strings for a string-like preference.
322 free_string_like_preference(pref_t *pref)
324 g_free(*pref->varp.string);
325 *pref->varp.string = NULL;
326 g_free(pref->default_val.string);
327 pref->default_val.string = NULL;
331 free_pref(gpointer data, gpointer user_data _U_)
333 pref_t *pref = (pref_t *)data;
334 int type = pref->type;
336 /* we reset the PREF_OBSOLETE bit in order to allow the original preference to be freed */
337 RESET_PREF_OBSOLETE(type);
343 case PREF_DECODE_AS_UINT:
344 case PREF_STATIC_TEXT:
349 case PREF_SAVE_FILENAME:
350 case PREF_OPEN_FILENAME:
352 g_free(*pref->varp.string);
353 *pref->varp.string = NULL;
354 g_free(pref->default_val.string);
355 pref->default_val.string = NULL;
358 case PREF_DECODE_AS_RANGE:
359 wmem_free(wmem_epan_scope(), *pref->varp.range);
360 *pref->varp.range = NULL;
361 wmem_free(wmem_epan_scope(), pref->default_val.range);
362 pref->default_val.range = NULL;
365 if (strcmp(pref->name, "columns") == 0)
366 pref->stashed_val.boolval = TRUE;
367 pref->custom_cbs.free_cb(pref);
375 free_module_prefs(module_t *module, gpointer data _U_)
378 g_list_foreach(module->prefs, free_pref, NULL);
379 g_list_free(module->prefs);
381 module->prefs = NULL;
382 module->numprefs = 0;
383 if (module->submodules) {
384 prefs_module_list_foreach(module->submodules, free_module_prefs, NULL, FALSE);
386 /* We don't free the actual module: its submodules pointer points to
387 a wmem_tree and the module itself is stored in a wmem_tree
393 /** Frees memory used by proto routines. Called at program shutdown */
397 /* This isn't strictly necessary since we're exiting anyway, but let's
398 * do what clean up we can.
400 prefs_module_list_foreach(prefs_modules, free_module_prefs, NULL, FALSE);
405 g_free(prefs.saved_at_version);
410 void prefs_set_gui_theme_is_dark(gboolean is_dark)
412 gui_theme_is_dark = is_dark;
416 * Register a module that will have preferences.
417 * Specify the module under which to register it or NULL to register it
418 * at the top level, the name used for the module in the preferences file,
419 * the title used in the tab for it in a preferences dialog box, and a
420 * routine to call back when we apply the preferences.
423 prefs_register_module(module_t *parent, const char *name, const char *title,
424 const char *description, void (*apply_cb)(void),
425 const gboolean use_gui)
427 return prefs_register_module_or_subtree(parent, name, title, description,
428 FALSE, apply_cb, use_gui);
432 prefs_deregister_module(module_t *parent, const char *name, const char *title)
434 /* Remove this module from the list of all modules */
435 module_t *module = (module_t *)wmem_tree_remove_string(prefs_modules, name, WMEM_TREE_STRING_NOCASE);
440 if (parent == NULL) {
441 /* Remove from top */
442 wmem_tree_remove_string(prefs_top_level_modules, title, WMEM_TREE_STRING_NOCASE);
443 } else if (parent->submodules) {
444 /* Remove from parent */
445 wmem_tree_remove_string(parent->submodules, title, WMEM_TREE_STRING_NOCASE);
448 free_module_prefs(module, NULL);
449 wmem_free(wmem_epan_scope(), module);
453 * Register a subtree that will have modules under it.
454 * Specify the module under which to register it or NULL to register it
455 * at the top level and the title used in the tab for it in a preferences
459 prefs_register_subtree(module_t *parent, const char *title, const char *description,
460 void (*apply_cb)(void))
462 return prefs_register_module_or_subtree(parent, NULL, title, description,
464 parent ? parent->use_gui : FALSE);
468 prefs_register_module_or_subtree(module_t *parent, const char *name,
469 const char *title, const char *description,
470 gboolean is_subtree, void (*apply_cb)(void),
477 /* this module may have been created as a subtree item previously */
478 if ((module = find_subtree(parent, title))) {
479 /* the module is currently a subtree */
481 module->apply_cb = apply_cb;
482 module->description = description;
484 if (prefs_find_module(name) == NULL) {
485 wmem_tree_insert_string(prefs_modules, name, module,
486 WMEM_TREE_STRING_NOCASE);
492 module = wmem_new(wmem_epan_scope(), module_t);
494 module->title = title;
495 module->description = description;
496 module->apply_cb = apply_cb;
497 module->prefs = NULL; /* no preferences, to start */
498 module->parent = parent;
499 module->submodules = NULL; /* no submodules, to start */
500 module->numprefs = 0;
501 module->prefs_changed_flags = 0;
502 module->obsolete = FALSE;
503 module->use_gui = use_gui;
504 /* A module's preferences affects dissection unless otherwise told */
505 module->effect_flags = PREF_EFFECT_DISSECTION;
508 * Do we have a module name?
513 * Make sure that only lower-case ASCII letters, numbers,
514 * underscores, hyphens, and dots appear in the name.
516 * Crash if there is, as that's an error in the code;
517 * you can make the title a nice string with capitalization,
518 * white space, punctuation, etc., but the name can be used
519 * on the command line, and shouldn't require quoting,
522 for (p = name; (c = *p) != '\0'; p++) {
523 if (!(g_ascii_islower(c) || g_ascii_isdigit(c) || c == '_' ||
524 c == '-' || c == '.'))
525 g_error("Preference module \"%s\" contains invalid characters", name);
529 * Make sure there's not already a module with that
530 * name. Crash if there is, as that's an error in the
531 * code, and the code has to be fixed not to register
532 * more than one module with the same name.
534 * We search the list of all modules; the subtree stuff
535 * doesn't require preferences in subtrees to have names
536 * that reflect the subtree they're in (that would require
537 * protocol preferences to have a bogus "protocol.", or
538 * something such as that, to be added to all their names).
540 g_assert(prefs_find_module(name) == NULL);
543 * Insert this module in the list of all modules.
545 wmem_tree_insert_string(prefs_modules, name, module, WMEM_TREE_STRING_NOCASE);
548 * This has no name, just a title; check to make sure it's a
549 * subtree, and crash if it's not.
551 g_assert(is_subtree);
555 * Insert this module into the appropriate place in the display
558 if (parent == NULL) {
560 * It goes at the top.
562 wmem_tree_insert_string(prefs_top_level_modules, title, module, WMEM_TREE_STRING_NOCASE);
565 * It goes into the list for this module.
568 if (parent->submodules == NULL)
569 parent->submodules = wmem_tree_new(wmem_epan_scope());
571 wmem_tree_insert_string(parent->submodules, title, module, WMEM_TREE_STRING_NOCASE);
578 * Register that a protocol has preferences.
580 module_t *protocols_module = NULL;
583 prefs_register_protocol(int id, void (*apply_cb)(void))
585 protocol_t *protocol;
588 * Have we yet created the "Protocols" subtree?
590 if (protocols_module == NULL) {
592 * No. Register Protocols subtree as well as any preferences
593 * for non-dissector modules.
596 prefs_register_modules();
598 protocol = find_protocol_by_id(id);
599 if (protocol == NULL)
600 g_error("Protocol preferences being registered with an invalid protocol ID");
601 return prefs_register_module(protocols_module,
602 proto_get_protocol_filter_name(id),
603 proto_get_protocol_short_name(protocol),
604 proto_get_protocol_name(id), apply_cb, TRUE);
608 prefs_deregister_protocol (int id)
610 protocol_t *protocol = find_protocol_by_id(id);
611 if (protocol == NULL)
612 g_error("Protocol preferences being de-registered with an invalid protocol ID");
613 prefs_deregister_module (protocols_module,
614 proto_get_protocol_filter_name(id),
615 proto_get_protocol_short_name(protocol));
619 prefs_register_protocol_subtree(const char *subtree, int id, void (*apply_cb)(void))
621 protocol_t *protocol;
622 module_t *subtree_module;
623 module_t *new_module;
624 char *sep = NULL, *ptr = NULL, *orig = NULL;
627 * Have we yet created the "Protocols" subtree?
628 * XXX - can we just do this by registering Protocols/{subtree}?
631 if (protocols_module == NULL) {
633 * No. Register Protocols subtree as well as any preferences
634 * for non-dissector modules.
637 prefs_register_modules();
640 subtree_module = protocols_module;
643 /* take a copy of the buffer, orig keeps a base pointer while ptr
644 * walks through the string */
645 orig = ptr = g_strdup(subtree);
647 while (ptr && *ptr) {
649 if ((sep = strchr(ptr, '/')))
652 if (!(new_module = find_subtree(subtree_module, ptr))) {
654 * There's no such module; create it, with the description
655 * being the name (if it's later registered explicitly
656 * with a description, that will override it).
658 ptr = wmem_strdup(wmem_epan_scope(), ptr);
659 new_module = prefs_register_subtree(subtree_module, ptr, ptr, NULL);
662 subtree_module = new_module;
670 protocol = find_protocol_by_id(id);
671 if (protocol == NULL)
672 g_error("Protocol subtree being registered with an invalid protocol ID");
673 return prefs_register_module(subtree_module,
674 proto_get_protocol_filter_name(id),
675 proto_get_protocol_short_name(protocol),
676 proto_get_protocol_name(id), apply_cb, TRUE);
681 * Register that a protocol used to have preferences but no longer does,
682 * by creating an "obsolete" module for it.
685 prefs_register_protocol_obsolete(int id)
688 protocol_t *protocol;
691 * Have we yet created the "Protocols" subtree?
693 if (protocols_module == NULL) {
695 * No. Register Protocols subtree as well as any preferences
696 * for non-dissector modules.
699 prefs_register_modules();
701 protocol = find_protocol_by_id(id);
702 if (protocol == NULL)
703 g_error("Protocol being registered with an invalid protocol ID");
704 module = prefs_register_module(protocols_module,
705 proto_get_protocol_filter_name(id),
706 proto_get_protocol_short_name(protocol),
707 proto_get_protocol_name(id), NULL, TRUE);
708 module->obsolete = TRUE;
713 * Register that a statistical tap has preferences.
715 * "name" is a name for the tap to use on the command line with "-o"
716 * and in preference files.
718 * "title" is a short human-readable name for the tap.
720 * "description" is a longer human-readable description of the tap.
722 module_t *stats_module = NULL;
725 prefs_register_stat(const char *name, const char *title,
726 const char *description, void (*apply_cb)(void))
729 * Have we yet created the "Statistics" subtree?
731 if (stats_module == NULL) {
733 * No. Register Statistics subtree as well as any preferences
734 * for non-dissector modules.
737 prefs_register_modules();
740 return prefs_register_module(stats_module, name, title, description,
745 * Register that a codec has preferences.
747 * "name" is a name for the codec to use on the command line with "-o"
748 * and in preference files.
750 * "title" is a short human-readable name for the codec.
752 * "description" is a longer human-readable description of the codec.
754 module_t *codecs_module = NULL;
757 prefs_register_codec(const char *name, const char *title,
758 const char *description, void (*apply_cb)(void))
761 * Have we yet created the "Codecs" subtree?
763 if (codecs_module == NULL) {
765 * No. Register Codecs subtree as well as any preferences
766 * for non-dissector modules.
769 prefs_register_modules();
772 return prefs_register_module(codecs_module, name, title, description,
777 prefs_find_module(const char *name)
779 return (module_t *)wmem_tree_lookup_string(prefs_modules, name, WMEM_TREE_STRING_NOCASE);
783 find_subtree(module_t *parent, const char *name)
785 return (module_t *)wmem_tree_lookup_string(parent ? parent->submodules : prefs_top_level_modules, name, WMEM_TREE_STRING_NOCASE);
789 * Call a callback function, with a specified argument, for each module
790 * in a list of modules. If the list is NULL, searches the top-level
791 * list in the display tree of modules. If any callback returns a
792 * non-zero value, we stop and return that value, otherwise we
795 * Normally "obsolete" modules are ignored; their sole purpose is to allow old
796 * preferences for dissectors that no longer have preferences to be
797 * silently ignored in preference files. Does not ignore subtrees,
798 * as this can be used when walking the display tree of modules.
805 gboolean skip_obsolete;
809 call_foreach_cb(const void *key _U_, void *value, void *data)
811 module_t *module = (module_t*)value;
812 call_foreach_t *call_data = (call_foreach_t*)data;
814 if (!call_data->skip_obsolete || !module->obsolete)
815 call_data->ret = (*call_data->callback)(module, call_data->user_data);
817 return (call_data->ret != 0);
821 prefs_module_list_foreach(wmem_tree_t *module_list, module_cb callback,
822 gpointer user_data, gboolean skip_obsolete)
824 call_foreach_t call_data;
826 if (module_list == NULL)
827 module_list = prefs_top_level_modules;
829 call_data.callback = callback;
830 call_data.user_data = user_data;
832 call_data.skip_obsolete = skip_obsolete;
833 wmem_tree_foreach(module_list, call_foreach_cb, &call_data);
834 return call_data.ret;
838 * Returns TRUE if module has any submodules
841 prefs_module_has_submodules(module_t *module)
843 if (module->submodules == NULL) {
847 if (wmem_tree_is_empty(module->submodules)) {
855 * Call a callback function, with a specified argument, for each module
856 * in the list of all modules. (This list does not include subtrees.)
858 * Ignores "obsolete" modules; their sole purpose is to allow old
859 * preferences for dissectors that no longer have preferences to be
860 * silently ignored in preference files.
863 prefs_modules_foreach(module_cb callback, gpointer user_data)
865 return prefs_module_list_foreach(prefs_modules, callback, user_data, TRUE);
869 * Call a callback function, with a specified argument, for each submodule
870 * of specified modules. If the module is NULL, goes through the top-level
871 * list in the display tree of modules.
873 * Ignores "obsolete" modules; their sole purpose is to allow old
874 * preferences for dissectors that no longer have preferences to be
875 * silently ignored in preference files. Does not ignore subtrees,
876 * as this can be used when walking the display tree of modules.
879 prefs_modules_foreach_submodules(module_t *module, module_cb callback,
882 return prefs_module_list_foreach((module)?module->submodules:prefs_top_level_modules, callback, user_data, TRUE);
886 call_apply_cb(const void *key _U_, void *value, void *data _U_)
888 module_t *module = (module_t *)value;
890 if (module->obsolete)
892 if (module->prefs_changed_flags) {
893 if (module->apply_cb != NULL)
894 (*module->apply_cb)();
895 module->prefs_changed_flags = 0;
897 if (module->submodules)
898 wmem_tree_foreach(module->submodules, call_apply_cb, NULL);
903 * Call the "apply" callback function for each module if any of its
904 * preferences have changed, and then clear the flag saying its
905 * preferences have changed, as the module has been notified of that
909 prefs_apply_all(void)
911 wmem_tree_foreach(prefs_modules, call_apply_cb, NULL);
915 * Call the "apply" callback function for a specific module if any of
916 * its preferences have changed, and then clear the flag saying its
917 * preferences have changed, as the module has been notified of that
921 prefs_apply(module_t *module)
923 if (module && module->prefs_changed_flags)
924 call_apply_cb(NULL, module, NULL);
928 * Register a preference in a module's list of preferences.
929 * If it has a title, give it an ordinal number; otherwise, it's a
930 * preference that won't show up in the UI, so it shouldn't get an
931 * ordinal number (the ordinal should be the ordinal in the set of
932 * *visible* preferences).
935 register_preference(module_t *module, const char *name, const char *title,
936 const char *description, int type)
940 const char *name_prefix = (module->name != NULL) ? module->name : module->parent->name;
942 preference = g_new(pref_t,1);
943 preference->name = name;
944 preference->title = title;
945 preference->description = description;
946 preference->type = type;
947 /* Default to module's preference effects */
948 preference->effect_flags = module->effect_flags;
950 preference->gui = GUI_ALL; /* default */
952 preference->ordinal = module->numprefs;
954 preference->ordinal = -1; /* no ordinal for you */
957 * Make sure that only lower-case ASCII letters, numbers,
958 * underscores, and dots appear in the preference name.
960 * Crash if there is, as that's an error in the code;
961 * you can make the title and description nice strings
962 * with capitalization, white space, punctuation, etc.,
963 * but the name can be used on the command line,
964 * and shouldn't require quoting, shifting, etc.
966 for (p = name; *p != '\0'; p++)
967 if (!(g_ascii_islower(*p) || g_ascii_isdigit(*p) || *p == '_' || *p == '.'))
968 g_error("Preference \"%s.%s\" contains invalid characters", module->name, name);
971 * Make sure there's not already a preference with that
972 * name. Crash if there is, as that's an error in the
973 * code, and the code has to be fixed not to register
974 * more than one preference with the same name.
976 if (prefs_find_preference(module, name) != NULL)
977 g_error("Preference %s has already been registered", name);
979 if ((!IS_PREF_OBSOLETE(type)) &&
980 /* Don't compare if it's a subtree */
981 (module->name != NULL)) {
983 * Make sure the preference name doesn't begin with the
984 * module name, as that's redundant and Just Silly.
986 if (!((strncmp(name, module->name, strlen(module->name)) != 0) ||
987 (((name[strlen(module->name)]) != '.') && ((name[strlen(module->name)]) != '_'))))
988 g_error("Preference %s begins with the module name", name);
991 /* The title shows up in the preferences dialog. Make sure it's UI-friendly. */
992 if (preference->title) {
993 const char *cur_char;
994 if (preference->type != PREF_STATIC_TEXT && g_utf8_strlen(preference->title, -1) > 80) { // Arbitrary.
995 g_error("Title for preference %s.%s is too long: %s", name_prefix, preference->name, preference->title);
998 if (!g_utf8_validate(preference->title, -1, NULL)) {
999 g_error("Title for preference %s.%s isn't valid UTF-8.", name_prefix, preference->name);
1002 for (cur_char = preference->title; *cur_char; cur_char = g_utf8_next_char(cur_char)) {
1003 if (!g_unichar_isprint(g_utf8_get_char(cur_char))) {
1004 g_error("Title for preference %s.%s isn't printable UTF-8.", name_prefix, preference->name);
1009 if (preference->description) {
1010 if (!g_utf8_validate(preference->description, -1, NULL)) {
1011 g_error("Description for preference %s.%s isn't valid UTF-8.", name_prefix, preference->name);
1016 * We passed all of our checks. Add the preference.
1018 module->prefs = g_list_append(module->prefs, preference);
1026 * Find a preference in a module's list of preferences, given the module
1027 * and the preference's name.
1032 module_t *submodule;
1036 preference_match(gconstpointer a, gconstpointer b)
1038 const pref_t *pref = (const pref_t *)a;
1039 const char *name = (const char *)b;
1041 return strcmp(name, pref->name);
1045 module_find_pref_cb(const void *key _U_, void *value, void *data)
1047 find_pref_arg_t* arg = (find_pref_arg_t*)data;
1049 module_t *module = (module_t *)value;
1054 list_entry = g_list_find_custom(module->prefs, arg->name,
1057 if (list_entry == NULL)
1060 arg->list_entry = list_entry;
1061 arg->submodule = module;
1065 /* Tries to find a preference, setting containing_module to the (sub)module
1066 * holding this preference. */
1067 static struct preference *
1068 prefs_find_preference_with_submodule(module_t *module, const char *name,
1069 module_t **containing_module)
1071 find_pref_arg_t arg;
1075 return NULL; /* invalid parameters */
1077 list_entry = g_list_find_custom(module->prefs, name,
1079 arg.submodule = NULL;
1081 if (list_entry == NULL)
1083 arg.list_entry = NULL;
1084 if (module->submodules != NULL)
1087 wmem_tree_foreach(module->submodules, module_find_pref_cb, &arg);
1090 list_entry = arg.list_entry;
1093 if (list_entry == NULL)
1094 return NULL; /* no such preference */
1096 if (containing_module)
1097 *containing_module = arg.submodule ? arg.submodule : module;
1099 return (struct preference *) list_entry->data;
1103 prefs_find_preference(module_t *module, const char *name)
1105 return prefs_find_preference_with_submodule(module, name, NULL);
1109 * Returns TRUE if the given protocol has registered preferences
1112 prefs_is_registered_protocol(const char *name)
1114 module_t *m = prefs_find_module(name);
1116 return (m != NULL && !m->obsolete);
1120 * Returns the module title of a registered protocol
1123 prefs_get_title_by_name(const char *name)
1125 module_t *m = prefs_find_module(name);
1127 return (m != NULL && !m->obsolete) ? m->title : NULL;
1131 * Register a preference with an unsigned integral value.
1134 prefs_register_uint_preference(module_t *module, const char *name,
1135 const char *title, const char *description,
1136 guint base, guint *var)
1140 preference = register_preference(module, name, title, description,
1142 preference->varp.uint = var;
1143 preference->default_val.uint = *var;
1144 g_assert(base > 0 && base != 1 && base < 37);
1145 preference->info.base = base;
1149 * XXX Add a prefs_register_{uint16|port}_preference which sets max_value?
1154 * Register a "custom" preference with a unsigned integral value.
1155 * XXX - This should be temporary until we can find a better way
1156 * to do "custom" preferences
1159 prefs_register_uint_custom_preference(module_t *module, const char *name,
1160 const char *title, const char *description,
1161 struct pref_custom_cbs* custom_cbs, guint *var)
1165 preference = register_preference(module, name, title, description,
1168 preference->custom_cbs = *custom_cbs;
1169 preference->varp.uint = var;
1170 preference->default_val.uint = *var;
1174 * Register a preference with an Boolean value.
1177 prefs_register_bool_preference(module_t *module, const char *name,
1178 const char *title, const char *description,
1183 preference = register_preference(module, name, title, description,
1185 preference->varp.boolp = var;
1186 preference->default_val.boolval = *var;
1189 unsigned int prefs_set_bool_value(pref_t *pref, gboolean value, pref_source_t source)
1191 unsigned int changed = 0;
1196 if (pref->default_val.boolval != value) {
1197 pref->default_val.boolval = value;
1198 changed = prefs_get_effect_flags(pref);
1202 if (pref->stashed_val.boolval != value) {
1203 pref->stashed_val.boolval = value;
1204 changed = prefs_get_effect_flags(pref);
1208 if (*pref->varp.boolp != value) {
1209 *pref->varp.boolp = value;
1210 changed = prefs_get_effect_flags(pref);
1214 g_assert_not_reached();
1221 void prefs_invert_bool_value(pref_t *pref, pref_source_t source)
1226 pref->default_val.boolval = !pref->default_val.boolval;
1229 pref->stashed_val.boolval = !pref->stashed_val.boolval;
1232 *pref->varp.boolp = !(*pref->varp.boolp);
1235 g_assert_not_reached();
1240 gboolean prefs_get_bool_value(pref_t *pref, pref_source_t source)
1245 return pref->default_val.boolval;
1248 return pref->stashed_val.boolval;
1251 return *pref->varp.boolp;
1254 g_assert_not_reached();
1262 * Register a preference with an enumerated value.
1265 * XXX Should we get rid of the radio_buttons parameter and make that
1266 * behavior automatic depending on the number of items?
1269 prefs_register_enum_preference(module_t *module, const char *name,
1270 const char *title, const char *description,
1271 gint *var, const enum_val_t *enumvals,
1272 gboolean radio_buttons)
1276 preference = register_preference(module, name, title, description,
1278 preference->varp.enump = var;
1279 preference->default_val.enumval = *var;
1280 preference->info.enum_info.enumvals = enumvals;
1281 preference->info.enum_info.radio_buttons = radio_buttons;
1284 unsigned int prefs_set_enum_value(pref_t *pref, gint value, pref_source_t source)
1286 unsigned int changed = 0;
1291 if (pref->default_val.enumval != value) {
1292 pref->default_val.enumval = value;
1293 changed = prefs_get_effect_flags(pref);
1297 if (pref->stashed_val.enumval != value) {
1298 pref->stashed_val.enumval = value;
1299 changed = prefs_get_effect_flags(pref);
1303 if (*pref->varp.enump != value) {
1304 *pref->varp.enump = value;
1305 changed = prefs_get_effect_flags(pref);
1309 g_assert_not_reached();
1316 gint prefs_get_enum_value(pref_t *pref, pref_source_t source)
1321 return pref->default_val.enumval;
1324 return pref->stashed_val.enumval;
1327 return *pref->varp.enump;
1330 g_assert_not_reached();
1337 const enum_val_t* prefs_get_enumvals(pref_t *pref)
1339 return pref->info.enum_info.enumvals;
1342 gboolean prefs_get_enum_radiobuttons(pref_t *pref)
1344 return pref->info.enum_info.radio_buttons;
1348 register_string_like_preference(module_t *module, const char *name,
1349 const char *title, const char *description,
1350 char **var, int type,
1351 struct pref_custom_cbs* custom_cbs,
1357 pref = register_preference(module, name, title, description, type);
1360 * String preference values should be non-null (as you can't
1361 * keep them null after using the preferences GUI, you can at best
1362 * have them be null strings) and freeable (as we free them
1363 * if we change them).
1365 * If the value is a null pointer, make it a copy of a null
1366 * string, otherwise make it a copy of the value.
1370 *var = g_strdup("");
1372 *var = g_strdup(*var);
1377 pref->varp.string = var;
1378 pref->default_val.string = g_strdup(*var);
1379 pref->stashed_val.string = NULL;
1380 if (type == PREF_CUSTOM) {
1381 g_assert(custom_cbs);
1382 pref->custom_cbs = *custom_cbs;
1387 * For use by UI code that sets preferences.
1390 prefs_set_string_value(pref_t *pref, const char* value, pref_source_t source)
1392 unsigned int changed = 0;
1397 if (*pref->default_val.string) {
1398 if (strcmp(pref->default_val.string, value) != 0) {
1399 changed = prefs_get_effect_flags(pref);
1400 g_free(pref->default_val.string);
1401 pref->default_val.string = g_strdup(value);
1404 pref->default_val.string = g_strdup(value);
1408 if (pref->stashed_val.string) {
1409 if (strcmp(pref->stashed_val.string, value) != 0) {
1410 changed = prefs_get_effect_flags(pref);
1411 g_free(pref->stashed_val.string);
1412 pref->stashed_val.string = g_strdup(value);
1415 pref->stashed_val.string = g_strdup(value);
1419 if (*pref->varp.string) {
1420 if (strcmp(*pref->varp.string, value) != 0) {
1421 changed = prefs_get_effect_flags(pref);
1422 g_free(*pref->varp.string);
1423 *pref->varp.string = g_strdup(value);
1426 *pref->varp.string = g_strdup(value);
1430 g_assert_not_reached();
1437 char* prefs_get_string_value(pref_t *pref, pref_source_t source)
1442 return pref->default_val.string;
1444 return pref->stashed_val.string;
1446 return *pref->varp.string;
1448 g_assert_not_reached();
1456 * Reset the value of a string-like preference.
1459 reset_string_like_preference(pref_t *pref)
1461 g_free(*pref->varp.string);
1462 *pref->varp.string = g_strdup(pref->default_val.string);
1466 * Register a preference with a character-string value.
1469 prefs_register_string_preference(module_t *module, const char *name,
1470 const char *title, const char *description,
1474 register_string_like_preference(module, name, title, description,
1475 (char **)var, PREF_STRING, NULL, FALSE);
1480 * Register a preference with a file name (string) value.
1483 prefs_register_filename_preference(module_t *module, const char *name,
1484 const char *title, const char *description,
1485 const char **var, gboolean for_writing)
1488 register_string_like_preference(module, name, title, description, (char **)var,
1489 for_writing ? PREF_SAVE_FILENAME : PREF_OPEN_FILENAME, NULL, FALSE);
1494 * Register a preference with a directory name (string) value.
1497 prefs_register_directory_preference(module_t *module, const char *name,
1498 const char *title, const char *description,
1502 register_string_like_preference(module, name, title, description,
1503 (char **)var, PREF_DIRNAME, NULL, FALSE);
1507 /* Refactoring to handle both PREF_RANGE and PREF_DECODE_AS_RANGE */
1509 prefs_register_range_preference_common(module_t *module, const char *name,
1510 const char *title, const char *description,
1511 range_t **var, guint32 max_value, int type)
1515 preference = register_preference(module, name, title, description, type);
1516 preference->info.max_value = max_value;
1519 * Range preference values should be non-null (as you can't
1520 * keep them null after using the preferences GUI, you can at best
1521 * have them be empty ranges) and freeable (as we free them
1522 * if we change them).
1524 * If the value is a null pointer, make it an empty range.
1527 *var = range_empty(wmem_epan_scope());
1528 preference->varp.range = var;
1529 preference->default_val.range = range_copy(wmem_epan_scope(), *var);
1530 preference->stashed_val.range = NULL;
1534 * Register a preference with a ranged value.
1537 prefs_register_range_preference(module_t *module, const char *name,
1538 const char *title, const char *description,
1539 range_t **var, guint32 max_value)
1541 prefs_register_range_preference_common(module, name, title,
1542 description, var, max_value, PREF_RANGE);
1546 prefs_set_range_value_work(pref_t *pref, const gchar *value,
1547 gboolean return_range_errors, unsigned int *changed_flags)
1551 if (range_convert_str_work(wmem_epan_scope(), &newrange, value, pref->info.max_value,
1552 return_range_errors) != CVT_NO_ERROR) {
1553 return FALSE; /* number was bad */
1556 if (!ranges_are_equal(*pref->varp.range, newrange)) {
1557 *changed_flags |= prefs_get_effect_flags(pref);
1558 wmem_free(wmem_epan_scope(), *pref->varp.range);
1559 *pref->varp.range = newrange;
1561 wmem_free(wmem_epan_scope(), newrange);
1567 * For use by UI code that sets preferences.
1570 prefs_set_stashed_range_value(pref_t *pref, const gchar *value)
1574 if (range_convert_str_work(wmem_epan_scope(), &newrange, value, pref->info.max_value,
1575 TRUE) != CVT_NO_ERROR) {
1576 return 0; /* number was bad */
1579 if (!ranges_are_equal(pref->stashed_val.range, newrange)) {
1580 wmem_free(wmem_epan_scope(), pref->stashed_val.range);
1581 pref->stashed_val.range = newrange;
1583 wmem_free(wmem_epan_scope(), newrange);
1585 return prefs_get_effect_flags(pref);
1589 gboolean prefs_set_range_value(pref_t *pref, range_t *value, pref_source_t source)
1591 gboolean changed = FALSE;
1596 if (!ranges_are_equal(pref->default_val.range, value)) {
1597 wmem_free(wmem_epan_scope(), pref->default_val.range);
1598 pref->default_val.range = range_copy(wmem_epan_scope(), value);
1603 if (!ranges_are_equal(pref->stashed_val.range, value)) {
1604 wmem_free(wmem_epan_scope(), pref->stashed_val.range);
1605 pref->stashed_val.range = range_copy(wmem_epan_scope(), value);
1610 if (!ranges_are_equal(*pref->varp.range, value)) {
1611 wmem_free(wmem_epan_scope(), *pref->varp.range);
1612 *pref->varp.range = range_copy(wmem_epan_scope(), value);
1617 g_assert_not_reached();
1624 range_t* prefs_get_range_value_real(pref_t *pref, pref_source_t source)
1629 return pref->default_val.range;
1631 return pref->stashed_val.range;
1634 return *pref->varp.range;
1637 g_assert_not_reached();
1644 range_t* prefs_get_range_value(const char *module_name, const char* pref_name)
1646 return prefs_get_range_value_real(prefs_find_preference(prefs_find_module(module_name), pref_name), pref_current);
1650 prefs_range_add_value(pref_t *pref, guint32 val)
1652 range_add_value(wmem_epan_scope(), pref->varp.range, val);
1656 prefs_range_remove_value(pref_t *pref, guint32 val)
1658 range_remove_value(wmem_epan_scope(), pref->varp.range, val);
1662 * Register a static text 'preference'. It can be used to add explanatory
1663 * text inline with other preferences in the GUI.
1664 * Note: Static preferences are not saved to the preferences file.
1667 prefs_register_static_text_preference(module_t *module, const char *name,
1669 const char *description)
1671 register_preference(module, name, title, description, PREF_STATIC_TEXT);
1675 * Register a uat 'preference'. It adds a button that opens the uat's window in the
1676 * preferences tab of the module.
1679 prefs_register_uat_preference(module_t *module, const char *name,
1680 const char *title, const char *description,
1684 pref_t* preference = register_preference(module, name, title, description, PREF_UAT);
1686 preference->varp.uat = uat;
1690 * Register a uat 'preference' for QT only. It adds a button that opens the uat's window in the
1691 * preferences tab of the module.
1694 prefs_register_uat_preference_qt(module_t *module, const char *name,
1695 const char *title, const char *description,
1699 pref_t* preference = register_preference(module, name, title, description, PREF_UAT);
1701 preference->varp.uat = uat;
1703 preference->gui = GUI_QT;
1706 struct epan_uat* prefs_get_uat_value(pref_t *pref)
1708 return pref->varp.uat;
1712 * Register a color preference.
1715 prefs_register_color_preference(module_t *module, const char *name,
1716 const char *title, const char *description,
1719 pref_t* preference = register_preference(module, name, title, description, PREF_COLOR);
1721 preference->varp.colorp = color;
1722 preference->default_val.color = *color;
1725 gboolean prefs_set_color_value(pref_t *pref, color_t value, pref_source_t source)
1727 gboolean changed = FALSE;
1732 if ((pref->default_val.color.red != value.red) &&
1733 (pref->default_val.color.green != value.green) &&
1734 (pref->default_val.color.blue != value.blue)) {
1736 pref->default_val.color = value;
1740 if ((pref->stashed_val.color.red != value.red) &&
1741 (pref->stashed_val.color.green != value.green) &&
1742 (pref->stashed_val.color.blue != value.blue)) {
1744 pref->stashed_val.color = value;
1748 if ((pref->varp.colorp->red != value.red) &&
1749 (pref->varp.colorp->green != value.green) &&
1750 (pref->varp.colorp->blue != value.blue)) {
1752 *pref->varp.colorp = value;
1756 g_assert_not_reached();
1763 color_t* prefs_get_color_value(pref_t *pref, pref_source_t source)
1768 return &pref->default_val.color;
1770 return &pref->stashed_val.color;
1773 return pref->varp.colorp;
1776 g_assert_not_reached();
1784 * Register a "custom" preference with a list.
1785 * XXX - This should be temporary until we can find a better way
1786 * to do "custom" preferences
1788 typedef void (*pref_custom_list_init_cb) (pref_t* pref, GList** value);
1791 prefs_register_list_custom_preference(module_t *module, const char *name,
1792 const char *title, const char *description,
1793 struct pref_custom_cbs* custom_cbs,
1794 pref_custom_list_init_cb init_cb,
1797 pref_t* preference = register_preference(module, name, title, description, PREF_CUSTOM);
1799 preference->custom_cbs = *custom_cbs;
1800 init_cb(preference, list);
1804 * Register a custom preference.
1807 prefs_register_custom_preference(module_t *module, const char *name,
1808 const char *title, const char *description,
1809 struct pref_custom_cbs* custom_cbs,
1810 void **custom_data _U_)
1812 pref_t* preference = register_preference(module, name, title, description, PREF_CUSTOM);
1814 preference->custom_cbs = *custom_cbs;
1815 /* XXX - wait until we can handle void** pointers
1816 preference->custom_cbs.init_cb(preference, custom_data);
1821 * Register a (internal) "Decode As" preference with a ranged value.
1823 void prefs_register_decode_as_range_preference(module_t *module, const char *name,
1824 const char *title, const char *description, range_t **var,
1827 prefs_register_range_preference_common(module, name, title,
1828 description, var, max_value, PREF_DECODE_AS_RANGE);
1832 * Register a (internal) "Decode As" preference with an unsigned integral value
1833 * for a dissector table.
1835 void prefs_register_decode_as_preference(module_t *module, const char *name,
1836 const char *title, const char *description, guint *var)
1840 preference = register_preference(module, name, title, description,
1841 PREF_DECODE_AS_UINT);
1842 preference->varp.uint = var;
1843 preference->default_val.uint = *var;
1844 /* XXX - Presume base 10 for now */
1845 preference->info.base = 10;
1848 gboolean prefs_add_decode_as_value(pref_t *pref, guint value, gboolean replace)
1852 case PREF_DECODE_AS_UINT:
1853 /* This doesn't support multiple values for a dissector in Decode As because the
1854 preference only supports a single value. This leads to a "last port for
1855 dissector in Decode As wins" */
1856 *pref->varp.uint = value;
1858 case PREF_DECODE_AS_RANGE:
1861 /* If range has single value, replace it */
1862 if (((*pref->varp.range)->nranges == 1) &&
1863 ((*pref->varp.range)->ranges[0].low == (*pref->varp.range)->ranges[0].high)) {
1864 wmem_free(wmem_epan_scope(), *pref->varp.range);
1865 *pref->varp.range = range_empty(wmem_epan_scope());
1869 prefs_range_add_value(pref, value);
1872 /* XXX - Worth asserting over? */
1879 gboolean prefs_remove_decode_as_value(pref_t *pref, guint value, gboolean set_default)
1883 case PREF_DECODE_AS_UINT:
1885 *pref->varp.uint = pref->default_val.uint;
1887 *pref->varp.uint = 0;
1890 case PREF_DECODE_AS_RANGE:
1891 prefs_range_remove_value(pref, value);
1901 * Register a preference that used to be supported but no longer is.
1904 prefs_register_obsolete_preference(module_t *module, const char *name)
1906 register_preference(module, name, NULL, NULL, PREF_OBSOLETE);
1910 * Check to see if a preference is obsolete.
1913 prefs_get_preference_obsolete(pref_t *pref)
1916 return (IS_PREF_OBSOLETE(pref->type) ? TRUE : FALSE);
1922 * Make a preference obsolete.
1924 extern prefs_set_pref_e
1925 prefs_set_preference_obsolete(pref_t *pref)
1928 SET_PREF_OBSOLETE(pref->type);
1929 return PREFS_SET_OK;
1931 return PREFS_SET_NO_SUCH_PREF;
1935 pref_stash(pref_t *pref, gpointer unused _U_)
1937 switch (pref->type) {
1939 case PREF_DECODE_AS_UINT:
1940 pref->stashed_val.uint = *pref->varp.uint;
1944 pref->stashed_val.uint = *pref->varp.uint;
1948 pref->stashed_val.boolval = *pref->varp.boolp;
1952 pref->stashed_val.enumval = *pref->varp.enump;
1956 case PREF_SAVE_FILENAME:
1957 case PREF_OPEN_FILENAME:
1959 g_free(pref->stashed_val.string);
1960 pref->stashed_val.string = g_strdup(*pref->varp.string);
1963 case PREF_DECODE_AS_RANGE:
1965 wmem_free(wmem_epan_scope(), pref->stashed_val.range);
1966 pref->stashed_val.range = range_copy(wmem_epan_scope(), *pref->varp.range);
1970 pref->stashed_val.color = *pref->varp.colorp;
1973 case PREF_STATIC_TEXT:
1979 g_assert_not_reached();
1986 pref_unstash(pref_t *pref, gpointer unstash_data_p)
1988 pref_unstash_data_t *unstash_data = (pref_unstash_data_t *)unstash_data_p;
1989 dissector_table_t sub_dissectors = NULL;
1990 dissector_handle_t handle = NULL;
1992 /* Revert the preference to its saved value. */
1993 switch (pref->type) {
1995 case PREF_DECODE_AS_UINT:
1996 if (*pref->varp.uint != pref->stashed_val.uint) {
1997 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
1999 if (unstash_data->handle_decode_as) {
2000 if (*pref->varp.uint != pref->default_val.uint) {
2001 dissector_reset_uint(pref->name, *pref->varp.uint);
2005 *pref->varp.uint = pref->stashed_val.uint;
2007 if (unstash_data->handle_decode_as) {
2008 sub_dissectors = find_dissector_table(pref->name);
2009 if (sub_dissectors != NULL) {
2010 handle = dissector_table_get_dissector_handle(sub_dissectors, (gchar*)unstash_data->module->title);
2011 if (handle != NULL) {
2012 dissector_change_uint(pref->name, *pref->varp.uint, handle);
2020 if (*pref->varp.uint != pref->stashed_val.uint) {
2021 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2022 *pref->varp.uint = pref->stashed_val.uint;
2027 if (*pref->varp.boolp != pref->stashed_val.boolval) {
2028 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2029 *pref->varp.boolp = pref->stashed_val.boolval;
2034 if (*pref->varp.enump != pref->stashed_val.enumval) {
2035 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2036 *pref->varp.enump = pref->stashed_val.enumval;
2041 case PREF_SAVE_FILENAME:
2042 case PREF_OPEN_FILENAME:
2044 if (strcmp(*pref->varp.string, pref->stashed_val.string) != 0) {
2045 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2046 g_free(*pref->varp.string);
2047 *pref->varp.string = g_strdup(pref->stashed_val.string);
2051 case PREF_DECODE_AS_RANGE:
2052 if (!ranges_are_equal(*pref->varp.range, pref->stashed_val.range)) {
2054 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2056 if (unstash_data->handle_decode_as) {
2057 sub_dissectors = find_dissector_table(pref->name);
2058 if (sub_dissectors != NULL) {
2059 handle = dissector_table_get_dissector_handle(sub_dissectors, (gchar*)unstash_data->module->title);
2060 if (handle != NULL) {
2061 /* Delete all of the old values from the dissector table */
2062 for (i = 0; i < (*pref->varp.range)->nranges; i++) {
2063 for (j = (*pref->varp.range)->ranges[i].low; j < (*pref->varp.range)->ranges[i].high; j++) {
2064 dissector_delete_uint(pref->name, j, handle);
2065 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(j), NULL, NULL);
2068 dissector_delete_uint(pref->name, (*pref->varp.range)->ranges[i].high, handle);
2069 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER((*pref->varp.range)->ranges[i].high), NULL, NULL);
2075 wmem_free(wmem_epan_scope(), *pref->varp.range);
2076 *pref->varp.range = range_copy(wmem_epan_scope(), pref->stashed_val.range);
2078 if (unstash_data->handle_decode_as) {
2079 if ((sub_dissectors != NULL) && (handle != NULL)) {
2081 /* Add new values to the dissector table */
2082 for (i = 0; i < (*pref->varp.range)->nranges; i++) {
2084 for (j = (*pref->varp.range)->ranges[i].low; j < (*pref->varp.range)->ranges[i].high; j++) {
2085 dissector_change_uint(pref->name, j, handle);
2086 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(j), NULL, NULL);
2089 dissector_change_uint(pref->name, (*pref->varp.range)->ranges[i].high, handle);
2090 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER((*pref->varp.range)->ranges[i].high), NULL, NULL);
2098 if (!ranges_are_equal(*pref->varp.range, pref->stashed_val.range)) {
2099 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2100 wmem_free(wmem_epan_scope(), *pref->varp.range);
2101 *pref->varp.range = range_copy(wmem_epan_scope(), pref->stashed_val.range);
2106 if ((pref->varp.colorp->blue != pref->stashed_val.color.blue) ||
2107 (pref->varp.colorp->red != pref->stashed_val.color.red) ||
2108 (pref->varp.colorp->green != pref->stashed_val.color.green)) {
2109 unstash_data->module->prefs_changed_flags |= prefs_get_effect_flags(pref);
2110 *pref->varp.colorp = pref->stashed_val.color;
2114 case PREF_STATIC_TEXT:
2120 g_assert_not_reached();
2127 reset_stashed_pref(pref_t *pref) {
2128 switch (pref->type) {
2130 case PREF_DECODE_AS_UINT:
2131 pref->stashed_val.uint = pref->default_val.uint;
2135 pref->stashed_val.uint = pref->default_val.uint;
2139 pref->stashed_val.boolval = pref->default_val.boolval;
2143 pref->stashed_val.enumval = pref->default_val.enumval;
2147 case PREF_SAVE_FILENAME:
2148 case PREF_OPEN_FILENAME:
2150 g_free(pref->stashed_val.string);
2151 pref->stashed_val.string = g_strdup(pref->default_val.string);
2154 case PREF_DECODE_AS_RANGE:
2156 wmem_free(wmem_epan_scope(), pref->stashed_val.range);
2157 pref->stashed_val.range = range_copy(wmem_epan_scope(), pref->default_val.range);
2161 memcpy(&pref->stashed_val.color, &pref->default_val.color, sizeof(color_t));
2164 case PREF_STATIC_TEXT:
2170 g_assert_not_reached();
2176 pref_clean_stash(pref_t *pref, gpointer unused _U_)
2178 switch (pref->type) {
2181 case PREF_DECODE_AS_UINT:
2191 case PREF_SAVE_FILENAME:
2192 case PREF_OPEN_FILENAME:
2194 if (pref->stashed_val.string != NULL) {
2195 g_free(pref->stashed_val.string);
2196 pref->stashed_val.string = NULL;
2200 case PREF_DECODE_AS_RANGE:
2202 if (pref->stashed_val.range != NULL) {
2203 wmem_free(wmem_epan_scope(), pref->stashed_val.range);
2204 pref->stashed_val.range = NULL;
2208 case PREF_STATIC_TEXT:
2215 g_assert_not_reached();
2222 /* Return the value assigned to the given uint preference. */
2224 prefs_get_uint_preference(pref_t *pref)
2226 if (pref && pref->type == PREF_UINT)
2227 return *pref->varp.uint;
2233 * Call a callback function, with a specified argument, for each preference
2234 * in a given module.
2236 * If any of the callbacks return a non-zero value, stop and return that
2237 * value, otherwise return 0.
2240 prefs_pref_foreach(module_t *module, pref_cb callback, gpointer user_data)
2246 for (elem = g_list_first(module->prefs); elem != NULL; elem = g_list_next(elem)) {
2247 pref = (pref_t *)elem->data;
2248 if (IS_PREF_OBSOLETE(pref->type)) {
2250 * This preference is no longer supported; it's
2251 * not a real preference, so we don't call the
2252 * callback for it (i.e., we treat it as if it
2253 * weren't found in the list of preferences,
2254 * and we weren't called in the first place).
2259 ret = (*callback)(pref, user_data);
2266 static const enum_val_t print_format_vals[] = {
2267 { "text", "Plain Text", PR_FMT_TEXT },
2268 { "postscript", "Postscript", PR_FMT_PS },
2272 static const enum_val_t print_dest_vals[] = {
2274 /* "PR_DEST_CMD" means "to printer" on Windows */
2275 { "command", "Printer", PR_DEST_CMD },
2277 { "command", "Command", PR_DEST_CMD },
2279 { "file", "File", PR_DEST_FILE },
2283 static const enum_val_t st_sort_col_vals[] = {
2284 { "name", "Node name (topic/item)", ST_SORT_COL_NAME },
2285 { "count", "Item count", ST_SORT_COL_COUNT },
2286 { "average", "Average value of the node", ST_SORT_COL_AVG },
2287 { "min", "Minimum value of the node", ST_SORT_COL_MIN },
2288 { "max", "Maximum value of the node", ST_SORT_COL_MAX },
2289 { "burst", "Burst rate of the node", ST_SORT_COL_BURSTRATE },
2294 stats_callback(void)
2296 /* Test for a sane tap update interval */
2297 if (prefs.tap_update_interval < 100 || prefs.tap_update_interval > 10000)
2298 prefs.tap_update_interval = TAP_UPDATE_DEFAULT_INTERVAL;
2300 #ifdef HAVE_LIBPORTAUDIO
2301 /* Test for a sane max channels entry */
2302 if (prefs.rtp_player_max_visible < 1 || prefs.rtp_player_max_visible > 10)
2303 prefs.rtp_player_max_visible = RTP_PLAYER_DEFAULT_VISIBLE;
2306 /* burst resolution can't be less than 1 (ms) */
2307 if (prefs.st_burst_resolution < 1) {
2308 prefs.st_burst_resolution = 1;
2310 else if (prefs.st_burst_resolution > ST_MAX_BURSTRES) {
2311 prefs.st_burst_resolution = ST_MAX_BURSTRES;
2313 /* make sure burst window value makes sense */
2314 if (prefs.st_burst_windowlen < prefs.st_burst_resolution) {
2315 prefs.st_burst_windowlen = prefs.st_burst_resolution;
2317 /* round burst window down to multiple of resolution */
2318 prefs.st_burst_windowlen -= prefs.st_burst_windowlen%prefs.st_burst_resolution;
2319 if ((prefs.st_burst_windowlen/prefs.st_burst_resolution) > ST_MAX_BURSTBUCKETS) {
2320 prefs.st_burst_windowlen = prefs.st_burst_resolution*ST_MAX_BURSTBUCKETS;
2327 /* Ensure there is at least one file count */
2328 if (prefs.gui_recent_files_count_max == 0)
2329 prefs.gui_recent_files_count_max = 10;
2331 /* Ensure there is at least one display filter entry */
2332 if (prefs.gui_recent_df_entries_max == 0)
2333 prefs.gui_recent_df_entries_max = 10;
2337 gui_layout_callback(void)
2339 if (prefs.gui_layout_type == layout_unused ||
2340 prefs.gui_layout_type >= layout_type_max) {
2341 /* XXX - report an error? It's not a syntax error - we'd need to
2342 add a way of reporting a *semantic* error. */
2343 prefs.gui_layout_type = layout_type_5;
2347 /******************************************************
2348 * All custom preference function callbacks
2349 ******************************************************/
2350 static void custom_pref_no_cb(pref_t* pref _U_) {}
2354 * Console log level custom preference functions
2357 console_log_level_reset_cb(pref_t* pref)
2359 *pref->varp.uint = pref->default_val.uint;
2362 static prefs_set_pref_e
2363 console_log_level_set_cb(pref_t* pref, const gchar* value, unsigned int* changed_flags)
2367 uval = (guint)strtoul(value, NULL, 10);
2369 if (*pref->varp.uint != uval) {
2370 *changed_flags = prefs_get_effect_flags(pref);
2371 *pref->varp.uint = uval;
2374 if (*pref->varp.uint & (G_LOG_LEVEL_INFO|G_LOG_LEVEL_DEBUG)) {
2376 * GLib >= 2.32 drops INFO and DEBUG messages by default. Tell
2377 * it not to do that.
2379 g_setenv("G_MESSAGES_DEBUG", "all", TRUE);
2382 return PREFS_SET_OK;
2385 static const char * console_log_level_type_name_cb(void) {
2389 static char * console_log_level_type_description_cb(void) {
2390 return g_strdup_printf(
2391 "Console log level (for debugging)\n"
2392 "A bitmask of log levels:\n"
2401 static gboolean console_log_level_is_default_cb(pref_t* pref) {
2402 return *pref->varp.uint == pref->default_val.uint;
2405 static char * console_log_level_to_str_cb(pref_t* pref, gboolean default_val) {
2406 return g_strdup_printf("%u", default_val ? pref->default_val.uint : *pref->varp.uint);
2410 * Column preference functions
2412 #define PRS_COL_HIDDEN "column.hidden"
2413 #define PRS_COL_FMT "column.format"
2414 #define PRS_COL_NUM "column.number"
2415 static module_t *gui_column_module = NULL;
2417 static prefs_set_pref_e
2418 column_hidden_set_cb(pref_t* pref, const gchar* value, unsigned int* changed_flags)
2422 pref_t *format_pref;
2424 (*changed_flags) |= prefs_set_string_value(pref, value, pref_current);
2427 * Set the "visible" flag for the existing columns; we need to
2428 * do this if we set PRS_COL_HIDDEN but don't set PRS_COL_FMT
2429 * after setting it (which might be the case if, for example, we
2430 * set PRS_COL_HIDDEN on the command line).
2432 format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT);
2433 for (clp = *format_pref->varp.list; clp != NULL; clp = clp->next) {
2434 cfmt = (fmt_data *)clp->data;
2435 cfmt->visible = prefs_is_column_visible(*pref->varp.string, cfmt);
2438 return PREFS_SET_OK;
2442 column_hidden_type_name_cb(void)
2444 return "Packet list hidden columns";
2448 column_hidden_type_description_cb(void)
2450 return g_strdup("List all columns to hide in the packet list.");
2454 column_hidden_to_str_cb(pref_t* pref, gboolean default_val)
2456 GString *cols_hidden = g_string_new ("");
2459 pref_t *format_pref;
2462 return g_strdup(pref->default_val.string);
2464 format_pref = prefs_find_preference(gui_column_module, PRS_COL_FMT);
2465 clp = (format_pref) ? *format_pref->varp.list : NULL;
2468 cfmt = (fmt_data *) clp->data;
2469 if ((cfmt->fmt == COL_CUSTOM) && (cfmt->custom_fields)) {
2470 prefs_fmt = g_strdup_printf("%s:%s:%d:%c",
2471 col_format_to_string(cfmt->fmt),
2472 cfmt->custom_fields,
2473 cfmt->custom_occurrence,
2474 cfmt->resolved ? 'R' : 'U');
2476 prefs_fmt = g_strdup(col_format_to_string(cfmt->fmt));
2478 if (!cfmt->visible) {
2479 if (cols_hidden->len)
2480 g_string_append (cols_hidden, ",");
2481 g_string_append (cols_hidden, prefs_fmt);
2487 return g_string_free (cols_hidden, FALSE);
2491 column_hidden_is_default_cb(pref_t* pref)
2493 char *cur_hidden_str = column_hidden_to_str_cb(pref, FALSE);
2494 gboolean is_default = g_strcmp0(cur_hidden_str, pref->default_val.string) == 0;
2496 g_free(cur_hidden_str);
2501 /* Number of columns "preference". This is only used internally and is not written to the
2505 column_num_reset_cb(pref_t* pref)
2507 *pref->varp.uint = pref->default_val.uint;
2510 static prefs_set_pref_e
2511 column_num_set_cb(pref_t* pref _U_, const gchar* value _U_, unsigned int* changed_flags _U_)
2513 /* Don't write this to the preferences file */
2514 return PREFS_SET_OK;
2518 column_num_type_name_cb(void)
2524 column_num_type_description_cb(void)
2526 return g_strdup("");
2530 column_num_is_default_cb(pref_t* pref _U_)
2536 column_num_to_str_cb(pref_t* pref _U_, gboolean default_val _U_)
2538 return g_strdup("");
2542 * Column format custom preference functions
2545 column_format_init_cb(pref_t* pref, GList** value)
2547 fmt_data *src_cfmt, *dest_cfmt;
2550 pref->varp.list = value;
2552 pref->default_val.list = NULL;
2553 for (entry = *pref->varp.list; entry != NULL; entry = g_list_next(entry)) {
2554 src_cfmt = (fmt_data *)entry->data;
2555 dest_cfmt = g_new(fmt_data,1);
2556 dest_cfmt->title = g_strdup(src_cfmt->title);
2557 dest_cfmt->fmt = src_cfmt->fmt;
2558 if (src_cfmt->custom_fields) {
2559 dest_cfmt->custom_fields = g_strdup(src_cfmt->custom_fields);
2560 dest_cfmt->custom_occurrence = src_cfmt->custom_occurrence;
2562 dest_cfmt->custom_fields = NULL;
2563 dest_cfmt->custom_occurrence = 0;
2565 dest_cfmt->visible = src_cfmt->visible;
2566 dest_cfmt->resolved = src_cfmt->resolved;
2567 pref->default_val.list = g_list_append(pref->default_val.list, dest_cfmt);
2572 column_format_free_cb(pref_t* pref)
2574 free_col_info(*pref->varp.list);
2575 free_col_info(pref->default_val.list);
2579 column_format_reset_cb(pref_t* pref)
2581 fmt_data *src_cfmt, *dest_cfmt;
2583 pref_t *col_num_pref;
2585 free_col_info(*pref->varp.list);
2586 *pref->varp.list = NULL;
2588 for (entry = pref->default_val.list; entry != NULL; entry = g_list_next(entry)) {
2589 src_cfmt = (fmt_data *)entry->data;
2590 dest_cfmt = g_new(fmt_data,1);
2591 dest_cfmt->title = g_strdup(src_cfmt->title);
2592 dest_cfmt->fmt = src_cfmt->fmt;
2593 if (src_cfmt->custom_fields) {
2594 dest_cfmt->custom_fields = g_strdup(src_cfmt->custom_fields);
2595 dest_cfmt->custom_occurrence = src_cfmt->custom_occurrence;
2597 dest_cfmt->custom_fields = NULL;
2598 dest_cfmt->custom_occurrence = 0;
2600 dest_cfmt->visible = src_cfmt->visible;
2601 dest_cfmt->resolved = src_cfmt->resolved;
2602 *pref->varp.list = g_list_append(*pref->varp.list, dest_cfmt);
2605 col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM);
2606 g_assert(col_num_pref != NULL); /* Should never happen */
2607 column_num_reset_cb(col_num_pref);
2610 static prefs_set_pref_e
2611 column_format_set_cb(pref_t* pref, const gchar* value, unsigned int* changed_flags _U_)
2613 GList *col_l, *col_l_elt;
2616 pref_t *hidden_pref, *col_num_pref;
2618 col_l = prefs_get_string_list(value);
2620 return PREFS_SET_SYNTAX_ERR;
2621 if ((g_list_length(col_l) % 2) != 0) {
2622 /* A title didn't have a matching format. */
2623 prefs_clear_string_list(col_l);
2624 return PREFS_SET_SYNTAX_ERR;
2626 /* Check to make sure all column formats are valid. */
2627 col_l_elt = g_list_first(col_l);
2629 fmt_data cfmt_check;
2631 /* Go past the title. */
2632 col_l_elt = col_l_elt->next;
2634 /* Parse the format to see if it's valid. */
2635 if (!parse_column_format(&cfmt_check, (char *)col_l_elt->data)) {
2636 /* It's not a valid column format. */
2637 prefs_clear_string_list(col_l);
2638 return PREFS_SET_SYNTAX_ERR;
2640 if (cfmt_check.fmt != COL_CUSTOM) {
2641 /* Some predefined columns have been migrated to use custom columns.
2642 * We'll convert these silently here */
2643 try_convert_to_custom_column(&col_l_elt->data);
2645 /* We don't need the custom column field on this pass. */
2646 g_free(cfmt_check.custom_fields);
2649 /* Go past the format. */
2650 col_l_elt = col_l_elt->next;
2653 /* They're all valid; process them. */
2654 free_col_info(*pref->varp.list);
2655 *pref->varp.list = NULL;
2656 hidden_pref = prefs_find_preference(gui_column_module, PRS_COL_HIDDEN);
2657 g_assert(hidden_pref != NULL); /* Should never happen */
2658 col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM);
2659 g_assert(col_num_pref != NULL); /* Should never happen */
2660 llen = g_list_length(col_l);
2661 *col_num_pref->varp.uint = llen / 2;
2662 col_l_elt = g_list_first(col_l);
2664 cfmt = g_new(fmt_data,1);
2665 cfmt->title = g_strdup((gchar *)col_l_elt->data);
2666 col_l_elt = col_l_elt->next;
2667 parse_column_format(cfmt, (char *)col_l_elt->data);
2668 cfmt->visible = prefs_is_column_visible(*hidden_pref->varp.string, cfmt);
2669 col_l_elt = col_l_elt->next;
2670 *pref->varp.list = g_list_append(*pref->varp.list, cfmt);
2673 prefs_clear_string_list(col_l);
2674 free_string_like_preference(hidden_pref);
2675 return PREFS_SET_OK;
2680 column_format_type_name_cb(void)
2682 return "Packet list column format";
2686 column_format_type_description_cb(void)
2688 return g_strdup("Each pair of strings consists of a column title and its format");
2692 column_format_is_default_cb(pref_t* pref)
2694 GList *clp = *pref->varp.list,
2695 *pref_col = g_list_first(clp),
2696 *def_col = g_list_first(pref->default_val.list);
2697 fmt_data *cfmt, *def_cfmt;
2698 gboolean is_default = TRUE;
2699 pref_t *col_num_pref;
2701 /* See if the column data has changed from the default */
2702 col_num_pref = prefs_find_preference(gui_column_module, PRS_COL_NUM);
2703 if (col_num_pref && *col_num_pref->varp.uint != col_num_pref->default_val.uint) {
2706 while (pref_col && def_col) {
2707 cfmt = (fmt_data *) pref_col->data;
2708 def_cfmt = (fmt_data *) def_col->data;
2709 if ((g_strcmp0(cfmt->title, def_cfmt->title) != 0) ||
2710 (cfmt->fmt != def_cfmt->fmt) ||
2711 (((cfmt->fmt == COL_CUSTOM) && (cfmt->custom_fields)) &&
2712 ((g_strcmp0(cfmt->custom_fields, def_cfmt->custom_fields) != 0) ||
2713 (cfmt->resolved != def_cfmt->resolved)))) {
2718 pref_col = pref_col->next;
2719 def_col = def_col->next;
2727 column_format_to_str_cb(pref_t* pref, gboolean default_val)
2729 GList *pref_l = default_val ? pref->default_val.list : *pref->varp.list;
2730 GList *clp = g_list_first(pref_l);
2734 char *column_format_str;
2738 cfmt = (fmt_data *) clp->data;
2739 col_l = g_list_append(col_l, g_strdup(cfmt->title));
2740 if ((cfmt->fmt == COL_CUSTOM) && (cfmt->custom_fields)) {
2741 prefs_fmt = g_strdup_printf("%s:%s:%d:%c",
2742 col_format_to_string(cfmt->fmt),
2743 cfmt->custom_fields,
2744 cfmt->custom_occurrence,
2745 cfmt->resolved ? 'R' : 'U');
2747 prefs_fmt = g_strdup(col_format_to_string(cfmt->fmt));
2749 col_l = g_list_append(col_l, prefs_fmt);
2753 column_format_str = join_string_list(col_l);
2754 prefs_clear_string_list(col_l);
2755 return column_format_str;
2759 /****** Capture column custom preference functions ******/
2761 /* This routine is only called when Wireshark is started, NOT when another profile is selected.
2762 Copy the pref->capture_columns list (just loaded with the capture_cols[] struct values)
2763 to prefs->default_val.list.
2766 capture_column_init_cb(pref_t* pref, GList** capture_cols_values)
2768 GList *ccv_list = *capture_cols_values,
2773 dlist = g_list_append(dlist, g_strdup((gchar *)ccv_list->data));
2774 ccv_list = ccv_list->next;
2777 pref->default_val.list = dlist;
2778 pref->varp.list = &prefs.capture_columns;
2779 pref->stashed_val.boolval = FALSE;
2782 /* Free the prefs->capture_columns list strings and remove the list entries.
2783 Note that since pref->varp.list points to &prefs.capture_columns, it is
2787 capture_column_free_cb(pref_t* pref)
2789 prefs_clear_string_list(prefs.capture_columns);
2790 prefs.capture_columns = NULL;
2792 if (pref->stashed_val.boolval == TRUE) {
2793 prefs_clear_string_list(pref->default_val.list);
2794 pref->default_val.list = NULL;
2798 /* Copy pref->default_val.list to *pref->varp.list.
2801 capture_column_reset_cb(pref_t* pref)
2803 GList *vlist = NULL, *dlist;
2805 /* Free the column name strings and remove the links from *pref->varp.list */
2806 prefs_clear_string_list(*pref->varp.list);
2808 for (dlist = pref->default_val.list; dlist != NULL; dlist = g_list_next(dlist)) {
2809 vlist = g_list_append(vlist, g_strdup((gchar *)dlist->data));
2811 *pref->varp.list = vlist;
2814 static prefs_set_pref_e
2815 capture_column_set_cb(pref_t* pref, const gchar* value, unsigned int* changed_flags _U_)
2817 GList *col_l = prefs_get_string_list(value);
2823 return PREFS_SET_SYNTAX_ERR;
2825 capture_column_free_cb(pref);
2827 /* If value (the list of capture.columns read from preferences) is empty, set capture.columns
2828 to the full list of valid capture column names. */
2829 col_l_elt = g_list_first(col_l);
2830 if (!(*(gchar *)col_l_elt->data)) {
2831 for (i = 0; i < num_capture_cols; i++) {
2832 col_name = g_strdup(capture_cols[i]);
2833 prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
2837 /* Verify that all the column names are valid. If not, use the entire list of valid columns.
2840 gboolean found_match = FALSE;
2841 col_name = (gchar *)col_l_elt->data;
2843 for (i = 0; i < num_capture_cols; i++) {
2844 if (strcmp(col_name, capture_cols[i])==0) {
2850 /* One or more cols are invalid so use the entire list of valid cols. */
2851 for (i = 0; i < num_capture_cols; i++) {
2852 col_name = g_strdup(capture_cols[i]);
2853 prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
2855 pref->varp.list = &prefs.capture_columns;
2856 prefs_clear_string_list(col_l);
2857 return PREFS_SET_SYNTAX_ERR;
2859 col_l_elt = col_l_elt->next;
2862 col_l_elt = g_list_first(col_l);
2864 col_name = (gchar *)col_l_elt->data;
2865 prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
2866 col_l_elt = col_l_elt->next;
2868 pref->varp.list = &prefs.capture_columns;
2870 return PREFS_SET_OK;
2875 capture_column_type_name_cb(void)
2877 return "Column list";
2881 capture_column_type_description_cb(void)
2884 "List of columns to be displayed in the capture options dialog.\n"
2885 CAPTURE_COL_TYPE_DESCRIPTION);
2889 capture_column_is_default_cb(pref_t* pref)
2891 GList *pref_col = g_list_first(prefs.capture_columns),
2892 *def_col = g_list_first(pref->default_val.list);
2893 gboolean is_default = TRUE;
2895 /* See if the column data has changed from the default */
2896 while (pref_col && def_col) {
2897 if (strcmp((gchar *)pref_col->data, (gchar *)def_col->data) != 0) {
2901 pref_col = pref_col->next;
2902 def_col = def_col->next;
2905 /* Ensure the same column count */
2906 if (((pref_col == NULL) && (def_col != NULL)) ||
2907 ((pref_col != NULL) && (def_col == NULL)))
2914 capture_column_to_str_cb(pref_t* pref, gboolean default_val)
2917 GList *pref_l = default_val ? pref->default_val.list : prefs.capture_columns;
2918 GList *clp = g_list_first(pref_l);
2919 GList *col_l = NULL;
2921 char *capture_column_str;
2924 col = (gchar *) clp->data;
2925 col_l = g_list_append(col_l, g_strdup(col));
2929 capture_column_str = join_string_list(col_l);
2930 prefs_clear_string_list(col_l);
2931 return capture_column_str;
2934 static prefs_set_pref_e
2935 colorized_frame_set_cb(pref_t* pref, const gchar* value, unsigned int* changed_flags)
2937 (*changed_flags) |= prefs_set_string_value(pref, value, pref_current);
2938 return PREFS_SET_OK;
2942 colorized_frame_type_name_cb(void)
2944 /* Don't write the colors of the 10 easy-access-colorfilters to the preferences
2945 * file until the colors can be changed in the GUI. Currently this is not really
2946 * possible since the STOCK-icons for these colors are hardcoded.
2948 * XXX Find a way to change the colors of the STOCK-icons on the fly and then
2949 * add these 10 colors to the list of colors that can be changed through
2957 colorized_frame_type_description_cb(void)
2959 return g_strdup("");
2963 colorized_frame_is_default_cb(pref_t* pref _U_)
2969 colorized_frame_to_str_cb(pref_t* pref _U_, gboolean default_val _U_)
2971 return g_strdup("");
2975 * Register all non-dissector modules' preferences.
2977 static module_t *gui_module = NULL;
2978 static module_t *gui_color_module = NULL;
2979 static module_t *nameres_module = NULL;
2982 prefs_register_modules(void)
2984 module_t *printing, *capture_module, *console_module,
2985 *gui_layout_module, *gui_font_module;
2986 module_t *extcap_module;
2987 unsigned int layout_gui_flags;
2988 struct pref_custom_cbs custom_cbs;
2990 if (protocols_module != NULL) {
2991 /* Already setup preferences */
2996 * These are "simple" GUI preferences that can be read/written using the
2997 * preference module API. These preferences still use their own
2998 * configuration screens for access, but this cuts down on the
2999 * preference "string compare list" in set_pref()
3001 extcap_module = prefs_register_module(NULL, "extcap", "Extcap Utilities",
3002 "Extcap Utilities", NULL, FALSE);
3004 /* Setting default value to true */
3005 prefs.extcap_save_on_start = TRUE;
3006 prefs_register_bool_preference(extcap_module, "gui_save_on_start",
3007 "Save arguments on start of capture",
3008 "Save arguments on start of capture",
3009 &prefs.extcap_save_on_start);
3012 * These are "simple" GUI preferences that can be read/written using the
3013 * preference module API. These preferences still use their own
3014 * configuration screens for access, but this cuts down on the
3015 * preference "string compare list" in set_pref()
3017 gui_module = prefs_register_module(NULL, "gui", "User Interface",
3018 "User Interface", &gui_callback, FALSE);
3020 /* gui.console_open is placed first in the list so that any problems encountered
3021 * in the following prefs can be displayed in the console window.
3023 prefs_register_enum_preference(gui_module, "console_open",
3024 "Open a console window",
3025 "Open a console window (Windows only)",
3026 (gint*)(void*)(&prefs.gui_console_open), gui_console_open_type, FALSE);
3028 prefs_register_obsolete_preference(gui_module, "scrollbar_on_right");
3029 prefs_register_obsolete_preference(gui_module, "packet_list_sel_browse");
3030 prefs_register_obsolete_preference(gui_module, "protocol_tree_sel_browse");
3032 prefs_register_bool_preference(gui_module, "tree_view_altern_colors",
3033 "Alternating colors in TreeViews",
3034 "Alternating colors in TreeViews?",
3035 &prefs.gui_altern_colors);
3037 prefs_register_bool_preference(gui_module, "expert_composite_eyecandy",
3038 "Display Icons on Expert Composite Dialog Tabs",
3039 "Display Icons on Expert Composite Dialog Tabs?",
3040 &prefs.gui_expert_composite_eyecandy);
3042 prefs_register_bool_preference(gui_module, "filter_toolbar_show_in_statusbar",
3043 "Place filter toolbar inside the statusbar",
3044 "Place filter toolbar inside the statusbar?",
3045 &prefs.filter_toolbar_show_in_statusbar);
3047 prefs_register_bool_preference(gui_module, "restore_filter_after_following_stream",
3048 "Restore current display filter after following a stream",
3049 "Restore current display filter after following a stream?",
3050 &prefs.restore_filter_after_following_stream);
3052 prefs_register_enum_preference(gui_module, "protocol_tree_line_style",
3053 "Protocol-tree line style",
3054 "Protocol-tree line style",
3055 &prefs.gui_ptree_line_style, gui_ptree_line_style, FALSE);
3057 prefs_register_enum_preference(gui_module, "protocol_tree_expander_style",
3058 "Protocol-tree expander style",
3059 "Protocol-tree expander style",
3060 &prefs.gui_ptree_expander_style, gui_ptree_expander_style, FALSE);
3062 prefs_register_enum_preference(gui_module, "hex_dump_highlight_style",
3063 "Hex dump highlight style",
3064 "Hex dump highlight style",
3065 &prefs.gui_hex_dump_highlight_style, gui_hex_dump_highlight_style, FALSE);
3067 gui_column_module = prefs_register_subtree(gui_module, "Columns", "Columns", NULL);
3069 custom_cbs.free_cb = free_string_like_preference;
3070 custom_cbs.reset_cb = reset_string_like_preference;
3071 custom_cbs.set_cb = column_hidden_set_cb;
3072 custom_cbs.type_name_cb = column_hidden_type_name_cb;
3073 custom_cbs.type_description_cb = column_hidden_type_description_cb;
3074 custom_cbs.is_default_cb = column_hidden_is_default_cb;
3075 custom_cbs.to_str_cb = column_hidden_to_str_cb;
3076 register_string_like_preference(gui_column_module, PRS_COL_HIDDEN, "Packet list hidden columns",
3077 "List all columns to hide in the packet list",
3078 &cols_hidden_list, PREF_CUSTOM, &custom_cbs, FALSE);
3080 custom_cbs.free_cb = column_format_free_cb;
3081 custom_cbs.reset_cb = column_format_reset_cb;
3082 custom_cbs.set_cb = column_format_set_cb;
3083 custom_cbs.type_name_cb = column_format_type_name_cb;
3084 custom_cbs.type_description_cb = column_format_type_description_cb;
3085 custom_cbs.is_default_cb = column_format_is_default_cb;
3086 custom_cbs.to_str_cb = column_format_to_str_cb;
3088 prefs_register_list_custom_preference(gui_column_module, PRS_COL_FMT, "Packet list column format",
3089 "Each pair of strings consists of a column title and its format", &custom_cbs,
3090 column_format_init_cb, &prefs.col_list);
3092 /* Number of columns. This is only used internally and is not written to the
3095 custom_cbs.free_cb = custom_pref_no_cb;
3096 custom_cbs.reset_cb = column_num_reset_cb;
3097 custom_cbs.set_cb = column_num_set_cb;
3098 custom_cbs.type_name_cb = column_num_type_name_cb;
3099 custom_cbs.type_description_cb = column_num_type_description_cb;
3100 custom_cbs.is_default_cb = column_num_is_default_cb;
3101 custom_cbs.to_str_cb = column_num_to_str_cb;
3102 prefs_register_uint_custom_preference(gui_column_module, PRS_COL_NUM, "Number of columns",
3103 "Number of columns in col_list", &custom_cbs, &prefs.num_cols);
3105 /* User Interface : Font */
3106 gui_font_module = prefs_register_subtree(gui_module, "Font", "Font", NULL);
3108 prefs_register_obsolete_preference(gui_font_module, "font_name");
3110 register_string_like_preference(gui_font_module, "gtk2.font_name", "Font name",
3111 "Font name for packet list, protocol tree, and hex dump panes. (GTK+)",
3112 &prefs.gui_gtk2_font_name, PREF_STRING, NULL, TRUE);
3114 register_string_like_preference(gui_font_module, "qt.font_name", "Font name",
3115 "Font name for packet list, protocol tree, and hex dump panes. (Qt)",
3116 &prefs.gui_qt_font_name, PREF_STRING, NULL, TRUE);
3118 /* User Interface : Colors */
3119 gui_color_module = prefs_register_subtree(gui_module, "Colors", "Colors", NULL);
3121 prefs_register_color_preference(gui_color_module, "marked_frame.fg", "Color preferences for a marked frame",
3122 "Color preferences for a marked frame", &prefs.gui_marked_fg);
3124 prefs_register_color_preference(gui_color_module, "marked_frame.bg", "Color preferences for a marked frame",
3125 "Color preferences for a marked frame", &prefs.gui_marked_bg);
3127 prefs_register_color_preference(gui_color_module, "ignored_frame.fg", "Color preferences for a ignored frame",
3128 "Color preferences for a ignored frame", &prefs.gui_ignored_fg);
3130 prefs_register_color_preference(gui_color_module, "ignored_frame.bg", "Color preferences for a ignored frame",
3131 "Color preferences for a ignored frame", &prefs.gui_ignored_bg);
3133 prefs_register_color_preference(gui_color_module, "stream.client.fg", "TCP stream window color preference",
3134 "TCP stream window color preference", &prefs.st_client_fg);
3136 prefs_register_color_preference(gui_color_module, "stream.client.bg", "TCP stream window color preference",
3137 "TCP stream window color preference", &prefs.st_client_bg);
3139 prefs_register_color_preference(gui_color_module, "stream.server.fg", "TCP stream window color preference",
3140 "TCP stream window color preference", &prefs.st_server_fg);
3142 prefs_register_color_preference(gui_color_module, "stream.server.bg", "TCP stream window color preference",
3143 "TCP stream window color preference", &prefs.st_server_bg);
3145 custom_cbs.free_cb = free_string_like_preference;
3146 custom_cbs.reset_cb = reset_string_like_preference;
3147 custom_cbs.set_cb = colorized_frame_set_cb;
3148 custom_cbs.type_name_cb = colorized_frame_type_name_cb;
3149 custom_cbs.type_description_cb = colorized_frame_type_description_cb;
3150 custom_cbs.is_default_cb = colorized_frame_is_default_cb;
3151 custom_cbs.to_str_cb = colorized_frame_to_str_cb;
3152 register_string_like_preference(gui_column_module, "colorized_frame.fg", "Colorized Foreground",
3153 "Filter Colorized Foreground",
3154 &prefs.gui_colorized_fg, PREF_CUSTOM, &custom_cbs, TRUE);
3156 custom_cbs.free_cb = free_string_like_preference;
3157 custom_cbs.reset_cb = reset_string_like_preference;
3158 custom_cbs.set_cb = colorized_frame_set_cb;
3159 custom_cbs.type_name_cb = colorized_frame_type_name_cb;
3160 custom_cbs.type_description_cb = colorized_frame_type_description_cb;
3161 custom_cbs.is_default_cb = colorized_frame_is_default_cb;
3162 custom_cbs.to_str_cb = colorized_frame_to_str_cb;
3163 register_string_like_preference(gui_column_module, "colorized_frame.bg", "Colorized Background",
3164 "Filter Colorized Background",
3165 &prefs.gui_colorized_bg, PREF_CUSTOM, &custom_cbs, TRUE);
3167 prefs_register_color_preference(gui_color_module, "color_filter_bg.valid", "Valid color filter background",
3168 "Valid color filter background", &prefs.gui_text_valid);
3170 prefs_register_color_preference(gui_color_module, "color_filter_bg.invalid", "Invalid color filter background",
3171 "Invalid color filter background", &prefs.gui_text_invalid);
3173 prefs_register_color_preference(gui_color_module, "color_filter_bg.deprecated", "Deprecated color filter background",
3174 "Deprecated color filter background", &prefs.gui_text_deprecated);
3176 prefs_register_enum_preference(gui_module, "fileopen.style",
3177 "Where to start the File Open dialog box",
3178 "Where to start the File Open dialog box",
3179 &prefs.gui_fileopen_style, gui_fileopen_style, FALSE);
3181 prefs_register_uint_preference(gui_module, "recent_files_count.max",
3182 "The max. number of items in the open recent files list",
3183 "The max. number of items in the open recent files list",
3185 &prefs.gui_recent_files_count_max);
3187 prefs_register_uint_preference(gui_module, "recent_display_filter_entries.max",
3188 "The max. number of entries in the display filter list",
3189 "The max. number of entries in the display filter list",
3191 &prefs.gui_recent_df_entries_max);
3193 register_string_like_preference(gui_module, "fileopen.dir", "Start Directory",
3194 "Directory to start in when opening File Open dialog.",
3195 &prefs.gui_fileopen_dir, PREF_DIRNAME, NULL, TRUE);
3197 prefs_register_obsolete_preference(gui_module, "fileopen.remembered_dir");
3199 prefs_register_uint_preference(gui_module, "fileopen.preview",
3200 "The preview timeout in the File Open dialog",
3201 "The preview timeout in the File Open dialog",
3203 &prefs.gui_fileopen_preview);
3205 prefs_register_bool_preference(gui_module, "ask_unsaved",
3206 "Ask to save unsaved capture files",
3207 "Ask to save unsaved capture files?",
3208 &prefs.gui_ask_unsaved);
3210 prefs_register_bool_preference(gui_module, "find_wrap",
3211 "Wrap to beginning/end of file during search",
3212 "Wrap to beginning/end of file during search?",
3213 &prefs.gui_find_wrap);
3215 prefs_register_bool_preference(gui_module, "use_pref_save",
3216 "Settings dialogs use a save button",
3217 "Settings dialogs use a save button?",
3218 &prefs.gui_use_pref_save);
3220 prefs_register_bool_preference(gui_module, "geometry.save.position",
3221 "Save window position at exit",
3222 "Save window position at exit?",
3223 &prefs.gui_geometry_save_position);
3225 prefs_register_bool_preference(gui_module, "geometry.save.size",
3226 "Save window size at exit",
3227 "Save window size at exit?",
3228 &prefs.gui_geometry_save_size);
3230 prefs_register_bool_preference(gui_module, "geometry.save.maximized",
3231 "Save window maximized state at exit",
3232 "Save window maximized state at exit?",
3233 &prefs.gui_geometry_save_maximized);
3236 prefs_register_bool_preference(gui_module, "macosx_style",
3238 "Use macOS style (macOS with native GTK only)?",
3239 &prefs.gui_macosx_style);
3241 prefs_register_obsolete_preference(gui_module, "geometry.main.x");
3242 prefs_register_obsolete_preference(gui_module, "geometry.main.y");
3243 prefs_register_obsolete_preference(gui_module, "geometry.main.width");
3244 prefs_register_obsolete_preference(gui_module, "geometry.main.height");
3245 prefs_register_obsolete_preference(gui_module, "toolbar_main_show");
3247 prefs_register_enum_preference(gui_module, "toolbar_main_style",
3248 "Main Toolbar style",
3249 "Main Toolbar style",
3250 &prefs.gui_toolbar_main_style, gui_toolbar_style, FALSE);
3252 prefs_register_enum_preference(gui_module, "toolbar_filter_style",
3253 "Filter Toolbar style",
3254 "Filter Toolbar style",
3255 &prefs.gui_toolbar_filter_style, gui_toolbar_style, FALSE);
3257 register_string_like_preference(gui_module, "webbrowser", "The path to the webbrowser",
3258 "The path to the webbrowser (Ex: mozilla)",
3259 &prefs.gui_webbrowser, PREF_STRING, NULL, TRUE);
3261 prefs_register_bool_preference(gui_module, "update.enabled",
3262 "Check for updates",
3263 "Check for updates (Windows only)",
3264 &prefs.gui_update_enabled);
3266 prefs_register_enum_preference(gui_module, "update.channel",
3268 "The type of update to fetch. You should probably leave this set to UPDATE_CHANNEL_STABLE.",
3269 (gint*)(void*)(&prefs.gui_update_channel), gui_update_channel, FALSE);
3271 prefs_register_uint_preference(gui_module, "update.interval",
3272 "How often to check for software updates",
3273 "How often to check for software updates in seconds",
3275 &prefs.gui_update_interval);
3277 register_string_like_preference(gui_module, "window_title", "Custom window title",
3278 "Custom window title to be appended to the existing title\n%P = profile name\n%V = version info",
3279 &prefs.gui_window_title, PREF_STRING, NULL, TRUE);
3281 register_string_like_preference(gui_module, "prepend_window_title", "Custom window title prefix",
3282 "Custom window title to be prepended to the existing title\n%P = profile name\n%V = version info",
3283 &prefs.gui_prepend_window_title, PREF_STRING, NULL, TRUE);
3285 register_string_like_preference(gui_module, "start_title", "Custom start page title",
3286 "Custom start page title",
3287 &prefs.gui_start_title, PREF_STRING, NULL, TRUE);
3289 prefs_register_enum_preference(gui_module, "version_placement",
3290 "Show version in the start page and/or main screen's title bar",
3291 "Show version in the start page and/or main screen's title bar",
3292 (gint*)(void*)(&prefs.gui_version_placement), gui_version_placement_type, FALSE);
3294 prefs_register_bool_preference(gui_module, "auto_scroll_on_expand",
3295 "Automatically scroll packet details",
3296 "When selecting a new packet, automatically scroll"
3297 "to the packet detail item that matches the most"
3298 "recently selected item",
3299 &prefs.gui_auto_scroll_on_expand);
3301 prefs_register_uint_preference(gui_module, "auto_scroll_percentage",
3302 "Packet detail scroll percentage",
3303 "The percentage down the view the recently expanded detail item should be scrolled",
3305 &prefs.gui_auto_scroll_percentage);
3307 /* User Interface : Layout */
3308 gui_layout_module = prefs_register_subtree(gui_module, "Layout", "Layout", gui_layout_callback);
3309 /* Adjust the preference effects of layout GUI for better handling of preferences at Wireshark (GUI) level */
3310 layout_gui_flags = prefs_get_module_effect_flags(gui_layout_module);
3311 layout_gui_flags |= PREF_EFFECT_GUI_LAYOUT;
3312 layout_gui_flags &= (~PREF_EFFECT_DISSECTION);
3314 prefs_register_uint_preference(gui_layout_module, "layout_type",
3316 "Layout type (1-6)",
3318 (guint*)(void*)(&prefs.gui_layout_type));
3319 prefs_set_effect_flags_by_name(gui_layout_module, "layout_type", layout_gui_flags);
3321 prefs_register_enum_preference(gui_layout_module, "layout_content_1",
3322 "Layout content of the pane 1",
3323 "Layout content of the pane 1",
3324 (gint*)(void*)(&prefs.gui_layout_content_1), gui_layout_content, FALSE);
3325 prefs_set_effect_flags_by_name(gui_layout_module, "layout_content_1", layout_gui_flags);
3327 prefs_register_enum_preference(gui_layout_module, "layout_content_2",
3328 "Layout content of the pane 2",
3329 "Layout content of the pane 2",
3330 (gint*)(void*)(&prefs.gui_layout_content_2), gui_layout_content, FALSE);
3331 prefs_set_effect_flags_by_name(gui_layout_module, "layout_content_2", layout_gui_flags);
3333 prefs_register_enum_preference(gui_layout_module, "layout_content_3",
3334 "Layout content of the pane 3",
3335 "Layout content of the pane 3",
3336 (gint*)(void*)(&prefs.gui_layout_content_3), gui_layout_content, FALSE);
3337 prefs_set_effect_flags_by_name(gui_layout_module, "layout_content_3", layout_gui_flags);
3339 prefs_register_bool_preference(gui_layout_module, "packet_list_separator.enabled",
3340 "Enable Packet List Separator",
3341 "Enable Packet List Separator",
3342 &prefs.gui_qt_packet_list_separator);
3344 prefs_register_bool_preference(gui_layout_module, "show_selected_packet.enabled",
3345 "Show selected packet in the Status Bar",
3346 "Show selected packet in the Status Bar",
3347 &prefs.gui_qt_show_selected_packet);
3349 prefs_register_bool_preference(gui_layout_module, "show_file_load_time.enabled",
3350 "Show file load time in the Status Bar",
3351 "Show file load time in the Status Bar",
3352 &prefs.gui_qt_show_file_load_time);
3354 prefs_register_bool_preference(gui_module, "packet_editor.enabled",
3355 "Enable Packet Editor",
3356 "Enable Packet Editor (Experimental)",
3357 &prefs.gui_packet_editor);
3359 prefs_register_enum_preference(gui_module, "packet_list_elide_mode",
3361 "The position of \"...\" in packet list text.",
3362 (gint*)(void*)(&prefs.gui_packet_list_elide_mode), gui_packet_list_elide_mode, FALSE);
3364 prefs_register_bool_preference(gui_layout_module, "packet_list_show_related",
3365 "Show Related Packets",
3366 "Show related packet indicators in the first column",
3367 &prefs.gui_packet_list_show_related);
3369 prefs_register_bool_preference(gui_layout_module, "packet_list_show_minimap",
3370 "Enable Intelligent Scroll Bar",
3371 "Show the intelligent scroll bar (a minimap of packet list colors in the scrollbar)",
3372 &prefs.gui_packet_list_show_minimap);
3375 prefs_register_bool_preference(gui_module, "interfaces_show_hidden",
3376 "Show hidden interfaces",
3377 "Show all interfaces, including interfaces marked as hidden",
3378 &prefs.gui_interfaces_show_hidden);
3380 #ifdef HAVE_PCAP_REMOTE
3381 prefs_register_bool_preference(gui_module, "interfaces_remote_display",
3382 "Show Remote interfaces",
3383 "Show remote interfaces in the interface selection",
3384 &prefs.gui_interfaces_remote_display);
3387 register_string_like_preference(gui_module, "interfaces_hidden_types", "Hide interface types in list",
3388 "Hide the given interface types in the startup list",
3389 &prefs.gui_interfaces_hide_types, PREF_STRING, NULL, TRUE);
3392 * These are preferences that can be read/written using the
3393 * preference module API. These preferences still use their own
3394 * configuration screens for access, but this cuts down on the
3395 * preference "string compare list" in set_pref()
3397 console_module = prefs_register_module(NULL, "console", "Console",
3398 "Console logging and debugging output", NULL, FALSE);
3400 custom_cbs.free_cb = custom_pref_no_cb;
3401 custom_cbs.reset_cb = console_log_level_reset_cb;
3402 custom_cbs.set_cb = console_log_level_set_cb;
3403 custom_cbs.type_name_cb = console_log_level_type_name_cb;
3404 custom_cbs.type_description_cb = console_log_level_type_description_cb;
3405 custom_cbs.is_default_cb = console_log_level_is_default_cb;
3406 custom_cbs.to_str_cb = console_log_level_to_str_cb;
3407 prefs_register_uint_custom_preference(console_module, "log.level", "logging level",
3408 "A bitmask of GLib log levels", &custom_cbs, &prefs.console_log_level);
3410 prefs_register_bool_preference(console_module, "incomplete_dissectors_check_debug",
3411 "Print debug line for incomplete dissectors",
3412 "Look for dissectors that left some bytes undecoded (debug)",
3413 &prefs.incomplete_dissectors_check_debug);
3415 /* Display filter Expressions
3416 * This used to be an array of individual fields that has now been
3417 * converted to a UAT. Just make it part of the GUI category even
3418 * though the name of the preference will never be seen in preference
3421 filter_expression_register_uat(gui_module);
3424 * These are preferences that can be read/written using the
3425 * preference module API. These preferences still use their own
3426 * configuration screens for access, but this cuts down on the
3427 * preference "string compare list" in set_pref()
3429 capture_module = prefs_register_module(NULL, "capture", "Capture",
3430 "Capture preferences", NULL, FALSE);
3431 /* Capture preferences don't affect dissection */
3432 prefs_set_module_effect_flags(capture_module, PREF_EFFECT_CAPTURE);
3434 register_string_like_preference(capture_module, "device", "Default capture device",
3435 "Default capture device",
3436 &prefs.capture_device, PREF_STRING, NULL, FALSE);
3438 register_string_like_preference(capture_module, "devices_linktypes", "Interface link-layer header type",
3439 "Interface link-layer header types (Ex: en0(1),en1(143),...)",
3440 &prefs.capture_devices_linktypes, PREF_STRING, NULL, FALSE);
3442 register_string_like_preference(capture_module, "devices_descr", "Interface descriptions",
3443 "Interface descriptions (Ex: eth0(eth0 descr),eth1(eth1 descr),...)",
3444 &prefs.capture_devices_descr, PREF_STRING, NULL, FALSE);
3446 register_string_like_preference(capture_module, "devices_hide", "Hide interface",
3447 "Hide interface? (Ex: eth0,eth3,...)",
3448 &prefs.capture_devices_hide, PREF_STRING, NULL, FALSE);
3450 register_string_like_preference(capture_module, "devices_monitor_mode", "Capture in monitor mode",
3451 "By default, capture in monitor mode on interface? (Ex: eth0,eth3,...)",
3452 &prefs.capture_devices_monitor_mode, PREF_STRING, NULL, FALSE);
3454 #ifdef CAN_SET_CAPTURE_BUFFER_SIZE
3455 register_string_like_preference(capture_module, "devices_buffersize", "Interface buffer size",
3456 "Interface buffer size (Ex: en0(1),en1(143),...)",
3457 &prefs.capture_devices_buffersize, PREF_STRING, NULL, FALSE);
3460 register_string_like_preference(capture_module, "devices_snaplen", "Interface snap length",
3461 "Interface snap length (Ex: en0(65535),en1(1430),...)",
3462 &prefs.capture_devices_snaplen, PREF_STRING, NULL, FALSE);
3464 register_string_like_preference(capture_module, "devices_pmode", "Interface promiscuous mode",
3465 "Interface promiscuous mode (Ex: en0(0),en1(1),...)",
3466 &prefs.capture_devices_pmode, PREF_STRING, NULL, FALSE);
3468 prefs_register_bool_preference(capture_module, "prom_mode", "Capture in promiscuous mode",
3469 "Capture in promiscuous mode?", &prefs.capture_prom_mode);
3471 register_string_like_preference(capture_module, "devices_filter", "Interface capture filter",
3472 "Interface capture filter (Ex: en0(tcp),en1(udp),...)",
3473 &prefs.capture_devices_filter, PREF_STRING, NULL, FALSE);
3475 prefs_register_bool_preference(capture_module, "pcap_ng", "Capture in pcapng format",
3476 "Capture in pcapng format?", &prefs.capture_pcap_ng);
3478 prefs_register_bool_preference(capture_module, "real_time_update", "Update packet list in real time during capture",
3479 "Update packet list in real time during capture?", &prefs.capture_real_time);
3481 prefs_register_bool_preference(capture_module, "no_extcap", "Disable external capture interfaces",
3482 "Disable external capture modules (extcap)", &prefs.capture_no_extcap);
3484 /* We might want to make this a "recent" setting. */
3485 prefs_register_bool_preference(capture_module, "auto_scroll", "Scroll packet list during capture",
3486 "Scroll packet list during capture?", &prefs.capture_auto_scroll);
3489 prefs_register_bool_preference(capture_module, "show_info", "Show capture info dialog while capturing",
3490 "Show capture info dialog while capturing?", &prefs.capture_show_info);
3492 prefs_register_obsolete_preference(capture_module, "syntax_check_filter");
3494 custom_cbs.free_cb = capture_column_free_cb;
3495 custom_cbs.reset_cb = capture_column_reset_cb;
3496 custom_cbs.set_cb = capture_column_set_cb;
3497 custom_cbs.type_name_cb = capture_column_type_name_cb;
3498 custom_cbs.type_description_cb = capture_column_type_description_cb;
3499 custom_cbs.is_default_cb = capture_column_is_default_cb;
3500 custom_cbs.to_str_cb = capture_column_to_str_cb;
3501 prefs_register_list_custom_preference(capture_module, "columns", "Capture options dialog column list",
3502 "List of columns to be displayed", &custom_cbs, capture_column_init_cb, &prefs.capture_columns);
3504 /* Name Resolution */
3505 nameres_module = prefs_register_module(NULL, "nameres", "Name Resolution",
3506 "Name Resolution", NULL, TRUE);
3507 addr_resolve_pref_init(nameres_module);
3508 oid_pref_init(nameres_module);
3510 geoip_db_pref_init(nameres_module);
3514 printing = prefs_register_module(NULL, "print", "Printing",
3515 "Printing", NULL, TRUE);
3517 prefs_register_enum_preference(printing, "format",
3518 "Format", "Can be one of \"text\" or \"postscript\"",
3519 &prefs.pr_format, print_format_vals, TRUE);
3521 prefs_register_enum_preference(printing, "destination",
3522 "Print to", "Can be one of \"command\" or \"file\"",
3523 &prefs.pr_dest, print_dest_vals, TRUE);
3526 register_string_like_preference(printing, "command", "Command",
3527 "Output gets piped to this command when the destination is set to \"command\"",
3528 &prefs.pr_cmd, PREF_STRING, NULL, TRUE);
3531 register_string_like_preference(printing, "file", "File",
3532 "This is the file that gets written to when the destination is set to \"file\"",
3533 &prefs.pr_file, PREF_SAVE_FILENAME, NULL, TRUE);
3536 codecs_module = prefs_register_module(NULL, "codecs", "Codecs",
3537 "Codecs", NULL, TRUE);
3540 stats_module = prefs_register_module(NULL, "statistics", "Statistics",
3541 "Statistics", &stats_callback, TRUE);
3543 prefs_register_uint_preference(stats_module, "update_interval",
3544 "Tap update interval in ms",
3545 "Determines time between tap updates",
3547 &prefs.tap_update_interval);
3549 #ifdef HAVE_LIBPORTAUDIO
3550 prefs_register_uint_preference(stats_module, "rtp_player_max_visible",
3551 "Max visible channels in RTP Player",
3552 "Determines maximum height of RTP Player window",
3554 &prefs.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() only exists since 2.28. */
3806 g_list_foreach(sl, (GFunc)g_free, NULL);
3811 * Takes a string, a pointer to an array of "enum_val_t"s, and a default gint
3813 * The array must be terminated by an entry with a null "name" string.
3815 * If the string matches a "name" string in an entry, the value from that
3816 * entry is returned.
3818 * Otherwise, if a string matches a "description" string in an entry, the
3819 * value from that entry is returned; we do that for backwards compatibility,
3820 * as we used to have only a "name" string that was used both for command-line
3821 * and configuration-file values and in the GUI (which meant either that
3822 * the GUI had what might be somewhat cryptic values to select from or that
3823 * the "-o" flag took long strings, often with spaces in them).
3825 * Otherwise, the default value that was passed as the third argument is
3829 find_val_for_string(const char *needle, const enum_val_t *haystack,
3834 for (i = 0; haystack[i].name != NULL; i++) {
3835 if (g_ascii_strcasecmp(needle, haystack[i].name) == 0) {
3836 return haystack[i].value;
3839 for (i = 0; haystack[i].name != NULL; i++) {
3840 if (g_ascii_strcasecmp(needle, haystack[i].description) == 0) {
3841 return haystack[i].value;
3844 return default_value;
3848 /* Array of columns that have been migrated to custom columns */
3849 struct deprecated_columns {
3850 const gchar *col_fmt;
3851 const gchar *col_expr;
3853 static struct deprecated_columns migrated_columns[] = {
3854 { /* COL_COS_VALUE */ "%U", "vlan.priority" },
3855 { /* COL_CIRCUIT_ID */ "%c", "iax2.call" },
3856 { /* COL_BSSGP_TLLI */ "%l", "bssgp.tlli" },
3857 { /* COL_HPUX_SUBSYS */ "%H", "nettl.subsys" },
3858 { /* COL_HPUX_DEVID */ "%P", "nettl.devid" },
3859 { /* COL_FR_DLCI */ "%C", "fr.dlci" },
3860 { /* COL_REL_CONV_TIME */ "%rct", "tcp.time_relative" },
3861 { /* COL_DELTA_CONV_TIME */ "%dct", "tcp.time_delta" },
3862 { /* COL_OXID */ "%XO", "fc.ox_id" },
3863 { /* COL_RXID */ "%XR", "fc.rx_id" },
3864 { /* COL_SRCIDX */ "%Xd", "mdshdr.srcidx" },
3865 { /* COL_DSTIDX */ "%Xs", "mdshdr.dstidx" },
3866 { /* COL_DCE_CTX */ "%z", "dcerpc.cn_ctx_id" }
3870 is_deprecated_column_format(const gchar* fmt)
3874 for (haystack_idx = 0;
3875 haystack_idx < G_N_ELEMENTS(migrated_columns);
3878 if (strcmp(migrated_columns[haystack_idx].col_fmt, fmt) == 0) {
3886 /* Preferences file format:
3887 * - Configuration directives start at the beginning of the line, and
3888 * are terminated with a colon.
3889 * - Directives can be continued on the next line by preceding them with
3894 # This is a comment line
3896 print.file: /a/very/long/path/
3901 #define DEF_NUM_COLS 7
3904 * Parse a column format, filling in the relevant fields of a fmt_data.
3907 parse_column_format(fmt_data *cfmt, const char *fmt)
3909 const gchar *cust_format = col_format_to_string(COL_CUSTOM);
3910 size_t cust_format_len = strlen(cust_format);
3911 gchar **cust_format_info;
3914 gchar *col_custom_fields = NULL;
3915 long col_custom_occurrence = 0;
3916 gboolean col_resolved = TRUE;
3919 * Is this a custom column?
3921 if ((strlen(fmt) > cust_format_len) && (fmt[cust_format_len] == ':') &&
3922 strncmp(fmt, cust_format, cust_format_len) == 0) {
3924 col_fmt = COL_CUSTOM;
3925 cust_format_info = g_strsplit(&fmt[cust_format_len+1],":",3); /* add 1 for ':' */
3926 col_custom_fields = g_strdup(cust_format_info[0]);
3927 if (col_custom_fields && cust_format_info[1]) {
3928 col_custom_occurrence = strtol(cust_format_info[1], &p, 10);
3929 if (p == cust_format_info[1] || *p != '\0') {
3930 /* Not a valid number. */
3931 g_free(col_custom_fields);
3932 g_strfreev(cust_format_info);
3936 if (col_custom_fields && cust_format_info[1] && cust_format_info[2]) {
3937 col_resolved = (cust_format_info[2][0] == 'U') ? FALSE : TRUE;
3939 g_strfreev(cust_format_info);
3941 col_fmt = get_column_format_from_str(fmt);
3942 if ((col_fmt == -1) && (!is_deprecated_column_format(fmt)))
3946 cfmt->fmt = col_fmt;
3947 cfmt->custom_fields = col_custom_fields;
3948 cfmt->custom_occurrence = (int)col_custom_occurrence;
3949 cfmt->resolved = col_resolved;
3953 /* Initialize non-dissector preferences to wired-in default values Called
3954 * at program startup and any time the profile changes. (The dissector
3955 * preferences are assumed to be set to those values by the dissectors.)
3956 * They may be overridden by the global preferences file or the user's
3962 if (prefs_initialized)
3968 * Ensure the "global" preferences have been initialized so the
3969 * preference API has the proper default values to work from
3973 prefs_register_modules();
3975 prefs_initialized = TRUE;
3979 * Initialize non-dissector preferences used by the "register preference" API
3980 * to default values so the default values can be used when registered.
3982 * String, filename, and directory preferences will be g_freed so they must
3986 pre_init_prefs(void)
3991 static const gchar *col_fmt[DEF_NUM_COLS*2] = {
3992 "No.", "%m", "Time", "%t",
3993 "Source", "%s", "Destination", "%d",
3994 "Protocol", "%p", "Length", "%L",
3997 prefs.pr_format = PR_FMT_TEXT;
3998 prefs.pr_dest = PR_DEST_CMD;
3999 g_free(prefs.pr_file);
4000 prefs.pr_file = g_strdup("wireshark.out");
4001 g_free(prefs.pr_cmd);
4002 prefs.pr_cmd = g_strdup("lpr");
4004 prefs.gui_altern_colors = FALSE;
4005 prefs.gui_expert_composite_eyecandy = FALSE;
4006 prefs.gui_ptree_line_style = 0;
4007 prefs.gui_ptree_expander_style = 1;
4008 prefs.gui_hex_dump_highlight_style = 1; /* GTK+ only */
4009 prefs.filter_toolbar_show_in_statusbar = FALSE;
4010 prefs.restore_filter_after_following_stream = FALSE;
4011 prefs.gui_toolbar_main_style = TB_STYLE_ICONS;
4012 prefs.gui_toolbar_filter_style = TB_STYLE_TEXT;
4013 /* These will be g_freed, so they must be g_mallocated. */
4014 g_free(prefs.gui_gtk2_font_name);
4016 prefs.gui_gtk2_font_name = g_strdup("Lucida Console 10");
4018 prefs.gui_gtk2_font_name = g_strdup("Monospace 10");
4020 /* We try to find the best font in the Qt code */
4021 g_free(prefs.gui_qt_font_name);
4022 prefs.gui_qt_font_name = g_strdup("");
4023 prefs.gui_marked_fg.red = 65535;
4024 prefs.gui_marked_fg.green = 65535;
4025 prefs.gui_marked_fg.blue = 65535;
4026 prefs.gui_marked_bg.red = 0;
4027 prefs.gui_marked_bg.green = 8224;
4028 prefs.gui_marked_bg.blue = 10794;
4029 prefs.gui_ignored_fg.red = 32767;
4030 prefs.gui_ignored_fg.green = 32767;
4031 prefs.gui_ignored_fg.blue = 32767;
4032 prefs.gui_ignored_bg.red = 65535;
4033 prefs.gui_ignored_bg.green = 65535;
4034 prefs.gui_ignored_bg.blue = 65535;
4035 g_free(prefs.gui_colorized_fg);
4036 prefs.gui_colorized_fg = g_strdup("000000,000000,000000,000000,000000,000000,000000,000000,000000,000000");
4037 g_free(prefs.gui_colorized_bg);
4038 prefs.gui_colorized_bg = g_strdup("ffc0c0,ffc0ff,e0c0e0,c0c0ff,c0e0e0,c0ffff,c0ffc0,ffffc0,e0e0c0,e0e0e0");
4039 prefs.st_client_fg.red = 32767;
4040 prefs.st_client_fg.green = 0;
4041 prefs.st_client_fg.blue = 0;
4042 prefs.st_client_bg.red = 64507;
4043 prefs.st_client_bg.green = 60909;
4044 prefs.st_client_bg.blue = 60909;
4045 prefs.st_server_fg.red = 0;
4046 prefs.st_server_fg.green = 0;
4047 prefs.st_server_fg.blue = 32767;
4048 prefs.st_server_bg.red = 60909;
4049 prefs.st_server_bg.green = 60909;
4050 prefs.st_server_bg.blue = 64507;
4052 if (gui_theme_is_dark) {
4053 // Green, red and yellow with HSV V = 84
4054 prefs.gui_text_valid.red = 0x0000; /* dark green */
4055 prefs.gui_text_valid.green = 0x66ff;
4056 prefs.gui_text_valid.blue = 0x0000;
4057 prefs.gui_text_invalid.red = 0x66FF; /* dark red */
4058 prefs.gui_text_invalid.green = 0x0000;
4059 prefs.gui_text_invalid.blue = 0x0000;
4060 prefs.gui_text_deprecated.red = 0x66FF; /* dark yellow / olive */
4061 prefs.gui_text_deprecated.green = 0x66FF;
4062 prefs.gui_text_deprecated.blue = 0x0000;
4064 // Green, red and yellow with HSV V = 20
4065 prefs.gui_text_valid.red = 0xAFFF; /* light green */
4066 prefs.gui_text_valid.green = 0xFFFF;
4067 prefs.gui_text_valid.blue = 0xAFFF;
4068 prefs.gui_text_invalid.red = 0xFFFF; /* light red */
4069 prefs.gui_text_invalid.green = 0xAFFF;
4070 prefs.gui_text_invalid.blue = 0xAFFF;
4071 prefs.gui_text_deprecated.red = 0xFFFF; /* light yellow */
4072 prefs.gui_text_deprecated.green = 0xFFFF;
4073 prefs.gui_text_deprecated.blue = 0xAFFF;
4076 prefs.gui_geometry_save_position = TRUE;
4077 prefs.gui_geometry_save_size = TRUE;
4078 prefs.gui_geometry_save_maximized= TRUE;
4079 prefs.gui_macosx_style = TRUE;
4080 prefs.gui_console_open = console_open_never;
4081 prefs.gui_fileopen_style = FO_STYLE_LAST_OPENED;
4082 prefs.gui_recent_df_entries_max = 10;
4083 prefs.gui_recent_files_count_max = 10;
4084 g_free(prefs.gui_fileopen_dir);
4085 prefs.gui_fileopen_dir = g_strdup(get_persdatafile_dir());
4086 prefs.gui_fileopen_preview = 3;
4087 prefs.gui_ask_unsaved = TRUE;
4088 prefs.gui_find_wrap = TRUE;
4089 prefs.gui_use_pref_save = FALSE;
4090 prefs.gui_update_enabled = TRUE;
4091 prefs.gui_update_channel = UPDATE_CHANNEL_STABLE;
4092 prefs.gui_update_interval = 60*60*24; /* Seconds */
4093 g_free(prefs.gui_webbrowser);
4094 prefs.gui_webbrowser = g_strdup("");
4095 g_free(prefs.gui_window_title);
4096 prefs.gui_window_title = g_strdup("");
4097 g_free(prefs.gui_prepend_window_title);
4098 prefs.gui_prepend_window_title = g_strdup("");
4099 g_free(prefs.gui_start_title);
4100 prefs.gui_start_title = g_strdup("The World's Most Popular Network Protocol Analyzer");
4101 prefs.gui_version_placement = version_both;
4102 prefs.gui_auto_scroll_on_expand = FALSE;
4103 prefs.gui_auto_scroll_percentage = 0;
4104 prefs.gui_layout_type = layout_type_5;
4105 prefs.gui_layout_content_1 = layout_pane_content_plist;
4106 prefs.gui_layout_content_2 = layout_pane_content_pdetails;
4107 prefs.gui_layout_content_3 = layout_pane_content_pbytes;
4108 prefs.gui_packet_editor = FALSE;
4109 prefs.gui_packet_list_elide_mode = ELIDE_RIGHT;
4110 prefs.gui_packet_list_show_related = TRUE;
4111 prefs.gui_packet_list_show_minimap = TRUE;
4112 g_free (prefs.gui_interfaces_hide_types);
4113 prefs.gui_interfaces_hide_types = g_strdup("");
4114 prefs.gui_interfaces_show_hidden = FALSE;
4115 #ifdef HAVE_PCAP_REMOTE
4116 prefs.gui_interfaces_remote_display = TRUE;
4119 prefs.gui_qt_packet_list_separator = FALSE;
4120 prefs.gui_qt_show_selected_packet = FALSE;
4121 prefs.gui_qt_show_file_load_time = FALSE;
4123 if (prefs.col_list) {
4124 free_col_info(prefs.col_list);
4125 prefs.col_list = NULL;
4127 for (i = 0; i < DEF_NUM_COLS; i++) {
4128 cfmt = g_new(fmt_data,1);
4129 cfmt->title = g_strdup(col_fmt[i * 2]);
4130 parse_column_format(cfmt, col_fmt[(i * 2) + 1]);
4131 cfmt->visible = TRUE;
4132 cfmt->resolved = TRUE;
4133 cfmt->custom_fields = NULL;
4134 cfmt->custom_occurrence = 0;
4135 prefs.col_list = g_list_append(prefs.col_list, cfmt);
4137 prefs.num_cols = DEF_NUM_COLS;
4139 /* set the default values for the capture dialog box */
4140 prefs.capture_prom_mode = TRUE;
4141 #ifdef PCAP_NG_DEFAULT
4142 prefs.capture_pcap_ng = TRUE;
4144 prefs.capture_pcap_ng = FALSE;
4146 prefs.capture_real_time = TRUE;
4147 prefs.capture_no_extcap = FALSE;
4148 prefs.capture_auto_scroll = TRUE;
4149 prefs.capture_show_info = FALSE;
4151 if (!prefs.capture_columns) {
4152 /* First time through */
4153 for (i = 0; i < num_capture_cols; i++) {
4154 col_name = g_strdup(capture_cols[i]);
4155 prefs.capture_columns = g_list_append(prefs.capture_columns, col_name);
4159 prefs.console_log_level =
4160 G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR;
4162 /* set the default values for the tap/statistics dialog box */
4163 prefs.tap_update_interval = TAP_UPDATE_DEFAULT_INTERVAL;
4164 prefs.rtp_player_max_visible = RTP_PLAYER_DEFAULT_VISIBLE;
4165 prefs.st_enable_burstinfo = TRUE;
4166 prefs.st_burst_showcount = FALSE;
4167 prefs.st_burst_resolution = ST_DEF_BURSTRES;
4168 prefs.st_burst_windowlen = ST_DEF_BURSTLEN;
4169 prefs.st_sort_casesensitve = TRUE;
4170 prefs.st_sort_rng_fixorder = TRUE;
4171 prefs.st_sort_rng_nameonly = TRUE;
4172 prefs.st_sort_defcolflag = ST_SORT_COL_COUNT;
4173 prefs.st_sort_defdescending = TRUE;
4174 prefs.st_sort_showfullname = FALSE;
4175 prefs.display_hidden_proto_items = FALSE;
4176 prefs.display_byte_fields_with_spaces = FALSE;
4180 * Reset a single dissector preference.
4183 reset_pref(pref_t *pref)
4191 * This preference is no longer supported; it's not a
4192 * real preference, so we don't reset it (i.e., we
4193 * treat it as if it weren't found in the list of
4194 * preferences, and we weren't called in the first place).
4196 if (IS_PREF_OBSOLETE(type))
4199 RESET_PREF_OBSOLETE(type);
4204 case PREF_DECODE_AS_UINT:
4205 *pref->varp.uint = pref->default_val.uint;
4209 *pref->varp.boolp = pref->default_val.boolval;
4214 * For now, we save the "description" value, so that if we
4215 * save the preferences older versions of Wireshark can at
4216 * least read preferences that they supported; we support
4217 * either the short name or the description when reading
4218 * the preferences file or a "-o" option.
4220 *pref->varp.enump = pref->default_val.enumval;
4224 case PREF_SAVE_FILENAME:
4225 case PREF_OPEN_FILENAME:
4227 reset_string_like_preference(pref);
4231 case PREF_DECODE_AS_RANGE:
4232 wmem_free(wmem_epan_scope(), *pref->varp.range);
4233 *pref->varp.range = range_copy(wmem_epan_scope(), pref->default_val.range);
4236 case PREF_STATIC_TEXT:
4242 *pref->varp.colorp = pref->default_val.color;
4246 pref->custom_cbs.reset_cb(pref);
4252 reset_pref_cb(gpointer data, gpointer user_data _U_)
4254 pref_t *pref = (pref_t *) data;
4263 * Reset all preferences for a module.
4266 reset_module_prefs(const void *key _U_, void *value, void *data _U_)
4268 reset_pref_arg_t arg;
4270 arg.module = (module_t *)value;
4271 g_list_foreach(arg.module->prefs, reset_pref_cb, &arg);
4275 /* Reset preferences */
4279 prefs_initialized = FALSE;
4280 g_free(prefs.saved_at_version);
4281 prefs.saved_at_version = NULL;
4284 * Unload all UAT preferences.
4289 * Unload any loaded MIBs.
4294 * Reset the non-dissector preferences.
4299 * Reset the non-UAT dissector preferences.
4301 wmem_tree_foreach(prefs_modules, reset_module_prefs, NULL);
4304 /* Read the preferences file, fill in "prefs", and return a pointer to it.
4306 If we got an error (other than "it doesn't exist") we report it through
4315 /* clean up libsmi structures before reading prefs */
4321 * If we don't already have the pathname of the global preferences
4322 * file, construct it. Then, in either case, try to open the file.
4324 if (gpf_path == NULL) {
4326 * We don't have the path; try the new path first, and, if that
4327 * file doesn't exist, try the old path.
4329 gpf_path = get_datafile_path(PF_NAME);
4330 if ((pf = ws_fopen(gpf_path, "r")) == NULL && errno == ENOENT) {
4332 * It doesn't exist by the new name; try the old name.
4335 gpf_path = get_datafile_path(OLD_GPF_NAME);
4336 pf = ws_fopen(gpf_path, "r");
4340 * We have the path; try it.
4342 pf = ws_fopen(gpf_path, "r");
4346 * If we were able to open the file, read it.
4347 * XXX - if it failed for a reason other than "it doesn't exist",
4352 * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
4355 mgcp_tcp_port_count = 0;
4356 mgcp_udp_port_count = 0;
4358 /* We succeeded in opening it; read it. */
4359 err = read_prefs_file(gpf_path, pf, set_pref, NULL);
4361 /* We had an error reading the file; report it. */
4362 report_warning("Error reading global preferences file \"%s\": %s.",
4363 gpf_path, g_strerror(err));
4367 /* We failed to open it. If we failed for some reason other than
4368 "it doesn't exist", report the error. */
4369 if (errno != ENOENT) {
4371 report_warning("Can't open global preferences file \"%s\": %s.",
4372 gpf_path, g_strerror(errno));
4377 /* Construct the pathname of the user's preferences file. */
4378 pf_path = get_persconffile_path(PF_NAME, TRUE);
4380 /* Read the user's preferences file, if it exists. */
4381 if ((pf = ws_fopen(pf_path, "r")) != NULL) {
4383 * Start out the counters of "mgcp.{tcp,udp}.port" entries we've
4386 mgcp_tcp_port_count = 0;
4387 mgcp_udp_port_count = 0;
4389 /* We succeeded in opening it; read it. */
4390 err = read_prefs_file(pf_path, pf, set_pref, NULL);
4392 /* We had an error reading the file; report it. */
4393 report_warning("Error reading your preferences file \"%s\": %s.",
4394 pf_path, g_strerror(err));
4399 /* We failed to open it. If we failed for some reason other than
4400 "it doesn't exist", return the errno and the pathname, so our
4401 caller can report the error. */
4402 if (errno != ENOENT) {
4403 report_warning("Can't open your preferences file \"%s\": %s.",
4404 pf_path, g_strerror(errno));
4409 /* load SMI modules if needed */
4415 /* read the preferences file (or similar) and call the callback
4416 * function to set each key/value pair found */
4418 read_prefs_file(const char *pf_path, FILE *pf,
4419 pref_set_pair_cb pref_set_pair_fct, void *private_data)
4422 START, /* beginning of a line */
4423 IN_VAR, /* processing key name */
4424 PRE_VAL, /* finished processing key name, skipping white space befor evalue */
4425 IN_VAL, /* processing value */
4426 IN_SKIP /* skipping to the end of the line */
4431 gboolean got_val = FALSE;
4432 gint fline = 1, pline = 1;
4433 gchar hint[] = "(save preferences to remove this warning)";
4436 cur_val = g_string_new("");
4437 cur_var = g_string_new("");
4439 /* Try to read in the profile name in the first line of the preferences file. */
4440 if (fscanf(pf, "# Configuration file for %127[^\r\n]", ver) == 1) {
4441 /* Assume trailing period and remove it */
4442 g_free(prefs.saved_at_version);
4443 prefs.saved_at_version = g_strndup(ver, strlen(ver) - 1);
4447 while ((got_c = ws_getc_unlocked(pf)) != EOF) {
4448 if (got_c == '\r') {
4449 /* Treat CR-LF at the end of a line like LF, so that if we're reading
4450 * a Windows-format file on UN*X, we handle it the same way we'd handle
4451 * a UN*X-format file. */
4452 got_c = ws_getc_unlocked(pf);
4455 if (got_c != '\n') {
4456 /* Put back the character after the CR, and process the CR normally. */
4461 if (got_c == '\n') {
4469 if (g_ascii_isalnum(got_c)) {
4470 if (cur_var->len > 0) {
4472 if (cur_val->len > 0) {
4473 if (cur_val->str[cur_val->len-1] == ',') {
4475 * If the pref has a trailing comma, eliminate it.
4477 cur_val->str[cur_val->len-1] = '\0';
4478 ws_g_warning ("%s line %d: trailing comma in \"%s\" %s", pf_path, pline, cur_var->str, hint);
4481 /* Call the routine to set the preference; it will parse
4482 the value as appropriate.
4484 Since we're reading a file, rather than processing
4485 explicit user input, for range preferences, silently
4486 lower values in excess of the range's maximum, rather
4487 than reporting errors and failing. */
4488 switch (pref_set_pair_fct(cur_var->str, cur_val->str, private_data, FALSE)) {
4493 case PREFS_SET_SYNTAX_ERR:
4494 ws_g_warning ("Syntax error in preference \"%s\" at line %d of\n%s %s",
4495 cur_var->str, pline, pf_path, hint);
4498 case PREFS_SET_NO_SUCH_PREF:
4500 * If "print.command" silently ignore it because it's valid
4501 * on non-Win32 platforms.
4503 if (strcmp(cur_var->str, "print.command") != 0)
4504 ws_g_warning ("No such preference \"%s\" at line %d of\n%s %s",
4505 cur_var->str, pline, pf_path, hint);
4506 prefs.unknown_prefs = TRUE;
4509 case PREFS_SET_OBSOLETE:
4510 if (strcmp(cur_var->str, "print.command") != 0)
4511 /* If an attempt is made to save the preferences, a popup warning will be
4512 displayed stating that obsolete prefs have been detected and the user will
4513 be given the opportunity to save these prefs under a different profile name.
4514 The prefs in question need to be listed in the console window so that the
4515 user can make an informed choice.
4517 ws_g_warning ("Obsolete preference \"%s\" at line %d of\n%s %s",
4518 cur_var->str, pline, pf_path, hint);
4519 prefs.unknown_prefs = TRUE;
4523 ws_g_warning ("Incomplete preference at line %d: of\n%s %s", pline, pf_path, hint);
4528 g_string_truncate(cur_var, 0);
4529 g_string_append_c(cur_var, (gchar) got_c);
4531 } else if (g_ascii_isspace(got_c) && cur_var->len > 0 && got_val) {
4533 } else if (got_c == '#') {
4536 ws_g_warning ("Malformed preference at line %d of\n%s %s", fline, pf_path, hint);
4541 g_string_append_c(cur_var, (gchar) got_c);
4543 /* This is a colon (':') */
4545 g_string_truncate(cur_val, 0);
4547 * Set got_val to TRUE to accommodate prefs such as
4548 * "gui.fileopen.dir" that do not require a value.
4554 if (!g_ascii_isspace(got_c)) {
4556 g_string_append_c(cur_val, (gchar) got_c);
4560 g_string_append_c(cur_val, (gchar) got_c);
4566 if (cur_var->len > 0) {
4568 /* Call the routine to set the preference; it will parse
4569 the value as appropriate.
4571 Since we're reading a file, rather than processing
4572 explicit user input, for range preferences, silently
4573 lower values in excess of the range's maximum, rather
4574 than reporting errors and failing. */
4575 switch (pref_set_pair_fct(cur_var->str, cur_val->str, private_data, FALSE)) {
4580 case PREFS_SET_SYNTAX_ERR:
4581 ws_g_warning ("Syntax error in preference %s at line %d of\n%s %s",
4582 cur_var->str, pline, pf_path, hint);
4585 case PREFS_SET_NO_SUCH_PREF:
4586 ws_g_warning ("No such preference \"%s\" at line %d of\n%s %s",
4587 cur_var->str, pline, pf_path, hint);
4588 prefs.unknown_prefs = TRUE;
4591 case PREFS_SET_OBSOLETE:
4592 prefs.unknown_prefs = TRUE;
4596 ws_g_warning("Incomplete preference at line %d of\n%s %s",
4597 pline, pf_path, hint);
4601 g_string_free(cur_val, TRUE);
4602 g_string_free(cur_var, TRUE);
4611 * If we were handed a preference starting with "uat:", try to turn it into
4612 * a valid uat entry.
4615 prefs_set_uat_pref(char *uat_entry, char **errmsg) {
4620 colonp = strchr(uat_entry, ':');
4628 * Skip over any white space (there probably won't be any, but
4629 * as we allow it in the preferences file, we might as well
4632 while (g_ascii_isspace(*p))
4636 * Put the colon back, so if our caller uses, in an
4637 * error message, the string they passed us, the message
4644 uat = uat_find(uat_entry);
4647 *errmsg = g_strdup("Unknown preference");
4651 ret = uat_load_str(uat, p, errmsg);
4656 * Given a string of the form "<pref name>:<pref value>", as might appear
4657 * as an argument to a "-o" option, parse it and set the preference in
4658 * question. Return an indication of whether it succeeded or failed
4662 prefs_set_pref(char *prefarg, char **errmsg)
4665 prefs_set_pref_e ret;
4668 * Set the counters of "mgcp.{tcp,udp}.port" entries we've
4669 * seen to values that keep us from trying to interpret them
4670 * as "mgcp.{tcp,udp}.gateway_port" or "mgcp.{tcp,udp}.callagent_port",
4671 * as, from the command line, we have no way of guessing which
4672 * the user had in mind.
4674 mgcp_tcp_port_count = -1;
4675 mgcp_udp_port_count = -1;
4679 colonp = strchr(prefarg, ':');
4681 return PREFS_SET_SYNTAX_ERR;
4687 * Skip over any white space (there probably won't be any, but
4688 * as we allow it in the preferences file, we might as well
4691 while (g_ascii_isspace(*p))
4695 * Put the colon back, so if our caller uses, in an
4696 * error message, the string they passed us, the message
4700 return PREFS_SET_SYNTAX_ERR;
4702 if (strcmp(prefarg, "uat")) {
4703 ret = set_pref(prefarg, p, NULL, TRUE);
4705 ret = prefs_set_uat_pref(p, errmsg) ? PREFS_SET_OK : PREFS_SET_SYNTAX_ERR;
4707 *colonp = ':'; /* put the colon back */
4711 guint prefs_get_uint_value_real(pref_t *pref, pref_source_t source)
4716 return pref->default_val.uint;
4719 return pref->stashed_val.uint;
4722 return *pref->varp.uint;
4725 g_assert_not_reached();
4732 guint prefs_get_uint_value(const char *module_name, const char* pref_name)
4734 return prefs_get_uint_value_real(prefs_find_preference(prefs_find_module(module_name), pref_name), pref_current);
4737 unsigned int prefs_set_uint_value(pref_t *pref, guint value, pref_source_t source)
4739 unsigned int changed = 0;
4743 if (pref->default_val.uint != value) {
4744 pref->default_val.uint = value;
4745 changed = prefs_get_effect_flags(pref);
4749 if (pref->stashed_val.uint != value) {
4750 pref->stashed_val.uint = value;
4751 changed = prefs_get_effect_flags(pref);
4755 if (*pref->varp.uint != value) {
4756 *pref->varp.uint = value;
4757 changed = prefs_get_effect_flags(pref);
4761 g_assert_not_reached();
4768 guint prefs_get_uint_base(pref_t *pref)
4770 return pref->info.base;
4774 * Returns TRUE if the given device is hidden
4777 prefs_is_capture_device_hidden(const char *name)
4779 gchar *tok, *devices;
4782 if (prefs.capture_devices_hide && name) {
4783 devices = g_strdup (prefs.capture_devices_hide);
4784 len = strlen (name);
4785 for (tok = strtok (devices, ","); tok; tok = strtok(NULL, ",")) {
4786 if (strlen (tok) == len && strcmp (name, tok) == 0) {
4798 * Returns TRUE if the given column is visible (not hidden)
4801 prefs_is_column_visible(const gchar *cols_hidden, fmt_data *cfmt)
4804 fmt_data cfmt_hidden;
4807 * Do we have a list of hidden columns?
4811 * Yes - check the column against each of the ones in the
4814 cols = g_strdup(cols_hidden);
4815 for (tok = strtok(cols, ","); tok; tok = strtok(NULL, ",")) {
4816 tok = g_strstrip(tok);
4819 * Parse this column format.
4821 if (!parse_column_format(&cfmt_hidden, tok)) {
4823 * It's not valid; ignore it.
4829 * Does it match the column?
4831 if (cfmt->fmt != cfmt_hidden.fmt) {
4833 g_free(cfmt_hidden.custom_fields);
4834 cfmt_hidden.custom_fields = NULL;
4837 if (cfmt->fmt == COL_CUSTOM) {
4839 * A custom column has to have the
4840 * same custom field and occurrence.
4842 if (cfmt_hidden.custom_fields && cfmt->custom_fields) {
4843 if (strcmp(cfmt->custom_fields,
4844 cfmt_hidden.custom_fields) != 0) {
4845 /* Different fields. */
4846 g_free(cfmt_hidden.custom_fields);
4847 cfmt_hidden.custom_fields = NULL;
4850 if (cfmt->custom_occurrence != cfmt_hidden.custom_occurrence) {
4851 /* Different occurrences. */
4852 g_free(cfmt_hidden.custom_fields);
4853 cfmt_hidden.custom_fields = NULL;
4860 * OK, they match, so it's one of the hidden fields,
4861 * hence not visible.
4863 g_free(cfmt_hidden.custom_fields);
4871 * No - either there are no hidden columns or this isn't one
4872 * of them - so it is visible.
4878 * Returns TRUE if the given device should capture in monitor mode by default
4881 prefs_capture_device_monitor_mode(const char *name)
4883 gchar *tok, *devices;
4886 if (prefs.capture_devices_monitor_mode && name) {
4887 devices = g_strdup (prefs.capture_devices_monitor_mode);
4888 len = strlen (name);
4889 for (tok = strtok (devices, ","); tok; tok = strtok(NULL, ",")) {
4890 if (strlen (tok) == len && strcmp (name, tok) == 0) {
4902 * Returns TRUE if the user has marked this column as visible
4905 prefs_capture_options_dialog_column_is_visible(const gchar *column)
4910 for (curr = g_list_first(prefs.capture_columns); curr; curr = g_list_next(curr)) {
4911 col = (gchar *)curr->data;
4912 if (col && (g_ascii_strcasecmp(col, column) == 0)) {
4920 prefs_has_layout_pane_content (layout_pane_content_e layout_pane_content)
4922 return ((prefs.gui_layout_content_1 == layout_pane_content) ||
4923 (prefs.gui_layout_content_2 == layout_pane_content) ||
4924 (prefs.gui_layout_content_3 == layout_pane_content));
4927 #define PRS_GUI_FILTER_LABEL "gui.filter_expressions.label"
4928 #define PRS_GUI_FILTER_EXPR "gui.filter_expressions.expr"
4929 #define PRS_GUI_FILTER_ENABLED "gui.filter_expressions.enabled"
4932 * Extract the red, green, and blue components of a 24-bit RGB value
4933 * and convert them from [0,255] to [0,65535].
4935 #define RED_COMPONENT(x) (guint16) (((((x) >> 16) & 0xff) * 65535 / 255))
4936 #define GREEN_COMPONENT(x) (guint16) (((((x) >> 8) & 0xff) * 65535 / 255))
4937 #define BLUE_COMPONENT(x) (guint16) ( (((x) & 0xff) * 65535 / 255))
4940 string_to_name_resolve(const char *string, e_addr_resolve *name_resolve)
4944 memset(name_resolve, 0, sizeof(e_addr_resolve));
4945 while ((c = *string++) != '\0') {
4948 name_resolve->mac_name = TRUE;
4951 name_resolve->network_name = TRUE;
4954 name_resolve->use_external_net_name_resolver = TRUE;
4957 name_resolve->transport_name = TRUE;
4961 /* name_resolve->concurrent_dns */
4964 name_resolve->dns_pkt_addr_resolution = TRUE;
4967 name_resolve->vlan_name = TRUE;
4971 * Unrecognized letter.
4980 try_convert_to_custom_column(gpointer *el_data)
4984 gchar **fmt = (gchar **) el_data;
4986 for (haystack_idx = 0;
4987 haystack_idx < G_N_ELEMENTS(migrated_columns);
4990 if (strcmp(migrated_columns[haystack_idx].col_fmt, *fmt) == 0) {
4991 gchar *cust_col = g_strdup_printf("%%Cus:%s:0",
4992 migrated_columns[haystack_idx].col_expr);
5001 deprecated_heur_dissector_pref(gchar *pref_name, const gchar *value)
5003 struct heur_pref_name
5005 const char* pref_name;
5006 const char* short_name;
5007 gboolean more_dissectors; /* For multiple dissectors controlled by the same preference */
5010 struct heur_pref_name heur_prefs[] = {
5011 {"acn.heuristic_acn", "acn_udp", 0},
5012 {"bfcp.enable", "bfcp_tcp", 1},
5013 {"bfcp.enable", "bfcp_udp", 0},
5014 {"bt-dht.enable", "bittorrent_dht_udp", 0},
5015 {"bt-utp.enable", "bt_utp_udp", 0},
5016 {"cattp.enable", "cattp_udp", 0},
5017 {"cfp.enable", "fp_eth", 0},
5018 {"dicom.heuristic", "dicom_tcp", 0},
5019 {"dnp3.heuristics", "dnp3_tcp", 1},
5020 {"dnp3.heuristics", "dnp3_udp", 0},
5021 {"dvb-s2_modeadapt.enable", "dvb_s2_udp", 0},
5022 {"esl.enable", "esl_eth", 0},
5023 {"fp.udp_heur", "fp_udp", 0},
5024 {"gvsp.enable_heuristic", "gvsp_udp", 0},
5025 {"hdcp2.enable", "hdcp2_tcp", 0},
5026 {"hislip.enable_heuristic", "hislip_tcp", 0},
5027 {"infiniband.dissect_eoib", "mellanox_eoib", 1},
5028 {"infiniband.identify_payload", "eth_over_ib", 0},
5029 {"jxta.udp.heuristic", "jxta_udp", 0},
5030 {"jxta.tcp.heuristic", "jxta_tcp", 0},
5031 {"jxta.sctp.heuristic", "jxta_sctp", 0},
5032 {"mac-lte.heuristic_mac_lte_over_udp", "mac_lte_udp", 0},
5033 {"mbim.bulk_heuristic", "mbim_usb_bulk", 0},
5034 {"norm.heuristic_norm", "rmt_norm_udp", 0},
5035 {"openflow.heuristic", "openflow_tcp", 0},
5036 {"pdcp-lte.heuristic_pdcp_lte_over_udp", "pdcp_lte_udp", 0},
5037 {"rlc.heuristic_rlc_over_udp", "rlc_udp", 0},
5038 {"rlc-lte.heuristic_rlc_lte_over_udp", "rlc_lte_udp", 0},
5039 {"rtcp.heuristic_rtcp", "rtcp_udp", 1},
5040 {"rtcp.heuristic_rtcp", "rtcp_stun", 0},
5041 {"rtp.heuristic_rtp", "rtp_udp", 1},
5042 {"rtp.heuristic_rtp", "rtp_stun", 0},
5043 {"teredo.heuristic_teredo", "teredo_udp", 0},
5044 {"vssmonitoring.use_heuristics", "vssmonitoring_eth", 0},
5045 {"xml.heuristic", "xml_http", 1},
5046 {"xml.heuristic", "xml_sip", 1},
5047 {"xml.heuristic", "xml_media", 0},
5048 {"xml.heuristic_tcp", "xml_tcp", 0},
5049 {"xml.heuristic_udp", "xml_udp", 0},
5053 heur_dtbl_entry_t* heuristic;
5056 for (i = 0; i < sizeof(heur_prefs)/sizeof(struct heur_pref_name); i++)
5058 if (strcmp(pref_name, heur_prefs[i].pref_name) == 0)
5060 heuristic = find_heur_dissector_by_unique_short_name(heur_prefs[i].short_name);
5061 if (heuristic != NULL) {
5062 heuristic->enabled = ((g_ascii_strcasecmp(value, "true") == 0) ? TRUE : FALSE);
5065 if (!heur_prefs[i].more_dissectors)
5075 deprecated_enable_dissector_pref(gchar *pref_name, const gchar *value)
5077 struct dissector_pref_name
5079 const char* pref_name;
5080 const char* short_name;
5083 struct dissector_pref_name dissector_prefs[] = {
5084 {"transum.tsumenabled", "TRANSUM"},
5085 {"snort.enable_snort_dissector", "Snort"},
5086 {"prp.enable", "PRP"},
5092 for (i = 0; i < sizeof(dissector_prefs)/sizeof(struct dissector_pref_name); i++)
5094 if (strcmp(pref_name, dissector_prefs[i].pref_name) == 0)
5096 proto_id = proto_get_id_by_short_name(dissector_prefs[i].short_name);
5098 proto_set_decoding(proto_id, ((g_ascii_strcasecmp(value, "true") == 0) ? TRUE : FALSE));
5107 deprecated_port_pref(gchar *pref_name, const gchar *value)
5109 struct port_pref_name
5111 const char* pref_name;
5112 const char* module_name;
5113 const char* table_name;
5117 struct obsolete_pref_name
5119 const char* pref_name;
5122 /* For now this is only supporting TCP/UDP port dissector preferences
5123 which are assumed to be decimal */
5124 struct port_pref_name port_prefs[] = {
5126 {"cmp.tcp_alternate_port", "CMP", "tcp.port", 10},
5127 {"h248.tcp_port", "H248", "tcp.port", 10},
5128 {"cops.tcp.cops_port", "COPS", "tcp.port", 10},
5129 {"dhcpfo.tcp_port", "DHCPFO", "tcp.port", 10},
5130 {"enttec.tcp_port", "ENTTEC", "tcp.port", 10},
5131 {"forces.tcp_alternate_port", "ForCES", "tcp.port", 10},
5132 {"ged125.tcp_port", "GED125", "tcp.port", 10},
5133 {"hpfeeds.dissector_port", "HPFEEDS", "tcp.port", 10},
5134 {"lsc.port", "LSC", "tcp.port", 10},
5135 {"megaco.tcp.txt_port", "MEGACO", "tcp.port", 10},
5136 {"netsync.tcp_port", "Netsync", "tcp.port", 10},
5137 {"osi.tpkt_port", "OSI", "tcp.port", 10},
5138 {"rsync.tcp_port", "RSYNC", "tcp.port", 10},
5139 {"sametime.tcp_port", "SAMETIME", "tcp.port", 10},
5140 {"sigcomp.tcp.port2", "SIGCOMP", "tcp.port", 10},
5141 {"synphasor.tcp_port", "SYNCHROPHASOR", "tcp.port", 10},
5142 {"tipc.alternate_port", "TIPC", "tcp.port", 10},
5143 {"vnc.alternate_port", "VNC", "tcp.port", 10},
5144 {"scop.port", "SCoP", "tcp.port", 10},
5145 {"scop.port_secure", "SCoP", "tcp.port", 10},
5147 {"h248.udp_port", "H248", "udp.port", 10},
5148 {"actrace.udp_port", "ACtrace", "udp.port", 10},
5149 {"brp.port", "BRP", "udp.port", 10},
5150 {"bvlc.additional_udp_port", "BVLC", "udp.port", 10},
5151 {"capwap.udp.port.control", "CAPWAP-CONTROL", "udp.port", 10},
5152 {"capwap.udp.port.data", "CAPWAP-CONTROL", "udp.port", 10},
5153 {"coap.udp_port", "CoAP", "udp.port", 10},
5154 {"enttec.udp_port", "ENTTEC", "udp.port", 10},
5155 {"forces.udp_alternate_port", "ForCES", "udp.port", 10},
5156 {"ldss.udp_port", "LDSS", "udp.port", 10},
5157 {"lmp.udp_port", "LMP", "udp.port", 10},
5158 {"ltp.port", "LTP", "udp.port", 10},
5159 {"lwres.udp.lwres_port", "LWRES", "udp.port", 10},
5160 {"megaco.udp.txt_port", "MEGACO", "udp.port", 10},
5161 {"pgm.udp.encap_ucast_port", "PGM", "udp.port", 10},
5162 {"pgm.udp.encap_mcast_port", "PGM", "udp.port", 10},
5163 {"quic.udp.quic.port", "QUIC", "udp.port", 10},
5164 {"quic.udp.quics.port", "QUIC", "udp.port", 10},
5165 {"radius.alternate_port", "RADIUS", "udp.port", 10},
5166 {"rdt.default_udp_port", "RDT", "udp.port", 10},
5167 {"alc.default.udp_port", "ALC", "udp.port", 10},
5168 {"sigcomp.udp.port2", "SIGCOMP", "udp.port", 10},
5169 {"synphasor.udp_port", "SYNCHROPHASOR", "udp.port", 10},
5170 {"tdmop.udpport", "TDMoP", "udp.port", 10},
5171 {"uaudp.port1", "UAUDP", "udp.port", 10},
5172 {"uaudp.port2", "UAUDP", "udp.port", 10},
5173 {"uaudp.port3", "UAUDP", "udp.port", 10},
5174 {"uaudp.port4", "UAUDP", "udp.port", 10},
5175 {"uhd.dissector_port", "UHD", "udp.port", 10},
5176 {"vrt.dissector_port", "VITA 49", "udp.port", 10},
5177 {"vuze-dht.udp_port", "Vuze-DHT", "udp.port", 10},
5178 {"wimaxasncp.udp.wimax_port", "WiMAX ASN CP", "udp.port", 10},
5181 struct port_pref_name port_range_prefs[] = {
5183 {"couchbase.tcp.ports", "Couchbase", "tcp.port", 10},
5184 {"gsm_ipa.tcp_ports", "GSM over IP", "tcp.port", 10},
5185 {"kafka.tcp.ports", "Kafka", "tcp.port", 10},
5186 {"kt.tcp.ports", "Kyoto Tycoon", "tcp.port", 10},
5187 {"memcache.tcp.ports", "MEMCACHE", "tcp.port", 10},
5188 {"mrcpv2.tcp.port_range", "MRCPv2", "tcp.port", 10},
5189 {"rtsp.tcp.port_range", "RTSP", "tcp.port", 10},
5190 {"sip.tcp.ports", "SIP", "tcp.port", 10},
5191 {"tds.tcp_ports", "TDS", "tcp.port", 10},
5192 {"uma.tcp.ports", "UMA", "tcp.port", 10},
5194 {"aruba_erm.udp.ports", "ARUBA_ERM", "udp.port", 10},
5195 {"diameter.udp.ports", "DIAMETER", "udp.port", 10},
5196 {"dmp.udp_ports", "DMP", "udp.port", 10},
5197 {"dns.udp.ports", "DNS", "udp.port", 10},
5198 {"gsm_ipa.udp_ports", "GSM over IP", "udp.port", 10},
5199 {"hcrt.dissector_udp_port", "HCrt", "udp.port", 10},
5200 {"memcache.udp.ports", "MEMCACHE", "udp.port", 10},
5201 {"nb_rtpmux.udp_ports", "NB_RTPMUX", "udp.port", 10},
5202 {"gprs-ns.udp.ports", "GPRS-NS", "udp.port", 10},
5203 {"p_mul.udp_ports", "P_MUL", "udp.port", 10},
5204 {"radius.ports", "RADIUS", "udp.port", 10},
5205 {"sflow.ports", "sFlow", "udp.port", 10},
5206 {"sscop.udp.ports", "SSCOP", "udp.port", 10},
5207 {"tftp.udp_ports", "TFTP", "udp.port", 10},
5208 {"tipc.udp.ports", "TIPC", "udp.port", 10},
5211 /* These are subdissectors of TPKT/OSITP that used to have a
5212 TCP port preference even though they were never
5213 directly on TCP. Convert them to use Decode As
5214 with the TPKT dissector handle */
5215 struct port_pref_name tpkt_subdissector_port_prefs[] = {
5216 {"dap.tcp.port", "DAP", "tcp.port", 10},
5217 {"disp.tcp.port", "DISP", "tcp.port", 10},
5218 {"dop.tcp.port", "DOP", "tcp.port", 10},
5219 {"dsp.tcp.port", "DSP", "tcp.port", 10},
5220 {"p1.tcp.port", "P1", "tcp.port", 10},
5221 {"p7.tcp.port", "P7", "tcp.port", 10},
5222 {"rdp.tcp.port", "RDP", "tcp.port", 10},
5225 /* These are obsolete preferences from the dissectors' view,
5226 (typically because of a switch from a single value to a
5227 range value) but the name of the preference conflicts
5228 with the generated preference name from the dissector table.
5229 Don't allow the obsolete preference through to be handled */
5230 struct obsolete_pref_name obsolete_prefs[] = {
5231 {"diameter.tcp.port"},
5233 {"mrcpv2.tcp.port"},
5242 dissector_table_t sub_dissectors;
5243 dissector_handle_t handle, tpkt_handle;
5247 for (i = 0; i < sizeof(port_prefs)/sizeof(struct port_pref_name); i++)
5249 if (strcmp(pref_name, port_prefs[i].pref_name) == 0)
5251 /* XXX - give an error if it doesn't fit in a guint? */
5252 uval = (guint)strtoul(value, &p, port_prefs[i].base);
5253 if (p == value || *p != '\0')
5254 return FALSE; /* number was bad */
5256 module = prefs_find_module((gchar*)port_prefs[i].module_name);
5257 pref = prefs_find_preference(module, port_prefs[i].table_name);
5260 module->prefs_changed_flags |= prefs_get_effect_flags(pref);
5261 *pref->varp.uint = uval;
5264 /* If the value is zero, it wouldn't add to the Decode As tables */
5267 sub_dissectors = find_dissector_table(port_prefs[i].table_name);
5268 if (sub_dissectors != NULL) {
5269 handle = dissector_table_get_dissector_handle(sub_dissectors, (gchar*)port_prefs[i].module_name);
5270 if (handle != NULL) {
5271 dissector_change_uint(port_prefs[i].table_name, uval, handle);
5272 decode_build_reset_list(port_prefs[i].table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(uval), NULL, NULL);
5281 for (i = 0; i < sizeof(port_range_prefs)/sizeof(struct port_pref_name); i++)
5283 if (strcmp(pref_name, port_range_prefs[i].pref_name) == 0)
5285 guint32 range_i, range_j;
5287 sub_dissectors = find_dissector_table(port_range_prefs[i].table_name);
5288 if (sub_dissectors != NULL) {
5289 switch (dissector_table_get_type(sub_dissectors)) {
5297 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));
5298 g_assert_not_reached();
5301 module = prefs_find_module((gchar*)port_range_prefs[i].module_name);
5302 pref = prefs_find_preference(module, port_range_prefs[i].table_name);
5305 if (!prefs_set_range_value_work(pref, value, TRUE, &module->prefs_changed_flags))
5307 return FALSE; /* number was bad */
5310 handle = dissector_table_get_dissector_handle(sub_dissectors, (gchar*)port_range_prefs[i].module_name);
5311 if (handle != NULL) {
5313 for (range_i = 0; range_i < (*pref->varp.range)->nranges; range_i++) {
5314 for (range_j = (*pref->varp.range)->ranges[range_i].low; range_j < (*pref->varp.range)->ranges[range_i].high; range_j++) {
5315 dissector_change_uint(port_range_prefs[i].table_name, range_j, handle);
5316 decode_build_reset_list(port_range_prefs[i].table_name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(range_j), NULL, NULL);
5319 dissector_change_uint(port_range_prefs[i].table_name, (*pref->varp.range)->ranges[range_i].high, handle);
5320 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);
5330 for (i = 0; i < sizeof(tpkt_subdissector_port_prefs)/sizeof(struct port_pref_name); i++)
5332 if (strcmp(pref_name, tpkt_subdissector_port_prefs[i].pref_name) == 0)
5334 /* XXX - give an error if it doesn't fit in a guint? */
5335 uval = (guint)strtoul(value, &p, tpkt_subdissector_port_prefs[i].base);
5336 if (p == value || *p != '\0')
5337 return FALSE; /* number was bad */
5339 /* If the value is 0 or 102 (default TPKT port), don't add to the Decode As tables */
5340 if ((uval != 0) && (uval != 102))
5342 tpkt_handle = find_dissector("tpkt");
5343 if (tpkt_handle != NULL) {
5344 dissector_change_uint(tpkt_subdissector_port_prefs[i].table_name, uval, tpkt_handle);
5352 for (i = 0; i < sizeof(obsolete_prefs)/sizeof(struct obsolete_pref_name); i++)
5354 if (strcmp(pref_name, obsolete_prefs[i].pref_name) == 0)
5356 /* Just ignore the preference */
5363 static prefs_set_pref_e
5364 set_pref(gchar *pref_name, const gchar *value, void *private_data _U_,
5365 gboolean return_range_errors)
5367 unsigned long int cval;
5372 gchar *dotp, *last_dotp;
5373 static gchar *filter_label = NULL;
5374 static gboolean filter_enabled = FALSE;
5375 gchar *filter_expr = NULL;
5376 module_t *module, *containing_module;
5380 //The PRS_GUI field names are here for backwards compatibility
5381 //display filters have been converted to a UAT.
5382 if (strcmp(pref_name, PRS_GUI_FILTER_LABEL) == 0) {
5383 filter_label = g_strdup(value);
5384 } else if (strcmp(pref_name, PRS_GUI_FILTER_ENABLED) == 0) {
5385 filter_enabled = (strcmp(value, "TRUE") == 0) ? TRUE : FALSE;
5386 } else if (strcmp(pref_name, PRS_GUI_FILTER_EXPR) == 0) {
5387 filter_expr = g_strdup(value);
5388 /* Comments not supported for "old" preference style */
5389 filter_expression_new(filter_label, filter_expr, "", filter_enabled);
5390 g_free(filter_label);
5391 g_free(filter_expr);
5392 } else if (strcmp(pref_name, "gui.version_in_start_page") == 0) {
5393 /* Convert deprecated value to closest current equivalent */
5394 if (g_ascii_strcasecmp(value, "true") == 0) {
5395 prefs.gui_version_placement = version_both;
5397 prefs.gui_version_placement = version_neither;
5399 } else if (strcmp(pref_name, "name_resolve") == 0 ||
5400 strcmp(pref_name, "capture.name_resolve") == 0) {
5402 * Handle the deprecated name resolution options.
5404 * "TRUE" and "FALSE", for backwards compatibility, are synonyms for
5405 * RESOLV_ALL and RESOLV_NONE.
5407 * Otherwise, we treat it as a list of name types we want to resolve.
5409 if (g_ascii_strcasecmp(value, "true") == 0) {
5410 gbl_resolv_flags.mac_name = TRUE;
5411 gbl_resolv_flags.network_name = TRUE;
5412 gbl_resolv_flags.transport_name = TRUE;
5414 else if (g_ascii_strcasecmp(value, "false") == 0) {
5415 disable_name_resolution();
5418 /* start out with none set */
5419 disable_name_resolution();
5420 if (string_to_name_resolve(value, &gbl_resolv_flags) != '\0')
5421 return PREFS_SET_SYNTAX_ERR;
5423 } else if (deprecated_heur_dissector_pref(pref_name, value)) {
5424 /* Handled within deprecated_heur_dissector_pref() if found */
5425 } else if (deprecated_enable_dissector_pref(pref_name, value)) {
5426 /* Handled within deprecated_enable_dissector_pref() if found */
5427 } else if (deprecated_port_pref(pref_name, value)) {
5428 /* Handled within deprecated_port_pref() if found */
5430 /* Handle deprecated "global" options that don't have a module
5431 * associated with them
5433 if ((strcmp(pref_name, "name_resolve_concurrency") == 0) ||
5434 (strcmp(pref_name, "name_resolve_load_smi_modules") == 0) ||
5435 (strcmp(pref_name, "name_resolve_suppress_smi_errors") == 0)) {
5436 module = nameres_module;
5439 /* To which module does this preference belong? */
5441 last_dotp = pref_name;
5443 dotp = strchr(last_dotp, '.');
5445 /* Either there's no such module, or no module was specified.
5446 In either case, that means there's no such preference. */
5447 return PREFS_SET_NO_SUCH_PREF;
5449 *dotp = '\0'; /* separate module and preference name */
5450 module = prefs_find_module(pref_name);
5453 * XXX - "Diameter" rather than "diameter" was used in earlier
5454 * versions of Wireshark; if we didn't find the module, and its name
5455 * was "Diameter", look for "diameter" instead.
5457 * In addition, the BEEP protocol used to be the BXXP protocol,
5458 * so if we didn't find the module, and its name was "bxxp",
5459 * look for "beep" instead.
5461 * Also, the preferences for GTP v0 and v1 were combined under
5462 * a single "gtp" heading, and the preferences for SMPP were
5463 * moved to "smpp-gsm-sms" and then moved to "gsm-sms-ud".
5464 * However, SMPP now has its own preferences, so we just map
5465 * "smpp-gsm-sms" to "gsm-sms-ud", and then handle SMPP below.
5467 * We also renamed "dcp" to "dccp", "x.25" to "x25", "x411" to "p1"
5468 * and "nsip" to "gprs_ns".
5470 * The SynOptics Network Management Protocol (SONMP) is now known by
5471 * its modern name, the Nortel Discovery Protocol (NDP).
5473 if (module == NULL) {
5474 if (strcmp(pref_name, "column") == 0)
5475 module = gui_column_module;
5476 else if (strcmp(pref_name, "Diameter") == 0)
5477 module = prefs_find_module("diameter");
5478 else if (strcmp(pref_name, "bxxp") == 0)
5479 module = prefs_find_module("beep");
5480 else if (strcmp(pref_name, "gtpv0") == 0 ||
5481 strcmp(pref_name, "gtpv1") == 0)
5482 module = prefs_find_module("gtp");
5483 else if (strcmp(pref_name, "smpp-gsm-sms") == 0)
5484 module = prefs_find_module("gsm-sms-ud");
5485 else if (strcmp(pref_name, "dcp") == 0)
5486 module = prefs_find_module("dccp");
5487 else if (strcmp(pref_name, "x.25") == 0)
5488 module = prefs_find_module("x25");
5489 else if (strcmp(pref_name, "x411") == 0)
5490 module = prefs_find_module("p1");
5491 else if (strcmp(pref_name, "nsip") == 0)
5492 module = prefs_find_module("gprs-ns");
5493 else if (strcmp(pref_name, "sonmp") == 0)
5494 module = prefs_find_module("ndp");
5495 else if (strcmp(pref_name, "etheric") == 0 ||
5496 strcmp(pref_name, "isup_thin") == 0) {
5497 /* This protocol was removed 7. July 2009 */
5498 return PREFS_SET_OBSOLETE;
5501 ws_g_warning ("Preference \"%s.%s\" has been converted to \"%s.%s.%s\"\n"
5502 "Save your preferences to make this change permanent.",
5503 pref_name, dotp+1, module->parent->name, pref_name, dotp+1);
5504 prefs.unknown_prefs = TRUE;
5507 *dotp = '.'; /* put the preference string back */
5508 dotp++; /* skip past separator to preference name */
5513 /* The pref is located in the module or a submodule.
5514 * Assume module, then search for a submodule holding the pref. */
5515 containing_module = module;
5516 pref = prefs_find_preference_with_submodule(module, dotp, &containing_module);
5519 prefs.unknown_prefs = TRUE;
5521 /* "gui" prefix was added to column preferences for better organization
5522 * within the preferences file
5524 if (module == gui_column_module) {
5525 /* While this has a subtree, there is no apply callback, so no
5526 * need to use prefs_find_preference_with_submodule to update
5527 * containing_module. It would not be useful. */
5528 pref = prefs_find_preference(module, pref_name);
5530 else if (strcmp(module->name, "mgcp") == 0) {
5532 * XXX - "mgcp.display raw text toggle" and "mgcp.display dissect tree"
5533 * rather than "mgcp.display_raw_text" and "mgcp.display_dissect_tree"
5534 * were used in earlier versions of Wireshark; if we didn't find the
5535 * preference, it was an MGCP preference, and its name was
5536 * "display raw text toggle" or "display dissect tree", look for
5537 * "display_raw_text" or "display_dissect_tree" instead.
5539 * "mgcp.tcp.port" and "mgcp.udp.port" are harder to handle, as both
5540 * the gateway and callagent ports were given those names; we interpret
5541 * the first as "mgcp.{tcp,udp}.gateway_port" and the second as
5542 * "mgcp.{tcp,udp}.callagent_port", as that's the order in which
5543 * they were registered by the MCCP dissector and thus that's the
5544 * order in which they were written to the preferences file. (If
5545 * we're not reading the preferences file, but are handling stuff
5546 * from a "-o" command-line option, we have no clue which the user
5547 * had in mind - they should have used "mgcp.{tcp,udp}.gateway_port"
5548 * or "mgcp.{tcp,udp}.callagent_port" instead.)
5550 if (strcmp(dotp, "display raw text toggle") == 0)
5551 pref = prefs_find_preference(module, "display_raw_text");
5552 else if (strcmp(dotp, "display dissect tree") == 0)
5553 pref = prefs_find_preference(module, "display_dissect_tree");
5554 else if (strcmp(dotp, "tcp.port") == 0) {
5555 mgcp_tcp_port_count++;
5556 if (mgcp_tcp_port_count == 1) {
5557 /* It's the first one */
5558 pref = prefs_find_preference(module, "tcp.gateway_port");
5559 } else if (mgcp_tcp_port_count == 2) {
5560 /* It's the second one */
5561 pref = prefs_find_preference(module, "tcp.callagent_port");
5563 /* Otherwise it's from the command line, and we don't bother
5565 } else if (strcmp(dotp, "udp.port") == 0) {
5566 mgcp_udp_port_count++;
5567 if (mgcp_udp_port_count == 1) {
5568 /* It's the first one */
5569 pref = prefs_find_preference(module, "udp.gateway_port");
5570 } else if (mgcp_udp_port_count == 2) {
5571 /* It's the second one */
5572 pref = prefs_find_preference(module, "udp.callagent_port");
5574 /* Otherwise it's from the command line, and we don't bother
5577 } else if (strcmp(module->name, "smb") == 0) {
5578 /* Handle old names for SMB preferences. */
5579 if (strcmp(dotp, "smb.trans.reassembly") == 0)
5580 pref = prefs_find_preference(module, "trans_reassembly");
5581 else if (strcmp(dotp, "smb.dcerpc.reassembly") == 0)
5582 pref = prefs_find_preference(module, "dcerpc_reassembly");
5583 } else if (strcmp(module->name, "ndmp") == 0) {
5584 /* Handle old names for NDMP preferences. */
5585 if (strcmp(dotp, "ndmp.desegment") == 0)
5586 pref = prefs_find_preference(module, "desegment");
5587 } else if (strcmp(module->name, "diameter") == 0) {
5588 /* Handle old names for Diameter preferences. */
5589 if (strcmp(dotp, "diameter.desegment") == 0)
5590 pref = prefs_find_preference(module, "desegment");
5591 } else if (strcmp(module->name, "pcli") == 0) {
5592 /* Handle old names for PCLI preferences. */
5593 if (strcmp(dotp, "pcli.udp_port") == 0)
5594 pref = prefs_find_preference(module, "udp_port");
5595 } else if (strcmp(module->name, "artnet") == 0) {
5596 /* Handle old names for ARTNET preferences. */
5597 if (strcmp(dotp, "artnet.udp_port") == 0)
5598 pref = prefs_find_preference(module, "udp_port");
5599 } else if (strcmp(module->name, "mapi") == 0) {
5600 /* Handle old names for MAPI preferences. */
5601 if (strcmp(dotp, "mapi_decrypt") == 0)
5602 pref = prefs_find_preference(module, "decrypt");
5603 } else if (strcmp(module->name, "fc") == 0) {
5604 /* Handle old names for Fibre Channel preferences. */
5605 if (strcmp(dotp, "reassemble_fc") == 0)
5606 pref = prefs_find_preference(module, "reassemble");
5607 else if (strcmp(dotp, "fc_max_frame_size") == 0)
5608 pref = prefs_find_preference(module, "max_frame_size");
5609 } else if (strcmp(module->name, "fcip") == 0) {
5610 /* Handle old names for Fibre Channel-over-IP preferences. */
5611 if (strcmp(dotp, "desegment_fcip_messages") == 0)
5612 pref = prefs_find_preference(module, "desegment");
5613 else if (strcmp(dotp, "fcip_port") == 0)
5614 pref = prefs_find_preference(module, "target_port");
5615 } else if (strcmp(module->name, "gtp") == 0) {
5616 /* Handle old names for GTP preferences. */
5617 if (strcmp(dotp, "gtpv0_port") == 0)
5618 pref = prefs_find_preference(module, "v0_port");
5619 else if (strcmp(dotp, "gtpv1c_port") == 0)
5620 pref = prefs_find_preference(module, "v1c_port");
5621 else if (strcmp(dotp, "gtpv1u_port") == 0)
5622 pref = prefs_find_preference(module, "v1u_port");
5623 else if (strcmp(dotp, "gtp_dissect_tpdu") == 0)
5624 pref = prefs_find_preference(module, "dissect_tpdu");
5625 else if (strcmp(dotp, "gtpv0_dissect_cdr_as") == 0)
5626 pref = prefs_find_preference(module, "v0_dissect_cdr_as");
5627 else if (strcmp(dotp, "gtpv0_check_etsi") == 0)
5628 pref = prefs_find_preference(module, "v0_check_etsi");
5629 else if (strcmp(dotp, "gtpv1_check_etsi") == 0)
5630 pref = prefs_find_preference(module, "v1_check_etsi");
5631 } else if (strcmp(module->name, "ip") == 0) {
5632 /* Handle old names for IP preferences. */
5633 if (strcmp(dotp, "ip_summary_in_tree") == 0)
5634 pref = prefs_find_preference(module, "summary_in_tree");
5635 } else if (strcmp(module->name, "iscsi") == 0) {
5636 /* Handle old names for iSCSI preferences. */
5637 if (strcmp(dotp, "iscsi_port") == 0)
5638 pref = prefs_find_preference(module, "target_port");
5639 } else if (strcmp(module->name, "lmp") == 0) {
5640 /* Handle old names for LMP preferences. */
5641 if (strcmp(dotp, "lmp_version") == 0)
5642 pref = prefs_find_preference(module, "version");
5643 } else if (strcmp(module->name, "mtp3") == 0) {
5644 /* Handle old names for MTP3 preferences. */
5645 if (strcmp(dotp, "mtp3_standard") == 0)
5646 pref = prefs_find_preference(module, "standard");
5647 else if (strcmp(dotp, "net_addr_format") == 0)
5648 pref = prefs_find_preference(module, "addr_format");
5649 } else if (strcmp(module->name, "nlm") == 0) {
5650 /* Handle old names for NLM preferences. */
5651 if (strcmp(dotp, "nlm_msg_res_matching") == 0)
5652 pref = prefs_find_preference(module, "msg_res_matching");
5653 } else if (strcmp(module->name, "ppp") == 0) {
5654 /* Handle old names for PPP preferences. */
5655 if (strcmp(dotp, "ppp_fcs") == 0)
5656 pref = prefs_find_preference(module, "fcs_type");
5657 else if (strcmp(dotp, "ppp_vj") == 0)
5658 pref = prefs_find_preference(module, "decompress_vj");
5659 } else if (strcmp(module->name, "rsvp") == 0) {
5660 /* Handle old names for RSVP preferences. */
5661 if (strcmp(dotp, "rsvp_process_bundle") == 0)
5662 pref = prefs_find_preference(module, "process_bundle");
5663 } else if (strcmp(module->name, "tcp") == 0) {
5664 /* Handle old names for TCP preferences. */
5665 if (strcmp(dotp, "tcp_summary_in_tree") == 0)
5666 pref = prefs_find_preference(module, "summary_in_tree");
5667 else if (strcmp(dotp, "tcp_analyze_sequence_numbers") == 0)
5668 pref = prefs_find_preference(module, "analyze_sequence_numbers");
5669 else if (strcmp(dotp, "tcp_relative_sequence_numbers") == 0)
5670 pref = prefs_find_preference(module, "relative_sequence_numbers");
5671 } else if (strcmp(module->name, "udp") == 0) {
5672 /* Handle old names for UDP preferences. */
5673 if (strcmp(dotp, "udp_summary_in_tree") == 0)
5674 pref = prefs_find_preference(module, "summary_in_tree");
5675 } else if (strcmp(module->name, "ndps") == 0) {
5676 /* Handle old names for NDPS preferences. */
5677 if (strcmp(dotp, "desegment_ndps") == 0)
5678 pref = prefs_find_preference(module, "desegment_tcp");
5679 } else if (strcmp(module->name, "http") == 0) {
5680 /* Handle old names for HTTP preferences. */
5681 if (strcmp(dotp, "desegment_http_headers") == 0)
5682 pref = prefs_find_preference(module, "desegment_headers");
5683 else if (strcmp(dotp, "desegment_http_body") == 0)
5684 pref = prefs_find_preference(module, "desegment_body");
5685 } else if (strcmp(module->name, "smpp") == 0) {
5686 /* Handle preferences that moved from SMPP. */
5687 module_t *new_module = prefs_find_module("gsm-sms-ud");
5689 if (strcmp(dotp, "port_number_udh_means_wsp") == 0) {
5690 pref = prefs_find_preference(new_module, "port_number_udh_means_wsp");
5691 containing_module = new_module;
5692 } else if (strcmp(dotp, "try_dissect_1st_fragment") == 0) {
5693 pref = prefs_find_preference(new_module, "try_dissect_1st_fragment");
5694 containing_module = new_module;
5697 } else if (strcmp(module->name, "asn1") == 0) {
5698 /* Handle old generic ASN.1 preferences (it's not really a
5699 rename, as the new preferences support multiple ports,
5700 but we might as well copy them over). */
5701 if (strcmp(dotp, "tcp_port") == 0)
5702 pref = prefs_find_preference(module, "tcp_ports");
5703 else if (strcmp(dotp, "udp_port") == 0)
5704 pref = prefs_find_preference(module, "udp_ports");
5705 else if (strcmp(dotp, "sctp_port") == 0)
5706 pref = prefs_find_preference(module, "sctp_ports");
5707 } else if (strcmp(module->name, "llcgprs") == 0) {
5708 if (strcmp(dotp, "ignore_cipher_bit") == 0)
5709 pref = prefs_find_preference(module, "autodetect_cipher_bit");
5710 } else if (strcmp(module->name, "erf") == 0) {
5711 if (strcmp(dotp, "erfeth") == 0) {
5712 /* Handle the old "erfeth" preference; map it to the new
5713 "ethfcs" preference, and map the values to those for
5714 the new preference. */
5715 pref = prefs_find_preference(module, "ethfcs");
5716 if (strcmp(value, "ethfcs") == 0 || strcmp(value, "Ethernet with FCS") == 0)
5718 else if (strcmp(value, "eth") == 0 || strcmp(value, "Ethernet") == 0)
5720 else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
5722 } else if (strcmp(dotp, "erfatm") == 0) {
5723 /* Handle the old "erfatm" preference; map it to the new
5724 "aal5_type" preference, and map the values to those for
5725 the new preference. */
5726 pref = prefs_find_preference(module, "aal5_type");
5727 if (strcmp(value, "atm") == 0 || strcmp(value, "ATM") == 0)
5729 else if (strcmp(value, "llc") == 0 || strcmp(value, "LLC") == 0)
5731 else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
5733 } else if (strcmp(dotp, "erfhdlc") == 0) {
5734 /* Handle the old "erfhdlc" preference; map it to the new
5735 "hdlc_type" preference, and map the values to those for
5736 the new preference. */
5737 pref = prefs_find_preference(module, "hdlc_type");
5738 if (strcmp(value, "chdlc") == 0 || strcmp(value, "Cisco HDLC") == 0)
5740 else if (strcmp(value, "ppp") == 0 || strcmp(value, "PPP serial") == 0)
5742 else if (strcmp(value, "fr") == 0 || strcmp(value, "Frame Relay") == 0)
5744 else if (strcmp(value, "mtp2") == 0 || strcmp(value, "SS7 MTP2") == 0)
5746 else if (strcmp(value, "raw") == 0 || strcmp(value, "Raw data") == 0)
5749 } else if (strcmp(module->name, "eth") == 0) {
5750 /* "eth.qinq_ethertype" has been changed(restored) to "vlan.qinq.ethertype" */
5751 if (strcmp(dotp, "qinq_ethertype") == 0) {
5752 module_t *new_module = prefs_find_module("vlan");
5754 pref = prefs_find_preference(new_module, "qinq_ethertype");
5755 containing_module = new_module;
5758 } else if (strcmp(module->name, "taps") == 0) {
5759 /* taps preferences moved to "statistics" module */
5760 if (strcmp(dotp, "update_interval") == 0 ||
5761 strcmp(dotp, "rtp_player_max_visible") == 0)
5762 pref = prefs_find_preference(stats_module, dotp);
5763 } else if (strcmp(module->name, "packet_list") == 0) {
5764 /* packet_list preferences moved to protocol module */
5765 if (strcmp(dotp, "display_hidden_proto_items") == 0)
5766 pref = prefs_find_preference(protocols_module, dotp);
5767 } else if (strcmp(module->name, "stream") == 0) {
5768 /* stream preferences moved to gui color module */
5769 if ((strcmp(dotp, "client.fg") == 0) ||
5770 (strcmp(dotp, "client.bg") == 0) ||
5771 (strcmp(dotp, "server.fg") == 0) ||
5772 (strcmp(dotp, "server.bg") == 0))
5773 pref = prefs_find_preference(gui_color_module, pref_name);
5774 } else if (strcmp(module->name, "nameres") == 0) {
5775 if (strcmp(pref_name, "name_resolve_concurrency") == 0) {
5776 pref = prefs_find_preference(nameres_module, pref_name);
5777 } else if (strcmp(pref_name, "name_resolve_load_smi_modules") == 0) {
5778 pref = prefs_find_preference(nameres_module, "load_smi_modules");
5779 } else if (strcmp(pref_name, "name_resolve_suppress_smi_errors") == 0) {
5780 pref = prefs_find_preference(nameres_module, "suppress_smi_errors");
5785 return PREFS_SET_NO_SUCH_PREF; /* no such preference */
5788 if (IS_PREF_OBSOLETE(type)) {
5789 return PREFS_SET_OBSOLETE; /* no such preference any more */
5791 RESET_PREF_OBSOLETE(type);
5797 /* XXX - give an error if it doesn't fit in a guint? */
5798 uval = (guint)strtoul(value, &p, pref->info.base);
5799 if (p == value || *p != '\0')
5800 return PREFS_SET_SYNTAX_ERR; /* number was bad */
5801 if (*pref->varp.uint != uval) {
5802 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
5803 *pref->varp.uint = uval;
5806 case PREF_DECODE_AS_UINT:
5808 /* This is for backwards compatibility in case any of the preferences
5809 that shared the "Decode As" preference name and used to be PREF_UINT
5810 are now applied directly to the Decode As funtionality */
5812 dissector_table_t sub_dissectors;
5813 dissector_handle_t handle;
5815 /* XXX - give an error if it doesn't fit in a guint? */
5816 uval = (guint)strtoul(value, &p, pref->info.base);
5817 if (p == value || *p != '\0')
5818 return PREFS_SET_SYNTAX_ERR; /* number was bad */
5820 if (*pref->varp.uint != uval) {
5821 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
5822 *pref->varp.uint = uval;
5824 /* Name of preference is the dissector table */
5825 sub_dissectors = find_dissector_table(pref->name);
5826 if (sub_dissectors != NULL) {
5827 handle = dissector_table_get_dissector_handle(sub_dissectors, (gchar*)module->title);
5828 if (handle != NULL) {
5830 dissector_change_uint(pref->name, uval, handle);
5831 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(uval), NULL, NULL);
5833 dissector_delete_uint(pref->name, *pref->varp.uint, handle);
5834 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), pref->varp.uint, NULL, NULL);
5837 /* XXX - Do we save the decode_as_entries file here? */
5844 /* XXX - give an error if it's neither "true" nor "false"? */
5845 if (g_ascii_strcasecmp(value, "true") == 0)
5849 if (*pref->varp.boolp != bval) {
5850 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
5851 *pref->varp.boolp = bval;
5856 /* XXX - give an error if it doesn't match? */
5857 enum_val = find_val_for_string(value, pref->info.enum_info.enumvals,
5859 if (*pref->varp.enump != enum_val) {
5860 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
5861 *pref->varp.enump = enum_val;
5866 case PREF_SAVE_FILENAME:
5867 case PREF_OPEN_FILENAME:
5869 containing_module->prefs_changed_flags |= prefs_set_string_value(pref, value, pref_current);
5874 if (!prefs_set_range_value_work(pref, value, return_range_errors,
5875 &containing_module->prefs_changed_flags))
5876 return PREFS_SET_SYNTAX_ERR; /* number was bad */
5879 case PREF_DECODE_AS_RANGE:
5881 /* This is for backwards compatibility in case any of the preferences
5882 that shared the "Decode As" preference name and used to be PREF_RANGE
5883 are now applied directly to the Decode As funtionality */
5885 dissector_table_t sub_dissectors;
5886 dissector_handle_t handle;
5889 if (range_convert_str_work(wmem_epan_scope(), &newrange, value, pref->info.max_value,
5890 return_range_errors) != CVT_NO_ERROR) {
5891 return PREFS_SET_SYNTAX_ERR; /* number was bad */
5894 if (!ranges_are_equal(*pref->varp.range, newrange)) {
5895 wmem_free(wmem_epan_scope(), *pref->varp.range);
5896 *pref->varp.range = newrange;
5897 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
5899 /* Name of preference is the dissector table */
5900 sub_dissectors = find_dissector_table(pref->name);
5901 if (sub_dissectors != NULL) {
5902 handle = dissector_table_get_dissector_handle(sub_dissectors, (gchar*)module->title);
5903 if (handle != NULL) {
5904 /* Delete all of the old values from the dissector table */
5905 for (i = 0; i < (*pref->varp.range)->nranges; i++) {
5906 for (j = (*pref->varp.range)->ranges[i].low; j < (*pref->varp.range)->ranges[i].high; j++) {
5907 dissector_delete_uint(pref->name, j, handle);
5908 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(j), NULL, NULL);
5911 dissector_delete_uint(pref->name, (*pref->varp.range)->ranges[i].high, handle);
5912 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER((*pref->varp.range)->ranges[i].high), NULL, NULL);
5915 /* Add new values to the dissector table */
5916 for (i = 0; i < newrange->nranges; i++) {
5917 for (j = newrange->ranges[i].low; j < newrange->ranges[i].high; j++) {
5918 dissector_change_uint(pref->name, j, handle);
5919 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(j), NULL, NULL);
5922 dissector_change_uint(pref->name, newrange->ranges[i].high, handle);
5923 decode_build_reset_list(pref->name, dissector_table_get_type(sub_dissectors), GUINT_TO_POINTER(newrange->ranges[i].high), NULL, NULL);
5926 /* XXX - Do we save the decode_as_entries file here? */
5930 wmem_free(wmem_epan_scope(), newrange);
5937 cval = strtoul(value, NULL, 16);
5938 if ((pref->varp.colorp->red != RED_COMPONENT(cval)) ||
5939 (pref->varp.colorp->green != GREEN_COMPONENT(cval)) ||
5940 (pref->varp.colorp->blue != BLUE_COMPONENT(cval))) {
5941 containing_module->prefs_changed_flags |= prefs_get_effect_flags(pref);
5942 pref->varp.colorp->red = RED_COMPONENT(cval);
5943 pref->varp.colorp->green = GREEN_COMPONENT(cval);
5944 pref->varp.colorp->blue = BLUE_COMPONENT(cval);
5950 return pref->custom_cbs.set_cb(pref, value, &containing_module->prefs_changed_flags);
5952 case PREF_STATIC_TEXT:
5960 return PREFS_SET_OK;
5965 gboolean is_gui_module;
5966 } write_gui_pref_arg_t;
5969 prefs_pref_type_name(pref_t *pref)
5971 const char *type_name = "[Unknown]";
5975 return type_name; /* ...or maybe assert? */
5980 if (IS_PREF_OBSOLETE(type)) {
5981 type_name = "Obsolete";
5983 RESET_PREF_OBSOLETE(type);
5989 switch (pref->info.base) {
5992 type_name = "Decimal";
5996 type_name = "Octal";
6000 type_name = "Hexadecimal";
6006 type_name = "Boolean";
6010 type_name = "Choice";
6014 type_name = "String";
6017 case PREF_SAVE_FILENAME:
6018 case PREF_OPEN_FILENAME:
6019 type_name = "Filename";
6023 type_name = "Directory";
6027 type_name = "Range";
6031 type_name = "Color";
6035 if (pref->custom_cbs.type_name_cb)
6036 return pref->custom_cbs.type_name_cb();
6037 type_name = "Custom";
6040 case PREF_DECODE_AS_UINT:
6041 type_name = "Decode As value";
6044 case PREF_DECODE_AS_RANGE:
6045 type_name = "Range (for Decode As)";
6048 case PREF_STATIC_TEXT:
6049 type_name = "Static text";
6060 prefs_get_effect_flags(pref_t *pref)
6065 return pref->effect_flags;
6069 prefs_set_effect_flags(pref_t *pref, unsigned int flags)
6072 pref->effect_flags = flags;
6077 prefs_set_effect_flags_by_name(module_t * module, const char *pref, unsigned int flags)
6079 prefs_set_effect_flags(prefs_find_preference(module, pref), flags);
6083 prefs_get_module_effect_flags(module_t * module)
6088 return module->effect_flags;
6092 prefs_set_module_effect_flags(module_t * module, unsigned int flags)
6094 if (module != NULL) {
6095 module->effect_flags = flags;
6100 prefs_pref_type_description(pref_t *pref)
6102 const char *type_desc = "An unknown preference type";
6106 return g_strdup_printf("%s.", type_desc); /* ...or maybe assert? */
6111 if (IS_PREF_OBSOLETE(type)) {
6112 type_desc = "An obsolete preference";
6114 RESET_PREF_OBSOLETE(type);
6120 switch (pref->info.base) {
6123 type_desc = "A decimal number";
6127 type_desc = "An octal number";
6131 type_desc = "A hexadecimal number";
6137 type_desc = "TRUE or FALSE (case-insensitive)";
6142 const enum_val_t *enum_valp = pref->info.enum_info.enumvals;
6143 GString *enum_str = g_string_new("One of: ");
6144 while (enum_valp->name != NULL) {
6145 g_string_append(enum_str, enum_valp->description);
6147 if (enum_valp->name != NULL)
6148 g_string_append(enum_str, ", ");
6150 g_string_append(enum_str, "\n(case-insensitive).");
6151 return g_string_free(enum_str, FALSE);
6156 type_desc = "A string";
6159 case PREF_SAVE_FILENAME:
6160 case PREF_OPEN_FILENAME:
6161 type_desc = "A path to a file";
6165 type_desc = "A path to a directory";
6170 type_desc = "A string denoting an positive integer range (e.g., \"1-20,30-40\")";
6176 type_desc = "A six-digit hexadecimal RGB color triplet (e.g. fce94f)";
6181 if (pref->custom_cbs.type_description_cb)
6182 return pref->custom_cbs.type_description_cb();
6183 type_desc = "A custom value";
6186 case PREF_DECODE_AS_UINT:
6187 type_desc = "An integer value used in Decode As";
6190 case PREF_DECODE_AS_RANGE:
6191 type_desc = "A string denoting an positive integer range for Decode As";
6194 case PREF_STATIC_TEXT:
6195 type_desc = "[Static text]";
6199 type_desc = "Configuration data stored in its own file";
6205 return g_strdup(type_desc);
6209 prefs_pref_is_default(pref_t *pref)
6212 if (!pref) return FALSE;
6215 if (IS_PREF_OBSOLETE(type)) {
6218 RESET_PREF_OBSOLETE(type);
6223 case PREF_DECODE_AS_UINT:
6224 if (pref->default_val.uint == *pref->varp.uint)
6229 if (pref->default_val.uint == *pref->varp.uint)
6234 if (pref->default_val.boolval == *pref->varp.boolp)
6239 if (pref->default_val.enumval == *pref->varp.enump)
6244 case PREF_SAVE_FILENAME:
6245 case PREF_OPEN_FILENAME:
6247 if (!(g_strcmp0(pref->default_val.string, *pref->varp.string)))
6251 case PREF_DECODE_AS_RANGE:
6254 if ((ranges_are_equal(pref->default_val.range, *pref->varp.range)))
6261 if ((pref->default_val.color.red == pref->varp.colorp->red) &&
6262 (pref->default_val.color.green == pref->varp.colorp->green) &&
6263 (pref->default_val.color.blue == pref->varp.colorp->blue))
6269 return pref->custom_cbs.is_default_cb(pref);
6271 case PREF_STATIC_TEXT:
6274 /* g_assert_not_reached(); */
6281 prefs_pref_to_str(pref_t *pref, pref_source_t source) {
6282 const char *pref_text = "[Unknown]";
6283 void *valp; /* pointer to preference value */
6284 color_t *pref_color;
6285 gchar *tmp_value, *ret_value;
6289 return g_strdup(pref_text);
6294 valp = &pref->default_val;
6295 /* valp = &boolval, &enumval, etc. are implied by union property */
6296 pref_color = &pref->default_val.color;
6299 valp = &pref->stashed_val;
6300 /* valp = &boolval, &enumval, etc. are implied by union property */
6301 pref_color = &pref->stashed_val.color;
6304 valp = pref->varp.uint;
6305 /* valp = boolval, enumval, etc. are implied by union property */
6306 pref_color = pref->varp.colorp;
6309 return g_strdup(pref_text);
6313 if (IS_PREF_OBSOLETE(type)) {
6314 pref_text = "[Obsolete]";
6316 RESET_PREF_OBSOLETE(type);
6321 case PREF_DECODE_AS_UINT:
6324 guint pref_uint = *(guint *) valp;
6325 switch (pref->info.base) {
6328 return g_strdup_printf("%u", pref_uint);
6331 return g_strdup_printf("%#o", pref_uint);
6334 return g_strdup_printf("%#x", pref_uint);
6340 return g_strdup((*(gboolean *) valp) ? "TRUE" : "FALSE");
6344 gint pref_enumval = *(gint *) valp;
6346 * For now, we return the "description" value, so that if we
6347 * save the preferences older versions of Wireshark can at
6348 * least read preferences that they supported; we support
6349 * either the short name or the description when reading
6350 * the preferences file or a "-o" option.
6352 const enum_val_t *enum_valp = pref->info.enum_info.enumvals;
6353 while (enum_valp->name != NULL) {
6354 if (enum_valp->value == pref_enumval)
6355 return g_strdup(enum_valp->description);
6362 case PREF_SAVE_FILENAME:
6363 case PREF_OPEN_FILENAME:
6365 return g_strdup(*(const char **) valp);
6367 case PREF_DECODE_AS_RANGE:
6369 /* Convert wmem to g_alloc memory */
6370 tmp_value = range_convert_range(NULL, *(range_t **) valp);
6371 ret_value = g_strdup(tmp_value);
6372 wmem_free(NULL, tmp_value);
6376 return g_strdup_printf("%02x%02x%02x",
6377 (pref_color->red * 255 / 65535),
6378 (pref_color->green * 255 / 65535),
6379 (pref_color->blue * 255 / 65535));
6382 if (pref->custom_cbs.to_str_cb)
6383 return pref->custom_cbs.to_str_cb(pref, source == pref_default ? TRUE : FALSE);
6384 pref_text = "[Custom]";
6387 case PREF_STATIC_TEXT:
6388 pref_text = "[Static text]";
6393 uat_t *uat = pref->varp.uat;
6394 if (uat && uat->filename)
6395 return g_strdup_printf("[Managed in the file \"%s\"]", uat->filename);
6397 pref_text = "[Managed in an unknown file]";
6404 return g_strdup(pref_text);
6408 * Write out a single dissector preference.
6411 write_pref(gpointer data, gpointer user_data)
6413 pref_t *pref = (pref_t *)data;
6414 write_pref_arg_t *arg = (write_pref_arg_t *)user_data;
6421 if (IS_PREF_OBSOLETE(type)) {
6423 * This preference is no longer supported; it's not a
6424 * real preference, so we don't write it out (i.e., we
6425 * treat it as if it weren't found in the list of
6426 * preferences, and we weren't called in the first place).
6430 RESET_PREF_OBSOLETE(type);
6435 case PREF_STATIC_TEXT:
6437 /* Nothing to do; don't bother printing the description */
6439 case PREF_DECODE_AS_UINT:
6440 case PREF_DECODE_AS_RANGE:
6441 /* Data is saved through Decode As mechanism and not part of preferences file */
6447 if (pref->type != PREF_CUSTOM || pref->custom_cbs.type_name_cb() != NULL) {
6449 * The prefix will either be the module name or the parent
6450 * name if it's a subtree
6452 const char *name_prefix = (arg->module->name != NULL) ? arg->module->name : arg->module->parent->name;
6453 char *type_desc, *pref_text;
6454 const char * def_prefix = prefs_pref_is_default(pref) ? "#" : "";
6456 if (pref->type == PREF_CUSTOM) fprintf(arg->pf, "\n# %s", pref->custom_cbs.type_name_cb());
6457 fprintf(arg->pf, "\n");
6458 if (pref->description &&
6459 (g_ascii_strncasecmp(pref->description,"", 2) != 0)) {
6460 if (pref->type != PREF_CUSTOM) {
6461 /* We get duplicate lines otherwise. */
6463 desc_lines = g_strsplit(pref->description,"\n",0);
6464 for (i = 0; desc_lines[i] != NULL; ++i) {
6465 fprintf(arg->pf, "# %s\n", desc_lines[i]);
6467 g_strfreev(desc_lines);
6470 fprintf(arg->pf, "# No description\n");
6473 type_desc = prefs_pref_type_description(pref);
6474 desc_lines = g_strsplit(type_desc,"\n",0);
6475 for (i = 0; desc_lines[i] != NULL; ++i) {
6476 fprintf(arg->pf, "# %s\n", desc_lines[i]);
6478 g_strfreev(desc_lines);
6481 pref_text = prefs_pref_to_str(pref, pref_current);
6482 fprintf(arg->pf, "%s%s.%s: ", def_prefix, name_prefix, pref->name);
6483 desc_lines = g_strsplit(pref_text,"\n",0);
6484 for (i = 0; desc_lines[i] != NULL; ++i) {
6485 fprintf(arg->pf, "%s%s\n", i == 0 ? "" : def_prefix, desc_lines[i]);
6487 if (i == 0) fprintf(arg->pf, "\n");
6488 g_strfreev(desc_lines);
6495 count_non_uat_pref(gpointer data, gpointer user_data)
6497 pref_t *pref = (pref_t *)data;
6498 int *arg = (int *)user_data;
6504 case PREF_DECODE_AS_UINT:
6505 case PREF_DECODE_AS_RANGE:
6506 //These types are not written in preference file
6514 static int num_non_uat_prefs(module_t *module)
6518 g_list_foreach(module->prefs, count_non_uat_pref, &num);
6524 * Write out all preferences for a module.
6527 write_module_prefs(module_t *module, gpointer user_data)
6529 write_gui_pref_arg_t *gui_pref_arg = (write_gui_pref_arg_t*)user_data;
6530 write_pref_arg_t arg;
6532 /* The GUI module needs to be explicitly called out so it
6533 can be written out of order */
6534 if ((module == gui_module) && (gui_pref_arg->is_gui_module != TRUE))
6537 /* Write a header for the main modules and GUI sub-modules */
6538 if (((module->parent == NULL) || (module->parent == gui_module)) &&
6539 ((prefs_module_has_submodules(module)) ||
6540 (num_non_uat_prefs(module) > 0) ||
6541 (module->name == NULL))) {
6542 if ((module->name == NULL) && (module->parent != NULL)) {
6543 fprintf(gui_pref_arg->pf, "\n####### %s: %s ########\n", module->parent->title, module->title);
6545 fprintf(gui_pref_arg->pf, "\n####### %s ########\n", module->title);
6549 arg.module = module;
6550 arg.pf = gui_pref_arg->pf;
6551 g_list_foreach(arg.module->prefs, write_pref, &arg);
6553 if (prefs_module_has_submodules(module))
6554 return prefs_modules_foreach_submodules(module, write_module_prefs, user_data);
6559 /* Write out "prefs" to the user's preferences file, and return 0.
6561 If the preferences file path is NULL, write to stdout.
6563 If we got an error, stuff a pointer to the path of the preferences file
6564 into "*pf_path_return", and return the errno. */
6566 write_prefs(char **pf_path_return)
6570 write_gui_pref_arg_t write_gui_pref_info;
6572 /* Needed for "-G defaultprefs" */
6576 * - Split output lines longer than MAX_VAL_LEN
6577 * - Create a function for the preference directory check/creation
6578 * so that duplication can be avoided with filter.c
6581 if (pf_path_return != NULL) {
6582 pf_path = get_persconffile_path(PF_NAME, TRUE);
6583 if ((pf = ws_fopen(pf_path, "w")) == NULL) {
6584 *pf_path_return = pf_path;
6592 fputs("# Configuration file for Wireshark " VERSION ".\n"
6594 "# This file is regenerated each time preferences are saved within\n"
6595 "# Wireshark. Making manual changes should be safe, however.\n"
6596 "# Preferences that have been commented out have not been\n"
6597 "# changed from their default value.\n", pf);
6600 * For "backwards compatibility" the GUI module is written first as it's
6601 * at the top of the file. This is followed by all modules that can't
6602 * fit into the preferences read/write API. Finally the remaining modules
6603 * are written in alphabetical order (including of course the protocol preferences)
6605 write_gui_pref_info.pf = pf;
6606 write_gui_pref_info.is_gui_module = TRUE;
6608 write_module_prefs(gui_module, &write_gui_pref_info);
6610 write_gui_pref_info.is_gui_module = FALSE;
6611 prefs_modules_foreach_submodules(NULL, write_module_prefs, &write_gui_pref_info);
6615 /* XXX - catch I/O errors (e.g. "ran out of disk space") and return
6616 an error indication, or maybe write to a new preferences file and
6617 rename that file on top of the old one only if there are not I/O
6622 /** The col_list is only partly managed by the custom preference API
6623 * because its data is shared between multiple preferences, so
6627 free_col_info(GList *list)
6630 GList *list_head = list;
6632 while (list != NULL) {
6633 cfmt = (fmt_data *)list->data;
6635 g_free(cfmt->title);
6636 g_free(cfmt->custom_fields);
6638 list = g_list_next(list);
6640 g_list_free(list_head);
6649 * indent-tabs-mode: nil
6652 * ex: set shiftwidth=4 tabstop=8 expandtab:
6653 * :indentSize=4:tabSize=8:noTabs=true: