diff --git a/docs/source/images/InitializationScriptEditor.png b/docs/source/images/InitializationScriptEditor.png new file mode 100644 index 00000000..6e72c1f8 Binary files /dev/null and b/docs/source/images/InitializationScriptEditor.png differ diff --git a/docs/source/user-docs.rst b/docs/source/user-docs.rst index e78c484a..d9cf7ca7 100644 --- a/docs/source/user-docs.rst +++ b/docs/source/user-docs.rst @@ -13,4 +13,5 @@ Cutter is an advanced reverse engineering platform that is powered by radare2. T user-docs/command-line user-docs/menus + user-docs/preferences diff --git a/docs/source/user-docs/preferences.rst b/docs/source/user-docs/preferences.rst new file mode 100644 index 00000000..7189df32 --- /dev/null +++ b/docs/source/user-docs/preferences.rst @@ -0,0 +1,11 @@ +Preferences +===================== +This part of the documentation will provide the reader with information about different preferences available. +Preferences can be opened by clicking ``Edit -> Preferences``. + +.. toctree:: + :maxdepth: 2 + :glob: + + preferences/initialization-script + preferences/* \ No newline at end of file diff --git a/docs/source/user-docs/preferences/initialization-script.rst b/docs/source/user-docs/preferences/initialization-script.rst new file mode 100644 index 00000000..fa92a5a5 --- /dev/null +++ b/docs/source/user-docs/preferences/initialization-script.rst @@ -0,0 +1,17 @@ +Initialization Script +=================================== + +On the launch of Cutter, it loads ``.cutterrc`` files from various locations if they are present. The directories from where ``.cutterrc`` files are loaded are all directories of type ``QStandardPaths::AppConfigLocation``. These locations vary according to OS. You can visit `here `__ to see all the locations. + +If multiple ``.cutterrc`` scripts are present in different directories, all of them will be loaded. In case of conflicting or contradictory commands, the corresponding command in the script loaded last will override all the previous commands. Cutter has a GUI editor for Initialization Script whose description is given below. The script from the editor will be the last loaded initialization script and hence will override all the previous scripts in the event of conflicting commands. + +Initialization Script Editor +----------------------------------- + +.. image:: ../../images/InitializationScriptEditor.png + :alt: Image of Initialization Script Editor + + +**Description:** You can add new commands and modify existing commands here. To save the script, click on the ``Save`` button. If you want to see the changes you have made without restarting Cutter, you can use the ``Execute`` button. The hyperlink that shows the location of the script will open the directory containing the script on click. + +**Steps to open:** ``Edit -> Preferences -> Initialization Script`` diff --git a/src/Cutter.pro b/src/Cutter.pro index 5ea3a78b..5f18dd53 100644 --- a/src/Cutter.pro +++ b/src/Cutter.pro @@ -344,6 +344,7 @@ SOURCES += \ dialogs/preferences/AppearanceOptionsWidget.cpp \ dialogs/preferences/GraphOptionsWidget.cpp \ dialogs/preferences/PreferenceCategory.cpp \ + dialogs/preferences/InitializationFileEditor.cpp \ widgets/QuickFilterView.cpp \ widgets/ClassesWidget.cpp \ widgets/ResourcesWidget.cpp \ @@ -484,6 +485,7 @@ HEADERS += \ dialogs/preferences/AppearanceOptionsWidget.h \ dialogs/preferences/PreferenceCategory.h \ dialogs/preferences/GraphOptionsWidget.h \ + dialogs/preferences/InitializationFileEditor.h \ widgets/QuickFilterView.h \ widgets/ClassesWidget.h \ widgets/ResourcesWidget.h \ @@ -598,6 +600,7 @@ FORMS += \ dialogs/preferences/PreferencesDialog.ui \ dialogs/preferences/AppearanceOptionsWidget.ui \ dialogs/preferences/GraphOptionsWidget.ui \ + dialogs/preferences/InitializationFileEditor.ui \ widgets/QuickFilterView.ui \ widgets/DecompilerWidget.ui \ widgets/ClassesWidget.ui \ diff --git a/src/core/Cutter.cpp b/src/core/Cutter.cpp index b485cc38..3cf87f6a 100644 --- a/src/core/Cutter.cpp +++ b/src/core/Cutter.cpp @@ -240,34 +240,49 @@ RCoreLocked CutterCore::core() return RCoreLocked(this); } -QVector CutterCore::getCutterRCDirectories() const +QDir CutterCore::getCutterRCDefaultDirectory() const { - QVector result; - result.push_back(QDir::home()); + return QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation); +} + +QVector CutterCore::getCutterRCFilePaths() const +{ + QVector result; + result.push_back(QFileInfo(QDir::home(), ".cutterrc").absoluteFilePath()); QStringList locations = QStandardPaths::standardLocations(QStandardPaths::AppConfigLocation); for (auto &location : locations) { - result.push_back(QDir(location)); + result.push_back(QFileInfo(QDir(location), ".cutterrc").absoluteFilePath()); } + result.push_back(QFileInfo(getCutterRCDefaultDirectory(), "rc").absoluteFilePath()); // File in config editor is from this path return result; } void CutterCore::loadCutterRC() { CORE_LOCK(); - - const auto result = getCutterRCDirectories(); - for(auto &dir : result){ - if(!dir.exists())continue; - auto cutterRCFileInfo = QFileInfo(dir, ".cutterrc"); - auto path = cutterRCFileInfo.absoluteFilePath(); - if (!cutterRCFileInfo.isFile()) { + const auto result = getCutterRCFilePaths(); + for(auto &cutterRCFilePath : result){ + auto cutterRCFileInfo = QFileInfo(cutterRCFilePath); + if (!cutterRCFileInfo.exists() || !cutterRCFileInfo.isFile()) { continue; } - qInfo() << "Loading initialization file from" << path; - r_core_cmd_file(core, path.toUtf8().constData()); + qInfo() << "Loading initialization file from " << cutterRCFilePath; + r_core_cmd_file(core, cutterRCFilePath.toUtf8().constData()); } } +void CutterCore::loadDefaultCutterRC() +{ + CORE_LOCK(); + auto cutterRCFilePath = QFileInfo(getCutterRCDefaultDirectory(), "rc").absoluteFilePath(); + const auto cutterRCFileInfo = QFileInfo(cutterRCFilePath); + if (!cutterRCFileInfo.exists() || !cutterRCFileInfo.isFile()) { + return; + } + qInfo() << "Loading initialization file from " << cutterRCFilePath; + r_core_cmd_file(core, cutterRCFilePath.toUtf8().constData()); +} + QList CutterCore::sdbList(QString path) { diff --git a/src/core/Cutter.h b/src/core/Cutter.h index 593f9ed7..777270a2 100644 --- a/src/core/Cutter.h +++ b/src/core/Cutter.h @@ -46,7 +46,9 @@ public: void initialize(bool loadPlugins = true); void loadCutterRC(); - + void loadDefaultCutterRC(); + QDir getCutterRCDefaultDirectory() const; + AsyncTaskManager *getAsyncTaskManager() { return asyncTaskManager; } RVA getOffset() const { return core_->offset; } @@ -710,7 +712,7 @@ private: QSharedPointer debugTask; R2TaskDialog *debugTaskDialog; - QVector getCutterRCDirectories() const; + QVector getCutterRCFilePaths() const; }; class RCoreLocked diff --git a/src/dialogs/preferences/InitializationFileEditor.cpp b/src/dialogs/preferences/InitializationFileEditor.cpp new file mode 100644 index 00000000..0356e722 --- /dev/null +++ b/src/dialogs/preferences/InitializationFileEditor.cpp @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "InitializationFileEditor.h" +#include "ui_InitializationFileEditor.h" + +#include "PreferencesDialog.h" + +#include "common/Helpers.h" +#include "common/Configuration.h" + +InitializationFileEditor::InitializationFileEditor(PreferencesDialog *dialog) + : QDialog(dialog), + ui(new Ui::InitializationFileEditor) +{ + ui->setupUi(this); + connect(ui->saveRC, &QDialogButtonBox::accepted, this, &InitializationFileEditor::saveCutterRC); + connect(ui->executeNow, &QDialogButtonBox::accepted, this, &InitializationFileEditor::executeCutterRC); + connect(ui->ConfigFileEdit, &QPlainTextEdit::modificationChanged, ui->saveRC, &QWidget::setEnabled); + + const QDir cutterRCDirectory = Core()->getCutterRCDefaultDirectory(); + auto cutterRCFileInfo = QFileInfo(cutterRCDirectory, "rc"); + QString cutterRCLocation = cutterRCFileInfo.absoluteFilePath(); + + ui->cutterRCLoaded->setTextInteractionFlags(Qt::TextBrowserInteraction); + ui->cutterRCLoaded->setOpenExternalLinks(true); + ui->cutterRCLoaded->setText(tr("Script is loaded from %2") + .arg(QUrl::fromLocalFile(cutterRCDirectory.absolutePath()).toString(), cutterRCLocation.toHtmlEscaped())); + + ui->executeNow->button(QDialogButtonBox::Retry)->setText("Execute"); + ui->ConfigFileEdit->clear(); + if(cutterRCFileInfo.exists()){ + QFile cutterRC(cutterRCLocation); + if(cutterRC.open(QIODevice::ReadWrite | QIODevice::Text)){ + ui->ConfigFileEdit->setPlainText(cutterRC.readAll()); + } + cutterRC.close(); + } + ui->saveRC->setDisabled(true); +} + +InitializationFileEditor::~InitializationFileEditor() {}; + + +void InitializationFileEditor::saveCutterRC(){ + const QDir cutterRCDirectory = Core()->getCutterRCDefaultDirectory(); + if(!cutterRCDirectory.exists()){ + cutterRCDirectory.mkpath("."); + } + auto cutterRCFileInfo = QFileInfo(cutterRCDirectory, "rc"); + QString cutterRCLocation = cutterRCFileInfo.absoluteFilePath(); + + QFile cutterRC(cutterRCLocation); + if(cutterRC.open(QIODevice::ReadWrite | QIODevice::Truncate | QIODevice::Text)){ + QTextStream out(&cutterRC); + QString text = ui->ConfigFileEdit->toPlainText(); + out << text; + cutterRC.close(); + } + ui->ConfigFileEdit->document()->setModified(false); +} + +void InitializationFileEditor::executeCutterRC(){ + saveCutterRC(); + Core()->loadDefaultCutterRC(); +} diff --git a/src/dialogs/preferences/InitializationFileEditor.h b/src/dialogs/preferences/InitializationFileEditor.h new file mode 100644 index 00000000..b302458e --- /dev/null +++ b/src/dialogs/preferences/InitializationFileEditor.h @@ -0,0 +1,31 @@ +#ifndef INITIALIZATIONFILEEDITOR_H +#define INITIALIZATIONFILEEDITOR_H + +#include +#include +#include +#include "core/Cutter.h" + +class PreferencesDialog; + +namespace Ui { +class InitializationFileEditor; +} + +class InitializationFileEditor : public QDialog +{ + Q_OBJECT + +public: + explicit InitializationFileEditor(PreferencesDialog *dialog); + ~InitializationFileEditor(); + void saveCutterRC(); + void executeCutterRC(); + +private: + std::unique_ptr ui; + +}; + + +#endif //INITIALIZATIONFILEEDITOR_H \ No newline at end of file diff --git a/src/dialogs/preferences/InitializationFileEditor.ui b/src/dialogs/preferences/InitializationFileEditor.ui new file mode 100644 index 00000000..30c5ece8 --- /dev/null +++ b/src/dialogs/preferences/InitializationFileEditor.ui @@ -0,0 +1,54 @@ + + + InitializationFileEditor + + + + 0 + 0 + 667 + 486 + + + + CutterRC Editor + + + + + + TextLabel + + + + + + + + 649 + 16777215 + + + + QDialogButtonBox::Save + + + + + + + + + + QDialogButtonBox::Retry + + + false + + + + + + + + diff --git a/src/dialogs/preferences/PreferencesDialog.cpp b/src/dialogs/preferences/PreferencesDialog.cpp index f6fc69b8..f8b30394 100644 --- a/src/dialogs/preferences/PreferencesDialog.cpp +++ b/src/dialogs/preferences/PreferencesDialog.cpp @@ -6,6 +6,7 @@ #include "GraphOptionsWidget.h" #include "DebugOptionsWidget.h" #include "PluginsOptionsWidget.h" +#include "InitializationFileEditor.h" #include "PreferenceCategory.h" @@ -51,6 +52,11 @@ PreferencesDialog::PreferencesDialog(QWidget *parent) tr("Plugins"), new PluginsOptionsWidget(this), QIcon(":/img/icons/plugins.svg") + }, + { + tr("Initialization Script"), + new InitializationFileEditor(this), + QIcon(":/img/icons/initialization.svg") } }; @@ -114,6 +120,7 @@ void PreferencesDialog::chooseThemeIcons() { QStringLiteral("Graph"), QStringLiteral("graph.svg") }, { QStringLiteral("Appearance"), QStringLiteral("polar.svg") }, { QStringLiteral("Plugins"), QStringLiteral("plugins.svg") }, + { QStringLiteral("Initialization Script"), QStringLiteral("initialization.svg") }, }; QList> supportedIconsNames; diff --git a/src/img/icons/initialization.svg b/src/img/icons/initialization.svg new file mode 100644 index 00000000..b248f327 --- /dev/null +++ b/src/img/icons/initialization.svg @@ -0,0 +1,99 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/img/icons/light/initialization.svg b/src/img/icons/light/initialization.svg new file mode 100644 index 00000000..87014521 --- /dev/null +++ b/src/img/icons/light/initialization.svg @@ -0,0 +1,99 @@ + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/resources.qrc b/src/resources.qrc index aabd289f..a072e2ff 100644 --- a/src/resources.qrc +++ b/src/resources.qrc @@ -56,6 +56,8 @@ img/icons/graph_white.svg img/icons/graph.svg img/icons/light/graph.svg + img/icons/initialization.svg + img/icons/light/initialization.svg img/icons/hexdump_light.svg img/icons/hexdump_white.svg img/icons/bug.svg