kio Library API Documentation

kprotocolmanager.cpp

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 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License version 2 as published by the Free Software Foundation.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00018    Boston, MA 02111-1307, USA.
00019 */
00020 
00021 #include <string.h>
00022 #include <sys/utsname.h>
00023 
00024 #include <dcopref.h>
00025 #include <kdebug.h>
00026 #include <kglobal.h>
00027 #include <klocale.h>
00028 #include <kconfig.h>
00029 #include <kstandarddirs.h>
00030 #include <klibloader.h>
00031 #include <kstringhandler.h>
00032 #include <kstaticdeleter.h>
00033 #include <kio/slaveconfig.h>
00034 #include <kio/ioslave_defaults.h>
00035 #include <kio/http_slave_defaults.h>
00036 
00037 #include "kprotocolmanager.h"
00038 
00039 class
00040 KProtocolManagerPrivate
00041 {
00042 public:
00043    KProtocolManagerPrivate();
00044 
00045    ~KProtocolManagerPrivate();
00046 
00047    KConfig *config;
00048    KConfig *http_config;
00049    bool init_busy;
00050    KURL url;
00051    QString protocol;
00052    QString proxy;
00053    QString modifiers;
00054    QString useragent;
00055    static KProtocolManagerPrivate *globalRef;
00056 };
00057 
00058 KProtocolManagerPrivate *KProtocolManagerPrivate::globalRef = 0;
00059 static KStaticDeleter<KProtocolManagerPrivate> kpmpksd;
00060 
00061 KProtocolManagerPrivate::KProtocolManagerPrivate()
00062                         :config(0), http_config(0), init_busy(false)
00063 {
00064    globalRef = kpmpksd.setObject(globalRef, this);
00065 }
00066 
00067 KProtocolManagerPrivate::~KProtocolManagerPrivate()
00068 {
00069    delete config;
00070    delete http_config;
00071 }
00072 
00073 static KProtocolManagerPrivate* d = 0;
00074 
00075 // DEFAULT USERAGENT STRING
00076 #define CFG_DEFAULT_UAGENT(X) \
00077 QString("Mozilla/5.0 (compatible; Konqueror/%1.%2%3) (KHTML, like Gecko)") \
00078         .arg(KDE_VERSION_MAJOR).arg(KDE_VERSION_MINOR).arg(X)
00079 
00080 void KProtocolManager::reparseConfiguration()
00081 {
00082   delete d;
00083   d = 0;
00084 
00085   // Force the slave config to re-read its config...
00086   KIO::SlaveConfig::self()->reset ();
00087 }
00088 
00089 KConfig *KProtocolManager::config()
00090 {
00091   if (!d)
00092      d = new KProtocolManagerPrivate;
00093 
00094   if (!d->config)
00095   {
00096      d->config = new KConfig("kioslaverc", true, false);
00097   }
00098   return d->config;
00099 }
00100 
00101 KConfig *KProtocolManager::http_config()
00102 {
00103   if (!d)
00104      d = new KProtocolManagerPrivate;
00105 
00106   if (!d->http_config)
00107   {
00108      d->http_config = new KConfig("kio_httprc", false, false);
00109   }
00110   return d->http_config;
00111 }
00112 
00113 /*=============================== TIMEOUT SETTINGS ==========================*/
00114 
00115 int KProtocolManager::readTimeout()
00116 {
00117   KConfig *cfg = config();
00118   cfg->setGroup( QString::null );
00119   int val = cfg->readNumEntry( "ReadTimeout", DEFAULT_READ_TIMEOUT );
00120   return QMAX(MIN_TIMEOUT_VALUE, val);
00121 }
00122 
00123 int KProtocolManager::connectTimeout()
00124 {
00125   KConfig *cfg = config();
00126   cfg->setGroup( QString::null );
00127   int val = cfg->readNumEntry( "ConnectTimeout", DEFAULT_CONNECT_TIMEOUT );
00128   return QMAX(MIN_TIMEOUT_VALUE, val);
00129 }
00130 
00131 int KProtocolManager::proxyConnectTimeout()
00132 {
00133   KConfig *cfg = config();
00134   cfg->setGroup( QString::null );
00135   int val = cfg->readNumEntry( "ProxyConnectTimeout", DEFAULT_PROXY_CONNECT_TIMEOUT );
00136   return QMAX(MIN_TIMEOUT_VALUE, val);
00137 }
00138 
00139 int KProtocolManager::responseTimeout()
00140 {
00141   KConfig *cfg = config();
00142   cfg->setGroup( QString::null );
00143   int val = cfg->readNumEntry( "ResponseTimeout", DEFAULT_RESPONSE_TIMEOUT );
00144   return QMAX(MIN_TIMEOUT_VALUE, val);
00145 }
00146 
00147 /*========================== PROXY SETTINGS =================================*/
00148 
00149 bool KProtocolManager::useProxy()
00150 {
00151   return proxyType() != NoProxy;
00152 }
00153 
00154 bool KProtocolManager::useReverseProxy()
00155 {
00156   KConfig *cfg = config();
00157   cfg->setGroup( "Proxy Settings" );
00158   return cfg->readBoolEntry("ReversedException", false);
00159 }
00160 
00161 KProtocolManager::ProxyType KProtocolManager::proxyType()
00162 {
00163   KConfig *cfg = config();
00164   cfg->setGroup( "Proxy Settings" );
00165   return static_cast<ProxyType>(cfg->readNumEntry( "ProxyType" ));
00166 }
00167 
00168 KProtocolManager::ProxyAuthMode KProtocolManager::proxyAuthMode()
00169 {
00170   KConfig *cfg = config();
00171   cfg->setGroup( "Proxy Settings" );
00172   return static_cast<ProxyAuthMode>(cfg->readNumEntry( "AuthMode" ));
00173 }
00174 
00175 /*========================== CACHING =====================================*/
00176 
00177 bool KProtocolManager::useCache()
00178 {
00179   KConfig *cfg = http_config();
00180   return cfg->readBoolEntry( "UseCache", true );
00181 }
00182 
00183 KIO::CacheControl KProtocolManager::cacheControl()
00184 {
00185   KConfig *cfg = http_config();
00186   QString tmp = cfg->readEntry("cache");
00187   if (tmp.isEmpty())
00188     return DEFAULT_CACHE_CONTROL;
00189   return KIO::parseCacheControl(tmp);
00190 }
00191 
00192 QString KProtocolManager::cacheDir()
00193 {
00194   KConfig *cfg = http_config();
00195   return cfg->readPathEntry("CacheDir", KGlobal::dirs()->saveLocation("cache","http"));
00196 }
00197 
00198 int KProtocolManager::maxCacheAge()
00199 {
00200   KConfig *cfg = http_config();
00201   return cfg->readNumEntry( "MaxCacheAge", DEFAULT_MAX_CACHE_AGE ); // 14 days
00202 }
00203 
00204 int KProtocolManager::maxCacheSize()
00205 {
00206   KConfig *cfg = http_config();
00207   return cfg->readNumEntry( "MaxCacheSize", DEFAULT_MAX_CACHE_SIZE ); // 5 MB
00208 }
00209 
00210 QString KProtocolManager::noProxyFor()
00211 {
00212   KConfig *cfg = config();
00213   cfg->setGroup( "Proxy Settings" );
00214 
00215   QString noProxy = cfg->readEntry( "NoProxyFor" );
00216   if (proxyType() == EnvVarProxy)
00217     noProxy = QString::fromLocal8Bit(getenv(noProxy.local8Bit()));
00218 
00219   return noProxy;
00220 }
00221 
00222 QString KProtocolManager::proxyFor( const QString& protocol )
00223 {
00224   QString scheme = protocol.lower();
00225 
00226   if (scheme == "webdav")
00227     scheme = "http";
00228   else if (scheme == "webdavs")
00229     scheme = "https";
00230 
00231   KConfig *cfg = config();
00232   cfg->setGroup( "Proxy Settings" );
00233   return cfg->readEntry( scheme + "Proxy" );
00234 }
00235 
00236 QString KProtocolManager::proxyForURL( const KURL &url )
00237 {
00238   QString proxy;
00239   ProxyType pt = proxyType();
00240 
00241   switch (pt)
00242   {
00243       case PACProxy:
00244       case WPADProxy:
00245           if (!url.host().isEmpty())
00246           {
00247             QString p = url.protocol();
00248             if ( p.startsWith( "http" ) || p == "ftp" || p == "gopher" )
00249               DCOPRef( "kded", "proxyscout" ).call( "proxyForURL", url ).get( proxy );
00250           }
00251           break;
00252       case EnvVarProxy:
00253           proxy = QString::fromLocal8Bit(getenv(proxyFor(url.protocol()).local8Bit())).stripWhiteSpace();
00254           break;
00255       case ManualProxy:
00256           proxy = proxyFor( url.protocol() );
00257           break;
00258       case NoProxy:
00259       default:
00260           break;
00261   }
00262 
00263   return (proxy.isEmpty() ? QString::fromLatin1("DIRECT") : proxy);
00264 }
00265 
00266 void KProtocolManager::badProxy( const QString &proxy )
00267 {
00268     DCOPRef( "kded", "proxyscout" ).send( "blackListProxy", proxy );
00269 }
00270 
00271 /*
00272     Domain suffix match. E.g. return true if host is "cuzco.inka.de" and
00273     nplist is "inka.de,hadiko.de" or if host is "localhost" and nplist is
00274     "localhost".
00275 */
00276 static bool revmatch(const char *host, const char *nplist)
00277 {
00278   if (host == 0)
00279     return false;
00280 
00281   const char *hptr = host + strlen( host ) - 1;
00282   const char *nptr = nplist + strlen( nplist ) - 1;
00283   const char *shptr = hptr;
00284 
00285   while ( nptr >= nplist )
00286   {
00287     if ( *hptr != *nptr )
00288     {
00289       hptr = shptr;
00290 
00291       // Try to find another domain or host in the list
00292       while(--nptr>=nplist && *nptr!=',' && *nptr!=' ') ;
00293 
00294       // Strip out multiple spaces and commas
00295       while(--nptr>=nplist && (*nptr==',' || *nptr==' ')) ;
00296     }
00297     else
00298     {
00299       if ( nptr==nplist || nptr[-1]==',' || nptr[-1]==' ')
00300         return true;
00301       if ( hptr == host ) // e.g. revmatch("bugs.kde.org","mybugs.kde.org")
00302         return false;
00303 
00304       hptr--;
00305       nptr--;
00306     }
00307   }
00308 
00309   return false;
00310 }
00311 
00312 QString KProtocolManager::slaveProtocol(const KURL &url, QString &proxy)
00313 {
00314   if (url.hasSubURL()) // We don't want the suburl's protocol
00315   {
00316      KURL::List list = KURL::split(url);
00317      KURL::List::Iterator it = list.fromLast();
00318      return slaveProtocol(*it, proxy);
00319   }
00320 
00321   if (!d)
00322     d = new KProtocolManagerPrivate;
00323 
00324   if (d->url == url)
00325   {
00326      proxy = d->proxy;
00327      return d->protocol;
00328   }
00329 
00330   if (useProxy())
00331   {
00332      proxy = proxyForURL(url);
00333      if ((proxy != "DIRECT") && (!proxy.isEmpty()))
00334      {
00335         bool isRevMatch = false;
00336         bool useRevProxy = ((proxyType() == ManualProxy) && useReverseProxy());
00337 
00338         QString noProxy = noProxyFor();
00339 
00340         if (!noProxy.isEmpty())
00341         {
00342            QString qhost = url.host().lower();
00343            const char *host = qhost.latin1();
00344            QString qno_proxy = noProxy.stripWhiteSpace().lower();
00345            const char *no_proxy = qno_proxy.latin1();
00346            isRevMatch = revmatch(host, no_proxy);
00347 
00348            // If no match is found and the request url has a port
00349            // number, try the combination of "host:port". This allows
00350            // users to enter host:port in the No-proxy-For list.
00351            if (!isRevMatch && url.port() > 0)
00352            {
00353               qhost += ':' + QString::number (url.port());
00354               host = qhost.latin1();
00355               isRevMatch = revmatch (host, no_proxy);
00356            }
00357 
00358            // If the hostname does not contain a dot, check if
00359            // <local> is part of noProxy.
00360            if (!isRevMatch && host && (strchr(host, '.') == NULL))
00361               isRevMatch = revmatch("<local>", no_proxy);
00362         }
00363 
00364         if ( (!useRevProxy && !isRevMatch) || (useRevProxy && isRevMatch) )
00365         {
00366            d->url = proxy;
00367            if ( d->url.isValid() )
00368            {
00369               // The idea behind slave protocols is not applicable to http
00370               // and webdav protocols.
00371               QString protocol = url.protocol().lower();
00372               if (protocol.startsWith("http") || protocol.startsWith("webdav"))
00373                 d->protocol = protocol;
00374               else
00375               {
00376                 d->protocol = d->url.protocol();
00377                 kdDebug () << "slaveProtocol: " << d->protocol << endl;
00378               }
00379 
00380               d->url = url;
00381               d->proxy = proxy;
00382               return d->protocol;
00383            }
00384         }
00385      }
00386   }
00387 
00388   d->url = url;
00389   d->proxy = proxy = QString::null;
00390   d->protocol = url.protocol();
00391   return d->protocol;
00392 }
00393 
00394 /*================================= USER-AGENT SETTINGS =====================*/
00395 
00396 QString KProtocolManager::userAgentForHost( const QString& hostname )
00397 {
00398   QString useragent = KIO::SlaveConfig::self()->configData("http", hostname.lower(), "UserAgent");
00399 
00400   // Return the default user-agent if none is specified
00401   // for the requested host.
00402   if (useragent.isEmpty())
00403     return defaultUserAgent();
00404 
00405   return useragent;
00406 }
00407 
00408 QString KProtocolManager::defaultUserAgent( )
00409 {
00410   QString modifiers = KIO::SlaveConfig::self()->configData("http", QString::null, "UserAgentKeys");
00411   return defaultUserAgent(modifiers);
00412 }
00413 
00414 QString KProtocolManager::defaultUserAgent( const QString &_modifiers )
00415 {
00416   if (!d)
00417      d = new KProtocolManagerPrivate;
00418 
00419   QString modifiers = _modifiers.lower();
00420   if (modifiers.isEmpty())
00421      modifiers = DEFAULT_USER_AGENT_KEYS;
00422 
00423   if (d->modifiers == modifiers)
00424      return d->useragent;
00425 
00426   QString supp;
00427   struct utsname nam;
00428   if( uname(&nam) >= 0 )
00429   {
00430     if( modifiers.contains('o') )
00431     {
00432       supp += QString("; %1").arg(nam.sysname);
00433       if ( modifiers.contains('v') )
00434         supp += QString(" %1").arg(nam.release);
00435     }
00436     if( modifiers.contains('p') )
00437     {
00438       supp += QString::fromLatin1("; X11");  // TODO: determine this valye instead of hardcoding...
00439     }
00440     if( modifiers.contains('m') )
00441     {
00442       supp += QString("; %1").arg(nam.machine);
00443     }
00444     if( modifiers.contains('l') )
00445     {
00446       QStringList languageList = KGlobal::locale()->languageList();
00447       QStringList::Iterator it = languageList.find( QString::fromLatin1("C") );
00448       if( it != languageList.end() )
00449       {
00450         if( languageList.contains( QString::fromLatin1("en") ) > 0 )
00451           languageList.remove( it );
00452         else
00453           (*it) = QString::fromLatin1("en");
00454       }
00455       if( languageList.count() )
00456         supp += QString("; %1").arg(languageList.join(", "));
00457     }
00458   }
00459   d->modifiers = modifiers;
00460   d->useragent = CFG_DEFAULT_UAGENT(supp);
00461   return d->useragent;
00462 }
00463 
00464 /*==================================== OTHERS ===============================*/
00465 
00466 bool KProtocolManager::markPartial()
00467 {
00468   KConfig *cfg = config();
00469   cfg->setGroup( QString::null );
00470   return cfg->readBoolEntry( "MarkPartial", true );
00471 }
00472 
00473 int KProtocolManager::minimumKeepSize()
00474 {
00475   KConfig *cfg = config();
00476   cfg->setGroup( QString::null );
00477   return cfg->readNumEntry( "MinimumKeepSize",
00478                             DEFAULT_MINIMUM_KEEP_SIZE ); // 5000 byte
00479 }
00480 
00481 bool KProtocolManager::autoResume()
00482 {
00483   KConfig *cfg = config();
00484   cfg->setGroup( QString::null );
00485   return cfg->readBoolEntry( "AutoResume", false );
00486 }
00487 
00488 bool KProtocolManager::persistentConnections()
00489 {
00490   KConfig *cfg = config();
00491   cfg->setGroup( QString::null );
00492   return cfg->readBoolEntry( "PersistentConnections", true );
00493 }
00494 
00495 bool KProtocolManager::persistentProxyConnection()
00496 {
00497   KConfig *cfg = config();
00498   cfg->setGroup( QString::null );
00499   return cfg->readBoolEntry( "PersistentProxyConnection", false );
00500 }
00501 
00502 QString KProtocolManager::proxyConfigScript()
00503 {
00504   KConfig *cfg = config();
00505   cfg->setGroup( "Proxy Settings" );
00506   return cfg->readEntry( "Proxy Config Script" );
00507 }
KDE Logo
This file is part of the documentation for kio Library Version 3.2.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Feb 4 12:35:06 2004 by doxygen 1.2.18 written by Dimitri van Heesch, © 1997-2003