diff --git a/src/CutterApplication.cpp b/src/CutterApplication.cpp index 53f15bfe..d54e0254 100644 --- a/src/CutterApplication.cpp +++ b/src/CutterApplication.cpp @@ -101,7 +101,23 @@ CutterApplication::CutterApplication(int &argc, char **argv) : QApplication(argc mainWindow->displayNewFileDialog(); } else { // filename specified as positional argument - mainWindow->openNewFile(args[0], analLevelSpecified ? analLevel : -1); + InitialOptions options; + options.filename = args[0]; + if (analLevelSpecified) { + switch (analLevel) { + case 0: + default: + options.analCmd = {}; + break; + case 1: + options.analCmd = { "aaa" }; + break; + case 2: + options.analCmd = { "aaaa" }; + break; + } + } + mainWindow->openNewFile(options, analLevelSpecified); } // Load plugins @@ -130,7 +146,9 @@ bool CutterApplication::event(QEvent *e) QString fileName = openEvent->file(); m_FileAlreadyDropped = true; mainWindow->closeNewFileDialog(); - mainWindow->openNewFile(fileName, -1); + InitialOptions options; + options.filename = fileName; + mainWindow->openNewFile(options); } } } diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index dd83723f..ca9f0a50 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -312,25 +312,27 @@ void MainWindow::addExtraWidget(QDockWidget *extraDock) restoreExtraDock.restoreWidth(extraDock->widget()); } -void MainWindow::openNewFile(const QString &fn, int analLevel, QList advancedOptions, const QString &shellcode) +void MainWindow::openNewFile(InitialOptions options, bool skipOptionsDialog) { - setFilename(fn); + setFilename(options.filename); /* Prompt to load filename.r2 script */ - QString script = QString("%1.r2").arg(this->filename); - QString loadScript; - if (r_file_exists(script.toStdString().data())) { - QMessageBox mb; - mb.setWindowTitle(tr("Script loading")); - mb.setText(tr("Do you want to load the '%1' script?").arg(script)); - mb.setStandardButtons(QMessageBox::Yes | QMessageBox::No); - if (mb.exec() == QMessageBox::Yes) { - loadScript = script; + if (options.script.isEmpty()) { + QString script = QString("%1.r2").arg(this->filename); + QString loadScript; + if (r_file_exists(script.toStdString().data())) { + QMessageBox mb; + mb.setWindowTitle(tr("Script loading")); + mb.setText(tr("Do you want to load the '%1' script?").arg(script)); + mb.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + if (mb.exec() == QMessageBox::Yes) { + loadScript = script; + } } } /* Show analysis options dialog */ - displayAnalysisOptionsDialog(analLevel, advancedOptions, loadScript, shellcode); + displayInitialOptionsDialog(options, skipOptionsDialog); } void MainWindow::openNewFileFailed() @@ -361,16 +363,15 @@ void MainWindow::closeNewFileDialog() newFileDialog = nullptr; } -void MainWindow::displayAnalysisOptionsDialog(int analLevel, QList advancedOptions, const QString &script, const QString &shellcode) +void MainWindow::displayInitialOptionsDialog(const InitialOptions &options, bool skipOptionsDialog) { - InitialOptionsDialog *o = new InitialOptionsDialog(this); + auto o = new InitialOptionsDialog(this); o->setAttribute(Qt::WA_DeleteOnClose); - o->setInitialScript(script); - o->setShellcode(shellcode); + o->loadOptions(options); o->show(); - if (analLevel >= 0) { - o->setupAndStartAnalysis(analLevel, advancedOptions); + if (skipOptionsDialog) { + o->setupAndStartAnalysis(); } } @@ -929,7 +930,7 @@ void MainWindow::on_actionRefresh_Panels_triggered() void MainWindow::on_actionAnalyze_triggered() { - displayAnalysisOptionsDialog(-1, QList(), nullptr); + // TODO: implement this, but do NOT open InitialOptionsDialog!! } void MainWindow::on_actionImportPDB_triggered() diff --git a/src/MainWindow.h b/src/MainWindow.h index 027f725f..d4e699a0 100644 --- a/src/MainWindow.h +++ b/src/MainWindow.h @@ -13,6 +13,7 @@ #include "widgets/PseudocodeWidget.h" #include "dialogs/NewFileDialog.h" #include "utils/Configuration.h" +#include "utils/InitialOptions.h" #include #include @@ -67,11 +68,9 @@ public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); - void openNewFile(const QString &fn, int analLevel = -1, - QList advancedOptions = QList(), const QString &shellcode = QString()); + void openNewFile(InitialOptions options = InitialOptions(), bool skipOptionsDialog = false); void displayNewFileDialog(); void closeNewFileDialog(); - void displayAnalysisOptionsDialog(int analLevel, QList advancedOptions, const QString &script, const QString &shellcode = QString()); void openProject(const QString &project_name); void initUI(); @@ -234,6 +233,8 @@ private: JupyterWidget *jupyterDock = nullptr; #endif + void displayInitialOptionsDialog(const InitialOptions &options = InitialOptions(), bool skipOptionsDialog = false); + void resetToDefaultLayout(); void resetToZenLayout(); void resetToDebugLayout(); diff --git a/src/dialogs/InitialOptionsDialog.cpp b/src/dialogs/InitialOptionsDialog.cpp index ae413e9d..6e0e9d3a 100644 --- a/src/dialogs/InitialOptionsDialog.cpp +++ b/src/dialogs/InitialOptionsDialog.cpp @@ -82,18 +82,41 @@ void InitialOptionsDialog::updateCPUComboBox() ui->cpuComboBox->lineEdit()->setText(currentText); } -void InitialOptionsDialog::setInitialScript(const QString &script) +void InitialOptionsDialog::loadOptions(const InitialOptions &options) { - ui->scriptCheckBox->setChecked(!script.isEmpty()); - ui->scriptLineEdit->setText(script); - if (!script.isEmpty()) { + if (options.analCmd.isEmpty()) { ui->analSlider->setValue(0); + } else if (options.analCmd == QList({ "aaa" })) { + ui->analSlider->setValue(1); + } else if (options.analCmd == QList({ "aaaa" })){ + // TODO: These checks must always be in sync with getSelectedAdvancedAnalCmds(), which is dangerous + ui->aa_symbols->setChecked(options.analCmd.contains("aa")); + ui->aar_references->setChecked(options.analCmd.contains("aar")); + ui->aac_calls->setChecked(options.analCmd.contains("aac")); + ui->aab_basicblocks->setChecked(options.analCmd.contains("aab")); + ui->aan_rename->setChecked(options.analCmd.contains("aan")); + ui->aae_emulate->setChecked(options.analCmd.contains("aae")); + ui->aat_consecutive->setChecked(options.analCmd.contains("aat")); + ui->afta_typeargument->setChecked(options.analCmd.contains("afta")); + ui->aaT_aftertrap->setChecked(options.analCmd.contains("aaT")); + ui->aap_preludes->setChecked(options.analCmd.contains("aap")); + ui->jmptbl->setChecked(options.analCmd.contains("e! anal.jmptbl")); + ui->pushret->setChecked(options.analCmd.contains("e! anal.pushret")); + ui->hasnext->setChecked(options.analCmd.contains("e! anal.hasnext")); } -} -void InitialOptionsDialog::setShellcode(const QString &shellcode) -{ - this->shellcode = shellcode; + if (!options.script.isEmpty()) { + ui->scriptCheckBox->setChecked(false); + ui->scriptLineEdit->setText(""); + ui->analSlider->setValue(0); + } else { + ui->scriptCheckBox->setChecked(true); + ui->scriptLineEdit->setText(options.script); + } + + shellcode = options.shellcode; + + // TODO: all other options should also be applied to the ui } QString InitialOptionsDialog::getSelectedArch() @@ -195,10 +218,8 @@ QList InitialOptionsDialog::getSelectedAdvancedAnalCmds() return advanced; } -void InitialOptionsDialog::setupAndStartAnalysis(int level, QList advanced) +void InitialOptionsDialog::setupAndStartAnalysis(/*int level, QList advanced*/) { - ui->analSlider->setValue(level); - main->initUI(); InitialOptions options; @@ -233,6 +254,7 @@ void InitialOptionsDialog::setupAndStartAnalysis(int level, QList advan options.endian = getSelectedEndianness(); options.bbsize = getSelectedBBSize(); + int level = ui->analSlider->value(); switch(level) { case 1: options.analCmd = { "aaa" }; @@ -241,7 +263,7 @@ void InitialOptionsDialog::setupAndStartAnalysis(int level, QList advan options.analCmd = { "aaaa" }; break; case 3: - options.analCmd = advanced; + options.analCmd = getSelectedAdvancedAnalCmds(); break; default: options.analCmd = {}; @@ -276,7 +298,7 @@ void InitialOptionsDialog::setupAndStartAnalysis(int level, QList advan void InitialOptionsDialog::on_okButton_clicked() { ui->okButton->setEnabled(false); - setupAndStartAnalysis(ui->analSlider->value(), getSelectedAdvancedAnalCmds()); + setupAndStartAnalysis(); } void InitialOptionsDialog::closeEvent(QCloseEvent *event) diff --git a/src/dialogs/InitialOptionsDialog.h b/src/dialogs/InitialOptionsDialog.h index d5fa45e4..385cec2d 100644 --- a/src/dialogs/InitialOptionsDialog.h +++ b/src/dialogs/InitialOptionsDialog.h @@ -8,6 +8,7 @@ #include #include "Cutter.h" #include "AnalTask.h" +#include "utils/InitialOptions.h" namespace Ui { @@ -26,7 +27,7 @@ public: QStringList asm_plugins; - void setupAndStartAnalysis(int level, QList advanced); + void setupAndStartAnalysis(/*int level, QList advanced*/); private slots: void on_okButton_clicked(); @@ -55,10 +56,6 @@ private: void updateCPUComboBox(); -public: - void setInitialScript(const QString &script); - void setShellcode(const QString &shellcode); - QString getSelectedArch(); QString getSelectedCPU(); int getSelectedBits(); @@ -67,6 +64,9 @@ public: QString getSelectedOS(); QList getSelectedAdvancedAnalCmds(); +public: + void loadOptions(const InitialOptions &options); + void reject() override; }; diff --git a/src/dialogs/NewFileDialog.cpp b/src/dialogs/NewFileDialog.cpp index 2e99de44..18409a70 100644 --- a/src/dialogs/NewFileDialog.cpp +++ b/src/dialogs/NewFileDialog.cpp @@ -361,7 +361,9 @@ void NewFileDialog::loadFile(const QString &filename) ioFile = ui->ioPlugin->currentText() + "://"; } ioFile += filename; - main->openNewFile(ioFile); + InitialOptions options; + options.filename = ioFile; + main->openNewFile(options); close(); } @@ -377,8 +379,10 @@ void NewFileDialog::loadProject(const QString &project) void NewFileDialog::loadShellcode(const QString &shellcode, const int size) { MainWindow *main = new MainWindow(); - QString ioFile = QString("malloc://%1").arg(size); - main->openNewFile(ioFile, -1, QList(), shellcode); + InitialOptions options; + options.filename = QString("malloc://%1").arg(size); + options.shellcode = shellcode; + main->openNewFile(options); close(); }