KIO

kprotocolmanager.cpp
1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 1999 Torben Weis <weis@kde.org>
4 SPDX-FileCopyrightText: 2000 Waldo Bastain <bastain@kde.org>
5 SPDX-FileCopyrightText: 2000 Dawit Alemayehu <adawit@kde.org>
6 SPDX-FileCopyrightText: 2008 Jarosław Staniek <staniek@kde.org>
7 SPDX-FileCopyrightText: 2022 Harald Sitter <sitter@kde.org>
8
9 SPDX-License-Identifier: LGPL-2.0-only
10*/
11
12#include "kprotocolmanager.h"
13#include "kprotocolinfo_p.h"
14#include "kprotocolmanager_p.h"
15
16#include "hostinfo.h"
17
18#include <config-kiocore.h>
19
20#include <qplatformdefs.h>
21#include <string.h>
22#ifdef Q_OS_WIN
23#include <qt_windows.h>
24#undef interface // windows.h defines this, breaks QtDBus since it has parameters named interface
25#else
26#include <sys/utsname.h>
27#endif
28
29#include <QCache>
30#include <QCoreApplication>
31#ifndef KIO_ANDROID_STUB
32#include <QDBusInterface>
33#include <QDBusReply>
34#endif
35#include <QHostAddress>
36#include <QHostInfo>
37#include <QLocale>
38#include <QMimeDatabase>
39#include <QRegularExpression>
40#include <QSslSocket>
41#include <QStandardPaths>
42#include <QUrl>
43
44#if !defined(QT_NO_NETWORKPROXY) && (defined(Q_OS_WIN32) || defined(Q_OS_MAC))
45#include <QNetworkProxyFactory>
46#include <QNetworkProxyQuery>
47#endif
48
49#include <KConfigGroup>
50#include <KSharedConfig>
51#include <kio_version.h>
52
53#include <kprotocolinfofactory_p.h>
54
55#include "ioworker_defaults.h"
56#include "workerconfig.h"
57
58/*
59 Domain suffix match. E.g. return true if host is "cuzco.inka.de" and
60 nplist is "inka.de,hadiko.de" or if host is "localhost" and nplist is
61 "localhost".
62*/
63static bool revmatch(const char *host, const char *nplist)
64{
65 if (host == nullptr) {
66 return false;
67 }
68
69 const char *hptr = host + strlen(host) - 1;
70 const char *nptr = nplist + strlen(nplist) - 1;
71 const char *shptr = hptr;
72
73 while (nptr >= nplist) {
74 if (*hptr != *nptr) {
75 hptr = shptr;
76
77 // Try to find another domain or host in the list
78 while (--nptr >= nplist && *nptr != ',' && *nptr != ' ') {
79 ;
80 }
81
82 // Strip out multiple spaces and commas
83 while (--nptr >= nplist && (*nptr == ',' || *nptr == ' ')) {
84 ;
85 }
86 } else {
87 if (nptr == nplist || nptr[-1] == ',' || nptr[-1] == ' ') {
88 return true;
89 }
90 if (nptr[-1] == '/' && hptr == host) { // "bugs.kde.org" vs "http://bugs.kde.org", the config UI says URLs are ok
91 return true;
92 }
93 if (hptr == host) { // e.g. revmatch("bugs.kde.org","mybugs.kde.org")
94 return false;
95 }
96
97 hptr--;
98 nptr--;
99 }
100 }
101
102 return false;
103}
104
105Q_GLOBAL_STATIC(KProtocolManagerPrivate, kProtocolManagerPrivate)
106
107static void syncOnExit()
108{
109 if (kProtocolManagerPrivate.exists()) {
110 kProtocolManagerPrivate()->sync();
111 }
112}
113
114KProtocolManagerPrivate::KProtocolManagerPrivate()
115{
116 // post routine since KConfig::sync() breaks if called too late
117 qAddPostRoutine(syncOnExit);
118 cachedProxyData.setMaxCost(200); // double the max cost.
119}
120
121KProtocolManagerPrivate::~KProtocolManagerPrivate()
122{
123}
124
125/*
126 * Returns true if url is in the no proxy list.
127 */
128bool KProtocolManagerPrivate::shouldIgnoreProxyFor(const QUrl &url)
129{
130 bool isMatch = false;
131 const ProxyType type = proxyType();
132 const bool useRevProxy = ((type == ManualProxy) && useReverseProxy());
133 const bool useNoProxyList = (type == ManualProxy || type == EnvVarProxy);
134
135 // No proxy only applies to ManualProxy and EnvVarProxy types...
136 if (useNoProxyList && noProxyFor.isEmpty()) {
137 QStringList noProxyForList(readNoProxyFor().split(QLatin1Char(',')));
138 QMutableStringListIterator it(noProxyForList);
139 while (it.hasNext()) {
140 SubnetPair subnet = QHostAddress::parseSubnet(it.next());
141 if (!subnet.first.isNull()) {
142 noProxySubnets << subnet;
143 it.remove();
144 }
145 }
146 noProxyFor = noProxyForList.join(QLatin1Char(','));
147 }
148
149 if (!noProxyFor.isEmpty()) {
150 QString qhost = url.host().toLower();
151 QByteArray host = qhost.toLatin1();
152 const QString qno_proxy = noProxyFor.trimmed().toLower();
153 const QByteArray no_proxy = qno_proxy.toLatin1();
154 isMatch = revmatch(host.constData(), no_proxy.constData());
155
156 // If no match is found and the request url has a port
157 // number, try the combination of "host:port". This allows
158 // users to enter host:port in the No-proxy-For list.
159 if (!isMatch && url.port() > 0) {
160 qhost += QLatin1Char(':') + QString::number(url.port());
161 host = qhost.toLatin1();
162 isMatch = revmatch(host.constData(), no_proxy.constData());
163 }
164
165 // If the hostname does not contain a dot, check if
166 // <local> is part of noProxy.
167 if (!isMatch && !host.isEmpty() && (strchr(host.constData(), '.') == nullptr)) {
168 isMatch = revmatch("<local>", no_proxy.constData());
169 }
170 }
171
172 const QString host(url.host());
173
174 if (!noProxySubnets.isEmpty() && !host.isEmpty()) {
175 QHostAddress address(host);
176 // If request url is not IP address, do a DNS lookup of the hostname.
177 // TODO: Perhaps we should make configurable ?
178 if (address.isNull()) {
179 // qDebug() << "Performing DNS lookup for" << host;
180 QHostInfo info = KIO::HostInfo::lookupHost(host, 2000);
181 const QList<QHostAddress> addresses = info.addresses();
182 if (!addresses.isEmpty()) {
183 address = addresses.first();
184 }
185 }
186
187 if (!address.isNull()) {
188 for (const SubnetPair &subnet : std::as_const(noProxySubnets)) {
189 if (address.isInSubnet(subnet)) {
190 isMatch = true;
191 break;
192 }
193 }
194 }
195 }
196
197 return (useRevProxy != isMatch);
198}
199
200void KProtocolManagerPrivate::sync()
201{
202 QMutexLocker lock(&mutex);
203 if (http_config) {
204 http_config->sync();
205 }
206 if (configPtr) {
207 configPtr->sync();
208 }
209}
210
212{
213 KProtocolManagerPrivate *d = kProtocolManagerPrivate();
214 QMutexLocker lock(&d->mutex);
215 if (d->http_config) {
216 d->http_config->reparseConfiguration();
217 }
218 if (d->configPtr) {
219 d->configPtr->reparseConfiguration();
220 }
221 d->cachedProxyData.clear();
222 d->noProxyFor.clear();
223 d->modifiers.clear();
224 d->useragent.clear();
225 lock.unlock();
226
227 // Force the slave config to re-read its config...
228 KIO::WorkerConfig::self()->reset();
229}
230
231static KSharedConfig::Ptr config()
232{
233 KProtocolManagerPrivate *d = kProtocolManagerPrivate();
234 Q_ASSERT(!d->mutex.tryLock()); // the caller must have locked the mutex
235 if (!d->configPtr) {
236 d->configPtr = KSharedConfig::openConfig(QStringLiteral("kioslaverc"), KConfig::NoGlobals);
237 }
238 return d->configPtr;
239}
240
241KProtocolManagerPrivate::ProxyType KProtocolManagerPrivate::proxyType()
242{
243 KConfigGroup cg(config(), QStringLiteral("Proxy Settings"));
244 return static_cast<ProxyType>(cg.readEntry("ProxyType", 0));
245}
246
247bool KProtocolManagerPrivate::useReverseProxy()
248{
249 KConfigGroup cg(config(), QStringLiteral("Proxy Settings"));
250 return cg.readEntry("ReversedException", false);
251}
252
253QString KProtocolManagerPrivate::readNoProxyFor()
254{
255 QString noProxy = config()->group(QStringLiteral("Proxy Settings")).readEntry("NoProxyFor");
256 if (proxyType() == EnvVarProxy) {
257 noProxy = QString::fromLocal8Bit(qgetenv(noProxy.toLocal8Bit().constData()));
258 }
259 return noProxy;
260}
261
262QMap<QString, QString> KProtocolManager::entryMap(const QString &group)
263{
264 KProtocolManagerPrivate *d = kProtocolManagerPrivate();
265 QMutexLocker lock(&d->mutex);
266 return config()->entryMap(group);
267}
268
269/*=============================== TIMEOUT SETTINGS ==========================*/
270
272{
273 KProtocolManagerPrivate *d = kProtocolManagerPrivate();
274 QMutexLocker lock(&d->mutex);
275 KConfigGroup cg(config(), QString());
276 int val = cg.readEntry("ReadTimeout", DEFAULT_READ_TIMEOUT);
277 return qMax(MIN_TIMEOUT_VALUE, val);
278}
279
281{
282 KProtocolManagerPrivate *d = kProtocolManagerPrivate();
283 QMutexLocker lock(&d->mutex);
284 KConfigGroup cg(config(), QString());
285 int val = cg.readEntry("ConnectTimeout", DEFAULT_CONNECT_TIMEOUT);
286 return qMax(MIN_TIMEOUT_VALUE, val);
287}
288
290{
291 KProtocolManagerPrivate *d = kProtocolManagerPrivate();
292 QMutexLocker lock(&d->mutex);
293 KConfigGroup cg(config(), QString());
294 int val = cg.readEntry("ProxyConnectTimeout", DEFAULT_PROXY_CONNECT_TIMEOUT);
295 return qMax(MIN_TIMEOUT_VALUE, val);
296}
297
299{
300 KProtocolManagerPrivate *d = kProtocolManagerPrivate();
301 QMutexLocker lock(&d->mutex);
302 KConfigGroup cg(config(), QString());
303 int val = cg.readEntry("ResponseTimeout", DEFAULT_RESPONSE_TIMEOUT);
304 return qMax(MIN_TIMEOUT_VALUE, val);
305}
306
307static QString adjustProtocol(const QString &scheme)
308{
309 if (scheme.compare(QLatin1String("webdav"), Qt::CaseInsensitive) == 0) {
310 return QStringLiteral("http");
311 }
312
313 if (scheme.compare(QLatin1String("webdavs"), Qt::CaseInsensitive) == 0) {
314 return QStringLiteral("https");
315 }
316
317 return scheme.toLower();
318}
319
320QString KProtocolManagerPrivate::proxyFor(const QString &protocol)
321{
322 const QString key = adjustProtocol(protocol) + QLatin1String("Proxy");
323 QString proxyStr(config()->group(QStringLiteral("Proxy Settings")).readEntry(key));
324 const int index = proxyStr.lastIndexOf(QLatin1Char(' '));
325
326 if (index > -1) {
327 const QStringView portStr = QStringView(proxyStr).right(proxyStr.length() - index - 1);
328 const bool isDigits = std::all_of(portStr.cbegin(), portStr.cend(), [](const QChar c) {
329 return c.isDigit();
330 });
331
332 if (isDigits) {
333 proxyStr = QStringView(proxyStr).left(index) + QLatin1Char(':') + portStr;
334 } else {
335 proxyStr.clear();
336 }
337 }
338
339 return proxyStr;
340}
341
342QStringList KProtocolManagerPrivate::getSystemProxyFor(const QUrl &url)
343{
344 QStringList proxies;
345
346#if !defined(QT_NO_NETWORKPROXY) && (defined(Q_OS_WIN32) || defined(Q_OS_MAC))
349 proxies.reserve(proxyList.size());
350 for (const QNetworkProxy &proxy : proxyList) {
351 QUrl url;
352 const QNetworkProxy::ProxyType type = proxy.type();
354 proxies << QLatin1String("DIRECT");
355 continue;
356 }
357
359 url.setScheme(QLatin1String("http"));
360 } else if (type == QNetworkProxy::Socks5Proxy) {
361 url.setScheme(QLatin1String("socks"));
362 } else if (type == QNetworkProxy::FtpCachingProxy) {
363 url.setScheme(QLatin1String("ftp"));
364 }
365
366 url.setHost(proxy.hostName());
367 url.setPort(proxy.port());
368 url.setUserName(proxy.user());
369 proxies << url.url();
370 }
371#else
372 // On Unix/Linux use system environment variables if any are set.
373 QString proxyVar(proxyFor(url.scheme()));
374 // Check for SOCKS proxy, if not proxy is found for given url.
375 if (!proxyVar.isEmpty()) {
376 const QString proxy(QString::fromLocal8Bit(qgetenv(proxyVar.toLocal8Bit().constData())).trimmed());
377 if (!proxy.isEmpty()) {
378 proxies << proxy;
379 }
380 }
381 // Add the socks proxy as an alternate proxy if it exists,
382 proxyVar = proxyFor(QStringLiteral("socks"));
383 if (!proxyVar.isEmpty()) {
384 QString proxy = QString::fromLocal8Bit(qgetenv(proxyVar.toLocal8Bit().constData())).trimmed();
385 // Make sure the scheme of SOCKS proxy is always set to "socks://".
386 const int index = proxy.indexOf(QLatin1String("://"));
387 const int offset = (index == -1) ? 0 : (index + 3);
388 proxy = QLatin1String("socks://") + QStringView(proxy).mid(offset);
389 if (!proxy.isEmpty()) {
390 proxies << proxy;
391 }
392 }
393#endif
394 return proxies;
395}
396
397QStringList KProtocolManagerPrivate::proxiesForUrl(const QUrl &url)
398{
399 QStringList proxyList;
400
401 KProtocolManagerPrivate *d = kProtocolManagerPrivate();
402 QMutexLocker lock(&d->mutex);
403 if (!d->shouldIgnoreProxyFor(url)) {
404 switch (d->proxyType()) {
405 case PACProxy:
406 case WPADProxy: {
407 QUrl u(url);
408 const QString protocol = adjustProtocol(u.scheme());
409 u.setScheme(protocol);
410
411#ifndef KIO_ANDROID_STUB
412 if (protocol.startsWith(QLatin1String("http")) || protocol.startsWith(QLatin1String("ftp"))) {
414 QDBusInterface(QStringLiteral("org.kde.kded6"), QStringLiteral("/modules/proxyscout"), QStringLiteral("org.kde.KPAC.ProxyScout"))
415 .call(QStringLiteral("proxiesForUrl"), u.toString());
416 proxyList = reply;
417 }
418#endif
419 break;
420 }
421 case EnvVarProxy:
422 proxyList = d->getSystemProxyFor(url);
423 break;
424 case ManualProxy: {
425 QString proxy(d->proxyFor(url.scheme()));
426 if (!proxy.isEmpty()) {
427 proxyList << proxy;
428 }
429 // Add the socks proxy as an alternate proxy if it exists,
430 proxy = d->proxyFor(QStringLiteral("socks"));
431 if (!proxy.isEmpty()) {
432 // Make sure the scheme of SOCKS proxy is always set to "socks://".
433 const int index = proxy.indexOf(QLatin1String("://"));
434 const int offset = (index == -1) ? 0 : (index + 3);
435 proxy = QLatin1String("socks://") + QStringView(proxy).mid(offset);
436 proxyList << proxy;
437 }
438 break;
439 }
440 case NoProxy:
441 break;
442 }
443 }
444
445 if (proxyList.isEmpty()) {
446 proxyList << QStringLiteral("DIRECT");
447 }
448
449 return proxyList;
450}
451
452// Generates proxy cache key from request given url.
453static QString extractProxyCacheKeyFromUrl(const QUrl &u)
454{
455 QString key = u.scheme();
456 key += u.host();
457
458 if (u.port() > 0) {
459 key += QString::number(u.port());
460 }
461 return key;
462}
463
464QString KProtocolManagerPrivate::workerProtocol(const QUrl &url, QStringList &proxyList)
465{
466 proxyList.clear();
467 KProtocolManagerPrivate *d = kProtocolManagerPrivate();
468 QMutexLocker lock(&d->mutex);
469 // Do not perform a proxy lookup for any url classified as a ":local" url or
470 // one that does not have a host component or if proxy is disabled.
471 QString protocol(url.scheme());
472 if (url.host().isEmpty() || KProtocolInfo::protocolClass(protocol) == QLatin1String(":local") || kProtocolManagerPrivate->proxyType() == NoProxy) {
473 return protocol;
474 }
475
476 const QString proxyCacheKey = extractProxyCacheKeyFromUrl(url);
477
478 // Look for cached proxy information to avoid more work.
479 if (d->cachedProxyData.contains(proxyCacheKey)) {
480 KProxyData *data = d->cachedProxyData.object(proxyCacheKey);
481 proxyList = data->proxyList;
482 return data->protocol;
483 }
484 lock.unlock();
485
486 const QStringList proxies = KProtocolManagerPrivate::proxiesForUrl(url);
487 const int count = proxies.count();
488
489 if (count > 0 && !(count == 1 && proxies.first() == QLatin1String("DIRECT"))) {
490 for (const QString &proxy : proxies) {
491 if (proxy == QLatin1String("DIRECT")) {
492 proxyList << proxy;
493 } else {
494 QUrl u(proxy);
495 if (!u.isEmpty() && u.isValid() && !u.scheme().isEmpty()) {
496 proxyList << proxy;
497 }
498 }
499 }
500 }
501
502 // The idea behind worker protocols is not applicable to http
503 // and webdav protocols as well as protocols unknown to KDE.
504 /* clang-format off */
505 if (!proxyList.isEmpty()
506 && !protocol.startsWith(QLatin1String("http"))
507 && !protocol.startsWith(QLatin1String("webdav"))
508 && KProtocolInfo::isKnownProtocol(protocol)) { /* clang-format on */
509 for (const QString &proxy : std::as_const(proxyList)) {
510 QUrl u(proxy);
512 protocol = u.scheme();
513 break;
514 }
515 }
516 }
517
518 lock.relock();
519 // cache the proxy information...
520 d->cachedProxyData.insert(proxyCacheKey, new KProxyData(protocol, proxyList));
521 return protocol;
522}
523
524/*================================= USER-AGENT SETTINGS =====================*/
525
526// This is not the OS, but the windowing system, e.g. X11 on Unix/Linux.
527static QString platform()
528{
529#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
530 return QStringLiteral("X11");
531#elif defined(Q_OS_MAC)
532 return QStringLiteral("Macintosh");
533#elif defined(Q_OS_WIN)
534 return QStringLiteral("Windows");
535#else
536 return QStringLiteral("Unknown");
537#endif
538}
539
540QString KProtocolManagerPrivate::defaultUserAgent(const QString &_modifiers)
541{
542 KProtocolManagerPrivate *d = kProtocolManagerPrivate();
543 QMutexLocker lock(&d->mutex);
544 QString modifiers = _modifiers.toLower();
545 if (modifiers.isEmpty()) {
546 modifiers = QStringLiteral("om"); // Show OS, Machine
547 }
548
549 if (d->modifiers == modifiers && !d->useragent.isEmpty()) {
550 return d->useragent;
551 }
552
553 d->modifiers = modifiers;
554
555 QString systemName;
556 QString systemVersion;
557 QString machine;
558 QString supp;
559 const bool sysInfoFound = KProtocolManagerPrivate::getSystemNameVersionAndMachine(systemName, systemVersion, machine);
560
561 supp += platform();
562
563 if (sysInfoFound) {
564 if (modifiers.contains(QLatin1Char('o'))) {
565 supp += QLatin1String("; ") + systemName;
566 if (modifiers.contains(QLatin1Char('v'))) {
567 supp += QLatin1Char(' ') + systemVersion;
568 }
569
570 if (modifiers.contains(QLatin1Char('m'))) {
571 supp += QLatin1Char(' ') + machine;
572 }
573 }
574
575 if (modifiers.contains(QLatin1Char('l'))) {
576 supp += QLatin1String("; ") + QLocale::languageToString(QLocale().language());
577 }
578 }
579
582 appName = QStringLiteral("KDE");
583 }
585 if (appVersion.isEmpty()) {
586 appVersion += QLatin1String(KIO_VERSION_STRING);
587 }
588
589 d->useragent = QLatin1String("Mozilla/5.0 (%1) ").arg(supp)
590 + QLatin1String("KIO/%1.%2 ").arg(QString::number(KIO_VERSION_MAJOR), QString::number(KIO_VERSION_MINOR))
591 + QLatin1String("%1/%2").arg(appName, appVersion);
592
593 // qDebug() << "USERAGENT STRING:" << d->useragent;
594 return d->useragent;
595}
596
597bool KProtocolManagerPrivate::getSystemNameVersionAndMachine(QString &systemName, QString &systemVersion, QString &machine)
598{
599#if defined(Q_OS_WIN)
600 // we do not use unameBuf.sysname information constructed in kdewin32
601 // because we want to get separate name and version
602 systemName = QStringLiteral("Windows");
603 OSVERSIONINFOEX versioninfo;
604 ZeroMemory(&versioninfo, sizeof(OSVERSIONINFOEX));
605 // try calling GetVersionEx using the OSVERSIONINFOEX, if that fails, try using the OSVERSIONINFO
606 versioninfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
607 bool ok = GetVersionEx((OSVERSIONINFO *)&versioninfo);
608 if (!ok) {
609 versioninfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
610 ok = GetVersionEx((OSVERSIONINFO *)&versioninfo);
611 }
612 if (ok) {
613 systemVersion = QString::number(versioninfo.dwMajorVersion);
614 systemVersion += QLatin1Char('.');
615 systemVersion += QString::number(versioninfo.dwMinorVersion);
616 }
617#else
618 struct utsname unameBuf;
619 if (0 != uname(&unameBuf)) {
620 return false;
621 }
622 systemName = QString::fromUtf8(unameBuf.sysname);
623 systemVersion = QString::fromUtf8(unameBuf.release);
624 machine = QString::fromUtf8(unameBuf.machine);
625#endif
626 return true;
627}
628
629/*==================================== OTHERS ===============================*/
630
632{
633 KProtocolManagerPrivate *d = kProtocolManagerPrivate();
634 QMutexLocker lock(&d->mutex);
635 return config()->group(QString()).readEntry("MarkPartial", true);
636}
637
639{
640 KProtocolManagerPrivate *d = kProtocolManagerPrivate();
641 QMutexLocker lock(&d->mutex);
642 return config()->group(QString()).readEntry("MinimumKeepSize",
643 DEFAULT_MINIMUM_KEEP_SIZE); // 5000 byte
644}
645
647{
648 KProtocolManagerPrivate *d = kProtocolManagerPrivate();
649 QMutexLocker lock(&d->mutex);
650 return config()->group(QString()).readEntry("AutoResume", false);
651}
652
653/* =========================== PROTOCOL CAPABILITIES ============== */
654
655static KProtocolInfoPrivate *findProtocol(const QUrl &url)
656{
657 if (!url.isValid()) {
658 return nullptr;
659 }
660 QString protocol = url.scheme();
661 if (!KProtocolInfo::proxiedBy(protocol).isEmpty()) {
662 QStringList dummy;
663 protocol = KProtocolManagerPrivate::workerProtocol(url, dummy);
664 }
665
666 return KProtocolInfoFactory::self()->findProtocol(protocol);
667}
668
670{
671 KProtocolInfoPrivate *prot = findProtocol(url);
672 if (!prot) {
674 }
675
676 return prot->m_inputType;
677}
678
680{
681 KProtocolInfoPrivate *prot = findProtocol(url);
682 if (!prot) {
684 }
685
686 return prot->m_outputType;
687}
688
690{
691 KProtocolInfoPrivate *prot = findProtocol(url);
692 if (!prot) {
693 return false;
694 }
695
696 return prot->m_isSourceProtocol;
697}
698
700{
701 KProtocolInfoPrivate *prot = findProtocol(url);
702 if (!prot) {
703 return false;
704 }
705
706 return prot->m_supportsListing;
707}
708
710{
711 KProtocolInfoPrivate *prot = findProtocol(url);
712 if (!prot) {
713 return QStringList();
714 }
715
716 return prot->m_listing;
717}
718
720{
721 KProtocolInfoPrivate *prot = findProtocol(url);
722 if (!prot) {
723 return false;
724 }
725
726 return prot->m_supportsReading;
727}
728
730{
731 KProtocolInfoPrivate *prot = findProtocol(url);
732 if (!prot) {
733 return false;
734 }
735
736 return prot->m_supportsWriting;
737}
738
740{
741 KProtocolInfoPrivate *prot = findProtocol(url);
742 if (!prot) {
743 return false;
744 }
745
746 return prot->m_supportsMakeDir;
747}
748
750{
751 KProtocolInfoPrivate *prot = findProtocol(url);
752 if (!prot) {
753 return false;
754 }
755
756 return prot->m_supportsDeleting;
757}
758
760{
761 KProtocolInfoPrivate *prot = findProtocol(url);
762 if (!prot) {
763 return false;
764 }
765
766 return prot->m_supportsLinking;
767}
768
770{
771 KProtocolInfoPrivate *prot = findProtocol(url);
772 if (!prot) {
773 return false;
774 }
775
776 return prot->m_supportsMoving;
777}
778
780{
781 KProtocolInfoPrivate *prot = findProtocol(url);
782 if (!prot) {
783 return false;
784 }
785
786 return prot->m_supportsOpening;
787}
788
790{
791 KProtocolInfoPrivate *prot = findProtocol(url);
792 if (!prot) {
793 return false;
794 }
795
796 return prot->m_supportsTruncating;
797}
798
800{
801 KProtocolInfoPrivate *prot = findProtocol(url);
802 if (!prot) {
803 return false;
804 }
805
806 return prot->m_canCopyFromFile;
807}
808
810{
811 KProtocolInfoPrivate *prot = findProtocol(url);
812 if (!prot) {
813 return false;
814 }
815
816 return prot->m_canCopyToFile;
817}
818
820{
821 KProtocolInfoPrivate *prot = findProtocol(url);
822 if (!prot) {
823 return false;
824 }
825
826 return prot->m_canRenameFromFile;
827}
828
830{
831 KProtocolInfoPrivate *prot = findProtocol(url);
832 if (!prot) {
833 return false;
834 }
835
836 return prot->m_canRenameToFile;
837}
838
840{
841 KProtocolInfoPrivate *prot = findProtocol(url);
842 if (!prot) {
843 return false;
844 }
845
846 return prot->m_canDeleteRecursive;
847}
848
849KProtocolInfo::FileNameUsedForCopying KProtocolManager::fileNameUsedForCopying(const QUrl &url)
850{
851 KProtocolInfoPrivate *prot = findProtocol(url);
852 if (!prot) {
853 return KProtocolInfo::FromUrl;
854 }
855
856 return prot->m_fileNameUsedForCopying;
857}
858
860{
861 KProtocolInfoPrivate *prot = findProtocol(url);
862 if (!prot) {
863 return QString();
864 }
865
866 return prot->m_defaultMimetype;
867}
868
870{
871 KProtocolManagerPrivate *d = kProtocolManagerPrivate();
872 QMutexLocker lock(&d->mutex);
873 if (d->protocolForArchiveMimetypes.isEmpty()) {
874 const QList<KProtocolInfoPrivate *> allProtocols = KProtocolInfoFactory::self()->allProtocols();
875 for (KProtocolInfoPrivate *allProtocol : allProtocols) {
876 const QStringList archiveMimetypes = allProtocol->m_archiveMimeTypes;
877 for (const QString &mime : archiveMimetypes) {
878 d->protocolForArchiveMimetypes.insert(mime, allProtocol->m_name);
879 }
880 }
881 }
882 return d->protocolForArchiveMimetypes.value(mimeType);
883}
884
886{
887 return KIO::WorkerConfig::self()->configData(url.scheme(), url.host(), QStringLiteral("Charset"));
888}
889
891{
892 KProtocolInfoPrivate *prot = findProtocol(url);
893 if (!prot) {
894 return true;
895 }
896
897 return prot->m_supportsPermissions;
898}
899
900#undef PRIVATE_DATA
901
902#include "moc_kprotocolmanager_p.cpp"
QString readEntry(const char *key, const char *aDefault=nullptr) const
void reset()
Undo any changes made by calls to setConfigData.
MetaData configData(const QString &protocol, const QString &host)
Query worker configuration for workers of type protocol when dealing with host.
static QString protocolClass(const QString &protocol)
Returns the protocol class 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...
Type
Describes the type of a protocol.
@ T_NONE
no information about the type available
static bool isKnownProtocol(const QUrl &url)
Returns whether a protocol is installed that is able to handle url.
static int proxyConnectTimeout()
Returns the preferred timeout value for proxy connections in seconds.
static bool supportsOpening(const QUrl &url)
Returns whether the protocol can be opened using KIO::open(const QUrl&).
static KProtocolInfo::Type outputType(const QUrl &url)
Returns whether the protocol should be treated as a filesystem or as a stream when writing to it.
static bool supportsPermissions(const QUrl &url)
Returns whether the protocol suppports KIO/POSIX permissions handling.
static QString charsetFor(const QUrl &url)
Returns the charset to use for the specified url.
static QStringList listing(const QUrl &url)
Returns the list of fields this protocol returns when listing The current possibilities are Name,...
static bool canRenameToFile(const QUrl &url)
Returns whether the protocol can rename (i.e.
static bool supportsReading(const QUrl &url)
Returns whether the protocol can retrieve data from URLs.
static bool canCopyFromFile(const QUrl &url)
Returns whether the protocol can copy files/objects directly from the filesystem itself.
static QString defaultMimetype(const QUrl &url)
Returns default MIME type for this URL based on the protocol.
static bool canRenameFromFile(const QUrl &url)
Returns whether the protocol can rename (i.e.
static KProtocolInfo::Type inputType(const QUrl &url)
Returns whether the protocol should be treated as a filesystem or as a stream when reading from it.
static bool supportsListing(const QUrl &url)
Returns whether the protocol can list files/objects.
static bool supportsDeleting(const QUrl &url)
Returns whether the protocol can delete files/objects.
static bool supportsLinking(const QUrl &url)
Returns whether the protocol can create links between files/objects.
static KProtocolInfo::FileNameUsedForCopying fileNameUsedForCopying(const QUrl &url)
This setting defines the strategy to use for generating a filename, when copying a file or directory ...
static QString protocolForArchiveMimetype(const QString &mimeType)
Returns which protocol handles this MIME type, if it's an archive MIME type.
static bool supportsTruncating(const QUrl &url)
Returns whether the protocol can be truncated with FileJob::truncate(KIO::filesize_t length).
static int connectTimeout()
Returns the preferred timeout value for remote connections in seconds.
static bool autoResume()
Returns true if partial downloads should be automatically resumed.
static bool markPartial()
Returns true if partial downloads should be marked with a ".part" extension.
static bool isSourceProtocol(const QUrl &url)
Returns whether the protocol can act as a source protocol.
static bool supportsMoving(const QUrl &url)
Returns whether the protocol can move files/objects between different locations.
static bool canCopyToFile(const QUrl &url)
Returns whether the protocol can copy files/objects directly to the filesystem itself.
static int minimumKeepSize()
Returns the minimum file size for keeping aborted downloads.
static bool supportsMakeDir(const QUrl &url)
Returns whether the protocol can create directories/folders.
static bool canDeleteRecursive(const QUrl &url)
Returns whether the protocol can recursively delete directories by itself.
static void reparseConfiguration()
Force a reload of the general config file of KIO workers ( kioslaverc).
static bool supportsWriting(const QUrl &url)
Returns whether the protocol can store data to URLs.
static int responseTimeout()
Returns the preferred response timeout value for remote connecting in seconds.
static int readTimeout()
Returns the preferred timeout value for reading from remote connections in seconds.
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
Type type(const QSqlDatabase &db)
KSERVICE_EXPORT KService::List query(FilterFunc filterFunc)
void lookupHost(const QString &hostName, QObject *receiver, const char *member)
Definition hostinfo.cpp:237
PostalAddress address(const QVariant &location)
QCA_EXPORT QString appName()
const char * constData() const const
bool isEmpty() const const
QDBusMessage call(QDBus::CallMode mode, const QString &method, Args &&... args)
QPair< QHostAddress, int > parseSubnet(const QString &subnet)
QList< QHostAddress > addresses() const const
void clear()
qsizetype count() const const
T & first()
iterator insert(const_iterator before, parameter_type value)
bool isEmpty() const const
void reserve(qsizetype size)
qsizetype size() const const
QString languageToString(Language language)
QList< QNetworkProxy > systemProxyForQuery(const QNetworkProxyQuery &query)
int compare(QLatin1StringView s1, const QString &s2, Qt::CaseSensitivity cs)
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
QString fromLocal8Bit(QByteArrayView str)
QString fromUtf8(QByteArrayView str)
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
QString & insert(qsizetype position, QChar ch)
bool isEmpty() const const
QString number(double n, char format, int precision)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QByteArray toLatin1() const const
QByteArray toLocal8Bit() const const
QString toLower() const const
QString trimmed() const const
QStringView left(qsizetype length) const const
QStringView mid(qsizetype start, qsizetype length) const const
QStringView right(qsizetype length) const const
const_iterator cbegin() const const
const_iterator cend() const const
CaseInsensitive
QString host(ComponentFormattingOptions options) const const
bool isEmpty() const const
bool isValid() const const
int port(int defaultPort) const const
QString scheme() const const
void setHost(const QString &host, ParsingMode mode)
void setPort(int port)
void setScheme(const QString &scheme)
void setUserName(const QString &userName, ParsingMode mode)
QString url(FormattingOptions options) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:18:51 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.