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>
This commit is contained in:
parent
97f9c6f8cd
commit
c524bbbb8a
@ -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
|
||||
|
@ -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);
|
||||
|
||||
// ### TODO: Use PAC somehow
|
||||
#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;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user