kprotocolmanager.cpp Source File (kio Library)

| # kio Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Source Files

# 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 }

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