/* SPDX-FileCopyrightText: 2023 Alexander Lohnau SPDX-License-Identifier: LGPL-2.0-or-later */ #include "KRunnerPlugininstallerRcJob.h" #include "ScriptConfirmationDialog.h" #include #include #include #include #include static QString installDBusServicePath(const QString &dbusService) { const QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); QDir dbusDir(dataLocation + "/dbus-1/services/"); dbusDir.mkpath((".")); return dbusDir.filePath(dbusService + ".service"); } static QString installMetaDataPath(const QString &filePath) { const QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); QDir krunnerPluginsDir(dataLocation + "/krunner/dbusplugins/"); krunnerPluginsDir.mkpath((".")); // Get the filename in case the .krunner-plugininstallerrc has specified the file to be in a subdir return krunnerPluginsDir.filePath(QFileInfo(filePath).fileName()); } static InstallerInfo getInstallerInfo(const QFileInfo &info) { const QDir rootDir = info.absoluteDir(); QString installerConfigFile = info.absoluteFilePath(); Q_ASSERT(installerConfigFile.endsWith("krunner-plugininstallerrc")); KConfig cfg(installerConfigFile); KConfigGroup grp = cfg.group(QStringLiteral("")); const QString exec = grp.readEntry("Exec").replace(QStringLiteral("%{PROJECTDIR}"), info.absolutePath()); const QString metaDataFile = grp.readEntry("MetaDataFile"); KDesktopFile desktopFile(rootDir.absoluteFilePath(metaDataFile)); QString dbusService = desktopFile.desktopGroup().readEntry("X-Plasma-DBusRunner-Service"); return {exec, dbusService, rootDir.absoluteFilePath(metaDataFile)}; } void KRunnerPluginInstallerRcJob::executeOperation(const QFileInfo &fileInfo, const QString & /*mimeType*/, bool install) { const InstallerInfo info = getInstallerInfo(fileInfo); if (info.exec.isEmpty() || info.desktopFilePath.isEmpty() || info.desktopFilePath.isEmpty()) { Q_EMIT error("The provided installer file is invalid. Please contact the author."); return; } if (install) { if (m_skipConfirmDialog || ScriptConfirmationDialog(QString(), install, fileInfo.absolutePath(), info).exec() == QDialog::Accepted) { doInstall(info); } else { Q_EMIT error(QString()); } } else { doUninstall(info); } } void KRunnerPluginInstallerRcJob::doInstall(const InstallerInfo &info) { QFile serviceFile(installDBusServicePath(info.dbusService)); if (serviceFile.open(QIODevice::WriteOnly)) { serviceFile.write( QLatin1String("# autogenerated by krunner-plugininstaller\n[D-BUS Service]\nName=%1\nExec=%2\n").arg(info.dbusService, info.exec).toLocal8Bit()); serviceFile.close(); qInfo() << "Wrote autostart file" << serviceFile.fileName(); } else { Q_EMIT error(serviceFile.errorString()); return; } const QString targetFilePath = installMetaDataPath(info.desktopFilePath); // In case we update an entry, simply remove a previous file if (QFileInfo::exists(targetFilePath)) { qInfo() << "Trying to remove old desktop file" << targetFilePath; QFile::remove(targetFilePath); } if (!QFile::copy(info.desktopFilePath, targetFilePath)) { qWarning() << "Failed to copy " << info.desktopFilePath << targetFilePath; Q_EMIT error(i18n("Failed to copy file %1 to %2", info.desktopFilePath, targetFilePath)); } else { qInfo() << "Copied desktop file to" << targetFilePath; Q_EMIT finished(); } } void KRunnerPluginInstallerRcJob::doUninstall(const InstallerInfo &info) { QFile dbusFile(installDBusServicePath(info.dbusService)); QFile metaDataFile(installMetaDataPath(info.desktopFilePath)); if (metaDataFile.remove()) { if (dbusFile.remove()) { Q_EMIT finished(); } else { Q_EMIT error(xi18nc("@info", "Failed to remove file %1:%2", dbusFile.fileName(), dbusFile.errorString())); } } else { Q_EMIT error(xi18nc("@info", "Failed to remove file %1:%2", metaDataFile.fileName(), metaDataFile.errorString())); } }