#include <QtCore/QRegExp>
#include <QtCore/QStringList>
+#include <QtCore/QUrl>
#include <QtCore/qendian.h>
#include <QtCore/qstringlist.h>
#include "private/qcore_mac_p.h"
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;
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));
+ }
}
}