Commit 043307f7 authored by Tomaz  Canabrava's avatar Tomaz Canabrava

Remove KAuth based code

This is a bit bigger than I wanted but I did not see how to easily
break this into smaller steps without redoing most of the work.
This remoes all calls to KAuth from netstat, and also removes the
`netstat` binary call - it's now only supposed to work with SS
Perhaps I should change the name of the files.
parent ec0f80db
......@@ -9,15 +9,17 @@
#include <KLocalizedString>
#include "netstatclient.h"
#include "netstathelper.h"
ConnectionsModel::ConnectionsModel(QObject *parent)
: QAbstractListModel(parent)
, m_queryAction(KAuth::Action(QStringLiteral("org.kde.netstat.query")))
{
m_queryAction.setHelperId("org.kde.netstat");
}
void ConnectionsModel::start()
{
connect(&timer, &QTimer::timeout, this, &ConnectionsModel::refreshConnections);
timer.setInterval(30000);
timer.setInterval(1000);
timer.start();
QTimer::singleShot(0, this, &ConnectionsModel::refreshConnections);
......@@ -96,50 +98,44 @@ void ConnectionsModel::refreshConnections()
setBusy(true);
KAuth::ExecuteJob *job = m_queryAction.execute();
connect(job, &KAuth::ExecuteJob::finished, this, [this, job] {
setBusy(false);
NetstatHelper helper;
QVector<QStringList> result = helper.query();
if (helper.hasError()) {
emit showErrorMessage(i18n("Failed to get connections: %1", helper.errorString()));
return;
}
if (job->error()) {
emit showErrorMessage(i18n("Failed to get connections: %1", job->errorString()));
return;
const auto oldConnectionsData = m_connectionsData;
QVector<ConnectionsData> newConnectionsData;
beginResetModel();
m_connectionsData.clear();
for (const auto connection : result) {
ConnectionsData conn {.protocol = connection.at(0),
.localAddress = connection.at(1),
.foreignAddress = connection.at(2),
.status = connection.at(3),
.pid = connection.at(4),
.program = connection.at(5)};
if (conn.status == "UNCONN") {
conn.status = i18n("Not Connected");
} else if (conn.status == "ESTAB") {
conn.status = i18n("Established");
} else if (conn.status == "LISTEN") {
conn.status = i18n("Listening");
}
const auto oldConnectionsData = m_connectionsData;
QVector<ConnectionsData> newConnectionsData;
newConnectionsData.append(conn);
}
if (newConnectionsData != oldConnectionsData) {
beginResetModel();
m_connectionsData.clear();
for (const auto connection : job->data().value("connections", QVariantList()).toList()) {
const auto connList = connection.toList();
ConnectionsData conn {.protocol = connList.at(0).toString(),
.localAddress = connList.at(1).toString(),
.foreignAddress = connList.at(2).toString(),
.status = connList.at(3).toString(),
.pid = connList.at(4).toString(),
.program = connList.at(5).toString()};
if (conn.status == "UNCONN") {
conn.status = i18n("Not Connected");
} else if (conn.status == "ESTAB") {
conn.status = i18n("Established");
} else if (conn.status == "LISTEN") {
conn.status = i18n("Listening");
}
newConnectionsData.append(conn);
}
if (newConnectionsData != oldConnectionsData) {
beginResetModel();
m_connectionsData = newConnectionsData;
endResetModel();
}
if (newConnectionsData.count() != oldConnectionsData.count()) {
emit countChanged();
}
});
m_connectionsData = newConnectionsData;
endResetModel();
}
job->start();
if (newConnectionsData.count() != oldConnectionsData.count()) {
emit countChanged();
}
}
......@@ -8,8 +8,6 @@
#include <QAbstractListModel>
#include <QTimer>
#include <KAuth>
#include <QLoggingCategory>
Q_DECLARE_LOGGING_CATEGORY(ConnectionsModelDebug)
......@@ -54,6 +52,8 @@ public:
QHash<int, QByteArray> roleNames() const override;
Q_INVOKABLE void start();
signals:
void countChanged();
void busyChanged();
......@@ -67,7 +67,6 @@ private:
bool m_busy = false;
QVector<ConnectionsData> m_connectionsData;
KAuth::Action m_queryAction;
QTimer timer;
};
......
......@@ -4,6 +4,8 @@
#include "netstatclient.h"
#include <QStandardPaths>
/* Access to the Netstat Client thru the Connections Model */
static NetstatClient *_self = nullptr;
......@@ -18,6 +20,12 @@ NetstatClient::NetstatClient(QObject *parent)
, m_connections(new ConnectionsModel(this))
{
_self = this;
mHasSS = !QStandardPaths::findExecutable("ss").isEmpty();
}
bool NetstatClient::hasSS() const
{
return mHasSS;
}
ConnectionsModel *NetstatClient::connectionsModel() const
......
......@@ -6,10 +6,10 @@
#define NETSTATCLIENT_H
#include <QObject>
#include <QLoggingCategory>
#include "conectionsmodel.h"
#include <QLoggingCategory>
#include "netstathelper.h"
Q_DECLARE_LOGGING_CATEGORY(NetstatClientDebug)
......@@ -18,20 +18,26 @@ class NetstatClient : public QObject
Q_OBJECT
Q_PROPERTY(QString status READ status WRITE setStatus NOTIFY statusChanged)
Q_PROPERTY(ConnectionsModel *connectionsModel READ connectionsModel CONSTANT)
Q_PROPERTY(bool hasSS READ hasSS CONSTANT)
public:
explicit NetstatClient(QObject *parent = nullptr);
static NetstatClient *self();
ConnectionsModel *connectionsModel() const;
Q_SLOT void setStatus(const QString &message);
QString status() const;
Q_SIGNAL void statusChanged(const QString &output);
bool hasSS() const;
protected:
QString mStatus;
ConnectionsModel *m_connections;
NetstatHelper *m_netstatHelper;
/* Netstat has been deprecated for more than 20 years,
* let's discourage distros using it as default.
*/
int mHasSS;
};
#endif // NETSTATCLIENT_H
......@@ -13,20 +13,13 @@
Q_LOGGING_CATEGORY(NetstatHelperDebug, "netstat.helper")
NetstatHelper::NetstatHelper()
NetstatHelper::NetstatHelper() : m_hasError(false)
{
mHasSS = !QStandardPaths::findExecutable("ss").isEmpty();
if (!mHasSS) { // could not execute file
qCWarning(NetstatHelperDebug) << i18n("could not find iproute2 or net-tools packages installed.");
}
}
KAuth::ActionReply NetstatHelper::query(const QVariantMap &map)
QVector<QStringList> NetstatHelper::query()
{
Q_UNUSED(map);
KAuth::ActionReply reply;
m_hasError = false;
QProcess netstat;
/* parameters passed to ss
* -r, --resolve resolve host names
......@@ -36,45 +29,41 @@ KAuth::ActionReply NetstatHelper::query(const QVariantMap &map)
* -t, --tcp display only TCP sockets
*/
QStringList netstatArgs({"-tuapr"});
QString executable = mHasSS ? QStringLiteral("ss") : QString();
if (executable.isEmpty()) {
qCWarning(NetstatHelperDebug) << i18n("No iproute or net-tools installed, can't run.");
KAuth::ActionReply::HelperErrorReply(-2);
return {};
}
QString executable = QStringLiteral("ss");
netstat.start(executable, netstatArgs, QIODevice::ReadOnly);
if (netstat.waitForStarted()) {
netstat.waitForFinished();
}
int exitCode(netstat.exitCode());
int exitCode = netstat.exitCode();
QVector<QStringList> result;
if (0 != exitCode) {
reply = KAuth::ActionReply::HelperErrorReply(exitCode);
reply.addData("response", netstat.readAllStandardError());
m_hasError = true;
m_errorString = netstat.readAllStandardError();
} else {
QVariantList connections = parseOutput(netstat.readAllStandardOutput());
reply.addData("connections", connections);
result = parseSSOutput(netstat.readAllStandardOutput());
}
return reply;
return result;
}
QVariantList NetstatHelper::parseOutput(const QByteArray &netstatOutput)
bool NetstatHelper::hasError() const
{
if (mHasSS) {
return parseSSOutput(netstatOutput);
}
return {};
return m_hasError;
}
QVariantList NetstatHelper::parseSSOutput(const QByteArray &netstatOutput)
QString NetstatHelper::errorString() const
{
return m_errorString;
}
QVector<QStringList> NetstatHelper::parseSSOutput(const QByteArray &netstatOutput)
{
QString rawOutput = netstatOutput;
QStringList outputLines = rawOutput.split("\n");
QVariantList connections;
QVector<QStringList> connections;
// discard lines.
while (outputLines.size()) {
......@@ -127,7 +116,7 @@ QVariantList NetstatHelper::parseSSOutput(const QByteArray &netstatOutput)
PidRole,
ProgramRole
*/
QVariantList connection {
QStringList connection {
values[0], // NetId
values[4], // Local Address
values[5], // Peer Address,
......@@ -136,91 +125,7 @@ QVariantList NetstatHelper::parseSSOutput(const QByteArray &netstatOutput)
appName,
};
connections.append((QVariant)connection);
}
return connections;
}
QVariantList NetstatHelper::parseNetstatOutput(const QByteArray &netstatOutput)
{
QString rawOutput = netstatOutput;
QStringList outputLines = rawOutput.split("\n");
QVariantList connections;
int lineIdx = 0;
int protIndex = 0;
int protSize = 0;
int localAddressIndex = 0;
int localAddressSize = 0;
int foreingAddressIndex = 0;
int foreingAddressSize = 0;
int stateIndex = 0;
int stateSize = 0;
int processIndex = 0;
int processSize = 0;
for (auto line : outputLines) {
lineIdx++;
if (line.isEmpty()) {
continue;
}
if (lineIdx == 1) {
continue;
}
if (lineIdx == 2) {
protIndex = 0;
protSize = line.indexOf("Recv-Q");
localAddressIndex = line.indexOf("Local Address");
localAddressSize = line.indexOf("Foreign Address") - localAddressIndex;
foreingAddressIndex = line.indexOf("Foreign Address");
foreingAddressSize = line.indexOf("State") - foreingAddressIndex;
stateIndex = line.indexOf("State");
stateSize = line.indexOf("PID/Program name") - stateIndex;
processIndex = line.indexOf("PID/Program name");
processSize = line.size() - processSize;
continue;
}
QVariantList connection(
{extractAndStrip(
line,
protIndex,
protSize),
extractAndStrip(
line,
localAddressIndex,
localAddressSize),
extractAndStrip(
line,
foreingAddressIndex,
foreingAddressSize),
extractAndStrip(
line,
stateIndex,
stateSize)});
QString pidAndProcess = extractAndStrip(line, processIndex, processSize);
int slashIndex = pidAndProcess.indexOf("/");
if (slashIndex != -1) {
QString pidStr = pidAndProcess.left(slashIndex);
QString program = pidAndProcess.right(pidAndProcess.size() - slashIndex - 1);
program = program.section(":", 0, 0);
connection << pidStr.toInt();
connection << program;
}
connections.append((QVariant)connection);
connections.append(connection);
}
return connections;
......@@ -232,5 +137,3 @@ QString NetstatHelper::extractAndStrip(const QString &src, const int &index, con
str.replace(" ", "");
return str;
}
KAUTH_HELPER_MAIN("org.kde.netstat", NetstatHelper)
......@@ -5,14 +5,12 @@
#ifndef NETSTATHELPER_H
#define NETSTATHELPER_H
#include <KAuth>
#include <QVariantMap>
#include <QLoggingCategory>
Q_DECLARE_LOGGING_CATEGORY(NetstatHelperDebug)
using namespace KAuth;
class NetstatHelper : public QObject
{
Q_OBJECT
......@@ -20,23 +18,16 @@ public:
NetstatHelper();
public Q_SLOTS:
ActionReply query(const QVariantMap &map);
QVector<QStringList> query();
QString errorString() const;
bool hasError() const;
private:
QVariantList parseOutput(const QByteArray &netstatOutput);
QVariantList parseNetstatOutput(const QByteArray &netstatOutput);
QVariantList parseSSOutput(const QByteArray &ss);
QVector<QStringList> parseSSOutput(const QByteArray &ss);
QString extractAndStrip(const QString &src, const int &index, const int &size);
/* Netstat has been deprecated for more than 20 years,
* some distros such as arch linux use 'ss' as default.
*/
int mHasSS;
/* Distros are not obliged to install this. let's query it before
* assuming that this actually exists */
int mHasNetstat;
QString m_errorString;
bool m_hasError;
};
#endif // NETSTATHELPER_H
......@@ -10,6 +10,7 @@ import org.kde.kirigami 2.10 as Kirigami
import org.kcm.firewall 1.0
ViewBase {
id: base
title: i18n("Connections")
model: netStatClient.connectionsModel
......@@ -37,5 +38,16 @@ ViewBase {
NetstatClient {
id: netStatClient
Component.onCompleted : {
console.log("Netstat client completed.");
if (!netStatClient.hasSS) {
console.log("Netstat client without ss");
base.errorMessage.text = i18n("could not find iproute2 or net-tools packages installed.");
base.errorMessage.visible = true;
} else {
console.log("Starting netstat client");
netStatClient.connectionsModel.start();
}
}
}
}
......@@ -31,6 +31,8 @@ KCM.ScrollViewKCM {
property alias filterPlaceholderText: searchField.placeholderText
property var filterRoleNames: []
property var errorMessage: modelErrorMessage
KSortFilterProxyModel {
id: proxyModel
sourceModel: root.model
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment