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, like Gecko)") \ 00076 .arg(KDE_VERSION_MAJOR).arg(KDE_VERSION_MINOR).arg(X) 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 KConfig *cfg = config(); 00210 cfg->setGroup( "Proxy Settings" ); 00211 00212 QString noProxy = cfg->readEntry( "NoProxyFor" ); 00213 if (proxyType() == EnvVarProxy) 00214 noProxy = QString::fromLocal8Bit(getenv(noProxy.local8Bit())); 00215 00216 return noProxy; 00217 } 00218 00219 QString KProtocolManager::proxyFor( const QString& protocol ) 00220 { 00221 QString scheme = protocol.lower(); 00222 00223 if (scheme == "webdav") 00224 scheme = "http"; 00225 else if (scheme == "webdavs") 00226 scheme = "https"; 00227 00228 KConfig *cfg = config(); 00229 cfg->setGroup( "Proxy Settings" ); 00230 return cfg->readEntry( scheme + "Proxy" ); 00231 } 00232 00233 QString KProtocolManager::proxyForURL( const KURL &url ) 00234 { 00235 QString proxy; 00236 ProxyType pt = proxyType(); 00237 00238 switch (pt) 00239 { 00240 case PACProxy: 00241 case WPADProxy: 00242 if (!url.host().isEmpty()) 00243 { 00244 QString p = url.protocol(); 00245 if ( p.startsWith( "http" ) || p == "ftp" || p == "gopher" ) 00246 DCOPRef( "kded", "proxyscout" ).call( "proxyForURL", url ).get( proxy ); 00247 } 00248 break; 00249 case EnvVarProxy: 00250 proxy = QString::fromLocal8Bit(getenv(proxyFor(url.protocol()).local8Bit())).stripWhiteSpace(); 00251 break; 00252 case ManualProxy: 00253 proxy = proxyFor( url.protocol() ); 00254 break; 00255 case NoProxy: 00256 default: 00257 break; 00258 } 00259 00260 return (proxy.isEmpty() ? QString::fromLatin1("DIRECT") : proxy); 00261 } 00262 00263 void KProtocolManager::badProxy( const QString &proxy ) 00264 { 00265 DCOPRef( "kded", "proxyscout" ).send( "blackListProxy", proxy ); 00266 } 00267 00268 /* 00269 Domain suffix match. E.g. return true if host is "cuzco.inka.de" and 00270 nplist is "inka.de,hadiko.de" or if host is "localhost" and nplist is 00271 "localhost". 00272 */ 00273 static bool revmatch(const char *host, const char *nplist) 00274 { 00275 if (host == 0) 00276 return false; 00277 00278 const char *hptr = host + strlen( host ) - 1; 00279 const char *nptr = nplist + strlen( nplist ) - 1; 00280 const char *shptr = hptr; 00281 00282 while ( nptr >= nplist ) 00283 { 00284 if ( *hptr != *nptr ) 00285 { 00286 hptr = shptr; 00287 00288 // Try to find another domain or host in the list 00289 while(--nptr>=nplist && *nptr!=',' && *nptr!=' ') ; 00290 00291 // Strip out multiple spaces and commas 00292 while(--nptr>=nplist && (*nptr==',' || *nptr==' ')) ; 00293 } 00294 else 00295 { 00296 if ( nptr==nplist || nptr[-1]==',' || nptr[-1]==' ') 00297 return true; 00298 if ( hptr == host ) // e.g. revmatch("bugs.kde.org","mybugs.kde.org") 00299 return false; 00300 00301 hptr--; 00302 nptr--; 00303 } 00304 } 00305 00306 return false; 00307 } 00308 00309 QString KProtocolManager::slaveProtocol(const KURL &url, QString &proxy) 00310 { 00311 if (url.hasSubURL()) // We don't want the suburl's protocol 00312 { 00313 KURL::List list = KURL::split(url); 00314 KURL::List::Iterator it = list.fromLast(); 00315 return slaveProtocol(*it, proxy); 00316 } 00317 00318 if (!d) 00319 d = new KProtocolManagerPrivate; 00320 00321 if (d->url == url) 00322 { 00323 proxy = d->proxy; 00324 return d->protocol; 00325 } 00326 00327 if (useProxy()) 00328 { 00329 proxy = proxyForURL(url); 00330 if ((proxy != "DIRECT") && (!proxy.isEmpty())) 00331 { 00332 bool isRevMatch = false; 00333 bool useRevProxy = ((proxyType() == ManualProxy) && useReverseProxy()); 00334 00335 QString noProxy = noProxyFor(); 00336 00337 if (!noProxy.isEmpty()) 00338 { 00339 QString qhost = url.host().lower(); 00340 const char *host = qhost.latin1(); 00341 QString qno_proxy = noProxy.stripWhiteSpace().lower(); 00342 const char *no_proxy = qno_proxy.latin1(); 00343 isRevMatch = revmatch(host, no_proxy); 00344 00345 // If no match is found and the request url has a port 00346 // number, try the combination of "host:port". This allows 00347 // users to enter host:port in the No-proxy-For list. 00348 if (!isRevMatch && url.port() > 0) 00349 { 00350 qhost += ':' + QString::number (url.port()); 00351 host = qhost.latin1(); 00352 isRevMatch = revmatch (host, no_proxy); 00353 } 00354 00355 // If the hostname does not contain a dot, check if 00356 // <local> is part of noProxy. 00357 if (!isRevMatch && host && (strchr(host, '.') == NULL)) 00358 isRevMatch = revmatch("<local>", no_proxy); 00359 } 00360 00361 if ( (!useRevProxy && !isRevMatch) || (useRevProxy && isRevMatch) ) 00362 { 00363 d->url = proxy; 00364 if ( d->url.isValid() ) 00365 { 00366 // The idea behind slave protocols is not applicable to http 00367 // and webdav protocols. 00368 QString protocol = url.protocol().lower(); 00369 if (protocol.startsWith("http") || protocol.startsWith("webdav")) 00370 d->protocol = protocol; 00371 else 00372 { 00373 d->protocol = d->url.protocol(); 00374 kdDebug () << "slaveProtocol: " << d->protocol << endl; 00375 } 00376 00377 d->url = url; 00378 d->proxy = proxy; 00379 return d->protocol; 00380 } 00381 } 00382 } 00383 } 00384 00385 d->url = url; 00386 d->proxy = proxy = QString::null; 00387 d->protocol = url.protocol(); 00388 return d->protocol; 00389 } 00390 00391 /*================================= USER-AGENT SETTINGS =====================*/ 00392 00393 QString KProtocolManager::userAgentForHost( const QString& hostname ) 00394 { 00395 QString sendUserAgent = KIO::SlaveConfig::self()->configData("http", hostname.lower(), "SendUserAgent").lower(); 00396 if (sendUserAgent == "false") 00397 return QString::null; 00398 00399 QString useragent = KIO::SlaveConfig::self()->configData("http", hostname.lower(), "UserAgent"); 00400 00401 // Return the default user-agent if none is specified 00402 // for the requested host. 00403 if (useragent.isEmpty()) 00404 return defaultUserAgent(); 00405 00406 return useragent; 00407 } 00408 00409 QString KProtocolManager::defaultUserAgent( ) 00410 { 00411 QString modifiers = KIO::SlaveConfig::self()->configData("http", QString::null, "UserAgentKeys"); 00412 return defaultUserAgent(modifiers); 00413 } 00414 00415 QString KProtocolManager::defaultUserAgent( const QString &_modifiers ) 00416 { 00417 if (!d) 00418 d = new KProtocolManagerPrivate; 00419 00420 QString modifiers = _modifiers.lower(); 00421 if (modifiers.isEmpty()) 00422 modifiers = DEFAULT_USER_AGENT_KEYS; 00423 00424 if (d->modifiers == modifiers) 00425 return d->useragent; 00426 00427 QString supp; 00428 struct utsname nam; 00429 if( uname(&nam) >= 0 ) 00430 { 00431 if( modifiers.contains('o') ) 00432 { 00433 supp += QString("; %1").arg(nam.sysname); 00434 if ( modifiers.contains('v') ) 00435 supp += QString(" %1").arg(nam.release); 00436 } 00437 if( modifiers.contains('p') ) 00438 { 00439 supp += QString::fromLatin1("; X11"); // TODO: determine this valye instead of hardcoding... 00440 } 00441 if( modifiers.contains('m') ) 00442 { 00443 supp += QString("; %1").arg(nam.machine); 00444 } 00445 if( modifiers.contains('l') ) 00446 { 00447 QStringList languageList = KGlobal::locale()->languageList(); 00448 QStringList::Iterator it = languageList.find( QString::fromLatin1("C") ); 00449 if( it != languageList.end() ) 00450 { 00451 if( languageList.contains( QString::fromLatin1("en") ) > 0 ) 00452 languageList.remove( it ); 00453 else 00454 (*it) = QString::fromLatin1("en"); 00455 } 00456 if( languageList.count() ) 00457 supp += QString("; %1").arg(languageList.join(", ")); 00458 } 00459 } 00460 d->modifiers = modifiers; 00461 d->useragent = CFG_DEFAULT_UAGENT(supp); 00462 return d->useragent; 00463 } 00464 00465 /*==================================== OTHERS ===============================*/ 00466 00467 bool KProtocolManager::markPartial() 00468 { 00469 KConfig *cfg = config(); 00470 cfg->setGroup( QString::null ); 00471 return cfg->readBoolEntry( "MarkPartial", true ); 00472 } 00473 00474 int KProtocolManager::minimumKeepSize() 00475 { 00476 KConfig *cfg = config(); 00477 cfg->setGroup( QString::null ); 00478 return cfg->readNumEntry( "MinimumKeepSize", 00479 DEFAULT_MINIMUM_KEEP_SIZE ); // 5000 byte 00480 } 00481 00482 bool KProtocolManager::autoResume() 00483 { 00484 KConfig *cfg = config(); 00485 cfg->setGroup( QString::null ); 00486 return cfg->readBoolEntry( "AutoResume", false ); 00487 } 00488 00489 bool KProtocolManager::persistentConnections() 00490 { 00491 KConfig *cfg = config(); 00492 cfg->setGroup( QString::null ); 00493 return cfg->readBoolEntry( "PersistentConnections", true ); 00494 } 00495 00496 bool KProtocolManager::persistentProxyConnection() 00497 { 00498 KConfig *cfg = config(); 00499 cfg->setGroup( QString::null ); 00500 return cfg->readBoolEntry( "PersistentProxyConnection", false ); 00501 } 00502 00503 QString KProtocolManager::proxyConfigScript() 00504 { 00505 KConfig *cfg = config(); 00506 cfg->setGroup( "Proxy Settings" ); 00507 return cfg->readEntry( "Proxy Config Script" ); 00508 }
KDE Logo
This file is part of the documentation for kio Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Sep 29 09:43:53 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003