diff options
Diffstat (limited to 'src/network/kernel/qnetworkproxy_mac.cpp')
-rw-r--r-- | src/network/kernel/qnetworkproxy_mac.cpp | 317 |
1 files changed, 0 insertions, 317 deletions
diff --git a/src/network/kernel/qnetworkproxy_mac.cpp b/src/network/kernel/qnetworkproxy_mac.cpp deleted file mode 100644 index aa691090cc..0000000000 --- a/src/network/kernel/qnetworkproxy_mac.cpp +++ /dev/null @@ -1,317 +0,0 @@ -// Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only - -#include "qnetworkproxy.h" - -#ifndef QT_NO_NETWORKPROXY - -#include <CFNetwork/CFNetwork.h> -#include <CoreFoundation/CoreFoundation.h> -#include <SystemConfiguration/SystemConfiguration.h> - -#include <QtCore/QRegularExpression> -#include <QtCore/QStringList> -#include <QtCore/QUrl> -#include <QtCore/qendian.h> -#include <QtCore/qstringlist.h> -#include "private/qcore_mac_p.h" - -/* - * MacOS X has a proxy configuration module in System Preferences (on - * MacOS X 10.5, it's in Network, Advanced), where one can set the - * proxy settings for: - * - * \list - * \li FTP proxy - * \li Web Proxy (HTTP) - * \li Secure Web Proxy (HTTPS) - * \li Streaming Proxy (RTSP) - * \li SOCKS Proxy - * \li Gopher Proxy - * \li URL for Automatic Proxy Configuration (PAC scripts) - * \li Bypass list (by default: *.local, 169.254/16) - * \endlist - * - * The matching configuration can be obtained by calling SCDynamicStoreCopyProxies - * (from <SystemConfiguration/SCDynamicStoreCopySpecific.h>). See - * Apple's documentation: - * - * http://developer.apple.com/DOCUMENTATION/Networking/Reference/SysConfig/SCDynamicStoreCopySpecific/CompositePage.html#//apple_ref/c/func/SCDynamicStoreCopyProxies - * - */ - -QT_BEGIN_NAMESPACE - -using namespace Qt::StringLiterals; - -static bool isHostExcluded(CFDictionaryRef dict, const QString &host) -{ - if (host.isEmpty()) - return true; - - bool isSimple = !host.contains(u'.') && !host.contains(u':'); - CFNumberRef excludeSimples; - if (isSimple && - (excludeSimples = (CFNumberRef)CFDictionaryGetValue(dict, kSCPropNetProxiesExcludeSimpleHostnames))) { - int enabled; - if (CFNumberGetValue(excludeSimples, kCFNumberIntType, &enabled) && enabled) - return true; - } - - QHostAddress ipAddress; - bool isIpAddress = ipAddress.setAddress(host); - - // not a simple host name - // does it match the list of exclusions? - CFArrayRef exclusionList = (CFArrayRef)CFDictionaryGetValue(dict, kSCPropNetProxiesExceptionsList); - if (!exclusionList) - return false; - - CFIndex size = CFArrayGetCount(exclusionList); - for (CFIndex i = 0; i < size; ++i) { - CFStringRef cfentry = (CFStringRef)CFArrayGetValueAtIndex(exclusionList, i); - QString entry = QString::fromCFString(cfentry); - - if (isIpAddress && ipAddress.isInSubnet(QHostAddress::parseSubnet(entry))) { - return true; // excluded - } else { - // do wildcard matching - auto rx = QRegularExpression::fromWildcard(entry, Qt::CaseInsensitive); - if (rx.match(host).hasMatch()) - return true; - } - } - - // host was not excluded - return false; -} - -static QNetworkProxy proxyFromDictionary(CFDictionaryRef dict, QNetworkProxy::ProxyType type, - CFStringRef enableKey, CFStringRef hostKey, - CFStringRef portKey) -{ - CFNumberRef protoEnabled; - CFNumberRef protoPort; - CFStringRef protoHost; - if (enableKey - && (protoEnabled = (CFNumberRef)CFDictionaryGetValue(dict, enableKey)) - && (protoHost = (CFStringRef)CFDictionaryGetValue(dict, hostKey)) - && (protoPort = (CFNumberRef)CFDictionaryGetValue(dict, portKey))) { - int enabled; - if (CFNumberGetValue(protoEnabled, kCFNumberIntType, &enabled) && enabled) { - QString host = QString::fromCFString(protoHost); - - int port; - CFNumberGetValue(protoPort, kCFNumberIntType, &port); - - return QNetworkProxy(type, host, port); - } - } - - // proxy not enabled - 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 = QString::fromCFString((CFStringRef)CFDictionaryGetValue(dict, kCFProxyHostNameKey)); - user = QString::fromCFString((CFStringRef)CFDictionaryGetValue(dict, kCFProxyUsernameKey)); - password = QString::fromCFString((CFStringRef)CFDictionaryGetValue(dict, kCFProxyPasswordKey)); - - CFNumberRef portNumber = (CFNumberRef)CFDictionaryGetValue(dict, kCFProxyPortNumberKey); - if (portNumber) { - CFNumberGetValue(portNumber, kCFNumberSInt16Type, &port); - } - - return QNetworkProxy(proxyType, hostName, port, user, password); -} - -namespace { -struct PACInfo { - QCFType<CFArrayRef> proxies; - QCFType<CFErrorRef> error; - bool done = false; -}; - -void proxyAutoConfigCallback(void *client, CFArrayRef proxylist, CFErrorRef error) -{ - Q_ASSERT(client); - - PACInfo *info = static_cast<PACInfo *>(client); - info->done = true; - - if (error) { - CFRetain(error); - info->error = error; - } - if (proxylist) { - CFRetain(proxylist); - info->proxies = proxylist; - } -} - -QCFType<CFStringRef> stringByAddingPercentEscapes(CFStringRef originalPath) -{ - Q_ASSERT(originalPath); - const auto qtPath = QString::fromCFString(originalPath); - const auto escaped = QString::fromUtf8(QUrl(qtPath).toEncoded()); - return escaped.toCFString(); -} - -} // anon namespace - -QList<QNetworkProxy> macQueryInternal(const QNetworkProxyQuery &query) -{ - QList<QNetworkProxy> result; - - // obtain a dictionary to the proxy settings: - const QCFType<CFDictionaryRef> dict = SCDynamicStoreCopyProxies(NULL); - if (!dict) { - qWarning("QNetworkProxyFactory::systemProxyForQuery: SCDynamicStoreCopyProxies returned NULL"); - return result; // failed - } - - if (isHostExcluded(dict, query.peerHostName())) - return result; // no proxy for this host - - // is there a PAC enabled? If so, use it first. - CFNumberRef pacEnabled; - if ((pacEnabled = (CFNumberRef)CFDictionaryGetValue(dict, kSCPropNetProxiesProxyAutoConfigEnable))) { - int enabled; - if (CFNumberGetValue(pacEnabled, kCFNumberIntType, &enabled) && enabled) { - // PAC is enabled - // kSCPropNetProxiesProxyAutoConfigURLString returns the URL string - // as entered in the system proxy configuration dialog - CFStringRef pacLocationSetting = (CFStringRef)CFDictionaryGetValue(dict, kSCPropNetProxiesProxyAutoConfigURLString); - auto cfPacLocation = stringByAddingPercentEscapes(pacLocationSetting); - QCFType<CFDataRef> pacData; - QCFType<CFURLRef> pacUrl = CFURLCreateWithString(kCFAllocatorDefault, cfPacLocation, NULL); - if (!pacUrl) { - qWarning("Invalid PAC URL \"%s\"", qPrintable(QString::fromCFString(cfPacLocation))); - 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 - } - - CFStreamClientContext pacCtx; - pacCtx.version = 0; - PACInfo pacInfo; - pacCtx.info = &pacInfo; - pacCtx.retain = NULL; - pacCtx.release = NULL; - pacCtx.copyDescription = NULL; - - static CFStringRef pacRunLoopMode = CFSTR("qtPACRunLoopMode"); - - QCFType<CFRunLoopSourceRef> pacRunLoopSource = CFNetworkExecuteProxyAutoConfigurationURL(pacUrl, targetURL, &proxyAutoConfigCallback, &pacCtx); - CFRunLoopAddSource(CFRunLoopGetCurrent(), pacRunLoopSource, pacRunLoopMode); - while (!pacInfo.done) - CFRunLoopRunInMode(pacRunLoopMode, 1000, /*returnAfterSourceHandled*/ true); - - if (!pacInfo.proxies) { - QString pacLocation = QString::fromCFString(cfPacLocation); - QCFType<CFStringRef> pacErrorDescription = CFErrorCopyDescription(pacInfo.error); - qWarning("Execution of PAC script at \"%s\" failed: %s", qPrintable(pacLocation), qPrintable(QString::fromCFString(pacErrorDescription))); - return result; - } - - CFIndex size = CFArrayGetCount(pacInfo.proxies); - for (CFIndex i = 0; i < size; ++i) { - CFDictionaryRef proxy = (CFDictionaryRef)CFArrayGetValueAtIndex(pacInfo.proxies, i); - result << proxyFromDictionary(proxy); - } - return result; - } - } - - // no PAC, decide which proxy we're looking for based on the query - bool isHttps = false; - QString protocol = query.protocolTag().toLower(); - - // try the protocol-specific proxy - QNetworkProxy protocolSpecificProxy; - if (protocol == "ftp"_L1) { - protocolSpecificProxy = - proxyFromDictionary(dict, QNetworkProxy::FtpCachingProxy, - kSCPropNetProxiesFTPEnable, - kSCPropNetProxiesFTPProxy, - kSCPropNetProxiesFTPPort); - } else if (protocol == "http"_L1) { - protocolSpecificProxy = - proxyFromDictionary(dict, QNetworkProxy::HttpProxy, - kSCPropNetProxiesHTTPEnable, - kSCPropNetProxiesHTTPProxy, - kSCPropNetProxiesHTTPPort); - } else if (protocol == "https"_L1) { - isHttps = true; - protocolSpecificProxy = - proxyFromDictionary(dict, QNetworkProxy::HttpProxy, - kSCPropNetProxiesHTTPSEnable, - kSCPropNetProxiesHTTPSProxy, - kSCPropNetProxiesHTTPSPort); - } - if (protocolSpecificProxy.type() != QNetworkProxy::DefaultProxy) - result << protocolSpecificProxy; - - // let's add SOCKSv5 if present too - QNetworkProxy socks5 = proxyFromDictionary(dict, QNetworkProxy::Socks5Proxy, - kSCPropNetProxiesSOCKSEnable, - kSCPropNetProxiesSOCKSProxy, - kSCPropNetProxiesSOCKSPort); - if (socks5.type() != QNetworkProxy::DefaultProxy) - result << socks5; - - // let's add the HTTPS proxy if present (and if we haven't added - // yet) - if (!isHttps) { - QNetworkProxy https = proxyFromDictionary(dict, QNetworkProxy::HttpProxy, - kSCPropNetProxiesHTTPSEnable, - kSCPropNetProxiesHTTPSProxy, - kSCPropNetProxiesHTTPSPort); - if (https.type() != QNetworkProxy::DefaultProxy && https != protocolSpecificProxy) - result << https; - } - - return result; -} - -QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkProxyQuery &query) -{ - QList<QNetworkProxy> result = macQueryInternal(query); - if (result.isEmpty()) - result << QNetworkProxy::NoProxy; - - return result; -} - -#endif - -QT_END_NAMESPACE |