KIO
kprotocolmanager.cpp
Go to the documentation of this file.
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 Copyright (C) 2008 Jarosław Staniek <staniek@kde.org> 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License version 2 as published by the Free Software Foundation. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 Boston, MA 02110-1301, USA. 00020 */ 00021 00022 #include "kprotocolmanager.h" 00023 00024 #include <string.h> 00025 #include <unistd.h> 00026 #include <sys/utsname.h> 00027 00028 #include <QtCore/QCoreApplication> 00029 #include <QtCore/QStringBuilder> 00030 #include <QtNetwork/QSslSocket> 00031 #include <QtDBus/QtDBus> 00032 00033 #include <kdeversion.h> 00034 #include <kdebug.h> 00035 #include <kglobal.h> 00036 #include <klocale.h> 00037 #include <kconfiggroup.h> 00038 #include <ksharedconfig.h> 00039 #include <kstandarddirs.h> 00040 #include <kstringhandler.h> 00041 #include <kurl.h> 00042 #include <kmimetypetrader.h> 00043 #include <kio/slaveconfig.h> 00044 #include <kio/ioslave_defaults.h> 00045 #include <kio/http_slave_defaults.h> 00046 #include <kprotocolinfofactory.h> 00047 00048 #define QL1S(x) QLatin1String(x) 00049 #define QL1C(x) QLatin1Char(x) 00050 00051 class 00052 KProtocolManagerPrivate 00053 { 00054 public: 00055 KProtocolManagerPrivate(); 00056 00057 ~KProtocolManagerPrivate(); 00058 00059 KSharedConfig::Ptr config; 00060 KSharedConfig::Ptr http_config; 00061 KUrl url; 00062 QString protocol; 00063 QString proxy; 00064 QString modifiers; 00065 QString useragent; 00066 00067 QMap<QString /*mimetype*/, QString /*protocol*/> protocolForArchiveMimetypes; 00068 }; 00069 00070 K_GLOBAL_STATIC(KProtocolManagerPrivate, kProtocolManagerPrivate) 00071 00072 KProtocolManagerPrivate::KProtocolManagerPrivate() 00073 { 00074 // post routine since KConfig::sync() breaks if called too late 00075 qAddPostRoutine(kProtocolManagerPrivate.destroy); 00076 } 00077 00078 KProtocolManagerPrivate::~KProtocolManagerPrivate() 00079 { 00080 qRemovePostRoutine(kProtocolManagerPrivate.destroy); 00081 } 00082 00083 00084 // DEFAULT USERAGENT STRING 00085 #define CFG_DEFAULT_UAGENT(X) \ 00086 QL1S("Mozilla/5.0 (compatible; Konqueror/") % \ 00087 QString::number(KDE::versionMajor()) % QL1C('.') % QString::number(KDE::versionMinor()) % \ 00088 X % QL1S(") KHTML/") % \ 00089 QString::number(KDE::versionMajor()) % QL1C('.') % QString::number(KDE::versionMinor()) % \ 00090 QL1C('.') % QString::number(KDE::versionRelease()) % QL1S(" (like Gecko) Fedora/4.6.2-1.fc15") 00091 00092 #define PRIVATE_DATA \ 00093 KProtocolManagerPrivate *d = kProtocolManagerPrivate 00094 00095 void KProtocolManager::reparseConfiguration() 00096 { 00097 PRIVATE_DATA; 00098 if (d->http_config) { 00099 d->http_config->reparseConfiguration(); 00100 } 00101 if (d->config) { 00102 d->config->reparseConfiguration(); 00103 } 00104 d->protocol.clear(); 00105 d->proxy.clear(); 00106 d->modifiers.clear(); 00107 d->useragent.clear(); 00108 d->url.clear(); 00109 00110 // Force the slave config to re-read its config... 00111 KIO::SlaveConfig::self()->reset (); 00112 } 00113 00114 KSharedConfig::Ptr KProtocolManager::config() 00115 { 00116 PRIVATE_DATA; 00117 if (!d->config) 00118 { 00119 d->config = KSharedConfig::openConfig("kioslaverc", KConfig::NoGlobals); 00120 } 00121 return d->config; 00122 } 00123 00124 static KConfigGroup http_config() 00125 { 00126 PRIVATE_DATA; 00127 if (!d->http_config) { 00128 d->http_config = KSharedConfig::openConfig("kio_httprc", KConfig::NoGlobals); 00129 } 00130 return KConfigGroup(d->http_config, QString()); 00131 } 00132 00133 /*=============================== TIMEOUT SETTINGS ==========================*/ 00134 00135 int KProtocolManager::readTimeout() 00136 { 00137 KConfigGroup cg( config(), QString() ); 00138 int val = cg.readEntry( "ReadTimeout", DEFAULT_READ_TIMEOUT ); 00139 return qMax(MIN_TIMEOUT_VALUE, val); 00140 } 00141 00142 int KProtocolManager::connectTimeout() 00143 { 00144 KConfigGroup cg( config(), QString() ); 00145 int val = cg.readEntry( "ConnectTimeout", DEFAULT_CONNECT_TIMEOUT ); 00146 return qMax(MIN_TIMEOUT_VALUE, val); 00147 } 00148 00149 int KProtocolManager::proxyConnectTimeout() 00150 { 00151 KConfigGroup cg( config(), QString() ); 00152 int val = cg.readEntry( "ProxyConnectTimeout", DEFAULT_PROXY_CONNECT_TIMEOUT ); 00153 return qMax(MIN_TIMEOUT_VALUE, val); 00154 } 00155 00156 int KProtocolManager::responseTimeout() 00157 { 00158 KConfigGroup cg( config(), QString() ); 00159 int val = cg.readEntry( "ResponseTimeout", DEFAULT_RESPONSE_TIMEOUT ); 00160 return qMax(MIN_TIMEOUT_VALUE, val); 00161 } 00162 00163 /*========================== PROXY SETTINGS =================================*/ 00164 00165 bool KProtocolManager::useProxy() 00166 { 00167 return proxyType() != NoProxy; 00168 } 00169 00170 bool KProtocolManager::useReverseProxy() 00171 { 00172 KConfigGroup cg(config(), "Proxy Settings" ); 00173 return cg.readEntry("ReversedException", false); 00174 } 00175 00176 KProtocolManager::ProxyType KProtocolManager::proxyType() 00177 { 00178 KConfigGroup cg(config(), "Proxy Settings" ); 00179 return static_cast<ProxyType>(cg.readEntry( "ProxyType" , 0)); 00180 } 00181 00182 KProtocolManager::ProxyAuthMode KProtocolManager::proxyAuthMode() 00183 { 00184 KConfigGroup cg(config(), "Proxy Settings" ); 00185 return static_cast<ProxyAuthMode>(cg.readEntry( "AuthMode" , 0)); 00186 } 00187 00188 /*========================== CACHING =====================================*/ 00189 00190 bool KProtocolManager::useCache() 00191 { 00192 return http_config().readEntry( "UseCache", true ); 00193 } 00194 00195 KIO::CacheControl KProtocolManager::cacheControl() 00196 { 00197 QString tmp = http_config().readEntry("cache"); 00198 if (tmp.isEmpty()) 00199 return DEFAULT_CACHE_CONTROL; 00200 return KIO::parseCacheControl(tmp); 00201 } 00202 00203 QString KProtocolManager::cacheDir() 00204 { 00205 return http_config().readPathEntry("CacheDir", KGlobal::dirs()->saveLocation("cache","http")); 00206 } 00207 00208 int KProtocolManager::maxCacheAge() 00209 { 00210 return http_config().readEntry( "MaxCacheAge", DEFAULT_MAX_CACHE_AGE ); // 14 days 00211 } 00212 00213 int KProtocolManager::maxCacheSize() 00214 { 00215 return http_config().readEntry( "MaxCacheSize", DEFAULT_MAX_CACHE_SIZE ); // 5 MB 00216 } 00217 00218 QString KProtocolManager::noProxyFor() 00219 { 00220 KProtocolManager::ProxyType type = proxyType(); 00221 00222 QString noProxy = config()->group("Proxy Settings").readEntry( "NoProxyFor" ); 00223 if (type == EnvVarProxy) 00224 noProxy = QString::fromLocal8Bit(qgetenv(noProxy.toLocal8Bit())); 00225 00226 return noProxy; 00227 } 00228 00229 QString KProtocolManager::proxyFor( const QString& protocol ) 00230 { 00231 QString key = protocol.toLower(); 00232 00233 if (key == QL1S("webdav")) 00234 key = QL1S("http"); 00235 else if (key == QL1S("webdavs")) 00236 key = QL1S("https"); 00237 00238 key += QL1S("Proxy"); 00239 00240 return config()->group("Proxy Settings").readEntry(key, QString()); 00241 } 00242 00243 QString KProtocolManager::proxyForUrl( const KUrl &url ) 00244 { 00245 QString proxy; 00246 ProxyType pt = proxyType(); 00247 00248 switch (pt) 00249 { 00250 case PACProxy: 00251 case WPADProxy: 00252 if (!url.host().isEmpty()) 00253 { 00254 KUrl u (url); 00255 QString p = u.protocol().toLower(); 00256 00257 // webdav is a KDE specific protocol. Look up proxy 00258 // information using HTTP instead... 00259 if (p == QL1S("webdav")) 00260 { 00261 p = QL1S("http"); 00262 u.setProtocol(p); 00263 } 00264 else if (p == QL1S("webdavs")) 00265 { 00266 p = QL1S("https"); 00267 u.setProtocol(p); 00268 } 00269 00270 if (p.startsWith(QL1S("http")) || p.startsWith(QL1S("ftp"))) 00271 { 00272 QDBusReply<QString> reply = QDBusInterface(QL1S("org.kde.kded"), 00273 QL1S("/modules/proxyscout"), 00274 QL1S("org.kde.KPAC.ProxyScout")) 00275 .call(QL1S("proxyForUrl"), u.url() ); 00276 proxy = reply; 00277 } 00278 } 00279 break; 00280 case EnvVarProxy: 00281 proxy = QString::fromLocal8Bit(qgetenv(proxyFor(url.protocol()).toLocal8Bit())).trimmed(); 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() ? QL1S("DIRECT") : proxy); 00292 } 00293 00294 void KProtocolManager::badProxy( const QString &proxy ) 00295 { 00296 QDBusInterface( QL1S("org.kde.kded"), QL1S("/modules/proxyscout")) 00297 .call(QL1S("blackListProxy"), 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 if ( nptr[-1]=='/' && hptr == host ) // "bugs.kde.org" vs "http://bugs.kde.org", the config UI says URLs are ok 00331 return true; 00332 if ( hptr == host ) // e.g. revmatch("bugs.kde.org","mybugs.kde.org") 00333 return false; 00334 00335 hptr--; 00336 nptr--; 00337 } 00338 } 00339 00340 return false; 00341 } 00342 00343 QString KProtocolManager::slaveProtocol(const KUrl &url, QString &proxy) 00344 { 00345 if (url.hasSubUrl()) // We don't want the suburl's protocol 00346 { 00347 KUrl::List list = KUrl::split(url); 00348 KUrl l = list.last(); 00349 return slaveProtocol(l, proxy); 00350 } 00351 00352 PRIVATE_DATA; 00353 if (d->url == url) 00354 { 00355 proxy = d->proxy; 00356 return d->protocol; 00357 } 00358 00359 if (useProxy()) 00360 { 00361 proxy = proxyForUrl(url); 00362 if ((proxy != "DIRECT") && (!proxy.isEmpty())) 00363 { 00364 bool isRevMatch = false; 00365 KProtocolManager::ProxyType type = proxyType(); 00366 bool useRevProxy = ((type == ManualProxy) && useReverseProxy()); 00367 00368 QString noProxy; 00369 // Check no proxy information iff the proxy type is either 00370 // manual or environment variable based... 00371 if ( (type == ManualProxy) || (type == EnvVarProxy) ) 00372 noProxy = noProxyFor(); 00373 00374 if (!noProxy.isEmpty()) 00375 { 00376 QString qhost = url.host().toLower(); 00377 QByteArray host = qhost.toLatin1(); 00378 QString qno_proxy = noProxy.trimmed().toLower(); 00379 const QByteArray no_proxy = qno_proxy.toLatin1(); 00380 isRevMatch = revmatch(host, no_proxy); 00381 00382 // If no match is found and the request url has a port 00383 // number, try the combination of "host:port". This allows 00384 // users to enter host:port in the No-proxy-For list. 00385 if (!isRevMatch && url.port() > 0) 00386 { 00387 qhost += QL1C(':'); 00388 qhost += QString::number(url.port()); 00389 host = qhost.toLatin1(); 00390 isRevMatch = revmatch (host, no_proxy); 00391 } 00392 00393 // If the hostname does not contain a dot, check if 00394 // <local> is part of noProxy. 00395 if (!isRevMatch && !host.isEmpty() && (strchr(host, '.') == NULL)) 00396 isRevMatch = revmatch("<local>", no_proxy); 00397 } 00398 00399 if ( (!useRevProxy && !isRevMatch) || (useRevProxy && isRevMatch) ) 00400 { 00401 d->url = proxy; 00402 if (d->url.isValid() && !d->url.protocol().isEmpty()) 00403 { 00404 // The idea behind slave protocols is not applicable to http 00405 // and webdav protocols. 00406 const QString protocol = url.protocol().toLower(); 00407 if (protocol.startsWith(QL1S("http")) || protocol.startsWith(QL1S("webdav")) || 00408 !KProtocolInfo::isKnownProtocol(protocol)) 00409 d->protocol = protocol; 00410 else 00411 { 00412 d->protocol = d->url.protocol(); 00413 kDebug () << "slaveProtocol: " << d->protocol; 00414 } 00415 00416 d->url = url; 00417 d->proxy = proxy; 00418 return d->protocol; 00419 } 00420 } 00421 } 00422 } 00423 00424 d->url = url; 00425 d->proxy.clear(); proxy.clear(); 00426 d->protocol = url.protocol(); 00427 return d->protocol; 00428 } 00429 00430 /*================================= USER-AGENT SETTINGS =====================*/ 00431 00432 QString KProtocolManager::userAgentForHost( const QString& hostname ) 00433 { 00434 const QString sendUserAgent = KIO::SlaveConfig::self()->configData("http", hostname.toLower(), "SendUserAgent").toLower(); 00435 if (sendUserAgent == QL1S("false")) 00436 return QString(); 00437 00438 const QString useragent = KIO::SlaveConfig::self()->configData("http", hostname.toLower(), "UserAgent"); 00439 00440 // Return the default user-agent if none is specified 00441 // for the requested host. 00442 if (useragent.isEmpty()) 00443 return defaultUserAgent(); 00444 00445 return useragent; 00446 } 00447 00448 QString KProtocolManager::defaultUserAgent( ) 00449 { 00450 const QString modifiers = KIO::SlaveConfig::self()->configData("http", QString(), "UserAgentKeys"); 00451 return defaultUserAgent(modifiers); 00452 } 00453 00454 static QString defaultUserAgentFromPreferredService() 00455 { 00456 QString agentStr; 00457 00458 // Check if the default COMPONENT contains a custom default UA string... 00459 KService::Ptr service = KMimeTypeTrader::self()->preferredService(QL1S("text/html"), 00460 QL1S("KParts/ReadOnlyPart")); 00461 if (service && service->showInKDE()) 00462 agentStr = service->property(QL1S("X-KDE-Default-UserAgent"), 00463 QVariant::String).toString(); 00464 return agentStr; 00465 } 00466 00467 QString KProtocolManager::defaultUserAgent( const QString &_modifiers ) 00468 { 00469 PRIVATE_DATA; 00470 QString modifiers = _modifiers.toLower(); 00471 if (modifiers.isEmpty()) 00472 modifiers = DEFAULT_USER_AGENT_KEYS; 00473 00474 if (d->modifiers == modifiers && !d->useragent.isEmpty()) 00475 return d->useragent; 00476 00477 d->modifiers = modifiers; 00478 00479 /* 00480 The following code attempts to determine the default user agent string 00481 from the 'X-KDE-UA-DEFAULT-STRING' property of the desktop file 00482 for the preferred service that was configured to handle the 'text/html' 00483 mime type. If the prefered service's desktop file does not specify this 00484 property, the long standing default user agent string will be used. 00485 The following keyword placeholders are automatically converted when the 00486 user agent string is read from the property: 00487 00488 %SECURITY% Expands to"U" when SSL is supported, "N" otherwise. 00489 %OSNAME% Expands to operating system name, e.g. Linux. 00490 %OSVERSION% Expands to operating system version, e.g. 2.6.32 00491 %SYSTYPE% Expands to machine or system type, e.g. i386 00492 %PLATFORM% Expands to windowing system, e.g. X11 on Unix/Linux. 00493 %LANGUAGE% Expands to default language in use, e.g. en-US. 00494 %APPVERSION% Expands to QCoreApplication applicationName()/applicationVerison(), 00495 e.g. Konqueror/4.5.0. If application name and/or application version 00496 number are not set, then "KDE" and the runtime KDE version numbers 00497 are used respectively. 00498 00499 All of the keywords are handled case-insensitively. 00500 */ 00501 00502 QString systemName, systemVersion, machine, supp; 00503 const bool sysInfoFound = getSystemNameVersionAndMachine( systemName, systemVersion, machine ); 00504 QString agentStr = defaultUserAgentFromPreferredService(); 00505 00506 if (agentStr.isEmpty()) 00507 { 00508 if (sysInfoFound) 00509 { 00510 if( modifiers.contains('o') ) 00511 { 00512 supp += QL1S("; "); 00513 supp += systemName; 00514 if ( modifiers.contains('v') ) 00515 { 00516 supp += QL1C(' '); 00517 supp += systemVersion; 00518 } 00519 } 00520 #ifdef Q_WS_X11 00521 if( modifiers.contains('p') ) 00522 supp += QL1S("; X11"); 00523 #endif 00524 if( modifiers.contains('m') ) 00525 { 00526 supp += QL1S("; "); 00527 supp += machine; 00528 } 00529 if( modifiers.contains('l') ) 00530 { 00531 supp += QL1S("; "); 00532 supp += KGlobal::locale()->language(); 00533 } 00534 } 00535 00536 d->useragent = CFG_DEFAULT_UAGENT(supp); 00537 } 00538 else 00539 { 00540 QString appName = QCoreApplication::applicationName(); 00541 if (appName.isEmpty() || appName.startsWith(QL1S("kcmshell"), Qt::CaseInsensitive)) 00542 appName = QL1S ("KDE"); 00543 00544 QString appVersion = QCoreApplication::applicationVersion(); 00545 if (appVersion.isEmpty()) 00546 appVersion += (QString::number(KDE::versionMajor()) % QL1C('.') % 00547 QString::number(KDE::versionMinor()) % QL1C('.') % 00548 QString::number(KDE::versionRelease())); 00549 00550 appName += QL1C('/') % appVersion; 00551 00552 agentStr.replace(QL1S("%appversion%"), appName, Qt::CaseInsensitive); 00553 00554 if (QSslSocket::supportsSsl()) 00555 agentStr.replace(QL1S("%security%"), QL1S("U"), Qt::CaseInsensitive); 00556 else 00557 agentStr.replace(QL1S("%security%"), QL1S("N"), Qt::CaseInsensitive); 00558 00559 if (sysInfoFound) 00560 { 00561 if (modifiers.contains('o')) 00562 { 00563 agentStr.replace(QL1S("%osname%"), systemName, Qt::CaseInsensitive); 00564 if (modifiers.contains('v')) 00565 agentStr.replace(QL1S("%osversion%"), systemVersion, Qt::CaseInsensitive); 00566 else 00567 agentStr.remove(QL1S("%osversion%"), Qt::CaseInsensitive); 00568 } 00569 else 00570 { 00571 agentStr.remove(QL1S("%osname%"), Qt::CaseInsensitive); 00572 agentStr.remove(QL1S("%osversion%"), Qt::CaseInsensitive); 00573 } 00574 00575 if (modifiers.contains('p')) 00576 #if defined(Q_WS_X11) 00577 agentStr.replace(QL1S("%platform%"), QL1S("X11"), Qt::CaseInsensitive); 00578 #elif defined(Q_WS_MAC) 00579 agentStr.replace(QL1S("%platform%"), QL1S("Macintosh"), Qt::CaseInsensitive); 00580 #elif defined(Q_WS_WIN) 00581 agentStr.replace(QL1S("%platform%"), QL1S("Windows"), Qt::CaseInsensitive); 00582 #elif defined (Q_WS_S60) 00583 agentStr.replace(QL1S("%platform%"), QL1S("Symbian"), Qt::CaseInsensitive); 00584 #endif 00585 else 00586 agentStr.remove(QL1S("%platform%"), Qt::CaseInsensitive); 00587 00588 if (modifiers.contains('m')) 00589 agentStr.replace(QL1S("%systype%"), machine, Qt::CaseInsensitive); 00590 else 00591 agentStr.remove(QL1S("%systype%"), Qt::CaseInsensitive); 00592 00593 if (modifiers.contains('l')) 00594 agentStr.replace(QL1S("%language%"), KGlobal::locale()->language(), Qt::CaseInsensitive); 00595 else 00596 agentStr.remove(QL1S("%language%"), Qt::CaseInsensitive); 00597 00598 // Clean up unnecessary separators that could be left over from the 00599 // possible keyword removal above... 00600 agentStr.replace(QRegExp("[(]\\s*[;]\\s*"), QL1S("(")); 00601 agentStr.replace(QRegExp("[;]\\s*[;]\\s*"), QL1S(";")); 00602 agentStr.replace(QRegExp("\\s*[;]\\s*[)]"), QL1S(")")); 00603 } 00604 else 00605 { 00606 agentStr.remove(QL1S("%osname%")); 00607 agentStr.remove(QL1S("%osversion%")); 00608 agentStr.remove(QL1S("%platform%")); 00609 agentStr.remove(QL1S("%systype%")); 00610 agentStr.remove(QL1S("%language%")); 00611 } 00612 00613 d->useragent = agentStr.simplified(); 00614 } 00615 00616 //kDebug() << "USERAGENT STRING:" << d->useragent; 00617 return d->useragent; 00618 } 00619 00620 QString KProtocolManager::userAgentForApplication( const QString &appName, const QString& appVersion, 00621 const QStringList& extraInfo ) 00622 { 00623 QString systemName, systemVersion, machine, info; 00624 00625 if (getSystemNameVersionAndMachine( systemName, systemVersion, machine )) 00626 { 00627 info += systemName; 00628 info += QL1C('/'); 00629 info += systemVersion; 00630 info += QL1S("; "); 00631 } 00632 00633 info += QL1S("KDE/"); 00634 info += QString::number(KDE::versionMajor()); 00635 info += QL1C('.'); 00636 info += QString::number(KDE::versionMinor()); 00637 info += QL1C('.'); 00638 info += QString::number(KDE::versionRelease()); 00639 00640 if (!machine.isEmpty()) 00641 { 00642 info += QL1S("; "); 00643 info += machine; 00644 } 00645 00646 info += QL1S("; "); 00647 info += extraInfo.join(QL1S("; ")); 00648 00649 return (appName % QL1C('/') % appVersion % QL1S(" (") % info % QL1C(')')); 00650 } 00651 00652 bool KProtocolManager::getSystemNameVersionAndMachine( 00653 QString& systemName, QString& systemVersion, QString& machine ) 00654 { 00655 struct utsname unameBuf; 00656 if ( 0 != uname( &unameBuf ) ) 00657 return false; 00658 #if defined(Q_WS_WIN) && !defined(_WIN32_WCE) 00659 // we do not use unameBuf.sysname information constructed in kdewin32 00660 // because we want to get separate name and version 00661 systemName = QL1S( "Windows" ); 00662 OSVERSIONINFOEX versioninfo; 00663 ZeroMemory(&versioninfo, sizeof(OSVERSIONINFOEX)); 00664 // try calling GetVersionEx using the OSVERSIONINFOEX, if that fails, try using the OSVERSIONINFO 00665 versioninfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); 00666 bool ok = GetVersionEx( (OSVERSIONINFO *) &versioninfo ); 00667 if ( !ok ) { 00668 versioninfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); 00669 ok = GetVersionEx( (OSVERSIONINFO *) &versioninfo ); 00670 } 00671 if ( ok ) 00672 systemVersion = (QString::number(versioninfo.dwMajorVersion) % 00673 QL1C('.') % QString::number(versioninfo.dwMinorVersion)); 00674 #else 00675 systemName = unameBuf.sysname; 00676 systemVersion = unameBuf.release; 00677 #endif 00678 machine = unameBuf.machine; 00679 return true; 00680 } 00681 00682 QString KProtocolManager::acceptLanguagesHeader() 00683 { 00684 static const QString &english = KGlobal::staticQString("en"); 00685 00686 // User's desktop language preference. 00687 QStringList languageList = KGlobal::locale()->languageList(); 00688 00689 // Replace possible "C" in the language list with "en", unless "en" is 00690 // already pressent. This is to keep user's priorities in order. 00691 // If afterwards "en" is still not present, append it. 00692 int idx = languageList.indexOf(QString::fromLatin1("C")); 00693 if (idx != -1) 00694 { 00695 if (languageList.contains(english)) 00696 languageList.removeAt(idx); 00697 else 00698 languageList[idx] = english; 00699 } 00700 if (!languageList.contains(english)) 00701 languageList += english; 00702 00703 // Some languages may have web codes different from locale codes, 00704 // read them from the config and insert in proper order. 00705 KConfig acclangConf("accept-languages.codes", KConfig::NoGlobals); 00706 KConfigGroup replacementCodes(&acclangConf, "ReplacementCodes"); 00707 QStringList languageListFinal; 00708 Q_FOREACH (const QString &lang, languageList) 00709 { 00710 const QStringList langs = replacementCodes.readEntry(lang, QStringList()); 00711 if (langs.isEmpty()) 00712 languageListFinal += lang; 00713 else 00714 languageListFinal += langs; 00715 } 00716 00717 // The header is composed of comma separated languages, with an optional 00718 // associated priority estimate (q=1..0) defaulting to 1. 00719 // As our language tags are already sorted by priority, we'll just decrease 00720 // the value evenly 00721 int prio = 10; 00722 QString header; 00723 Q_FOREACH (const QString &lang,languageListFinal) { 00724 header += lang; 00725 if (prio < 10) { 00726 header += QL1S(";q=0."); 00727 header += QString::number(prio); 00728 } 00729 // do not add cosmetic whitespace in here : it is less compatible (#220677) 00730 header += QL1S(","); 00731 if (prio > 1) 00732 --prio; 00733 } 00734 header.chop(1); 00735 00736 // Some of the languages may have country specifier delimited by 00737 // underscore, or modifier delimited by at-sign. 00738 // The header should use dashes instead. 00739 header.replace('_', '-'); 00740 header.replace('@', '-'); 00741 00742 return header; 00743 } 00744 00745 /*==================================== OTHERS ===============================*/ 00746 00747 bool KProtocolManager::markPartial() 00748 { 00749 return config()->group(QByteArray()).readEntry( "MarkPartial", true ); 00750 } 00751 00752 int KProtocolManager::minimumKeepSize() 00753 { 00754 return config()->group(QByteArray()).readEntry( "MinimumKeepSize", 00755 DEFAULT_MINIMUM_KEEP_SIZE ); // 5000 byte 00756 } 00757 00758 bool KProtocolManager::autoResume() 00759 { 00760 return config()->group(QByteArray()).readEntry( "AutoResume", false ); 00761 } 00762 00763 bool KProtocolManager::persistentConnections() 00764 { 00765 return config()->group(QByteArray()).readEntry( "PersistentConnections", true ); 00766 } 00767 00768 bool KProtocolManager::persistentProxyConnection() 00769 { 00770 return config()->group(QByteArray()).readEntry( "PersistentProxyConnection", false ); 00771 } 00772 00773 QString KProtocolManager::proxyConfigScript() 00774 { 00775 return config()->group("Proxy Settings").readEntry( "Proxy Config Script" ); 00776 } 00777 00778 /* =========================== PROTOCOL CAPABILITIES ============== */ 00779 00780 static KProtocolInfo::Ptr findProtocol(const KUrl &url) 00781 { 00782 QString protocol = url.protocol(); 00783 00784 if ( !KProtocolInfo::proxiedBy( protocol ).isEmpty() ) 00785 { 00786 QString dummy; 00787 protocol = KProtocolManager::slaveProtocol(url, dummy); 00788 } 00789 00790 return KProtocolInfoFactory::self()->findProtocol(protocol); 00791 } 00792 00793 00794 KProtocolInfo::Type KProtocolManager::inputType( const KUrl &url ) 00795 { 00796 KProtocolInfo::Ptr prot = findProtocol(url); 00797 if ( !prot ) 00798 return KProtocolInfo::T_NONE; 00799 00800 return prot->m_inputType; 00801 } 00802 00803 KProtocolInfo::Type KProtocolManager::outputType( const KUrl &url ) 00804 { 00805 KProtocolInfo::Ptr prot = findProtocol(url); 00806 if ( !prot ) 00807 return KProtocolInfo::T_NONE; 00808 00809 return prot->m_outputType; 00810 } 00811 00812 00813 bool KProtocolManager::isSourceProtocol( const KUrl &url ) 00814 { 00815 KProtocolInfo::Ptr prot = findProtocol(url); 00816 if ( !prot ) 00817 return false; 00818 00819 return prot->m_isSourceProtocol; 00820 } 00821 00822 bool KProtocolManager::supportsListing( const KUrl &url ) 00823 { 00824 KProtocolInfo::Ptr prot = findProtocol(url); 00825 if ( !prot ) 00826 return false; 00827 00828 return prot->m_supportsListing; 00829 } 00830 00831 QStringList KProtocolManager::listing( const KUrl &url ) 00832 { 00833 KProtocolInfo::Ptr prot = findProtocol(url); 00834 if ( !prot ) 00835 return QStringList(); 00836 00837 return prot->m_listing; 00838 } 00839 00840 bool KProtocolManager::supportsReading( const KUrl &url ) 00841 { 00842 KProtocolInfo::Ptr prot = findProtocol(url); 00843 if ( !prot ) 00844 return false; 00845 00846 return prot->m_supportsReading; 00847 } 00848 00849 bool KProtocolManager::supportsWriting( const KUrl &url ) 00850 { 00851 KProtocolInfo::Ptr prot = findProtocol(url); 00852 if ( !prot ) 00853 return false; 00854 00855 return prot->m_supportsWriting; 00856 } 00857 00858 bool KProtocolManager::supportsMakeDir( const KUrl &url ) 00859 { 00860 KProtocolInfo::Ptr prot = findProtocol(url); 00861 if ( !prot ) 00862 return false; 00863 00864 return prot->m_supportsMakeDir; 00865 } 00866 00867 bool KProtocolManager::supportsDeleting( const KUrl &url ) 00868 { 00869 KProtocolInfo::Ptr prot = findProtocol(url); 00870 if ( !prot ) 00871 return false; 00872 00873 return prot->m_supportsDeleting; 00874 } 00875 00876 bool KProtocolManager::supportsLinking( const KUrl &url ) 00877 { 00878 KProtocolInfo::Ptr prot = findProtocol(url); 00879 if ( !prot ) 00880 return false; 00881 00882 return prot->m_supportsLinking; 00883 } 00884 00885 bool KProtocolManager::supportsMoving( const KUrl &url ) 00886 { 00887 KProtocolInfo::Ptr prot = findProtocol(url); 00888 if ( !prot ) 00889 return false; 00890 00891 return prot->m_supportsMoving; 00892 } 00893 00894 bool KProtocolManager::supportsOpening( const KUrl &url ) 00895 { 00896 KProtocolInfo::Ptr prot = findProtocol(url); 00897 if ( !prot ) 00898 return false; 00899 00900 return prot->m_supportsOpening; 00901 } 00902 00903 bool KProtocolManager::canCopyFromFile( const KUrl &url ) 00904 { 00905 KProtocolInfo::Ptr prot = findProtocol(url); 00906 if ( !prot ) 00907 return false; 00908 00909 return prot->m_canCopyFromFile; 00910 } 00911 00912 00913 bool KProtocolManager::canCopyToFile( const KUrl &url ) 00914 { 00915 KProtocolInfo::Ptr prot = findProtocol(url); 00916 if ( !prot ) 00917 return false; 00918 00919 return prot->m_canCopyToFile; 00920 } 00921 00922 bool KProtocolManager::canRenameFromFile( const KUrl &url ) 00923 { 00924 KProtocolInfo::Ptr prot = findProtocol(url); 00925 if ( !prot ) 00926 return false; 00927 00928 return prot->canRenameFromFile(); 00929 } 00930 00931 00932 bool KProtocolManager::canRenameToFile( const KUrl &url ) 00933 { 00934 KProtocolInfo::Ptr prot = findProtocol(url); 00935 if ( !prot ) 00936 return false; 00937 00938 return prot->canRenameToFile(); 00939 } 00940 00941 bool KProtocolManager::canDeleteRecursive( const KUrl &url ) 00942 { 00943 KProtocolInfo::Ptr prot = findProtocol(url); 00944 if ( !prot ) 00945 return false; 00946 00947 return prot->canDeleteRecursive(); 00948 } 00949 00950 KProtocolInfo::FileNameUsedForCopying KProtocolManager::fileNameUsedForCopying( const KUrl &url ) 00951 { 00952 KProtocolInfo::Ptr prot = findProtocol(url); 00953 if ( !prot ) 00954 return KProtocolInfo::FromUrl; 00955 00956 return prot->fileNameUsedForCopying(); 00957 } 00958 00959 QString KProtocolManager::defaultMimetype( const KUrl &url ) 00960 { 00961 KProtocolInfo::Ptr prot = findProtocol(url); 00962 if ( !prot ) 00963 return QString(); 00964 00965 return prot->m_defaultMimetype; 00966 } 00967 00968 QString KProtocolManager::protocolForArchiveMimetype( const QString& mimeType ) 00969 { 00970 PRIVATE_DATA; 00971 if (d->protocolForArchiveMimetypes.isEmpty()) { 00972 const KProtocolInfo::List allProtocols = KProtocolInfoFactory::self()->allProtocols(); 00973 for (KProtocolInfo::List::const_iterator it = allProtocols.begin(); 00974 it != allProtocols.end(); ++it) { 00975 const QStringList archiveMimetypes = (*it)->archiveMimeTypes(); 00976 Q_FOREACH(const QString& mime, archiveMimetypes) { 00977 d->protocolForArchiveMimetypes.insert(mime, (*it)->name()); 00978 } 00979 } 00980 } 00981 return d->protocolForArchiveMimetypes.value(mimeType); 00982 } 00983 00984 #undef PRIVATE_DATA
KDE 4.6 API Reference