00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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
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
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
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
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 );
00202 }
00203
00204 int KProtocolManager::maxCacheSize()
00205 {
00206 KConfig *cfg = http_config();
00207 return cfg->readNumEntry( "MaxCacheSize", DEFAULT_MAX_CACHE_SIZE );
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
00273
00274
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
00292 while(--nptr>=nplist && *nptr!=',' && *nptr!=' ') ;
00293
00294
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 )
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())
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
00349
00350
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
00359
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
00370
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
00395
00396 QString KProtocolManager::userAgentForHost( const QString& hostname )
00397 {
00398 QString useragent = KIO::SlaveConfig::self()->configData("http", hostname.lower(), "UserAgent");
00399
00400
00401
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");
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
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 );
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 }