File indexing completed on 2025-01-26 05:06:36

0001 /*
0002     SPDX-FileCopyrightText: 2023 Alexander Lohnau <alexander.lohnau@gmx.de>
0003     SPDX-License-Identifier: LGPL-2.0-or-later
0004 */
0005 #include "KRunnerPlugininstallerRcJob.h"
0006 
0007 #include "ScriptConfirmationDialog.h"
0008 #include <KDesktopFile>
0009 #include <QApplication>
0010 #include <QDebug>
0011 #include <QDir>
0012 #include <QFileInfo>
0013 
0014 static QString installDBusServicePath(const QString &dbusService)
0015 {
0016     const QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
0017     QDir dbusDir(dataLocation + "/dbus-1/services/");
0018     dbusDir.mkpath(("."));
0019     return dbusDir.filePath(dbusService + ".service");
0020 }
0021 
0022 static QString installMetaDataPath(const QString &filePath)
0023 {
0024     const QString dataLocation = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
0025     QDir krunnerPluginsDir(dataLocation + "/krunner/dbusplugins/");
0026     krunnerPluginsDir.mkpath(("."));
0027     // Get the filename in case the .krunner-plugininstallerrc has specified the file to be in a subdir
0028     return krunnerPluginsDir.filePath(QFileInfo(filePath).fileName());
0029 }
0030 
0031 static InstallerInfo getInstallerInfo(const QFileInfo &info)
0032 {
0033     const QDir rootDir = info.absoluteDir();
0034     QString installerConfigFile = info.absoluteFilePath();
0035     Q_ASSERT(installerConfigFile.endsWith("krunner-plugininstallerrc"));
0036 
0037     KConfig cfg(installerConfigFile);
0038     KConfigGroup grp = cfg.group(QStringLiteral(""));
0039     const QString exec = grp.readEntry("Exec").replace(QStringLiteral("%{PROJECTDIR}"), info.absolutePath());
0040     const QString metaDataFile = grp.readEntry("MetaDataFile");
0041     KDesktopFile desktopFile(rootDir.absoluteFilePath(metaDataFile));
0042     QString dbusService = desktopFile.desktopGroup().readEntry("X-Plasma-DBusRunner-Service");
0043 
0044     return {exec, dbusService, rootDir.absoluteFilePath(metaDataFile)};
0045 }
0046 
0047 void KRunnerPluginInstallerRcJob::executeOperation(const QFileInfo &fileInfo, const QString & /*mimeType*/, bool install)
0048 {
0049     const InstallerInfo info = getInstallerInfo(fileInfo);
0050     if (info.exec.isEmpty() || info.desktopFilePath.isEmpty() || info.desktopFilePath.isEmpty()) {
0051         Q_EMIT error("The provided installer file is invalid. Please contact the author.");
0052         return;
0053     }
0054     if (install) {
0055         if (m_skipConfirmDialog || ScriptConfirmationDialog(QString(), install, fileInfo.absolutePath(), info).exec() == QDialog::Accepted) {
0056             doInstall(info);
0057         } else {
0058             Q_EMIT error(QString());
0059         }
0060     } else {
0061         doUninstall(info);
0062     }
0063 }
0064 
0065 void KRunnerPluginInstallerRcJob::doInstall(const InstallerInfo &info)
0066 {
0067     QFile serviceFile(installDBusServicePath(info.dbusService));
0068 
0069     if (serviceFile.open(QIODevice::WriteOnly)) {
0070         serviceFile.write(
0071             QLatin1String("# autogenerated by krunner-plugininstaller\n[D-BUS Service]\nName=%1\nExec=%2\n").arg(info.dbusService, info.exec).toLocal8Bit());
0072         serviceFile.close();
0073         qInfo() << "Wrote autostart file" << serviceFile.fileName();
0074     } else {
0075         Q_EMIT error(serviceFile.errorString());
0076         return;
0077     }
0078 
0079     const QString targetFilePath = installMetaDataPath(info.desktopFilePath);
0080     // In case we update an entry, simply remove a previous file
0081     if (QFileInfo::exists(targetFilePath)) {
0082         qInfo() << "Trying to remove old desktop file" << targetFilePath;
0083         QFile::remove(targetFilePath);
0084     }
0085 
0086     if (!QFile::copy(info.desktopFilePath, targetFilePath)) {
0087         qWarning() << "Failed to copy " << info.desktopFilePath << targetFilePath;
0088         Q_EMIT error(i18n("Failed to copy file %1 to %2", info.desktopFilePath, targetFilePath));
0089     } else {
0090         qInfo() << "Copied desktop file to" << targetFilePath;
0091         Q_EMIT finished();
0092     }
0093 }
0094 void KRunnerPluginInstallerRcJob::doUninstall(const InstallerInfo &info)
0095 {
0096     QFile dbusFile(installDBusServicePath(info.dbusService));
0097     QFile metaDataFile(installMetaDataPath(info.desktopFilePath));
0098 
0099     if (metaDataFile.remove()) {
0100         if (dbusFile.remove()) {
0101             Q_EMIT finished();
0102         } else {
0103             Q_EMIT error(xi18nc("@info", "Failed to remove file %1:<nl/>%2", dbusFile.fileName(), dbusFile.errorString()));
0104         }
0105     } else {
0106         Q_EMIT error(xi18nc("@info", "Failed to remove file %1:<nl/>%2", metaDataFile.fileName(), metaDataFile.errorString()));
0107     }
0108 }