diff --git a/kcm/backends/firewalld/firewalldclient.cpp b/kcm/backends/firewalld/firewalldclient.cpp index c33f976..96d8829 100644 --- a/kcm/backends/firewalld/firewalldclient.cpp +++ b/kcm/backends/firewalld/firewalldclient.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -547,4 +548,21 @@ FirewallClient::Capabilities FirewalldClient::capabilities() const QStringList FirewalldClient::knownProtocols() { return {"TCP", "UDP"}; } + +bool FirewalldClient::isCurrentlyLoaded() const +{ + QProcess process; + const QString name = "systemctl"; + const QStringList args = {"status", "firewalld"}; + + process.start(name, args); + process.waitForFinished(); + + // systemctl returns 0 for status if the app is loaded, and 3 otherwise. + // systemctl returns 0 for status if the app is loaded, and 3 otherwise. + qDebug() << "Firewalld is loaded?" << process.exitCode(); + + return process.exitCode() == EXIT_SUCCESS; +} + #include "firewalldclient.moc" diff --git a/kcm/backends/firewalld/firewalldclient.h b/kcm/backends/firewalld/firewalldclient.h index 3d548cd..85de802 100644 --- a/kcm/backends/firewalld/firewalldclient.h +++ b/kcm/backends/firewalld/firewalldclient.h @@ -60,6 +60,7 @@ class Q_DECL_EXPORT FirewalldClient : public IFirewallClientBackend void refreshProfiles() override; bool hasDependencies() const override; QStringList knownProtocols() override; + bool isCurrentlyLoaded() const override; protected slots: void refreshLogs(); diff --git a/kcm/backends/ufw/ufwclient.cpp b/kcm/backends/ufw/ufwclient.cpp index 1302dbe..abf5a16 100644 --- a/kcm/backends/ufw/ufwclient.cpp +++ b/kcm/backends/ufw/ufwclient.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -681,5 +682,21 @@ QString UfwClient::toXml(Rule *r) const return xmlString; } + +bool UfwClient::isCurrentlyLoaded() const +{ + QProcess process; + const QString name = "systemctl"; + const QStringList args = {"status", "ufw"}; + + process.start(name, args); + process.waitForFinished(); + + // systemctl returns 0 for status if the app is loaded, and 3 otherwise. + qDebug() << "Ufw is loaded?" << process.exitCode(); + + return process.exitCode() == EXIT_SUCCESS; +} + #include "ufwclient.moc" diff --git a/kcm/backends/ufw/ufwclient.h b/kcm/backends/ufw/ufwclient.h index 23f0217..46811c7 100644 --- a/kcm/backends/ufw/ufwclient.h +++ b/kcm/backends/ufw/ufwclient.h @@ -68,6 +68,8 @@ class Q_DECL_EXPORT UfwClient : public IFirewallClientBackend bool hasExecutable() const override; void refreshProfiles() override; bool hasDependencies() const override; + bool isCurrentlyLoaded() const override; + protected slots: void refreshLogs(); QStringList knownProtocols() override; diff --git a/kcm/core/firewallclient.cpp b/kcm/core/firewallclient.cpp index d930118..2d0c0a9 100644 --- a/kcm/core/firewallclient.cpp +++ b/kcm/core/firewallclient.cpp @@ -30,12 +30,7 @@ IFirewallClientBackend *FirewallClient::m_currentBackend = nullptr; FirewallClient::FirewallClient(QObject *parent) : QObject(parent) { - if (!m_currentBackend) { - setBackend("ufw"); - } - if (!m_currentBackend) { - setBackend("firewalld"); - } + setBackend({"ufw", "firewalld"}); } QStringList FirewallClient::knownProtocols() @@ -266,7 +261,7 @@ bool FirewallClient::hasExecutable() const return m_currentBackend->hasExecutable(); } -void FirewallClient::setBackend(const QString &backend) +void FirewallClient::setBackend(const QStringList &backendList) { if (m_currentBackend) { enabledChanged(false); @@ -276,8 +271,10 @@ void FirewallClient::setBackend(const QString &backend) const auto plugins = KPluginLoader::findPlugins(QStringLiteral("kf5/plasma_firewall")); + QList factories; for (const KPluginMetaData &metadata : plugins) { - if (metadata.pluginId() != backend + QLatin1String("backend")) { + QString pluginName = metadata.pluginId().remove("backend"); + if (!backendList.contains(pluginName)) { continue; } @@ -285,20 +282,42 @@ void FirewallClient::setBackend(const QString &backend) if (!factory) { continue; } + factories.append(factory); + } - auto perhaps = factory->create(this, QVariantList() /*args*/); - if (perhaps->hasDependencies()) { - qCDebug(FirewallClientDebug) << "Backend " << backend << "Loaded"; - m_currentBackend = perhaps; - break; - } else { - qCDebug(FirewallClientDebug) << "Backend " << backend << "Failed to meet dependencies"; + // lambdas + auto systemCheck = [this] (const QList factories) -> IFirewallClientBackend* { + for (KPluginFactory *factory : factories) { + qDebug() << "Testing factory" << factory->objectName(); + auto perhaps = factory->create(this, QVariantList()); + if (perhaps->isCurrentlyLoaded()) { + qDebug() << "Is Loaded!"; + return perhaps; + } perhaps->deleteLater(); } + qDebug() << "Returning nullptr"; + return nullptr; + }; + + auto loadFromBinary = [this] (const QList factories) -> IFirewallClientBackend* { + for (KPluginFactory *factory : factories) { + auto perhaps = factory->create(this, QVariantList() ); + if (perhaps->hasDependencies()) { + return perhaps; + } + perhaps->deleteLater(); + } + return nullptr; + }; + + m_currentBackend = systemCheck(factories); + if (!m_currentBackend) { + m_currentBackend = loadFromBinary(factories); } if (!m_currentBackend) { - qCDebug(FirewallClientDebug) << "Could not find backend" << backend; + qCDebug(FirewallClientDebug) << "Could not find any of the specified backends" << backendList; return; } diff --git a/kcm/core/firewallclient.h b/kcm/core/firewallclient.h index 41fc541..8ff1558 100644 --- a/kcm/core/firewallclient.h +++ b/kcm/core/firewallclient.h @@ -44,7 +44,6 @@ class KCM_FIREWALL_CORE_EXPORT FirewallClient : public QObject Q_PROPERTY(RuleListModel *rulesModel READ rulesModel CONSTANT) Q_PROPERTY(LogListModel *logsModel READ logsModel CONSTANT) Q_PROPERTY(bool logsAutoRefresh READ logsAutoRefresh WRITE setLogsAutoRefresh NOTIFY logsAutoRefreshChanged) - Q_PROPERTY(QString backend READ backend WRITE setBackend NOTIFY backendChanged) Q_PROPERTY(bool hasExecutable READ hasExecutable NOTIFY hasExecutableChanged) Q_PROPERTY(Capabilities capabilities READ capabilities NOTIFY capabilitiesChanged) Q_PROPERTY(QString name READ name) @@ -125,7 +124,7 @@ class KCM_FIREWALL_CORE_EXPORT FirewallClient : public QObject void showErrorMessage(const QString &message); private: - void setBackend(const QString &backend); + void setBackend(const QStringList &backendList); void setLogsAutoRefresh(bool logsAutoRefresh); void queryStatus(DefaultDataBehavior defaultDataBehavior = ReadDefaults, ProfilesBehavior ProfilesBehavior = ListenProfiles); diff --git a/kcm/core/ifirewallclientbackend.h b/kcm/core/ifirewallclientbackend.h index d68b9dc..3b21c81 100644 --- a/kcm/core/ifirewallclientbackend.h +++ b/kcm/core/ifirewallclientbackend.h @@ -70,8 +70,16 @@ class Q_DECL_EXPORT IFirewallClientBackend : public QObject virtual QString defaultOutgoingPolicy() const = 0; virtual bool hasExecutable() const = 0; virtual LogListModel *logs() = 0; + + /* TODO: Move it away from here. This asks the + * Logs model to refresh after a few seconds + */ virtual bool logsAutoRefresh() const = 0; + /* Returns true if the firewall represented + * by this backend is running right now */ + virtual bool isCurrentlyLoaded() const = 0; + virtual void refreshProfiles() = 0; virtual FirewallClient::Capabilities capabilities() const; virtual QStringList knownProtocols() = 0;