Qt: Add Decode as in Show Packet Bytes

Add an option to decode the packet bytes from base64 or zlib compressed.
Also add configurable start byte and end byte to make it possible to
decode a subset of bytes.  It's also possible to select a range in ASCII
view and select "Show selected" from the context menu to make a subset.

In ASCII view a null terminator is replaced by UTF8 symbol for NULL,
and a CR is replaced by UTF8 symbol for carriage return.  This is done
to make it possible to "Show selected" from the context menu.

Change-Id: Ie03c9912c304c121af6ca9e998a6e8445b5382c5
Reviewed-on: https://code.wireshark.org/review/13958
Petri-Dish: Stig Bjørlykke <stig@bjorlykke.org>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
This commit is contained in:
Stig Bjørlykke 2016-02-14 23:01:09 +01:00 committed by Alexis La Goutte
parent a6118997ff
commit 989739c4fc
7 changed files with 469 additions and 81 deletions

View File

@ -90,14 +90,19 @@ You can choose to view the data in one of the following formats:
=== Show Packet Bytes
If a selected packet field does not show all the bytes (i.e. they are truncated)
or if they are shown as bytes rather than string or if they require more formatting
because they contain an image or HTML then this dialog can be used.
If a selected packet field does not show all the bytes (i.e. they are truncated
when displayed) or if they are shown as bytes rather than string or if they require
more formatting because they contain an image or HTML then this dialog can be used.
This dialog can also be used to decode field bytes from base64 or zlib compressed
and show the decoded bytes as configurable output. It's also possible to select
a subset of bytes setting the start byte and end byte.
You can choose from the following actions:
. __Find__: Search for the given text. Matching text will be highlighted,
and the ``Find Next'' will search for more.
and the ``Find Next'' will search for more. In the context menu for the
find text it's possible to configure to use regular expression find.
. __Print__: Print the bytes in the currently selected format.
@ -107,13 +112,28 @@ You can choose from the following actions:
. __Close__: Close this dialog box.
You can choose to decode the data from one of the following formats:
. __None__: This is the default which does not decode anything.
. __Base64__: This will decode from Base64.
. __Compressed__: This will decompress the buffer using zlib.
You can choose to view the data in one of the following formats:
. __ASCII__: In this view you see the bytes as ASCII.
All non-ASCII bytes are replaced by dot for readability.
A null terminator is shown using the UTF-8 symbol for NULL, a CR is shown using
the UTF-8 symbol for carriage return, and all other non-ASCII bytes are replaced
by dot for readability.
. __C Array__: This allows you to import the field data into your own C program.
. __EBCDIC__: For the big-iron freaks out there.
. __HEX Dump__: This allows you to see all the data. This will require a lot of
screen space and is best used with binary protocols.
. __HTML__: This allows you to see all the data formatted as a HTML document.
The HTML supported is what's supported by the Qt QTextEdit class.
@ -128,6 +148,8 @@ You can choose to view the data in one of the following formats:
. __UTF8__: In this view you see the bytes as UTF-8.
. __YAML__: This will show the bytes as a YAML binary dump.
[[ChAdvExpert]]
=== Expert Information

View File

@ -26,55 +26,54 @@
#include "wireshark_application.h"
#include "epan/charsets.h"
#include <wsutil/utf8_entities.h>
#include "wsutil/base64.h"
#include "wsutil/utf8_entities.h"
#include <QAction>
#include <QImage>
#include <QKeyEvent>
#include <QMenu>
#include <QPrintDialog>
#include <QPrinter>
#include <QTextStream>
// To do:
// - Add show as custom protocol in a Packet Details view
// - Add show as PDF or handle PDF as Image
// - Add decode from BASE64
// - Use ByteViewText to ShowAsHexDump and supplementary view for custom protocol
// - Handle large data blocks
ShowPacketBytesDialog::ShowPacketBytesDialog(QWidget &parent, CaptureFile &cf) :
WiresharkDialog(parent, cf),
ui(new Ui::ShowPacketBytesDialog),
finfo_(cf.capFile()->finfo_selected),
decode_as_(DecodeAsNone),
show_as_(ShowAsASCII),
use_regex_find_(false)
{
ui->setupUi(this);
field_info *finfo = cf.capFile()->finfo_selected;
QString field_name = QString("%1 (%2)").arg(finfo->hfinfo->name, finfo->hfinfo->abbrev);
QString field_name = QString("%1 (%2)").arg(finfo_->hfinfo->name, finfo_->hfinfo->abbrev);
setWindowSubtitle (field_name);
const guint8 *bytes = tvb_get_ptr(finfo->ds_tvb, 0, -1) + finfo->start;
field_bytes_ = QByteArray((const char *)bytes, finfo->length);
QString hint = tr("Frame %1, %2, %Ln byte(s).", "", finfo->length)
.arg(cf.capFile()->current_frame->num)
.arg(field_name);
hint.prepend("<small><i>");
hint.append("</i></small>");
ui->hintLabel->setText(hint);
// Try loading as image
if (image_.loadFromData(field_bytes_)) {
show_as_ = ShowAsImage;
}
hint_label_ = tr("Frame %1, %2, %Ln byte(s).", "", finfo_->length)
.arg(cf.capFile()->current_frame->num)
.arg(field_name);
ui->tePacketBytes->installEventFilter(this);
connect(ui->tePacketBytes, SIGNAL(showSelected(int,int)), this, SLOT(showSelected(int,int)));
connect(ui->leFind, SIGNAL(useRegexFind(bool)), this, SLOT(useRegexFind(bool)));
// XXX Use recent settings instead
resize(parent.width() * 2 / 3, parent.height());
ui->cbDecodeAs->blockSignals(true);
ui->cbDecodeAs->addItem(tr("None"), DecodeAsNone);
ui->cbDecodeAs->addItem(tr("Base64"), DecodeAsBASE64);
ui->cbDecodeAs->addItem(tr("Compressed"), DecodeAsCompressed);
ui->cbDecodeAs->addItem(tr("ROT13"), DecodeAsROT13);
ui->cbDecodeAs->blockSignals(false);
ui->cbShowAs->blockSignals(true);
ui->cbShowAs->addItem(tr("ASCII"), ShowAsASCII);
ui->cbShowAs->addItem(tr("C Array"), ShowAsCArray);
@ -89,6 +88,9 @@ ShowPacketBytesDialog::ShowPacketBytesDialog(QWidget &parent, CaptureFile &cf) :
ui->cbShowAs->setCurrentIndex(show_as_);
ui->cbShowAs->blockSignals(false);
ui->sbStart->setMinimum(0);
ui->sbEnd->setMaximum(finfo_->length);
print_button_ = ui->buttonBox->addButton(tr("Print"), QDialogButtonBox::ActionRole);
connect(print_button_, SIGNAL(clicked()), this, SLOT(printBytes()));
@ -101,7 +103,8 @@ ShowPacketBytesDialog::ShowPacketBytesDialog(QWidget &parent, CaptureFile &cf) :
connect(ui->buttonBox, SIGNAL(helpRequested()), this, SLOT(helpButton()));
connect(&cap_file_, SIGNAL(captureFileClosing()), this, SLOT(captureFileClosing()));
updatePacketBytes();
setStartAndEnd(0, finfo_->length);
updateFieldBytes(true);
}
ShowPacketBytesDialog::~ShowPacketBytesDialog()
@ -109,16 +112,99 @@ ShowPacketBytesDialog::~ShowPacketBytesDialog()
delete ui;
}
void ShowPacketBytesDialog::showSelected(int start, int end)
{
if (end == -1) {
// end set to -1 means show all packet bytes
setStartAndEnd(0, finfo_->length);
} else {
setStartAndEnd(start_ + start, start_ + end);
}
updateFieldBytes();
}
void ShowPacketBytesDialog::setStartAndEnd(int start, int end)
{
start_ = start;
end_ = end;
ui->sbStart->blockSignals(true);
ui->sbStart->setMaximum(end_);
ui->sbStart->setValue(start_);
ui->sbStart->blockSignals(false);
ui->sbEnd->blockSignals(true);
ui->sbEnd->setMinimum(start_);
ui->sbEnd->setValue(end_);
ui->sbEnd->blockSignals(false);
updateHintLabel();
}
bool ShowPacketBytesDialog::enableShowSelected()
{
// "Show Selected" only works when showing all bytes:
// - DecodeAs must not alter the number of bytes in the buffer
// - ShowAs must show all bytes in the buffer
return (((decode_as_ == DecodeAsNone) ||
(decode_as_ == DecodeAsROT13)) &&
((show_as_ == ShowAsASCII) ||
(show_as_ == ShowAsEBCDIC)));
}
void ShowPacketBytesDialog::updateWidgets()
{
WiresharkDialog::updateWidgets();
}
void ShowPacketBytesDialog::updateHintLabel()
{
QString hint = hint_label_;
if (start_ > 0 || end_ < finfo_->length) {
hint.append(" <span style=\"color: red\">" +
tr("Displaying %Ln byte(s).", "", end_ - start_) +
"</span>");
}
ui->hintLabel->setText("<small><i>" + hint + "</i></small>");
}
void ShowPacketBytesDialog::on_sbStart_valueChanged(int value)
{
start_ = value;
ui->sbEnd->setMinimum(value);
updateHintLabel();
updateFieldBytes();
}
void ShowPacketBytesDialog::on_sbEnd_valueChanged(int value)
{
end_ = value;
ui->sbStart->setMaximum(value);
updateHintLabel();
updateFieldBytes();
}
void ShowPacketBytesDialog::on_cbDecodeAs_currentIndexChanged(int idx)
{
if (idx < 0) return;
decode_as_ = static_cast<DecodeAsType>(ui->cbDecodeAs->itemData(idx).toInt());
ui->tePacketBytes->setShowSelectedEnabled(enableShowSelected());
updateFieldBytes();
}
void ShowPacketBytesDialog::on_cbShowAs_currentIndexChanged(int idx)
{
if (idx < 0) return;
show_as_ = static_cast<ShowAsType>(ui->cbShowAs->itemData(idx).toInt());
ui->tePacketBytes->setShowSelectedEnabled(enableShowSelected());
ui->lFind->setEnabled(true);
ui->leFind->setEnabled(true);
ui->bFind->setEnabled(true);
@ -316,13 +402,86 @@ void ShowPacketBytesDialog::keyPressEvent(QKeyEvent *event)
QDialog::keyPressEvent(event);
}
static inline void sanitize_buffer(QByteArray &ba)
void ShowPacketBytesDialog::sanitizeBuffer(QByteArray &ba)
{
for (int i = 0; i < ba.length(); i++) {
if (!g_ascii_isspace(ba[i]) && !g_ascii_isprint(ba[i])) {
ba[i] = '.';
if (ba[i] != '\0' && ba[i] != '\r' && ba[i] != '\n') {
if (g_ascii_isspace(ba[i])) {
ba[i] = ' ';
} else if (!g_ascii_isprint(ba[i])) {
ba[i] = '.';
}
}
}
// Null and CR are replaced with UTF8 symbols to be able to show all
// bytes in ASCII view. This will ensure that "Show Selected" works.
ba.replace('\0', UTF8_SYMBOL_FOR_NULL);
ba.replace('\r', UTF8_SYMBOL_FOR_CARRIAGE_RETURN);
}
void ShowPacketBytesDialog::rot13(QByteArray &ba)
{
for (int i = 0; i < ba.length(); i++) {
gchar upper = g_ascii_toupper(ba[i]);
if (upper >= 'A' && upper <= 'M') ba[i] = ba[i] + 13;
else if (upper >= 'N' && upper <= 'Z') ba[i] = ba[i] - 13;
}
}
void ShowPacketBytesDialog::updateFieldBytes(bool initialization)
{
int start = finfo_->start + start_;
int length = end_ - start_;
const guint8 *bytes;
switch (decode_as_) {
case DecodeAsNone:
bytes = tvb_get_ptr(finfo_->ds_tvb, start, -1);
field_bytes_ = QByteArray((const char *)bytes, length);
break;
case DecodeAsBASE64:
{
bytes = tvb_get_ptr(finfo_->ds_tvb, start, -1);
field_bytes_ = QByteArray((const char *)bytes, length);
size_t len = ws_base64_decode_inplace(field_bytes_.data());
field_bytes_.resize(len);
break;
}
case DecodeAsCompressed:
{
tvbuff *uncompr_tvb = tvb_uncompress(finfo_->ds_tvb, start, length);
if (uncompr_tvb) {
bytes = tvb_get_ptr(uncompr_tvb, 0, -1);
field_bytes_ = QByteArray((const char *)bytes, tvb_reported_length(uncompr_tvb));
tvb_free(uncompr_tvb);
} else {
field_bytes_.clear();
}
break;
}
case DecodeAsROT13:
bytes = tvb_get_ptr(finfo_->ds_tvb, start, -1);
field_bytes_ = QByteArray((const char *)bytes, length);
rot13(field_bytes_);
break;
}
if (initialization || show_as_ == ShowAsImage) {
// Try loading as image
if (image_.loadFromData(field_bytes_) && initialization) {
show_as_ = ShowAsImage;
ui->cbShowAs->blockSignals(true);
ui->cbShowAs->setCurrentIndex(ShowAsImage);
ui->cbShowAs->blockSignals(false);
}
}
updatePacketBytes();
}
void ShowPacketBytesDialog::updatePacketBytes(void)
@ -337,7 +496,7 @@ void ShowPacketBytesDialog::updatePacketBytes(void)
case ShowAsASCII:
{
QByteArray ba(field_bytes_);
sanitize_buffer(ba);
sanitizeBuffer(ba);
ui->tePacketBytes->setPlainText(ba);
break;
}
@ -383,7 +542,7 @@ void ShowPacketBytesDialog::updatePacketBytes(void)
{
QByteArray ba(field_bytes_);
EBCDIC_to_ASCII((guint8*)ba.data(), ba.length());
sanitize_buffer(ba);
sanitizeBuffer(ba);
ui->tePacketBytes->setPlainText(ba);
break;
}
@ -392,6 +551,7 @@ void ShowPacketBytesDialog::updatePacketBytes(void)
{
int pos = 0, len = field_bytes_.length();
QString text;
text.reserve((len / 16) * 80);
while (pos < len) {
char hexbuf[256];
@ -458,6 +618,8 @@ void ShowPacketBytesDialog::updatePacketBytes(void)
case ShowAsISO8859_1:
{
// The ISO 8859-1 string should probably also use UTF8_SYMBOL_FOR_NULL
// to be able to show all bytes.
guint8 *bytes = get_8859_1_string(NULL, (const guint8 *)field_bytes_.constData(), field_bytes_.length());
ui->tePacketBytes->setPlainText((const char *)bytes);
wmem_free (NULL, bytes);
@ -469,7 +631,9 @@ void ShowPacketBytesDialog::updatePacketBytes(void)
// The QString docs say that invalid characters will be replaced with
// replacement characters or removed. It would be nice if we could
// explicitly choose one or the other.
QString utf8 = QString::fromUtf8(field_bytes_);
QByteArray ba(field_bytes_);
ba.replace('\0', UTF8_SYMBOL_FOR_NULL);
QString utf8 = QString::fromUtf8(ba);
ui->tePacketBytes->setPlainText(utf8);
break;
}
@ -499,9 +663,55 @@ void ShowPacketBytesDialog::updatePacketBytes(void)
void ShowPacketBytesDialog::captureFileClosing()
{
// We have lost the source backend and must disable all functions
// for manipulating decoding and displayed range.
ui->tePacketBytes->setMenusEnabled(false);
ui->lDecodeAs->setEnabled(false);
ui->cbDecodeAs->setEnabled(false);
ui->lStart->setEnabled(false);
ui->sbStart->setEnabled(false);
ui->lEnd->setEnabled(false);
ui->sbEnd->setEnabled(false);
finfo_ = NULL; // This will invalidate the source backend
WiresharkDialog::captureFileClosing();
}
void ShowPacketBytesTextEdit::contextMenuEvent(QContextMenuEvent *event)
{
QMenu *menu = createStandardContextMenu();
QAction *action;
menu->addSeparator();
action = menu->addAction(tr("Show Selected"));
action->setEnabled(menus_enabled_ && show_selected_enabled_ && textCursor().hasSelection());
connect(action, SIGNAL(triggered()), this, SLOT(showSelected()));
action = menu->addAction(tr("Show All"));
action->setEnabled(menus_enabled_);
connect(action, SIGNAL(triggered()), this, SLOT(showAll()));
menu->exec(event->globalPos());
delete menu;
}
void ShowPacketBytesTextEdit::showSelected()
{
QTextCursor cursor = textCursor();
int start = cursor.selectionStart();
int end = cursor.selectionEnd();
emit showSelected(start, end);
}
void ShowPacketBytesTextEdit::showAll()
{
emit showSelected(0, -1);
}
/*
* Editor modelines
*

View File

@ -33,10 +33,13 @@
#include "file.h"
#include "wireshark_dialog.h"
#include <QLineEdit>
#include <QPushButton>
#include <QTextEdit>
namespace Ui {
class ShowPacketBytesDialog;
class ShowPacketBytesTextEdit;
}
class ShowPacketBytesDialog : public WiresharkDialog
@ -55,11 +58,15 @@ protected:
void keyPressEvent(QKeyEvent *event);
private slots:
void on_sbStart_valueChanged(int value);
void on_sbEnd_valueChanged(int value);
void on_cbDecodeAs_currentIndexChanged(int idx);
void on_cbShowAs_currentIndexChanged(int idx);
void on_leFind_returnPressed();
void on_bFind_clicked();
void on_buttonBox_rejected();
void showSelected(int start, int end);
void useRegexFind(bool use_regex);
void findText(bool go_back = true);
void helpButton();
@ -68,6 +75,12 @@ private slots:
void saveAs();
private:
enum DecodeAsType {
DecodeAsNone,
DecodeAsBASE64,
DecodeAsCompressed,
DecodeAsROT13
};
enum ShowAsType {
ShowAsASCII,
ShowAsCArray,
@ -81,20 +94,56 @@ private:
ShowAsYAML
};
void setStartAndEnd(int start, int end);
bool enableShowSelected();
void updateWidgets(); // Needed for WiresharkDialog?
void updatePacketBytes(void);
void updateHintLabel();
void sanitizeBuffer(QByteArray &ba);
void rot13(QByteArray &ba);
void updateFieldBytes(bool initialization = false);
void updatePacketBytes();
Ui::ShowPacketBytesDialog *ui;
const field_info *finfo_;
QByteArray field_bytes_;
QString hint_label_;
QPushButton *print_button_;
QPushButton *copy_button_;
QPushButton *save_as_button_;
DecodeAsType decode_as_;
ShowAsType show_as_;
bool use_regex_find_;
int start_;
int end_;
QImage image_;
};
class ShowPacketBytesTextEdit : public QTextEdit
{
Q_OBJECT
public:
explicit ShowPacketBytesTextEdit(QWidget *parent = 0) :
QTextEdit(parent), show_selected_enabled_(true), menus_enabled_(true) { }
~ShowPacketBytesTextEdit() { }
void setShowSelectedEnabled(bool enabled) { show_selected_enabled_ = enabled; }
void setMenusEnabled(bool enabled) { menus_enabled_ = enabled; }
signals:
void showSelected(int, int);
private slots:
void contextMenuEvent(QContextMenuEvent *event);
void showSelected();
void showAll();
private:
bool show_selected_enabled_;
bool menus_enabled_;
};
#endif // SHOW_PACKET_BYTES_DIALOG_H
/*

View File

@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>594</width>
<width>710</width>
<height>620</height>
</rect>
</property>
@ -24,7 +24,7 @@
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTextEdit" name="tePacketBytes">
<widget class="ShowPacketBytesTextEdit" name="tePacketBytes">
<property name="readOnly">
<bool>true</bool>
</property>
@ -41,7 +41,17 @@
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_1" stretch="0,0,0">
<layout class="QHBoxLayout" name="horizontalLayout_1" stretch="0,0,0,0,1,0,0,0,0">
<item>
<widget class="QLabel" name="lDecodeAs">
<property name="text">
<string>Decode as</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="cbDecodeAs"/>
</item>
<item>
<widget class="QLabel" name="lShowAs">
<property name="text">
@ -69,6 +79,26 @@
</property>
</spacer>
</item>
<item>
<widget class="QLabel" name="lStart">
<property name="text">
<string>Start</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="sbStart"/>
</item>
<item>
<widget class="QLabel" name="lEnd">
<property name="text">
<string>End</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="sbEnd"/>
</item>
</layout>
</item>
<item>
@ -107,6 +137,11 @@
<extends>QLineEdit</extends>
<header>find_line_edit.h</header>
</customwidget>
<customwidget>
<class>ShowPacketBytesTextEdit</class>
<extends>QTextEdit</extends>
<header>show_packet_bytes_dialog.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>

Binary file not shown.

View File

@ -2665,21 +2665,34 @@ for filter files: %2.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FindLineEdit</name>
<message>
<location filename="find_line_edit.cpp" line="37"/>
<source>Textual Find</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="find_line_edit.cpp" line="42"/>
<source>Regular Expression Find</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>FollowStreamDialog</name>
<message>
<location filename="follow_stream_dialog.cpp" line="116"/>
<location filename="follow_stream_dialog.cpp" line="119"/>
<source>Filter Out This Stream</source>
<oldsource>Hide this stream</oldsource>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="follow_stream_dialog.cpp" line="119"/>
<location filename="follow_stream_dialog.cpp" line="122"/>
<source>Print</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="follow_stream_dialog.cpp" line="122"/>
<location filename="follow_stream_dialog.cpp" line="125"/>
<source>Save as</source>
<oldsource>Save as...</oldsource>
<translation type="unfinished"></translation>
@ -2699,47 +2712,47 @@ for filter files: %2.</source>
</translation>
</message>
<message>
<location filename="follow_stream_dialog.cpp" line="107"/>
<location filename="follow_stream_dialog.cpp" line="110"/>
<source>ASCII</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="follow_stream_dialog.cpp" line="108"/>
<location filename="follow_stream_dialog.cpp" line="111"/>
<source>C Arrays</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="follow_stream_dialog.cpp" line="109"/>
<location filename="follow_stream_dialog.cpp" line="112"/>
<source>EBCDIC</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="follow_stream_dialog.cpp" line="110"/>
<location filename="follow_stream_dialog.cpp" line="113"/>
<source>Hex Dump</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="follow_stream_dialog.cpp" line="111"/>
<location filename="follow_stream_dialog.cpp" line="114"/>
<source>UTF-8</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="follow_stream_dialog.cpp" line="112"/>
<location filename="follow_stream_dialog.cpp" line="115"/>
<source>YAML</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="follow_stream_dialog.cpp" line="113"/>
<location filename="follow_stream_dialog.cpp" line="116"/>
<source>Raw</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="follow_stream_dialog.cpp" line="166"/>
<location filename="follow_stream_dialog.cpp" line="169"/>
<source>Packet %1. </source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<location filename="follow_stream_dialog.cpp" line="169"/>
<location filename="follow_stream_dialog.cpp" line="172"/>
<source>%Ln &lt;span style=&quot;color: %1; background-color:%2&quot;&gt;client&lt;/span&gt; pkt(s), </source>
<translation>
<numerusform>%Ln &lt;span style=&quot;color: %1; background-color:%2&quot;&gt;client&lt;/span&gt; pkt, </numerusform>
@ -2747,7 +2760,7 @@ for filter files: %2.</source>
</translation>
</message>
<message numerus="yes">
<location filename="follow_stream_dialog.cpp" line="172"/>
<location filename="follow_stream_dialog.cpp" line="175"/>
<source>%Ln &lt;span style=&quot;color: %1; background-color:%2&quot;&gt;server&lt;/span&gt; pkt(s), </source>
<translation>
<numerusform>%Ln &lt;span style=&quot;color: %1; background-color:%2&quot;&gt;server&lt;/span&gt; pkt, </numerusform>
@ -2755,7 +2768,7 @@ for filter files: %2.</source>
</translation>
</message>
<message numerus="yes">
<location filename="follow_stream_dialog.cpp" line="175"/>
<location filename="follow_stream_dialog.cpp" line="178"/>
<source>%Ln turn(s).</source>
<translation>
<numerusform>%Ln turn.</numerusform>
@ -2763,65 +2776,65 @@ for filter files: %2.</source>
</translation>
</message>
<message>
<location filename="follow_stream_dialog.cpp" line="178"/>
<location filename="follow_stream_dialog.cpp" line="181"/>
<source> Click to select.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="follow_stream_dialog.cpp" line="239"/>
<location filename="follow_stream_dialog.cpp" line="261"/>
<source>Save Stream Content As</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="follow_stream_dialog.cpp" line="504"/>
<location filename="follow_stream_dialog.cpp" line="526"/>
<source>
[Stream output truncated]</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="follow_stream_dialog.cpp" line="769"/>
<location filename="follow_stream_dialog.cpp" line="791"/>
<source>No capture file.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="follow_stream_dialog.cpp" line="769"/>
<location filename="follow_stream_dialog.cpp" line="791"/>
<source>Please make sure you have a capture file opened.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="follow_stream_dialog.cpp" line="775"/>
<location filename="follow_stream_dialog.cpp" line="781"/>
<location filename="follow_stream_dialog.cpp" line="797"/>
<location filename="follow_stream_dialog.cpp" line="803"/>
<source>Error following stream.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="follow_stream_dialog.cpp" line="775"/>
<location filename="follow_stream_dialog.cpp" line="797"/>
<source>Capture file invalid.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="follow_stream_dialog.cpp" line="781"/>
<location filename="follow_stream_dialog.cpp" line="803"/>
<source>Please make sure you have a %1 packet selected.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="follow_stream_dialog.cpp" line="897"/>
<location filename="follow_stream_dialog.cpp" line="919"/>
<source>Follow %1 Stream (%2)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="follow_stream_dialog.cpp" line="803"/>
<location filename="follow_stream_dialog.cpp" line="825"/>
<source>Error creating filter for this stream.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="follow_stream_dialog.cpp" line="804"/>
<location filename="follow_stream_dialog.cpp" line="826"/>
<source>A transport or network layer header is needed.</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<location filename="follow_stream_dialog.cpp" line="834"/>
<location filename="follow_stream_dialog.cpp" line="846"/>
<location filename="follow_stream_dialog.cpp" line="856"/>
<location filename="follow_stream_dialog.cpp" line="868"/>
<source>%Ln total stream(s).</source>
<translation type="unfinished">
<numerusform>%Ln stream.</numerusform>
@ -2829,7 +2842,7 @@ for filter files: %2.</source>
</translation>
</message>
<message>
<location filename="follow_stream_dialog.cpp" line="915"/>
<location filename="follow_stream_dialog.cpp" line="937"/>
<source>File closed.</source>
<translation type="unfinished"></translation>
</message>
@ -13720,16 +13733,31 @@ a:hover {
</message>
<message>
<location filename="show_packet_bytes_dialog.ui" line="48"/>
<source>Decode as</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.ui" line="58"/>
<source>Show as</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.ui" line="79"/>
<location filename="show_packet_bytes_dialog.ui" line="85"/>
<source>Start</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.ui" line="95"/>
<source>End</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.ui" line="109"/>
<source>Find:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.ui" line="89"/>
<location filename="show_packet_bytes_dialog.ui" line="119"/>
<source>Find &amp;Next</source>
<translation type="unfinished"></translation>
</message>
@ -13742,76 +13770,117 @@ a:hover {
</translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.cpp" line="76"/>
<source>ASCII</source>
<location filename="show_packet_bytes_dialog.cpp" line="71"/>
<source>None</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.cpp" line="77"/>
<source>C Array</source>
<location filename="show_packet_bytes_dialog.cpp" line="72"/>
<source>Base64</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.cpp" line="73"/>
<source>Compressed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.cpp" line="74"/>
<source>ROT13</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.cpp" line="78"/>
<source>EBCDIC</source>
<source>ASCII</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.cpp" line="79"/>
<source>Hex Dump</source>
<source>C Array</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.cpp" line="80"/>
<source>HTML</source>
<source>EBCDIC</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.cpp" line="81"/>
<source>Image</source>
<source>Hex Dump</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.cpp" line="82"/>
<source>ISO 8859-1</source>
<source>HTML</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.cpp" line="83"/>
<source>Raw</source>
<source>Image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.cpp" line="84"/>
<source>UTF-8</source>
<source>ISO 8859-1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.cpp" line="85"/>
<source>Raw</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.cpp" line="86"/>
<source>UTF-8</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.cpp" line="87"/>
<source>YAML</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.cpp" line="89"/>
<location filename="show_packet_bytes_dialog.cpp" line="94"/>
<source>Print</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.cpp" line="92"/>
<location filename="show_packet_bytes_dialog.cpp" line="97"/>
<source>Copy</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.cpp" line="95"/>
<location filename="show_packet_bytes_dialog.cpp" line="100"/>
<source>Save as</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<location filename="show_packet_bytes_dialog.cpp" line="167"/>
<source>Displaying %Ln byte(s).</source>
<translation type="unfinished">
<numerusform>Displaying %Ln byte.</numerusform>
<numerusform>Displaying %Ln bytes.</numerusform>
</translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.cpp" line="183"/>
<location filename="show_packet_bytes_dialog.cpp" line="291"/>
<source>Save Selected Packet Bytes As</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>ShowPacketBytesTextEdit</name>
<message>
<location filename="show_packet_bytes_dialog.cpp" line="689"/>
<source>Show Selected</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="show_packet_bytes_dialog.cpp" line="693"/>
<source>Show All</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SimpleDialog</name>
<message>

View File

@ -45,6 +45,9 @@
#define UTF8_PLACE_OF_INTEREST_SIGN "\xe2\x8c\x98" /* 8984 / 0x2318 */
#define UTF8_SYMBOL_FOR_NULL "\xe2\x90\x80" /* 9216 / 0x2400 */
#define UTF8_SYMBOL_FOR_CARRIAGE_RETURN "\xe2\x90\x8d" /* 9229 / 0x240d */
#define UTF8_CHECK_MARK "\xe2\x9c\x93" /* 10003 / 0x2713 */
#define UTF8_BALLOT_X "\xe2\x9c\x97" /* 10007 / 0x2717 */
#define UTF8_LONG_RIGHTWARDS_ARROW "\xe2\x9f\xb6" /* 10230 / 0x27f6 */