2018-02-10 18:04:31 +00:00
# include "CutterApplication.h"
# include <QApplication>
# include <QFileOpenEvent>
# include <QEvent>
# include <QMessageBox>
# include <QCommandLineParser>
# include <QTextCodec>
# include <QStringList>
# include <QProcess>
2018-06-26 07:40:08 +00:00
# include <QPluginLoader>
# include <QDir>
2018-02-10 18:04:31 +00:00
2018-03-06 17:21:42 +00:00
# ifdef CUTTER_ENABLE_JUPYTER
# include "utils/JupyterConnection.h"
# endif
2018-06-26 07:40:08 +00:00
# include "plugins/CutterPlugin.h"
2018-03-06 17:21:42 +00:00
2018-03-21 20:32:32 +00:00
CutterApplication : : CutterApplication ( int & argc , char * * argv ) : QApplication ( argc , argv )
{
2018-02-10 18:04:31 +00:00
setOrganizationName ( " Cutter " ) ;
setApplicationName ( " Cutter " ) ;
setApplicationVersion ( APP_VERSION ) ;
setWindowIcon ( QIcon ( " :/img/cutter.svg " ) ) ;
2018-07-17 07:26:20 +00:00
setAttribute ( Qt : : AA_DontShowIconsInMenus ) ;
2018-02-10 18:04:31 +00:00
// Set QString codec to UTF-8
QTextCodec : : setCodecForLocale ( QTextCodec : : codecForName ( " UTF-8 " ) ) ;
# if QT_VERSION < QT_VERSION_CHECK(5,0,0)
QTextCodec : : setCodecForCStrings ( QTextCodec : : codecForName ( " UTF-8 " ) ) ;
QTextCodec : : setCodecForTr ( QTextCodec : : codecForName ( " UTF-8 " ) ) ;
# endif
QCommandLineParser cmd_parser ;
2018-03-21 20:32:32 +00:00
cmd_parser . setApplicationDescription (
QObject : : tr ( " A Qt and C++ GUI for radare2 reverse engineering framework " ) ) ;
2018-02-10 18:04:31 +00:00
cmd_parser . addHelpOption ( ) ;
cmd_parser . addVersionOption ( ) ;
cmd_parser . addPositionalArgument ( " filename " , QObject : : tr ( " Filename to open. " ) ) ;
QCommandLineOption analOption ( { " A " , " anal " } ,
2018-03-21 20:32:32 +00:00
QObject : : tr ( " Automatically open file and optionally start analysis. Needs filename to be specified. May be a value between 0 and 2: 0 = no analysis, 1 = aaa, 2 = aaaa (experimental) " ) ,
QObject : : tr ( " level " ) ) ;
2018-02-10 18:04:31 +00:00
cmd_parser . addOption ( analOption ) ;
2018-03-06 17:21:42 +00:00
# ifdef CUTTER_ENABLE_JUPYTER
2018-03-21 20:32:32 +00:00
QCommandLineOption pythonHomeOption ( " pythonhome " , QObject : : tr ( " PYTHONHOME to use for Jupyter " ) ,
" PYTHONHOME " ) ;
2018-03-06 17:21:42 +00:00
cmd_parser . addOption ( pythonHomeOption ) ;
# endif
2018-02-10 18:04:31 +00:00
cmd_parser . process ( * this ) ;
QStringList args = cmd_parser . positionalArguments ( ) ;
// Check r2 version
QString r2version = r_core_version ( ) ;
QString localVersion = " " R2_GITTAP ;
2018-03-21 20:32:32 +00:00
if ( r2version ! = localVersion ) {
2018-02-10 18:04:31 +00:00
QMessageBox msg ;
msg . setIcon ( QMessageBox : : Critical ) ;
msg . setStandardButtons ( QMessageBox : : Yes | QMessageBox : : No ) ;
msg . setWindowTitle ( QObject : : tr ( " Version mismatch! " ) ) ;
2018-03-21 20:32:32 +00:00
msg . setText ( QString (
QObject : : tr ( " The version used to compile Cutter (%1) does not match the binary version of radare2 (%2). This could result in unexpected behaviour. Are you sure you want to continue? " ) ) . arg (
localVersion , r2version ) ) ;
2018-02-10 18:04:31 +00:00
if ( msg . exec ( ) = = QMessageBox : : No )
exit ( 1 ) ;
}
2018-03-06 17:21:42 +00:00
# ifdef CUTTER_ENABLE_JUPYTER
2018-03-21 20:32:32 +00:00
if ( cmd_parser . isSet ( pythonHomeOption ) ) {
2018-03-06 17:21:42 +00:00
Jupyter ( ) - > setPythonHome ( cmd_parser . value ( pythonHomeOption ) ) ;
}
# endif
2018-02-10 18:04:31 +00:00
bool analLevelSpecified = false ;
2018-03-21 20:32:32 +00:00
int analLevel = 0 ;
2018-02-10 18:04:31 +00:00
2018-07-12 13:04:33 +00:00
// Initialize CutterCore and set default settings
Core ( ) - > setSettings ( ) ;
2018-03-21 20:32:32 +00:00
if ( cmd_parser . isSet ( analOption ) ) {
2018-02-10 18:04:31 +00:00
analLevel = cmd_parser . value ( analOption ) . toInt ( & analLevelSpecified ) ;
2018-03-21 20:32:32 +00:00
if ( ! analLevelSpecified | | analLevel < 0 | | analLevel > 2 ) {
printf ( " %s \n " ,
QObject : : tr ( " Invalid Analysis Level. May be a value between 0 and 2. " ) . toLocal8Bit ( ) . constData ( ) ) ;
2018-02-10 18:04:31 +00:00
exit ( 1 ) ;
}
}
2018-02-27 13:06:04 +00:00
mainWindow = new MainWindow ( ) ;
2018-05-13 07:50:01 +00:00
installEventFilter ( mainWindow ) ;
2018-02-10 18:04:31 +00:00
2018-03-21 20:32:32 +00:00
if ( args . empty ( ) ) {
if ( analLevelSpecified ) {
printf ( " %s \n " ,
QObject : : tr ( " Filename must be specified to start analysis automatically. " ) . toLocal8Bit ( ) . constData ( ) ) ;
2018-02-10 18:04:31 +00:00
exit ( 1 ) ;
}
2018-02-27 13:06:04 +00:00
mainWindow - > displayNewFileDialog ( ) ;
2018-03-21 20:32:32 +00:00
} else { // filename specified as positional argument
2018-02-27 13:06:04 +00:00
mainWindow - > openNewFile ( args [ 0 ] , analLevelSpecified ? analLevel : - 1 ) ;
2018-02-10 18:04:31 +00:00
}
2018-06-26 07:40:08 +00:00
// Load plugins
loadPlugins ( ) ;
2018-02-10 18:04:31 +00:00
}
2018-02-27 13:06:04 +00:00
CutterApplication : : ~ CutterApplication ( )
{
delete mainWindow ;
}
bool CutterApplication : : event ( QEvent * e )
{
2018-03-21 20:32:32 +00:00
if ( e - > type ( ) = = QEvent : : FileOpen ) {
2018-02-10 18:04:31 +00:00
QFileOpenEvent * openEvent = static_cast < QFileOpenEvent * > ( e ) ;
2018-03-21 20:32:32 +00:00
if ( openEvent ) {
if ( m_FileAlreadyDropped ) {
2018-05-08 20:44:53 +00:00
// We already dropped a file in macOS, let's spawn another instance
2018-02-10 18:04:31 +00:00
// (Like the File -> Open)
QString fileName = openEvent - > file ( ) ;
QProcess process ( this ) ;
process . setEnvironment ( QProcess : : systemEnvironment ( ) ) ;
QStringList args = QStringList ( fileName ) ;
process . startDetached ( qApp - > applicationFilePath ( ) , args ) ;
2018-03-21 20:32:32 +00:00
} else {
2018-02-10 18:04:31 +00:00
QString fileName = openEvent - > file ( ) ;
m_FileAlreadyDropped = true ;
2018-02-27 13:06:04 +00:00
mainWindow - > closeNewFileDialog ( ) ;
mainWindow - > openNewFile ( fileName , - 1 ) ;
2018-02-10 18:04:31 +00:00
}
}
}
return QApplication : : event ( e ) ;
}
2018-06-26 07:40:08 +00:00
void CutterApplication : : loadPlugins ( )
{
QList < CutterPlugin * > plugins ;
QDir pluginsDir ( qApp - > applicationDirPath ( ) ) ;
# if defined(Q_OS_WIN)
if ( pluginsDir . dirName ( ) . toLower ( ) = = " debug " | | pluginsDir . dirName ( ) . toLower ( ) = = " release " )
pluginsDir . cdUp ( ) ;
# elif defined(Q_OS_MAC)
if ( pluginsDir . dirName ( ) = = " MacOS " ) {
pluginsDir . cdUp ( ) ;
pluginsDir . cdUp ( ) ;
pluginsDir . cdUp ( ) ;
}
# endif
pluginsDir . cd ( " plugins " ) ;
foreach ( QString fileName , pluginsDir . entryList ( QDir : : Files ) ) {
QPluginLoader pluginLoader ( pluginsDir . absoluteFilePath ( fileName ) ) ;
QObject * plugin = pluginLoader . instance ( ) ;
if ( plugin ) {
CutterPlugin * cutterPlugin = qobject_cast < CutterPlugin * > ( plugin ) ;
if ( cutterPlugin ) {
cutterPlugin - > setupPlugin ( Core ( ) ) ;
plugins . append ( cutterPlugin ) ;
}
}
}
Core ( ) - > setCutterPlugins ( plugins ) ;
}