ssl: Use QSslSocket directly to avoid redundant qobject_casts
[quassel.git] / src / core / core.cpp
index f793855..11563fd 100644 (file)
@@ -1,5 +1,5 @@
 /***************************************************************************
- *   Copyright (C) 2005-2018 by the Quassel Project                        *
+ *   Copyright (C) 2005-2020 by the Quassel Project                        *
  *   devel@quassel-irc.org                                                 *
  *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
  ***************************************************************************/
 
+#include "core.h"
+
 #include <algorithm>
 
 #include <QCoreApplication>
 
-#include "core.h"
 #include "coreauthhandler.h"
 #include "coresession.h"
 #include "coresettings.h"
-#include "logger.h"
 #include "internalpeer.h"
 #include "network.h"
 #include "postgresqlstorage.h"
 #include "quassel.h"
 #include "sqlauthenticator.h"
 #include "sqlitestorage.h"
+#include "types.h"
 #include "util.h"
 
-// Currently building with LDAP bindings is optional.
 #ifdef HAVE_LDAP
-#include "ldapauthenticator.h"
+#    include "ldapauthenticator.h"
 #endif
 
 // migration related
 #include <QFile>
 #ifdef Q_OS_WIN
-#  include <windows.h>
+#    include <windows.h>
 #else
-#  include <unistd.h>
-#  include <termios.h>
+#    include <termios.h>
+#    include <unistd.h>
 #endif /* Q_OS_WIN */
 
-#ifdef HAVE_UMASK
-#  include <sys/types.h>
-#  include <sys/stat.h>
-#endif /* HAVE_UMASK */
-
 // ==============================
 //  Custom Events
 // ==============================
@@ -62,61 +57,53 @@ const int Core::AddClientEventId = QEvent::registerEventType();
 class AddClientEvent : public QEvent
 {
 public:
-    AddClientEvent(RemotePeer *p, UserId uid) : QEvent(QEvent::Type(Core::AddClientEventId)), peer(p), userId(uid) {}
-    RemotePeer *peer;
+    AddClientEvent(RemotePeer* p, UserId uid)
+        : QEvent(QEvent::Type(Core::AddClientEventId))
+        , peer(p)
+        , userId(uid)
+    {}
+    RemotePeer* peer;
     UserId userId;
 };
 
-
 // ==============================
 //  Core
 // ==============================
-Core *Core::instanceptr = 0;
 
-Core *Core::instance()
+Core::Core()
+    : Singleton<Core>{this}
 {
-    if (instanceptr) return instanceptr;
-    instanceptr = new Core();
-    instanceptr->init();
-    return instanceptr;
-}
+    Q_INIT_RESOURCE(sql);
 
+    // Parent all QObject-derived attributes, so when the Core instance gets moved into another
+    // thread, they get moved with it
+    _server.setParent(this);
+    _v6server.setParent(this);
+    _storageSyncTimer.setParent(this);
+}
 
-void Core::destroy()
+Core::~Core()
 {
-    delete instanceptr;
-    instanceptr = 0;
+    qDeleteAll(_connectingClients);
+    qDeleteAll(_sessions);
+    syncStorage();
 }
 
-
-Core::Core()
+void Core::init()
 {
-#ifdef HAVE_UMASK
-    umask(S_IRWXG | S_IRWXO);
-#endif
-    _startTime = QDateTime::currentDateTime().toUTC(); // for uptime :)
-
-    Quassel::loadTranslation(QLocale::system());
+    _startTime = QDateTime::currentDateTime().toUTC();  // for uptime :)
 
     // check settings version
     // so far, we only have 1
     CoreSettings s;
     if (s.version() != 1) {
-        qCritical() << "Invalid core settings version, terminating!";
-        exit(EXIT_FAILURE);
+        throw ExitException{EXIT_FAILURE, tr("Invalid core settings version!")};
     }
 
     // Set up storage and authentication backends
     registerStorageBackends();
     registerAuthenticators();
 
-    connect(&_storageSyncTimer, SIGNAL(timeout()), this, SLOT(syncStorage()));
-    _storageSyncTimer.start(10 * 60 * 1000); // 10 minutes
-}
-
-
-void Core::init()
-{
     QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
     bool config_from_environment = Quassel::isOptionSet("config-from-environment");
 
@@ -131,7 +118,8 @@ void Core::init()
     if (config_from_environment) {
         db_backend = environment.value("DB_BACKEND");
         auth_authenticator = environment.value("AUTH_AUTHENTICATOR");
-    } else {
+    }
+    else {
         CoreSettings cs;
 
         QVariantMap dbsettings = cs.storageSettings().toMap();
@@ -145,138 +133,228 @@ void Core::init()
         writeError = !cs.isWritable();
     }
 
-    // legacy
-    _configured = initStorage(db_backend, db_connectionProperties, environment, config_from_environment);
-
-    // Not entirely sure what is 'legacy' about the above, but it seems to be the way things work!
-    if (_configured) {
-        initAuthenticator(auth_authenticator, auth_properties, environment, config_from_environment);
+    try {
+        _configured = initStorage(db_backend, db_connectionProperties, environment, config_from_environment);
+        if (_configured) {
+            _configured = initAuthenticator(auth_authenticator, auth_properties, environment, config_from_environment);
+        }
+    }
+    catch (ExitException) {
+        // Try again later
+        _configured = false;
     }
 
     if (Quassel::isOptionSet("select-backend") || Quassel::isOptionSet("select-authenticator")) {
+        bool success{true};
         if (Quassel::isOptionSet("select-backend")) {
-            selectBackend(Quassel::optionValue("select-backend"));
+            success &= selectBackend(Quassel::optionValue("select-backend"));
         }
         if (Quassel::isOptionSet("select-authenticator")) {
-            selectAuthenticator(Quassel::optionValue("select-authenticator"));
+            success &= selectAuthenticator(Quassel::optionValue("select-authenticator"));
         }
-        exit(EXIT_SUCCESS);
+        throw ExitException{success ? EXIT_SUCCESS : EXIT_FAILURE};
     }
 
     if (!_configured) {
         if (config_from_environment) {
-            _configured = initStorage(db_backend, db_connectionProperties, environment, config_from_environment, true);
-            initAuthenticator(auth_authenticator, auth_properties, environment, config_from_environment, true);
+            try {
+                _configured = initStorage(db_backend, db_connectionProperties, environment, config_from_environment, true);
+                if (_configured) {
+                    _configured = initAuthenticator(auth_authenticator, auth_properties, environment, config_from_environment, true);
+                }
+            }
+            catch (ExitException e) {
+                throw ExitException{EXIT_FAILURE, tr("Cannot configure from environment: %1").arg(e.errorString)};
+            }
 
             if (!_configured) {
-                qWarning() << "Cannot configure from environment";
-                exit(EXIT_FAILURE);
+                throw ExitException{EXIT_FAILURE, tr("Cannot configure from environment!")};
             }
-        } else {
+        }
+        else {
             if (_registeredStorageBackends.empty()) {
-                quWarning() << qPrintable(tr("Could not initialize any storage backend! Exiting..."));
-                quWarning()
-                        << qPrintable(tr("Currently, Quassel supports SQLite3 and PostgreSQL. You need to build your\n"
-                                         "Qt library with the sqlite or postgres plugin enabled in order for quasselcore\n"
-                                         "to work."));
-                exit(EXIT_FAILURE); // TODO make this less brutal (especially for mono client -> popup)
+                throw ExitException{EXIT_FAILURE,
+                                    tr("Could not initialize any storage backend! Exiting...\n"
+                                       "Currently, Quassel supports SQLite3 and PostgreSQL. You need to build your\n"
+                                       "Qt library with the sqlite or postgres plugin enabled in order for quasselcore\n"
+                                       "to work.")};
             }
-            quWarning() << "Core is currently not configured! Please connect with a Quassel Client for basic setup.";
 
             if (writeError) {
-                qWarning() << "Cannot write quasselcore configuration; probably a permission problem.";
-                exit(EXIT_FAILURE);
+                throw ExitException{EXIT_FAILURE, tr("Cannot write quasselcore configuration; probably a permission problem.")};
             }
+
+            qInfo() << "Core is currently not configured! Please connect with a Quassel Client for basic setup.";
         }
     }
 
-    if (Quassel::isOptionSet("add-user")) {
-        exit(createUser() ? EXIT_SUCCESS : EXIT_FAILURE);
+    // This checks separately because config-from-environment might have only configured the core just now
+    if (_configured) {
+        if (Quassel::isOptionSet("add-user")) {
+            bool success = createUser();
+            throw ExitException{success ? EXIT_SUCCESS : EXIT_FAILURE};
+        }
 
-    }
+        if (Quassel::isOptionSet("change-userpass")) {
+            bool success = changeUserPass(Quassel::optionValue("change-userpass"));
+            throw ExitException{success ? EXIT_SUCCESS : EXIT_FAILURE};
+        }
 
-    if (Quassel::isOptionSet("change-userpass")) {
-        exit(changeUserPass(Quassel::optionValue("change-userpass")) ?
-                       EXIT_SUCCESS : EXIT_FAILURE);
+        _strictIdentEnabled = Quassel::isOptionSet("strict-ident");
+        if (_strictIdentEnabled) {
+            cacheSysIdent();
+        }
+
+        if (Quassel::isOptionSet("oidentd")) {
+            _oidentdConfigGenerator = new OidentdConfigGenerator(this);
+        }
+
+        if (Quassel::isOptionSet("ident-daemon")) {
+            _identServer = new IdentServer(this);
+        }
+
+        if (Quassel::isOptionSet("metrics-daemon")) {
+            _metricsServer = new MetricsServer(this);
+            _server.setMetricsServer(_metricsServer);
+            _v6server.setMetricsServer(_metricsServer);
+        }
+
+        Quassel::registerReloadHandler([]() {
+            // Currently, only reloading SSL certificates and the sysident cache is supported
+            if (Core::instance()) {
+                Core::instance()->cacheSysIdent();
+                Core::instance()->reloadCerts();
+                return true;
+            }
+            return false;
+        });
+
+        connect(&_storageSyncTimer, &QTimer::timeout, this, &Core::syncStorage);
+        _storageSyncTimer.start(10 * 60 * 1000);  // 10 minutes
     }
 
-    connect(&_server, SIGNAL(newConnection()), this, SLOT(incomingConnection()));
-    connect(&_v6server, SIGNAL(newConnection()), this, SLOT(incomingConnection()));
-    if (!startListening()) exit(1);  // TODO make this less brutal
+    connect(&_server, &QTcpServer::newConnection, this, &Core::incomingConnection);
+    connect(&_v6server, &QTcpServer::newConnection, this, &Core::incomingConnection);
 
-    _strictIdentEnabled = Quassel::isOptionSet("strict-ident");
-    if (_strictIdentEnabled) {
-        cacheSysIdent();
+    if (!startListening()) {
+        throw ExitException{EXIT_FAILURE, tr("Cannot open port for listening!")};
     }
 
-    if (Quassel::isOptionSet("oidentd")) {
-        _oidentdConfigGenerator = new OidentdConfigGenerator(this);
+    if (_configured && !Quassel::isOptionSet("norestore")) {
+        Core::restoreState();
+    }
+
+    _initialized = true;
+
+    if (_pendingInternalConnection) {
+        connectInternalPeer(_pendingInternalConnection);
+        _pendingInternalConnection = {};
     }
 }
 
+void Core::initAsync()
+{
+    try {
+        init();
+    }
+    catch (ExitException e) {
+        emit exitRequested(e.exitCode, e.errorString);
+    }
+}
 
-Core::~Core()
+void Core::shutdown()
 {
-    // FIXME do we need more cleanup for handlers?
-    foreach(CoreAuthHandler *handler, _connectingClients) {
-        handler->deleteLater(); // disconnect non authed clients
+    qInfo() << "Core shutting down...";
+
+    saveState();
+
+    for (auto&& client : _connectingClients) {
+        client->deleteLater();
+    }
+    _connectingClients.clear();
+
+    if (_sessions.isEmpty()) {
+        emit shutdownComplete();
+        return;
+    }
+
+    for (auto&& session : _sessions) {
+        connect(session, &SessionThread::shutdownComplete, this, &Core::onSessionShutdown);
+        session->shutdown();
     }
-    qDeleteAll(_sessions);
 }
 
+void Core::onSessionShutdown(SessionThread* session)
+{
+    _sessions.take(_sessions.key(session))->deleteLater();
+    if (_sessions.isEmpty()) {
+        qInfo() << "Core shutdown complete!";
+        emit shutdownComplete();
+    }
+}
 
 /*** Session Restore ***/
 
 void Core::saveState()
 {
-    QVariantList activeSessions;
-    foreach(UserId user, instance()->_sessions.keys())
-        activeSessions << QVariant::fromValue<UserId>(user);
-    instance()->_storage->setCoreState(activeSessions);
+    if (_storage) {
+        QVariantList activeSessions;
+        for (auto&& user : instance()->_sessions.keys())
+            activeSessions << QVariant::fromValue(user);
+        _storage->setCoreState(activeSessions);
+    }
 }
 
-
 void Core::restoreState()
 {
-    if (!instance()->_configured) {
-        // quWarning() << qPrintable(tr("Cannot restore a state for an unconfigured core!"));
+    if (!_configured) {
+        qWarning() << qPrintable(tr("Cannot restore a state for an unconfigured core!"));
         return;
     }
-    if (instance()->_sessions.count()) {
-        quWarning() << qPrintable(tr("Calling restoreState() even though active sessions exist!"));
+    if (_sessions.count()) {
+        qWarning() << qPrintable(tr("Calling restoreState() even though active sessions exist!"));
         return;
     }
+
     CoreSettings s;
     /* We don't check, since we are at the first version since switching to Git
     uint statever = s.coreState().toMap()["CoreStateVersion"].toUInt();
     if(statever < 1) {
-      quWarning() << qPrintable(tr("Core state too old, ignoring..."));
+      qWarning() << qPrintable(tr("Core state too old, ignoring..."));
       return;
     }
     */
 
-    const QList<QVariant> &activeSessionsFallback = s.coreState().toMap()["ActiveSessions"].toList();
+    const QList<QVariant>activeSessionsFallback = s.coreState().toMap()["ActiveSessions"].toList();
     QVariantList activeSessions = instance()->_storage->getCoreState(activeSessionsFallback);
 
     if (activeSessions.count() > 0) {
-        quInfo() << "Restoring previous core state...";
-        foreach(QVariant v, activeSessions) {
+        qInfo() << "Restoring previous core state...";
+        for (auto&& v : activeSessions) {
             UserId user = v.value<UserId>();
-            instance()->sessionForUser(user, true);
+            sessionForUser(user, true);
         }
     }
 }
 
-
 /*** Core Setup ***/
 
-QString Core::setup(const QString &adminUser, const QString &adminPassword, const QString &backend, const QVariantMap &setupData, const QString &authenticator, const QVariantMap &authSetupData)
+QString Core::setup(const QString& adminUser,
+                    const QString& adminPassword,
+                    const QString& backend,
+                    const QVariantMap& setupData,
+                    const QString& authenticator,
+                    const QVariantMap& authSetupData)
 {
     return instance()->setupCore(adminUser, adminPassword, backend, setupData, authenticator, authSetupData);
 }
 
-
-QString Core::setupCore(const QString &adminUser, const QString &adminPassword, const QString &backend, const QVariantMap &setupData, const QString &authenticator, const QVariantMap &authSetupData)
+QString Core::setupCore(const QString& adminUser,
+                        const QString& adminPassword,
+                        const QString& backend,
+                        const QVariantMap& setupData,
+                        const QString& authenticator,
+                        const QVariantMap& authSetupData)
 {
     if (_configured)
         return tr("Core is already configured! Not configuring again...");
@@ -284,14 +362,20 @@ QString Core::setupCore(const QString &adminUser, const QString &adminPassword,
     if (adminUser.isEmpty() || adminPassword.isEmpty()) {
         return tr("Admin user or password not set.");
     }
-    if (!(_configured = initStorage(backend, setupData, {}, false, true))) {
-        return tr("Could not setup storage!");
-    }
+    try {
+        if (!(_configured = initStorage(backend, setupData, {}, false, true))) {
+            return tr("Could not setup storage!");
+        }
 
-    quInfo() << "Selected authenticator:" << authenticator;
-    if (!(_configured = initAuthenticator(authenticator, authSetupData, {}, false, true)))
-    {
-        return tr("Could not setup authenticator!");
+        qInfo() << "Selected authenticator:" << authenticator;
+        if (!(_configured = initAuthenticator(authenticator, authSetupData, {}, false, true))) {
+            return tr("Could not setup authenticator!");
+        }
+    }
+    catch (ExitException e) {
+        // Event loop is running, so trigger an exit rather than throwing an exception
+        QCoreApplication::exit(e.exitCode);
+        return e.errorString.isEmpty() ? tr("Fatal failure while trying to setup, terminating") : e.errorString;
     }
 
     if (!saveBackendSettings(backend, setupData)) {
@@ -299,14 +383,13 @@ QString Core::setupCore(const QString &adminUser, const QString &adminPassword,
     }
     saveAuthenticatorSettings(authenticator, authSetupData);
 
-    quInfo() << qPrintable(tr("Creating admin user..."));
+    qInfo() << qPrintable(tr("Creating admin user..."));
     _storage->addUser(adminUser, adminPassword);
     cacheSysIdent();
-    startListening(); // TODO check when we need this
+    startListening();  // TODO check when we need this
     return QString();
 }
 
-
 QString Core::setupCoreForInternalUsage()
 {
     Q_ASSERT(!_registeredStorageBackends.empty());
@@ -322,7 +405,6 @@ QString Core::setupCoreForInternalUsage()
     return setupCore("AdminUser", QString::number(pass), "SQLite", QVariantMap(), "Database", QVariantMap());
 }
 
-
 /*** Storage Handling ***/
 
 template<typename Storage>
@@ -335,7 +417,6 @@ void Core::registerStorageBackend()
         backend->deleteLater();
 }
 
-
 void Core::registerStorageBackends()
 {
     if (_registeredStorageBackends.empty()) {
@@ -344,23 +425,19 @@ void Core::registerStorageBackends()
     }
 }
 
-
-DeferredSharedPtr<Storage> Core::storageBackend(const QString &backendId) const
+DeferredSharedPtr<Storage> Core::storageBackend(const QString& backendId) const
 {
-    auto it = std::find_if(_registeredStorageBackends.begin(), _registeredStorageBackends.end(),
-                           [backendId](const DeferredSharedPtr<Storage> &backend) {
-                               return backend->displayName() == backendId;
-                           });
+    auto it = std::find_if(_registeredStorageBackends.begin(),
+                           _registeredStorageBackends.end(),
+                           [backendId](const DeferredSharedPtr<Storage>& backend) { return backend->displayName() == backendId; });
     return it != _registeredStorageBackends.end() ? *it : nullptr;
 }
 
-// old db settings:
-// "Type" => "sqlite"
-bool Core::initStorage(const QString &backend, const QVariantMap &settings,
-                       const QProcessEnvironment &environment, bool loadFromEnvironment, bool setup)
+bool Core::initStorage(
+    const QString& backend, const QVariantMap& settings, const QProcessEnvironment& environment, bool loadFromEnvironment, bool setup)
 {
     if (backend.isEmpty()) {
-        quWarning() << "No storage backend selected!";
+        qWarning() << "No storage backend selected!";
         return false;
     }
 
@@ -370,6 +447,8 @@ bool Core::initStorage(const QString &backend, const QVariantMap &settings,
         return false;
     }
 
+    connect(storage.get(), &Storage::dbUpgradeInProgress, this, &Core::dbUpgradeInProgress);
+
     Storage::State storageState = storage->init(settings, environment, loadFromEnvironment);
     switch (storageState) {
     case Storage::NeedsSetup:
@@ -379,34 +458,32 @@ bool Core::initStorage(const QString &backend, const QVariantMap &settings,
             return initStorage(backend, settings, environment, loadFromEnvironment, false);
         return false;
 
-    // if initialization wasn't successful, we quit to keep from coming up unconfigured
     case Storage::NotAvailable:
-        qCritical() << "FATAL: Selected storage backend is not available:" << backend;
-        if (!setup)
-            exit(EXIT_FAILURE);
+        if (!setup) {
+            // If initialization wasn't successful, we quit to keep from coming up unconfigured
+            throw ExitException{EXIT_FAILURE, tr("Selected storage backend %1 is not available.").arg(backend)};
+        }
+        qCritical() << "Selected storage backend is not available:" << backend;
         return false;
 
     case Storage::IsReady:
         // delete all other backends
         _registeredStorageBackends.clear();
-        connect(storage.get(), SIGNAL(bufferInfoUpdated(UserId, const BufferInfo &)),
-                this, SIGNAL(bufferInfoUpdated(UserId, const BufferInfo &)));
+        connect(storage.get(), &Storage::bufferInfoUpdated, this, &Core::bufferInfoUpdated);
         break;
     }
     _storage = std::move(storage);
     return true;
 }
 
-
 void Core::syncStorage()
 {
     if (_storage)
         _storage->sync();
 }
 
-
 /*** Storage Access ***/
-bool Core::createNetwork(UserId user, NetworkInfo &info)
+bool Core::createNetwork(UserId user, NetworkInfoinfo)
 {
     NetworkId networkId = instance()->_storage->createNetwork(user, info);
     if (!networkId.isValid())
@@ -416,7 +493,6 @@ bool Core::createNetwork(UserId user, NetworkInfo &info)
     return true;
 }
 
-
 /*** Authenticators ***/
 
 // Authentication handling, now independent from storage.
@@ -430,7 +506,6 @@ void Core::registerAuthenticator()
         authenticator->deleteLater();
 }
 
-
 void Core::registerAuthenticators()
 {
     if (_registeredAuthenticators.empty()) {
@@ -441,25 +516,23 @@ void Core::registerAuthenticators()
     }
 }
 
-
-DeferredSharedPtr<Authenticator> Core::authenticator(const QString &backendId) const
+DeferredSharedPtr<Authenticator> Core::authenticator(const QString& backendId) const
 {
-    auto it = std::find_if(_registeredAuthenticators.begin(), _registeredAuthenticators.end(),
-                           [backendId](const DeferredSharedPtr<Authenticator> &authenticator) {
+    auto it = std::find_if(_registeredAuthenticators.begin(),
+                           _registeredAuthenticators.end(),
+                           [backendId](const DeferredSharedPtr<Authenticator>& authenticator) {
                                return authenticator->backendId() == backendId;
                            });
     return it != _registeredAuthenticators.end() ? *it : nullptr;
 }
 
-
 // FIXME: Apparently, this is the legacy way of initting storage backends?
 // If there's a not-legacy way, it should be used here
-bool Core::initAuthenticator(const QString &backend, const QVariantMap &settings,
-                             const QProcessEnvironment &environment, bool loadFromEnvironment,
-                             bool setup)
+bool Core::initAuthenticator(
+    const QString& backend, const QVariantMap& settings, const QProcessEnvironment& environment, bool loadFromEnvironment, bool setup)
 {
     if (backend.isEmpty()) {
-        quWarning() << "No authenticator selected!";
+        qWarning() << "No authenticator selected!";
         return false;
     }
 
@@ -478,11 +551,12 @@ bool Core::initAuthenticator(const QString &backend, const QVariantMap &settings
             return initAuthenticator(backend, settings, environment, loadFromEnvironment, false);
         return false;
 
-    // if initialization wasn't successful, we quit to keep from coming up unconfigured
     case Authenticator::NotAvailable:
-        qCritical() << "FATAL: Selected auth backend is not available:" << backend;
-        if (!setup)
-            exit(EXIT_FAILURE);
+        if (!setup) {
+            // If initialization wasn't successful, we quit to keep from coming up unconfigured
+            throw ExitException{EXIT_FAILURE, tr("Selected auth backend %1 is not available.").arg(backend)};
+        }
+        qCritical() << "Selected auth backend is not available:" << backend;
         return false;
 
     case Authenticator::IsReady:
@@ -494,45 +568,28 @@ bool Core::initAuthenticator(const QString &backend, const QVariantMap &settings
     return true;
 }
 
-
 /*** Network Management ***/
 
 bool Core::sslSupported()
 {
-#ifdef HAVE_SSL
-    SslServer *sslServer = qobject_cast<SslServer *>(&instance()->_server);
-    return sslServer && sslServer->isCertValid();
-#else
-    return false;
-#endif
+    return instance()->_server.isCertValid() && instance()->_v6server.isCertValid();
 }
 
-
 bool Core::reloadCerts()
 {
-#ifdef HAVE_SSL
-    SslServer *sslServerv4 = qobject_cast<SslServer *>(&instance()->_server);
-    bool retv4 = sslServerv4->reloadCerts();
-
-    SslServer *sslServerv6 = qobject_cast<SslServer *>(&instance()->_v6server);
-    bool retv6 = sslServerv6->reloadCerts();
+    bool retv4 = _server.reloadCerts();
+    bool retv6 = _v6server.reloadCerts();
 
     return retv4 && retv6;
-#else
-    // SSL not supported, don't mark configuration reload as failed
-    return true;
-#endif
 }
 
-
 void Core::cacheSysIdent()
 {
     if (isConfigured()) {
-        instance()->_authUserNames = instance()->_storage->getAllAuthUserNames();
+        _authUserNames = _storage->getAllAuthUserNames();
     }
 }
 
-
 QString Core::strictSysIdent(UserId user) const
 {
     if (_authUserNames.contains(user)) {
@@ -541,7 +598,7 @@ QString Core::strictSysIdent(UserId user) const
 
     // A new user got added since we last pulled our cache from the database.
     // There's no way to avoid a database hit - we don't even know the authname!
-    cacheSysIdent();
+    instance()->cacheSysIdent();
 
     if (_authUserNames.contains(user)) {
         return _authUserNames[user];
@@ -549,10 +606,9 @@ QString Core::strictSysIdent(UserId user) const
 
     // ...something very weird is going on if we ended up here (an active CoreSession without a corresponding database entry?)
     qWarning().nospace() << "Unable to find authusername for UserId " << user << ", this should never happen!";
-    return "unknown"; // Should we just terminate the program instead?
+    return "unknown";  // Should we just terminate the program instead?
 }
 
-
 bool Core::startListening()
 {
     // in mono mode we only start a local port if a port is specified in the cli call
@@ -565,72 +621,69 @@ bool Core::startListening()
     const QString listen = Quassel::optionValue("listen");
     const QStringList listen_list = listen.split(",", QString::SkipEmptyParts);
     if (listen_list.size() > 0) {
-        foreach(const QString listen_term, listen_list) { // TODO: handle multiple interfaces for same TCP version gracefully
+        foreach (const QString listen_term, listen_list) {  // TODO: handle multiple interfaces for same TCP version gracefully
             QHostAddress addr;
             if (!addr.setAddress(listen_term)) {
-                qCritical() << qPrintable(
-                    tr("Invalid listen address %1")
-                    .arg(listen_term)
-                    );
+                qCritical() << qPrintable(tr("Invalid listen address %1").arg(listen_term));
             }
             else {
                 switch (addr.protocol()) {
                 case QAbstractSocket::IPv6Protocol:
                     if (_v6server.listen(addr, port)) {
-                        quInfo() << qPrintable(
-                            tr("Listening for GUI clients on IPv6 %1 port %2 using protocol version %3")
-                            .arg(addr.toString())
-                            .arg(_v6server.serverPort())
-                            .arg(Quassel::buildInfo().protocolVersion)
-                            );
+                        qInfo() << qPrintable(tr("Listening for GUI clients on IPv6 %1 port %2 using protocol version %3")
+                                              .arg(addr.toString())
+                                              .arg(_v6server.serverPort())
+                                              .arg(Quassel::buildInfo().protocolVersion));
                         success = true;
                     }
                     else
-                        quWarning() << qPrintable(
-                            tr("Could not open IPv6 interface %1:%2: %3")
-                            .arg(addr.toString())
-                            .arg(port)
-                            .arg(_v6server.errorString()));
+                        qWarning() << qPrintable(tr("Could not open IPv6 interface %1:%2: %3").arg(addr.toString()).arg(port).arg(_v6server.errorString()));
                     break;
                 case QAbstractSocket::IPv4Protocol:
                     if (_server.listen(addr, port)) {
-                        quInfo() << qPrintable(
-                            tr("Listening for GUI clients on IPv4 %1 port %2 using protocol version %3")
-                            .arg(addr.toString())
-                            .arg(_server.serverPort())
-                            .arg(Quassel::buildInfo().protocolVersion)
-                            );
+                        qInfo() << qPrintable(tr("Listening for GUI clients on IPv4 %1 port %2 using protocol version %3")
+                                              .arg(addr.toString())
+                                              .arg(_server.serverPort())
+                                              .arg(Quassel::buildInfo().protocolVersion));
                         success = true;
                     }
                     else {
                         // if v6 succeeded on Any, the port will be already in use - don't display the error then
                         if (!success || _server.serverError() != QAbstractSocket::AddressInUseError)
-                            quWarning() << qPrintable(
-                                tr("Could not open IPv4 interface %1:%2: %3")
-                                .arg(addr.toString())
-                                .arg(port)
-                                .arg(_server.errorString()));
+                            qWarning() << qPrintable(tr("Could not open IPv4 interface %1:%2: %3").arg(addr.toString()).arg(port).arg(_server.errorString()));
                     }
                     break;
                 default:
-                    qCritical() << qPrintable(
-                        tr("Invalid listen address %1, unknown network protocol")
-                        .arg(listen_term)
-                        );
+                    qCritical() << qPrintable(tr("Invalid listen address %1, unknown network protocol").arg(listen_term));
                     break;
                 }
             }
         }
     }
     if (!success)
-        quError() << qPrintable(tr("Could not open any network interfaces to listen on!"));
+        qCritical() << qPrintable(tr("Could not open any network interfaces to listen on!"));
+
+    if (_identServer) {
+        _identServer->startListening();
+    }
+
+    if (_metricsServer) {
+        _metricsServer->startListening();
+    }
 
     return success;
 }
 
-
-void Core::stopListening(const QString &reason)
+void Core::stopListening(const QString& reason)
 {
+    if (_identServer) {
+        _identServer->stopListening(reason);
+    }
+
+    if (_metricsServer) {
+        _metricsServer->stopListening(reason);
+    }
+
     bool wasListening = false;
     if (_server.isListening()) {
         wasListening = true;
@@ -642,28 +695,28 @@ void Core::stopListening(const QString &reason)
     }
     if (wasListening) {
         if (reason.isEmpty())
-            quInfo() << "No longer listening for GUI clients.";
+            qInfo() << "No longer listening for GUI clients.";
         else
-            quInfo() << qPrintable(reason);
+            qInfo() << qPrintable(reason);
     }
 }
 
-
 void Core::incomingConnection()
 {
-    QTcpServer *server = qobject_cast<QTcpServer *>(sender());
+    auto* server = qobject_cast<SslServer*>(sender());
     Q_ASSERT(server);
     while (server->hasPendingConnections()) {
-        QTcpSocket *socket = server->nextPendingConnection();
+        auto socket = qobject_cast<QSslSocket*>(server->nextPendingConnection());
+        Q_ASSERT(socket);
 
-        CoreAuthHandler *handler = new CoreAuthHandler(socket, this);
+        auto* handler = new CoreAuthHandler(socket, this);
         _connectingClients.insert(handler);
 
-        connect(handler, SIGNAL(disconnected()), SLOT(clientDisconnected()));
-        connect(handler, SIGNAL(socketError(QAbstractSocket::SocketError,QString)), SLOT(socketError(QAbstractSocket::SocketError,QString)));
-        connect(handler, SIGNAL(handshakeComplete(RemotePeer*,UserId)), SLOT(setupClientSession(RemotePeer*,UserId)));
+        connect(handler, &AuthHandler::disconnected, this, &Core::clientDisconnected);
+        connect(handler, &AuthHandler::socketError, this, &Core::socketError);
+        connect(handler, &CoreAuthHandler::handshakeComplete, this, &Core::setupClientSession);
 
-        quInfo() << qPrintable(tr("Client connected from"))  << qPrintable(socket->peerAddress().toString());
+        qInfo() << qPrintable(tr("Client connected from")) << qPrintable(handler->hostAddress().toString());
 
         if (!_configured) {
             stopListening(tr("Closing server for basic setup."));
@@ -671,14 +724,13 @@ void Core::incomingConnection()
     }
 }
 
-
 // Potentially called during the initialization phase (before handing the connection off to the session)
 void Core::clientDisconnected()
 {
-    CoreAuthHandler *handler = qobject_cast<CoreAuthHandler *>(sender());
+    auto* handler = qobject_cast<CoreAuthHandler*>(sender());
     Q_ASSERT(handler);
 
-    quInfo() << qPrintable(tr("Non-authed client disconnected:")) << qPrintable(handler->socket()->peerAddress().toString());
+    qInfo() << qPrintable(tr("Non-authed client disconnected:")) << qPrintable(handler->hostAddress().toString());
     _connectingClients.remove(handler);
     handler->deleteLater();
 
@@ -691,14 +743,13 @@ void Core::clientDisconnected()
     // Suggestion: kill sessions if they are not connected to any network and client.
 }
 
-
-void Core::setupClientSession(RemotePeer *peer, UserId uid)
+void Core::setupClientSession(RemotePeer* peer, UserId uid)
 {
-    CoreAuthHandler *handler = qobject_cast<CoreAuthHandler *>(sender());
+    auto* handler = qobject_cast<CoreAuthHandler*>(sender());
     Q_ASSERT(handler);
 
     // From now on everything is handled by the client session
-    disconnect(handler, 0, this, 0);
+    disconnect(handler, nullptr, this, nullptr);
     _connectingClients.remove(handler);
     handler->deleteLater();
 
@@ -710,30 +761,41 @@ void Core::setupClientSession(RemotePeer *peer, UserId uid)
     QCoreApplication::postEvent(this, new AddClientEvent(peer, uid));
 }
 
-
-void Core::customEvent(QEvent *event)
+void Core::customEvent(QEvent* event)
 {
     if (event->type() == AddClientEventId) {
-        AddClientEvent *addClientEvent = static_cast<AddClientEvent *>(event);
+        auto* addClientEvent = static_cast<AddClientEvent*>(event);
         addClientHelper(addClientEvent->peer, addClientEvent->userId);
         return;
     }
 }
 
-
-void Core::addClientHelper(RemotePeer *peer, UserId uid)
+void Core::addClientHelper(RemotePeer* peer, UserId uid)
 {
     // Find or create session for validated user
-    SessionThread *session = sessionForUser(uid);
+    SessionThreadsession = sessionForUser(uid);
     session->addClient(peer);
 }
 
+void Core::connectInternalPeer(QPointer<InternalPeer> peer)
+{
+    if (_initialized && peer) {
+        setupInternalClientSession(peer);
+    }
+    else {
+        _pendingInternalConnection = peer;
+    }
+}
 
-void Core::setupInternalClientSession(InternalPeer *clientPeer)
+void Core::setupInternalClientSession(QPointer<InternalPeer> clientPeer)
 {
     if (!_configured) {
         stopListening();
-        setupCoreForInternalUsage();
+        auto errorString = setupCoreForInternalUsage();
+        if (!errorString.isEmpty()) {
+            emit exitRequested(EXIT_FAILURE, errorString);
+            return;
+        }
     }
 
     UserId uid;
@@ -741,99 +803,98 @@ void Core::setupInternalClientSession(InternalPeer *clientPeer)
         uid = _storage->internalUser();
     }
     else {
-        quWarning() << "Core::setupInternalClientSession(): You're trying to run monolithic Quassel with an unusable Backend! Go fix it!";
+        qWarning() << "Core::setupInternalClientSession(): You're trying to run monolithic Quassel with an unusable Backend! Go fix it!";
+        emit exitRequested(EXIT_FAILURE, tr("Cannot setup storage backend."));
+        return;
+    }
+
+    if (!clientPeer) {
+        qWarning() << "Client peer went away, not starting a session";
         return;
     }
 
-    InternalPeer *corePeer = new InternalPeer(this);
+    auto* corePeer = new InternalPeer(this);
     corePeer->setPeer(clientPeer);
     clientPeer->setPeer(corePeer);
 
     // Find or create session for validated user
-    SessionThread *sessionThread = sessionForUser(uid);
+    SessionThreadsessionThread = sessionForUser(uid);
     sessionThread->addClient(corePeer);
 }
 
-
-SessionThread *Core::sessionForUser(UserId uid, bool restore)
+SessionThread* Core::sessionForUser(UserId uid, bool restore)
 {
     if (_sessions.contains(uid))
         return _sessions[uid];
 
-    SessionThread *session = new SessionThread(uid, restore, strictIdentEnabled(), this);
-    _sessions[uid] = session;
-    session->start();
-    return session;
+    return (_sessions[uid] = new SessionThread(uid, restore, strictIdentEnabled(), this));
 }
 
-
-void Core::socketError(QAbstractSocket::SocketError err, const QString &errorString)
+void Core::socketError(QAbstractSocket::SocketError err, const QString& errorString)
 {
-    quWarning() << QString("Socket error %1: %2").arg(err).arg(errorString);
+    qWarning() << QString("Socket error %1: %2").arg(err).arg(errorString);
 }
 
-
 QVariantList Core::backendInfo()
 {
     instance()->registerStorageBackends();
 
     QVariantList backendInfos;
-    for (auto &&backend : instance()->_registeredStorageBackends) {
+    for (auto&& backend : instance()->_registeredStorageBackends) {
         QVariantMap v;
-        v["BackendId"]   = backend->backendId();
+        v["BackendId"] = backend->backendId();
         v["DisplayName"] = backend->displayName();
         v["Description"] = backend->description();
-        v["SetupData"]   = backend->setupData(); // ignored by legacy clients
+        v["SetupData"] = backend->setupData();  // ignored by legacy clients
 
         // TODO Protocol Break: Remove legacy (cf. authenticatorInfo())
-        const auto &setupData = backend->setupData();
+        const autosetupData = backend->setupData();
         QStringList setupKeys;
         QVariantMap setupDefaults;
         for (int i = 0; i + 2 < setupData.size(); i += 3) {
             setupKeys << setupData[i].toString();
             setupDefaults[setupData[i].toString()] = setupData[i + 2];
         }
-        v["SetupKeys"]     = setupKeys;
+        v["SetupKeys"] = setupKeys;
         v["SetupDefaults"] = setupDefaults;
         // TODO Protocol Break: Remove
-        v["IsDefault"]     = (backend->backendId() == "SQLite"); // newer clients will just use the first in the list
+        v["IsDefault"] = (backend->backendId() == "SQLite");  // newer clients will just use the first in the list
 
         backendInfos << v;
     }
     return backendInfos;
 }
 
-
 QVariantList Core::authenticatorInfo()
 {
     instance()->registerAuthenticators();
 
     QVariantList authInfos;
-    for(auto &&backend : instance()->_registeredAuthenticators) {
+    for (auto&& backend : instance()->_registeredAuthenticators) {
         QVariantMap v;
-        v["BackendId"]   = backend->backendId();
+        v["BackendId"] = backend->backendId();
         v["DisplayName"] = backend->displayName();
         v["Description"] = backend->description();
-        v["SetupData"]   = backend->setupData();
+        v["SetupData"] = backend->setupData();
         authInfos << v;
     }
     return authInfos;
 }
 
 // migration / backend selection
-bool Core::selectBackend(const QString &backend)
+bool Core::selectBackend(const QStringbackend)
 {
     // reregister all storage backends
     registerStorageBackends();
     auto storage = storageBackend(backend);
     if (!storage) {
         QStringList backends;
-        std::transform(_registeredStorageBackends.begin(), _registeredStorageBackends.end(),
-                       std::back_inserter(backends), [](const DeferredSharedPtr<Storage>& backend) {
-                           return backend->displayName();
-                       });
-        quWarning() << qPrintable(tr("Unsupported storage backend: %1").arg(backend));
-        quWarning() << qPrintable(tr("Supported backends are:")) << qPrintable(backends.join(", "));
+        std::transform(_registeredStorageBackends.begin(),
+                       _registeredStorageBackends.end(),
+                       std::back_inserter(backends),
+                       [](const DeferredSharedPtr<Storage>& backend) { return backend->displayName(); });
+        qWarning() << qPrintable(tr("Unsupported storage backend: %1").arg(backend));
+        qWarning() << qPrintable(tr("Supported backends are:")) << qPrintable(backends.join(", "));
         return false;
     }
 
@@ -845,27 +906,27 @@ bool Core::selectBackend(const QString &backend)
         if (!saveBackendSettings(backend, settings)) {
             qCritical() << qPrintable(QString("Could not save backend settings, probably a permission problem."));
         }
-        quWarning() << qPrintable(tr("Switched storage backend to: %1").arg(backend));
-        quWarning() << qPrintable(tr("Backend already initialized. Skipping Migration..."));
+        qWarning() << qPrintable(tr("Switched storage backend to: %1").arg(backend));
+        qWarning() << qPrintable(tr("Backend already initialized. Skipping Migration..."));
         return true;
     case Storage::NotAvailable:
         qCritical() << qPrintable(tr("Storage backend is not available: %1").arg(backend));
         return false;
     case Storage::NeedsSetup:
         if (!storage->setup(settings)) {
-            quWarning() << qPrintable(tr("Unable to setup storage backend: %1").arg(backend));
+            qWarning() << qPrintable(tr("Unable to setup storage backend: %1").arg(backend));
             return false;
         }
 
         if (storage->init(settings) != Storage::IsReady) {
-            quWarning() << qPrintable(tr("Unable to initialize storage backend: %1").arg(backend));
+            qWarning() << qPrintable(tr("Unable to initialize storage backend: %1").arg(backend));
             return false;
         }
 
         if (!saveBackendSettings(backend, settings)) {
             qCritical() << qPrintable(QString("Could not save backend settings, probably a permission problem."));
         }
-        quWarning() << qPrintable(tr("Switched storage backend to: %1").arg(backend));
+        qWarning() << qPrintable(tr("Switched storage backend to: %1").arg(backend));
         break;
     }
 
@@ -885,19 +946,19 @@ bool Core::selectBackend(const QString &backend)
             }
             return true;
         }
-        quWarning() << qPrintable(tr("Unable to migrate storage backend! (No migration writer for %1)").arg(backend));
+        qWarning() << qPrintable(tr("Unable to migrate storage backend! (No migration writer for %1)").arg(backend));
         return false;
     }
 
     // inform the user why we cannot merge
     if (!_storage) {
-        quWarning() << qPrintable(tr("No currently active storage backend. Skipping migration..."));
+        qWarning() << qPrintable(tr("No currently active storage backend. Skipping migration..."));
     }
     else if (!reader) {
-        quWarning() << qPrintable(tr("Currently active storage backend does not support migration: %1").arg(_storage->displayName()));
+        qWarning() << qPrintable(tr("Currently active storage backend does not support migration: %1").arg(_storage->displayName()));
     }
     if (writer) {
-        quWarning() << qPrintable(tr("New storage backend does not support migration: %1").arg(backend));
+        qWarning() << qPrintable(tr("New storage backend does not support migration: %1").arg(backend));
     }
 
     // so we were unable to merge, but let's create a user \o/
@@ -908,19 +969,19 @@ bool Core::selectBackend(const QString &backend)
 
 // TODO: I am not sure if this function is implemented correctly.
 // There is currently no concept of migraiton between auth backends.
-bool Core::selectAuthenticator(const QString &backend)
+bool Core::selectAuthenticator(const QStringbackend)
 {
     // Register all authentication backends.
     registerAuthenticators();
     auto auther = authenticator(backend);
     if (!auther) {
         QStringList authenticators;
-        std::transform(_registeredAuthenticators.begin(), _registeredAuthenticators.end(),
-                       std::back_inserter(authenticators), [](const DeferredSharedPtr<Authenticator>& authenticator) {
-                           return authenticator->displayName();
-                       });
-        quWarning() << qPrintable(tr("Unsupported authenticator: %1").arg(backend));
-        quWarning() << qPrintable(tr("Supported authenticators are:")) << qPrintable(authenticators.join(", "));
+        std::transform(_registeredAuthenticators.begin(),
+                       _registeredAuthenticators.end(),
+                       std::back_inserter(authenticators),
+                       [](const DeferredSharedPtr<Authenticator>& authenticator) { return authenticator->displayName(); });
+        qWarning() << qPrintable(tr("Unsupported authenticator: %1").arg(backend));
+        qWarning() << qPrintable(tr("Supported authenticators are:")) << qPrintable(authenticators.join(", "));
         return false;
     }
 
@@ -930,31 +991,30 @@ bool Core::selectAuthenticator(const QString &backend)
     switch (state) {
     case Authenticator::IsReady:
         saveAuthenticatorSettings(backend, settings);
-        quWarning() << qPrintable(tr("Switched authenticator to: %1").arg(backend));
+        qWarning() << qPrintable(tr("Switched authenticator to: %1").arg(backend));
         return true;
     case Authenticator::NotAvailable:
         qCritical() << qPrintable(tr("Authenticator is not available: %1").arg(backend));
         return false;
     case Authenticator::NeedsSetup:
         if (!auther->setup(settings)) {
-            quWarning() << qPrintable(tr("Unable to setup authenticator: %1").arg(backend));
+            qWarning() << qPrintable(tr("Unable to setup authenticator: %1").arg(backend));
             return false;
         }
 
         if (auther->init(settings) != Authenticator::IsReady) {
-            quWarning() << qPrintable(tr("Unable to initialize authenticator: %1").arg(backend));
+            qWarning() << qPrintable(tr("Unable to initialize authenticator: %1").arg(backend));
             return false;
         }
 
         saveAuthenticatorSettings(backend, settings);
-        quWarning() << qPrintable(tr("Switched authenticator to: %1").arg(backend));
+        qWarning() << qPrintable(tr("Switched authenticator to: %1").arg(backend));
     }
 
     _authenticator = std::move(auther);
     return true;
 }
 
-
 bool Core::createUser()
 {
     QTextStream out(stdout);
@@ -976,11 +1036,11 @@ bool Core::createUser()
     enableStdInEcho();
 
     if (password != password2) {
-        quWarning() << "Passwords don't match!";
+        qWarning() << "Passwords don't match!";
         return false;
     }
     if (password.isEmpty()) {
-        quWarning() << "Password is empty!";
+        qWarning() << "Password is empty!";
         return false;
     }
 
@@ -989,13 +1049,12 @@ bool Core::createUser()
         return true;
     }
     else {
-        quWarning() << "Unable to add user:" << qPrintable(username);
+        qWarning() << "Unable to add user:" << qPrintable(username);
         return false;
     }
 }
 
-
-bool Core::changeUserPass(const QString &username)
+bool Core::changeUserPass(const QString& username)
 {
     QTextStream out(stdout);
     QTextStream in(stdin);
@@ -1024,11 +1083,11 @@ bool Core::changeUserPass(const QString &username)
     enableStdInEcho();
 
     if (password != password2) {
-        quWarning() << "Passwords don't match!";
+        qWarning() << "Passwords don't match!";
         return false;
     }
     if (password.isEmpty()) {
-        quWarning() << "Password is empty!";
+        qWarning() << "Password is empty!";
         return false;
     }
 
@@ -1037,13 +1096,12 @@ bool Core::changeUserPass(const QString &username)
         return true;
     }
     else {
-        quWarning() << "Failed to change password!";
+        qWarning() << "Failed to change password!";
         return false;
     }
 }
 
-
-bool Core::changeUserPassword(UserId userId, const QString &password)
+bool Core::changeUserPassword(UserId userId, const QString& password)
 {
     if (!isConfigured() || !userId.isValid())
         return false;
@@ -1072,13 +1130,12 @@ bool Core::canChangeUserPassword(UserId userId)
     return true;
 }
 
-
-std::unique_ptr<AbstractSqlMigrationReader> Core::getMigrationReader(Storage *storage)
+std::unique_ptr<AbstractSqlMigrationReader> Core::getMigrationReader(Storage* storage)
 {
     if (!storage)
         return nullptr;
 
-    AbstractSqlStorage *sqlStorage = qobject_cast<AbstractSqlStorage *>(storage);
+    auto* sqlStorage = qobject_cast<AbstractSqlStorage*>(storage);
     if (!sqlStorage) {
         qDebug() << "Core::migrateDb(): only SQL based backends can be migrated!";
         return nullptr;
@@ -1087,13 +1144,12 @@ std::unique_ptr<AbstractSqlMigrationReader> Core::getMigrationReader(Storage *st
     return sqlStorage->createMigrationReader();
 }
 
-
-std::unique_ptr<AbstractSqlMigrationWriter> Core::getMigrationWriter(Storage *storage)
+std::unique_ptr<AbstractSqlMigrationWriter> Core::getMigrationWriter(Storage* storage)
 {
     if (!storage)
         return nullptr;
 
-    AbstractSqlStorage *sqlStorage = qobject_cast<AbstractSqlStorage *>(storage);
+    auto* sqlStorage = qobject_cast<AbstractSqlStorage*>(storage);
     if (!sqlStorage) {
         qDebug() << "Core::migrateDb(): only SQL based backends can be migrated!";
         return nullptr;
@@ -1102,8 +1158,7 @@ std::unique_ptr<AbstractSqlMigrationWriter> Core::getMigrationWriter(Storage *st
     return sqlStorage->createMigrationWriter();
 }
 
-
-bool Core::saveBackendSettings(const QString &backend, const QVariantMap &settings)
+bool Core::saveBackendSettings(const QString& backend, const QVariantMap& settings)
 {
     QVariantMap dbsettings;
     dbsettings["Backend"] = backend;
@@ -1113,8 +1168,7 @@ bool Core::saveBackendSettings(const QString &backend, const QVariantMap &settin
     return s.sync();
 }
 
-
-void Core::saveAuthenticatorSettings(const QString &backend, const QVariantMap &settings)
+void Core::saveAuthenticatorSettings(const QString& backend, const QVariantMap& settings)
 {
     QVariantMap dbsettings;
     dbsettings["Authenticator"] = backend;
@@ -1125,7 +1179,7 @@ void Core::saveAuthenticatorSettings(const QString &backend, const QVariantMap &
 // Generic version of promptForSettings that doesn't care what *type* of
 // backend it runs over.
 template<typename Backend>
-QVariantMap Core::promptForSettings(const Backend *backend)
+QVariantMap Core::promptForSettings(const Backendbackend)
 {
     QVariantMap settings;
     const QVariantList& setupData = backend->setupData();
@@ -1139,7 +1193,7 @@ QVariantMap Core::promptForSettings(const Backend *backend)
 
     for (int i = 0; i + 2 < setupData.size(); i += 3) {
         QString key = setupData[i].toString();
-        out << setupData[i+1].toString() << " [" << setupData[i+2].toString() << "]: " << flush;
+        out << setupData[i + 1].toString() << " [" << setupData[i + 2].toString() << "]: " << flush;
 
         bool noEcho = key.toLower().contains("password");
         if (noEcho) {
@@ -1151,7 +1205,7 @@ QVariantMap Core::promptForSettings(const Backend *backend)
             enableStdInEcho();
         }
 
-        QVariant value{setupData[i+2]};
+        QVariant value{setupData[i + 2]};
         if (!input.isEmpty()) {
             switch (value.type()) {
             case QVariant::Int:
@@ -1166,7 +1220,6 @@ QVariantMap Core::promptForSettings(const Backend *backend)
     return settings;
 }
 
-
 #ifdef Q_OS_WIN
 void Core::stdInEcho(bool on)
 {