File indexing completed on 2024-09-29 03:36:54
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 1999 Torben Weis <weis@kde.org> 0004 SPDX-FileCopyrightText: 2000 Waldo Bastain <bastain@kde.org> 0005 SPDX-FileCopyrightText: 2000 Dawit Alemayehu <adawit@kde.org> 0006 SPDX-FileCopyrightText: 2008 Jarosław Staniek <staniek@kde.org> 0007 SPDX-FileCopyrightText: 2022 Harald Sitter <sitter@kde.org> 0008 0009 SPDX-License-Identifier: LGPL-2.0-only 0010 */ 0011 0012 #include "kprotocolmanager.h" 0013 #include "kprotocolinfo_p.h" 0014 #include "kprotocolmanager_p.h" 0015 0016 #include "hostinfo.h" 0017 0018 #include <config-kiocore.h> 0019 0020 #include <qplatformdefs.h> 0021 #include <string.h> 0022 #ifdef Q_OS_WIN 0023 #include <qt_windows.h> 0024 #undef interface // windows.h defines this, breaks QtDBus since it has parameters named interface 0025 #else 0026 #include <sys/utsname.h> 0027 #endif 0028 0029 #include <QCache> 0030 #include <QCoreApplication> 0031 #ifndef KIO_ANDROID_STUB 0032 #include <QDBusInterface> 0033 #include <QDBusReply> 0034 #endif 0035 #include <QHostAddress> 0036 #include <QHostInfo> 0037 #include <QLocale> 0038 #include <QMimeDatabase> 0039 #include <QRegularExpression> 0040 #include <QSslSocket> 0041 #include <QStandardPaths> 0042 #include <QUrl> 0043 0044 #if !defined(QT_NO_NETWORKPROXY) && (defined(Q_OS_WIN32) || defined(Q_OS_MAC)) 0045 #include <QNetworkProxyFactory> 0046 #include <QNetworkProxyQuery> 0047 #endif 0048 0049 #include <KConfigGroup> 0050 #include <KSharedConfig> 0051 #include <kio_version.h> 0052 0053 #include <kprotocolinfofactory_p.h> 0054 0055 #include "ioworker_defaults.h" 0056 #include "workerconfig.h" 0057 0058 /* 0059 Domain suffix match. E.g. return true if host is "cuzco.inka.de" and 0060 nplist is "inka.de,hadiko.de" or if host is "localhost" and nplist is 0061 "localhost". 0062 */ 0063 static bool revmatch(const char *host, const char *nplist) 0064 { 0065 if (host == nullptr) { 0066 return false; 0067 } 0068 0069 const char *hptr = host + strlen(host) - 1; 0070 const char *nptr = nplist + strlen(nplist) - 1; 0071 const char *shptr = hptr; 0072 0073 while (nptr >= nplist) { 0074 if (*hptr != *nptr) { 0075 hptr = shptr; 0076 0077 // Try to find another domain or host in the list 0078 while (--nptr >= nplist && *nptr != ',' && *nptr != ' ') { 0079 ; 0080 } 0081 0082 // Strip out multiple spaces and commas 0083 while (--nptr >= nplist && (*nptr == ',' || *nptr == ' ')) { 0084 ; 0085 } 0086 } else { 0087 if (nptr == nplist || nptr[-1] == ',' || nptr[-1] == ' ') { 0088 return true; 0089 } 0090 if (nptr[-1] == '/' && hptr == host) { // "bugs.kde.org" vs "http://bugs.kde.org", the config UI says URLs are ok 0091 return true; 0092 } 0093 if (hptr == host) { // e.g. revmatch("bugs.kde.org","mybugs.kde.org") 0094 return false; 0095 } 0096 0097 hptr--; 0098 nptr--; 0099 } 0100 } 0101 0102 return false; 0103 } 0104 0105 Q_GLOBAL_STATIC(KProtocolManagerPrivate, kProtocolManagerPrivate) 0106 0107 static void syncOnExit() 0108 { 0109 if (kProtocolManagerPrivate.exists()) { 0110 kProtocolManagerPrivate()->sync(); 0111 } 0112 } 0113 0114 KProtocolManagerPrivate::KProtocolManagerPrivate() 0115 { 0116 // post routine since KConfig::sync() breaks if called too late 0117 qAddPostRoutine(syncOnExit); 0118 cachedProxyData.setMaxCost(200); // double the max cost. 0119 } 0120 0121 KProtocolManagerPrivate::~KProtocolManagerPrivate() 0122 { 0123 } 0124 0125 /* 0126 * Returns true if url is in the no proxy list. 0127 */ 0128 bool KProtocolManagerPrivate::shouldIgnoreProxyFor(const QUrl &url) 0129 { 0130 bool isMatch = false; 0131 const ProxyType type = proxyType(); 0132 const bool useRevProxy = ((type == ManualProxy) && useReverseProxy()); 0133 const bool useNoProxyList = (type == ManualProxy || type == EnvVarProxy); 0134 0135 // No proxy only applies to ManualProxy and EnvVarProxy types... 0136 if (useNoProxyList && noProxyFor.isEmpty()) { 0137 QStringList noProxyForList(readNoProxyFor().split(QLatin1Char(','))); 0138 QMutableStringListIterator it(noProxyForList); 0139 while (it.hasNext()) { 0140 SubnetPair subnet = QHostAddress::parseSubnet(it.next()); 0141 if (!subnet.first.isNull()) { 0142 noProxySubnets << subnet; 0143 it.remove(); 0144 } 0145 } 0146 noProxyFor = noProxyForList.join(QLatin1Char(',')); 0147 } 0148 0149 if (!noProxyFor.isEmpty()) { 0150 QString qhost = url.host().toLower(); 0151 QByteArray host = qhost.toLatin1(); 0152 const QString qno_proxy = noProxyFor.trimmed().toLower(); 0153 const QByteArray no_proxy = qno_proxy.toLatin1(); 0154 isMatch = revmatch(host.constData(), no_proxy.constData()); 0155 0156 // If no match is found and the request url has a port 0157 // number, try the combination of "host:port". This allows 0158 // users to enter host:port in the No-proxy-For list. 0159 if (!isMatch && url.port() > 0) { 0160 qhost += QLatin1Char(':') + QString::number(url.port()); 0161 host = qhost.toLatin1(); 0162 isMatch = revmatch(host.constData(), no_proxy.constData()); 0163 } 0164 0165 // If the hostname does not contain a dot, check if 0166 // <local> is part of noProxy. 0167 if (!isMatch && !host.isEmpty() && (strchr(host.constData(), '.') == nullptr)) { 0168 isMatch = revmatch("<local>", no_proxy.constData()); 0169 } 0170 } 0171 0172 const QString host(url.host()); 0173 0174 if (!noProxySubnets.isEmpty() && !host.isEmpty()) { 0175 QHostAddress address(host); 0176 // If request url is not IP address, do a DNS lookup of the hostname. 0177 // TODO: Perhaps we should make configurable ? 0178 if (address.isNull()) { 0179 // qDebug() << "Performing DNS lookup for" << host; 0180 QHostInfo info = KIO::HostInfo::lookupHost(host, 2000); 0181 const QList<QHostAddress> addresses = info.addresses(); 0182 if (!addresses.isEmpty()) { 0183 address = addresses.first(); 0184 } 0185 } 0186 0187 if (!address.isNull()) { 0188 for (const SubnetPair &subnet : std::as_const(noProxySubnets)) { 0189 if (address.isInSubnet(subnet)) { 0190 isMatch = true; 0191 break; 0192 } 0193 } 0194 } 0195 } 0196 0197 return (useRevProxy != isMatch); 0198 } 0199 0200 void KProtocolManagerPrivate::sync() 0201 { 0202 QMutexLocker lock(&mutex); 0203 if (http_config) { 0204 http_config->sync(); 0205 } 0206 if (configPtr) { 0207 configPtr->sync(); 0208 } 0209 } 0210 0211 void KProtocolManager::reparseConfiguration() 0212 { 0213 KProtocolManagerPrivate *d = kProtocolManagerPrivate(); 0214 QMutexLocker lock(&d->mutex); 0215 if (d->http_config) { 0216 d->http_config->reparseConfiguration(); 0217 } 0218 if (d->configPtr) { 0219 d->configPtr->reparseConfiguration(); 0220 } 0221 d->cachedProxyData.clear(); 0222 d->noProxyFor.clear(); 0223 d->modifiers.clear(); 0224 d->useragent.clear(); 0225 lock.unlock(); 0226 0227 // Force the slave config to re-read its config... 0228 KIO::WorkerConfig::self()->reset(); 0229 } 0230 0231 static KSharedConfig::Ptr config() 0232 { 0233 KProtocolManagerPrivate *d = kProtocolManagerPrivate(); 0234 Q_ASSERT(!d->mutex.tryLock()); // the caller must have locked the mutex 0235 if (!d->configPtr) { 0236 d->configPtr = KSharedConfig::openConfig(QStringLiteral("kioslaverc"), KConfig::NoGlobals); 0237 } 0238 return d->configPtr; 0239 } 0240 0241 KProtocolManagerPrivate::ProxyType KProtocolManagerPrivate::proxyType() 0242 { 0243 KConfigGroup cg(config(), QStringLiteral("Proxy Settings")); 0244 return static_cast<ProxyType>(cg.readEntry("ProxyType", 0)); 0245 } 0246 0247 bool KProtocolManagerPrivate::useReverseProxy() 0248 { 0249 KConfigGroup cg(config(), QStringLiteral("Proxy Settings")); 0250 return cg.readEntry("ReversedException", false); 0251 } 0252 0253 QString KProtocolManagerPrivate::readNoProxyFor() 0254 { 0255 QString noProxy = config()->group(QStringLiteral("Proxy Settings")).readEntry("NoProxyFor"); 0256 if (proxyType() == EnvVarProxy) { 0257 noProxy = QString::fromLocal8Bit(qgetenv(noProxy.toLocal8Bit().constData())); 0258 } 0259 return noProxy; 0260 } 0261 0262 QMap<QString, QString> KProtocolManager::entryMap(const QString &group) 0263 { 0264 KProtocolManagerPrivate *d = kProtocolManagerPrivate(); 0265 QMutexLocker lock(&d->mutex); 0266 return config()->entryMap(group); 0267 } 0268 0269 /*=============================== TIMEOUT SETTINGS ==========================*/ 0270 0271 int KProtocolManager::readTimeout() 0272 { 0273 KProtocolManagerPrivate *d = kProtocolManagerPrivate(); 0274 QMutexLocker lock(&d->mutex); 0275 KConfigGroup cg(config(), QString()); 0276 int val = cg.readEntry("ReadTimeout", DEFAULT_READ_TIMEOUT); 0277 return qMax(MIN_TIMEOUT_VALUE, val); 0278 } 0279 0280 int KProtocolManager::connectTimeout() 0281 { 0282 KProtocolManagerPrivate *d = kProtocolManagerPrivate(); 0283 QMutexLocker lock(&d->mutex); 0284 KConfigGroup cg(config(), QString()); 0285 int val = cg.readEntry("ConnectTimeout", DEFAULT_CONNECT_TIMEOUT); 0286 return qMax(MIN_TIMEOUT_VALUE, val); 0287 } 0288 0289 int KProtocolManager::proxyConnectTimeout() 0290 { 0291 KProtocolManagerPrivate *d = kProtocolManagerPrivate(); 0292 QMutexLocker lock(&d->mutex); 0293 KConfigGroup cg(config(), QString()); 0294 int val = cg.readEntry("ProxyConnectTimeout", DEFAULT_PROXY_CONNECT_TIMEOUT); 0295 return qMax(MIN_TIMEOUT_VALUE, val); 0296 } 0297 0298 int KProtocolManager::responseTimeout() 0299 { 0300 KProtocolManagerPrivate *d = kProtocolManagerPrivate(); 0301 QMutexLocker lock(&d->mutex); 0302 KConfigGroup cg(config(), QString()); 0303 int val = cg.readEntry("ResponseTimeout", DEFAULT_RESPONSE_TIMEOUT); 0304 return qMax(MIN_TIMEOUT_VALUE, val); 0305 } 0306 0307 static QString adjustProtocol(const QString &scheme) 0308 { 0309 if (scheme.compare(QLatin1String("webdav"), Qt::CaseInsensitive) == 0) { 0310 return QStringLiteral("http"); 0311 } 0312 0313 if (scheme.compare(QLatin1String("webdavs"), Qt::CaseInsensitive) == 0) { 0314 return QStringLiteral("https"); 0315 } 0316 0317 return scheme.toLower(); 0318 } 0319 0320 QString KProtocolManagerPrivate::proxyFor(const QString &protocol) 0321 { 0322 const QString key = adjustProtocol(protocol) + QLatin1String("Proxy"); 0323 QString proxyStr(config()->group(QStringLiteral("Proxy Settings")).readEntry(key)); 0324 const int index = proxyStr.lastIndexOf(QLatin1Char(' ')); 0325 0326 if (index > -1) { 0327 const QStringView portStr = QStringView(proxyStr).right(proxyStr.length() - index - 1); 0328 const bool isDigits = std::all_of(portStr.cbegin(), portStr.cend(), [](const QChar c) { 0329 return c.isDigit(); 0330 }); 0331 0332 if (isDigits) { 0333 proxyStr = QStringView(proxyStr).left(index) + QLatin1Char(':') + portStr; 0334 } else { 0335 proxyStr.clear(); 0336 } 0337 } 0338 0339 return proxyStr; 0340 } 0341 0342 QStringList KProtocolManagerPrivate::getSystemProxyFor(const QUrl &url) 0343 { 0344 QStringList proxies; 0345 0346 #if !defined(QT_NO_NETWORKPROXY) && (defined(Q_OS_WIN32) || defined(Q_OS_MAC)) 0347 QNetworkProxyQuery query(url); 0348 const QList<QNetworkProxy> proxyList = QNetworkProxyFactory::systemProxyForQuery(query); 0349 proxies.reserve(proxyList.size()); 0350 for (const QNetworkProxy &proxy : proxyList) { 0351 QUrl url; 0352 const QNetworkProxy::ProxyType type = proxy.type(); 0353 if (type == QNetworkProxy::NoProxy || type == QNetworkProxy::DefaultProxy) { 0354 proxies << QLatin1String("DIRECT"); 0355 continue; 0356 } 0357 0358 if (type == QNetworkProxy::HttpProxy || type == QNetworkProxy::HttpCachingProxy) { 0359 url.setScheme(QLatin1String("http")); 0360 } else if (type == QNetworkProxy::Socks5Proxy) { 0361 url.setScheme(QLatin1String("socks")); 0362 } else if (type == QNetworkProxy::FtpCachingProxy) { 0363 url.setScheme(QLatin1String("ftp")); 0364 } 0365 0366 url.setHost(proxy.hostName()); 0367 url.setPort(proxy.port()); 0368 url.setUserName(proxy.user()); 0369 proxies << url.url(); 0370 } 0371 #else 0372 // On Unix/Linux use system environment variables if any are set. 0373 QString proxyVar(proxyFor(url.scheme())); 0374 // Check for SOCKS proxy, if not proxy is found for given url. 0375 if (!proxyVar.isEmpty()) { 0376 const QString proxy(QString::fromLocal8Bit(qgetenv(proxyVar.toLocal8Bit().constData())).trimmed()); 0377 if (!proxy.isEmpty()) { 0378 proxies << proxy; 0379 } 0380 } 0381 // Add the socks proxy as an alternate proxy if it exists, 0382 proxyVar = proxyFor(QStringLiteral("socks")); 0383 if (!proxyVar.isEmpty()) { 0384 QString proxy = QString::fromLocal8Bit(qgetenv(proxyVar.toLocal8Bit().constData())).trimmed(); 0385 // Make sure the scheme of SOCKS proxy is always set to "socks://". 0386 const int index = proxy.indexOf(QLatin1String("://")); 0387 const int offset = (index == -1) ? 0 : (index + 3); 0388 proxy = QLatin1String("socks://") + QStringView(proxy).mid(offset); 0389 if (!proxy.isEmpty()) { 0390 proxies << proxy; 0391 } 0392 } 0393 #endif 0394 return proxies; 0395 } 0396 0397 QStringList KProtocolManagerPrivate::proxiesForUrl(const QUrl &url) 0398 { 0399 QStringList proxyList; 0400 0401 KProtocolManagerPrivate *d = kProtocolManagerPrivate(); 0402 QMutexLocker lock(&d->mutex); 0403 if (!d->shouldIgnoreProxyFor(url)) { 0404 switch (d->proxyType()) { 0405 case PACProxy: 0406 case WPADProxy: { 0407 QUrl u(url); 0408 const QString protocol = adjustProtocol(u.scheme()); 0409 u.setScheme(protocol); 0410 0411 #ifndef KIO_ANDROID_STUB 0412 if (protocol.startsWith(QLatin1String("http")) || protocol.startsWith(QLatin1String("ftp"))) { 0413 QDBusReply<QStringList> reply = 0414 QDBusInterface(QStringLiteral("org.kde.kded6"), QStringLiteral("/modules/proxyscout"), QStringLiteral("org.kde.KPAC.ProxyScout")) 0415 .call(QStringLiteral("proxiesForUrl"), u.toString()); 0416 proxyList = reply; 0417 } 0418 #endif 0419 break; 0420 } 0421 case EnvVarProxy: 0422 proxyList = d->getSystemProxyFor(url); 0423 break; 0424 case ManualProxy: { 0425 QString proxy(d->proxyFor(url.scheme())); 0426 if (!proxy.isEmpty()) { 0427 proxyList << proxy; 0428 } 0429 // Add the socks proxy as an alternate proxy if it exists, 0430 proxy = d->proxyFor(QStringLiteral("socks")); 0431 if (!proxy.isEmpty()) { 0432 // Make sure the scheme of SOCKS proxy is always set to "socks://". 0433 const int index = proxy.indexOf(QLatin1String("://")); 0434 const int offset = (index == -1) ? 0 : (index + 3); 0435 proxy = QLatin1String("socks://") + QStringView(proxy).mid(offset); 0436 proxyList << proxy; 0437 } 0438 break; 0439 } 0440 case NoProxy: 0441 break; 0442 } 0443 } 0444 0445 if (proxyList.isEmpty()) { 0446 proxyList << QStringLiteral("DIRECT"); 0447 } 0448 0449 return proxyList; 0450 } 0451 0452 // Generates proxy cache key from request given url. 0453 static QString extractProxyCacheKeyFromUrl(const QUrl &u) 0454 { 0455 QString key = u.scheme(); 0456 key += u.host(); 0457 0458 if (u.port() > 0) { 0459 key += QString::number(u.port()); 0460 } 0461 return key; 0462 } 0463 0464 QString KProtocolManagerPrivate::workerProtocol(const QUrl &url, QStringList &proxyList) 0465 { 0466 proxyList.clear(); 0467 KProtocolManagerPrivate *d = kProtocolManagerPrivate(); 0468 QMutexLocker lock(&d->mutex); 0469 // Do not perform a proxy lookup for any url classified as a ":local" url or 0470 // one that does not have a host component or if proxy is disabled. 0471 QString protocol(url.scheme()); 0472 if (url.host().isEmpty() || KProtocolInfo::protocolClass(protocol) == QLatin1String(":local") || kProtocolManagerPrivate->proxyType() == NoProxy) { 0473 return protocol; 0474 } 0475 0476 const QString proxyCacheKey = extractProxyCacheKeyFromUrl(url); 0477 0478 // Look for cached proxy information to avoid more work. 0479 if (d->cachedProxyData.contains(proxyCacheKey)) { 0480 KProxyData *data = d->cachedProxyData.object(proxyCacheKey); 0481 proxyList = data->proxyList; 0482 return data->protocol; 0483 } 0484 lock.unlock(); 0485 0486 const QStringList proxies = KProtocolManagerPrivate::proxiesForUrl(url); 0487 const int count = proxies.count(); 0488 0489 if (count > 0 && !(count == 1 && proxies.first() == QLatin1String("DIRECT"))) { 0490 for (const QString &proxy : proxies) { 0491 if (proxy == QLatin1String("DIRECT")) { 0492 proxyList << proxy; 0493 } else { 0494 QUrl u(proxy); 0495 if (!u.isEmpty() && u.isValid() && !u.scheme().isEmpty()) { 0496 proxyList << proxy; 0497 } 0498 } 0499 } 0500 } 0501 0502 // The idea behind worker protocols is not applicable to http 0503 // and webdav protocols as well as protocols unknown to KDE. 0504 /* clang-format off */ 0505 if (!proxyList.isEmpty() 0506 && !protocol.startsWith(QLatin1String("http")) 0507 && !protocol.startsWith(QLatin1String("webdav")) 0508 && KProtocolInfo::isKnownProtocol(protocol)) { /* clang-format on */ 0509 for (const QString &proxy : std::as_const(proxyList)) { 0510 QUrl u(proxy); 0511 if (u.isValid() && KProtocolInfo::isKnownProtocol(u.scheme())) { 0512 protocol = u.scheme(); 0513 break; 0514 } 0515 } 0516 } 0517 0518 lock.relock(); 0519 // cache the proxy information... 0520 d->cachedProxyData.insert(proxyCacheKey, new KProxyData(protocol, proxyList)); 0521 return protocol; 0522 } 0523 0524 /*================================= USER-AGENT SETTINGS =====================*/ 0525 0526 // This is not the OS, but the windowing system, e.g. X11 on Unix/Linux. 0527 static QString platform() 0528 { 0529 #if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN) 0530 return QStringLiteral("X11"); 0531 #elif defined(Q_OS_MAC) 0532 return QStringLiteral("Macintosh"); 0533 #elif defined(Q_OS_WIN) 0534 return QStringLiteral("Windows"); 0535 #else 0536 return QStringLiteral("Unknown"); 0537 #endif 0538 } 0539 0540 QString KProtocolManagerPrivate::defaultUserAgent(const QString &_modifiers) 0541 { 0542 KProtocolManagerPrivate *d = kProtocolManagerPrivate(); 0543 QMutexLocker lock(&d->mutex); 0544 QString modifiers = _modifiers.toLower(); 0545 if (modifiers.isEmpty()) { 0546 modifiers = QStringLiteral("om"); // Show OS, Machine 0547 } 0548 0549 if (d->modifiers == modifiers && !d->useragent.isEmpty()) { 0550 return d->useragent; 0551 } 0552 0553 d->modifiers = modifiers; 0554 0555 QString systemName; 0556 QString systemVersion; 0557 QString machine; 0558 QString supp; 0559 const bool sysInfoFound = KProtocolManagerPrivate::getSystemNameVersionAndMachine(systemName, systemVersion, machine); 0560 0561 supp += platform(); 0562 0563 if (sysInfoFound) { 0564 if (modifiers.contains(QLatin1Char('o'))) { 0565 supp += QLatin1String("; ") + systemName; 0566 if (modifiers.contains(QLatin1Char('v'))) { 0567 supp += QLatin1Char(' ') + systemVersion; 0568 } 0569 0570 if (modifiers.contains(QLatin1Char('m'))) { 0571 supp += QLatin1Char(' ') + machine; 0572 } 0573 } 0574 0575 if (modifiers.contains(QLatin1Char('l'))) { 0576 supp += QLatin1String("; ") + QLocale::languageToString(QLocale().language()); 0577 } 0578 } 0579 0580 QString appName = QCoreApplication::applicationName(); 0581 if (appName.isEmpty() || appName.startsWith(QLatin1String("kcmshell"), Qt::CaseInsensitive)) { 0582 appName = QStringLiteral("KDE"); 0583 } 0584 QString appVersion = QCoreApplication::applicationVersion(); 0585 if (appVersion.isEmpty()) { 0586 appVersion += QLatin1String(KIO_VERSION_STRING); 0587 } 0588 0589 d->useragent = QLatin1String("Mozilla/5.0 (%1) ").arg(supp) 0590 + QLatin1String("KIO/%1.%2 ").arg(QString::number(KIO_VERSION_MAJOR), QString::number(KIO_VERSION_MINOR)) 0591 + QLatin1String("%1/%2").arg(appName, appVersion); 0592 0593 // qDebug() << "USERAGENT STRING:" << d->useragent; 0594 return d->useragent; 0595 } 0596 0597 bool KProtocolManagerPrivate::getSystemNameVersionAndMachine(QString &systemName, QString &systemVersion, QString &machine) 0598 { 0599 #if defined(Q_OS_WIN) 0600 // we do not use unameBuf.sysname information constructed in kdewin32 0601 // because we want to get separate name and version 0602 systemName = QStringLiteral("Windows"); 0603 OSVERSIONINFOEX versioninfo; 0604 ZeroMemory(&versioninfo, sizeof(OSVERSIONINFOEX)); 0605 // try calling GetVersionEx using the OSVERSIONINFOEX, if that fails, try using the OSVERSIONINFO 0606 versioninfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); 0607 bool ok = GetVersionEx((OSVERSIONINFO *)&versioninfo); 0608 if (!ok) { 0609 versioninfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 0610 ok = GetVersionEx((OSVERSIONINFO *)&versioninfo); 0611 } 0612 if (ok) { 0613 systemVersion = QString::number(versioninfo.dwMajorVersion); 0614 systemVersion += QLatin1Char('.'); 0615 systemVersion += QString::number(versioninfo.dwMinorVersion); 0616 } 0617 #else 0618 struct utsname unameBuf; 0619 if (0 != uname(&unameBuf)) { 0620 return false; 0621 } 0622 systemName = QString::fromUtf8(unameBuf.sysname); 0623 systemVersion = QString::fromUtf8(unameBuf.release); 0624 machine = QString::fromUtf8(unameBuf.machine); 0625 #endif 0626 return true; 0627 } 0628 0629 /*==================================== OTHERS ===============================*/ 0630 0631 bool KProtocolManager::markPartial() 0632 { 0633 KProtocolManagerPrivate *d = kProtocolManagerPrivate(); 0634 QMutexLocker lock(&d->mutex); 0635 return config()->group(QString()).readEntry("MarkPartial", true); 0636 } 0637 0638 int KProtocolManager::minimumKeepSize() 0639 { 0640 KProtocolManagerPrivate *d = kProtocolManagerPrivate(); 0641 QMutexLocker lock(&d->mutex); 0642 return config()->group(QString()).readEntry("MinimumKeepSize", 0643 DEFAULT_MINIMUM_KEEP_SIZE); // 5000 byte 0644 } 0645 0646 bool KProtocolManager::autoResume() 0647 { 0648 KProtocolManagerPrivate *d = kProtocolManagerPrivate(); 0649 QMutexLocker lock(&d->mutex); 0650 return config()->group(QString()).readEntry("AutoResume", false); 0651 } 0652 0653 /* =========================== PROTOCOL CAPABILITIES ============== */ 0654 0655 static KProtocolInfoPrivate *findProtocol(const QUrl &url) 0656 { 0657 if (!url.isValid()) { 0658 return nullptr; 0659 } 0660 QString protocol = url.scheme(); 0661 if (!KProtocolInfo::proxiedBy(protocol).isEmpty()) { 0662 QStringList dummy; 0663 protocol = KProtocolManagerPrivate::workerProtocol(url, dummy); 0664 } 0665 0666 return KProtocolInfoFactory::self()->findProtocol(protocol); 0667 } 0668 0669 KProtocolInfo::Type KProtocolManager::inputType(const QUrl &url) 0670 { 0671 KProtocolInfoPrivate *prot = findProtocol(url); 0672 if (!prot) { 0673 return KProtocolInfo::T_NONE; 0674 } 0675 0676 return prot->m_inputType; 0677 } 0678 0679 KProtocolInfo::Type KProtocolManager::outputType(const QUrl &url) 0680 { 0681 KProtocolInfoPrivate *prot = findProtocol(url); 0682 if (!prot) { 0683 return KProtocolInfo::T_NONE; 0684 } 0685 0686 return prot->m_outputType; 0687 } 0688 0689 bool KProtocolManager::isSourceProtocol(const QUrl &url) 0690 { 0691 KProtocolInfoPrivate *prot = findProtocol(url); 0692 if (!prot) { 0693 return false; 0694 } 0695 0696 return prot->m_isSourceProtocol; 0697 } 0698 0699 bool KProtocolManager::supportsListing(const QUrl &url) 0700 { 0701 KProtocolInfoPrivate *prot = findProtocol(url); 0702 if (!prot) { 0703 return false; 0704 } 0705 0706 return prot->m_supportsListing; 0707 } 0708 0709 QStringList KProtocolManager::listing(const QUrl &url) 0710 { 0711 KProtocolInfoPrivate *prot = findProtocol(url); 0712 if (!prot) { 0713 return QStringList(); 0714 } 0715 0716 return prot->m_listing; 0717 } 0718 0719 bool KProtocolManager::supportsReading(const QUrl &url) 0720 { 0721 KProtocolInfoPrivate *prot = findProtocol(url); 0722 if (!prot) { 0723 return false; 0724 } 0725 0726 return prot->m_supportsReading; 0727 } 0728 0729 bool KProtocolManager::supportsWriting(const QUrl &url) 0730 { 0731 KProtocolInfoPrivate *prot = findProtocol(url); 0732 if (!prot) { 0733 return false; 0734 } 0735 0736 return prot->m_supportsWriting; 0737 } 0738 0739 bool KProtocolManager::supportsMakeDir(const QUrl &url) 0740 { 0741 KProtocolInfoPrivate *prot = findProtocol(url); 0742 if (!prot) { 0743 return false; 0744 } 0745 0746 return prot->m_supportsMakeDir; 0747 } 0748 0749 bool KProtocolManager::supportsDeleting(const QUrl &url) 0750 { 0751 KProtocolInfoPrivate *prot = findProtocol(url); 0752 if (!prot) { 0753 return false; 0754 } 0755 0756 return prot->m_supportsDeleting; 0757 } 0758 0759 bool KProtocolManager::supportsLinking(const QUrl &url) 0760 { 0761 KProtocolInfoPrivate *prot = findProtocol(url); 0762 if (!prot) { 0763 return false; 0764 } 0765 0766 return prot->m_supportsLinking; 0767 } 0768 0769 bool KProtocolManager::supportsMoving(const QUrl &url) 0770 { 0771 KProtocolInfoPrivate *prot = findProtocol(url); 0772 if (!prot) { 0773 return false; 0774 } 0775 0776 return prot->m_supportsMoving; 0777 } 0778 0779 bool KProtocolManager::supportsOpening(const QUrl &url) 0780 { 0781 KProtocolInfoPrivate *prot = findProtocol(url); 0782 if (!prot) { 0783 return false; 0784 } 0785 0786 return prot->m_supportsOpening; 0787 } 0788 0789 bool KProtocolManager::supportsTruncating(const QUrl &url) 0790 { 0791 KProtocolInfoPrivate *prot = findProtocol(url); 0792 if (!prot) { 0793 return false; 0794 } 0795 0796 return prot->m_supportsTruncating; 0797 } 0798 0799 bool KProtocolManager::canCopyFromFile(const QUrl &url) 0800 { 0801 KProtocolInfoPrivate *prot = findProtocol(url); 0802 if (!prot) { 0803 return false; 0804 } 0805 0806 return prot->m_canCopyFromFile; 0807 } 0808 0809 bool KProtocolManager::canCopyToFile(const QUrl &url) 0810 { 0811 KProtocolInfoPrivate *prot = findProtocol(url); 0812 if (!prot) { 0813 return false; 0814 } 0815 0816 return prot->m_canCopyToFile; 0817 } 0818 0819 bool KProtocolManager::canRenameFromFile(const QUrl &url) 0820 { 0821 KProtocolInfoPrivate *prot = findProtocol(url); 0822 if (!prot) { 0823 return false; 0824 } 0825 0826 return prot->m_canRenameFromFile; 0827 } 0828 0829 bool KProtocolManager::canRenameToFile(const QUrl &url) 0830 { 0831 KProtocolInfoPrivate *prot = findProtocol(url); 0832 if (!prot) { 0833 return false; 0834 } 0835 0836 return prot->m_canRenameToFile; 0837 } 0838 0839 bool KProtocolManager::canDeleteRecursive(const QUrl &url) 0840 { 0841 KProtocolInfoPrivate *prot = findProtocol(url); 0842 if (!prot) { 0843 return false; 0844 } 0845 0846 return prot->m_canDeleteRecursive; 0847 } 0848 0849 KProtocolInfo::FileNameUsedForCopying KProtocolManager::fileNameUsedForCopying(const QUrl &url) 0850 { 0851 KProtocolInfoPrivate *prot = findProtocol(url); 0852 if (!prot) { 0853 return KProtocolInfo::FromUrl; 0854 } 0855 0856 return prot->m_fileNameUsedForCopying; 0857 } 0858 0859 QString KProtocolManager::defaultMimetype(const QUrl &url) 0860 { 0861 KProtocolInfoPrivate *prot = findProtocol(url); 0862 if (!prot) { 0863 return QString(); 0864 } 0865 0866 return prot->m_defaultMimetype; 0867 } 0868 0869 QString KProtocolManager::protocolForArchiveMimetype(const QString &mimeType) 0870 { 0871 KProtocolManagerPrivate *d = kProtocolManagerPrivate(); 0872 QMutexLocker lock(&d->mutex); 0873 if (d->protocolForArchiveMimetypes.isEmpty()) { 0874 const QList<KProtocolInfoPrivate *> allProtocols = KProtocolInfoFactory::self()->allProtocols(); 0875 for (KProtocolInfoPrivate *allProtocol : allProtocols) { 0876 const QStringList archiveMimetypes = allProtocol->m_archiveMimeTypes; 0877 for (const QString &mime : archiveMimetypes) { 0878 d->protocolForArchiveMimetypes.insert(mime, allProtocol->m_name); 0879 } 0880 } 0881 } 0882 return d->protocolForArchiveMimetypes.value(mimeType); 0883 } 0884 0885 QString KProtocolManager::charsetFor(const QUrl &url) 0886 { 0887 return KIO::WorkerConfig::self()->configData(url.scheme(), url.host(), QStringLiteral("Charset")); 0888 } 0889 0890 bool KProtocolManager::supportsPermissions(const QUrl &url) 0891 { 0892 KProtocolInfoPrivate *prot = findProtocol(url); 0893 if (!prot) { 0894 return true; 0895 } 0896 0897 return prot->m_supportsPermissions; 0898 } 0899 0900 #undef PRIVATE_DATA 0901 0902 #include "moc_kprotocolmanager_p.cpp"