2006-09-30 20:02:39 +04:00
/*
2014-12-14 22:18:05 +03:00
* Bittorrent Client using Qt and libtorrent .
* Copyright ( C ) 2014 Vladimir Golovnev < glassez @ yandex . ru >
2007-07-14 18:31:59 +04:00
* Copyright ( C ) 2006 Christophe Dumez
2006-09-30 20:02:39 +04:00
*
2007-07-14 18:31:59 +04:00
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
2006-09-30 20:02:39 +04:00
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2007-07-14 18:31:59 +04:00
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*
2009-04-05 21:00:55 +04:00
* In addition , as a special exception , the copyright holders give permission to
* link this program with the OpenSSL project ' s " OpenSSL " library ( or with
* modified versions of it that use the same license as the " OpenSSL " library ) ,
* and distribute the linked executables . You must obey the GNU General Public
* License in all respects for all of the code used other than " OpenSSL " . If you
* modify file ( s ) , you may extend this exception to your version of the file ( s ) ,
* but you are not obligated to do so . If you do not wish to do so , delete this
* exception statement from your version .
*
2007-07-14 18:31:59 +04:00
* Contact : chris @ qbittorrent . org
2006-09-30 20:02:39 +04:00
*/
2014-07-05 16:44:13 +04:00
# include <QDebug>
2009-12-15 13:56:41 +03:00
2009-12-15 14:08:22 +03:00
# ifndef DISABLE_GUI
2014-12-14 22:18:05 +03:00
# include <QFont>
# include <QMessageBox>
# include <QPainter>
# include <QPen>
# include <QPushButton>
# include <QSplashScreen>
# include <QStyle>
# include <QStyleFactory>
# ifdef QBT_STATIC_QT
2012-12-28 15:40:22 +04:00
# include <QtPlugin>
2014-05-01 23:53:29 +04:00
# if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
Q_IMPORT_PLUGIN ( QICOPlugin )
# else
2012-12-28 15:40:22 +04:00
Q_IMPORT_PLUGIN ( qico )
# endif
2014-12-14 22:18:05 +03:00
# endif // QBT_STATIC_QT
2010-11-14 00:15:52 +03:00
# include "mainwindow.h"
2010-01-03 02:03:46 +03:00
# include "ico.h"
2014-12-14 22:18:05 +03:00
# else // DISABLE_GUI
2010-01-09 18:26:20 +03:00
# include <iostream>
# include <stdio.h>
2010-01-03 02:03:46 +03:00
# include "headlessloader.h"
2014-12-14 22:18:05 +03:00
# endif // DISABLE_GUI
2009-12-15 13:56:41 +03:00
2014-12-14 22:18:05 +03:00
# include "application.h"
# ifdef Q_OS_UNIX
2009-09-30 22:57:06 +04:00
# include <signal.h>
# include <execinfo.h>
# include "stacktrace.h"
2014-12-14 22:18:05 +03:00
# endif // Q_OS_UNIX
2010-03-30 15:35:20 +04:00
2013-03-03 03:17:04 +04:00
# ifdef STACKTRACE_WIN
2013-01-19 20:16:57 +04:00
# include <signal.h>
# include "stacktrace_win.h"
# include "stacktrace_win_dlg.h"
2014-12-14 22:18:05 +03:00
# endif //STACKTRACE_WIN
2013-01-19 20:16:57 +04:00
2006-09-30 20:02:39 +04:00
# include <stdlib.h>
# include "misc.h"
* Replace priority combo boxes by check boxes in Web UI as in Regular UI
* Prepare http server and preferences classes to add new settings to Web UI
* Tabified Program preferences in Web UI since there will be a lot of settings soon
* Started to add new settings to Web UI (PeX, LSD, Encryption, save path, temp path, scan dir, preallocateall, queueing, listen_port, upnp, nat-pmp, language, ip filter) -> Proxy is missing
* Added a command line parameter to change the web ui port
* Fix PeerGuardian .p2b binary filter support
2009-12-28 22:39:47 +03:00
# include "preferences.h"
2008-11-05 01:39:43 +03:00
2013-09-17 16:21:23 +04:00
# if defined(Q_OS_WIN) && !defined(QBT_HAS_GETCURRENTPID)
# error You seem to have updated QtSingleApplication without porting our custom QtSingleApplication::getRunningPid() function. Please see previous version to understate how it works.
# endif
2014-12-15 21:43:01 +03:00
// Signal handlers
# if defined(Q_OS_UNIX) || defined(STACKTRACE_WIN)
void sigintHandler ( int ) ;
void sigtermHandler ( int ) ;
void sigsegvHandler ( int ) ;
void sigabrtHandler ( int ) ;
# endif
# ifndef DISABLE_GUI
void showSplashScreen ( ) ;
void parseCommandLine ( bool & showVersion , bool & showUsage , bool & noSplash , QStringList & torrents ) ;
# else
void parseCommandLine ( bool & showVersion , bool & showUsage , bool & shouldDaemonize , QStringList & torrents ) ;
# endif
void displayVersion ( ) ;
void displayUsage ( const char * prg_name ) ;
bool userAgreesWithLegalNotice ( ) ;
// Main
int main ( int argc , char * argv [ ] )
{
// We must save it here because QApplication constructor may change it
bool isOneArg = ( argc = = 2 ) ;
bool showVersion ;
bool showUsage ;
# ifndef DISABLE_GUI
bool noSplash ;
# else
bool shouldDaemonize ;
# endif
QStringList torrents ;
// Create Application
Application app ( " qBittorrent- " + misc : : getUserIDString ( ) , argc , argv ) ;
# ifndef DISABLE_GUI
parseCommandLine ( showVersion , showUsage , noSplash , torrents ) ;
# else
parseCommandLine ( showVersion , showUsage , shouldDaemonize , torrents ) ;
# endif
if ( showVersion )
displayVersion ( ) ;
if ( showUsage )
displayUsage ( argv [ 0 ] ) ;
// If only one parameter is present and it is "--version"
// or "--help", program exits after printing appropriate message.
if ( isOneArg & & ( showVersion | | showUsage ) )
return EXIT_SUCCESS ;
// Set environment variable
if ( ! qputenv ( " QBITTORRENT " , QByteArray ( VERSION ) ) ) {
std : : cerr < < " Couldn't set environment variable... \n " ;
}
if ( ! userAgreesWithLegalNotice ( ) )
return EXIT_SUCCESS ;
// Check if qBittorrent is already running for this user
if ( app . isRunning ( ) ) {
qDebug ( " qBittorrent is already running for this user. " ) ;
# ifdef Q_OS_WIN
DWORD pid = ( DWORD ) app . getRunningPid ( ) ;
if ( pid > 0 ) {
BOOL b = AllowSetForegroundWindow ( pid ) ;
qDebug ( " AllowSetForegroundWindow() returns %s " , b ? " TRUE " : " FALSE " ) ;
}
# endif
if ( ! torrents . isEmpty ( ) ) {
QString message = torrents . join ( " | " ) ;
qDebug ( " Passing program parameters to running instance... " ) ;
qDebug ( " Message: %s " , qPrintable ( message ) ) ;
app . sendMessage ( message ) ;
}
else { // Raise main window
app . sendMessage ( " qbt://show " ) ;
}
return EXIT_SUCCESS ;
}
srand ( time ( 0 ) ) ;
# ifdef DISABLE_GUI
if ( shouldDaemonize & & ( daemon ( 1 , 0 ) ! = 0 ) ) {
qCritical ( " Something went wrong while daemonizing, exiting... " ) ;
return EXIT_FAILURE ;
}
# else
if ( ! noSplash )
showSplashScreen ( ) ;
# endif
# if defined(Q_OS_UNIX) || defined(STACKTRACE_WIN)
signal ( SIGABRT , sigabrtHandler ) ;
signal ( SIGTERM , sigtermHandler ) ;
signal ( SIGINT , sigintHandler ) ;
signal ( SIGSEGV , sigsegvHandler ) ;
# endif
# ifndef DISABLE_GUI
MainWindow window ( 0 , torrents ) ;
QObject : : connect ( & app , SIGNAL ( messageReceived ( const QString & ) ) ,
& window , SLOT ( processParams ( const QString & ) ) ) ;
app . setActivationWindow ( & window ) ;
# ifdef Q_OS_MAC
static_cast < QMacApplication * > ( & app ) - > setReadyToProcessEvents ( ) ;
# endif // Q_OS_MAC
# else
// Load Headless class
HeadlessLoader loader ( torrents ) ;
QObject : : connect ( & app , SIGNAL ( messageReceived ( const QString & ) ) ,
& loader , SLOT ( processParams ( const QString & ) ) ) ;
# endif
int ret = app . exec ( ) ;
qDebug ( " Application has exited " ) ;
return ret ;
}
2013-09-21 11:59:58 +04:00
# if defined(Q_OS_UNIX) || defined(STACKTRACE_WIN)
2014-12-13 20:22:35 +03:00
void sigintHandler ( int )
{
signal ( SIGINT , 0 ) ;
qDebug ( " Catching SIGINT, exiting cleanly " ) ;
qApp - > exit ( ) ;
2010-01-03 02:03:46 +03:00
}
2014-12-13 20:22:35 +03:00
void sigtermHandler ( int )
{
signal ( SIGTERM , 0 ) ;
qDebug ( " Catching SIGTERM, exiting cleanly " ) ;
qApp - > exit ( ) ;
2009-09-30 22:57:06 +04:00
}
2014-12-13 20:22:35 +03:00
void sigsegvHandler ( int )
{
signal ( SIGABRT , 0 ) ;
signal ( SIGSEGV , 0 ) ;
2014-09-11 06:44:25 +04:00
# if !defined Q_OS_WIN && !defined Q_OS_HAIKU
2014-12-13 20:22:35 +03:00
std : : cerr < < " \n \n ************************************************************* \n " ;
std : : cerr < < " Catching SIGSEGV, please report a bug at http://bug.qbittorrent.org \n and provide the following backtrace: \n " ;
std : : cerr < < " qBittorrent version: " < < VERSION < < std : : endl ;
print_stacktrace ( ) ;
2013-01-19 20:16:57 +04:00
# else
2013-01-25 22:52:12 +04:00
# ifdef STACKTRACE_WIN
2014-12-13 20:22:35 +03:00
StraceDlg dlg ;
dlg . setStacktraceString ( straceWin : : getBacktrace ( ) ) ;
dlg . exec ( ) ;
2013-01-25 22:52:12 +04:00
# endif
2013-01-19 20:16:57 +04:00
# endif
2014-12-13 20:22:35 +03:00
raise ( SIGSEGV ) ;
2009-09-30 22:57:06 +04:00
}
2014-12-13 20:22:35 +03:00
void sigabrtHandler ( int )
{
signal ( SIGABRT , 0 ) ;
signal ( SIGSEGV , 0 ) ;
2014-09-11 06:44:25 +04:00
# if !defined Q_OS_WIN && !defined Q_OS_HAIKU
2014-12-13 20:22:35 +03:00
std : : cerr < < " \n \n ************************************************************* \n " ;
std : : cerr < < " Catching SIGABRT, please report a bug at http://bug.qbittorrent.org \n and provide the following backtrace: \n " ;
std : : cerr < < " qBittorrent version: " < < VERSION < < std : : endl ;
print_stacktrace ( ) ;
2013-01-19 20:16:57 +04:00
# else
2013-01-25 22:52:12 +04:00
# ifdef STACKTRACE_WIN
2014-12-13 20:22:35 +03:00
StraceDlg dlg ;
dlg . setStacktraceString ( straceWin : : getBacktrace ( ) ) ;
dlg . exec ( ) ;
2013-01-25 22:52:12 +04:00
# endif
2013-01-19 20:16:57 +04:00
# endif
2014-12-13 20:22:35 +03:00
raise ( SIGABRT ) ;
2009-11-15 13:42:03 +03:00
}
2008-12-26 19:23:53 +03:00
# endif
2006-09-30 20:02:39 +04:00
2014-12-14 22:18:05 +03:00
# ifndef DISABLE_GUI
void showSplashScreen ( )
2014-12-13 20:22:35 +03:00
{
2014-12-14 22:18:05 +03:00
QPixmap splash_img ( " :/Icons/skin/splash.png " ) ;
QPainter painter ( & splash_img ) ;
QString version = VERSION ;
painter . setPen ( QPen ( Qt : : white ) ) ;
painter . setFont ( QFont ( " Arial " , 22 , QFont : : Black ) ) ;
painter . drawText ( 224 - painter . fontMetrics ( ) . width ( version ) , 270 , version ) ;
QSplashScreen * splash = new QSplashScreen ( splash_img , Qt : : WindowStaysOnTopHint ) ;
QTimer : : singleShot ( 1500 , splash , SLOT ( deleteLater ( ) ) ) ;
splash - > show ( ) ;
qApp - > processEvents ( ) ;
}
2013-11-11 12:38:20 +04:00
# endif
2014-12-13 20:22:35 +03:00
2014-12-14 22:18:05 +03:00
void displayVersion ( )
{
std : : cout < < qPrintable ( qApp - > applicationName ( ) ) < < " " < < VERSION < < std : : endl ;
}
void displayUsage ( const char * prg_name )
{
std : : cout < < qPrintable ( QObject : : tr ( " Usage: " ) ) < < std : : endl ;
std : : cout < < ' \t ' < < prg_name < < " --version: " < < qPrintable ( QObject : : tr ( " displays program version " ) ) < < std : : endl ;
# ifndef DISABLE_GUI
std : : cout < < ' \t ' < < prg_name < < " --no-splash: " < < qPrintable ( QObject : : tr ( " disable splash screen " ) ) < < std : : endl ;
2010-10-02 00:03:27 +04:00
# else
2014-12-14 22:18:05 +03:00
std : : cout < < ' \t ' < < prg_name < < " -d | --daemon: " < < qPrintable ( QObject : : tr ( " run in daemon-mode (background) " ) ) < < std : : endl ;
2010-10-02 00:03:27 +04:00
# endif
2014-12-14 22:18:05 +03:00
std : : cout < < ' \t ' < < prg_name < < " --help: " < < qPrintable ( QObject : : tr ( " displays this help message " ) ) < < std : : endl ;
std : : cout < < ' \t ' < < prg_name < < " --webui-port=x: " < < qPrintable ( QObject : : tr ( " changes the webui port (current: %1) " ) . arg ( QString : : number ( Preferences : : instance ( ) - > getWebUiPort ( ) ) ) ) < < std : : endl ;
std : : cout < < ' \t ' < < prg_name < < " " < < qPrintable ( QObject : : tr ( " [files or urls]: downloads the torrents passed by the user (optional) " ) ) < < std : : endl ;
}
2010-07-20 21:13:28 +04:00
2014-12-14 22:18:05 +03:00
# ifndef DISABLE_GUI
2014-12-15 21:43:01 +03:00
void parseCommandLine ( bool & showVersion , bool & showUsage , bool & noSplash , QStringList & torrents )
2014-12-14 22:18:05 +03:00
# else
2014-12-15 21:43:01 +03:00
void parseCommandLine ( bool & showVersion , bool & showUsage , bool & shouldDaemonize , QStringList & torrents )
2013-09-17 16:18:01 +04:00
# endif
2014-12-14 22:18:05 +03:00
{
// Default values
showVersion = false ;
showUsage = false ;
# ifndef DISABLE_GUI
noSplash = Preferences : : instance ( ) - > isSlashScreenDisabled ( ) ;
# else
shouldDaemonize = false ;
# endif
torrents . clear ( ) ;
2014-12-13 20:22:35 +03:00
2014-12-14 22:18:05 +03:00
QStringList appArguments = qApp - > arguments ( ) ;
2014-12-13 20:22:35 +03:00
2014-12-14 22:18:05 +03:00
for ( int i = 1 ; i < appArguments . size ( ) ; + + i ) {
QString & arg = appArguments [ i ] ;
if ( arg = = " --version " ) {
showVersion = true ;
2014-12-13 20:22:35 +03:00
}
2014-12-14 22:18:05 +03:00
else if ( arg = = " --usage " ) {
showUsage = true ;
}
else if ( arg . startsWith ( " --webui-port= " ) ) {
QStringList parts = arg . split ( " = " ) ;
if ( parts . size ( ) = = 2 ) {
bool ok = false ;
int new_port = parts . last ( ) . toInt ( & ok ) ;
if ( ok & & ( new_port > 0 ) & & ( new_port < = 65535 ) )
Preferences : : instance ( ) - > setWebUiPort ( new_port ) ;
}
2014-12-13 20:22:35 +03:00
}
2009-12-15 13:56:41 +03:00
# ifndef DISABLE_GUI
2014-12-14 22:18:05 +03:00
else if ( arg = = " --no-splash " ) {
noSplash = true ;
}
2012-08-18 20:11:27 +04:00
# else
2014-12-14 22:18:05 +03:00
else if ( ( arg = = " -d " ) | | ( arg = = " --daemon " ) ) {
shouldDaemonize = true ;
}
2009-12-15 13:56:41 +03:00
# endif
2014-12-14 22:18:05 +03:00
else if ( ! arg . startsWith ( " -- " ) ) {
QFileInfo torrentPath ;
torrentPath . setFile ( arg ) ;
2010-02-05 22:02:27 +03:00
2014-12-14 22:18:05 +03:00
if ( torrentPath . exists ( ) )
torrents + = torrentPath . absoluteFilePath ( ) ;
else
torrents + = arg ;
}
2014-12-13 20:22:35 +03:00
}
2014-12-14 22:18:05 +03:00
}
2010-02-05 22:02:27 +03:00
2014-12-14 22:18:05 +03:00
bool userAgreesWithLegalNotice ( )
{
Preferences * const pref = Preferences : : instance ( ) ;
if ( pref - > getAcceptedLegal ( ) ) // Already accepted once
return true ;
2010-01-03 01:20:37 +03:00
2014-12-14 22:18:05 +03:00
# ifdef DISABLE_GUI
std : : cout < < std : : endl < < " *** " < < qPrintable ( QObject : : tr ( " Legal Notice " ) ) < < " *** " < < std : : endl ;
std : : cout < < qPrintable ( QObject : : tr ( " qBittorrent is a file sharing program. When you run a torrent, its data will be made available to others by means of upload. Any content you share is your sole responsibility. \n \n No further notices will be issued. " ) ) < < std : : endl < < std : : endl ;
std : : cout < < qPrintable ( QObject : : tr ( " Press %1 key to accept and continue... " ) . arg ( " 'y' " ) ) < < std : : endl ;
char ret = getchar ( ) ; // Read pressed key
if ( ret = = ' y ' | | ret = = ' Y ' ) {
// Save the answer
pref - > setAcceptedLegal ( true ) ;
return true ;
2014-12-13 20:22:35 +03:00
}
2014-12-14 22:18:05 +03:00
# else
QMessageBox msgBox ;
msgBox . setText ( QObject : : tr ( " qBittorrent is a file sharing program. When you run a torrent, its data will be made available to others by means of upload. Any content you share is your sole responsibility. \n \n No further notices will be issued. " ) ) ;
msgBox . setWindowTitle ( QObject : : tr ( " Legal notice " ) ) ;
msgBox . addButton ( QObject : : tr ( " Cancel " ) , QMessageBox : : RejectRole ) ;
QAbstractButton * agree_button = msgBox . addButton ( QObject : : tr ( " I Agree " ) , QMessageBox : : AcceptRole ) ;
msgBox . show ( ) ; // Need to be shown or to moveToCenter does not work
msgBox . move ( misc : : screenCenter ( & msgBox ) ) ;
msgBox . exec ( ) ;
if ( msgBox . clickedButton ( ) = = agree_button ) {
// Save the answer
pref - > setAcceptedLegal ( true ) ;
return true ;
2014-12-13 20:22:35 +03:00
}
2009-12-15 13:56:41 +03:00
# endif
2014-12-13 20:22:35 +03:00
2014-12-14 22:18:05 +03:00
return false ;
}