forked from osmocom/wireshark
![Stig Bjørlykke](/assets/img/avatar_default.png)
Use the existing (possible hidden) column when doing "Apply as Column" on a field which is already used as a custom column. This will help prevent having multiple equal custom columns, where all will be hidden at startup and profile change when only one of them are configured as hidden. Multiple equal columns can always be manually configured using "Preferences -> Appearance -> Columns" if this is intended. Change-Id: Ib03893facfa3f194f3b3303645fb3f9313ec9e91 Reviewed-on: https://code.wireshark.org/review/37861 Petri-Dish: Stig Bjørlykke <stig@bjorlykke.org> Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman <a.broman58@gmail.com>
275 lines
7.3 KiB
C
275 lines
7.3 KiB
C
/* preference_utils.c
|
|
* Routines for handling preferences
|
|
*
|
|
* Wireshark - Network traffic analyzer
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
* Copyright 1998 Gerald Combs
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <errno.h>
|
|
|
|
#include <epan/column.h>
|
|
#include <wsutil/filesystem.h>
|
|
#include <epan/prefs.h>
|
|
#include <epan/prefs-int.h>
|
|
#include <epan/packet.h>
|
|
#include <epan/decode_as.h>
|
|
#include <epan/uat-int.h>
|
|
#include <ui/recent.h>
|
|
|
|
#ifdef HAVE_LIBPCAP
|
|
#include "capture_opts.h"
|
|
#include "ui/capture_globals.h"
|
|
#endif
|
|
|
|
#include "ui/preference_utils.h"
|
|
#include "ui/simple_dialog.h"
|
|
|
|
#ifdef HAVE_LIBPCAP
|
|
gboolean auto_scroll_live;
|
|
#endif
|
|
|
|
/* Fill in capture options with values from the preferences */
|
|
void
|
|
prefs_to_capture_opts(void)
|
|
{
|
|
#ifdef HAVE_LIBPCAP
|
|
/* Set promiscuous mode from the preferences setting. */
|
|
/* the same applies to other preferences settings as well. */
|
|
global_capture_opts.default_options.promisc_mode = prefs.capture_prom_mode;
|
|
global_capture_opts.use_pcapng = prefs.capture_pcap_ng;
|
|
global_capture_opts.show_info = prefs.capture_show_info;
|
|
global_capture_opts.real_time_mode = prefs.capture_real_time;
|
|
auto_scroll_live = prefs.capture_auto_scroll;
|
|
#endif /* HAVE_LIBPCAP */
|
|
}
|
|
|
|
void
|
|
prefs_main_write(void)
|
|
{
|
|
int err;
|
|
char *pf_dir_path;
|
|
char *pf_path;
|
|
|
|
/* Create the directory that holds personal configuration files, if
|
|
necessary. */
|
|
if (create_persconffile_dir(&pf_dir_path) == -1) {
|
|
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
|
|
"Can't create directory\n\"%s\"\nfor preferences file: %s.", pf_dir_path,
|
|
g_strerror(errno));
|
|
g_free(pf_dir_path);
|
|
} else {
|
|
/* Write the preferences out. */
|
|
err = write_prefs(&pf_path);
|
|
if (err != 0) {
|
|
simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
|
|
"Can't open preferences file\n\"%s\": %s.", pf_path,
|
|
g_strerror(err));
|
|
g_free(pf_path);
|
|
}
|
|
/* Write recent and recent_common files out to ensure sync with prefs. */
|
|
write_profile_recent();
|
|
write_recent();
|
|
}
|
|
}
|
|
|
|
static unsigned int
|
|
prefs_store_ext_helper(const char * module_name, const char *pref_name, const char *pref_value)
|
|
{
|
|
module_t * module = NULL;
|
|
pref_t * pref = NULL;
|
|
unsigned int pref_changed = 0;
|
|
|
|
if ( ! prefs_is_registered_protocol(module_name))
|
|
return 0;
|
|
|
|
module = prefs_find_module(module_name);
|
|
if ( ! module )
|
|
return 0;
|
|
|
|
pref = prefs_find_preference(module, pref_name);
|
|
|
|
if (!pref)
|
|
return 0;
|
|
|
|
if (prefs_get_type(pref) == PREF_STRING )
|
|
{
|
|
pref_changed |= prefs_set_string_value(pref, pref_value, pref_stashed);
|
|
if ( ! pref_changed || prefs_get_string_value(pref, pref_stashed) != 0 )
|
|
pref_changed |= prefs_set_string_value(pref, pref_value, pref_current);
|
|
}
|
|
|
|
return pref_changed;
|
|
}
|
|
|
|
unsigned int
|
|
prefs_store_ext(const char * module_name, const char *pref_name, const char *pref_value)
|
|
{
|
|
unsigned int changed_flags = prefs_store_ext_helper(module_name, pref_name, pref_value);
|
|
if ( changed_flags )
|
|
{
|
|
prefs_main_write();
|
|
prefs_apply_all();
|
|
prefs_to_capture_opts();
|
|
return changed_flags;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
gboolean
|
|
prefs_store_ext_multiple(const char * module, GHashTable * pref_values)
|
|
{
|
|
gboolean pref_changed = FALSE;
|
|
GList * keys = NULL;
|
|
|
|
if ( ! prefs_is_registered_protocol(module))
|
|
return pref_changed;
|
|
|
|
keys = g_hash_table_get_keys(pref_values);
|
|
if ( ! keys )
|
|
return pref_changed;
|
|
|
|
for ( GList * key = keys; key != NULL; key = g_list_next(key) )
|
|
{
|
|
gchar * pref_name = (gchar *)key->data;
|
|
gchar * pref_value = (gchar *) g_hash_table_lookup(pref_values, key->data);
|
|
|
|
if ( pref_name && pref_value )
|
|
{
|
|
if ( prefs_store_ext_helper(module, pref_name, pref_value) )
|
|
pref_changed = TRUE;
|
|
}
|
|
}
|
|
g_list_free(keys);
|
|
|
|
if ( pref_changed )
|
|
{
|
|
prefs_main_write();
|
|
prefs_apply_all();
|
|
prefs_to_capture_opts();
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
gint
|
|
column_prefs_add_custom(gint fmt, const gchar *title, const gchar *custom_fields, gint position)
|
|
{
|
|
GList *clp;
|
|
fmt_data *cfmt, *last_cfmt;
|
|
gint colnr;
|
|
|
|
cfmt = (fmt_data *) g_malloc(sizeof(fmt_data));
|
|
/*
|
|
* Because a single underscore is interpreted as a signal that the next character
|
|
* is going to be marked as accelerator for this header (i.e. is going to be
|
|
* shown underlined), escape it be inserting a second consecutive underscore.
|
|
*/
|
|
cfmt->title = g_strdup(title);
|
|
cfmt->fmt = fmt;
|
|
cfmt->custom_fields = g_strdup(custom_fields);
|
|
cfmt->custom_occurrence = 0;
|
|
cfmt->resolved = TRUE;
|
|
|
|
colnr = g_list_length(prefs.col_list);
|
|
|
|
if (custom_fields) {
|
|
cfmt->visible = TRUE;
|
|
clp = g_list_last(prefs.col_list);
|
|
last_cfmt = (fmt_data *) clp->data;
|
|
if (position > 0 && position <= colnr) {
|
|
/* Custom fields may be added at any position, depending on the given argument */
|
|
prefs.col_list = g_list_insert(prefs.col_list, cfmt, position);
|
|
} else if (last_cfmt->fmt == COL_INFO) {
|
|
/* Last column is COL_INFO, add custom column before this */
|
|
colnr -= 1;
|
|
prefs.col_list = g_list_insert(prefs.col_list, cfmt, colnr);
|
|
} else {
|
|
prefs.col_list = g_list_append(prefs.col_list, cfmt);
|
|
}
|
|
} else {
|
|
cfmt->visible = FALSE; /* Will be set to TRUE in visible_toggled() when added to list */
|
|
prefs.col_list = g_list_append(prefs.col_list, cfmt);
|
|
}
|
|
|
|
return colnr;
|
|
}
|
|
|
|
gint
|
|
column_prefs_has_custom(const gchar *custom_field)
|
|
{
|
|
GList *clp;
|
|
fmt_data *cfmt;
|
|
gint colnr = -1;
|
|
|
|
for (gint i = 0; i < prefs.num_cols; i++) {
|
|
clp = g_list_nth(prefs.col_list, i);
|
|
if (clp == NULL) /* Sanity check, invalid column requested */
|
|
continue;
|
|
|
|
cfmt = (fmt_data *) clp->data;
|
|
if (cfmt->fmt == COL_CUSTOM && strcmp(custom_field, cfmt->custom_fields) == 0) {
|
|
colnr = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return colnr;
|
|
}
|
|
|
|
void
|
|
column_prefs_remove_link(GList *col_link)
|
|
{
|
|
fmt_data *cfmt;
|
|
|
|
if (!col_link || !col_link->data) return;
|
|
|
|
cfmt = (fmt_data *) col_link->data;
|
|
|
|
g_free(cfmt->title);
|
|
g_free(cfmt->custom_fields);
|
|
g_free(cfmt);
|
|
prefs.col_list = g_list_remove_link(prefs.col_list, col_link);
|
|
}
|
|
|
|
void
|
|
column_prefs_remove_nth(gint col)
|
|
{
|
|
column_prefs_remove_link(g_list_nth(prefs.col_list, col));
|
|
}
|
|
|
|
void save_migrated_uat(const char *uat_name, gboolean *old_pref)
|
|
{
|
|
char *err = NULL;
|
|
|
|
if (!uat_save(uat_get_table_by_name(uat_name), &err)) {
|
|
g_warning("Unable to save %s: %s", uat_name, err);
|
|
g_free(err);
|
|
return;
|
|
}
|
|
|
|
// Ensure that any old preferences are removed after successful migration.
|
|
if (*old_pref) {
|
|
*old_pref = FALSE;
|
|
prefs_main_write();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Editor modelines - https://www.wireshark.org/tools/modelines.html
|
|
*
|
|
* Local Variables:
|
|
* c-basic-offset: 4
|
|
* tab-width: 8
|
|
* indent-tabs-mode: nil
|
|
* End:
|
|
*
|
|
* ex: set shiftwidth=4 tabstop=8 expandtab:
|
|
* :indentSize=4:tabSize=8:noTabs=true:
|
|
*/
|