kdeconnect-kde/core/dbushelper.cpp

165 lines
5.2 KiB
C++
Raw Permalink Normal View History

/**
* SPDX-FileCopyrightText: 2014 Albert Vaca <albertvaka@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include "dbushelper.h"
2019-06-18 02:21:31 +01:00
#include "core_debug.h"
#include <QCoreApplication>
2019-06-18 02:21:31 +01:00
#include <QDebug>
#include <QFile>
#include <QProcess>
#include <QRegularExpression>
#include <QStandardPaths>
#include <QUrl>
2019-06-18 02:21:31 +01:00
#include "kdeconnectconfig.h"
#ifdef Q_OS_MAC
#include <KLocalizedString>
#include <QRegularExpression>
#include <QRegularExpressionMatch>
#include <QStandardPaths>
#include <QThread>
2019-06-18 02:21:31 +01:00
#endif
namespace DBusHelper
{
2019-06-18 02:21:31 +01:00
void filterNonExportableCharacters(QString &s)
{
static QRegularExpression regexp(QStringLiteral("[^A-Za-z0-9_]"), QRegularExpression::CaseInsensitiveOption);
s.replace(regexp, QLatin1String("_"));
}
#ifdef Q_OS_MAC
2019-06-18 02:21:31 +01:00
const QString PrivateDbusAddr = QStringLiteral("unix:tmpdir=/tmp");
const QString PrivateDBusAddressPath = QStringLiteral("/tmp/private_dbus_address");
const QString DBUS_LAUNCHD_SESSION_BUS_SOCKET = QStringLiteral("DBUS_LAUNCHD_SESSION_BUS_SOCKET");
QProcess *m_dbusProcess = nullptr;
void setLaunchctlEnv(const QString &env)
2019-06-18 02:21:31 +01:00
{
QProcess setLaunchdDBusEnv;
setLaunchdDBusEnv.setProgram(QStringLiteral("launchctl"));
setLaunchdDBusEnv.setArguments({QStringLiteral("setenv"), DBUS_LAUNCHD_SESSION_BUS_SOCKET, env});
setLaunchdDBusEnv.start();
setLaunchdDBusEnv.waitForFinished();
2019-06-18 02:21:31 +01:00
}
void unsetLaunchctlEnv()
{
QProcess unsetLaunchdDBusEnv;
unsetLaunchdDBusEnv.setProgram(QStringLiteral("launchctl"));
unsetLaunchdDBusEnv.setArguments({QStringLiteral("unsetenv"), DBUS_LAUNCHD_SESSION_BUS_SOCKET});
unsetLaunchdDBusEnv.start();
unsetLaunchdDBusEnv.waitForFinished();
}
void stopDBusDaemon()
2019-06-18 02:21:31 +01:00
{
if (m_dbusProcess != nullptr) {
m_dbusProcess->terminate();
m_dbusProcess->waitForFinished();
delete m_dbusProcess;
m_dbusProcess = nullptr;
unsetLaunchctlEnv();
}
}
2019-06-18 02:21:31 +01:00
int startDBusDaemon()
{
if (m_dbusProcess) {
return 0;
}
qAddPostRoutine(stopDBusDaemon);
// Unset launchctl env and private dbus addr file, avoid block
unsetLaunchctlEnv();
QFile privateDBusAddressFile(PrivateDBusAddressPath);
if (privateDBusAddressFile.exists()) {
privateDBusAddressFile.resize(0);
}
QString kdeconnectDBusConfiguration;
QString dbusDaemonExecutable = QStandardPaths::findExecutable(QStringLiteral("dbus-daemon"), {QCoreApplication::applicationDirPath()});
if (!dbusDaemonExecutable.isNull()) {
kdeconnectDBusConfiguration = QStandardPaths::locate(QStandardPaths::AppDataLocation, QStringLiteral("dbus-1/session.conf"));
} else {
// macOS Debug env
dbusDaemonExecutable = QLatin1String(qgetenv("craftRoot")) + QLatin1String("/../bin/dbus-daemon");
kdeconnectDBusConfiguration = QLatin1String(qgetenv("craftRoot")) + QLatin1String("/../share/dbus-1/session.conf");
}
m_dbusProcess = new QProcess();
m_dbusProcess->setProgram(dbusDaemonExecutable);
m_dbusProcess->setArguments({QStringLiteral("--print-address"),
QStringLiteral("--nofork"),
QStringLiteral("--config-file"),
kdeconnectDBusConfiguration,
QStringLiteral("--address"),
PrivateDbusAddr});
m_dbusProcess->setWorkingDirectory(QCoreApplication::applicationDirPath());
m_dbusProcess->setStandardOutputFile(PrivateDBusAddressPath);
2019-06-18 02:21:31 +01:00
m_dbusProcess->start();
m_dbusProcess->waitForStarted();
QFile dbusAddressFile(PrivateDBusAddressPath);
if (!dbusAddressFile.open(QFile::ReadOnly | QFile::Text)) {
qCCritical(KDECONNECT_CORE) << "Private DBus enabled but error read private dbus address conf";
return -1;
}
2019-06-18 02:21:31 +01:00
QTextStream in(&dbusAddressFile);
2019-06-18 02:21:31 +01:00
qCDebug(KDECONNECT_CORE) << "Waiting for private dbus";
2019-06-18 02:21:31 +01:00
int retry = 0;
QString addr = in.readLine();
while (addr.length() == 0 && retry < 150) {
qCDebug(KDECONNECT_CORE) << "Retry reading private DBus address";
QThread::msleep(100);
retry++;
addr = in.readLine(); // Read until first not empty line
}
if (addr.length() == 0) {
qCCritical(KDECONNECT_CORE) << "Private DBus enabled but read private dbus address failed";
return -2;
2019-06-18 02:21:31 +01:00
}
qCDebug(KDECONNECT_CORE) << "Private dbus address: " << addr;
2019-06-18 02:21:31 +01:00
QRegularExpressionMatch path;
if (!addr.contains(QRegularExpression(QStringLiteral("path=(?<path>/tmp/dbus-[A-Za-z0-9]+)")), &path)) {
qCCritical(KDECONNECT_CORE) << "Fail to parse dbus address";
return -3;
}
2019-06-18 02:21:31 +01:00
QString dbusAddress = path.captured(QStringLiteral("path"));
qCDebug(KDECONNECT_CORE) << "DBus address: " << dbusAddress;
if (dbusAddress.isEmpty()) {
qCCritical(KDECONNECT_CORE) << "Fail to extract dbus address";
return -4;
}
setLaunchctlEnv(dbusAddress);
if (!QDBusConnection::sessionBus().isConnected()) {
qCCritical(KDECONNECT_CORE) << "Invalid env:" << dbusAddress;
return -5;
}
qCDebug(KDECONNECT_CORE) << "Private D-Bus daemon launched and connected.";
return 0;
}
#endif // Q_OS_MAC
} // namespace DBusHelper