summaryrefslogtreecommitdiffstats
path: root/ui/qt/utils/data_printer.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--ui/qt/utils/data_printer.cpp264
1 files changed, 264 insertions, 0 deletions
diff --git a/ui/qt/utils/data_printer.cpp b/ui/qt/utils/data_printer.cpp
new file mode 100644
index 00000000..36f1abd7
--- /dev/null
+++ b/ui/qt/utils/data_printer.cpp
@@ -0,0 +1,264 @@
+/* data_printer.cpp
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <ui/qt/utils/data_printer.h>
+#include <ui/qt/utils/variant_pointer.h>
+
+#include <ui/recent.h>
+
+#include <wsutil/utf8_entities.h>
+
+#include <stdint.h>
+
+#include <QApplication>
+#include <QClipboard>
+#include <QString>
+#include <QMimeData>
+
+DataPrinter::DataPrinter(QObject * parent)
+: QObject(parent),
+ byteLineLength_(16)
+{}
+
+void DataPrinter::toClipboard(DataPrinter::DumpType type, IDataPrintable * printable)
+{
+ const QByteArray printData = printable->printableData();
+
+ QString clipboard_text;
+
+ switch(type)
+ {
+ case DP_CString:
+ // Beginning quote
+ clipboard_text += QString("\"");
+ for (int i = 0; i < printData.length(); i++) {
+ /* ASCII printable */
+ int ch = printData[i];
+ if (ch >= 32 && ch <= 126) {
+ clipboard_text += QChar(ch);
+ }
+ else {
+ clipboard_text += QString("\\x%1").arg((uint8_t) printData[i], 2, 16, QChar('0'));
+ }
+ }
+ // End quote
+ clipboard_text += QString("\"");
+ break;
+ case DP_HexStream:
+ for (int i = 0; i < printData.length(); i++)
+ clipboard_text += QString("%1").arg((uint8_t) printData[i], 2, 16, QChar('0'));
+ break;
+ case DP_Base64:
+#if WS_IS_AT_LEAST_GNUC_VERSION(12,1)
+DIAG_OFF(stringop-overread)
+#endif
+ clipboard_text = printData.toBase64();
+#if WS_IS_AT_LEAST_GNUC_VERSION(12,1)
+DIAG_ON(stringop-overread)
+#endif
+ break;
+ case DP_MimeData:
+ binaryDump(printData);
+ break;
+ case DP_HexDump:
+ clipboard_text = hexTextDump(printData, true);
+ break;
+ case DP_HexOnly:
+ clipboard_text = hexTextDump(printData, false);
+ break;
+ default:
+ break;
+ }
+
+ if (!clipboard_text.isEmpty()) {
+ qApp->clipboard()->setText(clipboard_text);
+ }
+}
+
+void DataPrinter::binaryDump(const QByteArray printData)
+{
+ if (!printData.isEmpty()) {
+ QMimeData *mime_data = new QMimeData;
+ // gtk/gui_utils.c:copy_binary_to_clipboard says:
+ /* XXX - this is not understood by most applications,
+ * but can be pasted into the better hex editors - is
+ * there something better that we can do?
+ */
+ // As of 2015-07-30, pasting into Frhed works on Windows. Pasting into
+ // Hex Editor Neo and HxD does not.
+ mime_data->setData("application/octet-stream", printData);
+ qApp->clipboard()->setMimeData(mime_data);
+ }
+}
+
+void DataPrinter::setByteLineLength(int bll)
+{
+ byteLineLength_ = bll;
+}
+
+int DataPrinter::byteLineLength() const
+{
+ return byteLineLength_;
+}
+
+int DataPrinter::hexChars()
+{
+ int row_width, chars_per_byte;
+
+ switch (recent.gui_bytes_view) {
+ case BYTES_HEX:
+ row_width = 16;
+ chars_per_byte = 3;
+ break;
+ case BYTES_BITS:
+ row_width = 8;
+ chars_per_byte = 9;
+ break;
+ case BYTES_DEC:
+ case BYTES_OCT:
+ row_width = 16;
+ chars_per_byte = 4;
+ break;
+ default:
+ ws_assert_not_reached();
+ }
+ return (row_width * chars_per_byte) + ((row_width - 1) / separatorInterval());
+}
+
+QString DataPrinter::hexTextDump(const QByteArray printData, bool showASCII)
+{
+ QString clipboard_text;
+
+ QString byteStr;
+ QString dataStr;
+
+ int cnt = 0;
+ while (cnt < printData.length())
+ {
+ byteStr += QString(" %1").arg((uint8_t) printData[cnt], 2, 16, QChar('0'));
+ if (showASCII)
+ {
+ QChar ch(printData[cnt]);
+ if (g_ascii_isprint(printData[cnt]))
+ dataStr += printData[cnt];
+ else
+ dataStr += '.';
+ }
+ cnt++;
+ }
+
+ int lines = static_cast<int>(printData.length()) / byteLineLength_;
+ if (printData.length() % byteLineLength_ > 0)
+ lines++;
+
+ for (cnt = 0; cnt < lines; cnt++)
+ {
+ int offset = cnt * 0x10;
+
+ clipboard_text += QString("%1 ").arg(offset, 4, 16, QChar('0'));
+ clipboard_text += byteStr.mid(offset * 3, byteLineLength_ * 3);
+
+ if (showASCII)
+ {
+ /* separation bytes for byte and text */
+ clipboard_text += QString(3, ' ');
+
+ /* separation bytes last line */
+ if (cnt == (lines - 1) )
+ {
+ int remSpace = byteLineLength_ - static_cast<int>(dataStr.mid(offset, byteLineLength_).length());
+ clipboard_text += QString(remSpace * 3, ' ');
+ }
+
+ /* text representation */
+ clipboard_text += dataStr.mid(offset, byteLineLength_);
+ }
+
+ clipboard_text += "\n";
+ }
+
+ return clipboard_text;
+}
+
+DataPrinter * DataPrinter::instance()
+{
+ static DataPrinter * inst = Q_NULLPTR;
+ if (inst == Q_NULLPTR)
+ inst = new DataPrinter();
+ return inst;
+}
+
+QActionGroup * DataPrinter::copyActions(QObject * copyClass, QObject * data)
+{
+ QActionGroup * actions = new QActionGroup(copyClass);
+
+ if (! data && ! dynamic_cast<IDataPrintable *>(copyClass))
+ return actions;
+
+ DataPrinter * dpi = DataPrinter::instance();
+
+ if (data)
+ actions->setProperty("idataprintable", VariantPointer<QObject>::asQVariant(data));
+ else
+ actions->setProperty("idataprintable", VariantPointer<QObject>::asQVariant(copyClass));
+
+ // Mostly duplicated from main_window.ui
+ QAction * action = new QAction(tr("Copy Bytes as Hex + ASCII Dump"), actions);
+ action->setToolTip(tr("Copy packet bytes as a hex and ASCII dump."));
+ action->setProperty("printertype", DataPrinter::DP_HexDump);
+ connect(action, &QAction::triggered, dpi, &DataPrinter::copyIDataBytes);
+
+ action = new QAction(tr("…as Hex Dump"), actions);
+ action->setToolTip(tr("Copy packet bytes as a hex dump."));
+ action->setProperty("printertype", DataPrinter::DP_HexOnly);
+ connect(action, &QAction::triggered, dpi, &DataPrinter::copyIDataBytes);
+
+ action = new QAction(tr("…as a Hex Stream"), actions);
+ action->setToolTip(tr("Copy packet bytes as a stream of hex."));
+ action->setProperty("printertype", DataPrinter::DP_HexStream);
+ connect(action, &QAction::triggered, dpi, &DataPrinter::copyIDataBytes);
+
+ action = new QAction(tr("…as a Base64 String"), actions);
+ action->setToolTip(tr("Copy packet bytes as a base64 encoded string."));
+ action->setProperty("printertype", DataPrinter::DP_Base64);
+ connect(action, &QAction::triggered, dpi, &DataPrinter::copyIDataBytes);
+
+ action = new QAction(tr("…as MIME Data"), actions);
+ action->setToolTip(tr("Copy packet bytes as application/octet-stream MIME data."));
+ action->setProperty("printertype", DataPrinter::DP_MimeData);
+ connect(action, &QAction::triggered, dpi, &DataPrinter::copyIDataBytes);
+
+ action = new QAction(tr("…as C String"), actions);
+ action->setToolTip(tr("Copy packet bytes as printable ASCII characters and escape sequences."));
+ action->setProperty("printertype", DataPrinter::DP_CString);
+ connect(action, &QAction::triggered, dpi, &DataPrinter::copyIDataBytes);
+
+ return actions;
+}
+
+void DataPrinter::copyIDataBytes(bool /* state */)
+{
+ if (! dynamic_cast<QAction*>(sender()))
+ return;
+
+ QAction * sendingAction = dynamic_cast<QAction *>(sender());
+ if (! sendingAction->actionGroup() || ! sendingAction->actionGroup()->property("idataprintable").isValid())
+ return;
+
+ QObject * dataObject = VariantPointer<QObject>::asPtr(sendingAction->actionGroup()->property("idataprintable"));
+ if (! dataObject || ! dynamic_cast<IDataPrintable *>(dataObject))
+ return;
+
+ int dump_type = sendingAction->property("printertype").toInt();
+
+ if (dump_type >= 0 && dump_type <= DataPrinter::DP_Base64) {
+ DataPrinter printer;
+ printer.toClipboard((DataPrinter::DumpType) dump_type, dynamic_cast<IDataPrintable *>(dataObject));
+ }
+}