File indexing completed on 2024-04-14 04:51:40

0001 /**
0002  * SPDX-FileCopyrightText: 2014 Albert Vaca <albertvaka@gmail.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #include "dbushelper.h"
0008 #include "core_debug.h"
0009 
0010 #include <QCoreApplication>
0011 #include <QDebug>
0012 #include <QFile>
0013 #include <QProcess>
0014 #include <QRegularExpression>
0015 #include <QStandardPaths>
0016 #include <QUrl>
0017 
0018 #include "kdeconnectconfig.h"
0019 
0020 #ifdef Q_OS_MAC
0021 #include <QRegularExpression>
0022 #include <QRegularExpressionMatch>
0023 #endif
0024 
0025 namespace DBusHelper
0026 {
0027 #ifdef Q_OS_MAC
0028 class DBusInstancePrivate
0029 {
0030 public:
0031     DBusInstancePrivate();
0032     ~DBusInstancePrivate();
0033 
0034     void launchDBusDaemon();
0035     void closeDBusDaemon();
0036 
0037 private:
0038     QProcess *m_dbusProcess;
0039 };
0040 
0041 static DBusInstancePrivate dbusInstance;
0042 #endif
0043 
0044 void filterNonExportableCharacters(QString &s)
0045 {
0046     static QRegularExpression regexp(QStringLiteral("[^A-Za-z0-9_]"), QRegularExpression::CaseInsensitiveOption);
0047     s.replace(regexp, QLatin1String("_"));
0048 }
0049 
0050 #ifdef Q_OS_MAC
0051 void launchDBusDaemon()
0052 {
0053     dbusInstance.launchDBusDaemon();
0054     qAddPostRoutine(closeDBusDaemon);
0055 }
0056 
0057 void closeDBusDaemon()
0058 {
0059     dbusInstance.closeDBusDaemon();
0060 }
0061 
0062 void macosUnsetLaunchctlEnv()
0063 {
0064     // Unset Launchd env
0065     QProcess unsetLaunchdDBusEnv;
0066     unsetLaunchdDBusEnv.setProgram(QStringLiteral("launchctl"));
0067     unsetLaunchdDBusEnv.setArguments({QStringLiteral("unsetenv"), QStringLiteral(KDECONNECT_SESSION_DBUS_LAUNCHD_ENV)});
0068     unsetLaunchdDBusEnv.start();
0069     unsetLaunchdDBusEnv.waitForFinished();
0070 }
0071 
0072 void DBusInstancePrivate::launchDBusDaemon()
0073 {
0074     // Kill old dbus daemon
0075     if (m_dbusProcess != nullptr)
0076         closeDBusDaemon();
0077 
0078     // Start dbus daemon
0079     m_dbusProcess = new QProcess();
0080 
0081     QString kdeconnectDBusConfiguration;
0082     QString dbusDaemonExecutable = QStandardPaths::findExecutable(QStringLiteral("dbus-daemon"), {QCoreApplication::applicationDirPath()});
0083     if (!dbusDaemonExecutable.isNull()) {
0084         kdeconnectDBusConfiguration = QStandardPaths::locate(QStandardPaths::AppDataLocation, QStringLiteral("dbus-1/session.conf"));
0085     } else {
0086         // macOS Debug env
0087         dbusDaemonExecutable = QLatin1String(qgetenv("craftRoot")) + QLatin1String("/../bin/dbus-daemon");
0088         kdeconnectDBusConfiguration = QLatin1String(qgetenv("craftRoot")) + QLatin1String("/../share/dbus-1/session.conf");
0089     }
0090     m_dbusProcess->setProgram(dbusDaemonExecutable);
0091     m_dbusProcess->setArguments({QStringLiteral("--print-address"),
0092                                  QStringLiteral("--nofork"),
0093                                  QStringLiteral("--config-file=") + kdeconnectDBusConfiguration,
0094                                  QStringLiteral("--address=") + QStringLiteral(KDECONNECT_PRIVATE_DBUS_ADDR)});
0095     m_dbusProcess->setWorkingDirectory(QCoreApplication::applicationDirPath());
0096     m_dbusProcess->setStandardOutputFile(KdeConnectConfig::instance().privateDBusAddressPath());
0097     m_dbusProcess->setStandardErrorFile(QProcess::nullDevice());
0098     m_dbusProcess->start();
0099     m_dbusProcess->waitForStarted(); // Avoid potential racing condition
0100 
0101 #ifdef Q_OS_MAC
0102     // Set launchctl env
0103     QString privateDBusAddress = KdeConnectConfig::instance().privateDBusAddress();
0104     QRegularExpressionMatch path;
0105     if (privateDBusAddress.contains(QRegularExpression(QStringLiteral("path=(?<path>/tmp/dbus-[A-Za-z0-9]+)")), &path)) {
0106         qCDebug(KDECONNECT_CORE) << "DBus address: " << path.captured(QStringLiteral("path"));
0107         QProcess setLaunchdDBusEnv;
0108         setLaunchdDBusEnv.setProgram(QStringLiteral("launchctl"));
0109         setLaunchdDBusEnv.setArguments({QStringLiteral("setenv"), QStringLiteral(KDECONNECT_SESSION_DBUS_LAUNCHD_ENV), path.captured(QStringLiteral("path"))});
0110         setLaunchdDBusEnv.start();
0111         setLaunchdDBusEnv.waitForFinished();
0112     } else {
0113         qCDebug(KDECONNECT_CORE) << "Cannot get dbus address";
0114     }
0115 #endif
0116 }
0117 
0118 void DBusInstancePrivate::closeDBusDaemon()
0119 {
0120     if (m_dbusProcess != nullptr) {
0121         m_dbusProcess->terminate();
0122         m_dbusProcess->waitForFinished();
0123         delete m_dbusProcess;
0124         m_dbusProcess = nullptr;
0125 
0126         QFile privateDBusAddressFile(KdeConnectConfig::instance().privateDBusAddressPath());
0127 
0128         if (privateDBusAddressFile.exists())
0129             privateDBusAddressFile.resize(0);
0130 
0131         macosUnsetLaunchctlEnv();
0132     }
0133 }
0134 
0135 DBusInstancePrivate::DBusInstancePrivate()
0136     : m_dbusProcess(nullptr)
0137 {
0138 }
0139 
0140 DBusInstancePrivate::~DBusInstancePrivate()
0141 {
0142     closeDBusDaemon();
0143 }
0144 #endif
0145 
0146 }