2014-06-09 10:52:16 +01:00
/**
2020-08-17 10:48:10 +01:00
* SPDX - FileCopyrightText : 2013 Albert Vaca < albertvaka @ gmail . com >
2014-06-09 10:52:16 +01:00
*
2020-08-17 10:48:10 +01:00
* SPDX - License - Identifier : GPL - 2.0 - only OR GPL - 3.0 - only OR LicenseRef - KDE - Accepted - GPL
2014-06-09 10:52:16 +01:00
*/
2013-06-25 17:06:51 +01:00
# include "device.h"
2013-08-12 15:09:52 +01:00
2018-05-15 23:15:05 +01:00
# include <QVector>
# include <QSet>
2016-07-05 13:13:48 +01:00
# include <QSslCertificate>
2020-11-26 10:28:32 +00:00
# include <QSslKey>
2014-06-09 10:52:16 +01:00
2013-08-12 15:09:52 +01:00
# include <KSharedConfig>
2013-07-03 02:52:44 +01:00
# include <KConfigGroup>
2014-09-22 01:37:10 +01:00
# include <KLocalizedString>
2013-08-13 04:07:32 +01:00
2014-09-21 23:59:34 +01:00
# include "core_debug.h"
2014-06-14 15:34:00 +01:00
# include "kdeconnectplugin.h"
# include "pluginloader.h"
2013-09-09 17:35:56 +01:00
# include "backends/devicelink.h"
2017-07-22 10:13:21 +01:00
# include "backends/lan/landevicelink.h"
2013-09-09 17:35:56 +01:00
# include "backends/linkprovider.h"
2018-03-04 19:48:51 +00:00
# include "networkpacket.h"
2015-03-02 04:16:07 +00:00
# include "kdeconnectconfig.h"
2015-03-24 11:26:37 +00:00
# include "daemon.h"
2019-06-09 16:28:49 +01:00
# include "dbushelper.h"
2013-08-12 15:09:52 +01:00
Build kdeconnect on sailfish and port some simple plugins
Summary:
Below is a lost of the commits, but, in summary
Port the build system for Sailfish, which means selectively building only the bits we need/can, and only against the KF5 libs that are available.
Allow to build on Qt 5.6
Switch from knotification to nemo notification (not complete!)
Add a very simple example sailfish app.
Note, there is still much missing functionality. Notifications dont work, pairing sort of works but not really, but when it is paired you can send a ping to the desktop client
Dont build kio for Sailfish
Port core build system
Port daemon buld system
Require CoreAddons on Sailfish
Port plugins build for sailfish and include the ping plugin for now
Final build changes for sailfish.
Disable tests and other not needed parts
Add includes for QCA
Fix build errors on sailfish
Get core/ to build on sailfish
Get interfaces/ to build on sailfish
Build daemon on sailfish
On sailfish, dont install the kcm file
Start port plugin to sailfish
Fixup installed files
Add sfos app
Hack declarative plugin to give a public interface
Build sfos app
Compile declarativeplugin into the sfos app for now
Redefine qAsConst for qt 5.6
Packaging fixes
Use official icon
Package .desktop
Reviewers: #kde_connect, apol, nicolasfella, albertvaka
Reviewed By: #kde_connect, apol, nicolasfella, albertvaka
Subscribers: kdeconnect, andyholmes, albertvaka, kossebau, mtijink, vonreth, apol, #kde_connect, nicolasfella
Tags: #kde_connect
Differential Revision: https://phabricator.kde.org/D10703
2018-08-02 20:10:59 +01:00
//In older Qt released, qAsConst isnt available
# include "qtcompat_p.h"
2018-05-15 23:15:05 +01:00
class Device : : DevicePrivate
{
public :
DevicePrivate ( const QString & id )
: m_deviceId ( id )
{
}
~ DevicePrivate ( )
{
qDeleteAll ( m_deviceLinks ) ;
m_deviceLinks . clear ( ) ;
}
const QString m_deviceId ;
QString m_deviceName ;
DeviceType m_deviceType ;
int m_protocolVersion ;
QVector < DeviceLink * > m_deviceLinks ;
QHash < QString , KdeConnectPlugin * > m_plugins ;
QMultiMap < QString , KdeConnectPlugin * > m_pluginsByIncomingCapability ;
QSet < QString > m_supportedPlugins ;
2019-05-10 23:20:12 +01:00
QSet < QString > m_allPlugins ;
2018-05-15 23:15:05 +01:00
QSet < PairingHandler * > m_pairRequests ;
} ;
2017-09-03 20:39:44 +01:00
static void warn ( const QString & info )
2015-12-17 14:53:29 +00:00
{
qWarning ( ) < < " Device pairing error " < < info ;
}
2014-01-22 22:31:27 +00:00
Device : : Device ( QObject * parent , const QString & id )
: QObject ( parent )
2018-05-15 23:15:05 +01:00
, d ( new Device : : DevicePrivate ( id ) )
2013-07-03 02:52:44 +01:00
{
2018-05-15 23:15:05 +01:00
d - > m_protocolVersion = NetworkPacket : : s_protocolVersion ;
2019-09-08 16:09:52 +01:00
KdeConnectConfig : : DeviceInfo info = KdeConnectConfig : : instance ( ) . getTrustedDevice ( d - > m_deviceId ) ;
2013-07-26 15:21:19 +01:00
2018-05-15 23:15:05 +01:00
d - > m_deviceName = info . deviceName ;
d - > m_deviceType = str2type ( info . deviceType ) ;
2015-03-13 23:39:13 +00:00
2013-07-26 15:21:19 +01:00
//Register in bus
2022-04-12 06:40:03 +01:00
QDBusConnection : : sessionBus ( ) . registerObject ( dbusPath ( ) , this , QDBusConnection : : ExportScriptableContents | QDBusConnection : : ExportAdaptors ) ;
2015-12-17 14:53:29 +00:00
2016-09-05 23:42:19 +01:00
//Assume every plugin is supported until addLink is called and we can get the actual list
2019-05-10 23:20:12 +01:00
d - > m_allPlugins = PluginLoader : : instance ( ) - > getPluginList ( ) . toSet ( ) ;
d - > m_supportedPlugins = d - > m_allPlugins ;
2016-09-05 23:42:19 +01:00
2015-12-17 14:53:29 +00:00
connect ( this , & Device : : pairingError , this , & warn ) ;
2013-06-25 17:06:51 +01:00
}
2013-07-03 02:52:44 +01:00
2018-03-04 19:48:51 +00:00
Device : : Device ( QObject * parent , const NetworkPacket & identityPacket , DeviceLink * dl )
2014-01-22 22:31:27 +00:00
: QObject ( parent )
2018-05-15 23:15:05 +01:00
, d ( new Device : : DevicePrivate ( identityPacket . get < QString > ( QStringLiteral ( " deviceId " ) ) ) )
2013-07-03 02:52:44 +01:00
{
2018-05-15 23:15:05 +01:00
d - > m_deviceName = identityPacket . get < QString > ( QStringLiteral ( " deviceName " ) ) ;
2019-05-10 23:20:12 +01:00
d - > m_allPlugins = PluginLoader : : instance ( ) - > getPluginList ( ) . toSet ( ) ;
2018-03-04 19:48:51 +00:00
addLink ( identityPacket , dl ) ;
2015-09-08 16:28:47 +01:00
2013-08-16 05:26:40 +01:00
//Register in bus
2022-04-12 06:40:03 +01:00
QDBusConnection : : sessionBus ( ) . registerObject ( dbusPath ( ) , this , QDBusConnection : : ExportScriptableContents | QDBusConnection : : ExportAdaptors ) ;
2015-12-17 14:53:29 +00:00
connect ( this , & Device : : pairingError , this , & warn ) ;
2019-07-21 16:53:06 +01:00
connect ( this , & Device : : reachableChanged , this , & Device : : statusIconNameChanged ) ;
connect ( this , & Device : : trustedChanged , this , & Device : : statusIconNameChanged ) ;
2013-07-03 02:52:44 +01:00
}
2013-08-16 08:27:32 +01:00
Device : : ~ Device ( )
{
2018-05-15 23:15:05 +01:00
delete d ;
}
QString Device : : id ( ) const
{
return d - > m_deviceId ;
}
QString Device : : name ( ) const
{
return d - > m_deviceName ;
}
QString Device : : type ( ) const
{
return type2str ( d - > m_deviceType ) ;
}
bool Device : : isReachable ( ) const
{
return ! d - > m_deviceLinks . isEmpty ( ) ;
}
int Device : : protocolVersion ( )
{
return d - > m_protocolVersion ;
}
QStringList Device : : supportedPlugins ( ) const
{
return d - > m_supportedPlugins . toList ( ) ;
2013-07-03 02:52:44 +01:00
}
2013-08-13 04:07:32 +01:00
2013-09-01 21:13:03 +01:00
bool Device : : hasPlugin ( const QString & name ) const
2013-08-13 22:23:32 +01:00
{
2018-05-15 23:15:05 +01:00
return d - > m_plugins . contains ( name ) ;
2013-08-13 22:23:32 +01:00
}
2013-09-01 21:13:03 +01:00
QStringList Device : : loadedPlugins ( ) const
2013-08-18 19:27:25 +01:00
{
2018-05-15 23:15:05 +01:00
return d - > m_plugins . keys ( ) ;
2013-08-18 19:27:25 +01:00
}
2013-08-13 04:07:32 +01:00
void Device : : reloadPlugins ( )
{
2018-05-15 23:15:05 +01:00
QHash < QString , KdeConnectPlugin * > newPluginMap , oldPluginMap = d - > m_plugins ;
2016-07-06 16:37:22 +01:00
QMultiMap < QString , KdeConnectPlugin * > newPluginsByIncomingCapability ;
2013-08-13 04:07:32 +01:00
2015-12-01 18:45:14 +00:00
if ( isTrusted ( ) & & isReachable ( ) ) { //Do not load any plugin for unpaired devices, nor useless loading them for unreachable devices
2013-08-13 04:07:32 +01:00
2013-08-14 00:35:12 +01:00
PluginLoader * loader = PluginLoader : : instance ( ) ;
2013-08-13 04:07:32 +01:00
2018-05-15 23:15:05 +01:00
for ( const QString & pluginName : qAsConst ( d - > m_supportedPlugins ) ) {
2015-09-08 19:03:44 +01:00
const KPluginMetaData service = loader - > getPluginInfo ( pluginName ) ;
2013-08-13 04:07:32 +01:00
2015-09-08 19:03:44 +01:00
const bool pluginEnabled = isPluginEnabled ( pluginName ) ;
2018-03-04 19:48:51 +00:00
const QSet < QString > incomingCapabilities = KPluginMetaData : : readStringList ( service . rawData ( ) , QStringLiteral ( " X-KdeConnect-SupportedPacketType " ) ) . toSet ( ) ;
2015-09-08 19:03:44 +01:00
if ( pluginEnabled ) {
2018-05-15 23:15:05 +01:00
KdeConnectPlugin * plugin = d - > m_plugins . take ( pluginName ) ;
2014-07-11 00:54:19 +01:00
if ( ! plugin ) {
plugin = loader - > instantiatePluginForDevice ( pluginName , this ) ;
}
2016-07-06 16:37:22 +01:00
Q_ASSERT ( plugin ) ;
2014-07-11 00:54:19 +01:00
2017-07-20 15:14:07 +01:00
for ( const QString & interface : incomingCapabilities ) {
2016-07-06 16:37:22 +01:00
newPluginsByIncomingCapability . insert ( interface , plugin ) ;
2013-08-14 00:35:12 +01:00
}
2015-09-12 16:48:24 +01:00
2013-10-29 16:29:31 +00:00
newPluginMap [ pluginName ] = plugin ;
2013-08-14 00:35:12 +01:00
}
2013-08-13 04:07:32 +01:00
}
}
2016-08-21 12:21:40 +01:00
const bool differentPlugins = oldPluginMap ! = newPluginMap ;
2016-07-06 16:37:22 +01:00
2013-10-11 14:19:23 +01:00
//Erase all left plugins in the original map (meaning that we don't want
//them anymore, otherwise they would have been moved to the newPluginMap)
2018-05-15 23:15:05 +01:00
qDeleteAll ( d - > m_plugins ) ;
d - > m_plugins = newPluginMap ;
d - > m_pluginsByIncomingCapability = newPluginsByIncomingCapability ;
2013-08-14 00:35:12 +01:00
2022-04-12 06:40:03 +01:00
QDBusConnection bus = QDBusConnection : : sessionBus ( ) ;
2018-05-15 23:15:05 +01:00
for ( KdeConnectPlugin * plugin : qAsConst ( d - > m_plugins ) ) {
2017-01-14 01:49:40 +00:00
//TODO: see how it works in Android (only done once, when created)
2013-10-11 14:19:23 +01:00
plugin - > connected ( ) ;
2016-12-30 15:38:12 +00:00
const QString dbusPath = plugin - > dbusPath ( ) ;
if ( ! dbusPath . isEmpty ( ) ) {
2017-01-27 00:39:03 +00:00
bus . registerObject ( dbusPath , plugin , QDBusConnection : : ExportAllProperties | QDBusConnection : : ExportScriptableInvokables | QDBusConnection : : ExportScriptableSignals | QDBusConnection : : ExportScriptableSlots ) ;
2016-12-30 15:38:12 +00:00
}
2013-08-22 02:21:08 +01:00
}
2016-07-06 16:37:22 +01:00
if ( differentPlugins ) {
Q_EMIT pluginsChanged ( ) ;
2015-09-08 16:28:47 +01:00
}
2013-08-13 04:07:32 +01:00
}
2015-03-02 04:16:07 +00:00
QString Device : : pluginsConfigFile ( ) const
{
2019-09-08 16:09:52 +01:00
return KdeConnectConfig : : instance ( ) . deviceConfigDir ( id ( ) ) . absoluteFilePath ( QStringLiteral ( " config " ) ) ;
2015-03-02 04:16:07 +00:00
}
2013-08-30 18:10:43 +01:00
void Device : : requestPair ( )
2013-07-03 02:52:44 +01:00
{
2015-12-01 18:45:14 +00:00
if ( isTrusted ( ) ) {
Q_EMIT pairingError ( i18n ( " Already paired " ) ) ;
2015-11-30 18:36:01 +00:00
return ;
2015-06-15 03:22:13 +01:00
}
if ( ! isReachable ( ) ) {
2015-12-01 18:45:14 +00:00
Q_EMIT pairingError ( i18n ( " Device not reachable " ) ) ;
2015-06-15 03:22:13 +01:00
return ;
2013-08-30 18:10:43 +01:00
}
2018-05-15 23:15:05 +01:00
for ( DeviceLink * dl : qAsConst ( d - > m_deviceLinks ) ) {
2015-12-02 19:04:35 +00:00
dl - > userRequestsPair ( ) ;
2013-07-03 02:52:44 +01:00
}
2013-08-30 18:10:43 +01:00
}
void Device : : unpair ( )
{
2018-05-15 23:15:05 +01:00
for ( DeviceLink * dl : qAsConst ( d - > m_deviceLinks ) ) {
2015-12-02 19:04:35 +00:00
dl - > userRequestsUnpair ( ) ;
2015-07-09 22:51:08 +01:00
}
2019-09-08 16:09:52 +01:00
KdeConnectConfig : : instance ( ) . removeTrustedDevice ( id ( ) ) ;
2017-07-14 00:01:15 +01:00
Q_EMIT trustedChanged ( false ) ;
2015-03-16 02:13:54 +00:00
}
2013-08-30 18:10:43 +01:00
2015-12-01 18:45:14 +00:00
void Device : : pairStatusChanged ( DeviceLink : : PairStatus status )
2015-03-16 02:13:54 +00:00
{
2015-12-01 18:45:14 +00:00
if ( status = = DeviceLink : : NotPaired ) {
2019-09-08 16:09:52 +01:00
KdeConnectConfig : : instance ( ) . removeTrustedDevice ( id ( ) ) ;
2013-08-30 18:10:43 +01:00
2018-05-15 23:15:05 +01:00
for ( DeviceLink * dl : qAsConst ( d - > m_deviceLinks ) ) {
2015-12-01 18:45:14 +00:00
if ( dl ! = sender ( ) ) {
2015-12-02 19:04:35 +00:00
dl - > setPairStatus ( DeviceLink : : NotPaired ) ;
2015-12-01 18:45:14 +00:00
}
}
} else {
2019-09-08 16:09:52 +01:00
KdeConnectConfig : : instance ( ) . addTrustedDevice ( id ( ) , name ( ) , type ( ) ) ;
2015-11-30 18:36:01 +00:00
}
2015-12-01 18:45:14 +00:00
reloadPlugins ( ) ; //Will load/unload plugins
2015-11-30 18:36:01 +00:00
2015-12-01 18:45:14 +00:00
bool isTrusted = ( status = = DeviceLink : : Paired ) ;
2017-01-13 13:22:01 +00:00
Q_EMIT trustedChanged ( isTrusted ) ;
2015-12-01 18:45:14 +00:00
Q_ASSERT ( isTrusted = = this - > isTrusted ( ) ) ;
2013-07-03 02:52:44 +01:00
}
static bool lessThan ( DeviceLink * p1 , DeviceLink * p2 )
{
2013-07-24 17:42:33 +01:00
return p1 - > provider ( ) - > priority ( ) > p2 - > provider ( ) - > priority ( ) ;
2013-07-03 02:52:44 +01:00
}
2018-03-04 19:48:51 +00:00
void Device : : addLink ( const NetworkPacket & identityPacket , DeviceLink * link )
2013-07-03 02:52:44 +01:00
{
2014-09-21 22:54:27 +01:00
//qCDebug(KDECONNECT_CORE) << "Adding link to" << id() << "via" << link->provider();
2013-07-23 15:11:54 +01:00
2018-03-04 19:48:51 +00:00
setName ( identityPacket . get < QString > ( QStringLiteral ( " deviceName " ) ) ) ;
2020-08-02 12:57:58 +01:00
setType ( identityPacket . get < QString > ( QStringLiteral ( " deviceType " ) ) ) ;
2017-07-14 02:30:49 +01:00
2019-07-04 23:13:55 +01:00
if ( d - > m_deviceLinks . contains ( link ) ) {
2017-07-14 02:30:49 +01:00
return ;
2019-07-04 23:13:55 +01:00
}
2015-12-17 15:44:29 +00:00
2018-05-15 23:15:05 +01:00
d - > m_protocolVersion = identityPacket . get < int > ( QStringLiteral ( " protocolVersion " ) , - 1 ) ;
if ( d - > m_protocolVersion ! = NetworkPacket : : s_protocolVersion ) {
qCWarning ( KDECONNECT_CORE ) < < d - > m_deviceName < < " - warning, device uses a different protocol version " < < d - > m_protocolVersion < < " expected " < < NetworkPacket : : s_protocolVersion ;
2013-10-01 02:11:22 +01:00
}
2016-11-26 14:12:38 +00:00
connect ( link , & QObject : : destroyed ,
this , & Device : : linkDestroyed ) ;
2013-07-04 18:17:22 +01:00
2018-05-15 23:15:05 +01:00
d - > m_deviceLinks . append ( link ) ;
2013-08-10 04:21:55 +01:00
2013-08-13 22:23:32 +01:00
//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.
2015-03-02 04:16:07 +00:00
//-- Actually, we should not destroy them or the provider will store an invalid ref!
2013-08-10 04:21:55 +01:00
2018-03-04 19:48:51 +00:00
connect ( link , & DeviceLink : : receivedPacket ,
this , & Device : : privateReceivedPacket ) ;
2013-07-04 18:17:22 +01:00
2018-05-15 23:15:05 +01:00
std : : sort ( d - > m_deviceLinks . begin ( ) , d - > m_deviceLinks . end ( ) , lessThan ) ;
2013-07-28 21:00:45 +01:00
2018-03-04 19:48:51 +00:00
const bool capabilitiesSupported = identityPacket . has ( QStringLiteral ( " incomingCapabilities " ) ) | | identityPacket . has ( QStringLiteral ( " outgoingCapabilities " ) ) ;
2016-07-06 16:37:22 +01:00
if ( capabilitiesSupported ) {
2018-03-04 19:48:51 +00:00
const QSet < QString > outgoingCapabilities = identityPacket . get < QStringList > ( QStringLiteral ( " outgoingCapabilities " ) ) . toSet ( )
, incomingCapabilities = identityPacket . get < QStringList > ( QStringLiteral ( " incomingCapabilities " ) ) . toSet ( ) ;
2016-07-06 16:37:22 +01:00
2018-05-15 23:15:05 +01:00
d - > m_supportedPlugins = PluginLoader : : instance ( ) - > pluginsForCapabilities ( incomingCapabilities , outgoingCapabilities ) ;
2016-07-12 11:49:21 +01:00
//qDebug() << "new plugins for" << m_deviceName << m_supportedPlugins << incomingCapabilities << outgoingCapabilities;
2016-07-06 16:37:22 +01:00
} else {
2018-05-15 23:15:05 +01:00
d - > m_supportedPlugins = PluginLoader : : instance ( ) - > getPluginList ( ) . toSet ( ) ;
2016-07-06 16:37:22 +01:00
}
reloadPlugins ( ) ;
2018-05-15 23:15:05 +01:00
if ( d - > m_deviceLinks . size ( ) = = 1 ) {
2016-11-23 16:24:03 +00:00
Q_EMIT reachableChanged ( true ) ;
2013-07-28 21:00:45 +01:00
}
2015-07-25 12:45:19 +01:00
2015-12-06 00:51:53 +00:00
connect ( link , & DeviceLink : : pairStatusChanged , this , & Device : : pairStatusChanged ) ;
2017-01-24 23:22:22 +00:00
connect ( link , & DeviceLink : : pairingRequest , this , & Device : : addPairingRequest ) ;
connect ( link , & DeviceLink : : pairingRequestExpired , this , & Device : : removePairingRequest ) ;
2015-12-06 00:51:53 +00:00
connect ( link , & DeviceLink : : pairingError , this , & Device : : pairingError ) ;
2013-07-03 02:52:44 +01:00
}
2017-01-24 23:22:22 +00:00
void Device : : addPairingRequest ( PairingHandler * handler )
{
2018-05-15 23:15:05 +01:00
const bool wasEmpty = d - > m_pairRequests . isEmpty ( ) ;
d - > m_pairRequests . insert ( handler ) ;
2017-01-25 00:18:14 +00:00
2018-05-15 23:15:05 +01:00
if ( wasEmpty ! = d - > m_pairRequests . isEmpty ( ) )
Q_EMIT hasPairingRequestsChanged ( ! d - > m_pairRequests . isEmpty ( ) ) ;
2017-01-24 23:22:22 +00:00
}
void Device : : removePairingRequest ( PairingHandler * handler )
{
2018-05-15 23:15:05 +01:00
const bool wasEmpty = d - > m_pairRequests . isEmpty ( ) ;
d - > m_pairRequests . remove ( handler ) ;
2017-01-25 00:18:14 +00:00
2018-05-15 23:15:05 +01:00
if ( wasEmpty ! = d - > m_pairRequests . isEmpty ( ) )
Q_EMIT hasPairingRequestsChanged ( ! d - > m_pairRequests . isEmpty ( ) ) ;
2017-02-20 20:00:26 +00:00
}
bool Device : : hasPairingRequests ( ) const
{
2018-05-15 23:15:05 +01:00
return ! d - > m_pairRequests . isEmpty ( ) ;
2017-01-24 23:22:22 +00:00
}
void Device : : acceptPairing ( )
{
2018-05-15 23:15:05 +01:00
if ( d - > m_pairRequests . isEmpty ( ) )
2017-01-24 23:22:22 +00:00
qWarning ( ) < < " no pair requests to accept! " ;
//copying because the pairing handler will be removed upon accept
2018-05-15 23:15:05 +01:00
const auto prCopy = d - > m_pairRequests ;
2017-01-24 23:22:22 +00:00
for ( auto ph : prCopy )
ph - > acceptPairing ( ) ;
}
void Device : : rejectPairing ( )
{
2018-05-15 23:15:05 +01:00
if ( d - > m_pairRequests . isEmpty ( ) )
2017-01-24 23:22:22 +00:00
qWarning ( ) < < " no pair requests to reject! " ;
//copying because the pairing handler will be removed upon reject
2018-05-15 23:15:05 +01:00
const auto prCopy = d - > m_pairRequests ;
2017-01-24 23:22:22 +00:00
for ( auto ph : prCopy )
ph - > rejectPairing ( ) ;
}
2013-07-04 18:17:22 +01:00
void Device : : linkDestroyed ( QObject * o )
{
removeLink ( static_cast < DeviceLink * > ( o ) ) ;
}
2013-07-03 02:52:44 +01:00
void Device : : removeLink ( DeviceLink * link )
{
2018-05-15 23:15:05 +01:00
d - > m_deviceLinks . removeAll ( link ) ;
2013-07-28 21:00:45 +01:00
2014-09-21 22:54:27 +01:00
//qCDebug(KDECONNECT_CORE) << "RemoveLink" << m_deviceLinks.size() << "links remaining";
2013-07-28 21:00:45 +01:00
2018-05-15 23:15:05 +01:00
if ( d - > m_deviceLinks . isEmpty ( ) ) {
2013-08-16 00:01:58 +01:00
reloadPlugins ( ) ;
2016-11-23 16:24:03 +00:00
Q_EMIT reachableChanged ( false ) ;
2013-07-28 21:00:45 +01:00
}
2013-07-03 02:52:44 +01:00
}
2018-03-04 19:48:51 +00:00
bool Device : : sendPacket ( NetworkPacket & np )
2013-07-03 02:52:44 +01:00
{
2018-03-04 19:48:51 +00:00
Q_ASSERT ( np . type ( ) ! = PACKET_TYPE_PAIR ) ;
2015-12-02 19:04:35 +00:00
Q_ASSERT ( isTrusted ( ) ) ;
2018-03-04 19:48:51 +00:00
//Maybe we could block here any packet that is not an identity or a pairing packet to prevent sending non encrypted data
2018-05-15 23:15:05 +01:00
for ( DeviceLink * dl : qAsConst ( d - > m_deviceLinks ) ) {
2018-03-04 19:48:51 +00:00
if ( dl - > sendPacket ( np ) ) return true ;
2013-08-13 04:40:39 +01:00
}
2013-07-23 15:11:54 +01:00
return false ;
2013-07-03 02:52:44 +01:00
}
2018-03-04 19:48:51 +00:00
void Device : : privateReceivedPacket ( const NetworkPacket & np )
2013-07-03 02:52:44 +01:00
{
2018-03-04 19:48:51 +00:00
Q_ASSERT ( np . type ( ) ! = PACKET_TYPE_PAIR ) ;
2016-07-06 16:37:22 +01:00
if ( isTrusted ( ) ) {
2018-05-15 23:15:05 +01:00
const QList < KdeConnectPlugin * > plugins = d - > m_pluginsByIncomingCapability . values ( np . type ( ) ) ;
2016-06-03 14:51:05 +01:00
if ( plugins . isEmpty ( ) ) {
2018-03-04 19:48:51 +00:00
qWarning ( ) < < " discarding unsupported packet " < < np . type ( ) < < " for " < < name ( ) ;
2016-06-03 14:51:05 +01:00
}
2017-07-20 15:14:07 +01:00
for ( KdeConnectPlugin * plugin : plugins ) {
2018-03-04 19:48:51 +00:00
plugin - > receivePacket ( np ) ;
2013-10-29 16:29:31 +00:00
}
} else {
2018-03-04 19:48:51 +00:00
qCDebug ( KDECONNECT_CORE ) < < " device " < < name ( ) < < " not paired, ignoring packet " < < np . type ( ) ;
2015-07-27 16:28:58 +01:00
unpair ( ) ;
2013-07-03 02:52:44 +01:00
}
2013-08-30 18:10:43 +01:00
}
2015-12-01 18:45:14 +00:00
bool Device : : isTrusted ( ) const
2015-12-01 15:25:34 +00:00
{
2019-09-08 16:09:52 +01:00
return KdeConnectConfig : : instance ( ) . trustedDevices ( ) . contains ( id ( ) ) ;
2013-11-06 20:34:06 +00:00
}
2013-07-23 15:11:54 +01:00
QStringList Device : : availableLinks ( ) const
{
QStringList sl ;
2018-05-15 23:15:05 +01:00
sl . reserve ( d - > m_deviceLinks . size ( ) ) ;
for ( DeviceLink * dl : qAsConst ( d - > m_deviceLinks ) ) {
2013-07-24 17:42:33 +01:00
sl . append ( dl - > provider ( ) - > name ( ) ) ;
2013-07-23 15:11:54 +01:00
}
return sl ;
}
2016-01-10 15:12:13 +00:00
void Device : : cleanUnneededLinks ( ) {
if ( isTrusted ( ) ) {
return ;
}
2018-05-15 23:15:05 +01:00
for ( int i = 0 ; i < d - > m_deviceLinks . size ( ) ; ) {
DeviceLink * dl = d - > m_deviceLinks [ i ] ;
2016-01-10 15:12:13 +00:00
if ( ! dl - > linkShouldBeKeptAlive ( ) ) {
dl - > deleteLater ( ) ;
2018-05-15 23:15:05 +01:00
d - > m_deviceLinks . remove ( i ) ;
2016-01-10 15:12:13 +00:00
} else {
i + + ;
}
}
}
2017-07-22 10:13:21 +01:00
QHostAddress Device : : getLocalIpAddress ( ) const
{
2018-11-25 22:58:24 +00:00
for ( DeviceLink * dl : qAsConst ( d - > m_deviceLinks ) ) {
2017-07-22 10:13:21 +01:00
LanDeviceLink * ldl = dynamic_cast < LanDeviceLink * > ( dl ) ;
if ( ldl ) {
return ldl - > hostAddress ( ) ;
}
}
return QHostAddress : : Null ;
}
2017-09-03 20:39:44 +01:00
Device : : DeviceType Device : : str2type ( const QString & deviceType ) {
2016-11-26 14:38:08 +00:00
if ( deviceType = = QLatin1String ( " desktop " ) ) return Desktop ;
if ( deviceType = = QLatin1String ( " laptop " ) ) return Laptop ;
if ( deviceType = = QLatin1String ( " smartphone " ) | | deviceType = = QLatin1String ( " phone " ) ) return Phone ;
if ( deviceType = = QLatin1String ( " tablet " ) ) return Tablet ;
2018-05-10 12:12:42 +01:00
if ( deviceType = = QLatin1String ( " tv " ) ) return Tv ;
2013-11-06 20:31:37 +00:00
return Unknown ;
}
2013-11-06 20:34:06 +00:00
QString Device : : type2str ( Device : : DeviceType deviceType ) {
2016-11-26 14:38:08 +00:00
if ( deviceType = = Desktop ) return QStringLiteral ( " desktop " ) ;
if ( deviceType = = Laptop ) return QStringLiteral ( " laptop " ) ;
if ( deviceType = = Phone ) return QStringLiteral ( " smartphone " ) ;
if ( deviceType = = Tablet ) return QStringLiteral ( " tablet " ) ;
2018-05-10 12:12:42 +01:00
if ( deviceType = = Tv ) return QStringLiteral ( " tv " ) ;
2016-11-26 14:38:08 +00:00
return QStringLiteral ( " unknown " ) ;
2014-06-14 15:34:00 +01:00
}
2014-06-14 18:09:31 +01:00
2015-05-18 07:28:58 +01:00
QString Device : : statusIconName ( ) const
{
2015-12-01 18:45:14 +00:00
return iconForStatus ( isReachable ( ) , isTrusted ( ) ) ;
2015-05-18 07:28:58 +01:00
}
2014-06-14 18:09:31 +01:00
QString Device : : iconName ( ) const
{
2015-05-18 07:28:58 +01:00
return iconForStatus ( true , false ) ;
}
2015-12-01 18:45:14 +00:00
QString Device : : iconForStatus ( bool reachable , bool trusted ) const
2015-05-18 07:28:58 +01:00
{
2018-05-15 23:15:05 +01:00
Device : : DeviceType deviceType = d - > m_deviceType ;
2015-05-18 07:28:58 +01:00
if ( deviceType = = Device : : Unknown ) {
deviceType = Device : : Phone ; //Assume phone if we don't know the type
} else if ( deviceType = = Device : : Desktop ) {
deviceType = Device : : Device : : Laptop ; // We don't have desktop icon yet
2014-06-14 18:09:31 +01:00
}
2015-05-18 07:28:58 +01:00
2015-12-01 18:45:14 +00:00
QString status = ( reachable ? ( trusted ? QStringLiteral ( " connected " ) : QStringLiteral ( " disconnected " ) ) : QStringLiteral ( " trusted " ) ) ;
2015-05-18 07:28:58 +01:00
QString type = type2str ( deviceType ) ;
2016-11-28 15:27:13 +00:00
return type + status ;
2014-06-14 18:09:31 +01:00
}
2015-03-14 03:28:54 +00:00
2017-09-03 20:39:44 +01:00
void Device : : setName ( const QString & name )
2015-03-14 03:28:54 +00:00
{
2018-05-15 23:15:05 +01:00
if ( d - > m_deviceName ! = name ) {
d - > m_deviceName = name ;
2020-08-02 12:57:58 +01:00
KdeConnectConfig : : instance ( ) . setDeviceProperty ( d - > m_deviceId , QStringLiteral ( " name " ) , name ) ;
2015-03-14 03:28:54 +00:00
Q_EMIT nameChanged ( name ) ;
}
}
2015-09-07 13:54:33 +01:00
2020-08-02 12:57:58 +01:00
void Device : : setType ( const QString & strtype )
{
auto type = str2type ( strtype ) ;
if ( d - > m_deviceType ! = type ) {
d - > m_deviceType = type ;
KdeConnectConfig : : instance ( ) . setDeviceProperty ( d - > m_deviceId , QStringLiteral ( " type " ) , strtype ) ;
Q_EMIT typeChanged ( strtype ) ;
}
}
2015-09-07 13:54:33 +01:00
KdeConnectPlugin * Device : : plugin ( const QString & pluginName ) const
{
2018-05-15 23:15:05 +01:00
return d - > m_plugins [ pluginName ] ;
2015-09-07 13:54:33 +01:00
}
2015-09-08 16:28:47 +01:00
void Device : : setPluginEnabled ( const QString & pluginName , bool enabled )
{
2019-05-10 23:20:12 +01:00
if ( ! d - > m_allPlugins . contains ( pluginName ) ) {
return ;
}
2015-09-08 16:28:47 +01:00
KConfigGroup pluginStates = KSharedConfig : : openConfig ( pluginsConfigFile ( ) ) - > group ( " Plugins " ) ;
const QString enabledKey = pluginName + QStringLiteral ( " Enabled " ) ;
pluginStates . writeEntry ( enabledKey , enabled ) ;
reloadPlugins ( ) ;
}
bool Device : : isPluginEnabled ( const QString & pluginName ) const
{
const QString enabledKey = pluginName + QStringLiteral ( " Enabled " ) ;
KConfigGroup pluginStates = KSharedConfig : : openConfig ( pluginsConfigFile ( ) ) - > group ( " Plugins " ) ;
return ( pluginStates . hasKey ( enabledKey ) ? pluginStates . readEntry ( enabledKey , false )
: PluginLoader : : instance ( ) - > getPluginInfo ( pluginName ) . isEnabledByDefault ( ) ) ;
}
2015-11-30 18:36:01 +00:00
QString Device : : encryptionInfo ( ) const
{
QString result ;
2020-11-26 10:28:32 +00:00
const QCryptographicHash : : Algorithm digestAlgorithm = QCryptographicHash : : Algorithm : : Sha256 ;
2015-11-30 18:36:01 +00:00
2020-11-26 10:28:32 +00:00
QString localChecksum = QString : : fromLatin1 ( KdeConnectConfig : : instance ( ) . certificate ( ) . digest ( digestAlgorithm ) . toHex ( ) ) ;
for ( int i = 2 ; i < localChecksum . size ( ) ; i + = 3 ) {
localChecksum . insert ( i , QStringLiteral ( " : " ) ) ; // Improve readability
2015-11-30 18:36:01 +00:00
}
2020-11-26 10:28:32 +00:00
result + = i18n ( " SHA256 fingerprint of your device certificate is: %1 \n " , localChecksum ) ;
2015-11-30 18:36:01 +00:00
2019-09-08 16:09:52 +01:00
std : : string remotePem = KdeConnectConfig : : instance ( ) . getDeviceProperty ( id ( ) , QStringLiteral ( " certificate " ) ) . toStdString ( ) ;
2016-11-16 20:37:07 +00:00
QSslCertificate remoteCertificate = QSslCertificate ( QByteArray ( remotePem . c_str ( ) , ( int ) remotePem . size ( ) ) ) ;
2020-11-26 10:28:32 +00:00
QString remoteChecksum = QString : : fromLatin1 ( remoteCertificate . digest ( digestAlgorithm ) . toHex ( ) ) ;
for ( int i = 2 ; i < remoteChecksum . size ( ) ; i + = 3 ) {
remoteChecksum . insert ( i , QStringLiteral ( " : " ) ) ; // Improve readability
2015-11-30 18:36:01 +00:00
}
2020-11-26 10:28:32 +00:00
result + = i18n ( " SHA256 fingerprint of remote device certificate is: %1 \n " , remoteChecksum ) ;
2015-11-30 18:36:01 +00:00
return result ;
}
2020-11-26 10:28:32 +00:00
QSslCertificate Device : : certificate ( ) const
{
if ( ! d - > m_deviceLinks . isEmpty ( ) ) {
return d - > m_deviceLinks [ 0 ] - > certificate ( ) ;
}
return QSslCertificate ( ) ;
}
QByteArray Device : : verificationKey ( ) const
{
auto a = KdeConnectConfig : : instance ( ) . certificate ( ) . publicKey ( ) . toDer ( ) ;
auto b = certificate ( ) . publicKey ( ) . toDer ( ) ;
if ( a < b ) {
std : : swap ( a , b ) ;
}
QCryptographicHash hash ( QCryptographicHash : : Sha256 ) ;
hash . addData ( a ) ;
hash . addData ( b ) ;
return hash . result ( ) . toHex ( ) ;
}
2018-08-03 00:53:21 +01:00
QString Device : : pluginIconName ( const QString & pluginName )
{
if ( hasPlugin ( pluginName ) ) {
return d - > m_plugins [ pluginName ] - > iconName ( ) ;
}
return QString ( ) ;
}