• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.8.3 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 (KProtocolInfo::protocolClass(protocol) != QL1S(":local")) {
00474           QDBusReply<QStringList> reply = QDBusInterface(QL1S("org.kde.kded"),
00475                                                          QL1S("/modules/proxyscout"),
00476                                                          QL1S("org.kde.KPAC.ProxyScout"))
00477                                           .call(QL1S("proxiesForUrl"), u.url());
00478           proxyList = reply;
00479         }
00480         break;
00481       }
00482       case EnvVarProxy:
00483         proxyList = getSystemProxyFor( url );
00484         break;
00485       case ManualProxy:
00486       {
00487         QString proxy (proxyFor(url.protocol()));
00488         if (!proxy.isEmpty())
00489           proxyList << proxy;
00490         // Add the socks proxy as an alternate proxy if it exists,
00491         proxy = proxyFor(QL1S("socks"));
00492         if (!proxy.isEmpty()) {
00493           // Make sure the scheme of SOCKS proxy is always set to "socks://".
00494           const int index = proxy.indexOf(QL1S("://"));
00495           proxy = QL1S("socks://") + (index == -1 ? proxy : proxy.mid(index+3));
00496           proxyList << proxy;
00497         }
00498       }
00499       break;
00500       case NoProxy:
00501       default:
00502         break;
00503     }
00504   }
00505 
00506   if (proxyList.isEmpty()) {
00507     proxyList << QL1S("DIRECT");
00508   }
00509 
00510   return proxyList;
00511 }
00512 
00513 void KProtocolManager::badProxy( const QString &proxy )
00514 {
00515   QDBusInterface( QL1S("org.kde.kded"), QL1S("/modules/proxyscout"))
00516       .asyncCall(QL1S("blackListProxy"), proxy);
00517 
00518   PRIVATE_DATA;
00519   const QStringList keys (d->cachedProxyData.keys());
00520   Q_FOREACH(const QString& key, keys) {
00521       d->cachedProxyData[key]->removeAddress(proxy);
00522   }
00523 }
00524 
00525 QString KProtocolManager::slaveProtocol(const KUrl &url, QString &proxy)
00526 {
00527     QStringList proxyList;
00528     const QString protocol = KProtocolManager::slaveProtocol(url, proxyList);
00529     if (!proxyList.isEmpty()) {
00530       proxy = proxyList.first();
00531     }
00532     return protocol;
00533 }
00534 
00535 // Generates proxy cache key from request given url.
00536 static void extractProxyCacheKeyFromUrl(const KUrl& u, QString* key)
00537 {
00538     if (!key)
00539         return;
00540 
00541     *key = u.protocol();
00542     *key += u.host();
00543 
00544     if (u.port() > 0)
00545         *key += QString::number(u.port());
00546 }
00547 
00548 QString KProtocolManager::slaveProtocol(const KUrl &url, QStringList &proxyList)
00549 {
00550   if (url.hasSubUrl()) { // We don't want the suburl's protocol
00551       const KUrl::List list = KUrl::split(url);
00552       return slaveProtocol(list.last(), proxyList);
00553   }
00554 
00555   proxyList.clear();
00556 
00557   // Do not perform a proxy lookup for any url classified as a ":local" url or
00558   // one that does not have a host component or if proxy is disabled.
00559   QString protocol (url.protocol());
00560   if (!url.hasHost()
00561       || KProtocolInfo::protocolClass(protocol) == QL1S(":local")
00562       || KProtocolManager::proxyType() == KProtocolManager::NoProxy) {
00563       return protocol;
00564   }
00565 
00566   QString proxyCacheKey;
00567   extractProxyCacheKeyFromUrl(url, &proxyCacheKey);
00568 
00569   PRIVATE_DATA;
00570   // Look for cached proxy information to avoid more work.
00571   if (d->cachedProxyData.contains(proxyCacheKey)) {
00572       KProxyData* data = d->cachedProxyData.object(proxyCacheKey);
00573       proxyList = data->proxyList;
00574       return data->protocol;
00575   }
00576 
00577   const QStringList proxies = proxiesForUrl(url);
00578   const int count = proxies.count();
00579 
00580   if (count > 0 && !(count == 1 && proxies.first() == QL1S("DIRECT"))) {
00581       Q_FOREACH(const QString& proxy, proxies) {
00582           if (proxy == QL1S("DIRECT")) {
00583               proxyList << proxy;
00584           } else {
00585               KUrl u (proxy);
00586               if (!u.isEmpty() && u.isValid() && !u.protocol().isEmpty()) {
00587                   proxyList << proxy;
00588               }
00589           }
00590       }
00591   }
00592 
00593   // The idea behind slave protocols is not applicable to http
00594   // and webdav protocols as well as protocols unknown to KDE.
00595   if (!proxyList.isEmpty()
00596       && !protocol.startsWith(QL1S("http"))
00597       && !protocol.startsWith(QL1S("webdav"))
00598       && KProtocolInfo::isKnownProtocol(protocol)) {
00599       Q_FOREACH(const QString& proxy, proxyList) {
00600           KUrl u (proxy);
00601           if (u.isValid() && KProtocolInfo::isKnownProtocol(u.protocol())) {
00602               protocol = u.protocol();
00603               break;
00604           }
00605       }
00606   }
00607 
00608   // cache the proxy information...
00609   d->cachedProxyData.insert(proxyCacheKey, new KProxyData(protocol, proxyList));
00610   return protocol;
00611 }
00612 
00613 /*================================= USER-AGENT SETTINGS =====================*/
00614 
00615 QString KProtocolManager::userAgentForHost( const QString& hostname )
00616 {
00617   const QString sendUserAgent = KIO::SlaveConfig::self()->configData("http", hostname.toLower(), "SendUserAgent").toLower();
00618   if (sendUserAgent == QL1S("false"))
00619      return QString();
00620 
00621   const QString useragent = KIO::SlaveConfig::self()->configData("http", hostname.toLower(), "UserAgent");
00622 
00623   // Return the default user-agent if none is specified
00624   // for the requested host.
00625   if (useragent.isEmpty())
00626     return defaultUserAgent();
00627 
00628   return useragent;
00629 }
00630 
00631 QString KProtocolManager::defaultUserAgent( )
00632 {
00633   const QString modifiers = KIO::SlaveConfig::self()->configData("http", QString(), "UserAgentKeys");
00634   return defaultUserAgent(modifiers);
00635 }
00636 
00637 static QString defaultUserAgentFromPreferredService()
00638 {
00639   QString agentStr;
00640 
00641   // Check if the default COMPONENT contains a custom default UA string...
00642   KService::Ptr service = KMimeTypeTrader::self()->preferredService(QL1S("text/html"),
00643                                                       QL1S("KParts/ReadOnlyPart"));
00644   if (service && service->showInKDE())
00645     agentStr = service->property(QL1S("X-KDE-Default-UserAgent"),
00646                                  QVariant::String).toString();
00647   return agentStr;
00648 }
00649 
00650 static QString platform()
00651 {
00652 #if defined(Q_WS_X11)
00653     return QL1S("X11");
00654 #elif defined(Q_WS_MAC)
00655     return QL1S("Macintosh");
00656 #elif defined(Q_WS_WIN)
00657      return QL1S("Windows");
00658 #elif defined(Q_WS_S60)
00659      return QL1S("Symbian");
00660 #endif
00661 }
00662 
00663 QString KProtocolManager::defaultUserAgent( const QString &_modifiers )
00664 {
00665     PRIVATE_DATA;
00666   QString modifiers = _modifiers.toLower();
00667   if (modifiers.isEmpty())
00668     modifiers = DEFAULT_USER_AGENT_KEYS;
00669 
00670   if (d->modifiers == modifiers && !d->useragent.isEmpty())
00671     return d->useragent;
00672 
00673   d->modifiers = modifiers;
00674 
00675   /*
00676      The following code attempts to determine the default user agent string
00677      from the 'X-KDE-UA-DEFAULT-STRING' property of the desktop file
00678      for the preferred service that was configured to handle the 'text/html'
00679      mime type. If the prefered service's desktop file does not specify this
00680      property, the long standing default user agent string will be used.
00681      The following keyword placeholders are automatically converted when the
00682      user agent string is read from the property:
00683 
00684      %SECURITY%      Expands to"N" when SSL is not supported, otherwise it is ignored.
00685      %OSNAME%        Expands to operating system name, e.g. Linux.
00686      %OSVERSION%     Expands to operating system version, e.g. 2.6.32
00687      %SYSTYPE%       Expands to machine or system type, e.g. i386
00688      %PLATFORM%      Expands to windowing system, e.g. X11 on Unix/Linux.
00689      %LANGUAGE%      Expands to default language in use, e.g. en-US.
00690      %APPVERSION%    Expands to QCoreApplication applicationName()/applicationVerison(),
00691                      e.g. Konqueror/4.5.0. If application name and/or application version
00692                      number are not set, then "KDE" and the runtime KDE version numbers
00693                      are used respectively.
00694 
00695      All of the keywords are handled case-insensitively.
00696   */
00697 
00698   QString systemName, systemVersion, machine, supp;
00699   const bool sysInfoFound = getSystemNameVersionAndMachine( systemName, systemVersion, machine );
00700   QString agentStr = defaultUserAgentFromPreferredService();
00701 
00702   if (agentStr.isEmpty())
00703   {
00704     supp += platform();
00705 
00706     if (sysInfoFound)
00707     {
00708       if (modifiers.contains('o'))
00709       {
00710         supp += QL1S("; ");
00711         supp += systemName;
00712         if (modifiers.contains('v'))
00713         {
00714           supp += QL1C(' ');
00715           supp += systemVersion;
00716         }
00717 
00718         if (modifiers.contains('m'))
00719         {
00720           supp += QL1C(' ');
00721           supp += machine;
00722         }
00723       }
00724 
00725       if (modifiers.contains('l'))
00726       {
00727         supp += QL1S("; ");
00728         supp += KGlobal::locale()->language();
00729       }
00730     }
00731 
00732     // Full format: Mozilla/5.0 (Linux
00733     d->useragent = QL1S("Mozilla/5.0 (");
00734     d->useragent += supp;
00735     d->useragent += QL1S(") KHTML/");
00736     d->useragent += QString::number(KDE::versionMajor());
00737     d->useragent += QL1C('.');
00738     d->useragent += QString::number(KDE::versionMinor());
00739     d->useragent += QL1C('.');
00740     d->useragent += QString::number(KDE::versionRelease());
00741     d->useragent += QL1S(" (like Gecko) Konqueror/");
00742     d->useragent += QString::number(KDE::versionMajor());
00743     d->useragent += QL1C('.');
00744     d->useragent += QString::number(KDE::versionMinor());
00745     d->useragent += QL1S(" Fedora/4.8.3-1.fc17");
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-2012 The KDE developers.
Generated on Thu May 10 2012 20:55:22 by doxygen 1.8.0 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.8.3 API Reference

Skip menu "kdelibs-4.8.3 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