KIO

kprotocolinfo.cpp
1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 1999 Torben Weis <weis@kde.org>
4 SPDX-FileCopyrightText: 2003 Waldo Bastian <bastian@kde.org>
5 SPDX-FileCopyrightText: 2012 David Faure <faure@kde.org>
6 SPDX-FileCopyrightText: 2022 Harald Sitter <sitter@kde.org>
7
8 SPDX-License-Identifier: LGPL-2.0-only
9*/
10
11#include "kprotocolinfo.h"
12#include "kprotocolinfo_p.h"
13#include "kprotocolinfofactory_p.h"
14
15#include "kiocoredebug.h"
16
17#include <KApplicationTrader>
18#include <KConfig>
19#include <KConfigGroup>
20#include <KJsonUtils>
21#include <KPluginMetaData>
22#include <KSharedConfig>
23#include <QUrl>
24
25KProtocolInfoPrivate::KProtocolInfoPrivate(const QString &name, const QString &exec, const QJsonObject &json)
26 : m_name(name)
27 , m_exec(exec)
28{
29 // source has fallback true if not set
30 m_isSourceProtocol = json.value(QStringLiteral("source")).toBool(true);
31 // true if not set for backwards compatibility
32 m_supportsPermissions = json.value(QStringLiteral("permissions")).toBool(true);
33
34 // other bools are fine with default false by toBool
35 m_isHelperProtocol = json.value(QStringLiteral("helper")).toBool();
36 m_supportsReading = json.value(QStringLiteral("reading")).toBool();
37 m_supportsWriting = json.value(QStringLiteral("writing")).toBool();
38 m_supportsMakeDir = json.value(QStringLiteral("makedir")).toBool();
39 m_supportsDeleting = json.value(QStringLiteral("deleting")).toBool();
40 m_supportsLinking = json.value(QStringLiteral("linking")).toBool();
41 m_supportsMoving = json.value(QStringLiteral("moving")).toBool();
42 m_supportsOpening = json.value(QStringLiteral("opening")).toBool();
43 m_supportsTruncating = json.value(QStringLiteral("truncating")).toBool();
44 m_canCopyFromFile = json.value(QStringLiteral("copyFromFile")).toBool();
45 m_canCopyToFile = json.value(QStringLiteral("copyToFile")).toBool();
46 m_canRenameFromFile = json.value(QStringLiteral("renameFromFile")).toBool();
47 m_canRenameToFile = json.value(QStringLiteral("renameToFile")).toBool();
48 m_canDeleteRecursive = json.value(QStringLiteral("deleteRecursive")).toBool();
49
50 // default is "FromURL"
51 const QString fnu = json.value(QStringLiteral("fileNameUsedForCopying")).toString();
52 m_fileNameUsedForCopying = KProtocolInfo::FromUrl;
53 if (fnu == QLatin1String("Name")) {
54 m_fileNameUsedForCopying = KProtocolInfo::Name;
55 } else if (fnu == QLatin1String("DisplayName")) {
56 m_fileNameUsedForCopying = KProtocolInfo::DisplayName;
57 }
58
59 m_listing = json.value(QStringLiteral("listing")).toVariant().toStringList();
60 // Many .protocol files say "Listing=false" when they really mean "Listing=" (i.e. unsupported)
61 if (m_listing.count() == 1 && m_listing.first() == QLatin1String("false")) {
62 m_listing.clear();
63 }
64 m_supportsListing = (m_listing.count() > 0);
65
66 m_defaultMimetype = json.value(QStringLiteral("defaultMimetype")).toString();
67
68 // determineMimetypeFromExtension has fallback true if not set
69 m_determineMimetypeFromExtension = json.value(QStringLiteral("determineMimetypeFromExtension")).toBool(true);
70
71 m_archiveMimeTypes = json.value(QStringLiteral("archiveMimetype")).toVariant().toStringList();
72
73 m_icon = json.value(QStringLiteral("Icon")).toString();
74
75 // config has fallback to name if not set
76 m_config = json.value(QStringLiteral("config")).toString(m_name);
77
78 // max workers has fallback to 1 if not set
79 m_maxWorkers = json.value(QStringLiteral("maxInstances")).toInt(1);
80
81 m_maxWorkersPerHost = json.value(QStringLiteral("maxInstancesPerHost")).toInt();
82
83 QString tmp = json.value(QStringLiteral("input")).toString();
84 if (tmp == QLatin1String("filesystem")) {
85 m_inputType = KProtocolInfo::T_FILESYSTEM;
86 } else if (tmp == QLatin1String("stream")) {
87 m_inputType = KProtocolInfo::T_STREAM;
88 } else {
89 m_inputType = KProtocolInfo::T_NONE;
90 }
91
92 tmp = json.value(QStringLiteral("output")).toString();
93 if (tmp == QLatin1String("filesystem")) {
94 m_outputType = KProtocolInfo::T_FILESYSTEM;
95 } else if (tmp == QLatin1String("stream")) {
96 m_outputType = KProtocolInfo::T_STREAM;
97 } else {
98 m_outputType = KProtocolInfo::T_NONE;
99 }
100
101 m_docPath = json.value(QStringLiteral("X-DocPath")).toString();
102 if (m_docPath.isEmpty()) {
103 m_docPath = json.value(QStringLiteral("DocPath")).toString();
104 }
105
106 m_protClass = json.value(QStringLiteral("Class")).toString().toLower();
107 if (!m_protClass.startsWith(QLatin1Char(':'))) {
108 m_protClass.prepend(QLatin1Char(':'));
109 }
110
111 // ExtraNames is a translated value, use the KCoreAddons helper to read it
112 const QStringList extraNames = KJsonUtils::readTranslatedValue(json, QStringLiteral("ExtraNames")).toVariant().toStringList();
113 const QStringList extraTypes = json.value(QStringLiteral("ExtraTypes")).toVariant().toStringList();
114 if (extraNames.size() == extraTypes.size()) {
115 auto func = [](const QString &name, const QString &type) {
116 const int metaType = QMetaType::fromName(type.toLatin1().constData()).id();
117 // currently QMetaType::Type and ExtraField::Type use the same subset of values, so we can just cast.
118 return KProtocolInfo::ExtraField(name, static_cast<KProtocolInfo::ExtraField::Type>(metaType));
119 };
120
121 std::transform(extraNames.cbegin(), extraNames.cend(), extraTypes.cbegin(), std::back_inserter(m_extraFields), func);
122 } else {
123 qCWarning(KIO_CORE) << "Malformed JSON protocol file for protocol:" << name
124 << ", number of the ExtraNames fields should match the number of ExtraTypes fields";
125 }
126
127 // fallback based on class
128 m_showPreviews = json.value(QStringLiteral("ShowPreviews")).toBool(m_protClass == QLatin1String(":local"));
129
130 m_capabilities = json.value(QStringLiteral("Capabilities")).toVariant().toStringList();
131
132 m_proxyProtocol = json.value(QStringLiteral("ProxiedBy")).toString();
133}
134
135//
136// Static functions:
137//
138
140{
141 return KProtocolInfoFactory::self()->protocols();
142}
143
145{
146 // We call the findProtocol directly (not via KProtocolManager) to bypass any proxy settings.
147 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
148 if (!prot) {
149 return false;
150 }
151
152 return !prot->m_isSourceProtocol;
153}
154
156{
157 // We call the findProtocol directly (not via KProtocolManager) to bypass any proxy settings.
158 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
159 if (!prot) {
160 if (auto service = KApplicationTrader::preferredService(QLatin1String("x-scheme-handler/") + _protocol)) {
161 return service->icon();
162 } else {
163 return QString();
164 }
165 }
166
167 return prot->m_icon;
168}
169
171{
172 // We call the findProtocol directly (not via KProtocolManager) to bypass any proxy settings.
173 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
174 if (!prot) {
175 return QString();
176 }
177
178 return QStringLiteral("kio_%1rc").arg(prot->m_config);
179}
180
182{
183 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
184 if (!prot) {
185 return 1;
186 }
187
188 return prot->m_maxWorkers;
189}
190
192{
193 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
194 if (!prot) {
195 return 0;
196 }
197
198 return prot->m_maxWorkersPerHost;
199}
200
202{
203 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
204 if (!prot) {
205 return true;
206 }
207
208 return prot->m_determineMimetypeFromExtension;
209}
210
212{
213 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(protocol);
214 if (!prot) {
215 return QString();
216 }
217 return prot->m_exec;
218}
219
221{
222 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(url.scheme());
223 if (!prot) {
224 return ExtraFieldList();
225 }
226
227 return prot->m_extraFields;
228}
229
231{
232 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
233 if (!prot) {
234 return QString();
235 }
236
237 return prot->m_defaultMimetype;
238}
239
241{
242 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
243 if (!prot) {
244 return QString();
245 }
246
247 return prot->m_docPath;
248}
249
251{
252 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
253 if (!prot) {
254 return QString();
255 }
256
257 return prot->m_protClass;
258}
259
261{
262 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
263 const bool defaultSetting = prot ? prot->m_showPreviews : false;
264
265 KConfigGroup group(KSharedConfig::openConfig(), QStringLiteral("PreviewSettings"));
266 return group.readEntry(_protocol, defaultSetting);
267}
268
270{
271 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
272 if (!prot) {
273 return QStringList();
274 }
275
276 return prot->m_capabilities;
277}
278
280{
281 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(protocol);
282 if (!prot) {
283 return QStringList();
284 }
285
286 return prot->m_archiveMimeTypes;
287}
288
289#if KIOCORE_BUILD_DEPRECATED_SINCE(6, 4)
291{
292 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
293 if (!prot) {
294 return QString();
295 }
296
297 return prot->m_proxyProtocol;
298}
299#endif
300
302{
303 return isFilterProtocol(url.scheme());
304}
305
307{
308 return isHelperProtocol(url.scheme());
309}
310
312{
313 // We call the findProtocol directly (not via KProtocolManager) to bypass any proxy settings.
314 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(protocol);
315 if (prot) {
316 return prot->m_isHelperProtocol;
317 }
318 return false;
319}
320
322{
323 return isKnownProtocol(url.scheme());
324}
325
326bool KProtocolInfo::isKnownProtocol(const QString &protocol, bool updateCacheIfNotfound)
327{
328 // We call the findProtocol (const QString&) to bypass any proxy settings.
329 KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(protocol, updateCacheIfNotfound);
330 return prot;
331}
QString readEntry(const char *key, const char *aDefault=nullptr) const
static QString config(const QString &protocol)
Returns the name of the config file associated with the specified protocol.
static QString protocolClass(const QString &protocol)
Returns the protocol class for the specified protocol.
static bool determineMimetypeFromExtension(const QString &protocol)
Returns whether MIME types can be determined based on extension for this protocol.
static bool showFilePreview(const QString &protocol)
Returns whether file previews should be shown for the specified protocol.
static QString proxiedBy(const QString &protocol)
Returns the name of the protocol through which the request will be routed if proxy support is enabled...
static QStringList archiveMimetypes(const QString &protocol)
Returns the list of archive MIME types handled by the KIO worker implementing this protocol.
static QStringList capabilities(const QString &protocol)
Returns the list of capabilities provided by the KIO worker implementing this protocol.
static int maxWorkersPerHost(const QString &protocol)
Returns the limit on the number of KIO workers for this protocol per host.
@ T_STREAM
stream of data (e.g. single file)
@ T_NONE
no information about the type available
@ T_FILESYSTEM
structured directory
static QStringList protocols()
Returns list of all known protocols.
static QString docPath(const QString &protocol)
Returns the documentation path for the specified protocol.
static bool isKnownProtocol(const QUrl &url)
Returns whether a protocol is installed that is able to handle url.
static QString icon(const QString &protocol)
Returns the name of the icon, associated with the specified protocol.
static QString exec(const QString &protocol)
Returns the library / executable to open for the protocol protocol Example : "kio_ftp",...
static int maxWorkers(const QString &protocol)
Returns the soft limit on the number of KIO workers for this protocol.
static ExtraFieldList extraFields(const QUrl &url)
Definition of extra fields in the UDS entries, returned by a listDir operation.
static bool isHelperProtocol(const QUrl &url)
Returns whether the protocol can act as a helper protocol.
static bool isFilterProtocol(const QUrl &url)
Returns whether the protocol can act as a filter protocol.
static QString defaultMimetype(const QString &protocol)
Returns the default MIME type for the specified protocol, if one exists.
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
char * toString(const EngineQuery &query)
KSERVICE_EXPORT KService::Ptr preferredService(const QString &mimeType)
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
QString name(StandardAction id)
QJsonValue value(QLatin1StringView key) const const
bool toBool(bool defaultValue) const const
QString toString() const const
QVariant toVariant() const const
const_iterator cbegin() const const
const_iterator cend() const const
void clear()
qsizetype size() const const
QMetaType fromName(QByteArrayView typeName)
int id() const const
QString scheme() const const
QStringList toStringList() const const
Definition of an extra field in the UDS entries, returned by a listDir operation.
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jun 21 2024 11:57:29 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.