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