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 <kdelibs4configmigrator.h>
41 #include <commands/reloadkeyscommand.h>
42 #include <commands/selftestcommand.h>
44 #include <utils/gnupg-helper.h>
45 #include <utils/archivedefinition.h>
47 #ifdef HAVE_USABLE_ASSUAN
48 # include <uiserver/uiserver.h>
49 # include <uiserver/assuancommand.h>
50 # include <uiserver/echocommand.h>
51 # include <uiserver/decryptcommand.h>
52 # include <uiserver/verifycommand.h>
53 # include <uiserver/decryptverifyfilescommand.h>
54 # include <uiserver/decryptfilescommand.h>
55 # include <uiserver/verifyfilescommand.h>
56 # include <uiserver/prepencryptcommand.h>
57 # include <uiserver/prepsigncommand.h>
58 # include <uiserver/encryptcommand.h>
59 # include <uiserver/signcommand.h>
60 # include <uiserver/signencryptfilescommand.h>
61 # include <uiserver/selectcertificatecommand.h>
62 # include <uiserver/importfilescommand.h>
63 # include <uiserver/createchecksumscommand.h>
64 # include <uiserver/verifychecksumscommand.h>
72 #include <Libkleo/ChecksumDefinition>
74 #include "kleopatra_debug.h"
75 #include "kleopatra_options.h"
77 #include <KDBusService>
79 #include <KLocalizedString>
80 #include <kiconloader.h>
81 #include <QSplashScreen>
82 #include <kmessagebox.h>
84 #include <QTextDocument> // for Qt::escape
85 #include <QMessageBox>
89 #include <QThreadPool>
91 #include <gpgme++/global.h>
92 #include <gpgme++/error.h>
94 #include <boost/shared_ptr.hpp>
98 #include <QCommandLineParser>
100 using namespace boost
;
102 static const int SPLASHSCREEN_TIMEOUT
= 5000; // 5s
106 template <typename T
>
107 boost::shared_ptr
<T
> make_shared_ptr(T
*t
)
109 return t
? boost::shared_ptr
<T
>(t
) : boost::shared_ptr
<T
>();
113 static QPixmap
UserIcon_nocached(const char *name
)
115 // KIconLoader insists on caching all pixmaps. Since the splash
116 // screen is a particularly large 'icon' and used only once,
117 // caching is unneccesary and just hurts startup performance.
118 KIconLoader
*const il
= KIconLoader::global();
120 const QString iconPath
= il
->iconPath(QLatin1String(name
), KIconLoader::User
);
121 return iconPath
.isEmpty() ? il
->unknown() : QPixmap(iconPath
);
124 #ifndef QT_NO_SPLASHSCREEN
125 class SplashScreen
: public QSplashScreen
130 : QSplashScreen(UserIcon_nocached("kleopatra_splashscreen"), Qt::WindowStaysOnTopHint
),
133 m_timer
.start(SPLASHSCREEN_TIMEOUT
, this);
137 void timerEvent(QTimerEvent
*ev
) Q_DECL_OVERRIDE
{
138 if (ev
->timerId() == m_timer
.timerId())
143 QSplashScreen::timerEvent(ev
);
149 class SplashScreen
{};
150 #endif // QT_NO_SPLASHSCREEN
152 static bool selfCheck(SplashScreen
&splash
)
154 #ifndef QT_NO_SPLASHSCREEN
155 splash
.showMessage(i18n("Performing Self-Check..."));
157 Kleo::Commands::SelfTestCommand
cmd(0);
158 cmd
.setAutoDelete(false);
159 cmd
.setAutomaticMode(true);
160 #ifndef QT_NO_SPLASHSCREEN
161 cmd
.setSplashScreen(&splash
);
164 QObject::connect(&cmd
, &Kleo::Commands::SelfTestCommand::finished
, &loop
, &QEventLoop::quit
);
165 #ifndef QT_NO_SPLASHSCREEN
166 QObject::connect(&cmd
, SIGNAL(info(QString
)), &splash
, SLOT(showMessage(QString
)));
168 QTimer::singleShot(0, &cmd
, &Kleo::Command::start
); // start() may Q_EMIT finished()...
170 if (cmd
.isCanceled()) {
171 #ifndef QT_NO_SPLASHSCREEN
172 splash
.showMessage(i18nc("did not pass", "Self-Check Failed"));
176 #ifndef QT_NO_SPLASHSCREEN
177 splash
.showMessage(i18n("Self-Check Passed"));
183 static void fillKeyCache(SplashScreen
*splash
, Kleo::UiServer
*server
)
187 Kleo::ReloadKeysCommand
*cmd
= new Kleo::ReloadKeysCommand(0);
188 QObject::connect(cmd
, &Kleo::Commands::SelfTestCommand::finished
, &loop
, &QEventLoop::quit
);
189 #ifdef HAVE_USABLE_ASSUAN
190 QObject::connect(cmd
, SIGNAL(finished()), server
, SLOT(enableCryptoCommands()));
194 #ifndef QT_NO_SPLASHSCREEN
195 splash
->showMessage(i18n("Loading certificate cache..."));
201 #ifndef QT_NO_SPLASHSCREEN
202 splash
->showMessage(i18n("Certificate cache loaded."));
206 int main(int argc
, char **argv
)
208 KleopatraApplication
app(argc
, argv
);
209 app
.setAttribute(Qt::AA_UseHighDpiPixmaps
, true);
214 KLocalizedString::setApplicationDomain("kleopatra");
216 KDBusService
service(KDBusService::Unique
);
217 QObject::connect(&service
, &KDBusService::activateRequested
,
218 &app
, &KleopatraApplication::slotActivateRequested
);
219 QObject::connect(&app
, &KleopatraApplication::setExitValue
,
220 &service
, [&service
](int i
) {
221 service
.setExitValue(i
);
226 KAboutData::setApplicationData(aboutData
);
228 QCommandLineParser parser
;
229 aboutData
.setupCommandLine(&parser
);
230 kleopatra_options(&parser
);
232 parser
.process(QApplication::arguments());
233 aboutData
.processCommandLine(&parser
);
235 Kdelibs4ConfigMigrator
migrate(QStringLiteral("kleopatra"));
236 migrate
.setConfigFiles(QStringList() << QStringLiteral("kleopatrarc")
237 << QStringLiteral("libkleopatrarc"));
238 migrate
.setUiFiles(QStringList() << QStringLiteral("kleopatra.rc"));
241 qCDebug(KLEOPATRA_LOG
) << "Startup timing:" << timer
.elapsed() << "ms elapsed: Application created";
244 const GpgME::Error gpgmeInitError
= GpgME::initializeLibrary(0);
247 const unsigned int threads
= QThreadPool::globalInstance()->maxThreadCount();
248 QThreadPool::globalInstance()->setMaxThreadCount(qMax(2U, threads
));
250 if (gpgmeInitError
) {
251 KMessageBox::sorry(0, xi18nc("@info",
252 "<para>The version of the <application>GpgME</application> library you are running against "
253 "is older than the one that the <application>GpgME++</application> library was built against.</para>"
254 "<para><application>Kleopatra</application> will not function in this setting.</para>"
255 "<para>Please ask your administrator for help in resolving this issue.</para>"),
256 i18nc("@title", "GpgME Too Old"));
262 Kleo::ChecksumDefinition::setInstallPath(Kleo::gpg4winInstallPath());
263 Kleo::ArchiveDefinition::setInstallPath(Kleo::gnupgInstallPath());
266 #ifdef HAVE_USABLE_ASSUAN
268 Kleo::UiServer
server(parser
.value(QStringLiteral("uiserver-socket")));
270 qCDebug(KLEOPATRA_LOG
) << "Startup timing:" << timer
.elapsed() << "ms elapsed: UiServer created";
272 QObject::connect(&server
, &Kleo::UiServer::startKeyManagerRequested
, &app
, &KleopatraApplication::openOrRaiseMainWindow
);
274 QObject::connect(&server
, &Kleo::UiServer::startConfigDialogRequested
, &app
, &KleopatraApplication::openOrRaiseConfigDialog
);
276 #define REGISTER( Command ) server.registerCommandFactory( boost::shared_ptr<Kleo::AssuanCommandFactory>( new Kleo::GenericAssuanCommandFactory<Kleo::Command> ) )
277 REGISTER(CreateChecksumsCommand
);
278 REGISTER(DecryptCommand
);
279 REGISTER(DecryptFilesCommand
);
280 REGISTER(DecryptVerifyFilesCommand
);
281 REGISTER(EchoCommand
);
282 REGISTER(EncryptCommand
);
283 REGISTER(EncryptFilesCommand
);
284 REGISTER(EncryptSignFilesCommand
);
285 REGISTER(ImportFilesCommand
);
286 REGISTER(PrepEncryptCommand
);
287 REGISTER(PrepSignCommand
);
288 REGISTER(SelectCertificateCommand
);
289 REGISTER(SignCommand
);
290 REGISTER(SignEncryptFilesCommand
);
291 REGISTER(SignFilesCommand
);
292 #ifndef QT_NO_DIRMODEL
293 REGISTER(VerifyChecksumsCommand
);
294 #endif // QT_NO_DIRMODEL
295 REGISTER(VerifyCommand
);
296 REGISTER(VerifyFilesCommand
);
300 qCDebug(KLEOPATRA_LOG
) << "Startup timing:" << timer
.elapsed() << "ms elapsed: UiServer started";
303 const bool daemon
= parser
.isSet(QStringLiteral("daemon"));
304 if (!daemon
&& app
.isSessionRestored()) {
305 app
.restoreMainWindow();
308 #ifndef QT_NO_SPLASHSCREEN
309 // Don't show splash screen if daemon or session restore
310 if (!(daemon
|| app
.isSessionRestored())) {
314 if (!selfCheck(splash
)) {
317 qCDebug(KLEOPATRA_LOG
) << "Startup timing:" << timer
.elapsed() << "ms elapsed: SelfCheck completed";
319 #ifdef HAVE_USABLE_ASSUAN
320 fillKeyCache(&splash
, &server
);
322 fillKeyCache(&splash
, 0);
324 qCDebug(KLEOPATRA_LOG
) << "Startup timing:" << timer
.elapsed() << "ms elapsed: KeyCache loaded";
326 #ifndef QT_NO_SYSTEMTRAYICON
327 app
.startMonitoringSmartCard();
330 app
.setIgnoreNewInstance(false);
333 const QString err
= app
.newInstance(parser
);
334 if (!err
.isEmpty()) {
335 std::cerr
<< i18n("Invalid arguments: %1", err
).toLocal8Bit().constData() << "\n";
338 qCDebug(KLEOPATRA_LOG
) << "Startup timing:" << timer
.elapsed() << "ms elapsed: new instance created";
339 #ifndef QT_NO_SPLASHSCREEN
340 splash
.finish(app
.mainWindow());
341 #endif // QT_NO_SPLASHSCREEN
346 #ifdef HAVE_USABLE_ASSUAN
347 app
.setIgnoreNewInstance(true);
348 QObject::disconnect(&server
, &Kleo::UiServer::startKeyManagerRequested
, &app
, &KleopatraApplication::openOrRaiseMainWindow
);
349 QObject::disconnect(&server
, &Kleo::UiServer::startConfigDialogRequested
, &app
, &KleopatraApplication::openOrRaiseConfigDialog
);
352 server
.waitForStopped();
353 } catch (const std::exception
&e
) {
354 QMessageBox::information(0, i18n("GPG UI Server Error"),
355 i18n("<qt>The Kleopatra GPG UI Server Module could not be initialized.<br/>"
356 "The error given was: <b>%1</b><br/>"
357 "You can use Kleopatra as a certificate manager, but cryptographic plugins that "
358 "rely on a GPG UI Server being present might not work correctly, or at all.</qt>",
359 QString::fromUtf8(e
.what()).toHtmlEscaped()));
360 #ifndef QT_NO_SYSTEMTRAYICON
361 app
.startMonitoringSmartCard();
363 app
.setIgnoreNewInstance(false);
365 app
.setIgnoreNewInstance(true);