4 This file is part of Kleopatra, the KDE keymanager
5 Copyright (c) 2001,2002,2004,2008 Klar�vdalens Datakonsult AB
7 Kleopatra is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 Kleopatra is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 In addition, as a special exception, the copyright holders give
22 permission to link the code of this program with any edition of
23 the Qt library by Trolltech AS, Norway (or with modified versions
24 of Qt that use the same license as Qt), and distribute linked
25 combinations including the two. You must obey the GNU General
26 Public License in all respects for all of the code used other than
27 Qt. If you modify this file, you may extend this exception to
28 your version of the file, but you are not obligated to do so. If
29 you do not wish to do so, delete this exception statement from
33 #include <config-kleopatra.h>
35 #include "aboutdata.h"
36 #include "kleopatraapplication.h"
37 #include "mainwindow.h"
39 #include <commands/reloadkeyscommand.h>
40 #include <commands/selftestcommand.h>
42 #include <utils/gnupg-helper.h>
44 #ifdef HAVE_USABLE_ASSUAN
45 # include <uiserver/uiserver.h>
46 # include <uiserver/assuancommand.h>
47 # include <uiserver/echocommand.h>
48 # include <uiserver/decryptcommand.h>
49 # include <uiserver/verifycommand.h>
50 # include <uiserver/decryptverifyfilescommand.h>
51 # include <uiserver/decryptfilescommand.h>
52 # include <uiserver/verifyfilescommand.h>
53 # include <uiserver/prepencryptcommand.h>
54 # include <uiserver/prepsigncommand.h>
55 # include <uiserver/encryptcommand.h>
56 # include <uiserver/signcommand.h>
57 # include <uiserver/signencryptfilescommand.h>
58 # include <uiserver/selectcertificatecommand.h>
59 # include <uiserver/importfilescommand.h>
60 # include <uiserver/createchecksumscommand.h>
61 # include <uiserver/verifychecksumscommand.h>
68 #include <kcmdlineargs.h>
70 #include <kiconloader.h>
71 #include <ksplashscreen.h>
72 #include <kmessagebox.h>
74 #include <QTextDocument> // for Qt::escape
75 #include <QStringList>
76 #include <QMessageBox>
80 #include <QThreadPool>
83 #include <gpgme++/global.h>
84 #include <gpgme++/error.h>
86 #include <boost/shared_ptr.hpp>
90 using namespace boost
;
92 static const int SPLASHSCREEN_TIMEOUT
= 5000; // 5s
96 boost::shared_ptr
<T
> make_shared_ptr( T
* t
) {
97 return t
? boost::shared_ptr
<T
>( t
) : boost::shared_ptr
<T
>() ;
101 static QPixmap
UserIcon_nocached( const char * name
) {
102 // KIconLoader insists on caching all pixmaps. Since the splash
103 // screen is a particularly large 'icon' and used only once,
104 // caching is unneccesary and just hurts startup performance.
105 KIconLoader
* const il
= KIconLoader::global();
107 const QString iconPath
= il
->iconPath( QLatin1String( name
), KIconLoader::User
);
108 return iconPath
.isEmpty() ? il
->unknown() : QPixmap( iconPath
) ;
111 class SplashScreen
: public KSplashScreen
{
115 : KSplashScreen( UserIcon_nocached( "kleopatra_splashscreen" ), Qt::WindowStaysOnTopHint
),
118 m_timer
.start( SPLASHSCREEN_TIMEOUT
, this );
122 void timerEvent( QTimerEvent
* ev
) {
123 if ( ev
->timerId() == m_timer
.timerId() ) {
127 KSplashScreen::timerEvent( ev
);
133 static bool selfCheck( KSplashScreen
& splash
) {
134 splash
.showMessage( i18n("Performing Self-Check...") );
135 Kleo::Commands::SelfTestCommand
cmd( 0 );
136 cmd
.setAutoDelete( false );
137 cmd
.setAutomaticMode( true );
138 cmd
.setSplashScreen( &splash
);
140 QObject::connect( &cmd
, SIGNAL(finished()), &loop
, SLOT(quit()) );
141 QObject::connect( &cmd
, SIGNAL(info(QString
)), &splash
, SLOT(showMessage(QString
)) );
142 QTimer::singleShot( 0, &cmd
, SLOT(start()) ); // start() may emit finished()...
144 if ( cmd
.isCanceled() ) {
145 splash
.showMessage( i18nc("did not pass", "Self-Check Failed") );
148 splash
.showMessage( i18n("Self-Check Passed") );
153 static void fillKeyCache( KSplashScreen
* splash
, Kleo::UiServer
* server
) {
156 Kleo::ReloadKeysCommand
* cmd
= new Kleo::ReloadKeysCommand( 0 );
157 QObject::connect( cmd
, SIGNAL(finished()), &loop
, SLOT(quit()) );
158 #ifdef HAVE_USABLE_ASSUAN
159 QObject::connect( cmd
, SIGNAL(finished()), server
, SLOT(enableCryptoCommands()) );
163 splash
->showMessage( i18n("Loading certificate cache...") );
166 splash
->showMessage( i18n("Certificate cache loaded.") );
169 int main( int argc
, char** argv
)
174 const GpgME::Error gpgmeInitError
= GpgME::initializeLibrary(0);
177 const unsigned int threads
= QThreadPool::globalInstance()->maxThreadCount();
178 QThreadPool::globalInstance()->setMaxThreadCount( qMax( 2U, threads
) );
183 KCmdLineArgs::init(argc
, argv
, &aboutData
);
185 KCmdLineArgs::addCmdLineOptions( KleopatraApplication::commandLineOptions() );
187 qDebug() << "Statup timing:" << timer
.elapsed() << "ms elapsed: Command line args created";
189 KleopatraApplication app
;
191 qDebug() << "Startup timing:" << timer
.elapsed() << "ms elapsed: Application created";
193 KCmdLineArgs
*args
= KCmdLineArgs::parsedArgs();
195 if ( gpgmeInitError
) {
196 KMessageBox::sorry( 0, i18nc("@info",
197 "<para>The version of the <application>GpgME</application> library you are running against "
198 "is older than the one that the <application>GpgME++</application> library was built against.</para>"
199 "<para><application>Kleopatra</application> will not function in this setting.</para>"
200 "<para>Please ask your administrator for help in resolving this issue.</para>"),
201 i18nc("@title", "GpgME Too Old") );
208 #ifdef HAVE_USABLE_ASSUAN
210 Kleo::UiServer
server( args
->getOption("uiserver-socket") );
212 qDebug() << "Startup timing:" << timer
.elapsed() << "ms elapsed: UiServer created";
214 QObject::connect( &server
, SIGNAL(startKeyManagerRequested()),
215 &app
, SLOT(openOrRaiseMainWindow()) );
217 QObject::connect( &server
, SIGNAL(startConfigDialogRequested()),
218 &app
, SLOT(openOrRaiseConfigDialog()) );
220 #define REGISTER( Command ) server.registerCommandFactory( boost::shared_ptr<Kleo::AssuanCommandFactory>( new Kleo::GenericAssuanCommandFactory<Kleo::Command> ) )
221 REGISTER( CreateChecksumsCommand
);
222 REGISTER( DecryptCommand
);
223 REGISTER( DecryptFilesCommand
);
224 REGISTER( DecryptVerifyFilesCommand
);
225 REGISTER( EchoCommand
);
226 REGISTER( EncryptCommand
);
227 REGISTER( EncryptFilesCommand
);
228 REGISTER( EncryptSignFilesCommand
);
229 REGISTER( ImportFilesCommand
);
230 REGISTER( PrepEncryptCommand
);
231 REGISTER( PrepSignCommand
);
232 REGISTER( SelectCertificateCommand
);
233 REGISTER( SignCommand
);
234 REGISTER( SignEncryptFilesCommand
);
235 REGISTER( SignFilesCommand
);
236 REGISTER( VerifyChecksumsCommand
);
237 REGISTER( VerifyCommand
);
238 REGISTER( VerifyFilesCommand
);
242 qDebug() << "Startup timing:" << timer
.elapsed() << "ms elapsed: UiServer started";
245 const bool daemon
= args
->isSet("daemon");
249 if ( !selfCheck( splash
) )
251 qDebug() << "Startup timing:" << timer
.elapsed() << "ms elapsed: SelfCheck completed";
253 #ifdef HAVE_USABLE_ASSUAN
254 fillKeyCache( &splash
, &server
);
256 fillKeyCache( &splash
, 0 );
258 qDebug() << "Startup timing:" << timer
.elapsed() << "ms elapsed: KeyCache loaded";
260 app
.startMonitoringSmartCard();
262 app
.setIgnoreNewInstance( false );
266 qDebug() << "Startup timing:" << timer
.elapsed() << "ms elapsed: new instance created";
267 splash
.finish( app
.mainWindow() );
272 #ifdef HAVE_USABLE_ASSUAN
273 app
.setIgnoreNewInstance( true );
274 QObject::disconnect( &server
, SIGNAL(startKeyManagerRequested()),
275 &app
, SLOT(openOrRaiseMainWindow()) );
276 QObject::disconnect( &server
, SIGNAL(startConfigDialogRequested()),
277 &app
, SLOT(openOrRaiseConfigDialog()) );
280 server
.waitForStopped();
281 } catch ( const std::exception
& e
) {
282 QMessageBox::information( 0, i18n("GPG UI Server Error"),
283 i18n("<qt>The Kleopatra GPG UI Server Module could not be initialized.<br/>"
284 "The error given was: <b>%1</b><br/>"
285 "You can use Kleopatra as a certificate manager, but cryptographic plugins that "
286 "rely on a GPG UI Server being present might not work correctly, or at all.</qt>",
287 Qt::escape( QString::fromUtf8( e
.what() ) ) ));
288 app
.startMonitoringSmartCard();
289 app
.setIgnoreNewInstance( false );
291 app
.setIgnoreNewInstance( true );