2 * Routines for handling preferences
4 * Wireshark - Network traffic analyzer
5 * By Gerald Combs <gerald@wireshark.org>
6 * Copyright 1998 Gerald Combs
8 * SPDX-License-Identifier: GPL-2.0-or-later
15 #include <epan/column.h>
16 #include <wsutil/filesystem.h>
17 #include <wsutil/wslog.h>
18 #include <epan/prefs.h>
19 #include <epan/prefs-int.h>
20 #include <epan/packet.h>
21 #include <epan/decode_as.h>
22 #include <epan/uat-int.h>
23 #include <ui/recent.h>
26 #include "capture_opts.h"
27 #include "ui/capture_globals.h"
30 #include "ui/preference_utils.h"
31 #include "ui/simple_dialog.h"
33 /* Fill in capture options with values from the preferences */
35 prefs_to_capture_opts(void)
38 /* Set promiscuous mode from the preferences setting. */
39 /* the same applies to other preferences settings as well. */
40 global_capture_opts
.default_options
.promisc_mode
= prefs
.capture_prom_mode
;
41 global_capture_opts
.default_options
.monitor_mode
= prefs
.capture_monitor_mode
;
42 global_capture_opts
.use_pcapng
= prefs
.capture_pcap_ng
;
43 global_capture_opts
.show_info
= prefs
.capture_show_info
;
44 global_capture_opts
.real_time_mode
= prefs
.capture_real_time
;
45 global_capture_opts
.update_interval
= prefs
.capture_update_interval
;
46 #endif /* HAVE_LIBPCAP */
50 prefs_main_write(void)
56 /* Create the directory that holds personal configuration files, if
58 if (create_persconffile_dir(&pf_dir_path
) == -1) {
59 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
,
60 "Can't create directory\n\"%s\"\nfor preferences file: %s.", pf_dir_path
,
64 /* Write the preferences out. */
65 err
= write_prefs(&pf_path
);
67 simple_dialog(ESD_TYPE_ERROR
, ESD_BTN_OK
,
68 "Can't open preferences file\n\"%s\": %s.", pf_path
,
72 /* Write recent and recent_common files out to ensure sync with prefs. */
73 write_profile_recent();
79 prefs_store_ext_helper(const char * module_name
, const char *pref_name
, const char *pref_value
)
81 module_t
* module
= NULL
;
83 unsigned int pref_changed
= 0;
85 if ( !prefs_is_registered_protocol(module_name
))
88 module
= prefs_find_module(module_name
);
92 pref
= prefs_find_preference(module
, pref_name
);
97 if (prefs_get_type(pref
) == PREF_STRING
|| prefs_get_type(pref
) == PREF_DISSECTOR
)
99 pref_changed
|= prefs_set_string_value(pref
, pref_value
, pref_stashed
);
100 if ( !pref_changed
|| prefs_get_string_value(pref
, pref_stashed
) != 0 )
101 pref_changed
|= prefs_set_string_value(pref
, pref_value
, pref_current
);
102 } else if (prefs_get_type(pref
) == PREF_PASSWORD
)
104 pref_changed
|= prefs_set_password_value(pref
, pref_value
, pref_stashed
);
105 if ( !pref_changed
|| prefs_get_password_value(pref
, pref_stashed
) != 0 )
106 pref_changed
|= prefs_set_password_value(pref
, pref_value
, pref_current
);
113 prefs_store_ext(const char * module_name
, const char *pref_name
, const char *pref_value
)
115 unsigned int changed_flags
= prefs_store_ext_helper(module_name
, pref_name
, pref_value
);
120 prefs_to_capture_opts();
121 return changed_flags
;
128 prefs_store_ext_multiple(const char * module
, GHashTable
* pref_values
)
130 bool pref_changed
= false;
133 if ( !prefs_is_registered_protocol(module
))
136 keys
= g_hash_table_get_keys(pref_values
);
140 for ( GList
* key
= keys
; key
!= NULL
; key
= g_list_next(key
) )
142 char * pref_name
= (char *)key
->data
;
143 char * pref_value
= (char *) g_hash_table_lookup(pref_values
, key
->data
);
145 if ( pref_name
&& pref_value
)
147 if ( prefs_store_ext_helper(module
, pref_name
, pref_value
) )
157 prefs_to_capture_opts();
164 column_prefs_add_custom(int fmt
, const char *title
, const char *custom_fields
, int position
)
167 fmt_data
*cfmt
, *last_cfmt
;
170 cfmt
= g_new(fmt_data
, 1);
172 * Because a single underscore is interpreted as a signal that the next character
173 * is going to be marked as accelerator for this header (i.e. is going to be
174 * shown underlined), escape it be inserting a second consecutive underscore.
176 cfmt
->title
= g_strdup(title
);
178 cfmt
->custom_fields
= g_strdup(custom_fields
);
179 cfmt
->custom_occurrence
= 0;
180 if (column_prefs_custom_display_strings(custom_fields
)) {
181 cfmt
->display
= COLUMN_DISPLAY_STRINGS
;
183 cfmt
->display
= COLUMN_DISPLAY_VALUES
;
186 colnr
= g_list_length(prefs
.col_list
);
189 cfmt
->visible
= true;
190 clp
= g_list_last(prefs
.col_list
);
191 last_cfmt
= (fmt_data
*) clp
->data
;
192 if (position
> 0 && position
<= colnr
) {
193 /* Custom fields may be added at any position, depending on the given argument */
195 prefs
.col_list
= g_list_insert(prefs
.col_list
, cfmt
, colnr
);
196 } else if (last_cfmt
->fmt
== COL_INFO
) {
197 /* Last column is COL_INFO, add custom column before this */
199 prefs
.col_list
= g_list_insert(prefs
.col_list
, cfmt
, colnr
);
201 prefs
.col_list
= g_list_append(prefs
.col_list
, cfmt
);
204 cfmt
->visible
= false; /* Will be set to true in visible_toggled() when added to list */
205 prefs
.col_list
= g_list_append(prefs
.col_list
, cfmt
);
207 recent_insert_column(colnr
);
213 column_prefs_has_custom(const char *custom_field
)
219 for (int i
= 0; i
< prefs
.num_cols
; i
++) {
220 clp
= g_list_nth(prefs
.col_list
, i
);
221 if (clp
== NULL
) /* Sanity check, invalid column requested */
224 cfmt
= (fmt_data
*) clp
->data
;
225 if (cfmt
->fmt
== COL_CUSTOM
&& cfmt
->custom_occurrence
== 0 && strcmp(custom_field
, cfmt
->custom_fields
) == 0) {
235 column_prefs_custom_display_strings(const char* custom_field
)
238 header_field_info
*hfi
;
239 bool resolve
= false;
241 fields
= g_regex_split_simple(COL_CUSTOM_PRIME_REGEX
, custom_field
,
242 (GRegexCompileFlags
) (G_REGEX_RAW
),
245 for (unsigned i
= 0; i
< g_strv_length(fields
); i
++) {
246 if (fields
[i
] && *fields
[i
]) {
247 hfi
= proto_registrar_get_byname(fields
[i
]);
248 if (hfi
&& ((hfi
->type
== FT_OID
) || (hfi
->type
== FT_REL_OID
) || (hfi
->type
== FT_ETHER
) || (hfi
->type
== FT_BYTES
) || (hfi
->type
== FT_IPv4
) || (hfi
->type
== FT_IPv6
) || (hfi
->type
== FT_FCWWN
) || (hfi
->type
== FT_BOOLEAN
) ||
249 ((hfi
->strings
!= NULL
) &&
250 (FT_IS_INT(hfi
->type
) || FT_IS_UINT(hfi
->type
)))))
264 column_prefs_custom_display_details(const char* custom_field
)
267 header_field_info
*hfi
;
268 bool resolve
= false;
270 fields
= g_regex_split_simple(COL_CUSTOM_PRIME_REGEX
, custom_field
,
271 (GRegexCompileFlags
) (G_REGEX_RAW
),
274 for (unsigned i
= 0; i
< g_strv_length(fields
); i
++) {
275 if (fields
[i
] && *fields
[i
]) {
276 hfi
= proto_registrar_get_byname(fields
[i
]);
277 if (hfi
&& !(hfi
->display
& BASE_NO_DISPLAY_VALUE
)) {
290 column_prefs_remove_link(GList
*col_link
)
294 if (!col_link
|| !col_link
->data
) return;
296 cfmt
= (fmt_data
*) col_link
->data
;
299 g_free(cfmt
->custom_fields
);
301 prefs
.col_list
= g_list_remove_link(prefs
.col_list
, col_link
);
302 g_list_free_1(col_link
);
306 column_prefs_remove_nth(int col
)
308 column_prefs_remove_link(g_list_nth(prefs
.col_list
, col
));
309 recent_remove_column(col
);
312 void save_migrated_uat(const char *uat_name
, bool *old_pref
)
316 if (!uat_save(uat_get_table_by_name(uat_name
), &err
)) {
317 ws_warning("Unable to save %s: %s", uat_name
, err
);
322 // Ensure that any old preferences are removed after successful migration.