File indexing completed on 2024-04-28 05:36:11

0001 /*
0002  *  SPDX-FileCopyrightText: 2016 Marco Martin <mart@kde.org>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  *
0006  */
0007 
0008 #include "config-kcm.h"
0009 
0010 #include <QCoreApplication>
0011 #include <QDebug>
0012 #include <QFile>
0013 #include <QFileInfo>
0014 #include <QMimeDatabase>
0015 #include <qcommandlineoption.h>
0016 #include <qcommandlineparser.h>
0017 
0018 #include "ktar.h"
0019 #include "kzip.h"
0020 #include <KArchive>
0021 #include <KAuth/Action>
0022 #include <KAuth/ExecuteJob>
0023 #include <KConfigGroup>
0024 #include <KSharedConfig>
0025 #include <klocalizedstring.h>
0026 
0027 int main(int argc, char **argv)
0028 {
0029     QCommandLineParser parser;
0030     QCoreApplication app(argc, argv);
0031 
0032     const QString description = i18n("Plymouth theme installer");
0033 
0034     app.setApplicationVersion(QStringLiteral(PROJECT_VERSION));
0035     parser.addVersionOption();
0036     parser.addHelpOption();
0037     parser.setApplicationDescription(description);
0038     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("i") << QStringLiteral("install"), i18n("Install a theme.")));
0039     parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("u") << QStringLiteral("uninstall"), i18n("Uninstall a theme.")));
0040 
0041     parser.addPositionalArgument(QStringLiteral("themefile"), i18n("The theme to install, must be an existing archive file."));
0042 
0043     parser.process(app);
0044 
0045     if (!parser.isSet(QStringLiteral("install")) && !parser.isSet(QStringLiteral("uninstall"))) {
0046         qWarning() << "You need to specify either install or uninstall operation..";
0047         return 0;
0048     }
0049     const QStringList args = parser.positionalArguments();
0050 
0051     if (args.isEmpty()) {
0052         qWarning() << "No theme file specified.";
0053         return 0;
0054     }
0055 
0056     QString themefile = args.first();
0057     themefile.replace(QStringLiteral("//"), QStringLiteral("/"));
0058     if (parser.isSet(QStringLiteral("install")) && !QFile::exists(themefile)) {
0059         qWarning() << "Specified theme file does not exists";
0060         return 0;
0061     }
0062 
0063     QVariantMap helperargs;
0064     helperargs[QStringLiteral("themearchive")] = themefile;
0065 
0066     // support uninstalling from an archive
0067     QMimeDatabase db;
0068     QMimeType mimeType = db.mimeTypeForFile(themefile);
0069     bool isArchive = false;
0070     if (parser.isSet(QStringLiteral("uninstall"))) {
0071         QScopedPointer<KArchive> archive;
0072         if (mimeType.inherits(QStringLiteral("application/zip"))) {
0073             archive.reset(new KZip(themefile));
0074             // clang-format off
0075         } else if (mimeType.inherits(QStringLiteral("application/tar"))
0076             || mimeType.inherits(QStringLiteral("application/x-gzip"))
0077             || mimeType.inherits(QStringLiteral("application/x-bzip"))
0078             || mimeType.inherits(QStringLiteral("application/x-lzma"))
0079             || mimeType.inherits(QStringLiteral("application/x-xz"))
0080             || mimeType.inherits(QStringLiteral("application/x-bzip-compressed-tar"))
0081             || mimeType.inherits(QStringLiteral("application/x-compressed-tar"))) {
0082             archive.reset(new KTar(themefile));
0083             // clang-format on
0084         }
0085         if (archive) {
0086             isArchive = true;
0087             bool success = archive->open(QIODevice::ReadOnly);
0088             if (!success) {
0089                 qCritical() << "Cannot open archive file '" << themefile << "'";
0090                 exit(-1);
0091             }
0092             const KArchiveDirectory *dir = archive->directory();
0093             // if there is more than an item in the file,
0094             // plugin is a subdirectory with the same name as the file
0095             if (dir->entries().count() > 1) {
0096                 helperargs[QStringLiteral("theme")] = QFileInfo(archive->fileName()).baseName();
0097             } else {
0098                 helperargs[QStringLiteral("theme")] = dir->entries().constFirst();
0099             }
0100         } else {
0101             helperargs[QStringLiteral("theme")] = themefile;
0102         }
0103     }
0104 
0105     KAuth::Action action(parser.isSet(QStringLiteral("install")) ? QStringLiteral("org.kde.kcontrol.kcmplymouth.install")
0106                                                                  : QStringLiteral("org.kde.kcontrol.kcmplymouth.uninstall"));
0107     action.setHelperId(QStringLiteral("org.kde.kcontrol.kcmplymouth"));
0108     action.setArguments(helperargs);
0109 
0110     KAuth::ExecuteJob *job = action.execute();
0111     bool rc = job->exec();
0112     if (!rc) {
0113         qWarning() << i18n("Unable to authenticate/execute the action: %1, %2", job->error(), job->errorString());
0114         return -1;
0115     }
0116 
0117     KConfigGroup cg(KSharedConfig::openConfig(QStringLiteral("kplymouththemeinstallerrc")), QStringLiteral("DownloadedThemes"));
0118     if (parser.isSet(QStringLiteral("install"))) {
0119         cg.writeEntry(job->data().value(QStringLiteral("plugin")).toString(), themefile);
0120     } else {
0121         if (!isArchive) {
0122             // try to take the file name from the config file
0123             themefile = cg.readEntry(job->data().value(QStringLiteral("plugin")).toString(), QString());
0124         }
0125 
0126         if (themefile.isEmpty()) {
0127             // remove archive
0128             QFile(themefile).remove();
0129             // remove screenshot
0130             QFile::remove(QString(themefile + QStringLiteral(".png")));
0131         }
0132 
0133         cg.deleteEntry(job->data().value(QStringLiteral("plugin")).toString());
0134     }
0135 
0136     return app.exec();
0137 }