From 485bc456c57a16dbe50b76c476e48223038bb0e8 Mon Sep 17 00:00:00 2001 From: Roland Knall Date: Tue, 29 Dec 2015 07:57:36 +0100 Subject: extcap: Restore functionality for options Allow stored options to be restored to their default values. This adds a global cleanup method for extcap and globally defined preference values, which fixes the parameter problem with windows Change-Id: I48e0cf846ef81f4732d652c6a2ad0020db5df08e Reviewed-on: https://code.wireshark.org/review/13741 Petri-Dish: Roland Knall Tested-by: Petri Dish Buildbot Reviewed-by: Roland Knall --- capchild/capture_sync.c | 2 +- extcap.c | 145 +++++++++++++++++++++++++++------------- extcap.h | 19 ++++-- extcap_parser.c | 2 +- extcap_parser.h | 1 + rawshark.c | 16 +++++ tfshark.c | 19 ++++++ tshark.c | 19 ++++++ ui/gtk/main.c | 4 ++ ui/qt/extcap_argument.cpp | 52 +++++++++++--- ui/qt/extcap_argument.h | 11 ++- ui/qt/extcap_argument_file.cpp | 5 +- ui/qt/extcap_options_dialog.cpp | 114 +++++++++++++++++++++++++------ ui/qt/extcap_options_dialog.h | 4 ++ ui/qt/extcap_options_dialog.ui | 2 +- wireshark-qt.cpp | 4 ++ 16 files changed, 329 insertions(+), 90 deletions(-) diff --git a/capchild/capture_sync.c b/capchild/capture_sync.c index 9acb64e6bb..28c34a5542 100644 --- a/capchild/capture_sync.c +++ b/capchild/capture_sync.c @@ -1733,7 +1733,7 @@ sync_pipe_input_cb(gint source, gpointer user_data) #endif #ifdef HAVE_EXTCAP g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: cleaning extcap pipe"); - extcap_cleanup(cap_session->capture_opts); + extcap_if_cleanup(cap_session->capture_opts); #endif capture_input_closed(cap_session, primary_msg); g_free(primary_msg); diff --git a/extcap.c b/extcap.c index cff843487c..4fbf5d79e0 100644 --- a/extcap.c +++ b/extcap.c @@ -57,6 +57,8 @@ static HANDLE pipe_h = NULL; #endif +#define EXTCAP_PREF_SIZE 256 + /* internal container, for all the extcap interfaces that have been found. * will be resetted by every call to extcap_interface_list() and is being * used in extcap_get_if_* as well as extcap_init_interfaces to ensure, @@ -70,6 +72,12 @@ static GHashTable *ifaces = NULL; */ static GHashTable *tools = NULL; +/* internal container, to map preferences for extcap utilities to dynamic + * memory content, which survives extcap if garbage collection, and does + * not lead to dangling pointers + */ +static GHashTable *extcap_prefs_dynamic_vals = NULL; + /* Callback definition for extcap_foreach */ typedef gboolean (*extcap_cb_t)(const gchar *extcap, const gchar *ifname, gchar *output, void *data, gchar **err_str); @@ -417,6 +425,41 @@ void extcap_register_preferences(void) } } +void extcap_cleanup(void) +{ + if (extcap_prefs_dynamic_vals) { + g_hash_table_destroy(extcap_prefs_dynamic_vals); + } +} + +void extcap_pref_store(extcap_arg * arg, const char * newval) +{ + if (arg && arg->storeval != NULL) + { + memset(arg->storeval, 0, EXTCAP_PREF_SIZE * sizeof(char)); + if ( newval ) + g_snprintf(arg->storeval, EXTCAP_PREF_SIZE, "%s", newval); + } + +} + +static gchar * extcap_prefs_dynamic_valptr(const char *name) +{ + gchar *valp; + if (!extcap_prefs_dynamic_vals) { + /* Initialize table only as needed, most preferences are not dynamic */ + extcap_prefs_dynamic_vals = g_hash_table_new_full(g_str_hash, g_str_equal, + g_free, g_free); + } + valp = (gchar *)g_hash_table_lookup(extcap_prefs_dynamic_vals, name); + if (!valp) { + /* New dynamic pref, allocate, initialize and store. */ + valp = g_new0(gchar, EXTCAP_PREF_SIZE); + g_hash_table_insert(extcap_prefs_dynamic_vals, g_strdup(name), valp); + } + return valp; +} + static void extcap_free_if_configuration(GList *list) { GList *elem, *sl; @@ -433,32 +476,25 @@ static void extcap_free_if_configuration(GList *list) g_list_free(list); } -gchar * extcap_settings_key(const gchar * ifname, const gchar * setting) -{ - gchar * setting_nohyphen; - gchar * ifname_underscore; - gchar * ifname_lower; - gchar * key; - GRegex * regex = g_regex_new ("(?![a-zA-Z1-9_]).", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, NULL ); +struct preference * +extcap_pref_for_argument(const gchar *ifname, struct _extcap_arg * arg) { + struct preference * pref = NULL; - if (!regex) - return NULL; + GRegex * regex = g_regex_new ("[-]+", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, NULL ); + if (regex) { + if ( prefs_find_module("extcap") ) { + gchar * pref_name = g_regex_replace(regex, arg->call, strlen(arg->call), 0, "", (GRegexMatchFlags) 0, NULL ); + gchar * pref_ifname = g_strdup(g_strconcat(ifname, ".", pref_name, NULL)); - setting_nohyphen = - g_regex_replace_literal(regex, setting, strlen(setting), 0, - "", (GRegexMatchFlags) 0, NULL ); - ifname_underscore = - g_regex_replace_literal(regex, ifname, strlen(ifname), 0, - "_", (GRegexMatchFlags) 0, NULL ); - ifname_lower = g_utf8_strdown(ifname_underscore, -1); - key = g_strconcat(ifname_lower, ".", setting_nohyphen, NULL); + pref = prefs_find_preference(prefs_find_module("extcap"), pref_ifname); - g_free(setting_nohyphen); - g_free(ifname_underscore); - g_free(ifname_lower); - g_regex_unref(regex); + g_free(pref_name); + g_free(pref_ifname); + } + g_regex_unref(regex); + } - return key; + return pref; } static gboolean search_cb(const gchar *extcap _U_, const gchar *ifname _U_, gchar *output, void *data, @@ -482,29 +518,44 @@ static gboolean search_cb(const gchar *extcap _U_, const gchar *ifname _U_, gcha if ( dev_module ) { GList * walker = arguments; - while ( walker != NULL ) { - extcap_arg * arg = (extcap_arg *)walker->data; + GRegex * regex = g_regex_new ("[-]+", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, NULL ); + if (regex) { + while ( walker != NULL ) { + extcap_arg * arg = (extcap_arg *)walker->data; + arg->device_name = g_strdup(ifname); - if ( arg->save ) { - struct preference * pref = NULL; - gchar * pref_ifname = extcap_settings_key(ifname, arg->call); + if ( arg->save ) { + struct preference * pref = NULL; - if ( ( pref = prefs_find_preference(dev_module, pref_ifname) ) == NULL ) { - /* Set an initial value */ - if ( ! arg->storeval && arg->default_complex ) - arg->storeval = g_strdup(arg->default_complex->_val); + gchar * pref_name = g_regex_replace(regex, arg->call, strlen(arg->call), 0, "", (GRegexMatchFlags) 0, NULL ); + gchar * pref_ifname = g_strdup(g_strconcat(ifname, ".", pref_name, NULL)); + + if ( ( pref = prefs_find_preference(dev_module, pref_ifname) ) == NULL ) { + /* Set an initial value */ + if ( ! arg->storeval && arg->default_complex ) + { + arg->storeval = extcap_prefs_dynamic_valptr(pref_ifname); + g_snprintf(arg->storeval, EXTCAP_PREF_SIZE, "%s", arg->default_complex->_val); + } - prefs_register_string_preference(dev_module, g_strdup(pref_ifname), - arg->display, arg->display, (const gchar **)(void*)(&arg->storeval)); - } else { - /* Been here before, restore stored value */ - if (! arg->storeval && pref->varp.string) - arg->storeval = g_strdup(*(pref->varp.string)); + prefs_register_string_preference(dev_module, g_strdup(pref_ifname), + arg->display, arg->display, (const gchar **)&(arg->storeval)); + } else { + /* Been here before, restore stored value */ + if (! arg->storeval && pref->varp.string) + { + arg->storeval = extcap_prefs_dynamic_valptr(pref_ifname); + g_snprintf(arg->storeval, EXTCAP_PREF_SIZE, "%s", *(pref->varp.string)); + } } - g_free(pref_ifname); - } - walker = g_list_next(walker); + g_free(pref_name); + g_free(pref_ifname); + } + + walker = g_list_next(walker); + } + g_regex_unref(regex); } } @@ -592,7 +643,7 @@ extcap_has_configuration(const char * ifname, gboolean is_required) { return found; } -void extcap_cleanup(capture_options * capture_opts) { +void extcap_if_cleanup(capture_options * capture_opts) { interface_options interface_opts; guint icnt = 0; @@ -691,15 +742,15 @@ static void extcap_child_watch_cb(GPid pid, gint status _U_, gpointer user_data) static GPtrArray * extcap_prepare_arguments(interface_options interface_opts) { - GPtrArray *result = NULL; + GPtrArray *result = NULL; #if ARG_DEBUG gchar **tmp; int tmp_i; #endif - if (interface_opts.if_type == IF_EXTCAP ) - { - result = g_ptr_array_new(); + if (interface_opts.if_type == IF_EXTCAP ) + { + result = g_ptr_array_new(); #define add_arg(X) g_ptr_array_add(result, g_strdup(X)) @@ -781,9 +832,9 @@ GPtrArray * extcap_prepare_arguments(interface_options interface_opts) } #endif - } + } - return result; + return result; } /* call mkfifo for each extcap, diff --git a/extcap.h b/extcap.h index 509e007a5e..d8e94b9fad 100644 --- a/extcap.h +++ b/extcap.h @@ -28,6 +28,8 @@ #include +#include "ws_symbol_export.h" + #ifdef _WIN32 #include #include @@ -57,6 +59,8 @@ typedef struct _extcap_info { gchar * version; } extcap_info; +struct _extcap_arg; + #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ @@ -85,9 +89,6 @@ extcap_get_if_configuration(const char * ifname); gboolean extcap_has_configuration(const char * ifname, gboolean is_required); -/* converts an extcap setting to its equivalent preference key */ -gchar * extcap_settings_key(const gchar * ifname, const gchar * setting); - #ifdef WIN32 HANDLE extcap_get_win32_handle(); @@ -99,8 +100,18 @@ extcap_init_interfaces(capture_options * capture_opts); gboolean extcap_create_pipe(char ** fifo); +/* Clean up all if related stuff */ void -extcap_cleanup(capture_options * capture_opts _U_); +extcap_if_cleanup(capture_options * capture_opts _U_); + +struct preference * +extcap_pref_for_argument(const gchar *ifname, struct _extcap_arg * arg); + +void +extcap_pref_store(struct _extcap_arg * arg, const char * newval); + +/* Clean up global extcap stuff on program exit */ +void extcap_cleanup(void); #ifdef __cplusplus } diff --git a/extcap_parser.c b/extcap_parser.c index 1e6b1170a8..3fe0817465 100644 --- a/extcap_parser.c +++ b/extcap_parser.c @@ -350,7 +350,7 @@ void extcap_free_arg(extcap_arg *a) { g_free(a->tooltip); g_free(a->fileextension); g_free(a->regexp); - g_free(a->storeval); + g_free(a->device_name); if (a->range_start != NULL) extcap_free_complex(a->range_start); diff --git a/extcap_parser.h b/extcap_parser.h index e43e1ac6db..b6cc762797 100644 --- a/extcap_parser.h +++ b/extcap_parser.h @@ -118,6 +118,7 @@ typedef struct _extcap_arg { extcap_complex *default_complex; gchar * storeval; + gchar * device_name; GList * values; } extcap_arg; diff --git a/rawshark.c b/rawshark.c index ebfbea4f56..fe68b76f92 100644 --- a/rawshark.c +++ b/rawshark.c @@ -96,6 +96,10 @@ #include "caputils/capture-pcap-util.h" +#ifdef HAVE_EXTCAP +#include "extcap.h" +#endif + #ifdef HAVE_LIBPCAP #include #ifdef _WIN32 @@ -798,6 +802,9 @@ main(int argc, char *argv[]) cmdarg_err("%s", err_msg); g_free(err_msg); epan_free(cfile.epan); +#ifdef HAVE_EXTCAP + extcap_cleanup(); +#endif epan_cleanup(); exit(2); } @@ -819,6 +826,9 @@ main(int argc, char *argv[]) if (raw_cf_open(&cfile, pipe_name) != CF_OK) { epan_free(cfile.epan); +#ifdef HAVE_EXTCAP + extcap_cleanup(); +#endif epan_cleanup(); exit(2); } @@ -840,6 +850,9 @@ main(int argc, char *argv[]) /* Process the packets in the file */ if (!load_cap_file(&cfile)) { epan_free(cfile.epan); +#ifdef HAVE_EXTCAP + extcap_cleanup(); +#endif epan_cleanup(); exit(2); } @@ -850,6 +863,9 @@ main(int argc, char *argv[]) } epan_free(cfile.epan); +#ifdef HAVE_EXTCAP + extcap_cleanup(); +#endif epan_cleanup(); return 0; diff --git a/tfshark.c b/tfshark.c index fe97057713..4bea91c727 100644 --- a/tfshark.c +++ b/tfshark.c @@ -80,6 +80,10 @@ #include #endif +#ifdef HAVE_EXTCAP +#include "extcap.h" +#endif + #include #include @@ -859,6 +863,9 @@ main(int argc, char *argv[]) * cruft getting in the way. Makes the results of running * $ ./tools/valgrind-wireshark -n * much more useful. */ +#ifdef HAVE_EXTCAP + extcap_cleanup(); +#endif epan_cleanup(); return 0; } @@ -987,6 +994,9 @@ main(int argc, char *argv[]) if (!dfilter_compile(rfilter, &rfcode, &err_msg)) { cmdarg_err("%s", err_msg); g_free(err_msg); +#ifdef HAVE_EXTCAP + extcap_cleanup(); +#endif epan_cleanup(); return 2; } @@ -997,6 +1007,9 @@ main(int argc, char *argv[]) if (!dfilter_compile(dfilter, &dfcode, &err_msg)) { cmdarg_err("%s", err_msg); g_free(err_msg); +#ifdef HAVE_EXTCAP + extcap_cleanup(); +#endif epan_cleanup(); return 2; } @@ -1042,6 +1055,9 @@ main(int argc, char *argv[]) /* TODO: if tfshark is ever changed to give the user a choice of which open_routine reader to use, then the following needs to change. */ if (cf_open(&cfile, cf_name, WTAP_TYPE_AUTO, FALSE, &err) != CF_OK) { +#ifdef HAVE_EXTCAP + extcap_cleanup(); +#endif epan_cleanup(); return 2; } @@ -1080,6 +1096,9 @@ main(int argc, char *argv[]) draw_tap_listeners(TRUE); funnel_dump_all_text_windows(); epan_free(cfile.epan); +#ifdef HAVE_EXTCAP + extcap_cleanup(); +#endif epan_cleanup(); output_fields_free(output_fields); diff --git a/tshark.c b/tshark.c index 452e420bb3..7a8c2d4d63 100644 --- a/tshark.c +++ b/tshark.c @@ -122,6 +122,10 @@ #include #include +#ifdef HAVE_EXTCAP +#include "extcap.h" +#endif + #ifdef HAVE_PLUGINS #include #endif @@ -1306,6 +1310,9 @@ main(int argc, char *argv[]) * cruft getting in the way. Makes the results of running * $ ./tools/valgrind-wireshark -n * much more useful. */ +#ifdef HAVE_EXTCAP + extcap_cleanup(); +#endif epan_cleanup(); return 0; case 'O': /* Only output these protocols */ @@ -1725,6 +1732,9 @@ main(int argc, char *argv[]) if (!dfilter_compile(rfilter, &rfcode, &err_msg)) { cmdarg_err("%s", err_msg); g_free(err_msg); +#ifdef HAVE_EXTCAP + extcap_cleanup(); +#endif epan_cleanup(); #ifdef HAVE_PCAP_OPEN_DEAD { @@ -1751,6 +1761,9 @@ main(int argc, char *argv[]) if (!dfilter_compile(dfilter, &dfcode, &err_msg)) { cmdarg_err("%s", err_msg); g_free(err_msg); +#ifdef HAVE_EXTCAP + extcap_cleanup(); +#endif epan_cleanup(); #ifdef HAVE_PCAP_OPEN_DEAD { @@ -1862,6 +1875,9 @@ main(int argc, char *argv[]) * We're reading a capture file. */ if (cf_open(&cfile, cf_name, in_file_type, FALSE, &err) != CF_OK) { +#ifdef HAVE_EXTCAP + extcap_cleanup(); +#endif epan_cleanup(); return 2; } @@ -2023,6 +2039,9 @@ main(int argc, char *argv[]) draw_tap_listeners(TRUE); funnel_dump_all_text_windows(); epan_free(cfile.epan); +#ifdef HAVE_EXTCAP + extcap_cleanup(); +#endif epan_cleanup(); output_fields_free(output_fields); diff --git a/ui/gtk/main.c b/ui/gtk/main.c index b827509a24..4ff33feebc 100644 --- a/ui/gtk/main.c +++ b/ui/gtk/main.c @@ -2758,6 +2758,10 @@ main(int argc, char *argv[]) gtk_iface_mon_stop(); #endif +#ifdef HAVE_EXTCAP + extcap_cleanup(); +#endif + epan_cleanup(); AirPDcapDestroyContext(&airpdcap_ctx); diff --git a/ui/qt/extcap_argument.cpp b/ui/qt/extcap_argument.cpp index 9f5ecbacaf..5c2eff18c2 100644 --- a/ui/qt/extcap_argument.cpp +++ b/ui/qt/extcap_argument.cpp @@ -47,6 +47,7 @@ #include #include +#include #include #include @@ -280,11 +281,8 @@ bool ExtArgBool::defaultBool() if ( _argument ) { - if ( _argument->default_complex ) - { - if ( extcap_complex_get_bool(_argument->default_complex) == (gboolean)TRUE ) - result = true; - } + if ( extcap_complex_get_bool(_argument->default_complex) == (gboolean)TRUE ) + result = true; } return result; @@ -485,6 +483,12 @@ void ExtcapValue::setChildren(ExtcapValueList children) _children.append(children); } +ExtcapArgument::ExtcapArgument(QObject *parent) : + QObject(parent), _argument(0), _label(0), + label_style(QString("QLabel { color: %1; }")) +{ +} + ExtcapArgument::ExtcapArgument(extcap_arg * argument, QObject *parent) : QObject(parent), _argument(argument), _label(0), label_style(QString("QLabel { color: %1; }")) @@ -497,9 +501,21 @@ ExtcapArgument::ExtcapArgument(extcap_arg * argument, QObject *parent) : } } +ExtcapArgument::ExtcapArgument(const ExtcapArgument &obj) : + QObject(obj.parent()), _argument(obj._argument), _label(0), + label_style(QString("QLabel { color: %1; }")) +{ + if ( _argument->values != 0 ) + { + ExtcapValueList elements = loadValues(QString("")); + if ( elements.length() > 0 ) + values.append(elements); + } +} + ExtcapValueList ExtcapArgument::loadValues(QString parent) { - if (_argument->values == 0 ) + if (_argument == 0 || _argument->values == 0 ) return ExtcapValueList(); GList * walker = 0; @@ -532,7 +548,6 @@ ExtcapValueList ExtcapArgument::loadValues(QString parent) } ExtcapArgument::~ExtcapArgument() { - // TODO Auto-generated destructor stub } QWidget * ExtcapArgument::createLabel(QWidget * parent) @@ -544,7 +559,10 @@ QWidget * ExtcapArgument::createLabel(QWidget * parent) QString text = QString().fromUtf8(_argument->display); - _label = new QLabel(text, parent); + if ( _label == 0 ) + _label = new QLabel(text, parent); + else + _label->setText(text); _label->setProperty("isRequired", QString(isRequired() ? "true" : "false")); @@ -553,7 +571,7 @@ QWidget * ExtcapArgument::createLabel(QWidget * parent) if ( _argument->tooltip != 0 ) _label->setToolTip(QString().fromUtf8(_argument->tooltip)); - return _label; + return (QWidget *)_label; } QWidget * ExtcapArgument::createEditor(QWidget *) @@ -576,6 +594,12 @@ QString ExtcapArgument::prefValue() return value(); } +void ExtcapArgument::resetValue() +{ + if (_argument && _argument->storeval) + memset(_argument->storeval, 0, 128 * sizeof(char)); +} + bool ExtcapArgument::isValid() { /* Unrequired arguments are always valid, except if validity checks fail, @@ -599,10 +623,16 @@ QString ExtcapArgument::defaultValue() QString ExtcapArgument::prefKey(const QString & device_name) { - if ( ! _argument->save ) + struct preference * pref = NULL; + + if ( _argument == 0 || ! _argument->save ) return QString(); - return QString(extcap_settings_key(device_name.toStdString().c_str(), _argument->call)); + pref = extcap_pref_for_argument(device_name.toStdString().c_str(), _argument); + if ( pref != NULL ) + return QString(pref->name); + + return QString(); } bool ExtcapArgument::isRequired() diff --git a/ui/qt/extcap_argument.h b/ui/qt/extcap_argument.h index 084b3336f1..d4cfd875ec 100644 --- a/ui/qt/extcap_argument.h +++ b/ui/qt/extcap_argument.h @@ -82,8 +82,9 @@ class ExtcapArgument: public QObject Q_OBJECT public: + ExtcapArgument(QObject *parent=0); ExtcapArgument(extcap_arg * argument, QObject *parent=0); - + ExtcapArgument(const ExtcapArgument &obj); virtual ~ExtcapArgument(); virtual QWidget * createLabel(QWidget * parent = 0); @@ -95,12 +96,14 @@ public: virtual QString defaultValue(); bool isDefault(); - bool isValid(); + virtual bool isValid(); bool isRequired(); QString prefKey(const QString & device_name); virtual QString prefValue(); + void resetValue(); + static ExtcapArgument * create(extcap_arg * argument = 0); Q_SIGNALS: @@ -115,7 +118,7 @@ protected: ExtcapValueList values; extcap_arg * _argument; - QWidget * _label; + QLabel * _label; const QString label_style; @@ -127,6 +130,8 @@ private Q_SLOTS: }; +Q_DECLARE_METATYPE(ExtcapArgument) + class ExtArgText : public ExtcapArgument { diff --git a/ui/qt/extcap_argument_file.cpp b/ui/qt/extcap_argument_file.cpp index 5e538036bb..df8da8caeb 100644 --- a/ui/qt/extcap_argument_file.cpp +++ b/ui/qt/extcap_argument_file.cpp @@ -57,15 +57,16 @@ QWidget * ExtcapArgumentFileSelection::createEditor(QWidget * parent) { QString storeval; QString text = defaultValue(); + QString buttonText(UTF8_HORIZONTAL_ELLIPSIS); QWidget * fileWidget = new QWidget(parent); QHBoxLayout * editLayout = new QHBoxLayout(); QMargins margins = editLayout->contentsMargins(); editLayout->setContentsMargins(0, 0, 0, margins.bottom()); fileWidget->setContentsMargins(margins.left(), margins.right(), 0, margins.bottom()); - QPushButton * button = new QPushButton(UTF8_HORIZONTAL_ELLIPSIS, fileWidget); + QPushButton * button = new QPushButton(buttonText, fileWidget); - textBox = new QLineEdit(defaultValue(), parent); + textBox = new QLineEdit(text, parent); textBox->setReadOnly(true); if ( _argument->storeval ) diff --git a/ui/qt/extcap_options_dialog.cpp b/ui/qt/extcap_options_dialog.cpp index 07c0523628..cd728d8d91 100644 --- a/ui/qt/extcap_options_dialog.cpp +++ b/ui/qt/extcap_options_dialog.cpp @@ -190,29 +190,24 @@ void ExtcapOptionsDialog::anyValueChanged() ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(allowStart); } -void ExtcapOptionsDialog::updateWidgets() +void ExtcapOptionsDialog::loadArguments() { - GList * arguments = NULL, * walker = NULL, * item = NULL; - QWidget * lblWidget = NULL, *editWidget = NULL; + GList * arguments = NULL, * item = NULL; ExtcapArgument * argument = NULL; - bool allowStart = true; - - unsigned int counter = 0; if ( device_name.length() == 0 ) return; - arguments = extcap_get_if_configuration((const char *)( device_name.toStdString().c_str() ) ); - walker = g_list_first(arguments); + extcapArguments.clear(); - QGridLayout * layout = new QGridLayout(); + arguments = g_list_first(extcap_get_if_configuration((const char *)( device_name.toStdString().c_str() ) )); ExtcapArgumentList required; ExtcapArgumentList optional; - while ( walker != NULL ) + while ( arguments != NULL ) { - item = g_list_first((GList *)(walker->data)); + item = g_list_first((GList *)(arguments->data)); while ( item != NULL ) { argument = ExtcapArgument::create((extcap_arg *)(item->data)); @@ -226,7 +221,7 @@ void ExtcapOptionsDialog::updateWidgets() } item = item->next; } - walker = walker->next; + arguments = g_list_next(arguments); } if ( required.length() > 0 ) @@ -234,24 +229,52 @@ void ExtcapOptionsDialog::updateWidgets() if ( optional.length() > 0 ) extcapArguments << optional; +} + +void ExtcapOptionsDialog::updateWidgets() +{ + QWidget * lblWidget = NULL, *editWidget = NULL; + ExtcapArgument * argument = NULL; + bool allowStart = true; + + unsigned int counter = 0; + + if ( device_name.length() == 0 ) + return; + + /* find existing layout */ + if (ui->verticalLayout->children().count() > 0) + { + QGridLayout * layout = (QGridLayout *)ui->verticalLayout->itemAt(0); + ui->verticalLayout->removeItem(layout); + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + } + + QGridLayout * layout = new QGridLayout(); + + /* Load all extcap arguments */ + loadArguments(); + ExtcapArgumentList::iterator iter = extcapArguments.begin(); while ( iter != extcapArguments.end() ) { - lblWidget = (*iter)->createLabel((QWidget *)this); + argument = (ExtcapArgument *)(*iter); + lblWidget = argument->createLabel((QWidget *)this); if ( lblWidget != NULL ) { layout->addWidget(lblWidget, counter, 0, Qt::AlignVCenter); - editWidget = (*iter)->createEditor((QWidget *) this); + editWidget = argument->createEditor((QWidget *) this); if ( editWidget != NULL ) { + editWidget->setProperty(QString("extcap").toLocal8Bit(), QVariant::fromValue(argument)); layout->addWidget(editWidget, counter, 1, Qt::AlignVCenter); } - if ( (*iter)->isRequired() && ! (*iter)->isValid() ) + if ( argument->isRequired() && ! argument->isValid() ) allowStart = false; - connect((*iter), SIGNAL(valueChanged()), this, SLOT(anyValueChanged())); + connect(argument, SIGNAL(valueChanged()), this, SLOT(anyValueChanged())); counter++; } @@ -326,6 +349,59 @@ bool ExtcapOptionsDialog::saveOptionToCaptureInfo() return true; } +void ExtcapOptionsDialog::on_buttonBox_clicked(QAbstractButton *button) +{ + /* Only the save button has the ActionRole */ + if ( ui->buttonBox->buttonRole(button) == QDialogButtonBox::ResetRole ) + resetValues(); +} + +void ExtcapOptionsDialog::resetValues() +{ + ExtcapArgumentList::const_iterator iter; + QString value; + + if (ui->verticalLayout->children().count() > 0) + { + QGridLayout * layout = (QGridLayout *)ui->verticalLayout->findChild(); + + for ( int row = 0; row < layout->rowCount(); row++ ) + { + QWidget * child = layout->itemAtPosition(row, 1)->widget(); + + if ( child ) + { + /* Don't need labels, the edit widget contains the extcapargument property value */ + ExtcapArgument * arg = 0; + QVariant prop = child->property(QString("extcap").toLocal8Bit()); + + if ( prop.isValid() && prop.canConvert()) + { + arg = prop.value(); + + /* value<> can fail */ + if (arg) + { + arg->resetValue(); + + /* replacing the edit widget after resetting will lead to default value */ + layout->removeItem(layout->itemAtPosition(row, 1)); + QWidget * editWidget = arg->createEditor((QWidget *) this); + if ( editWidget != NULL ) + { + editWidget->setProperty(QString("extcap").toLocal8Bit(), QVariant::fromValue(arg)); + layout->addWidget(editWidget, row, 1, Qt::AlignVCenter); + } + } + } + } + } + + /* this stores all values to the preferences */ + storeValues(); + } +} + void ExtcapOptionsDialog::storeValues() { GHashTable * entries = g_hash_table_new(g_str_hash, g_str_equal); @@ -379,7 +455,7 @@ void ExtcapOptionsDialog::storeValues() gchar * val = g_strdup(value.length() == 0 ? " " : value.toStdString().c_str()); /* Setting the internally stored value for the preference to the new value */ - (*iter)->argument()->storeval = g_strdup(val); + extcap_pref_store((*iter)->argument(), val); g_hash_table_insert(entries, g_strdup(key.toStdString().c_str()), val); } @@ -388,10 +464,8 @@ void ExtcapOptionsDialog::storeValues() if ( g_hash_table_size(entries) > 0 ) { if ( prefs_store_ext_multiple("extcap", entries) ) - { - wsApp->emitAppSignal(WiresharkApplication::PacketDissectionChanged); wsApp->emitAppSignal(WiresharkApplication::PreferencesChanged); - } + } } diff --git a/ui/qt/extcap_options_dialog.h b/ui/qt/extcap_options_dialog.h index 3ca859ed35..14850a3836 100644 --- a/ui/qt/extcap_options_dialog.h +++ b/ui/qt/extcap_options_dialog.h @@ -56,6 +56,7 @@ public: private Q_SLOTS: void on_buttonBox_accepted(); void on_buttonBox_rejected(); + void on_buttonBox_clicked(QAbstractButton *button); void on_buttonBox_helpRequested(); void updateWidgets(); void anyValueChanged(); @@ -69,8 +70,11 @@ private: ExtcapArgumentList extcapArguments; + void loadArguments(); + bool saveOptionToCaptureInfo(); void storeValues(); + void resetValues(); }; #endif /* HAVE_EXTCAP */ diff --git a/ui/qt/extcap_options_dialog.ui b/ui/qt/extcap_options_dialog.ui index edd6c96c8c..aba67309ef 100644 --- a/ui/qt/extcap_options_dialog.ui +++ b/ui/qt/extcap_options_dialog.ui @@ -40,7 +40,7 @@ - QDialogButtonBox::Close|QDialogButtonBox::Help|QDialogButtonBox::Ok + QDialogButtonBox::Close|QDialogButtonBox::Help|QDialogButtonBox::Ok|QDialogButtonBox::RestoreDefaults diff --git a/wireshark-qt.cpp b/wireshark-qt.cpp index 7bdf9466ee..d32dfeb23b 100644 --- a/wireshark-qt.cpp +++ b/wireshark-qt.cpp @@ -852,6 +852,10 @@ int main(int argc, char *argv[]) ret_val = wsApp->exec(); +#ifdef HAVE_EXTCAP + extcap_cleanup(); +#endif + epan_cleanup(); AirPDcapDestroyContext(&airpdcap_ctx); -- cgit v1.2.1