extcap: Add Save functionality to options dialog
authorRoland Knall <roland.knall@br-automation.com>
Tue, 29 Dec 2015 06:57:36 +0000 (07:57 +0100)
committerRoland Knall <rknall@gmail.com>
Mon, 1 Feb 2016 12:12:41 +0000 (12:12 +0000)
This patch creates the functionality of saving all parameters
for extcap devices in the general preference section.

For now, multiselect and fileselect do not save their values
but patches for this will be provided in the future

Also, all preferences are stored as strings to make handling
easier. This might change in the future, but for the first version
it will stick.

Restore to Defaults is not implemented as of yet, and will be
in a future version, once the preference storing is finalized

Bug: 11666
Change-Id: I178346405146d2e43f4f3481c05c92c0b3595af5
Reviewed-on: https://code.wireshark.org/review/13451
Petri-Dish: Roland Knall <rknall@gmail.com>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Roland Knall <rknall@gmail.com>
15 files changed:
doc/README.extcap
doc/extcap_example.py
epan/prefs.c
epan/prefs.h
extcap.c
extcap.h
extcap_parser.c
extcap_parser.h
ui/gtk/main.c
ui/qt/extcap_argument.cpp
ui/qt/extcap_argument.h
ui/qt/extcap_options_dialog.cpp
ui/qt/extcap_options_dialog.h
ui/qt/extcap_options_dialog.ui
wireshark-qt.cpp

index 7b53b7fcfd65c02da24e1982a3b65c38a06ea2b8..6a4f33f44df0e1d5ebf55523f0f29b0cefb297c4 100644 (file)
@@ -150,7 +150,8 @@ These options do have types, for which the following types are being supported:
      the user input for validity beyond normal data type or range checks. Back-slashes
      must be escaped (as in \\b for \b)
 
- * PASSWORD - Let the user provide a masked string to the capture
+ * PASSWORD - Let the user provide a masked string to the capture. Password strings are
+   not saved, when the extcap configuration is being saved
 
    arg {number=0}{call=--password}{display=The user password}{tooltip=The password for the connection}{type=password}
 
index 571605837ef3f6b2d8d016bcf0ef6874b080f566..ab9967c4891f88b5d1aac7b6a2fc1929c3e73799 100755 (executable)
@@ -78,7 +78,10 @@ def extcap_config(interface):
        args.append ( (2, '--verify', 'Verify', 'Verify package content', 'boolflag', '{default=yes}') )
        args.append ( (3, '--remote', 'Remote Channel', 'Remote Channel Selector', 'selector', ''))
        args.append ( (4, '--fake_ip', 'Fake IP Address', 'Use this ip address as sender', 'string', '{save=false}{validation=\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b}'))
-       args.append ( (5, '--password', 'Password', 'Package message password', 'password', '') )
+       args.append ( (5, '--ltest', 'Long Test', 'Long Test Value', 'long', '{default=123123123123123123}'))
+       args.append ( (6, '--d1test', 'Double 1 Test', 'Long Test Value', 'double', '{default=123.456}'))
+       args.append ( (7, '--d2test', 'Double 2 Test', 'Long Test Value', 'double', '{default= 123,456}'))
+       args.append ( (8, '--password', 'Password', 'Package message password', 'password', '') )
 
        values.append ( (3, "if1", "Remote1", "true" ) )
        values.append ( (3, "if2", "Remote2", "false" ) )
index 2fb1b0d5678e8ccf895b256132dd69310d655115..fc471e00ad7a2b6e06ce8d54457c1aa40879d305 100644 (file)
@@ -2082,6 +2082,10 @@ prefs_register_modules(void)
 {
     module_t *printing, *capture_module, *console_module,
         *gui_layout_module, *gui_font_module;
+#ifdef HAVE_EXTCAP
+    module_t *extcap_module;
+#endif
+
     struct pref_custom_cbs custom_cbs;
 
     if (protocols_module != NULL) {
@@ -2089,6 +2093,24 @@ prefs_register_modules(void)
         return;
     }
 
+#ifdef HAVE_EXTCAP
+    /* GUI
+     * These are "simple" GUI preferences that can be read/written using the
+     * preference module API.  These preferences still use their own
+     * configuration screens for access, but this cuts down on the
+     * preference "string compare list" in set_pref()
+     */
+    extcap_module = prefs_register_module(NULL, "extcap", "Extcap Utilities",
+        "Extcap Utilities", NULL, FALSE);
+
+    /* Setting default value to true */
+    prefs.extcap_save_on_start = TRUE;
+    prefs_register_bool_preference(extcap_module, "gui_save_on_start",
+                                   "Save arguments on start of capture",
+                                   "Save arguments on start of capture",
+                                   &prefs.extcap_save_on_start);
+#endif
+
     /* GUI
      * These are "simple" GUI preferences that can be read/written using the
      * preference module API.  These preferences still use their own
index 6bb48d70dd8a6275534fb3b44e74b8ced350cc24..fd8afce28b4a70f70e982fbc71620ccb4191d5e7 100644 (file)
@@ -236,6 +236,9 @@ typedef struct _e_prefs {
   gint         st_sort_defcolflag;
   gboolean     st_sort_defdescending;
   gboolean     st_sort_showfullname;
+#ifdef HAVE_EXTCAP
+  gboolean     extcap_save_on_start;
+#endif
 } e_prefs;
 
 WS_DLL_PUBLIC e_prefs prefs;
index df40bd10172f7497b286ef94f113703ac38471e2..c2f01d102aef827ad6fb27bd28a524c11f2dbb66 100644 (file)
--- a/extcap.c
+++ b/extcap.c
@@ -40,6 +40,9 @@
 #include <glib.h>
 #include <log.h>
 
+#include <epan/prefs.h>
+#include <epan/prefs-int.h>
+
 #include <wsutil/file_util.h>
 #include <wsutil/filesystem.h>
 #include <wsutil/tempfile.h>
@@ -69,7 +72,7 @@ static GHashTable *ifaces = NULL;
 static GHashTable *tools = NULL;
 
 /* Callback definition for extcap_foreach */
-typedef gboolean (*extcap_cb_t)(const gchar *extcap, gchar *output, void *data,
+typedef gboolean (*extcap_cb_t)(const gchar *extcap, const gchar *ifname, gchar *output, void *data,
         gchar **err_str);
 
 /* #define ARG_DEBUG */
@@ -201,7 +204,7 @@ static void extcap_foreach(gint argc, gchar **args, extcap_cb_t cb,
                     &command_output, NULL, &exit_status, &error);
 
             if (status && exit_status == 0)
-            keep_going = cb(extcap_path->str, command_output, cb_data, err_str);
+            keep_going = cb(extcap_path->str, ifname, command_output, cb_data, err_str);
 
             g_free(argv[0]);
             g_free(command_output);
@@ -217,7 +220,7 @@ static void extcap_foreach(gint argc, gchar **args, extcap_cb_t cb,
     g_free(argv);
 }
 
-static gboolean dlt_cb(const gchar *extcap _U_, gchar *output, void *data,
+static gboolean dlt_cb(const gchar *extcap _U_, const gchar *ifname _U_, gchar *output, void *data,
         char **err_str) {
     extcap_token_sentence *tokens;
     extcap_dlt *dlts, *dlt_iter, *next;
@@ -300,7 +303,7 @@ extcap_get_if_dlts(const gchar *ifname, char **err_str) {
     return caps;
 }
 
-static gboolean interfaces_cb(const gchar *extcap, gchar *output, void *data,
+static gboolean interfaces_cb(const gchar *extcap, const gchar *ifname _U_, gchar *output, void *data,
         char **err_str _U_) {
     GList **il = (GList **) data;
     extcap_token_sentence *tokens;
@@ -422,6 +425,27 @@ static void extcap_free_arg_elem(gpointer data, gpointer user_data _U_) {
     g_free(data);
 }
 
+void extcap_register_preferences(void)
+{
+    GList * interfaces = NULL;
+
+    module_t * dev_module = prefs_find_module("extcap");
+
+    if ( !dev_module )
+        return;
+
+    if ( ! ifaces || g_hash_table_size(ifaces) == 0 )
+        extcap_interface_list(NULL);
+
+    interfaces = g_hash_table_get_keys(ifaces);
+
+    while ( interfaces ) {
+        extcap_get_if_configuration((gchar *)interfaces->data);
+
+        interfaces = g_list_next(interfaces);
+    }
+}
+
 static void extcap_free_if_configuration(GList *list)
 {
     GList *elem, *sl;
@@ -438,11 +462,12 @@ static void extcap_free_if_configuration(GList *list)
     g_list_free(list);
 }
 
-static gboolean search_cb(const gchar *extcap _U_, gchar *output, void *data,
+static gboolean search_cb(const gchar *extcap _U_, const gchar *ifname _U_, gchar *output, void *data,
         char **err_str _U_) {
     extcap_token_sentence *tokens = NULL;
     GList *arguments = NULL;
     GList **il = (GList **) data;
+    module_t * dev_module = NULL;
 
     tokens = extcap_tokenize_sentences(output);
     arguments = extcap_parse_args(tokens);
@@ -453,6 +478,45 @@ static gboolean search_cb(const gchar *extcap _U_, gchar *output, void *data,
     extcap_debug_arguments ( arguments );
 #endif
 
+    dev_module = prefs_find_module("extcap");
+
+    if ( dev_module ) {
+        GList * walker = arguments;
+
+        GRegex * regex = g_regex_new ("[-]+", (GRegexCompileFlags) 0, (GRegexMatchFlags) 0, NULL );
+        if (regex) {
+            while ( walker != NULL ) {
+                extcap_arg * arg = (extcap_arg *)walker->data;
+
+                if ( arg->save ) {
+                    struct preference * pref = NULL;
+
+                    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 = g_strdup(arg->default_complex->_val);
+
+                        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 = g_strdup(*(pref->varp.string));
+                    }
+
+                    g_free(pref_name);
+                    g_free(pref_ifname);
+                }
+
+                walker = g_list_next(walker);
+            }
+            g_regex_unref(regex);
+        }
+    }
+
     *il = g_list_append(*il, arguments);
 
     /* By returning false, extcap_foreach will break on first found */
@@ -494,16 +558,33 @@ extcap_has_configuration(const char * ifname, gboolean is_required) {
     arguments = extcap_get_if_configuration((const char *)( ifname ) );
     walker = g_list_first(arguments);
 
-    while ( walker != NULL && ! found )
-    {
+    while ( walker != NULL && ! found ) {
         item = g_list_first((GList *)(walker->data));
-        while ( item != NULL && ! found )
-        {
-            if ( (extcap_arg *)(item->data) != NULL )
-            {
+        while ( item != NULL && ! found ) {
+            if ( (extcap_arg *)(item->data) != NULL ) {
+                extcap_arg * arg = (extcap_arg *)(item->data);
                 /* Should required options be present, or any kind of options */
-                if ( ! is_required || ((extcap_arg *)(item->data))->is_required )
+                if ( ! is_required )
                     found = TRUE;
+                else if ( arg->is_required ) {
+                    gchar * stored = NULL;
+                    gchar * defval = NULL;
+
+                    if ( arg->storeval != NULL )
+                        stored = arg->storeval;
+
+                    if ( arg->default_complex != NULL && arg->default_complex->_val != NULL )
+                        defval = arg->default_complex->_val;
+
+                    if ( arg->is_required ) {
+                        /* If stored and defval is identical and the argument is required,
+                         * configuration is needed */
+                        if ( defval && stored && g_strcmp0(stored, defval) == 0 )
+                            found = TRUE;
+                        else if ( ! defval && (!stored || strlen(g_strchomp(stored)) <= (size_t)0) )
+                            found = TRUE;
+                    }
+                }
             }
 
             item = item->next;
@@ -574,8 +655,8 @@ void extcap_cleanup(capture_options * capture_opts) {
     }
 }
 
-static void
-extcap_arg_cb(gpointer key, gpointer value, gpointer data) {
+static gboolean
+extcap_add_arg_and_remove_cb(gpointer key, gpointer value, gpointer data) {
     GPtrArray *args = (GPtrArray *)data;
 
     if ( key != NULL )
@@ -584,7 +665,11 @@ extcap_arg_cb(gpointer key, gpointer value, gpointer data) {
 
         if ( value != NULL )
             g_ptr_array_add(args, g_strdup((const gchar*)value));
+
+        return TRUE;
     }
+
+    return FALSE;
 }
 
 static void extcap_child_watch_cb(GPid pid, gint status _U_, gpointer user_data)
@@ -650,7 +735,7 @@ extcap_init_interfaces(capture_options *capture_opts)
         }
         add_arg(EXTCAP_ARGUMENT_RUN_PIPE);
         add_arg(interface_opts.extcap_fifo);
-        if (interface_opts.extcap_args == NULL)
+        if (interface_opts.extcap_args == NULL || g_hash_table_size(interface_opts.extcap_args) == 0)
         {
             /* User did not perform interface configuration.
              *
@@ -672,18 +757,29 @@ extcap_init_interfaces(capture_options *capture_opts)
                 }
 
                 arg_list = g_list_first((GList *)elem->data);
-                while (arg_list != NULL)
-                {
+                while (arg_list != NULL) {
+                    gchar * stored = NULL, * defval = NULL;
                     /* In case of boolflags only first element in arg_list is relevant. */
                     arg_iter = (extcap_arg*) (arg_list->data);
-
-                    if  (arg_iter->arg_type == EXTCAP_ARG_BOOLFLAG)
-                    {
-                        if (arg_iter->default_complex != NULL
-                            && extcap_complex_get_bool(arg_iter->default_complex))
-                        {
-                            add_arg(arg_iter->call);
+                    if ( arg_iter->storeval != NULL )
+                        stored = arg_iter->storeval;
+
+                    if ( arg_iter->default_complex != NULL && arg_iter->default_complex->_val != NULL )
+                        defval = arg_iter->default_complex->_val;
+
+                    /* Different data in storage then set for default */
+                    if ( g_strcmp0(stored, defval) != 0 ) {
+                        if ( arg_iter->arg_type == EXTCAP_ARG_BOOLFLAG ) {
+                            if ( g_strcmp0(stored, "true") == 0 )
+                                add_arg(arg_iter->call);
+                        } else {
+                            gchar * call = g_strconcat(arg_iter->call, " ", stored, NULL);
+                            add_arg(call);
+                            g_free(call);
                         }
+                    } else if  (arg_iter->arg_type == EXTCAP_ARG_BOOLFLAG) {
+                        if (extcap_complex_get_bool(arg_iter->default_complex))
+                            add_arg(arg_iter->call);
                     }
 
                     arg_list = arg_list->next;
@@ -694,7 +790,7 @@ extcap_init_interfaces(capture_options *capture_opts)
         }
         else
         {
-            g_hash_table_foreach(interface_opts.extcap_args, extcap_arg_cb, args);
+            g_hash_table_foreach_remove(interface_opts.extcap_args, extcap_add_arg_and_remove_cb, args);
         }
         add_arg(NULL);
 #undef add_arg
index 02c230014f6d29313956e2b85ade7e86974b060c..b2b6b5fa4346b153227668d4271c3dd69f539fd7 100644 (file)
--- a/extcap.h
+++ b/extcap.h
@@ -63,6 +63,10 @@ typedef struct _extcap_info {
 extern "C" {
 #endif /* __cplusplus */
 
+/* Registers preferences for all interfaces */
+void
+extcap_register_preferences(void);
+
 /* try to get if capabilities from extcap */
 if_capabilities_t *
 extcap_get_if_dlts(const gchar * ifname, char ** err_str);
index 37c0e70728a3783a7ced1217506e22adb5695066..652d7dde14138cba9e44230264a0d5266b7936be 100644 (file)
@@ -353,6 +353,7 @@ void extcap_free_arg(extcap_arg *a) {
     g_free(a->tooltip);
     g_free(a->fileextension);
     g_free(a->regexp);
+    g_free(a->storeval);
 
     if (a->range_start != NULL)
         extcap_free_complex(a->range_start);
@@ -404,6 +405,7 @@ extcap_arg *extcap_parse_arg_sentence(GList * args, extcap_token_sentence *s) {
     if (sent == EXTCAP_SENTENCE_ARG) {
         target_arg = g_new0(extcap_arg, 1);
         target_arg->arg_type = EXTCAP_ARG_UNKNOWN;
+        target_arg->save = TRUE;
 
         if ((v = extcap_find_param_by_type(s->param_list, EXTCAP_PARAM_ARGNUM))
                 == NULL) {
@@ -489,7 +491,7 @@ extcap_arg *extcap_parse_arg_sentence(GList * args, extcap_token_sentence *s) {
         } else if (g_ascii_strcasecmp(v->value, "password") == 0) {
             target_arg->arg_type = EXTCAP_ARG_PASSWORD;
             /* default setting is to not save passwords */
-            target_arg->do_not_save = TRUE;
+            target_arg->save = FALSE;
         } else if (g_ascii_strcasecmp(v->value, "fileselect") == 0) {
             target_arg->arg_type = EXTCAP_ARG_FILESELECT;
         } else if (g_ascii_strcasecmp(v->value, "multicheck") == 0) {
@@ -502,7 +504,7 @@ extcap_arg *extcap_parse_arg_sentence(GList * args, extcap_token_sentence *s) {
 
         if ((v = extcap_find_param_by_type(s->param_list, EXTCAP_PARAM_SAVE))
                 != NULL) {
-            target_arg->do_not_save = ! g_regex_match_simple(EXTCAP_BOOLEAN_REGEX, v->value, G_REGEX_CASELESS, (GRegexMatchFlags)0 );
+            target_arg->save = g_regex_match_simple(EXTCAP_BOOLEAN_REGEX, v->value, G_REGEX_CASELESS, (GRegexMatchFlags)0 );
         }
 
         if ((v = extcap_find_param_by_type(s->param_list, EXTCAP_PARAM_RANGE))
index d1074c8a9bf404c6c88edf6706df8714fd3ab5a0..e43e1ac6dbf58cf9beedcdad0c0bc85808bf98ac 100644 (file)
@@ -107,7 +107,7 @@ typedef struct _extcap_arg {
     gboolean fileexists;
 
     gboolean is_required;
-    gboolean do_not_save;
+    gboolean save;
 
     gchar * regexp;
 
@@ -117,6 +117,8 @@ typedef struct _extcap_arg {
     extcap_complex *range_end;
     extcap_complex *default_complex;
 
+    gchar * storeval;
+
     GList * values;
 } extcap_arg;
 
index fef29535bd03f82998019b482068767dbc8f0b4d..b5294bafa48bd38812890531b6622e23b3fae20e 100644 (file)
 #include <zlib.h>      /* to get the libz version number */
 #endif
 
+#ifdef HAVE_EXTCAP
+#include <extcap.h>
+#endif
+
 #ifdef HAVE_LIBPORTAUDIO
 #include <portaudio.h>
 #endif /* HAVE_LIBPORTAUDIO */
@@ -2591,6 +2595,10 @@ main(int argc, char *argv[])
     register_all_plugin_tap_listeners();
 #endif
 
+#ifdef HAVE_EXTCAP
+    extcap_register_preferences();
+#endif
+
     register_all_tap_listeners();
     conversation_table_set_gui_info(init_conversation_table);
     hostlist_table_set_gui_info(init_hostlist_table);
index 0c06107f3eadc52362369fc0358b7ce4c61a3548..3200a7e1d62c37eddff128c8540675364539ede1 100644 (file)
 #include <QStandardItem>
 #include <QStandardItemModel>
 #include <QItemSelectionModel>
+#include <QRegExp>
 
 #include <glib.h>
 #include <log.h>
+
+#include <extcap.h>
 #include <epan/prefs.h>
 #include <color_utils.h>
 
@@ -57,6 +60,7 @@ QWidget * ExtArgSelector::createEditor(QWidget * parent)
 {
     int counter = 0;
     int selected = -1;
+    QString stored = _argument->storeval ? QString(_argument->storeval) : QString();
 
     boxSelection = new QComboBox(parent);
 
@@ -67,7 +71,10 @@ QWidget * ExtArgSelector::createEditor(QWidget * parent)
         while ( iter != values.constEnd() )
         {
             boxSelection->addItem((*iter).value(), (*iter).call());
-            if ( (*iter).isDefault() )
+
+            if ( ! _argument->storeval && (*iter).isDefault() )
+                selected = counter;
+            else if ( _argument->storeval && stored.compare((*iter).call()) == 0 )
                 selected = counter;
 
             counter++;
@@ -135,7 +142,7 @@ QWidget * ExtArgRadio::createEditor(QWidget * parent)
         ExtcapValueList::const_iterator iter = values.constBegin();
 
         while ( iter != values.constEnd() )
-       {
+        {
             QRadioButton * radio = new QRadioButton((*iter).value());
             QString callString = (*iter).call();
             callStrings->append(callString);
@@ -219,6 +226,15 @@ QWidget * ExtArgBool::createEditor(QWidget * parent)
     if ( _argument->tooltip != NULL )
         boolBox->setToolTip(QString().fromUtf8(_argument->tooltip));
 
+    if ( _argument->storeval )
+    {
+        QRegExp regexp(EXTCAP_BOOLEAN_REGEX);
+
+        bool savedstate = ( regexp.indexIn(QString(_argument->storeval[0]), 0) != -1 );
+        if ( savedstate != state )
+            state = savedstate;
+    }
+
     boolBox->setCheckState(state ? Qt::Checked : Qt::Unchecked );
 
     connect (boolBox, SIGNAL(stateChanged(int)), SLOT(onIntChanged(int)));
@@ -244,6 +260,13 @@ QString ExtArgBool::value()
     return QString(boolBox->checkState() == Qt::Checked ? "true" : "false");
 }
 
+QString ExtArgBool::prefValue()
+{
+    if ( boolBox == NULL )
+        return QString("false");
+    return QString(boolBox->checkState() == Qt::Checked ? "true" : "false");
+}
+
 bool ExtArgBool::isValid()
 {
     /* A bool is allways valid, but the base function checks on string length,
@@ -279,8 +302,17 @@ ExtArgText::ExtArgText(extcap_arg * argument) :
 
 QWidget * ExtArgText::createEditor(QWidget * parent)
 {
+    QString storeValue;
     QString text = defaultValue();
 
+    if ( _argument->storeval )
+    {
+        QString storeValue = _argument->storeval;
+
+        if ( storeValue.length() > 0 && storeValue.compare(text) != 0 )
+            text = storeValue.trimmed();
+    }
+
     textBox = new QLineEdit(text, parent);
 
     if ( _argument->tooltip != NULL )
@@ -334,7 +366,17 @@ ExtArgNumber::ExtArgNumber(extcap_arg * argument) :
 
 QWidget * ExtArgNumber::createEditor(QWidget * parent)
 {
+    QString storeValue;
     QString text = defaultValue();
+
+    if ( _argument->storeval )
+    {
+        QString storeValue = _argument->storeval;
+
+        if ( storeValue.length() > 0 && storeValue.compare(text) != 0 )
+            text = storeValue;
+    }
+
     textBox = (QLineEdit *)ExtArgText::createEditor(parent);
     textBox->disconnect(SIGNAL(textChanged(QString)));
 
@@ -525,6 +567,10 @@ QString ExtcapArgument::value()
     return QString();
 }
 
+QString ExtcapArgument::prefValue()
+{
+    return value();
+}
 
 bool ExtcapArgument::isValid()
 {
@@ -544,10 +590,17 @@ QString ExtcapArgument::defaultValue()
         if ( str != 0 )
             return QString(str);
     }
-
     return QString();
 }
 
+QString ExtcapArgument::prefKey()
+{
+    if ( ! _argument->save )
+        return QString();
+
+    return QString(_argument->call).replace("-", "");
+}
+
 bool ExtcapArgument::isRequired()
 {
     if ( _argument != NULL )
index c83111a2d3babe2b24afa5ec2749efa5f6b96fd6..2d605d28811ea4666ac195e0f4afc69fac3e00eb 100644 (file)
@@ -98,6 +98,9 @@ public:
     bool isValid();
     bool isRequired();
 
+    QString prefKey();
+    virtual QString prefValue();
+
     static ExtcapArgument * create(extcap_arg * argument = 0);
 
 Q_SIGNALS:
@@ -189,6 +192,7 @@ public:
     virtual QString value();
     virtual bool isValid();
     virtual QString defaultValue();
+    virtual QString prefValue();
 
 private:
 
index f36d4afbd81a30f27860fbbced0d00fba67dd174..ed7a0150e4edf3cdb492750c78430aa6a2416584 100644 (file)
 
 #include "qt_ui_utils.h"
 
+#include <epan/prefs.h>
+#include <ui/preference_utils.h>
+
+#include <ui/qt/wireshark_application.h>
+
 #include <ui/qt/extcap_argument.h>
 #include <ui/qt/extcap_argument_file.h>
 #include <ui/qt/extcap_argument_multiselect.h>
@@ -68,6 +73,7 @@ ExtcapOptionsDialog::ExtcapOptionsDialog(QWidget *parent) :
 
     setWindowTitle(wsApp->windowTitleString(tr("Extcap Interface Options")));
 
+    ui->checkSaveOnStart->setCheckState(prefs.extcap_save_on_start ? Qt::Checked : Qt::Unchecked);
 
     ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Start"));
 }
@@ -118,6 +124,12 @@ ExtcapOptionsDialog::~ExtcapOptionsDialog()
 void ExtcapOptionsDialog::on_buttonBox_accepted()
 {
     if (saveOptionToCaptureInfo()) {
+        /* Starting a new capture with those values */
+        prefs.extcap_save_on_start = ui->checkSaveOnStart->checkState() == Qt::Checked;
+
+        if ( prefs.extcap_save_on_start )
+            storeValues();
+
         accept();
     }
 }
@@ -281,7 +293,7 @@ bool ExtcapOptionsDialog::saveOptionToCaptureInfo()
     device = g_array_index(global_capture_opts.all_ifaces, interface_t, device_idx);
     global_capture_opts.all_ifaces = g_array_remove_index(global_capture_opts.all_ifaces, device_idx);
 
-    ret_args = g_hash_table_new(g_str_hash, g_str_equal);
+    ret_args = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
 
     ExtcapArgumentList::const_iterator iter;
 
@@ -301,6 +313,7 @@ bool ExtcapOptionsDialog::saveOptionToCaptureInfo()
 
         gchar * call_string = g_strdup(call.toStdString().c_str());
         gchar * value_string = g_strdup(value.toStdString().c_str());
+
         g_hash_table_insert(ret_args, call_string, value_string );
     }
 
@@ -313,6 +326,77 @@ bool ExtcapOptionsDialog::saveOptionToCaptureInfo()
     return true;
 }
 
+void ExtcapOptionsDialog::storeValues()
+{
+    GHashTable * entries = g_hash_table_new(g_str_hash, g_str_equal);
+    ExtcapArgumentList::const_iterator iter;
+
+    QString value;
+
+    /* All arguments are being iterated, to ensure, that any error handling catches all arguments */
+    for(iter = extcapArguments.constBegin(); iter != extcapArguments.constEnd(); ++iter)
+    {
+        ExtcapArgument * argument = (ExtcapArgument *)(*iter);
+
+        /* The dynamic casts are necessary, because we come here using the Signal/Slot system
+         * of Qt, and -in short- Q_OBJECT classes cannot be multiple inherited. Another possibility
+         * would be to use Q_INTERFACE, but this causes way more nightmares, and we really just
+         * need here an explicit cast for the check functionality */
+        if ( dynamic_cast<ExtArgBool *>((*iter)) != NULL)
+        {
+            value = ((ExtArgBool *)*iter)->prefValue();
+        }
+        else if ( dynamic_cast<ExtArgRadio *>((*iter)) != NULL)
+        {
+            value = ((ExtArgRadio *)*iter)->prefValue();
+        }
+        else if ( dynamic_cast<ExtArgSelector *>((*iter)) != NULL)
+        {
+            value = ((ExtArgSelector *)*iter)->prefValue();
+        }
+        else if ( dynamic_cast<ExtArgMultiSelect *>((*iter)) != NULL)
+        {
+            value = ((ExtArgMultiSelect *)*iter)->prefValue();
+        }
+        else if ( dynamic_cast<ExtcapArgumentFileSelection *>((*iter)) != NULL)
+        {
+            value = ((ExtcapArgumentFileSelection *)*iter)->prefValue();
+        }
+        else if ( dynamic_cast<ExtArgNumber *>((*iter)) != NULL)
+        {
+            value = ((ExtArgNumber *)*iter)->prefValue();
+        }
+        else if ( dynamic_cast<ExtArgText *>((*iter)) != NULL)
+        {
+            value = ((ExtArgText *)*iter)->prefValue();
+        }
+        else
+            value = (*iter)->prefValue();
+
+        QString prefKey = QString("%1.%2").arg(device_name).arg(argument->prefKey());
+        if ( prefKey.length() > 0 )
+        {
+            gchar * key = g_strdup(prefKey.toStdString().c_str());
+            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);
+
+            g_hash_table_insert(entries, key, val);
+        }
+    }
+
+    if ( g_hash_table_size(entries) > 0 )
+    {
+        if ( prefs_store_ext_multiple("extcap", entries) )
+        {
+            wsApp->emitAppSignal(WiresharkApplication::PacketDissectionChanged);
+            wsApp->emitAppSignal(WiresharkApplication::PreferencesChanged);
+        }
+    }
+}
+
+
 #endif /* HAVE_LIBPCAP */
 
 /*
index eb0761df8ee919701da77ae1c51a2760c32964c9..3ca859ed35fd0b343e8cba7ae0e2303f44dcd009 100644 (file)
@@ -70,6 +70,7 @@ private:
     ExtcapArgumentList extcapArguments;
 
     bool saveOptionToCaptureInfo();
+    void storeValues();
 };
 
 #endif /* HAVE_EXTCAP */
index d22380aee3399c70119f37ccb7b8e0a64f317830..edd6c96c8cd932b46eed61e116cdb637208dd8ca 100644 (file)
@@ -7,7 +7,7 @@
     <x>0</x>
     <y>0</y>
     <width>600</width>
-    <height>55</height>
+    <height>92</height>
    </rect>
   </property>
   <property name="minimumSize">
    <item>
     <layout class="QVBoxLayout" name="verticalLayout"/>
    </item>
+   <item>
+    <widget class="Line" name="line">
+     <property name="orientation">
+      <enum>Qt::Horizontal</enum>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QCheckBox" name="checkSaveOnStart">
+     <property name="text">
+      <string>Save parameter on capture start</string>
+     </property>
+     <property name="checked">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
    <item>
     <widget class="QDialogButtonBox" name="buttonBox">
      <property name="standardButtons">
index bd9277f0f722b264b0c4b7e33974f02fbc51af4e..1eaff2c89a1272b01b0373adf520ec29f770119d 100644 (file)
 #include <codecs/codecs.h>
 #endif
 
+#ifdef HAVE_EXTCAP
+#include <extcap.h>
+#endif
+
 /* general (not Qt specific) */
 #include "file.h"
 #include "epan/color_filters.h"
@@ -839,6 +843,10 @@ int main(int argc, char *argv[])
     register_all_plugin_tap_listeners();
 #endif
 
+#ifdef HAVE_EXTCAP
+    extcap_register_preferences();
+#endif
+
     register_all_tap_listeners();
     conversation_table_set_gui_info(init_conversation_table);
     hostlist_table_set_gui_info(init_endpoint_table);