KIO

kprotocolinfo.cpp
1 /*
2  This file is part of the KDE libraries
3  SPDX-FileCopyrightText: 1999 Torben Weis <[email protected]>
4  SPDX-FileCopyrightText: 2003 Waldo Bastian <[email protected]>
5  SPDX-FileCopyrightText: 2012 David Faure <[email protected]>
6  SPDX-FileCopyrightText: 2022 Harald Sitter <[email protected]>
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 
25 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 84)
26 //
27 // Internal functions:
28 //
29 KProtocolInfoPrivate::KProtocolInfoPrivate(const QString &path)
30 {
31  KConfig sconfig(path, KConfig::SimpleConfig);
32  KConfigGroup config(&sconfig, "Protocol");
33 
34  m_name = config.readEntry("protocol");
35  m_exec = config.readPathEntry("exec", QString());
36  m_isSourceProtocol = config.readEntry("source", true);
37  m_supportsPermissions = config.readEntry("permissions", true);
38  m_isHelperProtocol = config.readEntry("helper", false);
39  m_supportsReading = config.readEntry("reading", false);
40  m_supportsWriting = config.readEntry("writing", false);
41  m_supportsMakeDir = config.readEntry("makedir", false);
42  m_supportsDeleting = config.readEntry("deleting", false);
43  m_supportsLinking = config.readEntry("linking", false);
44  m_supportsMoving = config.readEntry("moving", false);
45  m_supportsOpening = config.readEntry("opening", false);
46  m_supportsTruncating = config.readEntry("truncating", false);
47  m_canCopyFromFile = config.readEntry("copyFromFile", false);
48  m_canCopyToFile = config.readEntry("copyToFile", false);
49  m_canRenameFromFile = config.readEntry("renameFromFile", false);
50  m_canRenameToFile = config.readEntry("renameToFile", false);
51  m_canDeleteRecursive = config.readEntry("deleteRecursive", false);
52  const QString fnu = config.readEntry("fileNameUsedForCopying", "FromURL");
53  m_fileNameUsedForCopying = KProtocolInfo::FromUrl;
54  if (fnu == QLatin1String("Name")) {
55  m_fileNameUsedForCopying = KProtocolInfo::Name;
56  } else if (fnu == QLatin1String("DisplayName")) {
57  m_fileNameUsedForCopying = KProtocolInfo::DisplayName;
58  }
59 
60  m_listing = config.readEntry("listing", QStringList());
61  // Many .protocol files say "Listing=false" when they really mean "Listing=" (i.e. unsupported)
62  if (m_listing.count() == 1 && m_listing.first() == QLatin1String("false")) {
63  m_listing.clear();
64  }
65  m_supportsListing = (m_listing.count() > 0);
66  m_defaultMimetype = config.readEntry("defaultMimetype");
67  m_determineMimetypeFromExtension = config.readEntry("determineMimetypeFromExtension", true);
68  m_archiveMimeTypes = config.readEntry("archiveMimetype", QStringList());
69  m_icon = config.readEntry("Icon");
70  m_config = config.readEntry("config", m_name);
71  m_maxWorkers = config.readEntry("maxInstances", 1);
72  m_maxWorkersPerHost = config.readEntry("maxInstancesPerHost", 0);
73 
74  QString tmp = config.readEntry("input");
75  if (tmp == QLatin1String("filesystem")) {
76  m_inputType = KProtocolInfo::T_FILESYSTEM;
77  } else if (tmp == QLatin1String("stream")) {
78  m_inputType = KProtocolInfo::T_STREAM;
79  } else {
80  m_inputType = KProtocolInfo::T_NONE;
81  }
82 
83  tmp = config.readEntry("output");
84  if (tmp == QLatin1String("filesystem")) {
85  m_outputType = KProtocolInfo::T_FILESYSTEM;
86  } else if (tmp == QLatin1String("stream")) {
87  m_outputType = KProtocolInfo::T_STREAM;
88  } else {
89  m_outputType = KProtocolInfo::T_NONE;
90  }
91 
92  m_docPath = config.readPathEntry("X-DocPath", QString());
93  if (m_docPath.isEmpty()) {
94  m_docPath = config.readPathEntry("DocPath", QString());
95  }
96  m_protClass = config.readEntry("Class").toLower();
97  if (!m_protClass.startsWith(QLatin1Char(':'))) {
98  m_protClass.prepend(QLatin1Char(':'));
99  }
100 
101  const QStringList extraNames = config.readEntry("ExtraNames", QStringList());
102  const QStringList extraTypes = config.readEntry("ExtraTypes", QStringList());
103  auto it = extraNames.cbegin();
104  auto typeit = extraTypes.cbegin();
105  for (; it != extraNames.cend() && typeit != extraTypes.cend(); ++it, ++typeit) {
106  QVariant::Type type = QVariant::nameToType((*typeit).toLatin1().constData());
107  // currently QVariant::Type and ExtraField::Type use the same subset of values, so we can just cast.
108  m_extraFields.append(KProtocolInfo::ExtraField(*it, static_cast<KProtocolInfo::ExtraField::Type>(type)));
109  }
110 
111  m_showPreviews = config.readEntry("ShowPreviews", m_protClass == QLatin1String(":local"));
112 
113  m_capabilities = config.readEntry("Capabilities", QStringList());
114 
115  m_slaveHandlesNotify = config.readEntry("slaveHandlesNotify", QStringList());
116 
117  m_proxyProtocol = config.readEntry("ProxiedBy");
118 }
119 #endif
120 
121 KProtocolInfoPrivate::KProtocolInfoPrivate(const QString &name, const QString &exec, const QJsonObject &json)
122  : m_name(name)
123  , m_exec(exec)
124 {
125  // source has fallback true if not set
126  m_isSourceProtocol = json.value(QStringLiteral("source")).toBool(true);
127  // true if not set for backwards compatibility
128  m_supportsPermissions = json.value(QStringLiteral("permissions")).toBool(true);
129 
130  // other bools are fine with default false by toBool
131  m_isHelperProtocol = json.value(QStringLiteral("helper")).toBool();
132  m_supportsReading = json.value(QStringLiteral("reading")).toBool();
133  m_supportsWriting = json.value(QStringLiteral("writing")).toBool();
134  m_supportsMakeDir = json.value(QStringLiteral("makedir")).toBool();
135  m_supportsDeleting = json.value(QStringLiteral("deleting")).toBool();
136  m_supportsLinking = json.value(QStringLiteral("linking")).toBool();
137  m_supportsMoving = json.value(QStringLiteral("moving")).toBool();
138  m_supportsOpening = json.value(QStringLiteral("opening")).toBool();
139  m_supportsTruncating = json.value(QStringLiteral("truncating")).toBool();
140  m_canCopyFromFile = json.value(QStringLiteral("copyFromFile")).toBool();
141  m_canCopyToFile = json.value(QStringLiteral("copyToFile")).toBool();
142  m_canRenameFromFile = json.value(QStringLiteral("renameFromFile")).toBool();
143  m_canRenameToFile = json.value(QStringLiteral("renameToFile")).toBool();
144  m_canDeleteRecursive = json.value(QStringLiteral("deleteRecursive")).toBool();
145 
146  // default is "FromURL"
147  const QString fnu = json.value(QStringLiteral("fileNameUsedForCopying")).toString();
148  m_fileNameUsedForCopying = KProtocolInfo::FromUrl;
149  if (fnu == QLatin1String("Name")) {
150  m_fileNameUsedForCopying = KProtocolInfo::Name;
151  } else if (fnu == QLatin1String("DisplayName")) {
152  m_fileNameUsedForCopying = KProtocolInfo::DisplayName;
153  }
154 
155  m_listing = json.value(QStringLiteral("listing")).toVariant().toStringList();
156  // Many .protocol files say "Listing=false" when they really mean "Listing=" (i.e. unsupported)
157  if (m_listing.count() == 1 && m_listing.first() == QLatin1String("false")) {
158  m_listing.clear();
159  }
160  m_supportsListing = (m_listing.count() > 0);
161 
162  m_defaultMimetype = json.value(QStringLiteral("defaultMimetype")).toString();
163 
164  // determineMimetypeFromExtension has fallback true if not set
165  m_determineMimetypeFromExtension = json.value(QStringLiteral("determineMimetypeFromExtension")).toBool(true);
166 
167  m_archiveMimeTypes = json.value(QStringLiteral("archiveMimetype")).toVariant().toStringList();
168 
169  m_icon = json.value(QStringLiteral("Icon")).toString();
170 
171  // config has fallback to name if not set
172  m_config = json.value(QStringLiteral("config")).toString(m_name);
173 
174  // max workers has fallback to 1 if not set
175  m_maxWorkers = json.value(QStringLiteral("maxInstances")).toInt(1);
176 
177  m_maxWorkersPerHost = json.value(QStringLiteral("maxInstancesPerHost")).toInt();
178 
179  QString tmp = json.value(QStringLiteral("input")).toString();
180  if (tmp == QLatin1String("filesystem")) {
181  m_inputType = KProtocolInfo::T_FILESYSTEM;
182  } else if (tmp == QLatin1String("stream")) {
183  m_inputType = KProtocolInfo::T_STREAM;
184  } else {
185  m_inputType = KProtocolInfo::T_NONE;
186  }
187 
188  tmp = json.value(QStringLiteral("output")).toString();
189  if (tmp == QLatin1String("filesystem")) {
190  m_outputType = KProtocolInfo::T_FILESYSTEM;
191  } else if (tmp == QLatin1String("stream")) {
192  m_outputType = KProtocolInfo::T_STREAM;
193  } else {
194  m_outputType = KProtocolInfo::T_NONE;
195  }
196 
197  m_docPath = json.value(QStringLiteral("X-DocPath")).toString();
198  if (m_docPath.isEmpty()) {
199  m_docPath = json.value(QStringLiteral("DocPath")).toString();
200  }
201 
202  m_protClass = json.value(QStringLiteral("Class")).toString().toLower();
203  if (!m_protClass.startsWith(QLatin1Char(':'))) {
204  m_protClass.prepend(QLatin1Char(':'));
205  }
206 
207  // ExtraNames is a translated value, use the KCoreAddons helper to read it
208  const QStringList extraNames = KJsonUtils::readTranslatedValue(json, QStringLiteral("ExtraNames")).toVariant().toStringList();
209  const QStringList extraTypes = json.value(QStringLiteral("ExtraTypes")).toVariant().toStringList();
210  if (extraNames.size() == extraTypes.size()) {
211  auto func = [](const QString &name, const QString &type) {
212  QVariant::Type variantType = QVariant::nameToType(type.toLatin1().constData());
213  // currently QVariant::Type and ExtraField::Type use the same subset of values, so we can just cast.
214  return KProtocolInfo::ExtraField(name, static_cast<KProtocolInfo::ExtraField::Type>(variantType));
215  };
216 
217  std::transform(extraNames.cbegin(), extraNames.cend(), extraTypes.cbegin(), std::back_inserter(m_extraFields), func);
218  } else {
219  qCWarning(KIO_CORE) << "Malformed JSON protocol file for protocol:" << name
220  << ", number of the ExtraNames fields should match the number of ExtraTypes fields";
221  }
222 
223  // fallback based on class
224  m_showPreviews = json.value(QStringLiteral("ShowPreviews")).toBool(m_protClass == QLatin1String(":local"));
225 
226  m_capabilities = json.value(QStringLiteral("Capabilities")).toVariant().toStringList();
227 
228 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 101)
229  m_slaveHandlesNotify = json.value(QStringLiteral("slaveHandlesNotify")).toVariant().toStringList();
230 #endif
231 
232  m_proxyProtocol = json.value(QStringLiteral("ProxiedBy")).toString();
233 }
234 
235 //
236 // Static functions:
237 //
238 
240 {
241  return KProtocolInfoFactory::self()->protocols();
242 }
243 
245 {
246  // We call the findProtocol directly (not via KProtocolManager) to bypass any proxy settings.
247  KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
248  if (!prot) {
249  return false;
250  }
251 
252  return !prot->m_isSourceProtocol;
253 }
254 
256 {
257  // We call the findProtocol directly (not via KProtocolManager) to bypass any proxy settings.
258  KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
259  if (!prot) {
260  if (auto service = KApplicationTrader::preferredService(QLatin1String("x-scheme-handler/") + _protocol)) {
261  return service->icon();
262  } else {
263  return QString();
264  }
265  }
266 
267  return prot->m_icon;
268 }
269 
271 {
272  // We call the findProtocol directly (not via KProtocolManager) to bypass any proxy settings.
273  KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
274  if (!prot) {
275  return QString();
276  }
277 
278  return QStringLiteral("kio_%1rc").arg(prot->m_config);
279 }
280 
281 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 101)
282 int KProtocolInfo::maxSlaves(const QString &_protocol)
283 {
284  return maxWorkers(_protocol);
285 }
286 #endif
287 
288 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 101)
290 {
291  return maxWorkersPerHost(_protocol);
292 }
293 #endif
294 
295 int KProtocolInfo::maxWorkers(const QString &_protocol)
296 {
297  KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
298  if (!prot) {
299  return 1;
300  }
301 
302  return prot->m_maxWorkers;
303 }
304 
306 {
307  KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
308  if (!prot) {
309  return 0;
310  }
311 
312  return prot->m_maxWorkersPerHost;
313 }
314 
316 {
317  KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
318  if (!prot) {
319  return true;
320  }
321 
322  return prot->m_determineMimetypeFromExtension;
323 }
324 
326 {
327  KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(protocol);
328  if (!prot) {
329  return QString();
330  }
331  return prot->m_exec;
332 }
333 
335 {
336  KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(url.scheme());
337  if (!prot) {
338  return ExtraFieldList();
339  }
340 
341  return prot->m_extraFields;
342 }
343 
345 {
346  KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
347  if (!prot) {
348  return QString();
349  }
350 
351  return prot->m_defaultMimetype;
352 }
353 
355 {
356  KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
357  if (!prot) {
358  return QString();
359  }
360 
361  return prot->m_docPath;
362 }
363 
365 {
366  KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
367  if (!prot) {
368  return QString();
369  }
370 
371  return prot->m_protClass;
372 }
373 
375 {
376  KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
377  const bool defaultSetting = prot ? prot->m_showPreviews : false;
378 
379  KConfigGroup group(KSharedConfig::openConfig(), "PreviewSettings");
380  return group.readEntry(_protocol, defaultSetting);
381 }
382 
384 {
385  KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
386  if (!prot) {
387  return QStringList();
388  }
389 
390  return prot->m_capabilities;
391 }
392 
394 {
395  KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(protocol);
396  if (!prot) {
397  return QStringList();
398  }
399 
400  return prot->m_archiveMimeTypes;
401 }
402 
403 #if KIOCORE_BUILD_DEPRECATED_SINCE(5, 101)
405 {
406  KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
407  if (!prot) {
408  return QStringList();
409  }
410 
411  return prot->m_slaveHandlesNotify;
412 }
413 #endif
414 
416 {
417  KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(_protocol);
418  if (!prot) {
419  return QString();
420  }
421 
422  return prot->m_proxyProtocol;
423 }
424 
426 {
427  return isFilterProtocol(url.scheme());
428 }
429 
431 {
432  return isHelperProtocol(url.scheme());
433 }
434 
436 {
437  // We call the findProtocol directly (not via KProtocolManager) to bypass any proxy settings.
438  KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(protocol);
439  if (prot) {
440  return prot->m_isHelperProtocol;
441  }
442  return false;
443 }
444 
446 {
447  return isKnownProtocol(url.scheme());
448 }
449 
451 {
452  // We call the findProtocol (const QString&) to bypass any proxy settings.
453  KProtocolInfoPrivate *prot = KProtocolInfoFactory::self()->findProtocol(protocol);
454  return prot;
455 }
bool toBool(bool defaultValue) const const
QString readEntry(const char *key, const char *aDefault=nullptr) const
static QString exec(const QString &protocol)
Returns the library / executable to open for the protocol protocol Example : "kio_ftp",...
QString toString(const T &enumerator)
static QStringList capabilities(const QString &protocol)
Returns the list of capabilities provided by the KIO worker implementing this protocol.
@ T_NONE
no information about the type available
Definition: kprotocolinfo.h:84
Definition of an extra field in the UDS entries, returned by a listDir operation.
Definition: kprotocolinfo.h:96
static int maxSlaves(const QString &protocol)
Returns the soft limit on the number of slaves for this protocol.
static bool isHelperProtocol(const QUrl &url)
Returns whether the protocol can act as a helper protocol.
Type type(const QSqlDatabase &db)
QString scheme() const const
static QString config(const QString &protocol)
Returns the name of the config file associated with the specified protocol.
QString & prepend(QChar ch)
QVariant::Type nameToType(const char *name)
static int maxWorkers(const QString &protocol)
Returns the soft limit on the number of KIO workers for this protocol.
QString toString() const const
static ExtraFieldList extraFields(const QUrl &url)
Definition of extra fields in the UDS entries, returned by a listDir operation.
@ T_FILESYSTEM
structured directory
Definition: kprotocolinfo.h:83
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
static bool isKnownProtocol(const QUrl &url)
Returns whether a protocol is installed that is able to handle url.
static QString docPath(const QString &protocol)
Returns the documentation path for the specified protocol.
int size() const const
KSERVICE_EXPORT KService::Ptr preferredService(const QString &mimeType)
@ T_STREAM
stream of data (e.g. single file)
Definition: kprotocolinfo.h:82
static QStringList protocols()
Returns list of all known protocols.
static bool determineMimetypeFromExtension(const QString &protocol)
Returns whether MIME types can be determined based on extension for this protocol.
QJsonValue value(const QString &key) const const
QVariant toVariant() const const
QList::const_iterator cend() const const
static int maxSlavesPerHost(const QString &protocol)
Returns the limit on the number of slaves for this protocol per host.
static QString defaultMimetype(const QString &protocol)
Returns the default MIME type for the specified protocol, if one exists.
KSharedConfigPtr config()
static QStringList slaveHandlesNotify(const QString &protocol)
Returns the list of notification types the kioslave implementing this protocol will produce on its ow...
static bool showFilePreview(const QString &protocol)
Returns whether file previews should be shown for the specified protocol.
QString toLower() const const
static bool isFilterProtocol(const QUrl &url)
Returns whether the protocol can act as a filter protocol.
static QString icon(const QString &protocol)
Returns the name of the icon, associated with the specified protocol.
QString name(StandardShortcut id)
QList::const_iterator cbegin() const const
static int maxWorkersPerHost(const QString &protocol)
Returns the limit on the number of KIO workers for this protocol per host.
static QStringList archiveMimetypes(const QString &protocol)
Returns the list of archive MIME types handled by the KIO worker implementing this protocol.
void clear()
QStringList toStringList() const const
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 QString protocolClass(const QString &protocol)
Returns the protocol class for the specified protocol.
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon May 8 2023 03:54:43 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.