Added KdeConnectConfig class that aims to be a KConfig abstraction

Benefits:
- We had config files in different paths, now they will be centralized.
- Daemon, LanLinkProvider and NetworkPackage depend only on Qt now.
- KConfig is accessed with strings as keys, where a typo can go unnoticed.
- Daemon is now thinner, as it doesn't need to initialize config values.
- QCA::Initializer is in a single place now (was in Daemon and Plugin).
This commit is contained in:
Albert Vaca 2015-03-01 20:16:07 -08:00
parent 7591e783ca
commit c7c91c1289
15 changed files with 321 additions and 166 deletions

View file

@ -18,6 +18,7 @@ set(kded_kdeconnect_SRCS
kdeconnectplugin.cpp kdeconnectplugin.cpp
pluginloader.cpp pluginloader.cpp
kdeconnectconfig.cpp
dbushelper.cpp dbushelper.cpp
networkpackage.cpp networkpackage.cpp
filetransferjob.cpp filetransferjob.cpp

View file

@ -19,6 +19,7 @@
*/ */
#include "devicelink.h" #include "devicelink.h"
#include "kdeconnectconfig.h"
#include "linkprovider.h" #include "linkprovider.h"
DeviceLink::DeviceLink(const QString& deviceId, LinkProvider* parent) DeviceLink::DeviceLink(const QString& deviceId, LinkProvider* parent)
@ -29,5 +30,7 @@ DeviceLink::DeviceLink(const QString& deviceId, LinkProvider* parent)
Q_ASSERT(!deviceId.isEmpty()); Q_ASSERT(!deviceId.isEmpty());
setProperty("deviceId", deviceId); setProperty("deviceId", deviceId);
mPrivateKey = KdeConnectConfig::instance()->privateKey();
} }

View file

@ -44,8 +44,6 @@ public:
virtual bool sendPackage(NetworkPackage& np) = 0; virtual bool sendPackage(NetworkPackage& np) = 0;
virtual bool sendPackageEncrypted(QCA::PublicKey& publicKey, NetworkPackage& np) = 0; virtual bool sendPackageEncrypted(QCA::PublicKey& publicKey, NetworkPackage& np) = 0;
void setPrivateKey(const QCA::PrivateKey& privateKey) { mPrivateKey = privateKey; }
Q_SIGNALS: Q_SIGNALS:
void receivedPackage(const NetworkPackage& np); void receivedPackage(const NetworkPackage& np);

View file

@ -30,10 +30,8 @@
#include <QTcpServer> #include <QTcpServer>
#include <QUdpSocket> #include <QUdpSocket>
#include <KSharedConfig>
#include <KConfigGroup>
#include "landevicelink.h" #include "landevicelink.h"
#include <kdeconnectconfig.h>
void LanLinkProvider::configureSocket(QTcpSocket* socket) void LanLinkProvider::configureSocket(QTcpSocket* socket)
{ {
@ -124,10 +122,7 @@ void LanLinkProvider::newUdpConnection()
return; return;
} }
KSharedConfigPtr config = KSharedConfig::openConfig("kdeconnectrc"); if (receivedPackage->get<QString>("deviceId") == KdeConnectConfig::instance()->deviceId()) {
const QString myId = config->group("myself").readEntry<QString>("id","");
if (receivedPackage->get<QString>("deviceId") == myId) {
//kDebug(debugArea()) << "Ignoring my own broadcast"; //kDebug(debugArea()) << "Ignoring my own broadcast";
delete receivedPackage; delete receivedPackage;
return; return;

View file

@ -20,23 +20,14 @@
#include "daemon.h" #include "daemon.h"
#include <QDir>
#include <QUuid>
#include <QFile>
#include <QFileInfo>
#include <QDBusConnection> #include <QDBusConnection>
#include <QNetworkSession> #include <QNetworkSession>
#include <QNetworkConfigurationManager> #include <QNetworkConfigurationManager>
#include <QtCrypto>
#include <QStandardPaths>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QDebug>
#include <KConfig>
#include <KConfigGroup>
#include <KSharedConfig>
#include "core_debug.h" #include "core_debug.h"
#include "dbushelper.h" #include "kdeconnectconfig.h"
#include "networkpackage.h" #include "networkpackage.h"
#include "backends/lan/lanlinkprovider.h" #include "backends/lan/lanlinkprovider.h"
#include "backends/loopback/loopbacklinkprovider.h" #include "backends/loopback/loopbacklinkprovider.h"
@ -45,7 +36,6 @@
#include "backends/devicelink.h" #include "backends/devicelink.h"
#include "backends/linkprovider.h" #include "backends/linkprovider.h"
#include <QDebug>
struct DaemonPrivate struct DaemonPrivate
{ {
//Different ways to find devices and connect to them //Different ways to find devices and connect to them
@ -53,10 +43,6 @@ struct DaemonPrivate
//Every known device //Every known device
QMap<QString, Device*> mDevices; QMap<QString, Device*> mDevices;
// The Initializer object sets things up, and also does cleanup when it goes out of scope
// Note it's not being used anywhere. That's inteneded
QCA::Initializer mQcaInitializer;
}; };
Daemon::Daemon(QObject *parent) Daemon::Daemon(QObject *parent)
@ -65,63 +51,12 @@ Daemon::Daemon(QObject *parent)
{ {
qCDebug(KDECONNECT_CORE) << "KdeConnect daemon starting"; qCDebug(KDECONNECT_CORE) << "KdeConnect daemon starting";
KSharedConfigPtr config = KSharedConfig::openConfig("kdeconnectrc"); //Load backends
if (!config->group("myself").hasKey("id")) {
QString uuid = QUuid::createUuid().toString();
DbusHelper::filterNonExportableCharacters(uuid);
config->group("myself").writeEntry("id", uuid);
config->sync();
qCDebug(KDECONNECT_CORE) << "My id:" << uuid;
}
//qCDebug(KDECONNECT_CORE) << "QCA supported capabilities:" << QCA::supportedFeatures().join(",");
if(!QCA::isSupported("rsa")) {
//TODO: Display this in a notification or another visible way
qCCritical(KDECONNECT_CORE) << "Error: KDE Connect could not find support for RSA in your QCA installation, if your distribution provides"
<< "separate packages for QCA-ossl and QCA-gnupg plugins, make sure you have them installed and try again";
return;
}
const QFile::Permissions strict = QFile::ReadOwner | QFile::WriteOwner | QFile::ReadUser | QFile::WriteUser;
const QString privateKeyPath = Device::privateKeyPath();
if (!QFile::exists(privateKeyPath))
{
QDir::root().mkpath(QFileInfo(privateKeyPath).dir().path());
QFile privKey(privateKeyPath);
if (!privKey.open(QIODevice::ReadWrite | QIODevice::Truncate))
{
qCCritical(KDECONNECT_CORE) << "Error: KDE Connect could not create private keys file: " << privateKeyPath;
return;
}
if (!privKey.setPermissions(strict))
{
qCDebug(KDECONNECT_CORE) << "Error: KDE Connect could not set permissions for private file: " << privateKeyPath;
}
privKey.write(QCA::KeyGenerator().createRSA(2048).toPEM().toLatin1());
}
if (QFile::permissions(privateKeyPath) != strict)
{
qCDebug(KDECONNECT_CORE) << "Error: KDE Connect detects wrong permissions for private file " << privateKeyPath;
}
//Register on DBus
QDBusConnection::sessionBus().registerService("org.kde.kdeconnect");
QDBusConnection::sessionBus().registerObject("/modules/kdeconnect", this, QDBusConnection::ExportScriptableContents);
//Load backends (hardcoded by now, should be plugins in a future)
d->mLinkProviders.insert(new LanLinkProvider()); d->mLinkProviders.insert(new LanLinkProvider());
//d->mLinkProviders.insert(new LoopbackLinkProvider()); //d->mLinkProviders.insert(new LoopbackLinkProvider());
//Read remebered paired devices //Read remebered paired devices
const KConfigGroup& known = config->group("trusted_devices"); const QStringList& list = KdeConnectConfig::instance()->trustedDevices();
const QStringList& list = known.groupList();
Q_FOREACH(const QString& id, list) { Q_FOREACH(const QString& id, list) {
Device* device = new Device(this, id); Device* device = new Device(this, id);
connect(device, SIGNAL(reachableStatusChanged()), connect(device, SIGNAL(reachableStatusChanged()),
@ -147,6 +82,10 @@ Daemon::Daemon(QObject *parent)
a, SLOT(onNetworkChange(QNetworkSession::State))); a, SLOT(onNetworkChange(QNetworkSession::State)));
} }
//Register on DBus
QDBusConnection::sessionBus().registerService("org.kde.kdeconnect");
QDBusConnection::sessionBus().registerObject("/modules/kdeconnect", this, QDBusConnection::ExportScriptableContents);
qCDebug(KDECONNECT_CORE) << "KdeConnect daemon started"; qCDebug(KDECONNECT_CORE) << "KdeConnect daemon started";
} }
@ -158,7 +97,6 @@ void Daemon::setDiscoveryEnabled(bool b)
else else
a->onStop(); a->onStop();
} }
} }
void Daemon::forceOnNetworkChange() void Daemon::forceOnNetworkChange()
@ -181,7 +119,6 @@ QStringList Daemon::devices(bool onlyReachable, bool onlyVisible) const
void Daemon::onNewDeviceLink(const NetworkPackage& identityPackage, DeviceLink* dl) void Daemon::onNewDeviceLink(const NetworkPackage& identityPackage, DeviceLink* dl)
{ {
const QString& id = identityPackage.get<QString>("deviceId"); const QString& id = identityPackage.get<QString>("deviceId");
//qCDebug(KDECONNECT_CORE) << "Device discovered" << id << "via" << dl->provider()->name(); //qCDebug(KDECONNECT_CORE) << "Device discovered" << id << "via" << dl->provider()->name();
@ -201,12 +138,10 @@ void Daemon::onNewDeviceLink(const NetworkPackage& identityPackage, DeviceLink*
} }
Q_EMIT deviceVisibilityChanged(id, true); Q_EMIT deviceVisibilityChanged(id, true);
} }
void Daemon::onDeviceReachableStatusChanged() void Daemon::onDeviceReachableStatusChanged()
{ {
Device* device = (Device*)sender(); Device* device = (Device*)sender();
QString id = device->id(); QString id = device->id();
@ -217,6 +152,7 @@ void Daemon::onDeviceReachableStatusChanged()
if (!device->isReachable()) { if (!device->isReachable()) {
if (!device->isPaired()) { if (!device->isPaired()) {
qCDebug(KDECONNECT_CORE) << "Destroying device" << device->name(); qCDebug(KDECONNECT_CORE) << "Destroying device" << device->name();
Q_EMIT deviceRemoved(id); Q_EMIT deviceRemoved(id);
d->mDevices.remove(id); d->mDevices.remove(id);
@ -224,7 +160,6 @@ void Daemon::onDeviceReachableStatusChanged()
} }
} }
} }
Daemon::~Daemon() Daemon::~Daemon()

View file

@ -33,6 +33,7 @@
#include <KNotification> #include <KNotification>
#include <KLocalizedString> #include <KLocalizedString>
#include <QIcon> #include <QIcon>
#include <QDir>
#include "core_debug.h" #include "core_debug.h"
#include "kdeconnectplugin.h" #include "kdeconnectplugin.h"
@ -40,39 +41,21 @@
#include "backends/devicelink.h" #include "backends/devicelink.h"
#include "backends/linkprovider.h" #include "backends/linkprovider.h"
#include "networkpackage.h" #include "networkpackage.h"
#include "kdeconnectconfig.h"
Q_LOGGING_CATEGORY(KDECONNECT_CORE, "kdeconnect.core") Q_LOGGING_CATEGORY(KDECONNECT_CORE, "kdeconnect.core")
QCA::PrivateKey initPrivateKey()
{
QCA::PrivateKey ret;
QFile privKey(Device::privateKeyPath());
if (privKey.open(QIODevice::ReadOnly))
ret = QCA::PrivateKey::fromPEM(privKey.readAll());
else {
qWarning() << "Could not open the private key" << Device::privateKeyPath();
}
Q_ASSERT(!ret.isNull());
return ret;
}
Q_GLOBAL_STATIC_WITH_ARGS(QCA::PrivateKey, s_privateKey, (initPrivateKey()))
Device::Device(QObject* parent, const QString& id) Device::Device(QObject* parent, const QString& id)
: QObject(parent) : QObject(parent)
, m_deviceId(id) , m_deviceId(id)
, m_pairStatus(Device::Paired) , m_pairStatus(Device::Paired)
, m_protocolVersion(NetworkPackage::ProtocolVersion) //We don't know it yet , m_protocolVersion(NetworkPackage::ProtocolVersion) //We don't know it yet
{ {
KSharedConfigPtr config = KSharedConfig::openConfig("kdeconnectrc"); KdeConnectConfig::DeviceInfo info = KdeConnectConfig::instance()->getTrustedDevice(id);
KConfigGroup data = config->group("trusted_devices").group(id);
m_deviceName = data.readEntry<QString>("deviceName", QLatin1String("unnamed")); m_deviceName = info.deviceName;
m_deviceType = str2type(data.readEntry<QString>("deviceType", QLatin1String("unknown"))); m_deviceType = str2type(info.deviceType);
m_publicKey = QCA::RSAPublicKey::fromPEM(info.publicKey);
const QString& key = data.readEntry<QString>("publicKey", QString());
m_publicKey = QCA::RSAPublicKey::fromPEM(key);
//Register in bus //Register in bus
QDBusConnection::sessionBus().registerObject(dbusPath(), this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportAdaptors); QDBusConnection::sessionBus().registerObject(dbusPath(), this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportAdaptors);
@ -117,8 +100,7 @@ void Device::reloadPlugins()
if (isPaired() && isReachable()) { //Do not load any plugin for unpaired devices, nor useless loading them for unreachable devices if (isPaired() && isReachable()) { //Do not load any plugin for unpaired devices, nor useless loading them for unreachable devices
QString path = QStandardPaths::locate(QStandardPaths::ConfigLocation, "kdeconnect/", QStandardPaths::LocateDirectory) + id(); KConfigGroup pluginStates = KSharedConfig::openConfig(pluginsConfigFile())->group("Plugins");
KConfigGroup pluginStates = KSharedConfig::openConfig(path)->group("Plugins");
PluginLoader* loader = PluginLoader::instance(); PluginLoader* loader = PluginLoader::instance();
@ -183,6 +165,11 @@ void Device::reloadPlugins()
} }
QString Device::pluginsConfigFile() const
{
return KdeConnectConfig::instance()->deviceConfigDir(id()).absoluteFilePath("config");
}
void Device::requestPair() void Device::requestPair()
{ {
switch(m_pairStatus) { switch(m_pairStatus) {
@ -226,8 +213,7 @@ void Device::unpair()
{ {
m_pairStatus = Device::NotPaired; m_pairStatus = Device::NotPaired;
KSharedConfigPtr config = KSharedConfig::openConfig("kdeconnectrc"); KdeConnectConfig::instance()->removeTrustedDevice(id());
config->group("trusted_devices").deleteGroup(id());
NetworkPackage np(PACKAGE_TYPE_PAIR); NetworkPackage np(PACKAGE_TYPE_PAIR);
np.set("pair", false); np.set("pair", false);
@ -271,12 +257,9 @@ void Device::addLink(const NetworkPackage& identityPackage, DeviceLink* link)
m_deviceName = identityPackage.get<QString>("deviceName"); m_deviceName = identityPackage.get<QString>("deviceName");
m_deviceType = str2type(identityPackage.get<QString>("deviceType")); m_deviceType = str2type(identityPackage.get<QString>("deviceType"));
Q_ASSERT(!s_privateKey->isNull());
link->setPrivateKey(*s_privateKey);
//Theoretically we will never add two links from the same provider (the provider should destroy //Theoretically we will never add two links from the same provider (the provider should destroy
//the old one before this is called), so we do not have to worry about destroying old links. //the old one before this is called), so we do not have to worry about destroying old links.
//Actually, we should not destroy them or the provider will store an invalid ref! //-- Actually, we should not destroy them or the provider will store an invalid ref!
connect(link, SIGNAL(receivedPackage(NetworkPackage)), connect(link, SIGNAL(receivedPackage(NetworkPackage)),
this, SLOT(privateReceivedPackage(NetworkPackage))); this, SLOT(privateReceivedPackage(NetworkPackage)));
@ -310,11 +293,6 @@ void Device::removeLink(DeviceLink* link)
} }
} }
QString Device::privateKeyPath()
{
return QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QStringLiteral("/org.kde.kdeconnect/key.pem");
}
bool Device::sendPackage(NetworkPackage& np) bool Device::sendPackage(NetworkPackage& np)
{ {
if (np.type() != PACKAGE_TYPE_PAIR && isPaired()) { if (np.type() != PACKAGE_TYPE_PAIR && isPaired()) {
@ -413,8 +391,10 @@ void Device::privateReceivedPackage(const NetworkPackage& np)
} }
} else { } else {
qCDebug(KDECONNECT_CORE) << "device" << name() << "not paired, ignoring package" << np.type(); qCDebug(KDECONNECT_CORE) << "device" << name() << "not paired, ignoring package" << np.type();
unpair();
//FIXME: Uncommenting this fixes a bug where trying to pair from kde does not work, but I want to investigate the root cause of the bug first (01/03/15)
//if (m_pairStatus != Device::Requested)
unpair();
} }
} }
@ -423,7 +403,7 @@ bool Device::sendOwnPublicKey()
{ {
NetworkPackage np(PACKAGE_TYPE_PAIR); NetworkPackage np(PACKAGE_TYPE_PAIR);
np.set("pair", true); np.set("pair", true);
np.set("publicKey", s_privateKey->toPublicKey().toPEM()); np.set("publicKey", KdeConnectConfig::instance()->publicKey().toPEM());
bool success = sendPackage(np); bool success = sendPackage(np);
return success; return success;
} }
@ -466,7 +446,8 @@ void Device::setAsPaired()
m_pairingTimeut.stop(); //Just in case it was started m_pairingTimeut.stop(); //Just in case it was started
storeAsTrusted(); //Save to the config as trusted //Save device info in the config
KdeConnectConfig::instance()->addTrustedDevice(id(), name(), type2str(m_deviceType), m_publicKey.toPEM());
reloadPlugins(); //Will actually load the plugins reloadPlugins(); //Will actually load the plugins
@ -474,15 +455,6 @@ void Device::setAsPaired()
} }
void Device::storeAsTrusted()
{
KSharedConfigPtr config = KSharedConfig::openConfig("kdeconnectrc");
config->group("trusted_devices").group(id()).writeEntry("publicKey", m_publicKey.toPEM());
config->group("trusted_devices").group(id()).writeEntry("deviceName", name());
config->group("trusted_devices").group(id()).writeEntry("deviceType", type2str(m_deviceType));
config->sync();
}
QStringList Device::availableLinks() const QStringList Device::availableLinks() const
{ {
QStringList sl; QStringList sl;

View file

@ -62,7 +62,7 @@ class KDECONNECTCORE_EXPORT Device
public: public:
/** /**
* Reads the @p device from KConfig * Restores the @p device from the saved configuration
* *
* We already know it but we need to wait for an incoming DeviceLink to communicate * We already know it but we need to wait for an incoming DeviceLink to communicate
*/ */
@ -86,8 +86,6 @@ public:
void addLink(const NetworkPackage& identityPackage, DeviceLink*); void addLink(const NetworkPackage& identityPackage, DeviceLink*);
void removeLink(DeviceLink*); void removeLink(DeviceLink*);
static QString privateKeyPath();
Q_SCRIPTABLE bool isPaired() const { return m_pairStatus==Device::Paired; } Q_SCRIPTABLE bool isPaired() const { return m_pairStatus==Device::Paired; }
Q_SCRIPTABLE bool pairRequested() const { return m_pairStatus==Device::Requested; } Q_SCRIPTABLE bool pairRequested() const { return m_pairStatus==Device::Requested; }
@ -97,6 +95,8 @@ public:
Q_SCRIPTABLE QStringList loadedPlugins() const; Q_SCRIPTABLE QStringList loadedPlugins() const;
Q_SCRIPTABLE bool hasPlugin(const QString& name) const; Q_SCRIPTABLE bool hasPlugin(const QString& name) const;
Q_SCRIPTABLE QString pluginsConfigFile() const;
public Q_SLOTS: public Q_SLOTS:
///sends a @p np package to the device ///sends a @p np package to the device
virtual bool sendPackage(NetworkPackage& np); virtual bool sendPackage(NetworkPackage& np);
@ -139,7 +139,6 @@ private:
QSet<QString> m_outgoingCapabilities; QSet<QString> m_outgoingCapabilities;
void setAsPaired(); void setAsPaired();
void storeAsTrusted();
bool sendOwnPublicKey(); bool sendOwnPublicKey();
}; };

194
core/kdeconnectconfig.cpp Normal file
View file

@ -0,0 +1,194 @@
/**
* Copyright 2015 Albert Vaca <albertvaka@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "kdeconnectconfig.h"
#include <KConfig>
#include <KConfigGroup>
#include <KSharedConfig>
#include <QtCrypto>
#include <QFile>
#include <QDebug>
#include <QFileInfo>
#include <QUuid>
#include <QDebug>
#include <QDir>
#include <QStandardPaths>
#include <QApplication>
#include <QHostInfo>
#include "core_debug.h"
#include "dbushelper.h"
struct KdeConnectConfigPrivate {
// The Initializer object sets things up, and also does cleanup when it goes out of scope
// Note it's not being used anywhere. That's inteneded
QCA::Initializer mQcaInitializer;
QCA::PrivateKey privateKey;
KSharedConfigPtr config;
};
KdeConnectConfig* KdeConnectConfig::instance()
{
static KdeConnectConfig* kcc = new KdeConnectConfig();
return kcc;
}
KdeConnectConfig::KdeConnectConfig()
: d(new KdeConnectConfigPrivate) {
//qCDebug(KDECONNECT_CORE) << "QCA supported capabilities:" << QCA::supportedFeatures().join(",");
if(!QCA::isSupported("rsa")) {
//TODO: Display this in a more visible way (notification?)
qCCritical(KDECONNECT_CORE) << "Error: KDE Connect could not find support for RSA in your QCA installation, if your distribution provides"
<< "separate packages for QCA-ossl and QCA-gnupg plugins, make sure you have them installed and try again";
return;
}
//Make sure base directory exists
QDir().mkpath(baseConfigDir().path());
//.config/kdeconnect/config
d->config = KSharedConfig::openConfig(baseConfigDir().absoluteFilePath("config"), KSharedConfig::SimpleConfig);
if (!d->config->group("myself").hasKey("id")) {
QString uuid = QUuid::createUuid().toString();
DbusHelper::filterNonExportableCharacters(uuid);
d->config->group("myself").writeEntry("id", uuid);
d->config->sync();
qCDebug(KDECONNECT_CORE) << "My id:" << uuid;
}
const QFile::Permissions strict = QFile::ReadOwner | QFile::WriteOwner | QFile::ReadUser | QFile::WriteUser;
QString keyPath = privateKeyPath();
QFile privKey(keyPath);
if (privKey.exists() && privKey.open(QIODevice::ReadOnly))
{
d->privateKey = QCA::PrivateKey::fromPEM(privKey.readAll());
}
else
{
if (!privKey.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
//TODO: Display this in a more visible way (notification?)
qCCritical(KDECONNECT_CORE) << "Error: KDE Connect could not create private key file: " << keyPath;
QApplication::exit(-1);
}
privKey.setPermissions(strict);
d->privateKey = QCA::KeyGenerator().createRSA(2048);
privKey.write(d->privateKey.toPEM().toLatin1());
}
//Extra security check
if (QFile::permissions(keyPath) != strict) {
qCDebug(KDECONNECT_CORE) << "Error: KDE Connect detects wrong permissions for private key file " << keyPath;
}
}
QString KdeConnectConfig::name() {
QString defaultName = qgetenv("USER") + "@" + QHostInfo::localHostName();
QString name = d->config->group("myself").readEntry("name", defaultName);
return name;
}
void KdeConnectConfig::setName(QString name)
{
d->config->group("myself").writeEntry("name", name);
d->config->sync();
}
QString KdeConnectConfig::deviceType()
{
return "desktop"; // TODO
}
QString KdeConnectConfig::deviceId() {
return d->config->group("myself").readEntry("id", "");
}
QString KdeConnectConfig::privateKeyPath()
{
return baseConfigDir().absoluteFilePath("privateKey.pem");
}
QCA::PrivateKey KdeConnectConfig::privateKey()
{
return d->privateKey;
}
QCA::PublicKey KdeConnectConfig::publicKey()
{
return d->privateKey.toPublicKey();
}
QDir KdeConnectConfig::baseConfigDir()
{
QString configPath = QStandardPaths::writableLocation(QStandardPaths::ConfigLocation);
QString kdeconnectConfigPath = QDir(configPath).absoluteFilePath("kdeconnect");
return QDir(kdeconnectConfigPath);
}
QStringList KdeConnectConfig::trustedDevices()
{
const KConfigGroup& known = d->config->group("trusted_devices");
const QStringList& list = known.groupList();
return list;
}
void KdeConnectConfig::addTrustedDevice(QString id, QString name, QString type, QString publicKey)
{
KConfigGroup device = d->config->group("trusted_devices").group(id);
device.writeEntry("deviceName", name);
device.writeEntry("deviceType", type);
device.writeEntry("publicKey", publicKey);
d->config->sync();
QDir().mkpath(deviceConfigDir(id).path());
}
KdeConnectConfig::DeviceInfo KdeConnectConfig::getTrustedDevice(QString id)
{
KConfigGroup data = d->config->group("trusted_devices").group(id);
KdeConnectConfig::DeviceInfo info;
info.deviceName = data.readEntry<QString>("deviceName", QLatin1String("unnamed"));
info.deviceType = data.readEntry<QString>("deviceType", QLatin1String("unknown"));
info.publicKey = data.readEntry<QString>("publicKey", QString());
return info;
}
void KdeConnectConfig::removeTrustedDevice(QString deviceId)
{
d->config->group("trusted_devices").deleteGroup(deviceId);
}
QDir KdeConnectConfig::deviceConfigDir(QString deviceId)
{
QString deviceConfigPath = baseConfigDir().absoluteFilePath(deviceId);
return QDir(deviceConfigPath);
}

78
core/kdeconnectconfig.h Normal file
View file

@ -0,0 +1,78 @@
/**
* Copyright 2015 Albert Vaca <albertvaka@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KDECONNECTCONFIG_H
#define KDECONNECTCONFIG_H
#include <QtCrypto>
#include <QDir>
#include "kdeconnectcore_export.h"
class KdeConnectConfigPrivate;
class KDECONNECTCORE_EXPORT KdeConnectConfig
{
public:
struct DeviceInfo {
QString deviceName;
QString deviceType;
QString publicKey;
};
static KdeConnectConfig* instance();
/*
* Our own info
*/
QString deviceId();
QString name();
QString deviceType();
QString privateKeyPath();
QCA::PrivateKey privateKey();
QCA::PublicKey publicKey();
void setName(QString name);
/*
* Trusted devices
*/
QStringList trustedDevices(); //Get a list of ids
void removeTrustedDevice(QString id);
void addTrustedDevice(QString id, QString name, QString type, QString publicKey);
KdeConnectConfig::DeviceInfo getTrustedDevice(QString id);
QDir baseConfigDir();
QDir deviceConfigDir(QString deviceId);
private:
KdeConnectConfig();
private:
QScopedPointer<KdeConnectConfigPrivate> d;
};
#endif

View file

@ -25,10 +25,6 @@ struct KdeConnectPluginPrivate
{ {
Device* mDevice; Device* mDevice;
QSet<QString> mOutgoingTypes; QSet<QString> mOutgoingTypes;
// The Initializer object sets things up, and also does cleanup when it goes out of scope
// Since the plugins use their own memory, they need their own initializer in order to send encrypted packages
QCA::Initializer init;
}; };
KdeConnectPlugin::KdeConnectPlugin(QObject* parent, const QVariantList& args) KdeConnectPlugin::KdeConnectPlugin(QObject* parent, const QVariantList& args)

View file

@ -21,23 +21,19 @@
#include "networkpackage.h" #include "networkpackage.h"
#include "core_debug.h" #include "core_debug.h"
#include <KSharedConfig>
#include <KConfigGroup>
#include <QMetaObject> #include <QMetaObject>
#include <QMetaProperty> #include <QMetaProperty>
#include <QByteArray> #include <QByteArray>
#include <QDataStream> #include <QDataStream>
#include <QHostInfo>
#include <QSslKey>
#include <QDateTime> #include <QDateTime>
#include <qjsondocument.h> #include <QJsonDocument>
#include <QtCrypto> #include <QtCrypto>
#include <QDebug> #include <QDebug>
#include "dbushelper.h" #include "dbushelper.h"
#include "filetransferjob.h" #include "filetransferjob.h"
#include "pluginloader.h" #include "pluginloader.h"
#include "kdeconnectconfig.h"
const QCA::EncryptionAlgorithm NetworkPackage::EncryptionAlgorithm = QCA::EME_PKCS1v15; const QCA::EncryptionAlgorithm NetworkPackage::EncryptionAlgorithm = QCA::EME_PKCS1v15;
const int NetworkPackage::ProtocolVersion = 5; const int NetworkPackage::ProtocolVersion = 5;
@ -53,15 +49,15 @@ NetworkPackage::NetworkPackage(const QString& type)
void NetworkPackage::createIdentityPackage(NetworkPackage* np) void NetworkPackage::createIdentityPackage(NetworkPackage* np)
{ {
KSharedConfigPtr config = KSharedConfig::openConfig("kdeconnectrc"); KdeConnectConfig* config = KdeConnectConfig::instance();
const QString id = config->group("myself").readEntry<QString>("id",""); const QString id = config->deviceId();
np->mId = QString::number(QDateTime::currentMSecsSinceEpoch()); np->mId = QString::number(QDateTime::currentMSecsSinceEpoch());
np->mType = PACKAGE_TYPE_IDENTITY; np->mType = PACKAGE_TYPE_IDENTITY;
np->mPayload = QSharedPointer<QIODevice>(); np->mPayload = QSharedPointer<QIODevice>();
np->mPayloadSize = 0; np->mPayloadSize = 0;
np->set("deviceId", id); np->set("deviceId", id);
np->set("deviceName", qgetenv("USER") + "@" + QHostInfo::localHostName()); np->set("deviceName", config->name());
np->set("deviceType", "desktop"); //TODO: Detect laptop, tablet, phone... np->set("deviceType", config->deviceType());
np->set("protocolVersion", NetworkPackage::ProtocolVersion); np->set("protocolVersion", NetworkPackage::ProtocolVersion);
np->set("SupportedIncomingInterfaces", PluginLoader::instance()->incomingInterfaces().join(",")); np->set("SupportedIncomingInterfaces", PluginLoader::instance()->incomingInterfaces().join(","));
np->set("SupportedOutgoingInterfaces", PluginLoader::instance()->outgoingInterfaces().join(",")); np->set("SupportedOutgoingInterfaces", PluginLoader::instance()->outgoingInterfaces().join(","));

View file

@ -23,9 +23,6 @@
#include <QDebug> #include <QDebug>
#include <QDBusInterface> #include <QDBusInterface>
#include <KSharedConfig>
#include <KConfigGroup>
#include <QIcon> #include <QIcon>
#include "dbusinterfaces.h" #include "dbusinterfaces.h"

View file

@ -142,7 +142,7 @@ void KdeConnectKcm::deviceSelected(const QModelIndex& current)
} }
} }
//FIXME: KPluginSelector has no way to remove a list of plugins and load another, so we need to destroy and recreate it each time //KPluginSelector has no way to remove a list of plugins and load another, so we need to destroy and recreate it each time
delete kcmUi->pluginSelector; delete kcmUi->pluginSelector;
kcmUi->pluginSelector = new KPluginSelector(this); kcmUi->pluginSelector = new KPluginSelector(this);
kcmUi->verticalLayout_2->addWidget(kcmUi->pluginSelector); kcmUi->verticalLayout_2->addWidget(kcmUi->pluginSelector);
@ -159,9 +159,7 @@ void KdeConnectKcm::deviceSelected(const QModelIndex& current)
KService::List offers = KServiceTypeTrader::self()->query("KdeConnect/Plugin"); KService::List offers = KServiceTypeTrader::self()->query("KdeConnect/Plugin");
QList<KPluginInfo> scriptinfos = KPluginInfo::fromServices(offers); QList<KPluginInfo> scriptinfos = KPluginInfo::fromServices(offers);
KSharedConfigPtr deviceConfig = KSharedConfig::openConfig(currentDevice->pluginsConfigFile());
QString path = QStandardPaths::locate(QStandardPaths::ConfigLocation, "kdeconnect/", QStandardPaths::LocateDirectory);
KSharedConfigPtr deviceConfig = KSharedConfig::openConfig(path + currentDevice->id());
kcmUi->pluginSelector->addPlugins(scriptinfos, KPluginSelector::ReadConfigFile, i18n("Plugins"), QString(), deviceConfig); kcmUi->pluginSelector->addPlugins(scriptinfos, KPluginSelector::ReadConfigFile, i18n("Plugins"), QString(), deviceConfig);
connect(kcmUi->pluginSelector, SIGNAL(changed(bool)), connect(kcmUi->pluginSelector, SIGNAL(changed(bool)),

View file

@ -21,18 +21,10 @@
#ifndef KDECONNECTKCM_H #ifndef KDECONNECTKCM_H
#define KDECONNECTKCM_H #define KDECONNECTKCM_H
#include <KCModule>
#include <QStandardItemModel> #include <QStandardItemModel>
#include <QDBusConnection>
#include <kcmodule.h>
#include <ksharedconfig.h>
class QModelIndex; class QModelIndex;
class AccountsModel;
class AccountWidget;
class QStackedLayout;
class QItemSelectionModel;
class QDBusInterface;
class DeviceDbusInterface; class DeviceDbusInterface;
class DevicesModel; class DevicesModel;
class DevicesSortProxyModel; class DevicesSortProxyModel;

View file

@ -26,6 +26,7 @@
#include "mounter.h" #include "mounter.h"
#include "sftp_debug.h" #include "sftp_debug.h"
#include <kdeconnectconfig.h>
static const char* idleTimeout_c = "idleTimeout"; static const char* idleTimeout_c = "idleTimeout";
@ -133,7 +134,7 @@ void Mounter::onPakcageReceived(const NetworkPackage& np)
<< "-p" << np.get<QString>("port") << "-p" << np.get<QString>("port")
<< "-d" << "-d"
<< "-f" << "-f"
<< "-o" << "IdentityFile=" + m_sftp->device()->privateKeyPath() << "-o" << "IdentityFile=" + KdeConnectConfig::instance()->privateKeyPath()
<< "-o" << "StrictHostKeyChecking=no" //Do not ask for confirmation because it is not a known host << "-o" << "StrictHostKeyChecking=no" //Do not ask for confirmation because it is not a known host
<< "-o" << "UserKnownHostsFile=/dev/null"; //Prevent storing as a known host << "-o" << "UserKnownHostsFile=/dev/null"; //Prevent storing as a known host