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

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

Skip menu "kdelibs"
  • 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
Generated for kdelibs by doxygen 1.7.5.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal