1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2020 David Faure <faure@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6*/
7
8#include "untrustedprogramhandlerinterface.h"
9
10#include "kiocoredebug.h"
11#include <QFile>
12#include <QSaveFile>
13
14using namespace KIO;
15
16UntrustedProgramHandlerInterface::UntrustedProgramHandlerInterface(QObject *parent)
17 : QObject(parent)
18 , d(nullptr)
19{
20}
21
22UntrustedProgramHandlerInterface::~UntrustedProgramHandlerInterface()
23{
24}
25
26void UntrustedProgramHandlerInterface::showUntrustedProgramWarning(KJob *job, const QString &programName)
27{
28 Q_UNUSED(job)
29 Q_UNUSED(programName)
30 Q_EMIT result(confirmed: false);
31}
32
33bool UntrustedProgramHandlerInterface::makeServiceFileExecutable(const QString &fileName, QString &errorString)
34{
35 // Open the file and read the first two characters, check if it's
36 // #!. If not, create a new file, prepend appropriate lines, and copy
37 // over.
38 QFile desktopFile(fileName);
39 if (!desktopFile.open(flags: QFile::ReadOnly)) {
40 errorString = desktopFile.errorString();
41 qCWarning(KIO_CORE) << "Error opening service" << fileName << errorString;
42 return false;
43 }
44
45 QByteArray header = desktopFile.peek(maxlen: 2); // First two chars of file
46 if (header.size() == 0) {
47 errorString = desktopFile.errorString();
48 qCWarning(KIO_CORE) << "Error inspecting service" << fileName << errorString;
49 return false; // Some kind of error
50 }
51
52 if (header != "#!") {
53 // Add header
54 QSaveFile saveFile;
55 saveFile.setFileName(fileName);
56 if (!saveFile.open(flags: QIODevice::WriteOnly)) {
57 errorString = saveFile.errorString();
58 qCWarning(KIO_CORE) << "Unable to open replacement file for" << fileName << errorString;
59 return false;
60 }
61
62 QByteArray shebang("#!/usr/bin/env xdg-open\n");
63 if (saveFile.write(data: shebang) != shebang.size()) {
64 errorString = saveFile.errorString();
65 qCWarning(KIO_CORE) << "Error occurred adding header for" << fileName << errorString;
66 saveFile.cancelWriting();
67 return false;
68 }
69
70 // Now copy the one into the other and then close and reopen desktopFile
71 QByteArray desktopData(desktopFile.readAll());
72 if (desktopData.isEmpty()) {
73 errorString = desktopFile.errorString();
74 qCWarning(KIO_CORE) << "Unable to read service" << fileName << errorString;
75 saveFile.cancelWriting();
76 return false;
77 }
78
79 if (saveFile.write(data: desktopData) != desktopData.size()) {
80 errorString = saveFile.errorString();
81 qCWarning(KIO_CORE) << "Error copying service" << fileName << errorString;
82 saveFile.cancelWriting();
83 return false;
84 }
85
86 desktopFile.close();
87 if (!saveFile.commit()) { // Figures....
88 errorString = saveFile.errorString();
89 qCWarning(KIO_CORE) << "Error committing changes to service" << fileName << errorString;
90 return false;
91 }
92
93 if (!desktopFile.open(flags: QFile::ReadOnly)) {
94 errorString = desktopFile.errorString();
95 qCWarning(KIO_CORE) << "Error re-opening service" << fileName << errorString;
96 return false;
97 }
98 } // Add header
99
100 return setExecuteBit(fileName, errorString);
101}
102
103bool UntrustedProgramHandlerInterface::setExecuteBit(const QString &fileName, QString &errorString)
104{
105 QFile file(fileName);
106
107 // corresponds to owner on unix, which will have to do since if the user
108 // isn't the owner we can't change perms anyways.
109 if (!file.setPermissions(QFile::ExeUser | file.permissions())) {
110 errorString = file.errorString();
111 qCWarning(KIO_CORE) << "Unable to change permissions for" << fileName << errorString;
112 return false;
113 }
114
115 return true;
116}
117
118#include "moc_untrustedprogramhandlerinterface.cpp"
119

source code of kio/src/core/untrustedprogramhandlerinterface.cpp