wireshark/ui/qt/export_dissection_dialog.cpp
John Thacker 0011bb6a4c Qt: Allow omitting secondary data sources when printing
Add a checkbox to the packet format group box to allow the
hexdump to only have the main frame instead of secondary data
sources as well, so that Print and Export Packet Dissections can
be used for input to text2pcap.
2022-02-10 23:28:53 -05:00

290 lines
9.6 KiB
C++

/* 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 "wireshark_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(wsApp->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(wsApp->lastOpenDir());
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)
QDialogButtonBox *button_box = findChild<QDialogButtonBox *>();
// 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);
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(accepted()), this, SLOT(dialogAccepted()));
#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()
{
if (selectedFiles().length() > 0) {
cf_print_status_t status;
QString file_name = selectedFiles()[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;
}
if (selectedFiles().length() > 0) {
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()
{
wsApp->helpTopicAction(HELP_EXPORT_FILE_DIALOG);
}
#endif // Q_OS_WIN