• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.9.5 API Reference
  • KDE Home
  • Contact Us
 

KIO

kprotocolmanager.cpp
Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002    Copyright (C) 1999 Torben Weis <weis@kde.org>
00003    Copyright (C) 2000- Waldo Bastain <bastain@kde.org>
00004    Copyright (C) 2000- Dawit Alemayehu <adawit@kde.org>
00005    Copyright (C) 2008 Jarosław Staniek <staniek@kde.org>
00006 
00007    This library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Library General Public
00009    License version 2 as published by the Free Software Foundation.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.LIB.  If not, write to
00018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019    Boston, MA 02110-1301, USA.
00020 */
00021 
00022 #include "kprotocolmanager.h"
00023 
00024 #include "hostinfo_p.h"
00025 
00026 #include <string.h>
00027 #include <unistd.h>
00028 #include <sys/utsname.h>
00029 
00030 #include <QtCore/QCoreApplication>
00031 #include <QtNetwork/QSslSocket>
00032 #include <QtNetwork/QHostAddress>
00033 #include <QtNetwork/QHostInfo>
00034 #include <QtDBus/QtDBus>
00035 #include <QtCore/QCache>
00036 
00037 #if !defined(QT_NO_NETWORKPROXY) && (defined (Q_OS_WIN32) || defined(Q_OS_MAC))
00038 #include <QtNetwork/QNetworkProxyFactory>
00039 #include <QtNetwork/QNetworkProxyQuery>
00040 #endif
00041 
00042 #include <kdeversion.h>
00043 #include <kdebug.h>
00044 #include <kglobal.h>
00045 #include <klocale.h>
00046 #include <kconfiggroup.h>
00047 #include <ksharedconfig.h>
00048 #include <kstandarddirs.h>
00049 #include <kurl.h>
00050 #include <kmimetypetrader.h>
00051 #include <kprotocolinfofactory.h>
00052 
00053 #include <kio/slaveconfig.h>
00054 #include <kio/ioslave_defaults.h>
00055 #include <kio/http_slave_defaults.h>
00056 
00057 #define QL1S(x)   QLatin1String(x)
00058 #define QL1C(x)   QLatin1Char(x)
00059 
00060 typedef QPair<QHostAddress, int> SubnetPair;
00061 
00062 /*
00063     Domain suffix match. E.g. return true if host is "cuzco.inka.de" and
00064     nplist is "inka.de,hadiko.de" or if host is "localhost" and nplist is
00065     "localhost".
00066 */
00067 static bool revmatch(const char *host, const char *nplist)
00068 {
00069   if (host == 0)
00070     return false;
00071 
00072   const char *hptr = host + strlen( host ) - 1;
00073   const char *nptr = nplist + strlen( nplist ) - 1;
00074   const char *shptr = hptr;
00075 
00076   while ( nptr >= nplist )
00077   {
00078     if ( *hptr != *nptr )
00079     {
00080       hptr = shptr;
00081 
00082       // Try to find another domain or host in the list
00083       while(--nptr>=nplist && *nptr!=',' && *nptr!=' ') ;
00084 
00085       // Strip out multiple spaces and commas
00086       while(--nptr>=nplist && (*nptr==',' || *nptr==' ')) ;
00087     }
00088     else
00089     {
00090       if ( nptr==nplist || nptr[-1]==',' || nptr[-1]==' ')
00091         return true;
00092       if ( nptr[-1]=='/' && hptr == host ) // "bugs.kde.org" vs "http://bugs.kde.org", the config UI says URLs are ok
00093         return true;
00094       if ( hptr == host ) // e.g. revmatch("bugs.kde.org","mybugs.kde.org")
00095         return false;
00096 
00097       hptr--;
00098       nptr--;
00099     }
00100   }
00101 
00102   return false;
00103 }
00104 
00105 class KProxyData : public QObject
00106 {
00107 public:
00108     KProxyData(const QString& slaveProtocol, const QStringList& proxyAddresses)
00109       :protocol(slaveProtocol)
00110       ,proxyList(proxyAddresses) {
00111     }
00112 
00113     void removeAddress(const QString& address) {
00114         proxyList.removeAll(address);
00115     }
00116 
00117     QString protocol;
00118     QStringList proxyList;
00119 };
00120 
00121 class KProtocolManagerPrivate
00122 {
00123 public:
00124    KProtocolManagerPrivate();
00125    ~KProtocolManagerPrivate();
00126     bool shouldIgnoreProxyFor(const KUrl& url);
00127 
00128    KSharedConfig::Ptr config;
00129    KSharedConfig::Ptr http_config;
00130    QString modifiers;
00131    QString useragent;
00132    QString noProxyFor;
00133    QList<SubnetPair> noProxySubnets;
00134    QCache<QString, KProxyData> cachedProxyData;
00135 
00136    QMap<QString /*mimetype*/, QString /*protocol*/> protocolForArchiveMimetypes;
00137 };
00138 
00139 K_GLOBAL_STATIC(KProtocolManagerPrivate, kProtocolManagerPrivate)
00140 
00141 KProtocolManagerPrivate::KProtocolManagerPrivate()
00142 {
00143     // post routine since KConfig::sync() breaks if called too late
00144     qAddPostRoutine(kProtocolManagerPrivate.destroy);
00145     cachedProxyData.setMaxCost(200); // double the max cost.
00146 }
00147 
00148 KProtocolManagerPrivate::~KProtocolManagerPrivate()
00149 {
00150     qRemovePostRoutine(kProtocolManagerPrivate.destroy);
00151 }
00152 
00153 /*
00154  * Returns true if url is in the no proxy list.
00155  */
00156 bool KProtocolManagerPrivate::shouldIgnoreProxyFor(const KUrl& url)
00157 {
00158   bool isMatch = false;
00159   const KProtocolManager::ProxyType type = KProtocolManager::proxyType();
00160   const bool useRevProxy = ((type == KProtocolManager::ManualProxy) && KProtocolManager::useReverseProxy());
00161   const bool useNoProxyList = (type == KProtocolManager::ManualProxy || type == KProtocolManager::EnvVarProxy);
00162 
00163   // No proxy only applies to ManualProxy and EnvVarProxy types...
00164   if (useNoProxyList && noProxyFor.isEmpty()) {
00165       QStringList noProxyForList (KProtocolManager::noProxyFor().split(QL1C(',')));
00166       QMutableStringListIterator it (noProxyForList);
00167       while (it.hasNext()) {
00168           SubnetPair subnet = QHostAddress::parseSubnet(it.next());
00169           if (!subnet.first.isNull()) {
00170               noProxySubnets << subnet;
00171               it.remove();
00172           }
00173       }
00174       noProxyFor =  noProxyForList.join(QL1S(","));
00175   }
00176 
00177   if (!noProxyFor.isEmpty()) {
00178     QString qhost = url.host().toLower();
00179     QByteArray host = qhost.toLatin1();
00180     const QString qno_proxy = noProxyFor.trimmed().toLower();
00181     const QByteArray no_proxy = qno_proxy.toLatin1();
00182     isMatch = revmatch(host, no_proxy);
00183 
00184     // If no match is found and the request url has a port
00185     // number, try the combination of "host:port". This allows
00186     // users to enter host:port in the No-proxy-For list.
00187     if (!isMatch && url.port() > 0) {
00188       qhost += QL1C(':');
00189       qhost += QString::number(url.port());
00190       host = qhost.toLatin1();
00191       isMatch = revmatch (host, no_proxy);
00192     }
00193 
00194     // If the hostname does not contain a dot, check if
00195     // <local> is part of noProxy.
00196     if (!isMatch && !host.isEmpty() && (strchr(host, '.') == NULL)) {
00197       isMatch = revmatch("<local>", no_proxy);
00198     }
00199   }
00200 
00201   const QString host (url.host());
00202 
00203   if (!noProxySubnets.isEmpty() && !host.isEmpty()) {
00204     QHostAddress address (host);
00205     // If request url is not IP address, do a DNS lookup of the hostname.
00206     // TODO: Perhaps we should make configurable ?
00207     if (address.isNull()) {
00208       kDebug() << "Performing DNS lookup for" << host;
00209       QHostInfo info = KIO::HostInfo::lookupHost(host, 2000);
00210       const QList<QHostAddress> addresses = info.addresses();
00211       if (!addresses.isEmpty())
00212         address = addresses.first();
00213     }
00214 
00215     if (!address.isNull()) {
00216       Q_FOREACH(const SubnetPair& subnet, noProxySubnets) {
00217         if (address.isInSubnet(subnet)) {
00218           isMatch = true;
00219           break;
00220         }
00221       }
00222     }
00223   }
00224 
00225   return (useRevProxy != isMatch);
00226 }
00227 
00228 
00229 #define PRIVATE_DATA \
00230 KProtocolManagerPrivate *d = kProtocolManagerPrivate
00231 
00232 void KProtocolManager::reparseConfiguration()
00233 {
00234     PRIVATE_DATA;
00235     if (d->http_config) {
00236         d->http_config->reparseConfiguration();
00237     }
00238     if (d->config) {
00239         d->config->reparseConfiguration();
00240     }
00241     d->cachedProxyData.clear();
00242     d->noProxyFor.clear();
00243     d->modifiers.clear();
00244     d->useragent.clear();
00245 
00246     // Force the slave config to re-read its config...
00247     KIO::SlaveConfig::self()->reset();
00248 }
00249 
00250 KSharedConfig::Ptr KProtocolManager::config()
00251 {
00252   PRIVATE_DATA;
00253   if (!d->config)
00254   {
00255      d->config = KSharedConfig::openConfig("kioslaverc", KConfig::NoGlobals);
00256   }
00257   return d->config;
00258 }
00259 
00260 static KConfigGroup http_config()
00261 {
00262   PRIVATE_DATA;
00263   if (!d->http_config) {
00264      d->http_config = KSharedConfig::openConfig("kio_httprc", KConfig::NoGlobals);
00265   }
00266   return KConfigGroup(d->http_config, QString());
00267 }
00268 
00269 /*=============================== TIMEOUT SETTINGS ==========================*/
00270 
00271 int KProtocolManager::readTimeout()
00272 {
00273   KConfigGroup cg( config(), QString() );
00274   int val = cg.readEntry( "ReadTimeout", DEFAULT_READ_TIMEOUT );
00275   return qMax(MIN_TIMEOUT_VALUE, val);
00276 }
00277 
00278 int KProtocolManager::connectTimeout()
00279 {
00280   KConfigGroup cg( config(), QString() );
00281   int val = cg.readEntry( "ConnectTimeout", DEFAULT_CONNECT_TIMEOUT );
00282   return qMax(MIN_TIMEOUT_VALUE, val);
00283 }
00284 
00285 int KProtocolManager::proxyConnectTimeout()
00286 {
00287   KConfigGroup cg( config(), QString() );
00288   int val = cg.readEntry( "ProxyConnectTimeout", DEFAULT_PROXY_CONNECT_TIMEOUT );
00289   return qMax(MIN_TIMEOUT_VALUE, val);
00290 }
00291 
00292 int KProtocolManager::responseTimeout()
00293 {
00294   KConfigGroup cg( config(), QString() );
00295   int val = cg.readEntry( "ResponseTimeout", DEFAULT_RESPONSE_TIMEOUT );
00296   return qMax(MIN_TIMEOUT_VALUE, val);
00297 }
00298 
00299 /*========================== PROXY SETTINGS =================================*/
00300 
00301 bool KProtocolManager::useProxy()
00302 {
00303   return proxyType() != NoProxy;
00304 }
00305 
00306 bool KProtocolManager::useReverseProxy()
00307 {
00308   KConfigGroup cg(config(), "Proxy Settings" );
00309   return cg.readEntry("ReversedException", false);
00310 }
00311 
00312 KProtocolManager::ProxyType KProtocolManager::proxyType()
00313 {
00314   KConfigGroup cg(config(), "Proxy Settings" );
00315   return static_cast<ProxyType>(cg.readEntry( "ProxyType" , 0));
00316 }
00317 
00318 KProtocolManager::ProxyAuthMode KProtocolManager::proxyAuthMode()
00319 {
00320   KConfigGroup cg(config(), "Proxy Settings" );
00321   return static_cast<ProxyAuthMode>(cg.readEntry( "AuthMode" , 0));
00322 }
00323 
00324 /*========================== CACHING =====================================*/
00325 
00326 bool KProtocolManager::useCache()
00327 {
00328   return http_config().readEntry( "UseCache", true );
00329 }
00330 
00331 KIO::CacheControl KProtocolManager::cacheControl()
00332 {
00333   QString tmp = http_config().readEntry("cache");
00334   if (tmp.isEmpty())
00335     return DEFAULT_CACHE_CONTROL;
00336   return KIO::parseCacheControl(tmp);
00337 }
00338 
00339 QString KProtocolManager::cacheDir()
00340 {
00341   return http_config().readPathEntry("CacheDir", KGlobal::dirs()->saveLocation("cache","http"));
00342 }
00343 
00344 int KProtocolManager::maxCacheAge()
00345 {
00346   return http_config().readEntry( "MaxCacheAge", DEFAULT_MAX_CACHE_AGE ); // 14 days
00347 }
00348 
00349 int KProtocolManager::maxCacheSize()
00350 {
00351   return http_config().readEntry( "MaxCacheSize", DEFAULT_MAX_CACHE_SIZE ); // 5 MB
00352 }
00353 
00354 QString KProtocolManager::noProxyFor()
00355 {
00356   QString noProxy = config()->group("Proxy Settings").readEntry( "NoProxyFor" );
00357   if (proxyType() == EnvVarProxy)
00358     noProxy = QString::fromLocal8Bit(qgetenv(noProxy.toLocal8Bit()));
00359 
00360   return noProxy;
00361 }
00362 
00363 static QString adjustProtocol(const QString& scheme)
00364 {
00365   if (scheme.compare(QL1S("webdav"), Qt::CaseInsensitive) == 0)
00366     return QL1S("http");
00367 
00368   if (scheme.compare(QL1S("webdavs"), Qt::CaseInsensitive) == 0)
00369     return QL1S("https");
00370 
00371   return scheme.toLower();
00372 }
00373 
00374 QString KProtocolManager::proxyFor( const QString& protocol )
00375 {
00376   const QString key = adjustProtocol(protocol) + QL1S("Proxy");
00377   QString proxyStr (config()->group("Proxy Settings").readEntry(key));
00378   const int index = proxyStr.lastIndexOf(QL1C(' '));
00379 
00380   if (index > -1)  {
00381       bool ok = false;
00382       const QString portStr(proxyStr.right(proxyStr.length() - index - 1));
00383       portStr.toInt(&ok);
00384       if (ok) {
00385           proxyStr = proxyStr.left(index) + QL1C(':') + portStr;
00386       } else {
00387           proxyStr.clear();
00388       }
00389   }
00390 
00391   return proxyStr;
00392 }
00393 
00394 QString KProtocolManager::proxyForUrl( const KUrl &url )
00395 {
00396   const QStringList proxies = proxiesForUrl(url);
00397 
00398   if (proxies.isEmpty())
00399     return QString();
00400 
00401   return proxies.first();
00402 }
00403 
00404 static QStringList getSystemProxyFor( const KUrl& url )
00405 {
00406   QStringList proxies;
00407 
00408 #if !defined(QT_NO_NETWORKPROXY) && (defined(Q_OS_WIN32) || defined(Q_OS_MAC))
00409   QNetworkProxyQuery query ( url );
00410   const QList<QNetworkProxy> proxyList = QNetworkProxyFactory::systemProxyForQuery(query);
00411   Q_FOREACH(const QNetworkProxy& proxy, proxyList)
00412   {
00413     KUrl url;
00414     const QNetworkProxy::ProxyType type = proxy.type();
00415     if (type == QNetworkProxy::NoProxy || type == QNetworkProxy::DefaultProxy)
00416     {
00417       proxies << QL1S("DIRECT");
00418       continue;
00419     }
00420 
00421     if (type == QNetworkProxy::HttpProxy || type == QNetworkProxy::HttpCachingProxy)
00422       url.setProtocol(QL1S("http"));
00423     else if (type == QNetworkProxy::Socks5Proxy)
00424       url.setProtocol(QL1S("socks"));
00425     else if (type == QNetworkProxy::FtpCachingProxy)
00426       url.setProtocol(QL1S("ftp"));
00427 
00428     url.setHost(proxy.hostName());
00429     url.setPort(proxy.port());
00430     url.setUser(proxy.user());
00431     proxies << url.url();
00432   }
00433 #else
00434   // On Unix/Linux use system environment variables if any are set.
00435   QString proxyVar (KProtocolManager::proxyFor(url.protocol()));
00436   // Check for SOCKS proxy, if not proxy is found for given url.
00437   if (!proxyVar.isEmpty()) {
00438     const QString proxy (QString::fromLocal8Bit(qgetenv(proxyVar.toLocal8Bit())).trimmed());
00439     if (!proxy.isEmpty()) {
00440       proxies << proxy;
00441     }
00442   }
00443   // Add the socks proxy as an alternate proxy if it exists,
00444   proxyVar = KProtocolManager::proxyFor(QL1S("socks"));
00445   if (!proxyVar.isEmpty()) {
00446     QString proxy = QString::fromLocal8Bit(qgetenv(proxyVar.toLocal8Bit())).trimmed();
00447     // Make sure the scheme of SOCKS proxy is always set to "socks://".
00448     const int index = proxy.indexOf(QL1S("://"));
00449     proxy = QL1S("socks://") + (index == -1 ? proxy : proxy.mid(index+3));
00450     if (!proxy.isEmpty()) {
00451       proxies << proxy;
00452     }
00453   }
00454 #endif
00455   return proxies;
00456 }
00457 
00458 QStringList KProtocolManager::proxiesForUrl( const KUrl &url )
00459 {
00460   QStringList proxyList;
00461 
00462   PRIVATE_DATA;
00463   if (!d->shouldIgnoreProxyFor(url)) {
00464     switch (proxyType())
00465     {
00466       case PACProxy:
00467       case WPADProxy:
00468       {
00469         KUrl u (url);
00470         const QString protocol = adjustProtocol(u.protocol());
00471         u.setProtocol(protocol);
00472 
00473         if (protocol.startsWith(QL1S("http"), Qt::CaseInsensitive) ||
00474             protocol.startsWith(QL1S("ftp"), Qt::CaseInsensitive)) {
00475           QDBusReply<QStringList> reply = QDBusInterface(QL1S("org.kde.kded"),
00476                                                          QL1S("/modules/proxyscout"),
00477                                                          QL1S("org.kde.KPAC.ProxyScout"))
00478                                           .call(QL1S("proxiesForUrl"), u.url());
00479           proxyList = reply;
00480         }
00481         break;
00482       }
00483       case EnvVarProxy:
00484         proxyList = getSystemProxyFor( url );
00485         break;
00486       case ManualProxy:
00487       {
00488         QString proxy (proxyFor(url.protocol()));
00489         if (!proxy.isEmpty())
00490           proxyList << proxy;
00491         // Add the socks proxy as an alternate proxy if it exists,
00492         proxy = proxyFor(QL1S("socks"));
00493         if (!proxy.isEmpty()) {
00494           // Make sure the scheme of SOCKS proxy is always set to "socks://".
00495           const int index = proxy.indexOf(QL1S("://"));
00496           proxy = QL1S("socks://") + (index == -1 ? proxy : proxy.mid(index+3));
00497           proxyList << proxy;
00498         }
00499       }
00500       break;
00501       case NoProxy:
00502       default:
00503         break;
00504     }
00505   }
00506 
00507   if (proxyList.isEmpty()) {
00508     proxyList << QL1S("DIRECT");
00509   }
00510 
00511   return proxyList;
00512 }
00513 
00514 void KProtocolManager::badProxy( const QString &proxy )
00515 {
00516   QDBusInterface( QL1S("org.kde.kded"), QL1S("/modules/proxyscout"))
00517       .asyncCall(QL1S("blackListProxy"), proxy);
00518 
00519   PRIVATE_DATA;
00520   const QStringList keys (d->cachedProxyData.keys());
00521   Q_FOREACH(const QString& key, keys) {
00522       d->cachedProxyData[key]->removeAddress(proxy);
00523   }
00524 }
00525 
00526 QString KProtocolManager::slaveProtocol(const KUrl &url, QString &proxy)
00527 {
00528     QStringList proxyList;
00529     const QString protocol = KProtocolManager::slaveProtocol(url, proxyList);
00530     if (!proxyList.isEmpty()) {
00531       proxy = proxyList.first();
00532     }
00533     return protocol;
00534 }
00535 
00536 // Generates proxy cache key from request given url.
00537 static void extractProxyCacheKeyFromUrl(const KUrl& u, QString* key)
00538 {
00539     if (!key)
00540         return;
00541 
00542     *key = u.protocol();
00543     *key += u.host();
00544 
00545     if (u.port() > 0)
00546         *key += QString::number(u.port());
00547 }
00548 
00549 QString KProtocolManager::slaveProtocol(const KUrl &url, QStringList &proxyList)
00550 {
00551   if (url.hasSubUrl()) { // We don't want the suburl's protocol
00552       const KUrl::List list = KUrl::split(url);
00553       return slaveProtocol(list.last(), proxyList);
00554   }
00555 
00556   proxyList.clear();
00557 
00558   // Do not perform a proxy lookup for any url classified as a ":local" url or
00559   // one that does not have a host component or if proxy is disabled.
00560   QString protocol (url.protocol());
00561   if (!url.hasHost()
00562       || KProtocolInfo::protocolClass(protocol) == QL1S(":local")
00563       || KProtocolManager::proxyType() == KProtocolManager::NoProxy) {
00564       return protocol;
00565   }
00566 
00567   QString proxyCacheKey;
00568   extractProxyCacheKeyFromUrl(url, &proxyCacheKey);
00569 
00570   PRIVATE_DATA;
00571   // Look for cached proxy information to avoid more work.
00572   if (d->cachedProxyData.contains(proxyCacheKey)) {
00573       KProxyData* data = d->cachedProxyData.object(proxyCacheKey);
00574       proxyList = data->proxyList;
00575       return data->protocol;
00576   }
00577 
00578   const QStringList proxies = proxiesForUrl(url);
00579   const int count = proxies.count();
00580 
00581   if (count > 0 && !(count == 1 && proxies.first() == QL1S("DIRECT"))) {
00582       Q_FOREACH(const QString& proxy, proxies) {
00583           if (proxy == QL1S("DIRECT")) {
00584               proxyList << proxy;
00585           } else {
00586               KUrl u (proxy);
00587               if (!u.isEmpty() && u.isValid() && !u.protocol().isEmpty()) {
00588                   proxyList << proxy;
00589               }
00590           }
00591       }
00592   }
00593 
00594   // The idea behind slave protocols is not applicable to http
00595   // and webdav protocols as well as protocols unknown to KDE.
00596   if (!proxyList.isEmpty()
00597       && !protocol.startsWith(QL1S("http"))
00598       && !protocol.startsWith(QL1S("webdav"))
00599       && KProtocolInfo::isKnownProtocol(protocol)) {
00600       Q_FOREACH(const QString& proxy, proxyList) {
00601           KUrl u (proxy);
00602           if (u.isValid() && KProtocolInfo::isKnownProtocol(u.protocol())) {
00603               protocol = u.protocol();
00604               break;
00605           }
00606       }
00607   }
00608 
00609   // cache the proxy information...
00610   d->cachedProxyData.insert(proxyCacheKey, new KProxyData(protocol, proxyList));
00611   return protocol;
00612 }
00613 
00614 /*================================= USER-AGENT SETTINGS =====================*/
00615 
00616 QString KProtocolManager::userAgentForHost( const QString& hostname )
00617 {
00618   const QString sendUserAgent = KIO::SlaveConfig::self()->configData("http", hostname.toLower(), "SendUserAgent").toLower();
00619   if (sendUserAgent == QL1S("false"))
00620      return QString();
00621 
00622   const QString useragent = KIO::SlaveConfig::self()->configData("http", hostname.toLower(), "UserAgent");
00623 
00624   // Return the default user-agent if none is specified
00625   // for the requested host.
00626   if (useragent.isEmpty())
00627     return defaultUserAgent();
00628 
00629   return useragent;
00630 }
00631 
00632 QString KProtocolManager::defaultUserAgent( )
00633 {
00634   const QString modifiers = KIO::SlaveConfig::self()->configData("http", QString(), "UserAgentKeys");
00635   return defaultUserAgent(modifiers);
00636 }
00637 
00638 static QString defaultUserAgentFromPreferredService()
00639 {
00640   QString agentStr;
00641 
00642   // Check if the default COMPONENT contains a custom default UA string...
00643   KService::Ptr service = KMimeTypeTrader::self()->preferredService(QL1S("text/html"),
00644                                                       QL1S("KParts/ReadOnlyPart"));
00645   if (service && service->showInKDE())
00646     agentStr = service->property(QL1S("X-KDE-Default-UserAgent"),
00647                                  QVariant::String).toString();
00648   return agentStr;
00649 }
00650 
00651 static QString platform()
00652 {
00653 #if defined(Q_WS_X11)
00654     return QL1S("X11");
00655 #elif defined(Q_WS_MAC)
00656     return QL1S("Macintosh");
00657 #elif defined(Q_WS_WIN)
00658      return QL1S("Windows");
00659 #elif defined(Q_WS_S60)
00660      return QL1S("Symbian");
00661 #endif
00662 }
00663 
00664 QString KProtocolManager::defaultUserAgent( const QString &_modifiers )
00665 {
00666     PRIVATE_DATA;
00667   QString modifiers = _modifiers.toLower();
00668   if (modifiers.isEmpty())
00669     modifiers = DEFAULT_USER_AGENT_KEYS;
00670 
00671   if (d->modifiers == modifiers && !d->useragent.isEmpty())
00672     return d->useragent;
00673 
00674   d->modifiers = modifiers;
00675 
00676   /*
00677      The following code attempts to determine the default user agent string
00678      from the 'X-KDE-UA-DEFAULT-STRING' property of the desktop file
00679      for the preferred service that was configured to handle the 'text/html'
00680      mime type. If the prefered service's desktop file does not specify this
00681      property, the long standing default user agent string will be used.
00682      The following keyword placeholders are automatically converted when the
00683      user agent string is read from the property:
00684 
00685      %SECURITY%      Expands to"N" when SSL is not supported, otherwise it is ignored.
00686      %OSNAME%        Expands to operating system name, e.g. Linux.
00687      %OSVERSION%     Expands to operating system version, e.g. 2.6.32
00688      %SYSTYPE%       Expands to machine or system type, e.g. i386
00689      %PLATFORM%      Expands to windowing system, e.g. X11 on Unix/Linux.
00690      %LANGUAGE%      Expands to default language in use, e.g. en-US.
00691      %APPVERSION%    Expands to QCoreApplication applicationName()/applicationVerison(),
00692                      e.g. Konqueror/4.5.0. If application name and/or application version
00693                      number are not set, then "KDE" and the runtime KDE version numbers
00694                      are used respectively.
00695 
00696      All of the keywords are handled case-insensitively.
00697   */
00698 
00699   QString systemName, systemVersion, machine, supp;
00700   const bool sysInfoFound = getSystemNameVersionAndMachine( systemName, systemVersion, machine );
00701   QString agentStr = defaultUserAgentFromPreferredService();
00702 
00703   if (agentStr.isEmpty())
00704   {
00705     supp += platform();
00706 
00707     if (sysInfoFound)
00708     {
00709       if (modifiers.contains('o'))
00710       {
00711         supp += QL1S("; ");
00712         supp += systemName;
00713         if (modifiers.contains('v'))
00714         {
00715           supp += QL1C(' ');
00716           supp += systemVersion;
00717         }
00718 
00719         if (modifiers.contains('m'))
00720         {
00721           supp += QL1C(' ');
00722           supp += machine;
00723         }
00724       }
00725 
00726       if (modifiers.contains('l'))
00727       {
00728         supp += QL1S("; ");
00729         supp += KGlobal::locale()->language();
00730       }
00731     }
00732 
00733     // Full format: Mozilla/5.0 (Linux
00734     d->useragent = QL1S("Mozilla/5.0 (");
00735     d->useragent += supp;
00736     d->useragent += QL1S(") KHTML/");
00737     d->useragent += QString::number(KDE::versionMajor());
00738     d->useragent += QL1C('.');
00739     d->useragent += QString::number(KDE::versionMinor());
00740     d->useragent += QL1C('.');
00741     d->useragent += QString::number(KDE::versionRelease());
00742     d->useragent += QL1S(" (like Gecko) Konqueror/");
00743     d->useragent += QString::number(KDE::versionMajor());
00744     d->useragent += QL1C('.');
00745     d->useragent += QString::number(KDE::versionMinor());
00746   }
00747   else
00748   {
00749     QString appName = QCoreApplication::applicationName();
00750     if (appName.isEmpty() || appName.startsWith(QL1S("kcmshell"), Qt::CaseInsensitive))
00751       appName = QL1S ("KDE");
00752 
00753     QString appVersion = QCoreApplication::applicationVersion();
00754     if (appVersion.isEmpty()) {
00755       appVersion += QString::number(KDE::versionMajor());
00756       appVersion += QL1C('.');
00757       appVersion += QString::number(KDE::versionMinor());
00758       appVersion += QL1C('.');
00759       appVersion += QString::number(KDE::versionRelease());
00760     }
00761 
00762     appName += QL1C('/');
00763     appName += appVersion;
00764 
00765     agentStr.replace(QL1S("%appversion%"), appName, Qt::CaseInsensitive);
00766 
00767     if (!QSslSocket::supportsSsl())
00768       agentStr.replace(QL1S("%security%"), QL1S("N"), Qt::CaseInsensitive);
00769     else
00770       agentStr.remove(QL1S("%security%"), Qt::CaseInsensitive);
00771 
00772     if (sysInfoFound)
00773     {
00774       // Platform (e.g. X11). It is no longer configurable from UI.
00775       agentStr.replace(QL1S("%platform%"), platform(), Qt::CaseInsensitive);
00776 
00777       // Operating system (e.g. Linux)
00778       if (modifiers.contains('o'))
00779       {
00780         agentStr.replace(QL1S("%osname%"), systemName, Qt::CaseInsensitive);
00781 
00782         // OS version (e.g. 2.6.36)
00783         if (modifiers.contains('v'))
00784           agentStr.replace(QL1S("%osversion%"), systemVersion, Qt::CaseInsensitive);
00785         else
00786           agentStr.remove(QL1S("%osversion%"), Qt::CaseInsensitive);
00787 
00788         // Machine type (i686, x86-64, etc.)
00789         if (modifiers.contains('m'))
00790           agentStr.replace(QL1S("%systype%"), machine, Qt::CaseInsensitive);
00791         else
00792           agentStr.remove(QL1S("%systype%"), Qt::CaseInsensitive);
00793       }
00794       else
00795       {
00796          agentStr.remove(QL1S("%osname%"), Qt::CaseInsensitive);
00797          agentStr.remove(QL1S("%osversion%"), Qt::CaseInsensitive);
00798          agentStr.remove(QL1S("%systype%"), Qt::CaseInsensitive);
00799       }
00800 
00801       // Language (e.g. en_US)
00802       if (modifiers.contains('l'))
00803         agentStr.replace(QL1S("%language%"), KGlobal::locale()->language(), Qt::CaseInsensitive);
00804       else
00805         agentStr.remove(QL1S("%language%"), Qt::CaseInsensitive);
00806 
00807       // Clean up unnecessary separators that could be left over from the
00808       // possible keyword removal above...
00809       agentStr.replace(QRegExp("[(]\\s*[;]\\s*"), QL1S("("));
00810       agentStr.replace(QRegExp("[;]\\s*[;]\\s*"), QL1S("; "));
00811       agentStr.replace(QRegExp("\\s*[;]\\s*[)]"), QL1S(")"));
00812     }
00813     else
00814     {
00815       agentStr.remove(QL1S("%osname%"));
00816       agentStr.remove(QL1S("%osversion%"));
00817       agentStr.remove(QL1S("%platform%"));
00818       agentStr.remove(QL1S("%systype%"));
00819       agentStr.remove(QL1S("%language%"));
00820     }
00821 
00822     d->useragent = agentStr.simplified();
00823   }
00824 
00825   //kDebug() << "USERAGENT STRING:" << d->useragent;
00826   return d->useragent;
00827 }
00828 
00829 QString KProtocolManager::userAgentForApplication( const QString &appName, const QString& appVersion,
00830   const QStringList& extraInfo )
00831 {
00832   QString systemName, systemVersion, machine, info;
00833 
00834   if (getSystemNameVersionAndMachine( systemName, systemVersion, machine ))
00835   {
00836     info +=  systemName;
00837     info += QL1C('/');
00838     info += systemVersion;
00839     info += QL1S("; ");
00840   }
00841 
00842   info += QL1S("KDE/");
00843   info += QString::number(KDE::versionMajor());
00844   info += QL1C('.');
00845   info += QString::number(KDE::versionMinor());
00846   info += QL1C('.');
00847   info += QString::number(KDE::versionRelease());
00848 
00849   if (!machine.isEmpty())
00850   {
00851     info += QL1S("; ");
00852     info += machine;
00853   }
00854 
00855   info += QL1S("; ");
00856   info += extraInfo.join(QL1S("; "));
00857 
00858   return (appName + QL1C('/') + appVersion + QL1S(" (") + info + QL1C(')'));
00859 }
00860 
00861 bool KProtocolManager::getSystemNameVersionAndMachine(
00862   QString& systemName, QString& systemVersion, QString& machine )
00863 {
00864   struct utsname unameBuf;
00865   if ( 0 != uname( &unameBuf ) )
00866     return false;
00867 #if defined(Q_WS_WIN) && !defined(_WIN32_WCE)
00868   // we do not use unameBuf.sysname information constructed in kdewin32
00869   // because we want to get separate name and version
00870   systemName = QL1S( "Windows" );
00871   OSVERSIONINFOEX versioninfo;
00872   ZeroMemory(&versioninfo, sizeof(OSVERSIONINFOEX));
00873   // try calling GetVersionEx using the OSVERSIONINFOEX, if that fails, try using the OSVERSIONINFO
00874   versioninfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
00875   bool ok = GetVersionEx( (OSVERSIONINFO *) &versioninfo );
00876   if ( !ok ) {
00877     versioninfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
00878     ok = GetVersionEx( (OSVERSIONINFO *) &versioninfo );
00879   }
00880   if ( ok ) {
00881     systemVersion = QString::number(versioninfo.dwMajorVersion);
00882     systemVersion +=  QL1C('.');
00883     systemVersion += QString::number(versioninfo.dwMinorVersion);
00884   }
00885 #else
00886   systemName = unameBuf.sysname;
00887   systemVersion = unameBuf.release;
00888 #endif
00889   machine = unameBuf.machine;
00890   return true;
00891 }
00892 
00893 QString KProtocolManager::acceptLanguagesHeader()
00894 {
00895   static const QString &english = KGlobal::staticQString("en");
00896 
00897   // User's desktop language preference.
00898   QStringList languageList = KGlobal::locale()->languageList();
00899 
00900   // Replace possible "C" in the language list with "en", unless "en" is
00901   // already pressent. This is to keep user's priorities in order.
00902   // If afterwards "en" is still not present, append it.
00903   int idx = languageList.indexOf(QString::fromLatin1("C"));
00904   if (idx != -1)
00905   {
00906     if (languageList.contains(english))
00907       languageList.removeAt(idx);
00908     else
00909       languageList[idx] = english;
00910   }
00911   if (!languageList.contains(english))
00912     languageList += english;
00913 
00914   // Some languages may have web codes different from locale codes,
00915   // read them from the config and insert in proper order.
00916   KConfig acclangConf("accept-languages.codes", KConfig::NoGlobals);
00917   KConfigGroup replacementCodes(&acclangConf, "ReplacementCodes");
00918   QStringList languageListFinal;
00919   Q_FOREACH (const QString &lang, languageList)
00920   {
00921     const QStringList langs = replacementCodes.readEntry(lang, QStringList());
00922     if (langs.isEmpty())
00923       languageListFinal += lang;
00924     else
00925       languageListFinal += langs;
00926   }
00927 
00928   // The header is composed of comma separated languages, with an optional
00929   // associated priority estimate (q=1..0) defaulting to 1.
00930   // As our language tags are already sorted by priority, we'll just decrease
00931   // the value evenly
00932   int prio = 10;
00933   QString header;
00934   Q_FOREACH (const QString &lang,languageListFinal) {
00935       header += lang;
00936       if (prio < 10) {
00937           header += QL1S(";q=0.");
00938           header += QString::number(prio);
00939       }
00940       // do not add cosmetic whitespace in here : it is less compatible (#220677)
00941       header += QL1S(",");
00942       if (prio > 1)
00943           --prio;
00944   }
00945   header.chop(1);
00946 
00947   // Some of the languages may have country specifier delimited by
00948   // underscore, or modifier delimited by at-sign.
00949   // The header should use dashes instead.
00950   header.replace('_', '-');
00951   header.replace('@', '-');
00952 
00953   return header;
00954 }
00955 
00956 /*==================================== OTHERS ===============================*/
00957 
00958 bool KProtocolManager::markPartial()
00959 {
00960   return config()->group(QByteArray()).readEntry( "MarkPartial", true );
00961 }
00962 
00963 int KProtocolManager::minimumKeepSize()
00964 {
00965     return config()->group(QByteArray()).readEntry( "MinimumKeepSize",
00966                                                 DEFAULT_MINIMUM_KEEP_SIZE ); // 5000 byte
00967 }
00968 
00969 bool KProtocolManager::autoResume()
00970 {
00971   return config()->group(QByteArray()).readEntry( "AutoResume", false );
00972 }
00973 
00974 bool KProtocolManager::persistentConnections()
00975 {
00976   return config()->group(QByteArray()).readEntry( "PersistentConnections", true );
00977 }
00978 
00979 bool KProtocolManager::persistentProxyConnection()
00980 {
00981   return config()->group(QByteArray()).readEntry( "PersistentProxyConnection", false );
00982 }
00983 
00984 QString KProtocolManager::proxyConfigScript()
00985 {
00986   return config()->group("Proxy Settings").readEntry( "Proxy Config Script" );
00987 }
00988 
00989 /* =========================== PROTOCOL CAPABILITIES ============== */
00990 
00991 static KProtocolInfo::Ptr findProtocol(const KUrl &url)
00992 {
00993    QString protocol = url.protocol();
00994 
00995    if ( !KProtocolInfo::proxiedBy( protocol ).isEmpty() )
00996    {
00997       QString dummy;
00998       protocol = KProtocolManager::slaveProtocol(url, dummy);
00999    }
01000 
01001    return KProtocolInfoFactory::self()->findProtocol(protocol);
01002 }
01003 
01004 
01005 KProtocolInfo::Type KProtocolManager::inputType( const KUrl &url )
01006 {
01007   KProtocolInfo::Ptr prot = findProtocol(url);
01008   if ( !prot )
01009     return KProtocolInfo::T_NONE;
01010 
01011   return prot->m_inputType;
01012 }
01013 
01014 KProtocolInfo::Type KProtocolManager::outputType( const KUrl &url )
01015 {
01016   KProtocolInfo::Ptr prot = findProtocol(url);
01017   if ( !prot )
01018     return KProtocolInfo::T_NONE;
01019 
01020   return prot->m_outputType;
01021 }
01022 
01023 
01024 bool KProtocolManager::isSourceProtocol( const KUrl &url )
01025 {
01026   KProtocolInfo::Ptr prot = findProtocol(url);
01027   if ( !prot )
01028     return false;
01029 
01030   return prot->m_isSourceProtocol;
01031 }
01032 
01033 bool KProtocolManager::supportsListing( const KUrl &url )
01034 {
01035   KProtocolInfo::Ptr prot = findProtocol(url);
01036   if ( !prot )
01037     return false;
01038 
01039   return prot->m_supportsListing;
01040 }
01041 
01042 QStringList KProtocolManager::listing( const KUrl &url )
01043 {
01044   KProtocolInfo::Ptr prot = findProtocol(url);
01045   if ( !prot )
01046     return QStringList();
01047 
01048   return prot->m_listing;
01049 }
01050 
01051 bool KProtocolManager::supportsReading( const KUrl &url )
01052 {
01053   KProtocolInfo::Ptr prot = findProtocol(url);
01054   if ( !prot )
01055     return false;
01056 
01057   return prot->m_supportsReading;
01058 }
01059 
01060 bool KProtocolManager::supportsWriting( const KUrl &url )
01061 {
01062   KProtocolInfo::Ptr prot = findProtocol(url);
01063   if ( !prot )
01064     return false;
01065 
01066   return prot->m_supportsWriting;
01067 }
01068 
01069 bool KProtocolManager::supportsMakeDir( const KUrl &url )
01070 {
01071   KProtocolInfo::Ptr prot = findProtocol(url);
01072   if ( !prot )
01073     return false;
01074 
01075   return prot->m_supportsMakeDir;
01076 }
01077 
01078 bool KProtocolManager::supportsDeleting( const KUrl &url )
01079 {
01080   KProtocolInfo::Ptr prot = findProtocol(url);
01081   if ( !prot )
01082     return false;
01083 
01084   return prot->m_supportsDeleting;
01085 }
01086 
01087 bool KProtocolManager::supportsLinking( const KUrl &url )
01088 {
01089   KProtocolInfo::Ptr prot = findProtocol(url);
01090   if ( !prot )
01091     return false;
01092 
01093   return prot->m_supportsLinking;
01094 }
01095 
01096 bool KProtocolManager::supportsMoving( const KUrl &url )
01097 {
01098   KProtocolInfo::Ptr prot = findProtocol(url);
01099   if ( !prot )
01100     return false;
01101 
01102   return prot->m_supportsMoving;
01103 }
01104 
01105 bool KProtocolManager::supportsOpening( const KUrl &url )
01106 {
01107   KProtocolInfo::Ptr prot = findProtocol(url);
01108   if ( !prot )
01109     return false;
01110 
01111   return prot->m_supportsOpening;
01112 }
01113 
01114 bool KProtocolManager::canCopyFromFile( const KUrl &url )
01115 {
01116   KProtocolInfo::Ptr prot = findProtocol(url);
01117   if ( !prot )
01118     return false;
01119 
01120   return prot->m_canCopyFromFile;
01121 }
01122 
01123 
01124 bool KProtocolManager::canCopyToFile( const KUrl &url )
01125 {
01126   KProtocolInfo::Ptr prot = findProtocol(url);
01127   if ( !prot )
01128     return false;
01129 
01130   return prot->m_canCopyToFile;
01131 }
01132 
01133 bool KProtocolManager::canRenameFromFile( const KUrl &url )
01134 {
01135   KProtocolInfo::Ptr prot = findProtocol(url);
01136   if ( !prot )
01137     return false;
01138 
01139   return prot->canRenameFromFile();
01140 }
01141 
01142 
01143 bool KProtocolManager::canRenameToFile( const KUrl &url )
01144 {
01145   KProtocolInfo::Ptr prot = findProtocol(url);
01146   if ( !prot )
01147     return false;
01148 
01149   return prot->canRenameToFile();
01150 }
01151 
01152 bool KProtocolManager::canDeleteRecursive( const KUrl &url )
01153 {
01154   KProtocolInfo::Ptr prot = findProtocol(url);
01155   if ( !prot )
01156     return false;
01157 
01158   return prot->canDeleteRecursive();
01159 }
01160 
01161 KProtocolInfo::FileNameUsedForCopying KProtocolManager::fileNameUsedForCopying( const KUrl &url )
01162 {
01163   KProtocolInfo::Ptr prot = findProtocol(url);
01164   if ( !prot )
01165     return KProtocolInfo::FromUrl;
01166 
01167   return prot->fileNameUsedForCopying();
01168 }
01169 
01170 QString KProtocolManager::defaultMimetype( const KUrl &url )
01171 {
01172   KProtocolInfo::Ptr prot = findProtocol(url);
01173   if ( !prot )
01174     return QString();
01175 
01176   return prot->m_defaultMimetype;
01177 }
01178 
01179 QString KProtocolManager::protocolForArchiveMimetype( const QString& mimeType )
01180 {
01181     PRIVATE_DATA;
01182     if (d->protocolForArchiveMimetypes.isEmpty()) {
01183         const KProtocolInfo::List allProtocols = KProtocolInfoFactory::self()->allProtocols();
01184         for (KProtocolInfo::List::const_iterator it = allProtocols.begin();
01185              it != allProtocols.end(); ++it) {
01186             const QStringList archiveMimetypes = (*it)->archiveMimeTypes();
01187             Q_FOREACH(const QString& mime, archiveMimetypes) {
01188                 d->protocolForArchiveMimetypes.insert(mime, (*it)->name());
01189             }
01190         }
01191     }
01192     return d->protocolForArchiveMimetypes.value(mimeType);
01193 }
01194 
01195 #undef PRIVATE_DATA
This file is part of the KDE documentation.
Documentation copyright © 1996-2019 The KDE developers.
Generated on Mon Jan 21 2019 12:35:01 by doxygen 1.7.5.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs-4.9.5 API Reference

Skip menu "kdelibs-4.9.5 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal