• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.10.2 API Reference
  • KDE Home
  • Contact Us
 

KIO

  • kio
  • kio
kprotocolmanager.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE libraries
2  Copyright (C) 1999 Torben Weis <weis@kde.org>
3  Copyright (C) 2000- Waldo Bastain <bastain@kde.org>
4  Copyright (C) 2000- Dawit Alemayehu <adawit@kde.org>
5  Copyright (C) 2008 JarosÅ‚aw Staniek <staniek@kde.org>
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Library General Public
9  License version 2 as published by the Free Software Foundation.
10 
11  This library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Library General Public License for more details.
15 
16  You should have received a copy of the GNU Library General Public License
17  along with this library; see the file COPYING.LIB. If not, write to
18  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  Boston, MA 02110-1301, USA.
20 */
21 
22 #include "kprotocolmanager.h"
23 
24 #include "hostinfo_p.h"
25 
26 #include <string.h>
27 #include <unistd.h>
28 #include <sys/utsname.h>
29 
30 #include <QtCore/QCoreApplication>
31 #include <QtNetwork/QSslSocket>
32 #include <QtNetwork/QHostAddress>
33 #include <QtNetwork/QHostInfo>
34 #include <QtDBus/QtDBus>
35 #include <QtCore/QCache>
36 
37 #if !defined(QT_NO_NETWORKPROXY) && (defined (Q_OS_WIN32) || defined(Q_OS_MAC))
38 #include <QtNetwork/QNetworkProxyFactory>
39 #include <QtNetwork/QNetworkProxyQuery>
40 #endif
41 
42 #include <kdeversion.h>
43 #include <kdebug.h>
44 #include <kglobal.h>
45 #include <klocale.h>
46 #include <kconfiggroup.h>
47 #include <ksharedconfig.h>
48 #include <kstandarddirs.h>
49 #include <kurl.h>
50 #include <kmimetypetrader.h>
51 #include <kprotocolinfofactory.h>
52 
53 #include <kio/slaveconfig.h>
54 #include <kio/ioslave_defaults.h>
55 #include <kio/http_slave_defaults.h>
56 
57 #define QL1S(x) QLatin1String(x)
58 #define QL1C(x) QLatin1Char(x)
59 
60 typedef QPair<QHostAddress, int> SubnetPair;
61 
62 /*
63  Domain suffix match. E.g. return true if host is "cuzco.inka.de" and
64  nplist is "inka.de,hadiko.de" or if host is "localhost" and nplist is
65  "localhost".
66 */
67 static bool revmatch(const char *host, const char *nplist)
68 {
69  if (host == 0)
70  return false;
71 
72  const char *hptr = host + strlen( host ) - 1;
73  const char *nptr = nplist + strlen( nplist ) - 1;
74  const char *shptr = hptr;
75 
76  while ( nptr >= nplist )
77  {
78  if ( *hptr != *nptr )
79  {
80  hptr = shptr;
81 
82  // Try to find another domain or host in the list
83  while(--nptr>=nplist && *nptr!=',' && *nptr!=' ') ;
84 
85  // Strip out multiple spaces and commas
86  while(--nptr>=nplist && (*nptr==',' || *nptr==' ')) ;
87  }
88  else
89  {
90  if ( nptr==nplist || nptr[-1]==',' || nptr[-1]==' ')
91  return true;
92  if ( nptr[-1]=='/' && hptr == host ) // "bugs.kde.org" vs "http://bugs.kde.org", the config UI says URLs are ok
93  return true;
94  if ( hptr == host ) // e.g. revmatch("bugs.kde.org","mybugs.kde.org")
95  return false;
96 
97  hptr--;
98  nptr--;
99  }
100  }
101 
102  return false;
103 }
104 
105 class KProxyData : public QObject
106 {
107 public:
108  KProxyData(const QString& slaveProtocol, const QStringList& proxyAddresses)
109  :protocol(slaveProtocol)
110  ,proxyList(proxyAddresses) {
111  }
112 
113  void removeAddress(const QString& address) {
114  proxyList.removeAll(address);
115  }
116 
117  QString protocol;
118  QStringList proxyList;
119 };
120 
121 class KProtocolManagerPrivate
122 {
123 public:
124  KProtocolManagerPrivate();
125  ~KProtocolManagerPrivate();
126  bool shouldIgnoreProxyFor(const KUrl& url);
127 
128  KSharedConfig::Ptr config;
129  KSharedConfig::Ptr http_config;
130  QString modifiers;
131  QString useragent;
132  QString noProxyFor;
133  QList<SubnetPair> noProxySubnets;
134  QCache<QString, KProxyData> cachedProxyData;
135 
136  QMap<QString /*mimetype*/, QString /*protocol*/> protocolForArchiveMimetypes;
137 };
138 
139 K_GLOBAL_STATIC(KProtocolManagerPrivate, kProtocolManagerPrivate)
140 
141 KProtocolManagerPrivate::KProtocolManagerPrivate()
142 {
143  // post routine since KConfig::sync() breaks if called too late
144  qAddPostRoutine(kProtocolManagerPrivate.destroy);
145  cachedProxyData.setMaxCost(200); // double the max cost.
146 }
147 
148 KProtocolManagerPrivate::~KProtocolManagerPrivate()
149 {
150  qRemovePostRoutine(kProtocolManagerPrivate.destroy);
151 }
152 
153 /*
154  * Returns true if url is in the no proxy list.
155  */
156 bool KProtocolManagerPrivate::shouldIgnoreProxyFor(const KUrl& url)
157 {
158  bool isMatch = false;
159  const KProtocolManager::ProxyType type = KProtocolManager::proxyType();
160  const bool useRevProxy = ((type == KProtocolManager::ManualProxy) && KProtocolManager::useReverseProxy());
161  const bool useNoProxyList = (type == KProtocolManager::ManualProxy || type == KProtocolManager::EnvVarProxy);
162 
163  // No proxy only applies to ManualProxy and EnvVarProxy types...
164  if (useNoProxyList && noProxyFor.isEmpty()) {
165  QStringList noProxyForList (KProtocolManager::noProxyFor().split(QL1C(',')));
166  QMutableStringListIterator it (noProxyForList);
167  while (it.hasNext()) {
168  SubnetPair subnet = QHostAddress::parseSubnet(it.next());
169  if (!subnet.first.isNull()) {
170  noProxySubnets << subnet;
171  it.remove();
172  }
173  }
174  noProxyFor = noProxyForList.join(QL1S(","));
175  }
176 
177  if (!noProxyFor.isEmpty()) {
178  QString qhost = url.host().toLower();
179  QByteArray host = qhost.toLatin1();
180  const QString qno_proxy = noProxyFor.trimmed().toLower();
181  const QByteArray no_proxy = qno_proxy.toLatin1();
182  isMatch = revmatch(host, no_proxy);
183 
184  // If no match is found and the request url has a port
185  // number, try the combination of "host:port". This allows
186  // users to enter host:port in the No-proxy-For list.
187  if (!isMatch && url.port() > 0) {
188  qhost += QL1C(':');
189  qhost += QString::number(url.port());
190  host = qhost.toLatin1();
191  isMatch = revmatch (host, no_proxy);
192  }
193 
194  // If the hostname does not contain a dot, check if
195  // <local> is part of noProxy.
196  if (!isMatch && !host.isEmpty() && (strchr(host, '.') == NULL)) {
197  isMatch = revmatch("<local>", no_proxy);
198  }
199  }
200 
201  const QString host (url.host());
202 
203  if (!noProxySubnets.isEmpty() && !host.isEmpty()) {
204  QHostAddress address (host);
205  // If request url is not IP address, do a DNS lookup of the hostname.
206  // TODO: Perhaps we should make configurable ?
207  if (address.isNull()) {
208  kDebug() << "Performing DNS lookup for" << host;
209  QHostInfo info = KIO::HostInfo::lookupHost(host, 2000);
210  const QList<QHostAddress> addresses = info.addresses();
211  if (!addresses.isEmpty())
212  address = addresses.first();
213  }
214 
215  if (!address.isNull()) {
216  Q_FOREACH(const SubnetPair& subnet, noProxySubnets) {
217  if (address.isInSubnet(subnet)) {
218  isMatch = true;
219  break;
220  }
221  }
222  }
223  }
224 
225  return (useRevProxy != isMatch);
226 }
227 
228 
229 #define PRIVATE_DATA \
230 KProtocolManagerPrivate *d = kProtocolManagerPrivate
231 
232 void KProtocolManager::reparseConfiguration()
233 {
234  PRIVATE_DATA;
235  if (d->http_config) {
236  d->http_config->reparseConfiguration();
237  }
238  if (d->config) {
239  d->config->reparseConfiguration();
240  }
241  d->cachedProxyData.clear();
242  d->noProxyFor.clear();
243  d->modifiers.clear();
244  d->useragent.clear();
245 
246  // Force the slave config to re-read its config...
247  KIO::SlaveConfig::self()->reset();
248 }
249 
250 KSharedConfig::Ptr KProtocolManager::config()
251 {
252  PRIVATE_DATA;
253  if (!d->config)
254  {
255  d->config = KSharedConfig::openConfig("kioslaverc", KConfig::NoGlobals);
256  }
257  return d->config;
258 }
259 
260 static KConfigGroup http_config()
261 {
262  PRIVATE_DATA;
263  if (!d->http_config) {
264  d->http_config = KSharedConfig::openConfig("kio_httprc", KConfig::NoGlobals);
265  }
266  return KConfigGroup(d->http_config, QString());
267 }
268 
269 /*=============================== TIMEOUT SETTINGS ==========================*/
270 
271 int KProtocolManager::readTimeout()
272 {
273  KConfigGroup cg( config(), QString() );
274  int val = cg.readEntry( "ReadTimeout", DEFAULT_READ_TIMEOUT );
275  return qMax(MIN_TIMEOUT_VALUE, val);
276 }
277 
278 int KProtocolManager::connectTimeout()
279 {
280  KConfigGroup cg( config(), QString() );
281  int val = cg.readEntry( "ConnectTimeout", DEFAULT_CONNECT_TIMEOUT );
282  return qMax(MIN_TIMEOUT_VALUE, val);
283 }
284 
285 int KProtocolManager::proxyConnectTimeout()
286 {
287  KConfigGroup cg( config(), QString() );
288  int val = cg.readEntry( "ProxyConnectTimeout", DEFAULT_PROXY_CONNECT_TIMEOUT );
289  return qMax(MIN_TIMEOUT_VALUE, val);
290 }
291 
292 int KProtocolManager::responseTimeout()
293 {
294  KConfigGroup cg( config(), QString() );
295  int val = cg.readEntry( "ResponseTimeout", DEFAULT_RESPONSE_TIMEOUT );
296  return qMax(MIN_TIMEOUT_VALUE, val);
297 }
298 
299 /*========================== PROXY SETTINGS =================================*/
300 
301 bool KProtocolManager::useProxy()
302 {
303  return proxyType() != NoProxy;
304 }
305 
306 bool KProtocolManager::useReverseProxy()
307 {
308  KConfigGroup cg(config(), "Proxy Settings" );
309  return cg.readEntry("ReversedException", false);
310 }
311 
312 KProtocolManager::ProxyType KProtocolManager::proxyType()
313 {
314  KConfigGroup cg(config(), "Proxy Settings" );
315  return static_cast<ProxyType>(cg.readEntry( "ProxyType" , 0));
316 }
317 
318 KProtocolManager::ProxyAuthMode KProtocolManager::proxyAuthMode()
319 {
320  KConfigGroup cg(config(), "Proxy Settings" );
321  return static_cast<ProxyAuthMode>(cg.readEntry( "AuthMode" , 0));
322 }
323 
324 /*========================== CACHING =====================================*/
325 
326 bool KProtocolManager::useCache()
327 {
328  return http_config().readEntry( "UseCache", true );
329 }
330 
331 KIO::CacheControl KProtocolManager::cacheControl()
332 {
333  QString tmp = http_config().readEntry("cache");
334  if (tmp.isEmpty())
335  return DEFAULT_CACHE_CONTROL;
336  return KIO::parseCacheControl(tmp);
337 }
338 
339 QString KProtocolManager::cacheDir()
340 {
341  return http_config().readPathEntry("CacheDir", KGlobal::dirs()->saveLocation("cache","http"));
342 }
343 
344 int KProtocolManager::maxCacheAge()
345 {
346  return http_config().readEntry( "MaxCacheAge", DEFAULT_MAX_CACHE_AGE ); // 14 days
347 }
348 
349 int KProtocolManager::maxCacheSize()
350 {
351  return http_config().readEntry( "MaxCacheSize", DEFAULT_MAX_CACHE_SIZE ); // 5 MB
352 }
353 
354 QString KProtocolManager::noProxyFor()
355 {
356  QString noProxy = config()->group("Proxy Settings").readEntry( "NoProxyFor" );
357  if (proxyType() == EnvVarProxy)
358  noProxy = QString::fromLocal8Bit(qgetenv(noProxy.toLocal8Bit()));
359 
360  return noProxy;
361 }
362 
363 static QString adjustProtocol(const QString& scheme)
364 {
365  if (scheme.compare(QL1S("webdav"), Qt::CaseInsensitive) == 0)
366  return QL1S("http");
367 
368  if (scheme.compare(QL1S("webdavs"), Qt::CaseInsensitive) == 0)
369  return QL1S("https");
370 
371  return scheme.toLower();
372 }
373 
374 QString KProtocolManager::proxyFor( const QString& protocol )
375 {
376  const QString key = adjustProtocol(protocol) + QL1S("Proxy");
377  QString proxyStr (config()->group("Proxy Settings").readEntry(key));
378  const int index = proxyStr.lastIndexOf(QL1C(' '));
379 
380  if (index > -1) {
381  bool ok = false;
382  const QString portStr(proxyStr.right(proxyStr.length() - index - 1));
383  portStr.toInt(&ok);
384  if (ok) {
385  proxyStr = proxyStr.left(index) + QL1C(':') + portStr;
386  } else {
387  proxyStr.clear();
388  }
389  }
390 
391  return proxyStr;
392 }
393 
394 QString KProtocolManager::proxyForUrl( const KUrl &url )
395 {
396  const QStringList proxies = proxiesForUrl(url);
397 
398  if (proxies.isEmpty())
399  return QString();
400 
401  return proxies.first();
402 }
403 
404 static QStringList getSystemProxyFor( const KUrl& url )
405 {
406  QStringList proxies;
407 
408 #if !defined(QT_NO_NETWORKPROXY) && (defined(Q_OS_WIN32) || defined(Q_OS_MAC))
409  QNetworkProxyQuery query ( url );
410  const QList<QNetworkProxy> proxyList = QNetworkProxyFactory::systemProxyForQuery(query);
411  Q_FOREACH(const QNetworkProxy& proxy, proxyList)
412  {
413  KUrl url;
414  const QNetworkProxy::ProxyType type = proxy.type();
415  if (type == QNetworkProxy::NoProxy || type == QNetworkProxy::DefaultProxy)
416  {
417  proxies << QL1S("DIRECT");
418  continue;
419  }
420 
421  if (type == QNetworkProxy::HttpProxy || type == QNetworkProxy::HttpCachingProxy)
422  url.setProtocol(QL1S("http"));
423  else if (type == QNetworkProxy::Socks5Proxy)
424  url.setProtocol(QL1S("socks"));
425  else if (type == QNetworkProxy::FtpCachingProxy)
426  url.setProtocol(QL1S("ftp"));
427 
428  url.setHost(proxy.hostName());
429  url.setPort(proxy.port());
430  url.setUser(proxy.user());
431  proxies << url.url();
432  }
433 #else
434  // On Unix/Linux use system environment variables if any are set.
435  QString proxyVar (KProtocolManager::proxyFor(url.protocol()));
436  // Check for SOCKS proxy, if not proxy is found for given url.
437  if (!proxyVar.isEmpty()) {
438  const QString proxy (QString::fromLocal8Bit(qgetenv(proxyVar.toLocal8Bit())).trimmed());
439  if (!proxy.isEmpty()) {
440  proxies << proxy;
441  }
442  }
443  // Add the socks proxy as an alternate proxy if it exists,
444  proxyVar = KProtocolManager::proxyFor(QL1S("socks"));
445  if (!proxyVar.isEmpty()) {
446  QString proxy = QString::fromLocal8Bit(qgetenv(proxyVar.toLocal8Bit())).trimmed();
447  // Make sure the scheme of SOCKS proxy is always set to "socks://".
448  const int index = proxy.indexOf(QL1S("://"));
449  proxy = QL1S("socks://") + (index == -1 ? proxy : proxy.mid(index+3));
450  if (!proxy.isEmpty()) {
451  proxies << proxy;
452  }
453  }
454 #endif
455  return proxies;
456 }
457 
458 QStringList KProtocolManager::proxiesForUrl( const KUrl &url )
459 {
460  QStringList proxyList;
461 
462  PRIVATE_DATA;
463  if (!d->shouldIgnoreProxyFor(url)) {
464  switch (proxyType())
465  {
466  case PACProxy:
467  case WPADProxy:
468  {
469  KUrl u (url);
470  const QString protocol = adjustProtocol(u.protocol());
471  u.setProtocol(protocol);
472 
473  if (protocol.startsWith(QL1S("http"), Qt::CaseInsensitive) ||
474  protocol.startsWith(QL1S("ftp"), Qt::CaseInsensitive)) {
475  QDBusReply<QStringList> reply = QDBusInterface(QL1S("org.kde.kded"),
476  QL1S("/modules/proxyscout"),
477  QL1S("org.kde.KPAC.ProxyScout"))
478  .call(QL1S("proxiesForUrl"), u.url());
479  proxyList = reply;
480  }
481  break;
482  }
483  case EnvVarProxy:
484  proxyList = getSystemProxyFor( url );
485  break;
486  case ManualProxy:
487  {
488  QString proxy (proxyFor(url.protocol()));
489  if (!proxy.isEmpty())
490  proxyList << proxy;
491  // Add the socks proxy as an alternate proxy if it exists,
492  proxy = proxyFor(QL1S("socks"));
493  if (!proxy.isEmpty()) {
494  // Make sure the scheme of SOCKS proxy is always set to "socks://".
495  const int index = proxy.indexOf(QL1S("://"));
496  proxy = QL1S("socks://") + (index == -1 ? proxy : proxy.mid(index+3));
497  proxyList << proxy;
498  }
499  }
500  break;
501  case NoProxy:
502  default:
503  break;
504  }
505  }
506 
507  if (proxyList.isEmpty()) {
508  proxyList << QL1S("DIRECT");
509  }
510 
511  return proxyList;
512 }
513 
514 void KProtocolManager::badProxy( const QString &proxy )
515 {
516  QDBusInterface( QL1S("org.kde.kded"), QL1S("/modules/proxyscout"))
517  .asyncCall(QL1S("blackListProxy"), proxy);
518 
519  PRIVATE_DATA;
520  const QStringList keys (d->cachedProxyData.keys());
521  Q_FOREACH(const QString& key, keys) {
522  d->cachedProxyData[key]->removeAddress(proxy);
523  }
524 }
525 
526 QString KProtocolManager::slaveProtocol(const KUrl &url, QString &proxy)
527 {
528  QStringList proxyList;
529  const QString protocol = KProtocolManager::slaveProtocol(url, proxyList);
530  if (!proxyList.isEmpty()) {
531  proxy = proxyList.first();
532  }
533  return protocol;
534 }
535 
536 // Generates proxy cache key from request given url.
537 static void extractProxyCacheKeyFromUrl(const KUrl& u, QString* key)
538 {
539  if (!key)
540  return;
541 
542  *key = u.protocol();
543  *key += u.host();
544 
545  if (u.port() > 0)
546  *key += QString::number(u.port());
547 }
548 
549 QString KProtocolManager::slaveProtocol(const KUrl &url, QStringList &proxyList)
550 {
551  if (url.hasSubUrl()) { // We don't want the suburl's protocol
552  const KUrl::List list = KUrl::split(url);
553  return slaveProtocol(list.last(), proxyList);
554  }
555 
556  proxyList.clear();
557 
558  // Do not perform a proxy lookup for any url classified as a ":local" url or
559  // one that does not have a host component or if proxy is disabled.
560  QString protocol (url.protocol());
561  if (!url.hasHost()
562  || KProtocolInfo::protocolClass(protocol) == QL1S(":local")
563  || KProtocolManager::proxyType() == KProtocolManager::NoProxy) {
564  return protocol;
565  }
566 
567  QString proxyCacheKey;
568  extractProxyCacheKeyFromUrl(url, &proxyCacheKey);
569 
570  PRIVATE_DATA;
571  // Look for cached proxy information to avoid more work.
572  if (d->cachedProxyData.contains(proxyCacheKey)) {
573  KProxyData* data = d->cachedProxyData.object(proxyCacheKey);
574  proxyList = data->proxyList;
575  return data->protocol;
576  }
577 
578  const QStringList proxies = proxiesForUrl(url);
579  const int count = proxies.count();
580 
581  if (count > 0 && !(count == 1 && proxies.first() == QL1S("DIRECT"))) {
582  Q_FOREACH(const QString& proxy, proxies) {
583  if (proxy == QL1S("DIRECT")) {
584  proxyList << proxy;
585  } else {
586  KUrl u (proxy);
587  if (!u.isEmpty() && u.isValid() && !u.protocol().isEmpty()) {
588  proxyList << proxy;
589  }
590  }
591  }
592  }
593 
594  // The idea behind slave protocols is not applicable to http
595  // and webdav protocols as well as protocols unknown to KDE.
596  if (!proxyList.isEmpty()
597  && !protocol.startsWith(QL1S("http"))
598  && !protocol.startsWith(QL1S("webdav"))
599  && KProtocolInfo::isKnownProtocol(protocol)) {
600  Q_FOREACH(const QString& proxy, proxyList) {
601  KUrl u (proxy);
602  if (u.isValid() && KProtocolInfo::isKnownProtocol(u.protocol())) {
603  protocol = u.protocol();
604  break;
605  }
606  }
607  }
608 
609  // cache the proxy information...
610  d->cachedProxyData.insert(proxyCacheKey, new KProxyData(protocol, proxyList));
611  return protocol;
612 }
613 
614 /*================================= USER-AGENT SETTINGS =====================*/
615 
616 QString KProtocolManager::userAgentForHost( const QString& hostname )
617 {
618  const QString sendUserAgent = KIO::SlaveConfig::self()->configData("http", hostname.toLower(), "SendUserAgent").toLower();
619  if (sendUserAgent == QL1S("false"))
620  return QString();
621 
622  const QString useragent = KIO::SlaveConfig::self()->configData("http", hostname.toLower(), "UserAgent");
623 
624  // Return the default user-agent if none is specified
625  // for the requested host.
626  if (useragent.isEmpty())
627  return defaultUserAgent();
628 
629  return useragent;
630 }
631 
632 QString KProtocolManager::defaultUserAgent( )
633 {
634  const QString modifiers = KIO::SlaveConfig::self()->configData("http", QString(), "UserAgentKeys");
635  return defaultUserAgent(modifiers);
636 }
637 
638 static QString defaultUserAgentFromPreferredService()
639 {
640  QString agentStr;
641 
642  // Check if the default COMPONENT contains a custom default UA string...
643  KService::Ptr service = KMimeTypeTrader::self()->preferredService(QL1S("text/html"),
644  QL1S("KParts/ReadOnlyPart"));
645  if (service && service->showInKDE())
646  agentStr = service->property(QL1S("X-KDE-Default-UserAgent"),
647  QVariant::String).toString();
648  return agentStr;
649 }
650 
651 static QString platform()
652 {
653 #if defined(Q_WS_X11)
654  return QL1S("X11");
655 #elif defined(Q_WS_MAC)
656  return QL1S("Macintosh");
657 #elif defined(Q_WS_WIN)
658  return QL1S("Windows");
659 #elif defined(Q_WS_S60)
660  return QL1S("Symbian");
661 #endif
662 }
663 
664 QString KProtocolManager::defaultUserAgent( const QString &_modifiers )
665 {
666  PRIVATE_DATA;
667  QString modifiers = _modifiers.toLower();
668  if (modifiers.isEmpty())
669  modifiers = DEFAULT_USER_AGENT_KEYS;
670 
671  if (d->modifiers == modifiers && !d->useragent.isEmpty())
672  return d->useragent;
673 
674  d->modifiers = modifiers;
675 
676  /*
677  The following code attempts to determine the default user agent string
678  from the 'X-KDE-UA-DEFAULT-STRING' property of the desktop file
679  for the preferred service that was configured to handle the 'text/html'
680  mime type. If the prefered service's desktop file does not specify this
681  property, the long standing default user agent string will be used.
682  The following keyword placeholders are automatically converted when the
683  user agent string is read from the property:
684 
685  %SECURITY% Expands to"N" when SSL is not supported, otherwise it is ignored.
686  %OSNAME% Expands to operating system name, e.g. Linux.
687  %OSVERSION% Expands to operating system version, e.g. 2.6.32
688  %SYSTYPE% Expands to machine or system type, e.g. i386
689  %PLATFORM% Expands to windowing system, e.g. X11 on Unix/Linux.
690  %LANGUAGE% Expands to default language in use, e.g. en-US.
691  %APPVERSION% Expands to QCoreApplication applicationName()/applicationVerison(),
692  e.g. Konqueror/4.5.0. If application name and/or application version
693  number are not set, then "KDE" and the runtime KDE version numbers
694  are used respectively.
695 
696  All of the keywords are handled case-insensitively.
697  */
698 
699  QString systemName, systemVersion, machine, supp;
700  const bool sysInfoFound = getSystemNameVersionAndMachine( systemName, systemVersion, machine );
701  QString agentStr = defaultUserAgentFromPreferredService();
702 
703  if (agentStr.isEmpty())
704  {
705  supp += platform();
706 
707  if (sysInfoFound)
708  {
709  if (modifiers.contains('o'))
710  {
711  supp += QL1S("; ");
712  supp += systemName;
713  if (modifiers.contains('v'))
714  {
715  supp += QL1C(' ');
716  supp += systemVersion;
717  }
718 
719  if (modifiers.contains('m'))
720  {
721  supp += QL1C(' ');
722  supp += machine;
723  }
724  }
725 
726  if (modifiers.contains('l'))
727  {
728  supp += QL1S("; ");
729  supp += KGlobal::locale()->language();
730  }
731  }
732 
733  // Full format: Mozilla/5.0 (Linux
734  d->useragent = QL1S("Mozilla/5.0 (");
735  d->useragent += supp;
736  d->useragent += QL1S(") KHTML/");
737  d->useragent += QString::number(KDE::versionMajor());
738  d->useragent += QL1C('.');
739  d->useragent += QString::number(KDE::versionMinor());
740  d->useragent += QL1C('.');
741  d->useragent += QString::number(KDE::versionRelease());
742  d->useragent += QL1S(" (like Gecko) Konqueror/");
743  d->useragent += QString::number(KDE::versionMajor());
744  d->useragent += QL1C('.');
745  d->useragent += QString::number(KDE::versionMinor());
746  d->useragent += QL1S(" Fedora/4.10.2-2.fc18");
747  }
748  else
749  {
750  QString appName = QCoreApplication::applicationName();
751  if (appName.isEmpty() || appName.startsWith(QL1S("kcmshell"), Qt::CaseInsensitive))
752  appName = QL1S ("KDE");
753 
754  QString appVersion = QCoreApplication::applicationVersion();
755  if (appVersion.isEmpty()) {
756  appVersion += QString::number(KDE::versionMajor());
757  appVersion += QL1C('.');
758  appVersion += QString::number(KDE::versionMinor());
759  appVersion += QL1C('.');
760  appVersion += QString::number(KDE::versionRelease());
761  }
762 
763  appName += QL1C('/');
764  appName += appVersion;
765 
766  agentStr.replace(QL1S("%appversion%"), appName, Qt::CaseInsensitive);
767 
768  if (!QSslSocket::supportsSsl())
769  agentStr.replace(QL1S("%security%"), QL1S("N"), Qt::CaseInsensitive);
770  else
771  agentStr.remove(QL1S("%security%"), Qt::CaseInsensitive);
772 
773  if (sysInfoFound)
774  {
775  // Platform (e.g. X11). It is no longer configurable from UI.
776  agentStr.replace(QL1S("%platform%"), platform(), Qt::CaseInsensitive);
777 
778  // Operating system (e.g. Linux)
779  if (modifiers.contains('o'))
780  {
781  agentStr.replace(QL1S("%osname%"), systemName, Qt::CaseInsensitive);
782 
783  // OS version (e.g. 2.6.36)
784  if (modifiers.contains('v'))
785  agentStr.replace(QL1S("%osversion%"), systemVersion, Qt::CaseInsensitive);
786  else
787  agentStr.remove(QL1S("%osversion%"), Qt::CaseInsensitive);
788 
789  // Machine type (i686, x86-64, etc.)
790  if (modifiers.contains('m'))
791  agentStr.replace(QL1S("%systype%"), machine, Qt::CaseInsensitive);
792  else
793  agentStr.remove(QL1S("%systype%"), Qt::CaseInsensitive);
794  }
795  else
796  {
797  agentStr.remove(QL1S("%osname%"), Qt::CaseInsensitive);
798  agentStr.remove(QL1S("%osversion%"), Qt::CaseInsensitive);
799  agentStr.remove(QL1S("%systype%"), Qt::CaseInsensitive);
800  }
801 
802  // Language (e.g. en_US)
803  if (modifiers.contains('l'))
804  agentStr.replace(QL1S("%language%"), KGlobal::locale()->language(), Qt::CaseInsensitive);
805  else
806  agentStr.remove(QL1S("%language%"), Qt::CaseInsensitive);
807 
808  // Clean up unnecessary separators that could be left over from the
809  // possible keyword removal above...
810  agentStr.replace(QRegExp("[(]\\s*[;]\\s*"), QL1S("("));
811  agentStr.replace(QRegExp("[;]\\s*[;]\\s*"), QL1S("; "));
812  agentStr.replace(QRegExp("\\s*[;]\\s*[)]"), QL1S(")"));
813  }
814  else
815  {
816  agentStr.remove(QL1S("%osname%"));
817  agentStr.remove(QL1S("%osversion%"));
818  agentStr.remove(QL1S("%platform%"));
819  agentStr.remove(QL1S("%systype%"));
820  agentStr.remove(QL1S("%language%"));
821  }
822 
823  d->useragent = agentStr.simplified();
824  }
825 
826  //kDebug() << "USERAGENT STRING:" << d->useragent;
827  return d->useragent;
828 }
829 
830 QString KProtocolManager::userAgentForApplication( const QString &appName, const QString& appVersion,
831  const QStringList& extraInfo )
832 {
833  QString systemName, systemVersion, machine, info;
834 
835  if (getSystemNameVersionAndMachine( systemName, systemVersion, machine ))
836  {
837  info += systemName;
838  info += QL1C('/');
839  info += systemVersion;
840  info += QL1S("; ");
841  }
842 
843  info += QL1S("KDE/");
844  info += QString::number(KDE::versionMajor());
845  info += QL1C('.');
846  info += QString::number(KDE::versionMinor());
847  info += QL1C('.');
848  info += QString::number(KDE::versionRelease());
849 
850  if (!machine.isEmpty())
851  {
852  info += QL1S("; ");
853  info += machine;
854  }
855 
856  info += QL1S("; ");
857  info += extraInfo.join(QL1S("; "));
858 
859  return (appName + QL1C('/') + appVersion + QL1S(" (") + info + QL1C(')'));
860 }
861 
862 bool KProtocolManager::getSystemNameVersionAndMachine(
863  QString& systemName, QString& systemVersion, QString& machine )
864 {
865  struct utsname unameBuf;
866  if ( 0 != uname( &unameBuf ) )
867  return false;
868 #if defined(Q_WS_WIN) && !defined(_WIN32_WCE)
869  // we do not use unameBuf.sysname information constructed in kdewin32
870  // because we want to get separate name and version
871  systemName = QL1S( "Windows" );
872  OSVERSIONINFOEX versioninfo;
873  ZeroMemory(&versioninfo, sizeof(OSVERSIONINFOEX));
874  // try calling GetVersionEx using the OSVERSIONINFOEX, if that fails, try using the OSVERSIONINFO
875  versioninfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
876  bool ok = GetVersionEx( (OSVERSIONINFO *) &versioninfo );
877  if ( !ok ) {
878  versioninfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
879  ok = GetVersionEx( (OSVERSIONINFO *) &versioninfo );
880  }
881  if ( ok ) {
882  systemVersion = QString::number(versioninfo.dwMajorVersion);
883  systemVersion += QL1C('.');
884  systemVersion += QString::number(versioninfo.dwMinorVersion);
885  }
886 #else
887  systemName = unameBuf.sysname;
888  systemVersion = unameBuf.release;
889 #endif
890  machine = unameBuf.machine;
891  return true;
892 }
893 
894 QString KProtocolManager::acceptLanguagesHeader()
895 {
896  static const QString &english = KGlobal::staticQString("en");
897 
898  // User's desktop language preference.
899  QStringList languageList = KGlobal::locale()->languageList();
900 
901  // Replace possible "C" in the language list with "en", unless "en" is
902  // already pressent. This is to keep user's priorities in order.
903  // If afterwards "en" is still not present, append it.
904  int idx = languageList.indexOf(QString::fromLatin1("C"));
905  if (idx != -1)
906  {
907  if (languageList.contains(english))
908  languageList.removeAt(idx);
909  else
910  languageList[idx] = english;
911  }
912  if (!languageList.contains(english))
913  languageList += english;
914 
915  // Some languages may have web codes different from locale codes,
916  // read them from the config and insert in proper order.
917  KConfig acclangConf("accept-languages.codes", KConfig::NoGlobals);
918  KConfigGroup replacementCodes(&acclangConf, "ReplacementCodes");
919  QStringList languageListFinal;
920  Q_FOREACH (const QString &lang, languageList)
921  {
922  const QStringList langs = replacementCodes.readEntry(lang, QStringList());
923  if (langs.isEmpty())
924  languageListFinal += lang;
925  else
926  languageListFinal += langs;
927  }
928 
929  // The header is composed of comma separated languages, with an optional
930  // associated priority estimate (q=1..0) defaulting to 1.
931  // As our language tags are already sorted by priority, we'll just decrease
932  // the value evenly
933  int prio = 10;
934  QString header;
935  Q_FOREACH (const QString &lang,languageListFinal) {
936  header += lang;
937  if (prio < 10) {
938  header += QL1S(";q=0.");
939  header += QString::number(prio);
940  }
941  // do not add cosmetic whitespace in here : it is less compatible (#220677)
942  header += QL1S(",");
943  if (prio > 1)
944  --prio;
945  }
946  header.chop(1);
947 
948  // Some of the languages may have country specifier delimited by
949  // underscore, or modifier delimited by at-sign.
950  // The header should use dashes instead.
951  header.replace('_', '-');
952  header.replace('@', '-');
953 
954  return header;
955 }
956 
957 /*==================================== OTHERS ===============================*/
958 
959 bool KProtocolManager::markPartial()
960 {
961  return config()->group(QByteArray()).readEntry( "MarkPartial", true );
962 }
963 
964 int KProtocolManager::minimumKeepSize()
965 {
966  return config()->group(QByteArray()).readEntry( "MinimumKeepSize",
967  DEFAULT_MINIMUM_KEEP_SIZE ); // 5000 byte
968 }
969 
970 bool KProtocolManager::autoResume()
971 {
972  return config()->group(QByteArray()).readEntry( "AutoResume", false );
973 }
974 
975 bool KProtocolManager::persistentConnections()
976 {
977  return config()->group(QByteArray()).readEntry( "PersistentConnections", true );
978 }
979 
980 bool KProtocolManager::persistentProxyConnection()
981 {
982  return config()->group(QByteArray()).readEntry( "PersistentProxyConnection", false );
983 }
984 
985 QString KProtocolManager::proxyConfigScript()
986 {
987  return config()->group("Proxy Settings").readEntry( "Proxy Config Script" );
988 }
989 
990 /* =========================== PROTOCOL CAPABILITIES ============== */
991 
992 static KProtocolInfo::Ptr findProtocol(const KUrl &url)
993 {
994  QString protocol = url.protocol();
995 
996  if ( !KProtocolInfo::proxiedBy( protocol ).isEmpty() )
997  {
998  QString dummy;
999  protocol = KProtocolManager::slaveProtocol(url, dummy);
1000  }
1001 
1002  return KProtocolInfoFactory::self()->findProtocol(protocol);
1003 }
1004 
1005 
1006 KProtocolInfo::Type KProtocolManager::inputType( const KUrl &url )
1007 {
1008  KProtocolInfo::Ptr prot = findProtocol(url);
1009  if ( !prot )
1010  return KProtocolInfo::T_NONE;
1011 
1012  return prot->m_inputType;
1013 }
1014 
1015 KProtocolInfo::Type KProtocolManager::outputType( const KUrl &url )
1016 {
1017  KProtocolInfo::Ptr prot = findProtocol(url);
1018  if ( !prot )
1019  return KProtocolInfo::T_NONE;
1020 
1021  return prot->m_outputType;
1022 }
1023 
1024 
1025 bool KProtocolManager::isSourceProtocol( const KUrl &url )
1026 {
1027  KProtocolInfo::Ptr prot = findProtocol(url);
1028  if ( !prot )
1029  return false;
1030 
1031  return prot->m_isSourceProtocol;
1032 }
1033 
1034 bool KProtocolManager::supportsListing( const KUrl &url )
1035 {
1036  KProtocolInfo::Ptr prot = findProtocol(url);
1037  if ( !prot )
1038  return false;
1039 
1040  return prot->m_supportsListing;
1041 }
1042 
1043 QStringList KProtocolManager::listing( const KUrl &url )
1044 {
1045  KProtocolInfo::Ptr prot = findProtocol(url);
1046  if ( !prot )
1047  return QStringList();
1048 
1049  return prot->m_listing;
1050 }
1051 
1052 bool KProtocolManager::supportsReading( const KUrl &url )
1053 {
1054  KProtocolInfo::Ptr prot = findProtocol(url);
1055  if ( !prot )
1056  return false;
1057 
1058  return prot->m_supportsReading;
1059 }
1060 
1061 bool KProtocolManager::supportsWriting( const KUrl &url )
1062 {
1063  KProtocolInfo::Ptr prot = findProtocol(url);
1064  if ( !prot )
1065  return false;
1066 
1067  return prot->m_supportsWriting;
1068 }
1069 
1070 bool KProtocolManager::supportsMakeDir( const KUrl &url )
1071 {
1072  KProtocolInfo::Ptr prot = findProtocol(url);
1073  if ( !prot )
1074  return false;
1075 
1076  return prot->m_supportsMakeDir;
1077 }
1078 
1079 bool KProtocolManager::supportsDeleting( const KUrl &url )
1080 {
1081  KProtocolInfo::Ptr prot = findProtocol(url);
1082  if ( !prot )
1083  return false;
1084 
1085  return prot->m_supportsDeleting;
1086 }
1087 
1088 bool KProtocolManager::supportsLinking( const KUrl &url )
1089 {
1090  KProtocolInfo::Ptr prot = findProtocol(url);
1091  if ( !prot )
1092  return false;
1093 
1094  return prot->m_supportsLinking;
1095 }
1096 
1097 bool KProtocolManager::supportsMoving( const KUrl &url )
1098 {
1099  KProtocolInfo::Ptr prot = findProtocol(url);
1100  if ( !prot )
1101  return false;
1102 
1103  return prot->m_supportsMoving;
1104 }
1105 
1106 bool KProtocolManager::supportsOpening( const KUrl &url )
1107 {
1108  KProtocolInfo::Ptr prot = findProtocol(url);
1109  if ( !prot )
1110  return false;
1111 
1112  return prot->m_supportsOpening;
1113 }
1114 
1115 bool KProtocolManager::canCopyFromFile( const KUrl &url )
1116 {
1117  KProtocolInfo::Ptr prot = findProtocol(url);
1118  if ( !prot )
1119  return false;
1120 
1121  return prot->m_canCopyFromFile;
1122 }
1123 
1124 
1125 bool KProtocolManager::canCopyToFile( const KUrl &url )
1126 {
1127  KProtocolInfo::Ptr prot = findProtocol(url);
1128  if ( !prot )
1129  return false;
1130 
1131  return prot->m_canCopyToFile;
1132 }
1133 
1134 bool KProtocolManager::canRenameFromFile( const KUrl &url )
1135 {
1136  KProtocolInfo::Ptr prot = findProtocol(url);
1137  if ( !prot )
1138  return false;
1139 
1140  return prot->canRenameFromFile();
1141 }
1142 
1143 
1144 bool KProtocolManager::canRenameToFile( const KUrl &url )
1145 {
1146  KProtocolInfo::Ptr prot = findProtocol(url);
1147  if ( !prot )
1148  return false;
1149 
1150  return prot->canRenameToFile();
1151 }
1152 
1153 bool KProtocolManager::canDeleteRecursive( const KUrl &url )
1154 {
1155  KProtocolInfo::Ptr prot = findProtocol(url);
1156  if ( !prot )
1157  return false;
1158 
1159  return prot->canDeleteRecursive();
1160 }
1161 
1162 KProtocolInfo::FileNameUsedForCopying KProtocolManager::fileNameUsedForCopying( const KUrl &url )
1163 {
1164  KProtocolInfo::Ptr prot = findProtocol(url);
1165  if ( !prot )
1166  return KProtocolInfo::FromUrl;
1167 
1168  return prot->fileNameUsedForCopying();
1169 }
1170 
1171 QString KProtocolManager::defaultMimetype( const KUrl &url )
1172 {
1173  KProtocolInfo::Ptr prot = findProtocol(url);
1174  if ( !prot )
1175  return QString();
1176 
1177  return prot->m_defaultMimetype;
1178 }
1179 
1180 QString KProtocolManager::protocolForArchiveMimetype( const QString& mimeType )
1181 {
1182  PRIVATE_DATA;
1183  if (d->protocolForArchiveMimetypes.isEmpty()) {
1184  const KProtocolInfo::List allProtocols = KProtocolInfoFactory::self()->allProtocols();
1185  for (KProtocolInfo::List::const_iterator it = allProtocols.begin();
1186  it != allProtocols.end(); ++it) {
1187  const QStringList archiveMimetypes = (*it)->archiveMimeTypes();
1188  Q_FOREACH(const QString& mime, archiveMimetypes) {
1189  d->protocolForArchiveMimetypes.insert(mime, (*it)->name());
1190  }
1191  }
1192  }
1193  return d->protocolForArchiveMimetypes.value(mimeType);
1194 }
1195 
1196 QString KProtocolManager::charsetFor(const KUrl& url)
1197 {
1198  return KIO::SlaveConfig::self()->configData(url.scheme(), url.host(), QLatin1String("Charset"));
1199 }
1200 
1201 #undef PRIVATE_DATA
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Tue Apr 16 2013 19:14:52 by doxygen 1.8.3.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs-4.10.2 API Reference

Skip menu "kdelibs-4.10.2 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal