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);
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;
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 );
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")) || 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());
488 if (!proxy.isEmpty())
492 if (!proxy.isEmpty()) {
494 const int index = proxy.indexOf(
QL1S(
"://"));
495 proxy =
QL1S(
"socks://") + (index == -1 ? proxy : proxy.mid(index+3));
506 if (proxyList.isEmpty()) {
507 proxyList <<
QL1S(
"DIRECT");
515 QDBusInterface(
QL1S(
"org.kde.kded"),
QL1S(
"/modules/proxyscout"))
516 .asyncCall(
QL1S(
"blackListProxy"), proxy);
519 const QStringList keys (d->cachedProxyData.keys());
520 Q_FOREACH(
const QString& key, keys) {
521 d->cachedProxyData[key]->removeAddress(proxy);
529 if (!proxyList.isEmpty()) {
530 proxy = proxyList.first();
571 if (d->cachedProxyData.contains(proxyCacheKey)) {
572 KProxyData* data = d->cachedProxyData.object(proxyCacheKey);
573 proxyList = data->proxyList;
574 return data->protocol;
578 const int count = proxies.count();
580 if (count > 0 && !(count == 1 && proxies.first() ==
QL1S(
"DIRECT"))) {
581 Q_FOREACH(
const QString& proxy, proxies) {
582 if (proxy ==
QL1S(
"DIRECT")) {
586 if (!u.isEmpty() && u.isValid() && !u.
protocol().isEmpty()) {
595 if (!proxyList.isEmpty()
596 && !protocol.startsWith(
QL1S(
"http"))
597 && !protocol.startsWith(
QL1S(
"webdav"))
599 Q_FOREACH(
const QString& proxy, proxyList) {
609 d->cachedProxyData.insert(proxyCacheKey,
new KProxyData(protocol, proxyList));
618 if (sendUserAgent ==
QL1S(
"false"))
625 if (useragent.isEmpty())
643 QL1S(
"KParts/ReadOnlyPart"));
645 agentStr = service->
property(
QL1S(
"X-KDE-Default-UserAgent"),
646 QVariant::String).toString();
652 #if defined(Q_WS_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");
666 QString modifiers = _modifiers.toLower();
667 if (modifiers.isEmpty())
670 if (d->modifiers == modifiers && !d->useragent.isEmpty())
673 d->modifiers = modifiers;
698 QString systemName, systemVersion, machine, supp;
702 if (agentStr.isEmpty())
708 if (modifiers.contains(
'o'))
712 if (modifiers.contains(
'v'))
715 supp += systemVersion;
718 if (modifiers.contains(
'm'))
725 if (modifiers.contains(
'l'))
728 supp += KGlobal::locale()->language();
733 d->useragent =
QL1S(
"Mozilla/5.0 (");
734 d->useragent += supp;
735 d->useragent +=
QL1S(
") KHTML/");
737 d->useragent +=
QL1C(
'.');
739 d->useragent +=
QL1C(
'.');
741 d->useragent +=
QL1S(
" (like Gecko) Konqueror/");
743 d->useragent +=
QL1C(
'.');
745 d->useragent +=
QL1S(
" Fedora/4.11.5-2.fc19");
749 QString appName = QCoreApplication::applicationName();
750 if (appName.isEmpty() || appName.startsWith(
QL1S(
"kcmshell"), Qt::CaseInsensitive))
751 appName =
QL1S (
"KDE");
753 QString appVersion = QCoreApplication::applicationVersion();
754 if (appVersion.isEmpty()) {
756 appVersion +=
QL1C(
'.');
758 appVersion +=
QL1C(
'.');
762 appName +=
QL1C(
'/');
763 appName += appVersion;
765 agentStr.replace(
QL1S(
"%appversion%"), appName, Qt::CaseInsensitive);
767 if (!QSslSocket::supportsSsl())
768 agentStr.replace(
QL1S(
"%security%"),
QL1S(
"N"), Qt::CaseInsensitive);
770 agentStr.remove(
QL1S(
"%security%"), Qt::CaseInsensitive);
775 agentStr.replace(
QL1S(
"%platform%"),
platform(), Qt::CaseInsensitive);
778 if (modifiers.contains(
'o'))
780 agentStr.replace(
QL1S(
"%osname%"), systemName, Qt::CaseInsensitive);
783 if (modifiers.contains(
'v'))
784 agentStr.replace(
QL1S(
"%osversion%"), systemVersion, Qt::CaseInsensitive);
786 agentStr.remove(
QL1S(
"%osversion%"), Qt::CaseInsensitive);
789 if (modifiers.contains(
'm'))
790 agentStr.replace(
QL1S(
"%systype%"), machine, Qt::CaseInsensitive);
792 agentStr.remove(
QL1S(
"%systype%"), Qt::CaseInsensitive);
796 agentStr.remove(
QL1S(
"%osname%"), Qt::CaseInsensitive);
797 agentStr.remove(
QL1S(
"%osversion%"), Qt::CaseInsensitive);
798 agentStr.remove(
QL1S(
"%systype%"), Qt::CaseInsensitive);
802 if (modifiers.contains(
'l'))
803 agentStr.replace(
QL1S(
"%language%"), KGlobal::locale()->language(), Qt::CaseInsensitive);
805 agentStr.remove(
QL1S(
"%language%"), Qt::CaseInsensitive);
809 agentStr.replace(QRegExp(
"[(]\\s*[;]\\s*"),
QL1S(
"("));
810 agentStr.replace(QRegExp(
"[;]\\s*[;]\\s*"),
QL1S(
"; "));
811 agentStr.replace(QRegExp(
"\\s*[;]\\s*[)]"),
QL1S(
")"));
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%"));
822 d->useragent = agentStr.simplified();
832 QString systemName, systemVersion, machine, info;
838 info += systemVersion;
842 info +=
QL1S(
"KDE/");
849 if (!machine.isEmpty())
856 info += extraInfo.join(
QL1S(
"; "));
858 return (appName +
QL1C(
'/') + appVersion +
QL1S(
" (") + info +
QL1C(
')'));
864 struct utsname unameBuf;
865 if ( 0 != uname( &unameBuf ) )
867 #if defined(Q_WS_WIN) && !defined(_WIN32_WCE)
870 systemName =
QL1S(
"Windows" );
871 OSVERSIONINFOEX versioninfo;
872 ZeroMemory(&versioninfo,
sizeof(OSVERSIONINFOEX));
874 versioninfo.dwOSVersionInfoSize =
sizeof(OSVERSIONINFOEX);
875 bool ok = GetVersionEx( (OSVERSIONINFO *) &versioninfo );
877 versioninfo.dwOSVersionInfoSize =
sizeof (OSVERSIONINFO);
878 ok = GetVersionEx( (OSVERSIONINFO *) &versioninfo );
882 systemVersion +=
QL1C(
'.');
886 systemName = unameBuf.sysname;
887 systemVersion = unameBuf.release;
889 machine = unameBuf.machine;
895 static const QString &english = KGlobal::staticQString(
"en");
898 QStringList languageList = KGlobal::locale()->languageList();
903 int idx = languageList.indexOf(QString::fromLatin1(
"C"));
906 if (languageList.contains(english))
907 languageList.removeAt(idx);
909 languageList[idx] = english;
911 if (!languageList.contains(english))
912 languageList += english;
917 KConfigGroup replacementCodes(&acclangConf,
"ReplacementCodes");
919 Q_FOREACH (
const QString &lang, languageList)
923 languageListFinal += lang;
925 languageListFinal += langs;
934 Q_FOREACH (
const QString &lang,languageListFinal) {
937 header +=
QL1S(
";q=0.");
950 header.replace(
'_',
'-');
951 header.replace(
'@',
'-');
960 return config()->
group(QByteArray()).
readEntry(
"MarkPartial",
true );
965 return config()->
group(QByteArray()).
readEntry(
"MinimumKeepSize",
971 return config()->
group(QByteArray()).
readEntry(
"AutoResume",
false );
976 return config()->
group(QByteArray()).
readEntry(
"PersistentConnections",
true );
981 return config()->
group(QByteArray()).
readEntry(
"PersistentProxyConnection",
false );
986 return config()->
group(
"Proxy Settings").
readEntry(
"Proxy Config Script" );
1011 return prot->m_inputType;
1020 return prot->m_outputType;
1030 return prot->m_isSourceProtocol;
1039 return prot->m_supportsListing;
1048 return prot->m_listing;
1057 return prot->m_supportsReading;
1066 return prot->m_supportsWriting;
1075 return prot->m_supportsMakeDir;
1084 return prot->m_supportsDeleting;
1093 return prot->m_supportsLinking;
1102 return prot->m_supportsMoving;
1111 return prot->m_supportsOpening;
1120 return prot->m_canCopyFromFile;
1130 return prot->m_canCopyToFile;
1139 return prot->canRenameFromFile();
1149 return prot->canRenameToFile();
1158 return prot->canDeleteRecursive();
1167 return prot->fileNameUsedForCopying();
1176 return prot->m_defaultMimetype;
1182 if (d->protocolForArchiveMimetypes.isEmpty()) {
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());
1192 return d->protocolForArchiveMimetypes.value(mimeType);