summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAron Rosenberg <aronrosenberg@gmail.com>2012-04-04 16:34:33 -0700
committerQt by Nokia <qt-info@nokia.com>2012-04-11 01:42:12 +0200
commitc524bbbb8aa4ba10bac68292a3078534f1b51df5 (patch)
treea6208ed0a2e93a2da6f463fd25903a60c1464b2f /src
parent97f9c6f8cdc0dd0f676c6ccfeb1cd6096e72fd48 (diff)
Add Proxy Auto Config support (PAC) on Mac
Adds support for fetching and parsing Proxy Auto Config files if one is specified in the Mac System Preferences Task-Number: QTBUG-2069 Task-Number: QTIFW-28 Change-Id: I91feb999222187e7467f2c41383904cf0cff8633 Reviewed-by: Shane Kearns <shane.kearns@accenture.com>
Diffstat (limited to 'src')
-rw-r--r--src/network/kernel/kernel.pri2
-rw-r--r--src/network/kernel/qnetworkproxy_mac.cpp116
2 files changed, 113 insertions, 5 deletions
diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri
index a5508af31f..f9ea6065a3 100644
--- a/src/network/kernel/kernel.pri
+++ b/src/network/kernel/kernel.pri
@@ -33,7 +33,7 @@ win32: {
}
integrity:SOURCES += kernel/qdnslookup_unix.cpp kernel/qhostinfo_unix.cpp kernel/qnetworkinterface_unix.cpp
-mac:LIBS_PRIVATE += -framework SystemConfiguration -framework CoreFoundation
+mac:LIBS_PRIVATE += -framework SystemConfiguration -framework CoreFoundation -framework CoreServices
mac:SOURCES += kernel/qnetworkproxy_mac.cpp
else:win32:SOURCES += kernel/qnetworkproxy_win.cpp
else:SOURCES += kernel/qnetworkproxy_generic.cpp
diff --git a/src/network/kernel/qnetworkproxy_mac.cpp b/src/network/kernel/qnetworkproxy_mac.cpp
index d25917ee47..3e62c0f867 100644
--- a/src/network/kernel/qnetworkproxy_mac.cpp
+++ b/src/network/kernel/qnetworkproxy_mac.cpp
@@ -48,6 +48,7 @@
#include <QtCore/QRegExp>
#include <QtCore/QStringList>
+#include <QtCore/QUrl>
#include <QtCore/qendian.h>
#include <QtCore/qstringlist.h>
#include "private/qcore_mac_p.h"
@@ -146,6 +147,66 @@ static QNetworkProxy proxyFromDictionary(CFDictionaryRef dict, QNetworkProxy::Pr
return QNetworkProxy();
}
+
+static QNetworkProxy proxyFromDictionary(CFDictionaryRef dict)
+{
+ QNetworkProxy::ProxyType proxyType = QNetworkProxy::DefaultProxy;
+ QString hostName;
+ quint16 port = 0;
+ QString user;
+ QString password;
+
+ CFStringRef cfProxyType = (CFStringRef)CFDictionaryGetValue(dict, kCFProxyTypeKey);
+ if (CFStringCompare(cfProxyType, kCFProxyTypeNone, 0) == kCFCompareEqualTo) {
+ proxyType = QNetworkProxy::NoProxy;
+ } else if (CFStringCompare(cfProxyType, kCFProxyTypeFTP, 0) == kCFCompareEqualTo) {
+ proxyType = QNetworkProxy::FtpCachingProxy;
+ } else if (CFStringCompare(cfProxyType, kCFProxyTypeHTTP, 0) == kCFCompareEqualTo) {
+ proxyType = QNetworkProxy::HttpProxy;
+ } else if (CFStringCompare(cfProxyType, kCFProxyTypeHTTPS, 0) == kCFCompareEqualTo) {
+ proxyType = QNetworkProxy::HttpProxy;
+ } else if (CFStringCompare(cfProxyType, kCFProxyTypeSOCKS, 0) == kCFCompareEqualTo) {
+ proxyType = QNetworkProxy::Socks5Proxy;
+ }
+
+ hostName = QCFString::toQString((CFStringRef)CFDictionaryGetValue(dict, kCFProxyHostNameKey));
+ user = QCFString::toQString((CFStringRef)CFDictionaryGetValue(dict, kCFProxyUsernameKey));
+ password = QCFString::toQString((CFStringRef)CFDictionaryGetValue(dict, kCFProxyPasswordKey));
+
+ CFNumberRef portNumber = (CFNumberRef)CFDictionaryGetValue(dict, kCFProxyPortNumberKey);
+ if (portNumber) {
+ CFNumberGetValue(portNumber, kCFNumberSInt16Type, &port);
+ }
+
+ return QNetworkProxy(proxyType, hostName, port, user, password);
+}
+
+const char * cfurlErrorDescription(SInt32 errorCode)
+{
+ switch (errorCode) {
+ case kCFURLUnknownError:
+ return "Unknown Error";
+ case kCFURLUnknownSchemeError:
+ return "Unknown Scheme";
+ case kCFURLResourceNotFoundError:
+ return "Resource Not Found";
+ case kCFURLResourceAccessViolationError:
+ return "Resource Access Violation";
+ case kCFURLRemoteHostUnavailableError:
+ return "Remote Host Unavailable";
+ case kCFURLImproperArgumentsError:
+ return "Improper Arguments";
+ case kCFURLUnknownPropertyKeyError:
+ return "Unknown Property Key";
+ case kCFURLPropertyKeyUnavailableError:
+ return "Property Key Unavailable";
+ case kCFURLTimeoutError:
+ return "Timeout";
+ default:
+ return "Really Unknown Error";
+ }
+}
+
QList<QNetworkProxy> macQueryInternal(const QNetworkProxyQuery &query)
{
QList<QNetworkProxy> result;
@@ -168,11 +229,58 @@ QList<QNetworkProxy> macQueryInternal(const QNetworkProxyQuery &query)
int enabled;
if (CFNumberGetValue(pacEnabled, kCFNumberIntType, &enabled) && enabled) {
// PAC is enabled
- CFStringRef pacUrl =
- (CFStringRef)CFDictionaryGetValue(dict, kSCPropNetProxiesProxyAutoConfigURLString);
- QString url = QCFString::toQString(pacUrl);
+ CFStringRef cfPacLocation = (CFStringRef)CFDictionaryGetValue(dict, kSCPropNetProxiesProxyAutoConfigURLString);
+
+#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5)
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) {
+ QCFType<CFDataRef> pacData;
+ QCFType<CFURLRef> pacUrl = CFURLCreateWithString(kCFAllocatorDefault, cfPacLocation, NULL);
+ SInt32 errorCode;
+ if (!CFURLCreateDataAndPropertiesFromResource(kCFAllocatorDefault, pacUrl, &pacData, NULL, NULL, &errorCode)) {
+ QString pacLocation = QCFString::toQString(cfPacLocation);
+ qWarning("Unable to get the PAC script at \"%s\" (%s)", qPrintable(pacLocation), cfurlErrorDescription(errorCode));
+ return result;
+ }
- // ### TODO: Use PAC somehow
+ QCFType<CFStringRef> pacScript = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, pacData, kCFStringEncodingISOLatin1);
+ if (!pacScript) {
+ // This should never happen, but the documentation says it may return NULL if there was a problem creating the object.
+ QString pacLocation = QCFString::toQString(cfPacLocation);
+ qWarning("Unable to read the PAC script at \"%s\"", qPrintable(pacLocation));
+ return result;
+ }
+
+ QByteArray encodedURL = query.url().toEncoded(); // converted to UTF-8
+ if (encodedURL.isEmpty()) {
+ return result; // Invalid URL, abort
+ }
+
+ QCFType<CFURLRef> targetURL = CFURLCreateWithBytes(kCFAllocatorDefault, (UInt8*)encodedURL.data(), encodedURL.size(), kCFStringEncodingUTF8, NULL);
+ if (!targetURL) {
+ return result; // URL creation problem, abort
+ }
+
+ QCFType<CFErrorRef> pacError;
+ QCFType<CFArrayRef> proxies = CFNetworkCopyProxiesForAutoConfigurationScript(pacScript, targetURL, &pacError);
+ if (!proxies) {
+ QString pacLocation = QCFString::toQString(cfPacLocation);
+ QCFType<CFStringRef> pacErrorDescription = CFErrorCopyDescription(pacError);
+ qWarning("Execution of PAC script at \"%s\" failed: %s", qPrintable(pacLocation), qPrintable(QCFString::toQString(pacErrorDescription)));
+ return result;
+ }
+
+ CFIndex size = CFArrayGetCount(proxies);
+ for (CFIndex i = 0; i < size; ++i) {
+ CFDictionaryRef proxy = (CFDictionaryRef)CFArrayGetValueAtIndex(proxies, i);
+ result << proxyFromDictionary(proxy);
+ }
+ return result;
+ } else
+#endif
+ {
+ QString pacLocation = QCFString::toQString(cfPacLocation);
+ qWarning("Mac system proxy: PAC script at \"%s\" not handled", qPrintable(pacLocation));
+ }
}
}