28 #include <sys/utsname.h>
30 #include <QtCore/QCoreApplication>
31 #include <QtNetwork/QSslSocket>
32 #include <QtNetwork/QHostAddress>
33 #include <QtNetwork/QHostInfo>
34 #include <QtDBus/QtDBus>
35 #include <QtCore/QCache>
37 #if !defined(QT_NO_NETWORKPROXY) && (defined (Q_OS_WIN32) || defined(Q_OS_MAC))
38 #include <QtNetwork/QNetworkProxyFactory>
39 #include <QtNetwork/QNetworkProxyQuery>
42 #include <kdeversion.h>
57 #define QL1S(x) QLatin1String(x)
58 #define QL1C(x) QLatin1Char(x)
67 static bool revmatch(
const char *host,
const char *nplist)
72 const char *hptr = host + strlen( host ) - 1;
73 const char *nptr = nplist + strlen( nplist ) - 1;
74 const char *shptr = hptr;
76 while ( nptr >= nplist )
83 while(--nptr>=nplist && *nptr!=
',' && *nptr!=
' ') ;
86 while(--nptr>=nplist && (*nptr==
',' || *nptr==
' ')) ;
90 if ( nptr==nplist || nptr[-1]==
',' || nptr[-1]==
' ')
92 if ( nptr[-1]==
'/' && hptr == host )
105 class KProxyData :
public QObject
109 :protocol(slaveProtocol)
110 ,proxyList(proxyAddresses) {
113 void removeAddress(
const QString& address) {
114 proxyList.removeAll(address);
121 class KProtocolManagerPrivate
124 KProtocolManagerPrivate();
125 ~KProtocolManagerPrivate();
126 bool shouldIgnoreProxyFor(
const KUrl& url);
133 QList<SubnetPair> noProxySubnets;
134 QCache<QString, KProxyData> cachedProxyData;
141 KProtocolManagerPrivate::KProtocolManagerPrivate()
144 qAddPostRoutine(kProtocolManagerPrivate.destroy);
145 cachedProxyData.setMaxCost(200);
148 KProtocolManagerPrivate::~KProtocolManagerPrivate()
150 qRemovePostRoutine(kProtocolManagerPrivate.destroy);
156 bool KProtocolManagerPrivate::shouldIgnoreProxyFor(
const KUrl& url)
158 bool isMatch =
false;
164 if (useNoProxyList && noProxyFor.isEmpty()) {
166 QMutableStringListIterator it (noProxyForList);
167 while (it.hasNext()) {
168 SubnetPair subnet = QHostAddress::parseSubnet(it.next());
169 if (!subnet.first.isNull()) {
170 noProxySubnets << subnet;
174 noProxyFor = noProxyForList.join(
QL1S(
","));
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();
187 if (!isMatch && url.port() > 0) {
190 host = qhost.toLatin1();
191 isMatch =
revmatch (host, no_proxy);
196 if (!isMatch && !host.isEmpty() && (strchr(host,
'.') == NULL)) {
197 isMatch =
revmatch(
"<local>", no_proxy);
201 const QString host (url.host());
203 if (!noProxySubnets.isEmpty() && !host.isEmpty()) {
204 QHostAddress address (host);
207 if (address.isNull()) {
208 kDebug() <<
"Performing DNS lookup for" << host;
210 const QList<QHostAddress> addresses = info.addresses();
211 if (!addresses.isEmpty())
212 address = addresses.first();
215 if (!address.isNull()) {
216 Q_FOREACH(
const SubnetPair& subnet, noProxySubnets) {
217 if (address.isInSubnet(subnet)) {
225 return (useRevProxy != isMatch);
229 #define PRIVATE_DATA \
230 KProtocolManagerPrivate *d = kProtocolManagerPrivate
235 if (d->http_config) {
236 d->http_config->reparseConfiguration();
239 d->config->reparseConfiguration();
241 d->cachedProxyData.clear();
242 d->noProxyFor.clear();
243 d->modifiers.clear();
244 d->useragent.clear();
263 if (!d->http_config) {
309 return cg.
readEntry(
"ReversedException",
false);
358 noProxy = QString::fromLocal8Bit(qgetenv(noProxy.toLocal8Bit()));
365 if (scheme.compare(
QL1S(
"webdav"), Qt::CaseInsensitive) == 0)
368 if (scheme.compare(
QL1S(
"webdavs"), Qt::CaseInsensitive) == 0)
369 return QL1S(
"https");
371 return scheme.toLower();
378 const int index = proxyStr.lastIndexOf(
QL1C(
' '));
382 const QString portStr(proxyStr.right(proxyStr.length() - index - 1));
385 proxyStr = proxyStr.left(index) +
QL1C(
':') + portStr;
398 if (proxies.isEmpty())
401 return proxies.first();
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)
414 const QNetworkProxy::ProxyType type = proxy.type();
415 if (type == QNetworkProxy::NoProxy || type == QNetworkProxy::DefaultProxy)
417 proxies <<
QL1S(
"DIRECT");
421 if (type == QNetworkProxy::HttpProxy || type == QNetworkProxy::HttpCachingProxy)
423 else if (type == QNetworkProxy::Socks5Proxy)
425 else if (type == QNetworkProxy::FtpCachingProxy)
428 url.setHost(proxy.hostName());
429 url.setPort(proxy.port());
431 proxies << url.
url();
437 if (!proxyVar.isEmpty()) {
438 const QString proxy (QString::fromLocal8Bit(qgetenv(proxyVar.toLocal8Bit())).trimmed());
439 if (!proxy.isEmpty()) {
445 if (!proxyVar.isEmpty()) {
446 QString proxy = QString::fromLocal8Bit(qgetenv(proxyVar.toLocal8Bit())).trimmed();
448 const int index = proxy.indexOf(
QL1S(
"://"));
449 proxy =
QL1S(
"socks://") + (index == -1 ? proxy : proxy.mid(index+3));
450 if (!proxy.isEmpty()) {
463 if (!d->shouldIgnoreProxyFor(url)) {
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());
489 if (!proxy.isEmpty())
493 if (!proxy.isEmpty()) {
495 const int index = proxy.indexOf(
QL1S(
"://"));
496 proxy =
QL1S(
"socks://") + (index == -1 ? proxy : proxy.mid(index+3));
507 if (proxyList.isEmpty()) {
508 proxyList <<
QL1S(
"DIRECT");
516 QDBusInterface(
QL1S(
"org.kde.kded"),
QL1S(
"/modules/proxyscout"))
517 .asyncCall(
QL1S(
"blackListProxy"), proxy);
520 const QStringList keys (d->cachedProxyData.keys());
521 Q_FOREACH(
const QString& key, keys) {
522 d->cachedProxyData[key]->removeAddress(proxy);
530 if (!proxyList.isEmpty()) {
531 proxy = proxyList.first();
572 if (d->cachedProxyData.contains(proxyCacheKey)) {
573 KProxyData* data = d->cachedProxyData.object(proxyCacheKey);
574 proxyList = data->proxyList;
575 return data->protocol;
579 const int count = proxies.count();
581 if (count > 0 && !(count == 1 && proxies.first() ==
QL1S(
"DIRECT"))) {
582 Q_FOREACH(
const QString& proxy, proxies) {
583 if (proxy ==
QL1S(
"DIRECT")) {
587 if (!u.isEmpty() && u.isValid() && !u.
protocol().isEmpty()) {
596 if (!proxyList.isEmpty()
597 && !protocol.startsWith(
QL1S(
"http"))
598 && !protocol.startsWith(
QL1S(
"webdav"))
600 Q_FOREACH(
const QString& proxy, proxyList) {
610 d->cachedProxyData.insert(proxyCacheKey,
new KProxyData(protocol, proxyList));
619 if (sendUserAgent ==
QL1S(
"false"))
626 if (useragent.isEmpty())
644 QL1S(
"KParts/ReadOnlyPart"));
646 agentStr = service->
property(
QL1S(
"X-KDE-Default-UserAgent"),
647 QVariant::String).toString();
653 #if defined(Q_WS_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");
667 QString modifiers = _modifiers.toLower();
668 if (modifiers.isEmpty())
671 if (d->modifiers == modifiers && !d->useragent.isEmpty())
674 d->modifiers = modifiers;
699 QString systemName, systemVersion, machine, supp;
703 if (agentStr.isEmpty())
709 if (modifiers.contains(
'o'))
713 if (modifiers.contains(
'v'))
716 supp += systemVersion;
719 if (modifiers.contains(
'm'))
726 if (modifiers.contains(
'l'))
734 d->useragent =
QL1S(
"Mozilla/5.0 (");
735 d->useragent += supp;
736 d->useragent +=
QL1S(
") KHTML/");
738 d->useragent +=
QL1C(
'.');
740 d->useragent +=
QL1C(
'.');
742 d->useragent +=
QL1S(
" (like Gecko) Konqueror/");
744 d->useragent +=
QL1C(
'.');
746 d->useragent +=
QL1S(
" Fedora/4.10.4-1.fc17");
750 QString appName = QCoreApplication::applicationName();
751 if (appName.isEmpty() || appName.startsWith(
QL1S(
"kcmshell"), Qt::CaseInsensitive))
752 appName =
QL1S (
"KDE");
754 QString appVersion = QCoreApplication::applicationVersion();
755 if (appVersion.isEmpty()) {
757 appVersion +=
QL1C(
'.');
759 appVersion +=
QL1C(
'.');
763 appName +=
QL1C(
'/');
764 appName += appVersion;
766 agentStr.replace(
QL1S(
"%appversion%"), appName, Qt::CaseInsensitive);
768 if (!QSslSocket::supportsSsl())
769 agentStr.replace(
QL1S(
"%security%"),
QL1S(
"N"), Qt::CaseInsensitive);
771 agentStr.remove(
QL1S(
"%security%"), Qt::CaseInsensitive);
776 agentStr.replace(
QL1S(
"%platform%"),
platform(), Qt::CaseInsensitive);
779 if (modifiers.contains(
'o'))
781 agentStr.replace(
QL1S(
"%osname%"), systemName, Qt::CaseInsensitive);
784 if (modifiers.contains(
'v'))
785 agentStr.replace(
QL1S(
"%osversion%"), systemVersion, Qt::CaseInsensitive);
787 agentStr.remove(
QL1S(
"%osversion%"), Qt::CaseInsensitive);
790 if (modifiers.contains(
'm'))
791 agentStr.replace(
QL1S(
"%systype%"), machine, Qt::CaseInsensitive);
793 agentStr.remove(
QL1S(
"%systype%"), Qt::CaseInsensitive);
797 agentStr.remove(
QL1S(
"%osname%"), Qt::CaseInsensitive);
798 agentStr.remove(
QL1S(
"%osversion%"), Qt::CaseInsensitive);
799 agentStr.remove(
QL1S(
"%systype%"), Qt::CaseInsensitive);
803 if (modifiers.contains(
'l'))
806 agentStr.remove(
QL1S(
"%language%"), Qt::CaseInsensitive);
810 agentStr.replace(QRegExp(
"[(]\\s*[;]\\s*"),
QL1S(
"("));
811 agentStr.replace(QRegExp(
"[;]\\s*[;]\\s*"),
QL1S(
"; "));
812 agentStr.replace(QRegExp(
"\\s*[;]\\s*[)]"),
QL1S(
")"));
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%"));
823 d->useragent = agentStr.simplified();
833 QString systemName, systemVersion, machine, info;
839 info += systemVersion;
843 info +=
QL1S(
"KDE/");
850 if (!machine.isEmpty())
857 info += extraInfo.join(
QL1S(
"; "));
859 return (appName +
QL1C(
'/') + appVersion +
QL1S(
" (") + info +
QL1C(
')'));
865 struct utsname unameBuf;
866 if ( 0 != uname( &unameBuf ) )
868 #if defined(Q_WS_WIN) && !defined(_WIN32_WCE)
871 systemName =
QL1S(
"Windows" );
872 OSVERSIONINFOEX versioninfo;
873 ZeroMemory(&versioninfo,
sizeof(OSVERSIONINFOEX));
875 versioninfo.dwOSVersionInfoSize =
sizeof(OSVERSIONINFOEX);
876 bool ok = GetVersionEx( (OSVERSIONINFO *) &versioninfo );
878 versioninfo.dwOSVersionInfoSize =
sizeof (OSVERSIONINFO);
879 ok = GetVersionEx( (OSVERSIONINFO *) &versioninfo );
883 systemVersion +=
QL1C(
'.');
887 systemName = unameBuf.sysname;
888 systemVersion = unameBuf.release;
890 machine = unameBuf.machine;
904 int idx = languageList.indexOf(QString::fromLatin1(
"C"));
907 if (languageList.contains(english))
908 languageList.removeAt(idx);
910 languageList[idx] = english;
912 if (!languageList.contains(english))
913 languageList += english;
918 KConfigGroup replacementCodes(&acclangConf,
"ReplacementCodes");
920 Q_FOREACH (
const QString &lang, languageList)
924 languageListFinal += lang;
926 languageListFinal += langs;
935 Q_FOREACH (
const QString &lang,languageListFinal) {
938 header +=
QL1S(
";q=0.");
951 header.replace(
'_',
'-');
952 header.replace(
'@',
'-');
961 return config()->
group(QByteArray()).
readEntry(
"MarkPartial",
true );
966 return config()->
group(QByteArray()).
readEntry(
"MinimumKeepSize",
972 return config()->
group(QByteArray()).
readEntry(
"AutoResume",
false );
977 return config()->
group(QByteArray()).
readEntry(
"PersistentConnections",
true );
982 return config()->
group(QByteArray()).
readEntry(
"PersistentProxyConnection",
false );
987 return config()->
group(
"Proxy Settings").
readEntry(
"Proxy Config Script" );
1012 return prot->m_inputType;
1021 return prot->m_outputType;
1031 return prot->m_isSourceProtocol;
1040 return prot->m_supportsListing;
1049 return prot->m_listing;
1058 return prot->m_supportsReading;
1067 return prot->m_supportsWriting;
1076 return prot->m_supportsMakeDir;
1085 return prot->m_supportsDeleting;
1094 return prot->m_supportsLinking;
1103 return prot->m_supportsMoving;
1112 return prot->m_supportsOpening;
1121 return prot->m_canCopyFromFile;
1131 return prot->m_canCopyToFile;
1140 return prot->canRenameFromFile();
1150 return prot->canRenameToFile();
1159 return prot->canDeleteRecursive();
1168 return prot->fileNameUsedForCopying();
1177 return prot->m_defaultMimetype;
1183 if (d->protocolForArchiveMimetypes.isEmpty()) {
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());
1193 return d->protocolForArchiveMimetypes.value(mimeType);