• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.11.5 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")) || protocol.startsWith(QL1S("ftp"))) {
474  QDBusReply<QStringList> reply = QDBusInterface(QL1S("org.kde.kded"),
475  QL1S("/modules/proxyscout"),
476  QL1S("org.kde.KPAC.ProxyScout"))
477  .call(QL1S("proxiesForUrl"), u.url());
478  proxyList = reply;
479  }
480  break;
481  }
482  case EnvVarProxy:
483  proxyList = getSystemProxyFor( url );
484  break;
485  case ManualProxy:
486  {
487  QString proxy (proxyFor(url.protocol()));
488  if (!proxy.isEmpty())
489  proxyList << proxy;
490  // Add the socks proxy as an alternate proxy if it exists,
491  proxy = proxyFor(QL1S("socks"));
492  if (!proxy.isEmpty()) {
493  // Make sure the scheme of SOCKS proxy is always set to "socks://".
494  const int index = proxy.indexOf(QL1S("://"));
495  proxy = QL1S("socks://") + (index == -1 ? proxy : proxy.mid(index+3));
496  proxyList << proxy;
497  }
498  }
499  break;
500  case NoProxy:
501  default:
502  break;
503  }
504  }
505 
506  if (proxyList.isEmpty()) {
507  proxyList << QL1S("DIRECT");
508  }
509 
510  return proxyList;
511 }
512 
513 void KProtocolManager::badProxy( const QString &proxy )
514 {
515  QDBusInterface( QL1S("org.kde.kded"), QL1S("/modules/proxyscout"))
516  .asyncCall(QL1S("blackListProxy"), proxy);
517 
518  PRIVATE_DATA;
519  const QStringList keys (d->cachedProxyData.keys());
520  Q_FOREACH(const QString& key, keys) {
521  d->cachedProxyData[key]->removeAddress(proxy);
522  }
523 }
524 
525 QString KProtocolManager::slaveProtocol(const KUrl &url, QString &proxy)
526 {
527  QStringList proxyList;
528  const QString protocol = KProtocolManager::slaveProtocol(url, proxyList);
529  if (!proxyList.isEmpty()) {
530  proxy = proxyList.first();
531  }
532  return protocol;
533 }
534 
535 // Generates proxy cache key from request given url.
536 static void extractProxyCacheKeyFromUrl(const KUrl& u, QString* key)
537 {
538  if (!key)
539  return;
540 
541  *key = u.protocol();
542  *key += u.host();
543 
544  if (u.port() > 0)
545  *key += QString::number(u.port());
546 }
547 
548 QString KProtocolManager::slaveProtocol(const KUrl &url, QStringList &proxyList)
549 {
550  if (url.hasSubUrl()) { // We don't want the suburl's protocol
551  const KUrl::List list = KUrl::split(url);
552  return slaveProtocol(list.last(), proxyList);
553  }
554 
555  proxyList.clear();
556 
557  // Do not perform a proxy lookup for any url classified as a ":local" url or
558  // one that does not have a host component or if proxy is disabled.
559  QString protocol (url.protocol());
560  if (!url.hasHost()
561  || KProtocolInfo::protocolClass(protocol) == QL1S(":local")
562  || KProtocolManager::proxyType() == KProtocolManager::NoProxy) {
563  return protocol;
564  }
565 
566  QString proxyCacheKey;
567  extractProxyCacheKeyFromUrl(url, &proxyCacheKey);
568 
569  PRIVATE_DATA;
570  // Look for cached proxy information to avoid more work.
571  if (d->cachedProxyData.contains(proxyCacheKey)) {
572  KProxyData* data = d->cachedProxyData.object(proxyCacheKey);
573  proxyList = data->proxyList;
574  return data->protocol;
575  }
576 
577  const QStringList proxies = proxiesForUrl(url);
578  const int count = proxies.count();
579 
580  if (count > 0 && !(count == 1 && proxies.first() == QL1S("DIRECT"))) {
581  Q_FOREACH(const QString& proxy, proxies) {
582  if (proxy == QL1S("DIRECT")) {
583  proxyList << proxy;
584  } else {
585  KUrl u (proxy);
586  if (!u.isEmpty() && u.isValid() && !u.protocol().isEmpty()) {
587  proxyList << proxy;
588  }
589  }
590  }
591  }
592 
593  // The idea behind slave protocols is not applicable to http
594  // and webdav protocols as well as protocols unknown to KDE.
595  if (!proxyList.isEmpty()
596  && !protocol.startsWith(QL1S("http"))
597  && !protocol.startsWith(QL1S("webdav"))
598  && KProtocolInfo::isKnownProtocol(protocol)) {
599  Q_FOREACH(const QString& proxy, proxyList) {
600  KUrl u (proxy);
601  if (u.isValid() && KProtocolInfo::isKnownProtocol(u.protocol())) {
602  protocol = u.protocol();
603  break;
604  }
605  }
606  }
607 
608  // cache the proxy information...
609  d->cachedProxyData.insert(proxyCacheKey, new KProxyData(protocol, proxyList));
610  return protocol;
611 }
612 
613 /*================================= USER-AGENT SETTINGS =====================*/
614 
615 QString KProtocolManager::userAgentForHost( const QString& hostname )
616 {
617  const QString sendUserAgent = KIO::SlaveConfig::self()->configData("http", hostname.toLower(), "SendUserAgent").toLower();
618  if (sendUserAgent == QL1S("false"))
619  return QString();
620 
621  const QString useragent = KIO::SlaveConfig::self()->configData("http", hostname.toLower(), "UserAgent");
622 
623  // Return the default user-agent if none is specified
624  // for the requested host.
625  if (useragent.isEmpty())
626  return defaultUserAgent();
627 
628  return useragent;
629 }
630 
631 QString KProtocolManager::defaultUserAgent( )
632 {
633  const QString modifiers = KIO::SlaveConfig::self()->configData("http", QString(), "UserAgentKeys");
634  return defaultUserAgent(modifiers);
635 }
636 
637 static QString defaultUserAgentFromPreferredService()
638 {
639  QString agentStr;
640 
641  // Check if the default COMPONENT contains a custom default UA string...
642  KService::Ptr service = KMimeTypeTrader::self()->preferredService(QL1S("text/html"),
643  QL1S("KParts/ReadOnlyPart"));
644  if (service && service->showInKDE())
645  agentStr = service->property(QL1S("X-KDE-Default-UserAgent"),
646  QVariant::String).toString();
647  return agentStr;
648 }
649 
650 static QString platform()
651 {
652 #if defined(Q_WS_X11)
653  return QL1S("X11");
654 #elif defined(Q_WS_MAC)
655  return QL1S("Macintosh");
656 #elif defined(Q_WS_WIN)
657  return QL1S("Windows");
658 #elif defined(Q_WS_S60)
659  return QL1S("Symbian");
660 #endif
661 }
662 
663 QString KProtocolManager::defaultUserAgent( const QString &_modifiers )
664 {
665  PRIVATE_DATA;
666  QString modifiers = _modifiers.toLower();
667  if (modifiers.isEmpty())
668  modifiers = DEFAULT_USER_AGENT_KEYS;
669 
670  if (d->modifiers == modifiers && !d->useragent.isEmpty())
671  return d->useragent;
672 
673  d->modifiers = modifiers;
674 
675  /*
676  The following code attempts to determine the default user agent string
677  from the 'X-KDE-UA-DEFAULT-STRING' property of the desktop file
678  for the preferred service that was configured to handle the 'text/html'
679  mime type. If the prefered service's desktop file does not specify this
680  property, the long standing default user agent string will be used.
681  The following keyword placeholders are automatically converted when the
682  user agent string is read from the property:
683 
684  %SECURITY% Expands to"N" when SSL is not supported, otherwise it is ignored.
685  %OSNAME% Expands to operating system name, e.g. Linux.
686  %OSVERSION% Expands to operating system version, e.g. 2.6.32
687  %SYSTYPE% Expands to machine or system type, e.g. i386
688  %PLATFORM% Expands to windowing system, e.g. X11 on Unix/Linux.
689  %LANGUAGE% Expands to default language in use, e.g. en-US.
690  %APPVERSION% Expands to QCoreApplication applicationName()/applicationVerison(),
691  e.g. Konqueror/4.5.0. If application name and/or application version
692  number are not set, then "KDE" and the runtime KDE version numbers
693  are used respectively.
694 
695  All of the keywords are handled case-insensitively.
696  */
697 
698  QString systemName, systemVersion, machine, supp;
699  const bool sysInfoFound = getSystemNameVersionAndMachine( systemName, systemVersion, machine );
700  QString agentStr = defaultUserAgentFromPreferredService();
701 
702  if (agentStr.isEmpty())
703  {
704  supp += platform();
705 
706  if (sysInfoFound)
707  {
708  if (modifiers.contains('o'))
709  {
710  supp += QL1S("; ");
711  supp += systemName;
712  if (modifiers.contains('v'))
713  {
714  supp += QL1C(' ');
715  supp += systemVersion;
716  }
717 
718  if (modifiers.contains('m'))
719  {
720  supp += QL1C(' ');
721  supp += machine;
722  }
723  }
724 
725  if (modifiers.contains('l'))
726  {
727  supp += QL1S("; ");
728  supp += KGlobal::locale()->language();
729  }
730  }
731 
732  // Full format: Mozilla/5.0 (Linux
733  d->useragent = QL1S("Mozilla/5.0 (");
734  d->useragent += supp;
735  d->useragent += QL1S(") KHTML/");
736  d->useragent += QString::number(KDE::versionMajor());
737  d->useragent += QL1C('.');
738  d->useragent += QString::number(KDE::versionMinor());
739  d->useragent += QL1C('.');
740  d->useragent += QString::number(KDE::versionRelease());
741  d->useragent += QL1S(" (like Gecko) Konqueror/");
742  d->useragent += QString::number(KDE::versionMajor());
743  d->useragent += QL1C('.');
744  d->useragent += QString::number(KDE::versionMinor());
745  d->useragent += QL1S(" Fedora/4.11.5-2.fc19");
746  }
747  else
748  {
749  QString appName = QCoreApplication::applicationName();
750  if (appName.isEmpty() || appName.startsWith(QL1S("kcmshell"), Qt::CaseInsensitive))
751  appName = QL1S ("KDE");
752 
753  QString appVersion = QCoreApplication::applicationVersion();
754  if (appVersion.isEmpty()) {
755  appVersion += QString::number(KDE::versionMajor());
756  appVersion += QL1C('.');
757  appVersion += QString::number(KDE::versionMinor());
758  appVersion += QL1C('.');
759  appVersion += QString::number(KDE::versionRelease());
760  }
761 
762  appName += QL1C('/');
763  appName += appVersion;
764 
765  agentStr.replace(QL1S("%appversion%"), appName, Qt::CaseInsensitive);
766 
767  if (!QSslSocket::supportsSsl())
768  agentStr.replace(QL1S("%security%"), QL1S("N"), Qt::CaseInsensitive);
769  else
770  agentStr.remove(QL1S("%security%"), Qt::CaseInsensitive);
771 
772  if (sysInfoFound)
773  {
774  // Platform (e.g. X11). It is no longer configurable from UI.
775  agentStr.replace(QL1S("%platform%"), platform(), Qt::CaseInsensitive);
776 
777  // Operating system (e.g. Linux)
778  if (modifiers.contains('o'))
779  {
780  agentStr.replace(QL1S("%osname%"), systemName, Qt::CaseInsensitive);
781 
782  // OS version (e.g. 2.6.36)
783  if (modifiers.contains('v'))
784  agentStr.replace(QL1S("%osversion%"), systemVersion, Qt::CaseInsensitive);
785  else
786  agentStr.remove(QL1S("%osversion%"), Qt::CaseInsensitive);
787 
788  // Machine type (i686, x86-64, etc.)
789  if (modifiers.contains('m'))
790  agentStr.replace(QL1S("%systype%"), machine, Qt::CaseInsensitive);
791  else
792  agentStr.remove(QL1S("%systype%"), Qt::CaseInsensitive);
793  }
794  else
795  {
796  agentStr.remove(QL1S("%osname%"), Qt::CaseInsensitive);
797  agentStr.remove(QL1S("%osversion%"), Qt::CaseInsensitive);
798  agentStr.remove(QL1S("%systype%"), Qt::CaseInsensitive);
799  }
800 
801  // Language (e.g. en_US)
802  if (modifiers.contains('l'))
803  agentStr.replace(QL1S("%language%"), KGlobal::locale()->language(), Qt::CaseInsensitive);
804  else
805  agentStr.remove(QL1S("%language%"), Qt::CaseInsensitive);
806 
807  // Clean up unnecessary separators that could be left over from the
808  // possible keyword removal above...
809  agentStr.replace(QRegExp("[(]\\s*[;]\\s*"), QL1S("("));
810  agentStr.replace(QRegExp("[;]\\s*[;]\\s*"), QL1S("; "));
811  agentStr.replace(QRegExp("\\s*[;]\\s*[)]"), QL1S(")"));
812  }
813  else
814  {
815  agentStr.remove(QL1S("%osname%"));
816  agentStr.remove(QL1S("%osversion%"));
817  agentStr.remove(QL1S("%platform%"));
818  agentStr.remove(QL1S("%systype%"));
819  agentStr.remove(QL1S("%language%"));
820  }
821 
822  d->useragent = agentStr.simplified();
823  }
824 
825  //kDebug() << "USERAGENT STRING:" << d->useragent;
826  return d->useragent;
827 }
828 
829 QString KProtocolManager::userAgentForApplication( const QString &appName, const QString& appVersion,
830  const QStringList& extraInfo )
831 {
832  QString systemName, systemVersion, machine, info;
833 
834  if (getSystemNameVersionAndMachine( systemName, systemVersion, machine ))
835  {
836  info += systemName;
837  info += QL1C('/');
838  info += systemVersion;
839  info += QL1S("; ");
840  }
841 
842  info += QL1S("KDE/");
843  info += QString::number(KDE::versionMajor());
844  info += QL1C('.');
845  info += QString::number(KDE::versionMinor());
846  info += QL1C('.');
847  info += QString::number(KDE::versionRelease());
848 
849  if (!machine.isEmpty())
850  {
851  info += QL1S("; ");
852  info += machine;
853  }
854 
855  info += QL1S("; ");
856  info += extraInfo.join(QL1S("; "));
857 
858  return (appName + QL1C('/') + appVersion + QL1S(" (") + info + QL1C(')'));
859 }
860 
861 bool KProtocolManager::getSystemNameVersionAndMachine(
862  QString& systemName, QString& systemVersion, QString& machine )
863 {
864  struct utsname unameBuf;
865  if ( 0 != uname( &unameBuf ) )
866  return false;
867 #if defined(Q_WS_WIN) && !defined(_WIN32_WCE)
868  // we do not use unameBuf.sysname information constructed in kdewin32
869  // because we want to get separate name and version
870  systemName = QL1S( "Windows" );
871  OSVERSIONINFOEX versioninfo;
872  ZeroMemory(&versioninfo, sizeof(OSVERSIONINFOEX));
873  // try calling GetVersionEx using the OSVERSIONINFOEX, if that fails, try using the OSVERSIONINFO
874  versioninfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
875  bool ok = GetVersionEx( (OSVERSIONINFO *) &versioninfo );
876  if ( !ok ) {
877  versioninfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
878  ok = GetVersionEx( (OSVERSIONINFO *) &versioninfo );
879  }
880  if ( ok ) {
881  systemVersion = QString::number(versioninfo.dwMajorVersion);
882  systemVersion += QL1C('.');
883  systemVersion += QString::number(versioninfo.dwMinorVersion);
884  }
885 #else
886  systemName = unameBuf.sysname;
887  systemVersion = unameBuf.release;
888 #endif
889  machine = unameBuf.machine;
890  return true;
891 }
892 
893 QString KProtocolManager::acceptLanguagesHeader()
894 {
895  static const QString &english = KGlobal::staticQString("en");
896 
897  // User's desktop language preference.
898  QStringList languageList = KGlobal::locale()->languageList();
899 
900  // Replace possible "C" in the language list with "en", unless "en" is
901  // already pressent. This is to keep user's priorities in order.
902  // If afterwards "en" is still not present, append it.
903  int idx = languageList.indexOf(QString::fromLatin1("C"));
904  if (idx != -1)
905  {
906  if (languageList.contains(english))
907  languageList.removeAt(idx);
908  else
909  languageList[idx] = english;
910  }
911  if (!languageList.contains(english))
912  languageList += english;
913 
914  // Some languages may have web codes different from locale codes,
915  // read them from the config and insert in proper order.
916  KConfig acclangConf("accept-languages.codes", KConfig::NoGlobals);
917  KConfigGroup replacementCodes(&acclangConf, "ReplacementCodes");
918  QStringList languageListFinal;
919  Q_FOREACH (const QString &lang, languageList)
920  {
921  const QStringList langs = replacementCodes.readEntry(lang, QStringList());
922  if (langs.isEmpty())
923  languageListFinal += lang;
924  else
925  languageListFinal += langs;
926  }
927 
928  // The header is composed of comma separated languages, with an optional
929  // associated priority estimate (q=1..0) defaulting to 1.
930  // As our language tags are already sorted by priority, we'll just decrease
931  // the value evenly
932  int prio = 10;
933  QString header;
934  Q_FOREACH (const QString &lang,languageListFinal) {
935  header += lang;
936  if (prio < 10) {
937  header += QL1S(";q=0.");
938  header += QString::number(prio);
939  }
940  // do not add cosmetic whitespace in here : it is less compatible (#220677)
941  header += QL1S(",");
942  if (prio > 1)
943  --prio;
944  }
945  header.chop(1);
946 
947  // Some of the languages may have country specifier delimited by
948  // underscore, or modifier delimited by at-sign.
949  // The header should use dashes instead.
950  header.replace('_', '-');
951  header.replace('@', '-');
952 
953  return header;
954 }
955 
956 /*==================================== OTHERS ===============================*/
957 
958 bool KProtocolManager::markPartial()
959 {
960  return config()->group(QByteArray()).readEntry( "MarkPartial", true );
961 }
962 
963 int KProtocolManager::minimumKeepSize()
964 {
965  return config()->group(QByteArray()).readEntry( "MinimumKeepSize",
966  DEFAULT_MINIMUM_KEEP_SIZE ); // 5000 byte
967 }
968 
969 bool KProtocolManager::autoResume()
970 {
971  return config()->group(QByteArray()).readEntry( "AutoResume", false );
972 }
973 
974 bool KProtocolManager::persistentConnections()
975 {
976  return config()->group(QByteArray()).readEntry( "PersistentConnections", true );
977 }
978 
979 bool KProtocolManager::persistentProxyConnection()
980 {
981  return config()->group(QByteArray()).readEntry( "PersistentProxyConnection", false );
982 }
983 
984 QString KProtocolManager::proxyConfigScript()
985 {
986  return config()->group("Proxy Settings").readEntry( "Proxy Config Script" );
987 }
988 
989 /* =========================== PROTOCOL CAPABILITIES ============== */
990 
991 static KProtocolInfo::Ptr findProtocol(const KUrl &url)
992 {
993  QString protocol = url.protocol();
994 
995  if ( !KProtocolInfo::proxiedBy( protocol ).isEmpty() )
996  {
997  QString dummy;
998  protocol = KProtocolManager::slaveProtocol(url, dummy);
999  }
1000 
1001  return KProtocolInfoFactory::self()->findProtocol(protocol);
1002 }
1003 
1004 
1005 KProtocolInfo::Type KProtocolManager::inputType( const KUrl &url )
1006 {
1007  KProtocolInfo::Ptr prot = findProtocol(url);
1008  if ( !prot )
1009  return KProtocolInfo::T_NONE;
1010 
1011  return prot->m_inputType;
1012 }
1013 
1014 KProtocolInfo::Type KProtocolManager::outputType( const KUrl &url )
1015 {
1016  KProtocolInfo::Ptr prot = findProtocol(url);
1017  if ( !prot )
1018  return KProtocolInfo::T_NONE;
1019 
1020  return prot->m_outputType;
1021 }
1022 
1023 
1024 bool KProtocolManager::isSourceProtocol( const KUrl &url )
1025 {
1026  KProtocolInfo::Ptr prot = findProtocol(url);
1027  if ( !prot )
1028  return false;
1029 
1030  return prot->m_isSourceProtocol;
1031 }
1032 
1033 bool KProtocolManager::supportsListing( const KUrl &url )
1034 {
1035  KProtocolInfo::Ptr prot = findProtocol(url);
1036  if ( !prot )
1037  return false;
1038 
1039  return prot->m_supportsListing;
1040 }
1041 
1042 QStringList KProtocolManager::listing( const KUrl &url )
1043 {
1044  KProtocolInfo::Ptr prot = findProtocol(url);
1045  if ( !prot )
1046  return QStringList();
1047 
1048  return prot->m_listing;
1049 }
1050 
1051 bool KProtocolManager::supportsReading( const KUrl &url )
1052 {
1053  KProtocolInfo::Ptr prot = findProtocol(url);
1054  if ( !prot )
1055  return false;
1056 
1057  return prot->m_supportsReading;
1058 }
1059 
1060 bool KProtocolManager::supportsWriting( const KUrl &url )
1061 {
1062  KProtocolInfo::Ptr prot = findProtocol(url);
1063  if ( !prot )
1064  return false;
1065 
1066  return prot->m_supportsWriting;
1067 }
1068 
1069 bool KProtocolManager::supportsMakeDir( const KUrl &url )
1070 {
1071  KProtocolInfo::Ptr prot = findProtocol(url);
1072  if ( !prot )
1073  return false;
1074 
1075  return prot->m_supportsMakeDir;
1076 }
1077 
1078 bool KProtocolManager::supportsDeleting( const KUrl &url )
1079 {
1080  KProtocolInfo::Ptr prot = findProtocol(url);
1081  if ( !prot )
1082  return false;
1083 
1084  return prot->m_supportsDeleting;
1085 }
1086 
1087 bool KProtocolManager::supportsLinking( const KUrl &url )
1088 {
1089  KProtocolInfo::Ptr prot = findProtocol(url);
1090  if ( !prot )
1091  return false;
1092 
1093  return prot->m_supportsLinking;
1094 }
1095 
1096 bool KProtocolManager::supportsMoving( const KUrl &url )
1097 {
1098  KProtocolInfo::Ptr prot = findProtocol(url);
1099  if ( !prot )
1100  return false;
1101 
1102  return prot->m_supportsMoving;
1103 }
1104 
1105 bool KProtocolManager::supportsOpening( const KUrl &url )
1106 {
1107  KProtocolInfo::Ptr prot = findProtocol(url);
1108  if ( !prot )
1109  return false;
1110 
1111  return prot->m_supportsOpening;
1112 }
1113 
1114 bool KProtocolManager::canCopyFromFile( const KUrl &url )
1115 {
1116  KProtocolInfo::Ptr prot = findProtocol(url);
1117  if ( !prot )
1118  return false;
1119 
1120  return prot->m_canCopyFromFile;
1121 }
1122 
1123 
1124 bool KProtocolManager::canCopyToFile( const KUrl &url )
1125 {
1126  KProtocolInfo::Ptr prot = findProtocol(url);
1127  if ( !prot )
1128  return false;
1129 
1130  return prot->m_canCopyToFile;
1131 }
1132 
1133 bool KProtocolManager::canRenameFromFile( const KUrl &url )
1134 {
1135  KProtocolInfo::Ptr prot = findProtocol(url);
1136  if ( !prot )
1137  return false;
1138 
1139  return prot->canRenameFromFile();
1140 }
1141 
1142 
1143 bool KProtocolManager::canRenameToFile( const KUrl &url )
1144 {
1145  KProtocolInfo::Ptr prot = findProtocol(url);
1146  if ( !prot )
1147  return false;
1148 
1149  return prot->canRenameToFile();
1150 }
1151 
1152 bool KProtocolManager::canDeleteRecursive( const KUrl &url )
1153 {
1154  KProtocolInfo::Ptr prot = findProtocol(url);
1155  if ( !prot )
1156  return false;
1157 
1158  return prot->canDeleteRecursive();
1159 }
1160 
1161 KProtocolInfo::FileNameUsedForCopying KProtocolManager::fileNameUsedForCopying( const KUrl &url )
1162 {
1163  KProtocolInfo::Ptr prot = findProtocol(url);
1164  if ( !prot )
1165  return KProtocolInfo::FromUrl;
1166 
1167  return prot->fileNameUsedForCopying();
1168 }
1169 
1170 QString KProtocolManager::defaultMimetype( const KUrl &url )
1171 {
1172  KProtocolInfo::Ptr prot = findProtocol(url);
1173  if ( !prot )
1174  return QString();
1175 
1176  return prot->m_defaultMimetype;
1177 }
1178 
1179 QString KProtocolManager::protocolForArchiveMimetype( const QString& mimeType )
1180 {
1181  PRIVATE_DATA;
1182  if (d->protocolForArchiveMimetypes.isEmpty()) {
1183  const KProtocolInfo::List allProtocols = KProtocolInfoFactory::self()->allProtocols();
1184  for (KProtocolInfo::List::const_iterator it = allProtocols.begin();
1185  it != allProtocols.end(); ++it) {
1186  const QStringList archiveMimetypes = (*it)->archiveMimeTypes();
1187  Q_FOREACH(const QString& mime, archiveMimetypes) {
1188  d->protocolForArchiveMimetypes.insert(mime, (*it)->name());
1189  }
1190  }
1191  }
1192  return d->protocolForArchiveMimetypes.value(mimeType);
1193 }
1194 
1195 QString KProtocolManager::charsetFor(const KUrl& url)
1196 {
1197  return KIO::SlaveConfig::self()->configData(url.scheme(), url.host(), QLatin1String("Charset"));
1198 }
1199 
1200 #undef PRIVATE_DATA
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Mon May 5 2014 18:13:42 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.11.5 API Reference

Skip menu "kdelibs-4.11.5 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