summaryrefslogtreecommitdiffstats
path: root/ui/qt/export_object_dialog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ui/qt/export_object_dialog.cpp')
-rw-r--r--ui/qt/export_object_dialog.cpp303
1 files changed, 303 insertions, 0 deletions
diff --git a/ui/qt/export_object_dialog.cpp b/ui/qt/export_object_dialog.cpp
new file mode 100644
index 00000000..79ad427e
--- /dev/null
+++ b/ui/qt/export_object_dialog.cpp
@@ -0,0 +1,303 @@
+/* export_object_dialog.cpp
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "export_object_dialog.h"
+#include <ui_export_object_dialog.h>
+
+#include <ui/alert_box.h>
+#include <wsutil/utf8_entities.h>
+
+#include "main_application.h"
+#include "ui/qt/widgets/wireshark_file_dialog.h"
+#include <ui/qt/widgets/export_objects_view.h>
+#include <ui/qt/models/export_objects_model.h>
+#include <ui/qt/utils/qt_ui_utils.h>
+
+#include <QDialogButtonBox>
+#include <QMessageBox>
+#include <QMimeDatabase>
+#include <QPushButton>
+#include <QComboBox>
+#include <QDir>
+#include <QFile>
+#include <QFileInfo>
+#include <QDesktopServices>
+
+ExportObjectDialog::ExportObjectDialog(QWidget &parent, CaptureFile &cf, register_eo_t* eo) :
+ WiresharkDialog(parent, cf),
+ eo_ui_(new Ui::ExportObjectDialog),
+ save_bt_(NULL),
+ save_all_bt_(NULL),
+ model_(eo, this),
+ proxyModel_(this)
+{
+ QPushButton *close_bt;
+
+ eo_ui_->setupUi(this);
+ setAttribute(Qt::WA_DeleteOnClose, true);
+
+ proxyModel_.setSourceModel(&model_);
+ eo_ui_->objectTree->setModel(&proxyModel_);
+
+ proxyModel_.setFilterFixedString("");
+ proxyModel_.setFilterCaseSensitivity(Qt::CaseInsensitive);
+ proxyModel_.setFilterKeyColumn(-1);
+
+#if defined(Q_OS_MAC)
+ eo_ui_->progressLabel->setAttribute(Qt::WA_MacSmallSize, true);
+ eo_ui_->progressBar->setAttribute(Qt::WA_MacSmallSize, true);
+#endif
+
+ connect(&model_, &ExportObjectModel::rowsInserted,
+ this, &ExportObjectDialog::modelDataChanged);
+ connect(&model_, &ExportObjectModel::modelReset, this, &ExportObjectDialog::modelRowsReset);
+ connect(eo_ui_->filterLine, &QLineEdit::textChanged, &proxyModel_, &ExportObjectProxyModel::setTextFilterString);
+ connect(eo_ui_->objectTree, &ExportObjectsTreeView::currentIndexChanged, this, &ExportObjectDialog::currentHasChanged);
+
+ 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 (eo_ui_->buttonBox->button(QDialogButtonBox::Open))
+ {
+ QPushButton * open = eo_ui_->buttonBox->button(QDialogButtonBox::Open);
+ open->setText(tr("Preview"));
+ open->setEnabled(false);
+ }
+
+ contentTypes << tr("All Content-Types");
+ eo_ui_->cmbContentType->addItems(contentTypes);
+
+ setWindowTitle(mainApp->windowTitleString(QStringList() << tr("Export") << tr("%1 object list").arg(proto_get_protocol_short_name(find_protocol_by_id(get_eo_proto_id(eo))))));
+
+ if (save_bt_) save_bt_->setEnabled(false);
+ if (save_all_bt_) save_all_bt_->setEnabled(false);
+ if (close_bt) close_bt->setDefault(true);
+
+ connect(&cap_file_, &CaptureFile::captureEvent,
+ this, &ExportObjectDialog::captureEvent);
+}
+
+ExportObjectDialog::~ExportObjectDialog()
+{
+ delete eo_ui_;
+ model_.removeTap();
+ removeTapListeners();
+}
+
+void ExportObjectDialog::currentHasChanged(QModelIndex current)
+{
+ if (current.isValid())
+ {
+ QModelIndex sibl = current.sibling(current.row(), ExportObjectModel::colPacket);
+ if (eo_ui_->buttonBox->button(QDialogButtonBox::Open))
+ {
+ QString mime_type = sibl.sibling(current.row(), ExportObjectModel::colContent).data().toString();
+ eo_ui_->buttonBox->button(QDialogButtonBox::Open)->setEnabled(mimeTypeIsPreviewable(mime_type));
+ }
+ mainApp->gotoFrame(sibl.data().toInt());
+ }
+}
+
+bool ExportObjectDialog::mimeTypeIsPreviewable(QString mime_type)
+{
+ // XXX This excludes everything except HTTP. Maybe that's a good thing?
+ // Take care when adding to this, e.g. text/html or image/svg might contain JavaScript.
+ QStringList previewable_mime_types = QStringList()
+ << "text/plain"
+ << "image/gif" << "image/jpeg" << "image/png";
+
+ if (previewable_mime_types.contains(mime_type)) {
+ return true;
+ }
+ return false;
+}
+
+void ExportObjectDialog::modelDataChanged(const QModelIndex&, int from, int to)
+{
+ bool contentTypes_changed = false;
+ bool enabled = (model_.rowCount() > 0);
+ if (save_bt_) save_bt_->setEnabled(enabled);
+ if (save_all_bt_) save_all_bt_->setEnabled(enabled);
+
+ for (int row = from; row <= to; row++)
+ {
+ QModelIndex idx = model_.index(row, ExportObjectModel::colContent);
+ if (idx.isValid())
+ {
+ QString dataType = idx.data().toString();
+ if (dataType.length() > 0 && ! contentTypes.contains(dataType))
+ {
+ contentTypes << dataType;
+ contentTypes_changed = true;
+ }
+ }
+ }
+ if (contentTypes_changed) {
+ contentTypes.sort(Qt::CaseInsensitive);
+ QString selType = eo_ui_->cmbContentType->currentText();
+ eo_ui_->cmbContentType->clear();
+ eo_ui_->cmbContentType->addItem(tr("All Content-Types"));
+ eo_ui_->cmbContentType->addItems(contentTypes);
+ if (contentTypes.contains(selType) )
+ eo_ui_->cmbContentType->setCurrentText(selType);
+ }
+}
+
+void ExportObjectDialog::modelRowsReset()
+{
+ contentTypes.clear();
+ eo_ui_->cmbContentType->clear();
+ eo_ui_->cmbContentType->addItem(tr("All Content-Types"));
+
+ if (save_bt_) save_bt_->setEnabled(false);
+ if (save_all_bt_) save_all_bt_->setEnabled(false);
+}
+
+void ExportObjectDialog::show()
+{
+ /* Data will be gathered via a tap callback */
+ if (!registerTapListener(model_.getTapListenerName(), model_.getTapData(), NULL, 0,
+ ExportObjectModel::resetTap,
+ model_.getTapPacketFunc(),
+ NULL)) {
+ return;
+ }
+
+ QDialog::show();
+ cap_file_.retapPackets();
+ eo_ui_->progressFrame->hide();
+ for (int i = 0; i < eo_ui_->objectTree->model()->columnCount(); i++)
+ eo_ui_->objectTree->resizeColumnToContents(i);
+
+ eo_ui_->objectTree->sortByColumn(ExportObjectModel::colPacket, Qt::AscendingOrder);
+}
+
+void ExportObjectDialog::keyPressEvent(QKeyEvent *evt)
+{
+ if(evt->key() == Qt::Key_Enter || evt->key() == Qt::Key_Return)
+ return;
+ QDialog::keyPressEvent(evt);
+}
+
+void ExportObjectDialog::accept()
+{
+ // Don't close the dialog.
+}
+
+void ExportObjectDialog::captureEvent(CaptureEvent e)
+{
+ if ((e.captureContext() == CaptureEvent::File) &&
+ (e.eventType() == CaptureEvent::Closing))
+ {
+ close();
+ }
+}
+
+void ExportObjectDialog::on_buttonBox_helpRequested()
+{
+ mainApp->helpTopicAction(HELP_EXPORT_OBJECT_LIST);
+}
+
+void ExportObjectDialog::on_buttonBox_clicked(QAbstractButton *button)
+{
+ switch (eo_ui_->buttonBox->standardButton(button)) {
+ case QDialogButtonBox::Save:
+ saveCurrentEntry();
+ break;
+ case QDialogButtonBox::SaveAll:
+ saveAllEntries();
+ break;
+ case QDialogButtonBox::Open:
+ {
+ QString temp;
+ saveCurrentEntry(&temp);
+
+ if (temp.length() > 0) {
+ QMimeDatabase mime_db;
+ QMimeType mime_type = mime_db.mimeTypeForFile(temp, QMimeDatabase::MatchContent);
+ if (mimeTypeIsPreviewable(mime_type.name())) {
+ QDesktopServices::openUrl(QUrl(QString("file:///").append(temp), QUrl::TolerantMode));
+ } else {
+ desktop_show_in_folder(temp);
+ }
+
+ }
+ break;
+ }
+ default: // Help, Cancel
+ break;
+ }
+}
+
+void ExportObjectDialog::on_cmbContentType_currentIndexChanged(int index)
+{
+ QString filterString = index <= 0 ? "" : eo_ui_->cmbContentType->currentText();
+ proxyModel_.setContentFilterString(filterString);
+
+}
+
+void ExportObjectDialog::saveCurrentEntry(QString *tempFile)
+{
+ QDir path(mainApp->openDialogInitialDir());
+
+ QModelIndex proxyIndex = eo_ui_->objectTree->currentIndex();
+ if (!proxyIndex.isValid())
+ return;
+
+ QModelIndex current = proxyModel_.mapToSource(proxyIndex);
+ if (!current.isValid())
+ return;
+
+ QString entry_filename = current.sibling(current.row(), ExportObjectModel::colFilename).data().toString();
+ if (entry_filename.isEmpty())
+ return;
+
+ QString file_name;
+ if (!tempFile)
+ {
+ GString *safe_filename = eo_massage_str(entry_filename.toUtf8().constData(), EXPORT_OBJECT_MAXFILELEN, 0);
+ file_name = WiresharkFileDialog::getSaveFileName(this, mainApp->windowTitleString(tr("Save Object As…")),
+ safe_filename->str);
+ g_string_free(safe_filename, TRUE);
+ } else {
+ QString path = QDir::tempPath().append("/").append(entry_filename);
+ /* This means, the system must remove the file! */
+ file_name = path;
+ if (QFileInfo::exists(path))
+ QFile::remove(path);
+ *tempFile = path;
+ }
+
+ model_.saveEntry(current, file_name);
+}
+
+void ExportObjectDialog::saveAllEntries()
+{
+ QDir save_in_dir(mainApp->openDialogInitialDir());
+ QString save_in_path;
+
+ //
+ // We want the user to be able to specify a directory in which
+ // to drop files for all the objects, not a file name.
+ //
+ // XXX - what we *really* want is something that asks the user
+ // for an existing directory *but* lets them create a new
+ // directory in the process. That's what we get on macOS,
+ // as the native dialog is used, and it supports that; does
+ // that also work on Windows and with Qt's own dialog?
+ //
+ save_in_path = WiresharkFileDialog::getExistingDirectory(this, mainApp->windowTitleString(tr("Save All Objects In…")),
+ save_in_dir.canonicalPath(),
+ QFileDialog::ShowDirsOnly);
+
+ if (save_in_path.length() < 1)
+ return;
+
+ model_.saveAllEntries(save_in_path);
+}