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-03-06 17:21:42 +00:00
# ifdef CUTTER_ENABLE_JUPYTER
# include "utils/JupyterConnection.h"
# endif
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 " ) ) ;
// 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-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-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-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 ) ;
}