diff options
Diffstat (limited to 'ui/qt/export_dissection_dialog.cpp')
-rw-r--r-- | ui/qt/export_dissection_dialog.cpp | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/ui/qt/export_dissection_dialog.cpp b/ui/qt/export_dissection_dialog.cpp new file mode 100644 index 00000000..7f2664ec --- /dev/null +++ b/ui/qt/export_dissection_dialog.cpp @@ -0,0 +1,287 @@ +/* export_dissection_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_dissection_dialog.h" + +#ifdef Q_OS_WIN +#include <windows.h> +#include "ui/packet_range.h" +#include "ui/win32/file_dlg_win32.h" +#else // Q_OS_WIN + +#include "ui/alert_box.h" +#include "ui/help_url.h" +#include "ui/util.h" + +#include <epan/print.h> +#include <wsutil/filesystem.h> + +#include <ui/qt/utils/qt_ui_utils.h> + + +#include <QDialogButtonBox> +#include <QGridLayout> +#include <QPushButton> +#endif // Q_OS_WIN + +#include <epan/prefs.h> +#include "main_application.h" + +#if !defined(Q_OS_WIN) +static const QStringList export_extensions = QStringList() + << "" + << "txt" + << "" + << "csv" + << "psml" + << "pdml" + << "c" + << "json"; + +#endif + +ExportDissectionDialog::ExportDissectionDialog(QWidget *parent, capture_file *cap_file, export_type_e export_type, QString selRange): + WiresharkFileDialog(parent), + export_type_(export_type), + cap_file_(cap_file) +#if !defined(Q_OS_WIN) + , save_bt_(NULL) +#else + , sel_range_(selRange) +#endif /* Q_OS_WIN */ +{ + setWindowTitle(mainApp->windowTitleString(tr("Export Packet Dissections"))); + + switch (prefs.gui_fileopen_style) { + + case FO_STYLE_LAST_OPENED: + /* The user has specified that we should start out in the last directory + * we looked in. If we've already opened a file, use its containing + * directory, if we could determine it, as the directory, otherwise + * use the "last opened" directory saved in the preferences file if + * there was one. + */ + setDirectory(mainApp->openDialogInitialDir()); + break; + + case FO_STYLE_SPECIFIED: + /* The user has specified that we should always start out in a + * specified directory; if they've specified that directory, + * start out by showing the files in that dir. + */ + if (prefs.gui_fileopen_dir[0] != '\0') + setDirectory(prefs.gui_fileopen_dir); + break; + } + +#if !defined(Q_OS_WIN) + // Add extra widgets + // https://wiki.qt.io/Qt_project_org_faq#How_can_I_add_widgets_to_my_QFileDialog_instance.3F + setOption(QFileDialog::DontUseNativeDialog, true); + QDialogButtonBox *button_box = findChild<QDialogButtonBox *>(); + QGridLayout *fd_grid = qobject_cast<QGridLayout*>(layout()); + QHBoxLayout *h_box = new QHBoxLayout(); + QStringList name_filters; + int last_row; + + setAcceptMode(QFileDialog::AcceptSave); + setLabelText(FileType, tr("Export As:")); + + // export_type_map_keys() sorts alphabetically. We don't want that. + name_filters + << tr("Plain text (*.txt)") + << tr("Comma Separated Values - summary (*.csv)") + << tr("PSML - summary (*.psml, *.xml)") + << tr("PDML - details (*.pdml, *.xml)") + << tr("JSON (*.json)") + << tr("C Arrays - bytes (*.c, *.h)"); + export_type_map_[name_filters[0]] = export_type_text; + export_type_map_[name_filters[1]] = export_type_csv; + export_type_map_[name_filters[2]] = export_type_psml; + export_type_map_[name_filters[3]] = export_type_pdml; + export_type_map_[name_filters[4]] = export_type_json; + export_type_map_[name_filters[5]] = export_type_carrays; + setNameFilters(name_filters); + selectNameFilter(export_type_map_.key(export_type)); + exportTypeChanged(export_type_map_.key(export_type)); + + last_row = fd_grid->rowCount(); + fd_grid->addItem(new QSpacerItem(1, 1), last_row, 0); + fd_grid->addLayout(h_box, last_row, 1); + + print_args_.file = NULL; + /* Init the export range */ + packet_range_init(&print_args_.range, cap_file_); + /* Default to displayed packets */ + print_args_.range.process_filtered = TRUE; + + packet_range_group_box_.initRange(&print_args_.range, selRange); + h_box->addWidget(&packet_range_group_box_); + + h_box->addWidget(&packet_format_group_box_, 0, Qt::AlignTop); + + if (button_box) { + button_box->addButton(QDialogButtonBox::Help); + connect(button_box, SIGNAL(helpRequested()), this, SLOT(on_buttonBox_helpRequested())); + + save_bt_ = button_box->button(QDialogButtonBox::Save); + } + + if (save_bt_) { + connect(&packet_range_group_box_, SIGNAL(validityChanged(bool)), + this, SLOT(checkValidity())); + connect(&packet_format_group_box_, SIGNAL(formatChanged()), + this, SLOT(checkValidity())); + } + connect(this, SIGNAL(filterSelected(QString)), this, SLOT(exportTypeChanged(QString))); + + // Grow the dialog to account for the extra widgets. + resize(width(), height() + (packet_range_group_box_.height() * 2 / 3)); + + connect(this, SIGNAL(filesSelected(QStringList)), this, SLOT(dialogAccepted(QStringList))); +#else // Q_OS_WIN +#endif // Q_OS_WIN +} + +ExportDissectionDialog::~ExportDissectionDialog() +{ +#if !defined(Q_OS_WIN) + g_free(print_args_.file); + packet_range_cleanup(&print_args_.range); +#endif +} + +void ExportDissectionDialog::show() +{ +#if !defined(Q_OS_WIN) + if (cap_file_) { + WiresharkFileDialog::show(); + } +#else // Q_OS_WIN + win32_export_file((HWND)parentWidget()->effectiveWinId(), windowTitle().toStdWString().c_str(), cap_file_, export_type_, sel_range_.toStdString().c_str()); +#endif // Q_OS_WIN +} + +#ifndef Q_OS_WIN +void ExportDissectionDialog::dialogAccepted(const QStringList &selected) +{ + if (selected.length() > 0) { + cf_print_status_t status; + QString file_name = selected[0]; + + /* Fill in our print (and export) args */ + + print_args_.file = qstring_strdup(file_name); + print_args_.format = PR_FMT_TEXT; + print_args_.to_file = TRUE; + print_args_.cmd = NULL; + print_args_.print_summary = TRUE; + print_args_.print_col_headings = TRUE; + print_args_.print_dissections = print_dissections_as_displayed; + print_args_.print_hex = FALSE; + print_args_.print_formfeed = FALSE; + + switch (export_type_) { + case export_type_text: /* Text */ + print_args_.print_summary = packet_format_group_box_.summaryEnabled(); + print_args_.print_col_headings = packet_format_group_box_.includeColumnHeadingsEnabled(); + print_args_.print_dissections = print_dissections_none; + if (packet_format_group_box_.detailsEnabled()) { + if (packet_format_group_box_.allCollapsedEnabled()) + print_args_.print_dissections = print_dissections_collapsed; + else if (packet_format_group_box_.asDisplayedEnabled()) + print_args_.print_dissections = print_dissections_as_displayed; + else if (packet_format_group_box_.allExpandedEnabled()) + print_args_.print_dissections = print_dissections_expanded; + } + print_args_.print_hex = packet_format_group_box_.bytesEnabled(); + print_args_.hexdump_options = packet_format_group_box_.getHexdumpOptions(); + print_args_.stream = print_stream_text_new(TRUE, print_args_.file); + if (print_args_.stream == NULL) { + open_failure_alert_box(print_args_.file, errno, TRUE); + return; + } + status = cf_print_packets(cap_file_, &print_args_, TRUE); + break; + case export_type_csv: /* CSV */ + status = cf_write_csv_packets(cap_file_, &print_args_); + break; + case export_type_carrays: /* C Arrays */ + status = cf_write_carrays_packets(cap_file_, &print_args_); + break; + case export_type_psml: /* PSML */ + status = cf_write_psml_packets(cap_file_, &print_args_); + break; + case export_type_pdml: /* PDML */ + status = cf_write_pdml_packets(cap_file_, &print_args_); + break; + case export_type_json: /* JSON */ + status = cf_write_json_packets(cap_file_, &print_args_); + break; + default: + return; + } + + switch (status) { + case CF_PRINT_OK: + break; + case CF_PRINT_OPEN_ERROR: + open_failure_alert_box(print_args_.file, errno, TRUE); + break; + case CF_PRINT_WRITE_ERROR: + write_failure_alert_box(print_args_.file, errno); + break; + } + + gchar *dirname; + /* Save the directory name for future file dialogs. */ + dirname = get_dirname(print_args_.file); /* Overwrites file_name data */ + set_last_open_dir(dirname); + } +} + +void ExportDissectionDialog::exportTypeChanged(QString name_filter) +{ + export_type_ = export_type_map_.value(name_filter); + if (export_type_ == export_type_text) { + packet_format_group_box_.setEnabled(true); + print_args_.format = PR_FMT_TEXT; + } else { + packet_format_group_box_.setEnabled(false); + } + + checkValidity(); + setDefaultSuffix(export_extensions[export_type_]); +} + +void ExportDissectionDialog::checkValidity() +{ + bool enable = true; + + if (!save_bt_) return; + + if (!packet_range_group_box_.isValid()) enable = false; + + if (export_type_ == export_type_text) { + if (! packet_format_group_box_.summaryEnabled() && + ! packet_format_group_box_.detailsEnabled() && + ! packet_format_group_box_.bytesEnabled()) + { + enable = false; + } + } + + save_bt_->setEnabled(enable); +} + +void ExportDissectionDialog::on_buttonBox_helpRequested() +{ + mainApp->helpTopicAction(HELP_EXPORT_FILE_DIALOG); +} +#endif // Q_OS_WIN |