/* data_printer.cpp * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later */ #include #include #include #include #include #include #include #include #include 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_PrintableText: for (int i = 0; i < printData.length(); i++) { QChar ch(printData[i]); if (ch.isSpace() || ch.isLetter()) { clipboard_text += ch; } } 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_EscapedString: // Beginning quote clipboard_text += QString("\""); for (int i = 0; i < printData.length(); i++) { // Terminate this line if it has reached 16 bytes, // unless it is also the very last byte in the data, // as the termination after this for loop will take // care of that. if (i % 16 == 0 && i != 0 && i != printData.length() - 1) { clipboard_text += QString("\" \\\n\""); } clipboard_text += QString("\\x%1").arg((uint8_t) printData[i], 2, 16, QChar('0')); } // End quote clipboard_text += QString("\"\n"); break; case DP_Binary: 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 = recent.gui_bytes_view == BYTES_HEX ? 16 : 8; int chars_per_byte = recent.gui_bytes_view == BYTES_HEX ? 3 : 9; return (row_width * chars_per_byte) + ((row_width - 1) / separatorInterval()); } QString DataPrinter::hexTextDump(const QByteArray printData, bool showText) { 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 ( showText ) { QChar ch(printData[cnt]); if (!ch.isPrint()) ch = '.'; dataStr += ch; } cnt++; } int lines = 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 ( showText ) { /* separation bytes for byte and text */ clipboard_text += QString(3, ' '); /* separation bytes last line */ if ( cnt == ( lines - 1 ) ) { int remSpace = byteLineLength_ - 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(copyClass) ) return actions; DataPrinter * dpi = DataPrinter::instance(); if ( data ) actions->setProperty("idataprintable", VariantPointer::asQVariant(data)); else actions->setProperty("idataprintable", VariantPointer::asQVariant(copyClass)); // Mostly duplicated from main_window.ui QAction * action = new QAction(tr("Copy Bytes as Hex + ASCII Dump"), dpi); action->setToolTip(tr("Copy packet bytes as a hex and ASCII dump.")); action->setProperty("printertype", DataPrinter::DP_HexDump); connect(action, SIGNAL(triggered(bool)), dpi, SLOT(copyIDataBytes(bool))); actions->addAction(action); action = new QAction(tr(UTF8_HORIZONTAL_ELLIPSIS "as Hex Dump"), dpi); action->setToolTip(tr("Copy packet bytes as a hex dump.")); action->setProperty("printertype", DataPrinter::DP_HexOnly); connect(action, SIGNAL(triggered(bool)), dpi, SLOT(copyIDataBytes(bool))); actions->addAction(action); action = new QAction(tr(UTF8_HORIZONTAL_ELLIPSIS "as Printable Text"), dpi); action->setToolTip(tr("Copy only the printable text in the packet.")); action->setProperty("printertype", DataPrinter::DP_PrintableText); connect(action, SIGNAL(triggered(bool)), dpi, SLOT(copyIDataBytes(bool))); actions->addAction(action); action = new QAction(tr(UTF8_HORIZONTAL_ELLIPSIS "as a Hex Stream"), dpi); action->setToolTip(tr("Copy packet bytes as a stream of hex.")); action->setProperty("printertype", DataPrinter::DP_HexStream); connect(action, SIGNAL(triggered(bool)), dpi, SLOT(copyIDataBytes(bool))); actions->addAction(action); action = new QAction(tr(UTF8_HORIZONTAL_ELLIPSIS "as Raw Binary"), dpi); action->setToolTip(tr("Copy packet bytes as application/octet-stream MIME data.")); action->setProperty("printertype", DataPrinter::DP_Binary); connect(action, SIGNAL(triggered(bool)), dpi, SLOT(copyIDataBytes(bool))); actions->addAction(action); action = new QAction(tr(UTF8_HORIZONTAL_ELLIPSIS "as Escaped String"), dpi); action->setToolTip(tr("Copy packet bytes as an escaped string.")); action->setProperty("printertype", DataPrinter::DP_EscapedString); connect(action, SIGNAL(triggered(bool)), dpi, SLOT(copyIDataBytes(bool))); actions->addAction(action); return actions; } void DataPrinter::copyIDataBytes(bool /* state */) { if ( ! dynamic_cast(sender()) ) return; QAction * sendingAction = dynamic_cast(sender()); if ( ! sendingAction->actionGroup() || ! sendingAction->actionGroup()->property("idataprintable").isValid() ) return; QObject * dataObject = VariantPointer::asPtr(sendingAction->actionGroup()->property("idataprintable")); if ( ! dataObject || ! dynamic_cast(dataObject) ) return; int dump_type = sendingAction->property("printertype").toInt(); if (dump_type >= 0 && dump_type <= DataPrinter::DP_Binary) { DataPrinter printer; printer.toClipboard((DataPrinter::DumpType) dump_type, dynamic_cast(dataObject)); } } /* * Editor modelines * * Local Variables: * c-basic-offset: 4 * tab-width: 8 * indent-tabs-mode: nil * End: * * ex: set shiftwidth=4 tabstop=8 expandtab: * :indentSize=4:tabSize=8:noTabs=true: */