"Fossies" - the Fresh Open Source Software Archive

Member "cutter-1.10.3/src/widgets/HexdumpWidget.cpp" (8 May 2020, 11923 Bytes) of package /linux/privat/cutter-1.10.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "HexdumpWidget.cpp" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.10.2_vs_1.10.3.

    1 #include "HexdumpWidget.h"
    2 #include "ui_HexdumpWidget.h"
    3 
    4 #include "common/Helpers.h"
    5 #include "common/Configuration.h"
    6 #include "common/TempConfig.h"
    7 #include "common/SyntaxHighlighter.h"
    8 #include "core/MainWindow.h"
    9 
   10 #include <QJsonObject>
   11 #include <QJsonArray>
   12 #include <QElapsedTimer>
   13 #include <QTextDocumentFragment>
   14 #include <QMenu>
   15 #include <QClipboard>
   16 #include <QScrollBar>
   17 #include <QInputDialog>
   18 #include <QShortcut>
   19 
   20 HexdumpWidget::HexdumpWidget(MainWindow *main, QAction *action) :
   21     MemoryDockWidget(MemoryWidgetType::Hexdump, main, action),
   22     ui(new Ui::HexdumpWidget)
   23 {
   24     ui->setupUi(this);
   25 
   26     setObjectName(main
   27                   ? main->getUniqueObjectName(getWidgetType())
   28                   : getWidgetType());
   29 
   30     ui->copyMD5->setIcon(QIcon(":/img/icons/copy.svg"));
   31     ui->copySHA1->setIcon(QIcon(":/img/icons/copy.svg"));
   32     ui->copySHA256->setIcon(QIcon(":/img/icons/copy.svg"));
   33     ui->copyCRC32->setIcon(QIcon(":/img/icons/copy.svg"));
   34 
   35 
   36     ui->splitter->setChildrenCollapsible(false);
   37 
   38     QToolButton *closeButton = new QToolButton;
   39     QIcon closeIcon = QIcon(":/img/icons/delete.svg");
   40     closeButton->setIcon(closeIcon);
   41     closeButton->setAutoRaise(true);
   42 
   43     ui->hexSideTab_2->setCornerWidget(closeButton);
   44     syntaxHighLighter = Config()->createSyntaxHighlighter(ui->hexDisasTextEdit->document());
   45 
   46     ui->openSideViewB->hide();  // hide button at startup since side view is visible
   47 
   48     connect(closeButton, &QToolButton::clicked, this, [this] {
   49         showSidePanel(false);
   50     });
   51 
   52     connect(ui->openSideViewB, &QToolButton::clicked, this, [this] {
   53         showSidePanel(true);
   54     });
   55 
   56     // Set placeholders for the line-edit components
   57     QString placeholder = tr("Select bytes to display information");
   58     ui->bytesMD5->setPlaceholderText(placeholder);
   59     ui->bytesEntropy->setPlaceholderText(placeholder);
   60     ui->bytesSHA1->setPlaceholderText(placeholder);
   61     ui->bytesSHA256->setPlaceholderText(placeholder);
   62     ui->bytesCRC32->setPlaceholderText(placeholder);
   63     ui->hexDisasTextEdit->setPlaceholderText(placeholder);
   64 
   65     setupFonts();
   66 
   67     ui->openSideViewB->setStyleSheet(""
   68                                      "QToolButton {"
   69                                      "   border : 0px;"
   70                                      "   padding : 0px;"
   71                                      "   margin : 0px;"
   72                                      "}"
   73                                      "QToolButton:hover {"
   74                                      "  border : 1px solid;"
   75                                      "  border-width : 1px;"
   76                                      "  border-color : #3daee9"
   77                                      "}");
   78 
   79     setWindowTitle(getWindowTitle());
   80 
   81     refreshDeferrer = createReplacingRefreshDeferrer<RVA>(false, [this](const RVA *offset) {
   82         refresh(offset ? *offset : RVA_INVALID);
   83     });
   84 
   85     this->ui->hexTextView->addAction(&syncAction);
   86 
   87     connect(Config(), &Configuration::fontsUpdated, this, &HexdumpWidget::fontsUpdated);
   88     connect(Core(), &CutterCore::refreshAll, this, [this]() { refresh(); });
   89     connect(Core(), &CutterCore::instructionChanged, this, [this]() { refresh(); });
   90     connect(Core(), &CutterCore::stackChanged, this, [this]() { refresh(); });
   91     connect(Core(), &CutterCore::registersChanged, this, [this]() { refresh(); });
   92 
   93     connect(seekable, &CutterSeekable::seekableSeekChanged, this, &HexdumpWidget::onSeekChanged);
   94     connect(ui->hexTextView, &HexWidget::positionChanged, this, [this](RVA addr) {
   95         if (!sent_seek) {
   96             sent_seek = true;
   97             seekable->seek(addr);
   98             sent_seek = false;
   99         }
  100     });
  101     connect(ui->hexTextView, &HexWidget::selectionChanged, this, &HexdumpWidget::selectionChanged);
  102     connect(ui->hexSideTab_2, &QTabWidget::currentChanged, this, &HexdumpWidget::refreshSelectionInfo);
  103     ui->hexTextView->installEventFilter(this);
  104 
  105     initParsing();
  106     selectHexPreview();
  107 
  108     // apply initial offset
  109     refresh(seekable->getOffset());
  110 }
  111 
  112 void HexdumpWidget::onSeekChanged(RVA addr)
  113 {
  114     if (sent_seek) {
  115         sent_seek = false;
  116         return;
  117     }
  118     refresh(addr);
  119 }
  120 
  121 HexdumpWidget::~HexdumpWidget() {}
  122 
  123 QString HexdumpWidget::getWidgetType()
  124 {
  125     return "Hexdump";
  126 }
  127 
  128 void HexdumpWidget::refresh()
  129 {
  130     refresh(RVA_INVALID);
  131 }
  132 
  133 void HexdumpWidget::refresh(RVA addr)
  134 {
  135     if (!refreshDeferrer->attemptRefresh(addr == RVA_INVALID ? nullptr : new RVA(addr))) {
  136         return;
  137     }
  138     sent_seek = true;
  139     if (addr != RVA_INVALID) {
  140         ui->hexTextView->seek(addr);
  141     } else {
  142         ui->hexTextView->refresh();
  143         refreshSelectionInfo();
  144     }
  145     sent_seek = false;
  146 }
  147 
  148 
  149 void HexdumpWidget::initParsing()
  150 {
  151     // Fill the plugins combo for the hexdump sidebar
  152     ui->parseArchComboBox->insertItems(0, Core()->getAsmPluginNames());
  153 
  154     ui->parseEndianComboBox->setCurrentIndex(Core()->getConfigb("cfg.bigendian") ? 1 : 0);
  155 }
  156 
  157 void HexdumpWidget::selectionChanged(HexWidget::Selection selection)
  158 {
  159     if (selection.empty) {
  160         clearParseWindow();
  161     } else {
  162         updateParseWindow(selection.startAddress, selection.endAddress - selection.startAddress + 1);
  163     }
  164 }
  165 
  166 void HexdumpWidget::on_parseArchComboBox_currentTextChanged(const QString &/*arg1*/)
  167 {
  168     refreshSelectionInfo();
  169 }
  170 
  171 void HexdumpWidget::on_parseBitsComboBox_currentTextChanged(const QString &/*arg1*/)
  172 {
  173     refreshSelectionInfo();
  174 }
  175 
  176 void HexdumpWidget::setupFonts()
  177 {
  178     QFont font = Config()->getFont();
  179     ui->hexDisasTextEdit->setFont(font);
  180     ui->hexTextView->setMonospaceFont(font);
  181 }
  182 
  183 void HexdumpWidget::refreshSelectionInfo()
  184 {
  185     selectionChanged(ui->hexTextView->getSelection());
  186 }
  187 
  188 void HexdumpWidget::fontsUpdated()
  189 {
  190     setupFonts();
  191 }
  192 
  193 void HexdumpWidget::clearParseWindow()
  194 {
  195     ui->hexDisasTextEdit->setPlainText("");
  196     ui->bytesEntropy->setText("");
  197     ui->bytesMD5->setText("");
  198     ui->bytesSHA1->setText("");
  199     ui->bytesSHA256->setText("");
  200     ui->bytesCRC32->setText("");
  201 }
  202 
  203 void HexdumpWidget::showSidePanel(bool show)
  204 {
  205     ui->hexSideTab_2->setVisible(show);
  206     ui->openSideViewB->setHidden(show);
  207     if (show) {
  208         refreshSelectionInfo();
  209     }
  210 }
  211 
  212 QString HexdumpWidget::getWindowTitle() const
  213 {
  214     return tr("Hexdump");
  215 }
  216 
  217 void HexdumpWidget::updateParseWindow(RVA start_address, int size)
  218 {
  219     if (!ui->hexSideTab_2->isVisible()) {
  220         return;
  221     }
  222 
  223     if (ui->hexSideTab_2->currentIndex() == 0) {
  224         // scope for TempConfig
  225 
  226         // Get selected combos
  227         QString arch = ui->parseArchComboBox->currentText();
  228         QString bits = ui->parseBitsComboBox->currentText();
  229         QString selectedCommand = "";
  230         QString commandResult = "";
  231         bool bigEndian = ui->parseEndianComboBox->currentIndex() == 1;
  232 
  233         TempConfig tempConfig;
  234         tempConfig
  235         .set("asm.arch", arch)
  236         .set("asm.bits", bits)
  237         .set("cfg.bigendian", bigEndian);
  238 
  239         switch (ui->parseTypeComboBox->currentIndex()) {
  240         case 0: // Disassembly
  241             selectedCommand = "pda";
  242             break;
  243         case 1: // String
  244             selectedCommand = "pcs";
  245             break;
  246         case 2: // Assembler
  247             selectedCommand = "pca";
  248             break;
  249         case 3: // C byte array
  250             selectedCommand = "pc";
  251             break;
  252         case 4: // C half-word
  253             selectedCommand = "pch";
  254             break;
  255         case 5: // C word
  256             selectedCommand = "pcw";
  257             break;
  258         case 6: // C dword
  259             selectedCommand = "pcd";
  260             break;
  261         case 7: // Python
  262             selectedCommand = "pcp";
  263             break;
  264         case 8: // JSON
  265             selectedCommand = "pcj";
  266             break;
  267         case 9: // JavaScript
  268             selectedCommand = "pcJ";
  269             break;
  270         case 10: // Yara
  271             selectedCommand = "pcy";
  272             break;
  273         }
  274         ui->hexDisasTextEdit->setPlainText(selectedCommand != "" ? Core()->cmdRawAt(QString("%1 %2")
  275                                                                     .arg(selectedCommand)
  276                                                                     .arg(size)
  277                                                                     , start_address) : "");
  278     } else {
  279         // Fill the information tab hashes and entropy
  280         ui->bytesMD5->setText(Core()->cmdRawAt(QString("ph md5 %1").arg(size), start_address).trimmed());
  281         ui->bytesSHA1->setText(Core()->cmdRawAt(QString("ph sha1 %1").arg(size), start_address).trimmed());
  282         ui->bytesSHA256->setText(Core()->cmdRawAt(QString("ph sha256 %1").arg(size), start_address).trimmed());
  283         ui->bytesCRC32->setText(Core()->cmdRawAt(QString("ph crc32 %1").arg(size), start_address).trimmed());
  284         ui->bytesEntropy->setText(Core()->cmdRawAt(QString("ph entropy %1").arg(size), start_address).trimmed());
  285         ui->bytesMD5->setCursorPosition(0);
  286         ui->bytesSHA1->setCursorPosition(0);
  287         ui->bytesSHA256->setCursorPosition(0);
  288         ui->bytesCRC32->setCursorPosition(0);
  289     }
  290 }
  291 
  292 void HexdumpWidget::on_parseTypeComboBox_currentTextChanged(const QString &)
  293 {
  294     if (ui->parseTypeComboBox->currentIndex() == 0) {
  295         ui->hexSideFrame_2->show();
  296     } else {
  297         ui->hexSideFrame_2->hide();
  298     }
  299     refreshSelectionInfo();
  300 }
  301 
  302 void HexdumpWidget::on_parseEndianComboBox_currentTextChanged(const QString &)
  303 {
  304     refreshSelectionInfo();
  305 }
  306 
  307 void HexdumpWidget::on_hexSideTab_2_currentChanged(int /*index*/)
  308 {
  309     /*
  310     if (index == 2) {
  311         // Add data to HTML Polar functions graph
  312         QFile html(":/html/bar.html");
  313         if(!html.open(QIODevice::ReadOnly)) {
  314             QMessageBox::information(0,"error",html.errorString());
  315         }
  316         QString code = html.readAll();
  317         html.close();
  318         this->histoWebView->setHtml(code);
  319         this->histoWebView->show();
  320     } else {
  321         this->histoWebView->hide();
  322     }
  323     */
  324 }
  325 
  326 
  327 void HexdumpWidget::resizeEvent(QResizeEvent *event)
  328 {
  329     // Heuristics to hide sidebar when it hides the content of the hexdump. 600px looks just "okay"
  330     // Only applied when widget width is decreased to avoid unwanted behavior
  331     if (event->oldSize().width() > event->size().width() && event->size().width() < 600) {
  332         showSidePanel(false);
  333     }
  334     QDockWidget::resizeEvent(event);
  335     refresh();
  336 }
  337 
  338 QWidget *HexdumpWidget::widgetToFocusOnRaise()
  339 {
  340     return ui->hexTextView;
  341 }
  342 
  343 void HexdumpWidget::on_copyMD5_clicked()
  344 {
  345     QString md5 = ui->bytesMD5->text();
  346     QClipboard *clipboard = QApplication::clipboard();
  347     clipboard->setText(md5);
  348     Core()->message("MD5 copied to clipboard: " + md5);
  349 }
  350 
  351 void HexdumpWidget::on_copySHA1_clicked()
  352 {
  353     QString sha1 = ui->bytesSHA1->text();
  354     QClipboard *clipboard = QApplication::clipboard();
  355     clipboard->setText(sha1);
  356     Core()->message("SHA1 copied to clipboard: " + sha1);
  357 }
  358 
  359 void HexdumpWidget::on_copySHA256_clicked()
  360 {
  361     QString sha256 = ui->bytesSHA256->text();
  362     QClipboard *clipboard = QApplication::clipboard();
  363     clipboard->setText(sha256);
  364     Core()->message("SHA256 copied to clipboard: " + sha256);
  365 }
  366 
  367 void HexdumpWidget::on_copyCRC32_clicked()
  368 {
  369     QString crc32 = ui->bytesCRC32->text();
  370     QClipboard *clipboard = QApplication::clipboard();
  371     clipboard->setText(crc32);
  372     Core()->message("CRC32 copied to clipboard: " + crc32);
  373 }
  374 
  375 void HexdumpWidget::selectHexPreview()
  376 {
  377     // Pre-select arch and bits in the hexdump sidebar
  378     QString arch = Core()->getConfig("asm.arch");
  379     QString bits = Core()->getConfig("asm.bits");
  380 
  381     if (ui->parseArchComboBox->findText(arch) != -1) {
  382         ui->parseArchComboBox->setCurrentIndex(ui->parseArchComboBox->findText(arch));
  383     }
  384 
  385     if (ui->parseBitsComboBox->findText(bits) != -1) {
  386         ui->parseBitsComboBox->setCurrentIndex(ui->parseBitsComboBox->findText(bits));
  387     }
  388 }