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