aboutsummaryrefslogtreecommitdiffstats
path: root/ui/qt/export_object_dialog.cpp
diff options
context:
space:
mode:
authorGerald Combs <gerald@wireshark.org>2012-10-18 21:14:43 +0000
committerGerald Combs <gerald@wireshark.org>2012-10-18 21:14:43 +0000
commit576b24c96ee4ac4ca7fb9fc116b6e8ce3704227d (patch)
treef8e0abf64215eb0083a475acfdcea3806e4c0ba5 /ui/qt/export_object_dialog.cpp
parent05c1e47f68b609702ec13a09e5ebc1a572841e12 (diff)
Move ui-independent object export routines to the common ui directory.
Implement DICOM, HTTP, and SMB object exports. Rename the GTK+ export files. C++-ize epan/tap.h. Fix an apparent memory leak in eo_save_all_clicked_cb. The Qt dialog has an indeterminate progress bar. I tried adding something similar to the GTK+ dialog but event processing led down a rabbit hole. svn path=/trunk/; revision=45647
Diffstat (limited to 'ui/qt/export_object_dialog.cpp')
-rw-r--r--ui/qt/export_object_dialog.cpp316
1 files changed, 316 insertions, 0 deletions
diff --git a/ui/qt/export_object_dialog.cpp b/ui/qt/export_object_dialog.cpp
new file mode 100644
index 0000000000..49546de70f
--- /dev/null
+++ b/ui/qt/export_object_dialog.cpp
@@ -0,0 +1,316 @@
+/* export_object_dialog.cpp
+ *
+ * $Id: main_window.h 45589 2012-10-16 18:14:16Z gerald $
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * 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 "export_object_dialog.h"
+#include "ui_export_object_dialog.h"
+#include "wireshark_application.h"
+
+#include <QDialogButtonBox>
+#include <QPushButton>
+#include <QMessageBox>
+#include <QFileDialog>
+
+#include <ui/alert_box.h>
+
+#include <epan/filesystem.h>
+
+#include <wsutil/str_util.h>
+
+extern "C" {
+
+// object_list_add_entry and object_list_get_entry are defined in ui/export_object.h
+
+void object_list_add_entry(export_object_list_t *object_list, export_object_entry_t *entry) {
+ if (object_list && object_list->eod) object_list->eod->addObjectEntry(entry);
+}
+
+export_object_entry_t *object_list_get_entry(export_object_list_t *object_list, int row) {
+ if (object_list && object_list->eod) return object_list->eod->objectEntry(row);
+ return NULL;
+}
+
+// Called by taps
+
+/* Runs at the beginning of tapping only */
+static void
+eo_reset(void *tapdata)
+{
+ export_object_list_t *object_list = (export_object_list_t *) tapdata;
+ if (object_list) object_list->eod->resetObjects();
+}
+
+} // extern "C"
+
+ExportObjectDialog::ExportObjectDialog(QWidget *parent, capture_file *cf, ObjectType object_type) :
+ QDialog(parent),
+ eo_ui_(new Ui::ExportObjectDialog),
+ cap_file_(cf),
+ save_bt_(NULL),
+ save_all_bt_(NULL),
+ tap_name_(NULL),
+ name_(NULL),
+ tap_packet_(NULL),
+ eo_protocoldata_resetfn_(NULL)
+{
+ QPushButton *close_bt;
+
+ eo_ui_->setupUi(this);
+ setAttribute(Qt::WA_DeleteOnClose, true);
+
+#if defined(Q_WS_MAC)
+ eo_ui_->progressLabel->setAttribute(Qt::WA_MacSmallSize, true);
+ eo_ui_->progressBar->setAttribute(Qt::WA_MacSmallSize, true);
+#endif
+
+ export_object_list_.eod = this;
+
+ switch (object_type) {
+ case Dicom:
+ tap_name_ = "dicom_eo";
+ name_ = "DICOM";
+ tap_packet_ = eo_dicom_packet;
+ break;
+ case Http:
+ tap_name_ = "http_eo";
+ name_ = "HTTP";
+ tap_packet_ = eo_http_packet;
+ break;
+ case Smb:
+ tap_name_ = "smb_eo";
+ name_ = "SMB";
+ tap_packet_ = eo_smb_packet;
+ eo_protocoldata_resetfn_ = eo_smb_cleanup;
+ break;
+ }
+
+ save_bt_ = eo_ui_->buttonBox->button(QDialogButtonBox::Save);
+ save_all_bt_ = eo_ui_->buttonBox->button(QDialogButtonBox::SaveAll);
+ close_bt = eo_ui_->buttonBox->button(QDialogButtonBox::Close);
+
+ if (save_bt_) save_bt_->setEnabled(false);
+ if (save_all_bt_) save_all_bt_->setEnabled(false);
+ if (close_bt) close_bt->setDefault(true);
+
+ connect(wsApp, SIGNAL(captureFileClosing(const capture_file*)),
+ this, SLOT(captureFileClosing(const capture_file*)));
+}
+
+ExportObjectDialog::~ExportObjectDialog()
+{
+ delete eo_ui_;
+}
+
+void ExportObjectDialog::show()
+{
+ GString *error_msg;
+
+ if (!cap_file_) destroy(); // Assert?
+
+ /* Data will be gathered via a tap callback */
+ error_msg = register_tap_listener(tap_name_, (void *)&export_object_list_, NULL, 0,
+ eo_reset,
+ tap_packet_,
+ NULL);
+
+ if (error_msg) {
+ QMessageBox::warning(
+ this,
+ tr("Tap registration error"),
+ QString("Unable to register ") + name_ + QString(" tap: ") + error_msg->str,
+ QMessageBox::Ok
+ );
+ g_string_free(error_msg, TRUE);
+ return;
+ }
+
+ QDialog::show();
+ cf_retap_packets(cap_file_);
+ eo_ui_->progressFrame->hide();
+ for (int i = 0; i < eo_ui_->objectTree->columnCount(); i++)
+ eo_ui_->objectTree->resizeColumnToContents(i);
+
+}
+
+void ExportObjectDialog::addObjectEntry(export_object_entry_t *entry)
+{
+ QTreeWidgetItem *entry_item;
+ gchar *size_str;
+
+ if (!entry) return;
+
+ size_str = format_size(entry->payload_len, format_size_unit_bytes|format_size_prefix_si);
+
+ entry_item = new QTreeWidgetItem(eo_ui_->objectTree);
+ entry_item->setData(0, Qt::UserRole, qVariantFromValue(entry));
+
+ entry_item->setText(0, QString().setNum(entry->pkt_num));
+ entry_item->setText(1, entry->hostname);
+ entry_item->setText(2, entry->content_type);
+ entry_item->setText(3, size_str);
+ entry_item->setText(2, entry->filename);
+ g_free(size_str);
+ // Not perfect but better than nothing.
+ entry_item->setTextAlignment(3, Qt::AlignRight);
+
+ if (save_all_bt_) save_all_bt_->setEnabled(true);
+}
+
+export_object_entry_t *ExportObjectDialog::objectEntry(int row)
+{
+ QTreeWidgetItem *item = eo_ui_->objectTree->topLevelItem(row);
+
+ if (item) return item->data(0, Qt::UserRole).value<export_object_entry_t *>();
+
+ return NULL;
+}
+
+void ExportObjectDialog::resetObjects()
+{
+ if (eo_protocoldata_resetfn_) eo_protocoldata_resetfn_();
+ if (save_bt_) save_bt_->setEnabled(false);
+ if (save_all_bt_) save_all_bt_->setEnabled(false);
+}
+
+void ExportObjectDialog::accept()
+{
+ // Don't close the dialog.
+}
+
+void ExportObjectDialog::captureFileClosing(const capture_file *cf)
+{
+ if (cap_file_ && cf == cap_file_) {
+ close();
+ }
+}
+
+void ExportObjectDialog::on_buttonBox_helpRequested()
+{
+ wsApp->helpTopicAction(HELP_EXPORT_OBJECT_LIST);
+}
+
+void ExportObjectDialog::on_objectTree_currentItemChanged(QTreeWidgetItem *item, QTreeWidgetItem *previous)
+{
+ Q_UNUSED(previous);
+
+ if (!item) {
+ if (save_bt_) save_bt_->setEnabled(false);
+ return;
+ }
+
+ if (save_bt_) save_bt_->setEnabled(true);
+
+ export_object_entry_t *entry = item->data(0, Qt::UserRole).value<export_object_entry_t *>();
+ if (entry && cap_file_) {
+ cf_goto_frame(cap_file_, entry->pkt_num);
+ }
+}
+
+void ExportObjectDialog::on_buttonBox_clicked(QAbstractButton *button)
+{
+ switch (eo_ui_->buttonBox->standardButton(button)) {
+ case QDialogButtonBox::Save:
+ saveCurrentEntry();
+ break;
+ case QDialogButtonBox::SaveAll:
+ saveAllEntries();
+ break;
+ default: // Help, Cancel
+ break;
+ }
+}
+
+void ExportObjectDialog::saveCurrentEntry()
+{
+ QTreeWidgetItem *item = eo_ui_->objectTree->currentItem();
+ export_object_entry_t *entry;
+ QDir path(wsApp->lastOpenDir());
+ QString file_name;
+
+ if (!item) return;
+
+ entry = item->data(0, Qt::UserRole).value<export_object_entry_t *>();
+ if (!entry) return;
+
+ file_name = QFileDialog::getSaveFileName(this, tr("Wireshark: Save Object As..."),
+ path.filePath(entry->filename));
+
+ if (file_name.length() > 0) {
+ eo_save_entry(file_name.toUtf8().constData(), entry, TRUE);
+ }
+}
+
+#define MAXFILELEN 255
+void ExportObjectDialog::saveAllEntries()
+{
+ int i;
+ QTreeWidgetItem *item;
+ QDir path(wsApp->lastOpenDir());
+ QString file_path;
+ bool all_saved = true;
+
+ file_path = QFileDialog::getSaveFileName(this, tr("Wireshark: Save All Objects In..."),
+ path.canonicalPath(), QString(), NULL,
+ QFileDialog::ShowDirsOnly);
+
+ if (file_path.length() < 1 || file_path.length() > MAXFILELEN) return;
+
+ for (i = 0, item = eo_ui_->objectTree->topLevelItem(i); item != NULL; i++) {
+ int count = 0;
+ QString file_name;
+ export_object_entry_t *entry = item->data(0, Qt::UserRole).value<export_object_entry_t *>();
+
+ if (!entry) continue;
+
+ do {
+ GString *safe_filename;
+
+ path.setCurrent(file_path);
+ if (entry->filename)
+ safe_filename = eo_massage_str(entry->filename,
+ MAXFILELEN - file_path.length(), count);
+ else {
+ char generic_name[256];
+ const char *ext;
+ ext = ct2ext(entry->content_type);
+ g_snprintf(generic_name, sizeof(generic_name),
+ "object%u%s%s", entry->pkt_num, ext ? "." : "",
+ ext ? ext : "");
+ safe_filename = eo_massage_str(generic_name,
+ MAXFILELEN - file_path.length(), count);
+ }
+ file_name = path.filePath(safe_filename->str);
+ g_string_free(safe_filename, TRUE);
+ } while (g_file_test(file_path.toUtf8().constData(), G_FILE_TEST_EXISTS) && ++count < 1000);
+ count = 0;
+ if (!eo_save_entry(file_path.toUtf8().constData(), entry, FALSE))
+ all_saved = false;
+ }
+ if (!all_saved) {
+ QMessageBox::warning(
+ this,
+ tr("Object Export"),
+ tr("Some files could not be saved."),
+ QMessageBox::Ok
+ );
+ }
+}