cutter/src/widgets/HexdumpWidget.cpp

967 lines
27 KiB
C++
Raw Normal View History

#include "HexdumpWidget.h"
#include "ui_HexdumpWidget.h"
#include "DisassemblerGraphView.h"
2017-10-01 19:09:42 +00:00
#include "MainWindow.h"
#include "utils/Helpers.h"
#include <QTemporaryFile>
#include <QFontDialog>
#include <QScrollBar>
#include <QClipboard>
#include <QShortcut>
#include <QMenu>
#include <QFont>
#include <QUrl>
#include <QSettings>
#include <cassert>
2017-11-17 12:41:30 +00:00
const int HexdumpWidget::linesMarginMin = 32;
const int HexdumpWidget::linesMarginDefault = 48;
const int HexdumpWidget::linesMarginMax = 64;
2017-11-15 21:42:39 +00:00
HexdumpWidget::HexdumpWidget(QWidget *parent, Qt::WindowFlags flags) :
QDockWidget(parent, flags),
2017-11-15 21:42:39 +00:00
ui(new Ui::HexdumpWidget)
{
ui->setupUi(this);
//this->on_actionSettings_menu_1_triggered();
// Setup hex highlight
//connect(ui->hexHexText, SIGNAL(cursorPositionChanged()), this, SLOT(highlightHexCurrentLine()));
//highlightHexCurrentLine();
2017-11-19 21:21:02 +00:00
int margin = static_cast<int>(ui->hexOffsetText->document()->documentMargin());
ui->offsetHeaderLabel->setContentsMargins(margin, 0, margin, 0);
margin = static_cast<int>(ui->hexHexText->document()->documentMargin());
ui->hexHeaderLabel->setContentsMargins(margin, 0, margin, 0);
margin = static_cast<int>(ui->hexASCIIText->document()->documentMargin());
ui->asciiHeaderLabel->setContentsMargins(margin, 0, margin, 0);
setupFonts();
2017-11-19 21:21:02 +00:00
updateHeaders();
// Set hexdump context menu
2017-11-15 21:42:39 +00:00
ui->hexHexText->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->hexHexText, SIGNAL(customContextMenuRequested(const QPoint &)),
this, SLOT(showHexdumpContextMenu(const QPoint &)));
2017-11-15 21:42:39 +00:00
ui->hexASCIIText->setContextMenuPolicy(Qt::CustomContextMenu);
connect(ui->hexASCIIText, SIGNAL(customContextMenuRequested(const QPoint &)),
this, SLOT(showHexASCIIContextMenu(const QPoint &)));
setupScrollSync();
// Control Disasm and Hex scroll to add more contents
2017-11-17 12:41:30 +00:00
connectScroll(false);
connect(Config(), SIGNAL(fontsUpdated()), this, SLOT(fontsUpdated()));
2017-11-15 21:42:39 +00:00
connect(Core(), SIGNAL(seekChanged(RVA)), this, SLOT(on_seekChanged(RVA)));
connect(Core(), SIGNAL(raisePrioritizedMemoryWidget(CutterCore::MemoryWidgetType)), this, SLOT(raisePrioritizedMemoryWidget(CutterCore::MemoryWidgetType)));
connect(this, &QDockWidget::visibilityChanged, this, [](bool visibility) {
if (visibility)
{
Core()->setMemoryWidgetPriority(CutterCore::MemoryWidgetType::Hexdump);
}
});
connect(Core(), &CutterCore::refreshAll, this, [this]() {
refresh(Core()->getOffset());
});
fillPlugins();
}
HexdumpWidget::HexdumpWidget(const QString &title, QWidget *parent, Qt::WindowFlags flags)
: HexdumpWidget(parent, flags)
{
setWindowTitle(title);
}
void HexdumpWidget::setupScrollSync()
{
/*
* For some reason, QScrollBar::valueChanged is not emitted when
* the scrolling happened from moving the cursor beyond the visible content,
* so QPlainTextEdit::cursorPositionChanged has to be connected as well.
*/
auto offsetHexFunc = [this]() {
ui->hexHexText->verticalScrollBar()->setValue(ui->hexOffsetText->verticalScrollBar()->value());
};
auto offsetASCIIFunc = [this]() {
ui->hexASCIIText->verticalScrollBar()->setValue(ui->hexOffsetText->verticalScrollBar()->value());
};
connect(ui->hexOffsetText->verticalScrollBar(), &QScrollBar::valueChanged, ui->hexHexText->verticalScrollBar(), offsetHexFunc);
connect(ui->hexOffsetText, &QPlainTextEdit::cursorPositionChanged, ui->hexHexText->verticalScrollBar(), offsetHexFunc);
connect(ui->hexOffsetText->verticalScrollBar(), &QScrollBar::valueChanged, ui->hexASCIIText->verticalScrollBar(), offsetASCIIFunc);
connect(ui->hexOffsetText, &QPlainTextEdit::cursorPositionChanged, ui->hexASCIIText->verticalScrollBar(), offsetASCIIFunc);
auto hexOffsetFunc = [this]() {
ui->hexOffsetText->verticalScrollBar()->setValue(ui->hexHexText->verticalScrollBar()->value());
};
auto hexASCIIFunc = [this]() {
ui->hexASCIIText->verticalScrollBar()->setValue(ui->hexHexText->verticalScrollBar()->value());
};
connect(ui->hexHexText->verticalScrollBar(), &QScrollBar::valueChanged, ui->hexOffsetText->verticalScrollBar(), hexOffsetFunc);
connect(ui->hexHexText, &QPlainTextEdit::cursorPositionChanged, ui->hexOffsetText->verticalScrollBar(), hexOffsetFunc);
connect(ui->hexHexText->verticalScrollBar(), &QScrollBar::valueChanged, ui->hexASCIIText->verticalScrollBar(), hexASCIIFunc);
connect(ui->hexHexText, &QPlainTextEdit::cursorPositionChanged, ui->hexASCIIText->verticalScrollBar(), hexASCIIFunc);
auto asciiOffsetFunc = [this]() {
ui->hexOffsetText->verticalScrollBar()->setValue(ui->hexASCIIText->verticalScrollBar()->value());
};
auto asciiHexFunc = [this]() {
ui->hexHexText->verticalScrollBar()->setValue(ui->hexASCIIText->verticalScrollBar()->value());
};
connect(ui->hexASCIIText->verticalScrollBar(), &QScrollBar::valueChanged, ui->hexOffsetText->verticalScrollBar(), asciiOffsetFunc);
connect(ui->hexASCIIText, &QPlainTextEdit::cursorPositionChanged, ui->hexOffsetText->verticalScrollBar(), asciiOffsetFunc);
connect(ui->hexASCIIText->verticalScrollBar(), &QScrollBar::valueChanged, ui->hexHexText->verticalScrollBar(), asciiHexFunc);
connect(ui->hexASCIIText, &QPlainTextEdit::cursorPositionChanged, ui->hexHexText->verticalScrollBar(), asciiHexFunc);
}
void HexdumpWidget::on_seekChanged(RVA addr)
{
refresh(addr);
}
void HexdumpWidget::raisePrioritizedMemoryWidget(CutterCore::MemoryWidgetType type)
{
if (type == CutterCore::MemoryWidgetType::Hexdump)
{
raise();
}
}
2017-11-17 12:41:30 +00:00
void HexdumpWidget::connectScroll(bool disconnect)
{
if (disconnect)
{
2017-11-19 14:09:48 +00:00
this->disconnect(ui->hexASCIIText->verticalScrollBar(), &QScrollBar::valueChanged, this,
&HexdumpWidget::adjustHexdumpLines);
this->disconnect(ui->hexASCIIText, &QPlainTextEdit::cursorPositionChanged, this,
&HexdumpWidget::adjustHexdumpLines);
2017-11-17 12:41:30 +00:00
}
else
{
2017-11-19 14:09:48 +00:00
connect(ui->hexASCIIText->verticalScrollBar(), &QScrollBar::valueChanged, this,
&HexdumpWidget::adjustHexdumpLines);
connect(ui->hexASCIIText, &QPlainTextEdit::cursorPositionChanged, this, &HexdumpWidget::adjustHexdumpLines);
2017-11-17 12:41:30 +00:00
}
}
HexdumpWidget::~HexdumpWidget() {}
/*
* Text highlight functions
*/
void HexdumpWidget::highlightHexCurrentLine()
{
QList<QTextEdit::ExtraSelection> extraSelections;
2017-11-15 21:42:39 +00:00
if (!ui->hexHexText->isReadOnly())
2017-04-09 19:55:06 +00:00
{
QTextEdit::ExtraSelection selection;
QColor lineColor = QColor(190, 144, 212);
selection.format.setBackground(lineColor);
selection.format.setProperty(QTextFormat::FullWidthSelection, true);
2017-11-15 21:42:39 +00:00
selection.cursor = ui->hexHexText->textCursor();
selection.cursor.clearSelection();
extraSelections.append(selection);
}
2017-11-15 21:42:39 +00:00
QTextCursor cursor = ui->hexHexText->textCursor();
cursor.select(QTextCursor::WordUnderCursor);
QTextEdit::ExtraSelection currentWord;
QColor blueColor = QColor(Qt::blue).lighter(160);
currentWord.format.setBackground(blueColor);
currentWord.cursor = cursor;
extraSelections.append(currentWord);
2017-11-15 21:42:39 +00:00
ui->hexHexText->setExtraSelections(extraSelections);
highlightHexWords(cursor.selectedText());
}
void HexdumpWidget::highlightHexWords(const QString &str)
{
QString searchString = str;
2017-11-15 21:42:39 +00:00
QTextDocument *document = ui->hexHexText->document();
document->undo();
QTextCursor highlightCursor(document);
QTextCursor cursor(document);
cursor.beginEditBlock();
QColor blueColor = QColor(Qt::blue).lighter(160);
QTextCharFormat plainFormat(highlightCursor.charFormat());
QTextCharFormat colorFormat = plainFormat;
colorFormat.setBackground(blueColor);
2017-04-09 19:55:06 +00:00
while (!highlightCursor.isNull() && !highlightCursor.atEnd())
{
highlightCursor = document->find(searchString, highlightCursor, QTextDocument::FindWholeWords);
2017-04-09 19:55:06 +00:00
if (!highlightCursor.isNull())
{
highlightCursor.movePosition(QTextCursor::EndOfWord, QTextCursor::KeepAnchor);
highlightCursor.mergeCharFormat(colorFormat);
}
}
cursor.endEditBlock();
}
void HexdumpWidget::refresh(RVA addr)
2017-04-09 19:55:06 +00:00
{
2017-11-19 21:21:02 +00:00
updateHeaders();
if (addr == RVA_INVALID)
2017-04-09 19:55:06 +00:00
{
2017-11-15 21:42:39 +00:00
addr = Core()->getOffset();
}
2017-11-18 12:56:48 +00:00
int visibleLines = qhelpers::getMaxFullyDisplayedLines(ui->hexHexText);
2017-11-15 21:42:39 +00:00
RCoreLocked lcore = Core()->core();
2017-11-17 12:41:30 +00:00
connectScroll(true);
2017-11-16 21:12:44 +00:00
int cols = lcore->print->cols;
2017-11-18 12:56:48 +00:00
RVA marginBytes = static_cast<RVA>(linesMarginDefault) * cols;
// lower bound of 0
if (addr > marginBytes)
{
topOffset = addr - marginBytes;
topOffset = (topOffset / cols) * cols; // align
}
else
{
topOffset = 0;
}
2017-11-17 12:41:30 +00:00
int fetchLines = visibleLines + linesMarginDefault * 2;
2017-11-16 21:12:44 +00:00
RVA bytes = static_cast<RVA>(fetchLines) * cols;
2017-11-18 12:56:48 +00:00
// upper bound of UT64_MAX
RVA bytesLeft = UT64_MAX - topOffset;
if (bytes > bytesLeft)
{
bottomOffset = UT64_MAX;
topOffset = bottomOffset - bytes;
}
else
{
bottomOffset = topOffset + bytes;
}
2017-11-16 21:12:44 +00:00
auto hexdump = fetchHexdump(topOffset, bytes);
2017-11-16 21:12:44 +00:00
ui->hexOffsetText->setPlainText(hexdump[0]);
ui->hexHexText->setPlainText(hexdump[1]);
ui->hexASCIIText->setPlainText(hexdump[2]);
2017-11-19 14:05:47 +00:00
int seekLine = static_cast<int>((addr - topOffset) / cols);
// Move cursors to desired address
2017-11-15 21:42:39 +00:00
QTextCursor cur = ui->hexOffsetText->textCursor();
2017-11-16 21:12:44 +00:00
cur.movePosition(QTextCursor::Start);
2017-11-19 14:05:47 +00:00
cur.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, seekLine);
2017-11-16 21:12:44 +00:00
ui->hexOffsetText->setTextCursor(cur);
2017-11-19 14:05:47 +00:00
cur = ui->hexHexText->textCursor();
cur.movePosition(QTextCursor::Start);
cur.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, seekLine);
ui->hexHexText->setTextCursor(cur);
cur = ui->hexASCIIText->textCursor();
cur.movePosition(QTextCursor::Start);
cur.movePosition(QTextCursor::Down, QTextCursor::MoveAnchor, seekLine);
ui->hexASCIIText->setTextCursor(cur);
ui->hexOffsetText->verticalScrollBar()->setValue(seekLine);
ui->hexHexText->verticalScrollBar()->setValue(seekLine);
ui->hexASCIIText->verticalScrollBar()->setValue(seekLine);
2017-11-17 12:41:30 +00:00
2017-11-18 12:56:48 +00:00
connectScroll(false);
2017-11-17 12:41:30 +00:00
}
void HexdumpWidget::appendHexdumpLines(int lines, bool top)
{
connectScroll(true);
int cols = Core()->getConfigi("hex.cols");
RVA bytes = static_cast<RVA>(lines) * cols;
if (top)
{
2017-11-18 12:56:48 +00:00
if (bytes > topOffset)
{
bytes = topOffset;
if (bytes == 0)
{
connectScroll(false);
return;
}
}
2017-11-17 12:41:30 +00:00
topOffset -= bytes;
auto hexdump = fetchHexdump(topOffset, bytes);
int scroll = ui->hexASCIIText->verticalScrollBar()->value();
QTextCursor cur = ui->hexOffsetText->textCursor();
cur.movePosition(QTextCursor::Start);
cur.insertText(hexdump[0]);
cur = ui->hexHexText->textCursor();
cur.movePosition(QTextCursor::Start);
cur.insertText(hexdump[1]);
cur = ui->hexASCIIText->textCursor();
cur.movePosition(QTextCursor::Start);
cur.insertText(hexdump[2]);
int actualLines = static_cast<int>(bytes / cols);
2017-11-18 12:56:48 +00:00
ui->hexOffsetText->verticalScrollBar()->setValue(actualLines + scroll);
ui->hexHexText->verticalScrollBar()->setValue(actualLines + scroll);
2017-11-17 12:41:30 +00:00
ui->hexASCIIText->verticalScrollBar()->setValue(actualLines + scroll);
}
else
{
2017-11-18 12:56:48 +00:00
if (bytes > UT64_MAX - bottomOffset)
{
bytes = UT64_MAX - bottomOffset;
if (bytes == 0)
{
connectScroll(false);
return;
}
}
2017-11-17 12:41:30 +00:00
auto hexdump = fetchHexdump(bottomOffset, bytes);
bottomOffset += bytes;
QTextCursor cur = ui->hexOffsetText->textCursor();
cur.movePosition(QTextCursor::End);
cur.insertText(hexdump[0]);
cur = ui->hexHexText->textCursor();
cur.movePosition(QTextCursor::End);
cur.insertText(hexdump[1]);
cur = ui->hexASCIIText->textCursor();
cur.movePosition(QTextCursor::End);
cur.insertText(hexdump[2]);
}
2017-11-17 12:41:30 +00:00
connectScroll(false);
}
2017-11-17 12:41:30 +00:00
void HexdumpWidget::removeHexdumpLines(int lines, bool top)
{
connectScroll(true);
int cols = Core()->getConfigi("hex.cols");
std::array<QPlainTextEdit *, 3> edits = { ui->hexOffsetText, ui->hexHexText, ui->hexASCIIText };
int scroll = ui->hexASCIIText->verticalScrollBar()->value();
2017-11-18 12:56:48 +00:00
if (top)
2017-11-17 12:41:30 +00:00
{
2017-11-18 12:56:48 +00:00
for (QPlainTextEdit *edit : edits)
2017-11-17 12:41:30 +00:00
{
2017-11-18 12:56:48 +00:00
QTextCursor cur = edit->textCursor();
2017-11-17 12:41:30 +00:00
cur.movePosition(QTextCursor::Start);
cur.movePosition(QTextCursor::Down, QTextCursor::KeepAnchor, lines + 1);
2017-11-18 12:56:48 +00:00
cur.removeSelectedText();
2017-11-17 12:41:30 +00:00
}
2017-11-18 12:56:48 +00:00
topOffset += lines * cols;
ui->hexOffsetText->verticalScrollBar()->setValue(scroll - lines);
ui->hexHexText->verticalScrollBar()->setValue(scroll - lines);
ui->hexASCIIText->verticalScrollBar()->setValue(scroll - lines);
}
else
{
for (QPlainTextEdit *edit : edits)
2017-11-17 12:41:30 +00:00
{
2017-11-18 12:56:48 +00:00
QTextCursor cur = edit->textCursor();
2017-11-17 12:41:30 +00:00
cur.movePosition(QTextCursor::End);
cur.movePosition(QTextCursor::Up, QTextCursor::KeepAnchor, lines);
cur.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor);
cur.removeSelectedText();
}
2017-11-18 12:56:48 +00:00
bottomOffset -= lines * cols;
2017-11-17 12:41:30 +00:00
}
connectScroll(false);
}
2017-11-19 21:21:02 +00:00
void HexdumpWidget::updateHeaders()
{
int cols = Core()->getConfigi("hex.cols");
bool pairs = Core()->getConfigb("hex.pairs");
QString hexHeaderString;
QString asciiHeaderString;
QTextStream hexHeader(&hexHeaderString);
QTextStream asciiHeader(&asciiHeaderString);
hexHeader.setIntegerBase(16);
hexHeader.setNumberFlags(QTextStream::UppercaseDigits);
asciiHeader.setIntegerBase(16);
asciiHeader.setNumberFlags(QTextStream::UppercaseDigits);
for (int i=0; i<cols; i++)
{
if (i > 0 && ((pairs && !(i&1)) || !pairs))
{
hexHeader << " ";
}
hexHeader << " " << (i & 0xF);
asciiHeader << (i & 0xF);
}
hexHeader.flush();
asciiHeader.flush();
ui->hexHeaderLabel->setText(hexHeaderString);
ui->asciiHeaderLabel->setText(asciiHeaderString);
}
/*
* Content management functions
*/
void HexdumpWidget::fillPlugins()
{
// Fill the plugins combo for the hexdump sidebar
2017-11-15 21:42:39 +00:00
ui->hexArchComboBox_2->insertItems(0, Core()->getAsmPluginNames());
}
2017-11-16 21:12:44 +00:00
std::array<QString, 3> HexdumpWidget::fetchHexdump(RVA offset, RVA bytes)
2017-04-09 19:55:06 +00:00
{
2017-11-16 21:12:44 +00:00
QString hexdump = Core()->cmd(QString("px %1 @ %2").arg(QString::number(bytes), QString::number(offset)));
QString offsets;
QString hex;
QString ascii;
int ln = 0;
2017-11-16 21:12:44 +00:00
for (const QString &line : hexdump.split("\n"))
{
2017-11-17 12:41:30 +00:00
if (ln++ == 0 || line.trimmed().isEmpty())
{
continue;
}
2017-11-17 12:41:30 +00:00
int wc = 0;
for (const QString a : line.split(" "))
{
switch (wc++)
{
case 0:
offsets += a + "\n";
break;
case 1:
hex += a.trimmed() + "\n";
break;
case 2:
ascii += a + "\n";
break;
}
}
}
2017-11-16 21:12:44 +00:00
return { offsets, hex, ascii };
}
2017-11-19 14:09:48 +00:00
void HexdumpWidget::adjustHexdumpLines()
{
2017-11-15 21:42:39 +00:00
QScrollBar *sb = ui->hexASCIIText->verticalScrollBar();
2017-11-18 12:56:48 +00:00
int topMargin = sb->value() - sb->minimum();
int bottomMargin = sb->maximum() - sb->value();
2017-11-17 12:41:30 +00:00
if (topMargin < linesMarginMin)
{
int loadLines = linesMarginDefault - topMargin;
appendHexdumpLines(loadLines, true);
}
2017-11-17 12:41:30 +00:00
if(bottomMargin < linesMarginMin)
{
int loadLines = linesMarginDefault - bottomMargin;
appendHexdumpLines(loadLines, false);
}
2017-11-17 12:41:30 +00:00
if(topMargin > linesMarginMax)
{
int removeLines = topMargin - linesMarginDefault;
removeHexdumpLines(removeLines, true);
2017-04-09 19:55:06 +00:00
}
2017-11-17 12:41:30 +00:00
if(bottomMargin > linesMarginMax)
2017-04-09 19:55:06 +00:00
{
2017-11-17 12:41:30 +00:00
int removeLines = bottomMargin - linesMarginDefault;
removeHexdumpLines(removeLines, false);
}
}
2017-11-16 21:12:44 +00:00
void HexdumpWidget::on_hexHexText_selectionChanged()
{
// Get selected partsing type
QString parsing = ui->codeCombo_2->currentText();
// Get selected text
2017-11-15 21:42:39 +00:00
QTextCursor cursor(ui->hexHexText->textCursor());
QString sel_text = cursor.selectedText();
sel_text = sel_text.simplified().remove(" ");
//eprintf ("-- (((%s))) --\n", sel_text.toUtf8().constData());
2017-04-09 19:55:06 +00:00
if (sel_text == "")
{
2017-11-15 21:42:39 +00:00
ui->hexDisasTextEdit->setPlainText("");
ui->bytesEntropy->setText("");
ui->bytesMD5->setText("");
ui->bytesSHA1->setText("");
2017-04-09 19:55:06 +00:00
}
else
{
if (parsing == "Dissasembly")
{
// Get selected combos
QString arch = ui->hexArchComboBox_2->currentText();
QString bits = ui->hexBitsComboBox_2->currentText();
2017-11-15 21:42:39 +00:00
QString oarch = Core()->getConfig("asm.arch");
QString obits = Core()->getConfig("asm.bits");
2017-11-15 21:42:39 +00:00
Core()->setConfig("asm.arch", arch);
Core()->setConfig("asm.bits", bits);
QString str = Core()->cmd("pad " + sel_text);
ui->hexDisasTextEdit->setPlainText(str);
Core()->setConfig("asm.arch", oarch);
Core()->setConfig("asm.bits", obits);
//qDebug() << "Selected Arch: " << arch;
//qDebug() << "Selected Bits: " << bits;
//qDebug() << "Selected Text: " << sel_text;
}
// TODO: update on selection changes.. use cmd("pc "+len+"@"+off)
2017-04-09 19:55:06 +00:00
else if (parsing == "C byte array")
{
2017-11-15 21:42:39 +00:00
ui->hexDisasTextEdit->setPlainText(Core()->cmd("pc@x:" + sel_text));
2017-04-09 19:55:06 +00:00
}
else if (parsing == "C dword array")
{
2017-11-15 21:42:39 +00:00
ui->hexDisasTextEdit->setPlainText(Core()->cmd("pcw@x:" + sel_text));
2017-04-09 19:55:06 +00:00
}
else if (parsing == "C qword array")
{
2017-11-15 21:42:39 +00:00
ui->hexDisasTextEdit->setPlainText(Core()->cmd("pcq@x:" + sel_text));
2017-04-09 19:55:06 +00:00
}
else if (parsing == "Assembler")
{
2017-11-15 21:42:39 +00:00
ui->hexDisasTextEdit->setPlainText(Core()->cmd("pca@x:" + sel_text));
2017-04-09 19:55:06 +00:00
}
else if (parsing == "String")
{
2017-11-15 21:42:39 +00:00
ui->hexDisasTextEdit->setPlainText(Core()->cmd("pcs@x:" + sel_text));
2017-04-09 19:55:06 +00:00
}
else if (parsing == "JSON")
{
2017-11-15 21:42:39 +00:00
ui->hexDisasTextEdit->setPlainText(Core()->cmd("pcj@x:" + sel_text));
2017-04-09 19:55:06 +00:00
}
else if (parsing == "Javascript")
{
2017-11-15 21:42:39 +00:00
ui->hexDisasTextEdit->setPlainText(Core()->cmd("pcJ@x:" + sel_text));
2017-04-09 19:55:06 +00:00
}
else if (parsing == "Python")
{
2017-11-15 21:42:39 +00:00
ui->hexDisasTextEdit->setPlainText(Core()->cmd("pcp@x:" + sel_text));
}
// Fill the information tab hashes and entropy
2017-11-15 21:42:39 +00:00
ui->bytesMD5->setText(Core()->cmd("ph md5@x:" + sel_text).trimmed());
ui->bytesSHA1->setText(Core()->cmd("ph sha1@x:" + sel_text).trimmed());
ui->bytesEntropy->setText(Core()->cmd("ph entropy@x:" + sel_text).trimmed());
ui->bytesMD5->setCursorPosition(0);
ui->bytesSHA1->setCursorPosition(0);
}
}
void HexdumpWidget::on_hexArchComboBox_2_currentTextChanged(const QString &/*arg1*/)
{
2017-11-16 21:12:44 +00:00
on_hexHexText_selectionChanged();
}
void HexdumpWidget::on_hexBitsComboBox_2_currentTextChanged(const QString &/*arg1*/)
{
2017-11-16 21:12:44 +00:00
on_hexHexText_selectionChanged();
}
/*
* Context menu functions
*/
void HexdumpWidget::showHexdumpContextMenu(const QPoint &pt)
{
// Set Hexdump popup menu
2017-11-15 21:42:39 +00:00
QMenu *menu = ui->hexHexText->createStandardContextMenu();
menu->clear();
menu->addAction(ui->actionHexCopy_Hexpair);
menu->addAction(ui->actionHexCopy_ASCII);
menu->addAction(ui->actionHexCopy_Text);
menu->addSeparator();
2017-04-09 19:55:06 +00:00
QMenu *colSubmenu = menu->addMenu("Columns");
colSubmenu->addAction(ui->action4columns);
colSubmenu->addAction(ui->action8columns);
colSubmenu->addAction(ui->action16columns);
colSubmenu->addAction(ui->action32columns);
menu->addSeparator();
menu->addAction(ui->actionHexEdit);
menu->addAction(ui->actionHexPaste);
menu->addSeparator();
menu->addAction(ui->actionHexInsert_Hex);
menu->addAction(ui->actionHexInsert_String);
2017-11-15 21:42:39 +00:00
ui->hexHexText->setContextMenuPolicy(Qt::CustomContextMenu);
2017-11-15 21:42:39 +00:00
menu->exec(ui->hexHexText->mapToGlobal(pt));
delete menu;
}
void HexdumpWidget::showHexASCIIContextMenu(const QPoint &pt)
{
// Set Hex ASCII popup menu
2017-11-15 21:42:39 +00:00
QMenu *menu = ui->hexASCIIText->createStandardContextMenu();
menu->clear();
menu->addAction(ui->actionHexCopy_Hexpair);
menu->addAction(ui->actionHexCopy_ASCII);
menu->addAction(ui->actionHexCopy_Text);
menu->addSeparator();
2017-04-09 19:55:06 +00:00
QMenu *colSubmenu = menu->addMenu("Columns");
colSubmenu->addAction(ui->action4columns);
colSubmenu->addAction(ui->action8columns);
colSubmenu->addAction(ui->action16columns);
colSubmenu->addAction(ui->action32columns);
menu->addSeparator();
menu->addAction(ui->actionHexEdit);
menu->addAction(ui->actionHexPaste);
menu->addSeparator();
menu->addAction(ui->actionHexInsert_Hex);
menu->addAction(ui->actionHexInsert_String);
2017-11-15 21:42:39 +00:00
ui->hexASCIIText->setContextMenuPolicy(Qt::CustomContextMenu);
2017-11-15 21:42:39 +00:00
menu->exec(ui->hexASCIIText->mapToGlobal(pt));
delete menu;
}
2017-11-17 12:41:30 +00:00
void HexdumpWidget::setupFonts()
2017-04-09 19:55:06 +00:00
{
QFont font = Config()->getFont();
2017-11-19 21:21:02 +00:00
2017-11-15 21:42:39 +00:00
ui->hexOffsetText->setFont(font);
ui->hexHexText->setFont(font);
ui->hexASCIIText->setFont(font);
2017-11-19 21:21:02 +00:00
ui->offsetHeaderLabel->setFont(font);
ui->hexHeaderLabel->setFont(font);
ui->asciiHeaderLabel->setFont(font);
}
void HexdumpWidget::fontsUpdated()
{
setupFonts();
adjustHexdumpLines();
}
/*
* Actions callback functions
*/
void HexdumpWidget::on_actionHideHexdump_side_panel_triggered()
{
2017-04-09 19:55:06 +00:00
if (ui->hexSideTab_2->isVisible())
{
ui->hexSideTab_2->hide();
2017-04-09 19:55:06 +00:00
}
else
{
ui->hexSideTab_2->show();
}
}
/*void HexdumpWidget::on_actionSend_to_Notepad_triggered()
{
QTextCursor cursor = ui->disasTextEdit_2->textCursor();
QString text = cursor.selectedText();
2017-10-09 18:08:35 +00:00
// TODO
// this->main->sendToNotepad(text);
}*/
void HexdumpWidget::on_action8columns_triggered()
{
2017-11-15 21:42:39 +00:00
Core()->setConfig("hex.cols", 8);
refresh();
}
void HexdumpWidget::on_action16columns_triggered()
{
2017-11-15 21:42:39 +00:00
Core()->setConfig("hex.cols", 16);
refresh();
}
void HexdumpWidget::on_action4columns_triggered()
{
2017-11-15 21:42:39 +00:00
Core()->setConfig("hex.cols", 4);
refresh();
}
void HexdumpWidget::on_action32columns_triggered()
{
2017-11-15 21:42:39 +00:00
Core()->setConfig("hex.cols", 32);
refresh();
}
void HexdumpWidget::on_action64columns_triggered()
{
2017-11-15 21:42:39 +00:00
Core()->setConfig("hex.cols", 64);
refresh();
}
void HexdumpWidget::on_action2columns_triggered()
{
2017-11-15 21:42:39 +00:00
Core()->setConfig("hex.cols", 2);
refresh();
}
void HexdumpWidget::on_action1column_triggered()
{
2017-11-15 21:42:39 +00:00
Core()->setConfig("hex.cols", 1);
refresh();
}
void HexdumpWidget::on_codeCombo_2_currentTextChanged(const QString &arg1)
{
2017-04-09 19:55:06 +00:00
if (arg1 == "Dissasembly")
{
ui->hexSideFrame_2->show();
2017-11-15 21:42:39 +00:00
ui->hexDisasTextEdit->setPlainText(";; Select some bytes on the left\n;; to see them disassembled");
2017-04-09 19:55:06 +00:00
}
else
{
ui->hexSideFrame_2->hide();
2017-11-15 21:42:39 +00:00
ui->hexDisasTextEdit->setPlainText(";; Select some bytes on the left\n;; to see them parsed here");
}
}
QString HexdumpWidget::normalize_addr(QString addr)
2017-04-09 19:55:06 +00:00
{
2017-11-15 21:42:39 +00:00
QString base = Core()->cmd("s").split("0x")[1].trimmed();
int len = base.length();
2017-04-09 19:55:06 +00:00
if (len < 8)
{
int padding = 8 - len;
QString zero = "0";
QString zeroes = zero.repeated(padding);
QString s = "0x" + zeroes + base;
return s;
2017-04-09 19:55:06 +00:00
}
else
{
return addr.trimmed();
}
}
QString HexdumpWidget::normalizeAddr(QString addr)
2017-04-09 19:55:06 +00:00
{
QString base = addr.split("0x")[1].trimmed();
int len = base.length();
2017-04-09 19:55:06 +00:00
if (len < 8)
{
int padding = 8 - len;
QString zero = "0";
QString zeroes = zero.repeated(padding);
QString s = "0x" + zeroes + base;
return s;
2017-04-09 19:55:06 +00:00
}
else
{
return addr;
}
}
void HexdumpWidget::on_hexSideTab_2_currentChanged(int /*index*/)
{
/*
if (index == 2) {
// Add data to HTML Polar functions graph
QFile html(":/html/bar.html");
if(!html.open(QIODevice::ReadOnly)) {
QMessageBox::information(0,"error",html.errorString());
}
QString code = html.readAll();
html.close();
this->histoWebView->setHtml(code);
this->histoWebView->show();
} else {
this->histoWebView->hide();
}
*/
}
void HexdumpWidget::on_memSideToolButton_clicked()
{
2017-04-09 19:55:06 +00:00
if (ui->memSideToolButton->isChecked())
{
ui->hexSideTab_2->hide();
ui->memSideToolButton->setIcon(QIcon(":/img/icons/left_light.svg"));
2017-04-09 19:55:06 +00:00
}
else
{
ui->hexSideTab_2->show();
ui->memSideToolButton->setIcon(QIcon(":/img/icons/right_light.svg"));
}
}
void HexdumpWidget::resizeEvent(QResizeEvent *event)
2017-04-09 19:55:06 +00:00
{
QDockWidget::resizeEvent(event);
2017-11-19 14:09:48 +00:00
adjustHexdumpLines();
}
void HexdumpWidget::wheelEvent(QWheelEvent* event)
{
if( Qt::ControlModifier == event->modifiers() )
{
const QPoint numDegrees = event->angleDelta() / 8;
if(!numDegrees.isNull())
{
const QPoint numSteps = numDegrees / 15;
if( 0 != numSteps.y() )
{
if(numSteps.y() > 0)
{
zoomIn(1);
}
else if( numSteps.y() < 0 )
{
zoomOut(1);
}
}
}
event->accept();
return;
}
event->ignore();
}
void HexdumpWidget::on_copyMD5_clicked()
{
QString md5 = ui->bytesMD5->text();
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(md5);
2017-10-09 18:08:35 +00:00
// FIXME
// this->main->addOutput("MD5 copied to clipboard: " + md5);
}
void HexdumpWidget::on_copySHA1_clicked()
{
QString sha1 = ui->bytesSHA1->text();
QClipboard *clipboard = QApplication::clipboard();
clipboard->setText(sha1);
2017-10-09 18:08:35 +00:00
// FIXME
// this->main->addOutput("SHA1 copied to clipboard: " + sha1);
}
void HexdumpWidget::selectHexPreview()
2017-04-09 19:55:06 +00:00
{
// Pre-select arch and bits in the hexdump sidebar
2017-11-15 21:42:39 +00:00
QString arch = Core()->cmd("e asm.arch").trimmed();
QString bits = Core()->cmd("e asm.bits").trimmed();
//int arch_index = ui->hexArchComboBox_2->findText(arch);
2017-04-09 19:55:06 +00:00
if (ui->hexArchComboBox_2->findText(arch) != -1)
{
ui->hexArchComboBox_2->setCurrentIndex(ui->hexArchComboBox_2->findText(arch));
}
//int bits_index = ui->hexBitsComboBox_2->findText(bits);
2017-04-09 19:55:06 +00:00
if (ui->hexBitsComboBox_2->findText(bits) != -1)
{
ui->hexBitsComboBox_2->setCurrentIndex(ui->hexBitsComboBox_2->findText(bits));
}
}
2017-04-05 09:35:19 +00:00
void HexdumpWidget::showOffsets(bool show)
{
if (show)
{
2017-11-15 21:42:39 +00:00
ui->hexOffsetText->show();
Core()->setConfig("asm.offset", 1);
}
else
{
2017-11-15 21:42:39 +00:00
ui->hexOffsetText->hide();
Core()->setConfig("asm.offset", 0);
}
}
void HexdumpWidget::zoomIn(int range)
{
2017-11-15 21:42:39 +00:00
ui->hexOffsetText->zoomIn(range);
ui->hexASCIIText->zoomIn(range);
ui->hexHexText->zoomIn(range);
}
void HexdumpWidget::zoomOut(int range)
{
2017-11-15 21:42:39 +00:00
ui->hexOffsetText->zoomOut(range);
ui->hexASCIIText->zoomOut(range);
ui->hexHexText->zoomOut(range);
}