...
 
Commits (92)
......@@ -7,3 +7,4 @@ insert_final_newline = true
indent_style = space
indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
......@@ -16,3 +16,9 @@ KDEConnect.includes
*.qmlc
*.rej
.vscode
# Eclipse settings
.cproject
.project
.settings/*
......@@ -2,15 +2,28 @@ cmake_minimum_required(VERSION 3.0)
project(kdeconnect)
set(KDECONNECT_VERSION_MAJOR 1)
set(KDECONNECT_VERSION_MINOR 3)
set(KDECONNECT_VERSION_PATCH 3)
find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
include(KDEInstallDirs)
include(KDECompilerSettings NO_POLICY_SCOPE)
include(KDECMakeSettings)
include(ECMAddTests)
include(ECMSetupVersion)
include(ECMInstallIcons)
include(FeatureSummary)
include(ECMQtDeclareLoggingCategory)
include(GenerateExportHeader)
set(KDECONNECT_VERSION "${KDECONNECT_VERSION_MAJOR}.${KDECONNECT_VERSION_MINOR}.${KDECONNECT_VERSION_PATCH}")
include(KDEConnectMacros.cmake)
find_package(PkgConfig)
ecm_setup_version(1.3.3
VARIABLE_PREFIX KDECONNECT
VERSION_HEADER ${CMAKE_CURRENT_BINARY_DIR}/kdeconnect-version.h
)
if (SAILFISHOS)
find_package(PkgConfig)
set(KF5_MIN_VERSION "5.31.0")
set(QT_MIN_VERSION "5.6.0")
set(KF5_REQUIRED_COMPONENTS I18n DBusAddons CoreAddons IconThemes Config)
......@@ -23,7 +36,7 @@ if (SAILFISHOS)
add_definitions(-DQT_NO_URL_CAST_FROM_STRING)
else()
set(KF5_MIN_VERSION "5.42.0")
set(QT_MIN_VERSION "5.7.0")
set(QT_MIN_VERSION "5.10.0")
set(KF5_REQUIRED_COMPONENTS I18n ConfigWidgets DBusAddons IconThemes Notifications KIO KCMUtils Service)
set(KF5_OPTIONAL_COMPONENTS DocTools)
if(UNIX)
......@@ -31,13 +44,12 @@ else()
endif()
set(QCA_MIN_VERSION "2.1.0")
find_package(Qca-qt5 ${QCA_MIN_VERSION} REQUIRED)
find_package(KF5PulseAudioQt)
add_definitions(-DQT_NO_URL_CAST_FROM_STRING -DQT_NO_KEYWORDS)
if(NOT WIN32 AND NOT APPLE)
find_package(KF5PulseAudioQt REQUIRED)
endif()
add_definitions(-DQT_NO_URL_CAST_FROM_STRING -DQT_NO_KEYWORDS -DQT_NO_CAST_FROM_ASCII)
endif()
find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} ${CMAKE_SOURCE_DIR}/cmake)
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Quick Network)
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS ${KF5_REQUIRED_COMPONENTS})
if (KF5_OPTIONAL_COMPONENTS)
......@@ -57,20 +69,6 @@ set_package_properties(KF5Kirigami2 PROPERTIES
TYPE RUNTIME
)
configure_file(kdeconnect-version.h.in ${CMAKE_CURRENT_BINARY_DIR}/kdeconnect-version.h)
include(KDEInstallDirs)
include(KDECompilerSettings NO_POLICY_SCOPE)
include(KDECMakeSettings)
include(ECMAddTests)
include(ECMSetupVersion)
include(ECMInstallIcons)
include(FeatureSummary)
include(KDEConnectMacros.cmake)
include(GenerateExportHeader)
add_subdirectory(core)
if(NOT SAILFISHOS)
add_subdirectory(kcm)
......
......@@ -4,5 +4,20 @@
# Thoroughly inspired in kdevplatform_add_plugin
function(kdeconnect_add_plugin)
string(TOUPPER ${ARGV0} identifier)
ecm_qt_declare_logging_category(
kdeconnect_${ARGV0}_SRCS
HEADER ${ARGV0}-debug.h
IDENTIFIER KDECONNECT_PLUGIN_${identifier}
CATEGORY_NAME kdeconnect.plugin.${ARGV0}
)
kcoreaddons_add_plugin(kdeconnect_${ARGV0} JSON kdeconnect_${ARGV0}.json SOURCES ${kdeconnect_${ARGV0}_SRCS} INSTALL_NAMESPACE kdeconnect)
endfunction()
function(kdeconnect_add_plugin_old)
kcoreaddons_add_plugin(${ARGN} INSTALL_NAMESPACE kdeconnect)
endfunction()
......@@ -7,6 +7,7 @@ target_include_directories(kdeconnect-cli PUBLIC ${CMAKE_BINARY_DIR})
target_link_libraries(kdeconnect-cli
kdeconnectinterfaces
kdeconnectcore
KF5::CoreAddons
KF5::I18n
)
......
This diff is collapsed.
project(KDEConnectCore)
add_definitions(-DTRANSLATION_DOMAIN=\"kdeconnect-core\")
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
)
set(KDECONNECT_PRIVATE_DBUS_ADDR unix:path=/tmp/kdeconnect-dbus)
set(KDECONNECT_PRIVATE_DBUS_NAME DBusKDEConnectOnly)
configure_file(dbushelper.h.in ${CMAKE_CURRENT_BINARY_DIR}/dbushelper.h)
add_subdirectory(backends/lan)
add_subdirectory(backends/loopback)
......@@ -33,9 +31,17 @@ set(kdeconnectcore_SRCS
dbushelper.cpp
networkpacket.cpp
filetransferjob.cpp
compositefiletransferjob.cpp
daemon.cpp
device.cpp
core_debug.cpp
notificationserverinfo.cpp
)
ecm_qt_declare_logging_category(
kdeconnectcore_SRCS
HEADER core_debug.h
IDENTIFIER KDECONNECT_CORE
CATEGORY_NAME kdeconnect.core
)
add_library(kdeconnectcore ${kdeconnectcore_SRCS})
......
......@@ -45,7 +45,7 @@ BluetoothDeviceLink::BluetoothDeviceLink(const QString& deviceId, LinkProvider*
QString BluetoothDeviceLink::name()
{
return "BluetoothLink"; // Should be same in both android and kde version
return QStringLiteral("BluetoothLink"); // Should be same in both android and kde version
}
bool BluetoothDeviceLink::sendPacket(NetworkPacket& np)
......
......@@ -23,7 +23,7 @@
BluetoothDownloadJob::BluetoothDownloadJob(const QBluetoothAddress& remoteAddress, const QVariantMap& transferInfo, QObject* parent)
: QObject(parent)
, mRemoteAddress(remoteAddress)
, mTransferUuid(QBluetoothUuid(transferInfo.value("uuid").toString()))
, mTransferUuid(QBluetoothUuid(transferInfo.value(QStringLiteral("uuid")).toString()))
, mSocket(new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol))
{
}
......
......@@ -34,7 +34,7 @@
BluetoothLinkProvider::BluetoothLinkProvider()
{
mServiceUuid = QBluetoothUuid(QString("185f3df4-3268-4e3f-9fca-d4d5059915bd"));
mServiceUuid = QBluetoothUuid(QStringLiteral("185f3df4-3268-4e3f-9fca-d4d5059915bd"));
connectTimer = new QTimer(this);
connectTimer->setInterval(30000);
......@@ -61,7 +61,7 @@ void BluetoothLinkProvider::onStart()
mServiceDiscoveryAgent->start();
connectTimer->start();
mKdeconnectService = mBluetoothServer->listen(mServiceUuid, "KDE Connect");
mKdeconnectService = mBluetoothServer->listen(mServiceUuid, QStringLiteral("KDE Connect"));
}
void BluetoothLinkProvider::onStop()
......@@ -183,7 +183,7 @@ void BluetoothLinkProvider::clientIdentityReceived()
disconnect(socket, SIGNAL(readyRead()), this, SLOT(clientIdentityReceived()));
NetworkPacket receivedPacket("");
NetworkPacket receivedPacket;
bool success = NetworkPacket::unserialize(identityArray, &receivedPacket);
if (!success || receivedPacket.type() != PACKET_TYPE_IDENTITY) {
......@@ -198,10 +198,10 @@ void BluetoothLinkProvider::clientIdentityReceived()
disconnect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(connectError()));
const QString& deviceId = receivedPacket.get<QString>("deviceId");
const QString& deviceId = receivedPacket.get<QString>(QStringLiteral("deviceId"));
BluetoothDeviceLink* deviceLink = new BluetoothDeviceLink(deviceId, this, socket);
NetworkPacket np2("");
NetworkPacket np2;
NetworkPacket::createIdentityPacket(&np2);
success = deviceLink->sendPacket(np2);
......@@ -243,7 +243,7 @@ void BluetoothLinkProvider::serverNewConnection()
connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(connectError()));
connect(socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
NetworkPacket np2("");
NetworkPacket np2;
NetworkPacket::createIdentityPacket(&np2);
socket->write(np2.serialize());
......@@ -276,7 +276,7 @@ void BluetoothLinkProvider::serverDataReceived()
disconnect(socket, SIGNAL(readyRead()), this, SLOT(serverDataReceived()));
disconnect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(connectError()));
NetworkPacket receivedPacket("");
NetworkPacket receivedPacket;
bool success = NetworkPacket::unserialize(identityArray, &receivedPacket);
if (!success || receivedPacket.type() != PACKET_TYPE_IDENTITY) {
......@@ -289,7 +289,7 @@ void BluetoothLinkProvider::serverDataReceived()
qCDebug(KDECONNECT_CORE()) << "Received identity packet from" << socket->peerAddress();
const QString& deviceId = receivedPacket.get<QString>("deviceId");
const QString& deviceId = receivedPacket.get<QString>(QStringLiteral("deviceId"));
BluetoothDeviceLink* deviceLink = new BluetoothDeviceLink(deviceId, this, socket);
connect(deviceLink, SIGNAL(destroyed(QObject*)),
......
......@@ -45,7 +45,7 @@ public:
BluetoothLinkProvider();
virtual ~BluetoothLinkProvider();
QString name() override { return "BluetoothLinkProvider"; }
QString name() override { return QStringLiteral("BluetoothLinkProvider"); }
int priority() override { return PRIORITY_MEDIUM; }
public Q_SLOTS:
......
......@@ -42,7 +42,7 @@ void BluetoothPairingHandler::packetReceived(const NetworkPacket& np)
m_pairingTimeout.stop();
bool wantsPair = np.get<bool>("pair");
bool wantsPair = np.get<bool>(QStringLiteral("pair"));
if (wantsPair) {
......@@ -91,7 +91,7 @@ bool BluetoothPairingHandler::requestPairing()
}
NetworkPacket np(PACKET_TYPE_PAIR);
np.set("pair", true);
np.set(QStringLiteral("pair"), true);
bool success;
success = deviceLink()->sendPacket(np);
if (success) {
......@@ -106,7 +106,7 @@ bool BluetoothPairingHandler::acceptPairing()
qCDebug(KDECONNECT_CORE) << "User accepts pairing";
m_pairingTimeout.stop(); // Just in case it is started
NetworkPacket np(PACKET_TYPE_PAIR);
np.set("pair", true);
np.set(QStringLiteral("pair"), true);
bool success = deviceLink()->sendPacket(np);
if (success) {
setInternalPairStatus(Paired);
......@@ -118,14 +118,14 @@ void BluetoothPairingHandler::rejectPairing()
{
qCDebug(KDECONNECT_CORE) << "User rejects pairing";
NetworkPacket np(PACKET_TYPE_PAIR);
np.set("pair", false);
np.set(QStringLiteral("pair"), false);
deviceLink()->sendPacket(np);
setInternalPairStatus(NotPaired);
}
void BluetoothPairingHandler::unpair() {
NetworkPacket np(PACKET_TYPE_PAIR);
np.set("pair", false);
np.set(QStringLiteral("pair"), false);
deviceLink()->sendPacket(np);
setInternalPairStatus(NotPaired);
}
......@@ -133,7 +133,7 @@ void BluetoothPairingHandler::unpair() {
void BluetoothPairingHandler::pairingTimeout()
{
NetworkPacket np(PACKET_TYPE_PAIR);
np.set("pair", false);
np.set(QStringLiteral("pair"), false);
deviceLink()->sendPacket(np);
setInternalPairStatus(NotPaired); //Will emit the change as well
Q_EMIT pairingError(i18n("Timed out"));
......
......@@ -43,11 +43,11 @@ public:
BluetoothPairingHandler(DeviceLink* deviceLink);
virtual ~BluetoothPairingHandler() { }
virtual void packetReceived(const NetworkPacket& np) Q_DECL_OVERRIDE;
virtual bool requestPairing() Q_DECL_OVERRIDE;
virtual bool acceptPairing() Q_DECL_OVERRIDE;
virtual void rejectPairing() Q_DECL_OVERRIDE;
virtual void unpair() Q_DECL_OVERRIDE;
void packetReceived(const NetworkPacket& np) override;
bool requestPairing() override;
bool acceptPairing() override;
void rejectPairing() override;
void unpair() override;
bool isPairRequested() const { return m_status == Requested; }
bool isPaired() const { return m_status == Paired; }
......
......@@ -38,14 +38,14 @@ BluetoothUploadJob::BluetoothUploadJob(const QSharedPointer<QIODevice>& data, co
QVariantMap BluetoothUploadJob::transferInfo() const
{
QVariantMap ret;
ret["uuid"] = mTransferUuid.toString().mid(1, 36);
ret[QStringLiteral("uuid")] = mTransferUuid.toString().mid(1, 36);
return ret;
}
void BluetoothUploadJob::start()
{
connect(mServer, &QBluetoothServer::newConnection, this, &BluetoothUploadJob::newConnection);
mServiceInfo = mServer->listen(mTransferUuid, "KDE Connect Transfer Job");
mServiceInfo = mServer->listen(mTransferUuid, QStringLiteral("KDE Connect Transfer Job"));
Q_ASSERT(mServiceInfo.isValid());
}
......
......@@ -111,7 +111,7 @@ void CompositeUploadJob::startNextSubJob()
//TODO: Create a copy of the networkpacket that can be re-injected if sending via lan fails?
NetworkPacket np = m_currentJob->getNetworkPacket();
np.setPayload(nullptr, np.payloadSize());
np.setPayloadTransferInfo({{"port", m_port}});
np.setPayloadTransferInfo({{QStringLiteral("port"), m_port}});
np.set<int>(QStringLiteral("numberOfFiles"), m_totalJobs);
np.set<quint64>(QStringLiteral("totalPayloadSize"), m_totalPayloadSize);
......@@ -272,7 +272,7 @@ void CompositeUploadJob::slotResult(KJob *job) {
startNextSubJob();
} else {
QPair<QString, QString> field2;
field2.first = QString("Files");
field2.first = QStringLiteral("Files");
field2.second = i18np("Sent 1 file", "Sent %1 files", m_totalJobs);
Q_EMIT description(this, i18n("Sending to %1", Daemon::instance()->getDevice(this->m_deviceId)->name()),
{ QString(), QString() }, field2
......
......@@ -179,7 +179,7 @@ void LanDeviceLink::setPairStatus(PairStatus status)
if (status == Paired) {
Q_ASSERT(KdeConnectConfig::instance()->trustedDevices().contains(deviceId()));
Q_ASSERT(!m_socketLineReader->peerCertificate().isNull());
KdeConnectConfig::instance()->setDeviceProperty(deviceId(), QStringLiteral("certificate"), m_socketLineReader->peerCertificate().toPem());
KdeConnectConfig::instance()->setDeviceProperty(deviceId(), QStringLiteral("certificate"), QString::fromLatin1(m_socketLineReader->peerCertificate().toPem().data()));
}
}
......
......@@ -30,6 +30,7 @@
#include <QHostInfo>
#include <QTcpServer>
#include <QMetaEnum>
#include <QNetworkProxy>
#include <QUdpSocket>
#include <QNetworkSession>
......@@ -44,10 +45,16 @@
#define MIN_VERSION_WITH_SSL_SUPPORT 6
LanLinkProvider::LanLinkProvider(bool testMode)
LanLinkProvider::LanLinkProvider(
bool testMode,
quint16 udpBroadcastPort,
quint16 udpListenPort
)
: m_server(new Server(this))
, m_udpSocket(this)
, m_tcpPort(0)
, m_udpBroadcastPort(udpBroadcastPort)
, m_udpListenPort(udpListenPort)
, m_testMode(testMode)
, m_combineBroadcastsTimer(this)
{
......@@ -85,11 +92,19 @@ void LanLinkProvider::onStart()
{
const QHostAddress bindAddress = m_testMode? QHostAddress::LocalHost : QHostAddress::Any;
bool success = m_udpSocket.bind(bindAddress, UDP_PORT, QUdpSocket::ShareAddress);
bool success = m_udpSocket.bind(bindAddress, m_udpListenPort, QUdpSocket::ShareAddress);
if (!success) {
QAbstractSocket::SocketError sockErr = m_udpSocket.error();
// Refer to https://doc.qt.io/qt-5/qabstractsocket.html#SocketError-enum to decode socket error number
QString errorMessage = QString::fromLatin1(QMetaEnum::fromType<QAbstractSocket::SocketError>().valueToKey(sockErr));
qCritical(KDECONNECT_CORE)
<< QLatin1String("Failed to bind UDP socket on port")
<< m_udpListenPort
<< QLatin1String("with error")
<< errorMessage;
}
Q_ASSERT(success);
qCDebug(KDECONNECT_CORE) << "onStart";
m_tcpPort = MIN_TCP_PORT;
while (!m_server->listen(bindAddress, m_tcpPort)) {
m_tcpPort++;
......@@ -101,13 +116,14 @@ void LanLinkProvider::onStart()
}
onNetworkChange();
qCDebug(KDECONNECT_CORE) << "LanLinkProvider started";
}
void LanLinkProvider::onStop()
{
qCDebug(KDECONNECT_CORE) << "onStop";
m_udpSocket.close();
m_server->close();
qCDebug(KDECONNECT_CORE) << "LanLinkProvider stopped";
}
void LanLinkProvider::onNetworkChange()
......@@ -150,15 +166,14 @@ void LanLinkProvider::broadcastToNetwork()
QHostAddress sourceAddress = ifaceAddress.ip();
if (sourceAddress.protocol() == QAbstractSocket::IPv4Protocol && sourceAddress != QHostAddress::LocalHost) {
qCDebug(KDECONNECT_CORE()) << "Broadcasting as" << sourceAddress;
sendSocket.bind(sourceAddress, UDP_PORT);
sendSocket.writeDatagram(np.serialize(), destAddress, UDP_PORT);
sendSocket.writeDatagram(np.serialize(), destAddress, m_udpBroadcastPort);
sendSocket.close();
}
}
}
}
#else
m_udpSocket.writeDatagram(np.serialize(), destAddress, UDP_PORT);
m_udpSocket.writeDatagram(np.serialize(), destAddress, m_udpBroadcastPort);
#endif
}
......@@ -217,16 +232,17 @@ void LanLinkProvider::udpBroadcastReceived()
}
}
void LanLinkProvider::connectError()
void LanLinkProvider::connectError(QAbstractSocket::SocketError socketError)
{
QSslSocket* socket = qobject_cast<QSslSocket*>(sender());
if (!socket) return;
qCDebug(KDECONNECT_CORE) << "Socket error" << socketError;
qCDebug(KDECONNECT_CORE) << "Fallback (1), try reverse connection (send udp packet)" << socket->errorString();
NetworkPacket np(QLatin1String(""));
NetworkPacket::createIdentityPacket(&np);
np.set(QStringLiteral("tcpPort"), m_tcpPort);
m_udpSocket.writeDatagram(np.serialize(), m_receivedIdentityPackets[socket].sender, UDP_PORT);
m_udpSocket.writeDatagram(np.serialize(), m_receivedIdentityPackets[socket].sender, m_udpBroadcastPort);
//The socket we created didn't work, and we didn't manage
//to create a LanDeviceLink from it, deleting everything.
......@@ -288,7 +304,7 @@ void LanLinkProvider::tcpSocketConnected()
//I think this will never happen, but if it happens the deviceLink
//(or the socket that is now inside it) might not be valid. Delete them.
qCDebug(KDECONNECT_CORE) << "Fallback (2), try reverse connection (send udp packet)";
m_udpSocket.writeDatagram(np2.serialize(), m_receivedIdentityPackets[socket].sender, UDP_PORT);
m_udpSocket.writeDatagram(np2.serialize(), m_receivedIdentityPackets[socket].sender, m_udpBroadcastPort);
}
delete m_receivedIdentityPackets.take(socket).np;
......
......@@ -40,7 +40,16 @@ class KDECONNECTCORE_EXPORT LanLinkProvider
Q_OBJECT
public:
LanLinkProvider(bool testMode = false);
/**
* @param testMode Some special overrides needed while testing
* @param udpBroadcastPort Port which should be used for *sending* identity packets
* @param udpListenPort Port which should be used for *receiving* identity packets
*/
LanLinkProvider(
bool testMode = false,
quint16 udpBroadcastPort = UDP_PORT,
quint16 udpListenPort = UDP_PORT
);
~LanLinkProvider() override;
QString name() override { return QStringLiteral("LanLinkProvider"); }
......@@ -53,6 +62,9 @@ public:
static void configureSslSocket(QSslSocket* socket, const QString& deviceId, bool isDeviceTrusted);
static void configureSocket(QSslSocket* socket);
/**
* This is the default UDP port both for broadcasting and receiving identity packets
*/
const static quint16 UDP_PORT = 1716;
const static quint16 MIN_TCP_PORT = 1716;
const static quint16 MAX_TCP_PORT = 1764;
......@@ -63,7 +75,7 @@ public Q_SLOTS:
void onStop() override;
void tcpSocketConnected();
void encrypted();
void connectError();
void connectError(QAbstractSocket::SocketError socketError);
private Q_SLOTS:
void udpBroadcastReceived();
......@@ -83,6 +95,9 @@ private:
QUdpSocket m_udpSocket;
quint16 m_tcpPort;
quint16 m_udpBroadcastPort;
quint16 m_udpListenPort;
QMap<QString, LanDeviceLink*> m_links;
QMap<QString, LanPairingHandler*> m_pairingHandlers;
......
......@@ -81,7 +81,7 @@ bool LanPairingHandler::requestPairing()
return acceptPairing();
}
NetworkPacket np(PACKET_TYPE_PAIR, {{"pair", true}});
NetworkPacket np(PACKET_TYPE_PAIR, {{QStringLiteral("pair"), true}});
const bool success = deviceLink()->sendPacket(np);
if (success) {
setInternalPairStatus(Requested);
......@@ -91,7 +91,7 @@ bool LanPairingHandler::requestPairing()
bool LanPairingHandler::acceptPairing()
{
NetworkPacket np(PACKET_TYPE_PAIR, {{"pair", true}});
NetworkPacket np(PACKET_TYPE_PAIR, {{QStringLiteral("pair"), true}});
bool success = deviceLink()->sendPacket(np);
if (success) {
setInternalPairStatus(Paired);
......@@ -101,20 +101,20 @@ bool LanPairingHandler::acceptPairing()
void LanPairingHandler::rejectPairing()
{
NetworkPacket np(PACKET_TYPE_PAIR, {{"pair", false}});
NetworkPacket np(PACKET_TYPE_PAIR, {{QStringLiteral("pair"), false}});
deviceLink()->sendPacket(np);
setInternalPairStatus(NotPaired);
}
void LanPairingHandler::unpair() {
NetworkPacket np(PACKET_TYPE_PAIR, {{"pair", false}});
NetworkPacket np(PACKET_TYPE_PAIR, {{QStringLiteral("pair"), false}});
deviceLink()->sendPacket(np);
setInternalPairStatus(NotPaired);
}
void LanPairingHandler::pairingTimeout()
{
NetworkPacket np(PACKET_TYPE_PAIR, {{"pair", false}});
NetworkPacket np(PACKET_TYPE_PAIR, {{QStringLiteral("pair"), false}});
deviceLink()->sendPacket(np);
setInternalPairStatus(NotPaired); //Will emit the change as well
Q_EMIT pairingError(i18n("Timed out"));
......
......@@ -38,7 +38,7 @@ void Server::incomingConnection(qintptr socketDescriptor) {
if (serverSocket->setSocketDescriptor(socketDescriptor)) {
addPendingConnection(serverSocket);
} else {
qWarning() << "setSocketDescriptor failed " + serverSocket->errorString();
qWarning() << "setSocketDescriptor failed" << serverSocket->errorString();
delete serverSocket;
}
}
......
/**
* Copyright 2019 Nicolas Fella <nicolas.fella@gmx.de>
*
* 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 "compositefiletransferjob.h"
#include <core_debug.h>
#include <KLocalizedString>
#include <kio/global.h>
#include <KJobTrackerInterface>
#include <daemon.h>
#include "filetransferjob.h"
CompositeFileTransferJob::CompositeFileTransferJob(const QString& deviceId)
: KCompositeJob()
, m_deviceId(deviceId)
, m_running(false)
, m_currentJobNum(1)
, m_totalJobs(0)
, m_currentJobSendPayloadSize(0)
, m_totalSendPayloadSize(0)
, m_totalPayloadSize(0)
, m_currentJob(nullptr)
, m_prevElapsedTime(0)
{
setCapabilities(Killable);
}
bool CompositeFileTransferJob::isRunning() const
{
return m_running;
}
void CompositeFileTransferJob::start()
{
QMetaObject::invokeMethod(this, "startNextSubJob", Qt::QueuedConnection);
m_running = true;
}
void CompositeFileTransferJob::startNextSubJob()
{
m_currentJob = qobject_cast<FileTransferJob*>(subjobs().at(0));
m_currentJobSendPayloadSize = 0;
emitDescription(m_currentJob->destination().toString());
m_currentJob->start();
connect(m_currentJob, QOverload<KJob*,KJob::Unit,qulonglong>::of(&FileTransferJob::processedAmount), this, &CompositeFileTransferJob::slotProcessedAmount);
}
bool CompositeFileTransferJob::addSubjob(KJob* job)
{
if (FileTransferJob *uploadJob = qobject_cast<FileTransferJob*>(job)) {
const NetworkPacket* np = uploadJob->networkPacket();
if (np->has(QStringLiteral("totalPayloadSize"))) {
m_totalPayloadSize = np->get<quint64>(QStringLiteral("totalPayloadSize"));
setTotalAmount(Bytes, m_totalPayloadSize);
}
if (np->has(QStringLiteral("numberOfFiles"))) {
m_totalJobs = np->get<int>(QStringLiteral("numberOfFiles"));
}
QString filename = np->get<QString>(QStringLiteral("filename"));
emitDescription(filename);
if (!hasSubjobs()) {
QMetaObject::invokeMethod(this, "startNextSubJob", Qt::QueuedConnection);
}
return KCompositeJob::addSubjob(job);
} else {
qCDebug(KDECONNECT_CORE) << "CompositeFileTransferJob::addSubjob() - you can only add FileTransferJob's, ignoring";
return false;
}
return true;
}
bool CompositeFileTransferJob::doKill()
{
m_running = false;
if (m_currentJob) {
return m_currentJob->kill();
}
return true;
}
void CompositeFileTransferJob::slotProcessedAmount(KJob *job, KJob::Unit unit, qulonglong amount)
{
Q_UNUSED(job);
m_currentJobSendPayloadSize = amount;
quint64 uploaded = m_totalSendPayloadSize + m_currentJobSendPayloadSize;
if (uploaded == m_totalPayloadSize || m_prevElapsedTime == 0 || m_timer.elapsed() - m_prevElapsedTime >= 100) {
m_prevElapsedTime = m_timer.elapsed();
setProcessedAmount(unit, uploaded);
const auto elapsed = m_timer.elapsed();
if (elapsed > 0) {
emitSpeed((1000 * uploaded) / elapsed);
}
}
}
void CompositeFileTransferJob::slotResult(KJob *job)
{
//Copies job error and errorText and emits result if job is in error otherwise removes job from subjob list
KCompositeJob::slotResult(job);
if (error() || !m_running) {
return;
}
m_totalSendPayloadSize += m_currentJobSendPayloadSize;
setProcessedAmount(Files, m_currentJobNum);
if (m_currentJobNum < m_totalJobs) {
m_currentJobNum++;
if (!subjobs().empty()) {
startNextSubJob();
}
} else {
emitResult();
}
}
void CompositeFileTransferJob::emitDescription(const QString& currentFileName)
{
QPair<QString, QString> field2;
const QUrl fileUrl(currentFileName);
const QString fileName = fileUrl.toDisplayString(QUrl::PreferLocalFile);
if (m_totalJobs > 1) {
field2.first = i18n("Progress");
field2.second = i18n("Receiving file %1 of %2", m_currentJobNum, m_totalJobs);
}
Q_EMIT description(this, i18np("Receiving file from %2", "Receiving %1 files from %2", m_totalJobs, Daemon::instance()->getDevice(this->m_deviceId)->name()),
{ i18n("File"), fileName }, field2
);
}
/**
* Copyright 2019 Nicolas Fella <nicolas.fella@gmx.de>
*
* 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 COMPOSITEFILETRANSFERJOB_H
#define COMPOSITEFILETRANSFERJOB_H
#include "kdeconnectcore_export.h"
#include <KCompositeJob>
#include <QElapsedTimer>
class FileTransferJob;
class KDECONNECTCORE_EXPORT CompositeFileTransferJob
: public KCompositeJob
{
Q_OBJECT
public:
explicit CompositeFileTransferJob(const QString& deviceId);
void start() override;
bool isRunning() const;
bool addSubjob(KJob* job) override;
protected:
bool doKill() override;
private Q_SLOTS:
void slotProcessedAmount(KJob *job, KJob::Unit unit, qulonglong amount);
void slotResult(KJob *job) override;
void startNextSubJob();
private:
void emitDescription(const QString& currentFileName);
QString m_deviceId;
bool m_running;
int m_currentJobNum;
int m_totalJobs;
quint64 m_currentJobSendPayloadSize;
quint64 m_totalSendPayloadSize;
quint64 m_totalPayloadSize;
FileTransferJob *m_currentJob;
QElapsedTimer m_timer;
quint64 m_prevElapsedTime;
};
#endif //COMPOSITEFILETRANSFERJOB_H
......@@ -20,7 +20,6 @@
#include "daemon.h"
#include <QDBusConnection>
#include <QDBusMetaType>
#include <QNetworkAccessManager>
#include <QDebug>
......@@ -29,6 +28,8 @@
#include "core_debug.h"
#include "kdeconnectconfig.h"
#include "networkpacket.h"
#include "dbushelper.h"
#include "notificationserverinfo.h"
#ifdef KDECONNECT_BLUETOOTH
#include "backends/bluetooth/bluetoothlinkprovider.h"
......@@ -54,6 +55,7 @@ struct DaemonPrivate
QMap<QString, Device*> m_devices;
QSet<QString> m_discoveryModeAcquisitions;
bool m_testMode;
};
Daemon* Daemon::instance()
......@@ -68,10 +70,18 @@ Daemon::Daemon(QObject* parent, bool testMode)
{
Q_ASSERT(!s_instance);
s_instance = this;
qCDebug(KDECONNECT_CORE) << "KdeConnect daemon starting";
d->m_testMode = testMode;
// HACK init may call pure virtual functions from this class so it can't be called directly from the ctor
QTimer::singleShot(0, this, &Daemon::init);
}
void Daemon::init()
{
qCDebug(KDECONNECT_CORE) << "Daemon starting";
//Load backends
if (testMode)
if (d->m_testMode)
d->m_linkProviders.insert(new LoopbackLinkProvider());
else {
d->m_linkProviders.insert(new LanLinkProvider());
......@@ -98,10 +108,12 @@ Daemon::Daemon(QObject* parent, bool testMode)
//Register on DBus
qDBusRegisterMetaType< QMap<QString,QString> >();
QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.kdeconnect"));
QDBusConnection::sessionBus().registerObject(QStringLiteral("/modules/kdeconnect"), this, QDBusConnection::ExportScriptableContents);
DbusHelper::sessionBus().registerService(QStringLiteral("org.kde.kdeconnect"));
DbusHelper::sessionBus().registerObject(QStringLiteral("/modules/kdeconnect"), this, QDBusConnection::ExportScriptableContents);
qCDebug(KDECONNECT_CORE) << "KdeConnect daemon started";
NotificationServerInfo::instance().init();
qCDebug(KDECONNECT_CORE) << "Daemon started";
}
void Daemon::acquireDiscoveryMode(const QString& key)
......@@ -151,7 +163,7 @@ void Daemon::cleanDevices()
void Daemon::forceOnNetworkChange()
{
qCDebug(KDECONNECT_CORE) << "Sending onNetworkChange to " << d->m_linkProviders.size() << " LinkProviders";
qCDebug(KDECONNECT_CORE) << "Sending onNetworkChange to" << d->m_linkProviders.size() << "LinkProviders";
for (LinkProvider* a : qAsConst(d->m_linkProviders)) {
a->onNetworkChange();
}
......@@ -167,6 +179,11 @@ Device*Daemon::getDevice(const QString& deviceId)
return nullptr;
}
const QSet<LinkProvider*>& Daemon::getLinkProviders() const
{
return d->m_linkProviders;
}
QStringList Daemon::devices(bool onlyReachable, bool onlyTrusted) const
{
QStringList ret;
......
......@@ -51,10 +51,13 @@ public:
virtual void askPairingConfirmation(Device* device) = 0;
virtual void reportError(const QString& title, const QString& description) = 0;
virtual void quit() = 0;
virtual QNetworkAccessManager* networkAccessManager();
Device* getDevice(const QString& deviceId);
const QSet<LinkProvider*>& getLinkProviders() const;
QStringList pairingRequests() const;
Q_SCRIPTABLE QString selfId() const;
......@@ -89,6 +92,9 @@ private Q_SLOTS:
void onNewDeviceLink(const NetworkPacket& identityPacket, DeviceLink* dl);
void onDeviceStatusChanged();
private:
void init();
protected:
void addDevice(Device* device);
bool isDiscoveringDevices() const;
......
......@@ -20,14 +20,21 @@
#include "dbushelper.h"
#include <QRegExp>
namespace DbusHelper {
void filterNonExportableCharacters(QString& s)
{
static QRegExp regexp("[^A-Za-z0-9_]", Qt::CaseSensitive, QRegExp::Wildcard);
static QRegExp regexp(QStringLiteral("[^A-Za-z0-9_]"), Qt::CaseSensitive, QRegExp::Wildcard);
s.replace(regexp,QLatin1String("_"));
}
QDBusConnection sessionBus()
{
#ifdef Q_OS_MAC
return QDBusConnection::connectToBus(QStringLiteral(KDECONNECT_PRIVATE_DBUS_ADDR), QStringLiteral(KDECONNECT_PRIVATE_DBUS_NAME));
#else
return QDBusConnection::sessionBus();
#endif
}
}
......@@ -21,11 +21,17 @@
#ifndef KDECONNECT_DBUSHELPER_H
#define KDECONNECT_DBUSHELPER_H
#include <QString>
#include <QDBusConnection>
#include "kdeconnectcore_export.h"
#define KDECONNECT_PRIVATE_DBUS_ADDR "${KDECONNECT_PRIVATE_DBUS_ADDR}"
#define KDECONNECT_PRIVATE_DBUS_NAME "${KDECONNECT_PRIVATE_DBUS_NAME}"
namespace DbusHelper {
void KDECONNECTCORE_EXPORT filterNonExportableCharacters(QString& s);
QDBusConnection KDECONNECTCORE_EXPORT sessionBus();
}
#endif
......@@ -20,7 +20,6 @@
#include "device.h"
#include <QDBusConnection>
#include <QVector>
#include <QSet>
#include <QSslCertificate>
......@@ -38,6 +37,7 @@
#include "networkpacket.h"
#include "kdeconnectconfig.h"
#include "daemon.h"
#include "dbushelper.h"
//In older Qt released, qAsConst isnt available
#include "qtcompat_p.h"
......@@ -67,6 +67,7 @@ public:
QMultiMap<QString, KdeConnectPlugin *> m_pluginsByIncomingCapability;
QSet<QString> m_supportedPlugins;
QSet<QString> m_allPlugins;
QSet<PairingHandler *> m_pairRequests;
};
......@@ -86,10 +87,11 @@ Device::Device(QObject* parent, const QString& id)
d->m_deviceType = str2type(info.deviceType);
//Register in bus
QDBusConnection::sessionBus().registerObject(dbusPath(), this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportAdaptors);
DbusHelper::sessionBus().registerObject(dbusPath(), this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportAdaptors);
//Assume every plugin is supported until addLink is called and we can get the actual list
d->m_supportedPlugins = PluginLoader::instance()->getPluginList().toSet();
d->m_allPlugins = PluginLoader::instance()->getPluginList().toSet();
d->m_supportedPlugins = d->m_allPlugins;
connect(this, &Device::pairingError, this, &warn);
}
......@@ -99,10 +101,12 @@ Device::Device(QObject* parent, const NetworkPacket& identityPacket, DeviceLink*
, d(new Device::DevicePrivate(identityPacket.get<QString>(QStringLiteral("deviceId"))))
{
d->m_deviceName = identityPacket.get<QString>(QStringLiteral("deviceName"));
d->m_allPlugins = PluginLoader::instance()->getPluginList().toSet();
addLink(identityPacket, dl);
//Register in bus
QDBusConnection::sessionBus().registerObject(dbusPath(), this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportAdaptors);
DbusHelper::sessionBus().registerObject(dbusPath(), this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportAdaptors);
connect(this, &Device::pairingError, this, &warn);
}
......@@ -192,7 +196,7 @@ void Device::reloadPlugins()
d->m_plugins = newPluginMap;
d->m_pluginsByIncomingCapability = newPluginsByIncomingCapability;
QDBusConnection bus = QDBusConnection::sessionBus();
QDBusConnection bus = DbusHelper::sessionBus();
for (KdeConnectPlugin* plugin : qAsConst(d->m_plugins)) {
//TODO: see how it works in Android (only done once, when created)
plugin->connected();
......@@ -509,6 +513,10 @@ KdeConnectPlugin* Device::plugin(const QString& pluginName) const
void Device::setPluginEnabled(const QString& pluginName, bool enabled)
{
if (!d->m_allPlugins.contains(pluginName)) {
return;
}
KConfigGroup pluginStates = KSharedConfig::openConfig(pluginsConfigFile())->group("Plugins");
const QString enabledKey = pluginName + QStringLiteral("Enabled");
......@@ -532,7 +540,7 @@ QString Device::encryptionInfo() const
QString localSha1 = QString::fromLatin1(KdeConnectConfig::instance()->certificate().digest(digestAlgorithm).toHex());
for (int i = 2; i<localSha1.size(); i += 3) {
localSha1.insert(i, ':'); // Improve readability
localSha1.insert(i, QStringLiteral(":")); // Improve readability
}
result += i18n("SHA1 fingerprint of your device certificate is: %1\n", localSha1);
......@@ -540,7 +548,7 @@ QString Device::encryptionInfo() const
QSslCertificate remoteCertificate = QSslCertificate(QByteArray(remotePem.c_str(), (int)remotePem.size()));
QString remoteSha1 = QString::fromLatin1(remoteCertificate.digest(digestAlgorithm).toHex());
for (int i = 2; i < remoteSha1.size(); i += 3) {
remoteSha1.insert(i, ':'); // Improve readability
remoteSha1.insert(i, QStringLiteral(":")); // Improve readability
}
result += i18n("SHA1 fingerprint of remote device certificate is: %1\n", remoteSha1);
......
......@@ -74,7 +74,7 @@ public:
QString id() const;
QString name() const;
QString dbusPath() const { return "/modules/kdeconnect/devices/"+id(); }
QString dbusPath() const { return QStringLiteral("/modules/kdeconnect/devices/") + id(); }
QString type() const;
QString iconName() const;
QString statusIconName() const;
......@@ -87,7 +87,7 @@ public:
Q_SCRIPTABLE bool isTrusted() const;
Q_SCRIPTABLE QStringList availableLinks() const;
bool isReachable() const;
virtual bool isReachable() const;
Q_SCRIPTABLE QStringList loadedPlugins() const;
Q_SCRIPTABLE bool hasPlugin(const QString& name) const;
......
......@@ -29,15 +29,16 @@
#include <KLocalizedString>
FileTransferJob::FileTransferJob(const QSharedPointer<QIODevice>& origin, qint64 size, const QUrl& destination)
FileTransferJob::FileTransferJob(const NetworkPacket* np, const QUrl& destination)
: KJob()
, m_origin(origin)
, m_origin(np->payload())
, m_reply(nullptr)
, m_from(QStringLiteral("KDE Connect"))
, m_destination(destination)
, m_speedBytes(0)
, m_written(0)
, m_size(size)
, m_size(np->payloadSize())
, m_np(np)
{
Q_ASSERT(m_origin);
//Disabled this assert: QBluetoothSocket doesn't report "->isReadable() == true" until it's connected
......@@ -48,7 +49,7 @@ FileTransferJob::FileTransferJob(const QSharedPointer<QIODevice>& origin, qint64
}
setCapabilities(Killable);
qCDebug(KDECONNECT_CORE) << "FileTransferJob Downloading payload to" << destination << "size:" << size;
qCDebug(KDECONNECT_CORE) << "FileTransferJob Downloading payload to" << destination << "size:" << m_size;
}
void FileTransferJob::start()
......@@ -59,10 +60,6 @@ void FileTransferJob::start()