/* extcap_options_dialog.cpp * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include #include #include #include #include #ifdef HAVE_EXTCAP #include #include #include #include #include #include "ringbuffer.h" #include "ui/capture_ui_utils.h" #include "ui/capture_globals.h" #include "ui/iface_lists.h" #include "ui/last_open_dir.h" #include "ui/ui_util.h" #include "ui/util.h" #include #include #include #include #include #include #include "qt_ui_utils.h" #include #include #include #include #include #include ExtcapOptionsDialog::ExtcapOptionsDialog(QWidget *parent) : QDialog(parent), ui(new Ui::ExtcapOptionsDialog), device_name(""), device_idx(0) { ui->setupUi(this); 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")); } ExtcapOptionsDialog * ExtcapOptionsDialog::createForDevice(QString &dev_name, QWidget *parent) { interface_t device; ExtcapOptionsDialog * resultDialog = NULL; bool dev_found = false; guint if_idx; if ( dev_name.length() == 0 ) return NULL; for (if_idx = 0; if_idx < global_capture_opts.all_ifaces->len; if_idx++) { device = g_array_index(global_capture_opts.all_ifaces, interface_t, if_idx); if (dev_name.compare(QString(device.name)) == 0 && device.if_info.type == IF_EXTCAP) { dev_found = true; break; } } if ( ! dev_found ) return NULL; resultDialog = new ExtcapOptionsDialog(parent); resultDialog->device_name = QString(dev_name); resultDialog->device_idx = if_idx; resultDialog->setWindowTitle(wsApp->windowTitleString(tr("Extcap Interface Options") + ": " + device.display_name)); resultDialog->updateWidgets(); /* mark required fields */ resultDialog->anyValueChanged(); return resultDialog; } ExtcapOptionsDialog::~ExtcapOptionsDialog() { delete ui; } 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(); } } void ExtcapOptionsDialog::anyValueChanged() { bool allowStart = true; ExtcapArgumentList::const_iterator iter; /* All arguments are being iterated, to ensure, that any error handling catches all arguments */ for(iter = extcapArguments.constBegin(); iter != extcapArguments.constEnd(); ++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((*iter)) != NULL) { if ( ! ((ExtArgBool *)*iter)->isValid() ) allowStart = false; } else if ( dynamic_cast((*iter)) != NULL) { if ( ! ((ExtArgRadio *)*iter)->isValid() ) allowStart = false; } else if ( dynamic_cast((*iter)) != NULL) { if ( ! ((ExtArgSelector *)*iter)->isValid() ) allowStart = false; } else if ( dynamic_cast((*iter)) != NULL) { if ( ! ((ExtArgMultiSelect *)*iter)->isValid() ) allowStart = false; } else if ( dynamic_cast((*iter)) != NULL) { if ( ! ((ExtcapArgumentFileSelection *)*iter)->isValid() ) allowStart = false; } else if ( dynamic_cast((*iter)) != NULL) { if ( ! ((ExtArgNumber *)*iter)->isValid() ) allowStart = false; } else if ( dynamic_cast((*iter)) != NULL) { if ( ! ((ExtArgText *)*iter)->isValid() ) allowStart = false; } else if ( ! (*iter)->isValid() ) allowStart = false; } ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(allowStart); } void ExtcapOptionsDialog::updateWidgets() { GList * arguments = NULL, * walker = NULL, * item = NULL; QWidget * lblWidget = NULL, *editWidget = 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); QGridLayout * layout = new QGridLayout(); ExtcapArgumentList required; ExtcapArgumentList optional; while ( walker != NULL ) { item = g_list_first((GList *)(walker->data)); while ( item != NULL ) { argument = ExtcapArgument::create((extcap_arg *)(item->data)); if ( argument != NULL ) { if ( argument->isRequired() ) required << argument; else optional << argument; } item = item->next; } walker = walker->next; } if ( required.length() > 0 ) extcapArguments << required; if ( optional.length() > 0 ) extcapArguments << optional; ExtcapArgumentList::iterator iter = extcapArguments.begin(); while ( iter != extcapArguments.end() ) { lblWidget = (*iter)->createLabel((QWidget *)this); if ( lblWidget != NULL ) { layout->addWidget(lblWidget, counter, 0, Qt::AlignVCenter); editWidget = (*iter)->createEditor((QWidget *) this); if ( editWidget != NULL ) { layout->addWidget(editWidget, counter, 1, Qt::AlignVCenter); } if ( (*iter)->isRequired() && ! (*iter)->isValid() ) allowStart = false; connect((*iter), SIGNAL(valueChanged()), this, SLOT(anyValueChanged())); counter++; } ++iter; } if ( counter > 0 ) { setStyleSheet ( "QLabel[isRequired=\"true\"] { font-weight: bold; } "); ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(allowStart); ui->verticalLayout->addLayout(layout); ui->verticalLayout->addSpacerItem(new QSpacerItem(20, 100, QSizePolicy::Minimum, QSizePolicy::Expanding)); } else { delete layout; } } // Not sure why we have to do this manually. void ExtcapOptionsDialog::on_buttonBox_rejected() { reject(); } void ExtcapOptionsDialog::on_buttonBox_helpRequested() { // Probably the wrong URL. wsApp->helpTopicAction(HELP_EXTCAP_OPTIONS_DIALOG); } bool ExtcapOptionsDialog::saveOptionToCaptureInfo() { GHashTable * ret_args; interface_t device; 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_full(g_str_hash, g_str_equal, g_free, g_free); ExtcapArgumentList::const_iterator iter; for(iter = extcapArguments.constBegin(); iter != extcapArguments.constEnd(); ++iter) { QString call = (*iter)->call(); QString value = (*iter)->value(); if ((*iter)->argument()->arg_type != EXTCAP_ARG_BOOLFLAG && value.length() == 0) continue; if ( call.length() <= 0 ) continue; if ( value.compare((*iter)->defaultValue()) == 0 ) continue; 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 ); } if (device.external_cap_args_settings != NULL) g_hash_table_unref(device.external_cap_args_settings); device.external_cap_args_settings = ret_args; g_array_insert_val(global_capture_opts.all_ifaces, device_idx, device); 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((*iter)) != NULL) { value = ((ExtArgBool *)*iter)->prefValue(); } else if ( dynamic_cast((*iter)) != NULL) { value = ((ExtArgRadio *)*iter)->prefValue(); } else if ( dynamic_cast((*iter)) != NULL) { value = ((ExtArgSelector *)*iter)->prefValue(); } else if ( dynamic_cast((*iter)) != NULL) { value = ((ExtArgMultiSelect *)*iter)->prefValue(); } else if ( dynamic_cast((*iter)) != NULL) { value = ((ExtcapArgumentFileSelection *)*iter)->prefValue(); } else if ( dynamic_cast((*iter)) != NULL) { value = ((ExtArgNumber *)*iter)->prefValue(); } else if ( dynamic_cast((*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 */ /* * Editor modelines * * 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: */