60 bool isSimple = !host.contains(u'.') && !host.contains(u':');
61 CFNumberRef excludeSimples;
63 (excludeSimples = (CFNumberRef)CFDictionaryGetValue(dict, kCFNetworkProxiesExcludeSimpleHostnames))) {
65 if (CFNumberGetValue(excludeSimples, kCFNumberIntType, &enabled) && enabled)
69 QHostAddress ipAddress;
70 bool isIpAddress = ipAddress.setAddress(host);
74 CFArrayRef exclusionList = (CFArrayRef)CFDictionaryGetValue(dict, kCFNetworkProxiesExceptionsList);
78 CFIndex size = CFArrayGetCount(exclusionList);
79 for (CFIndex i = 0; i < size; ++i) {
80 CFStringRef cfentry = (CFStringRef)CFArrayGetValueAtIndex(exclusionList, i);
81 QString entry = QString::fromCFString(cfentry);
83 if (isIpAddress && ipAddress.isInSubnet(QHostAddress::parseSubnet(entry))) {
87 auto rx = QRegularExpression::fromWildcard(entry, Qt::CaseInsensitive);
88 if (rx.match(host).hasMatch())
100 CFStringRef enableKey, CFStringRef hostKey,
103 CFNumberRef protoEnabled;
104 CFNumberRef protoPort;
105 CFStringRef protoHost;
107 && (protoEnabled = (CFNumberRef)CFDictionaryGetValue(dict, enableKey))
108 && (protoHost = (CFStringRef)CFDictionaryGetValue(dict, hostKey))
109 && (protoPort = (CFNumberRef)CFDictionaryGetValue(dict, portKey))) {
111 if (CFNumberGetValue(protoEnabled, kCFNumberIntType, &enabled) && enabled) {
112 QString host = QString::fromCFString(protoHost);
115 CFNumberGetValue(protoPort, kCFNumberIntType, &port);
117 return QNetworkProxy(type, host, port);
122 return QNetworkProxy();
127 QNetworkProxy::ProxyType proxyType = QNetworkProxy::DefaultProxy;
133 CFStringRef cfProxyType = (CFStringRef)CFDictionaryGetValue(dict, kCFProxyTypeKey);
134 if (CFStringCompare(cfProxyType, kCFProxyTypeNone, 0) == kCFCompareEqualTo) {
135 proxyType = QNetworkProxy::NoProxy;
136 }
else if (CFStringCompare(cfProxyType, kCFProxyTypeFTP, 0) == kCFCompareEqualTo) {
137 proxyType = QNetworkProxy::FtpCachingProxy;
138 }
else if (CFStringCompare(cfProxyType, kCFProxyTypeHTTP, 0) == kCFCompareEqualTo) {
139 proxyType = QNetworkProxy::HttpProxy;
140 }
else if (CFStringCompare(cfProxyType, kCFProxyTypeHTTPS, 0) == kCFCompareEqualTo) {
141 proxyType = QNetworkProxy::HttpProxy;
142 }
else if (CFStringCompare(cfProxyType, kCFProxyTypeSOCKS, 0) == kCFCompareEqualTo) {
143 proxyType = QNetworkProxy::Socks5Proxy;
146 hostName = QString::fromCFString((CFStringRef)CFDictionaryGetValue(dict, kCFProxyHostNameKey));
147 user = QString::fromCFString((CFStringRef)CFDictionaryGetValue(dict, kCFProxyUsernameKey));
148 password = QString::fromCFString((CFStringRef)CFDictionaryGetValue(dict, kCFProxyPasswordKey));
150 CFNumberRef portNumber = (CFNumberRef)CFDictionaryGetValue(dict, kCFProxyPortNumberKey);
152 CFNumberGetValue(portNumber, kCFNumberSInt16Type, &port);
155 return QNetworkProxy(proxyType, hostName, port, user, password);
221 QList<QNetworkProxy> result;
224 const QCFType<CFDictionaryRef> dict = CFNetworkCopySystemProxySettings();
226 qWarning(
"QNetworkProxyFactory::systemProxyForQuery: CFNetworkCopySystemProxySettings returned nullptr");
230 if (isHostExcluded(dict, query.peerHostName()))
234 CFNumberRef pacEnabled;
235 if ((pacEnabled = (CFNumberRef)CFDictionaryGetValue(dict, kCFNetworkProxiesProxyAutoConfigEnable))) {
237 if (CFNumberGetValue(pacEnabled, kCFNumberIntType, &enabled) && enabled) {
241 CFStringRef pacLocationSetting = (CFStringRef)CFDictionaryGetValue(dict, kCFNetworkProxiesProxyAutoConfigURLString);
242 auto cfPacLocation = stringByAddingPercentEscapes(pacLocationSetting);
243 QCFType<CFDataRef> pacData;
244 QCFType<CFURLRef> pacUrl = CFURLCreateWithString(kCFAllocatorDefault, cfPacLocation, NULL);
246 qWarning(
"Invalid PAC URL \"%s\"", qPrintable(QString::fromCFString(cfPacLocation)));
250 QByteArray encodedURL = query.url().toEncoded();
251 if (encodedURL.isEmpty()) {
255 QCFType<CFURLRef> targetURL = CFURLCreateWithBytes(kCFAllocatorDefault, (UInt8*)encodedURL.data(), encodedURL.size(), kCFStringEncodingUTF8, NULL);
260 CFStreamClientContext pacCtx;
263 pacCtx.info = &pacInfo;
264 pacCtx.retain = NULL;
265 pacCtx.release = NULL;
266 pacCtx.copyDescription = NULL;
268 static CFStringRef pacRunLoopMode = CFSTR(
"qtPACRunLoopMode");
270 QCFType<CFRunLoopSourceRef> pacRunLoopSource = CFNetworkExecuteProxyAutoConfigurationURL(pacUrl, targetURL, &proxyAutoConfigCallback, &pacCtx);
271 CFRunLoopAddSource(CFRunLoopGetCurrent(), pacRunLoopSource, pacRunLoopMode);
272 while (!pacInfo.done)
273 CFRunLoopRunInMode(pacRunLoopMode, 1000,
true);
275 if (!pacInfo.proxies) {
276 QString pacLocation = QString::fromCFString(cfPacLocation);
277 QCFType<CFStringRef> pacErrorDescription = CFErrorCopyDescription(pacInfo.error);
278 qWarning(
"Execution of PAC script at \"%s\" failed: %s", qPrintable(pacLocation), qPrintable(QString::fromCFString(pacErrorDescription)));
282 CFIndex size = CFArrayGetCount(pacInfo.proxies);
283 for (CFIndex i = 0; i < size; ++i) {
284 CFDictionaryRef proxy = (CFDictionaryRef)CFArrayGetValueAtIndex(pacInfo.proxies, i);
285 result << proxyFromDictionary(proxy);
293 const QString protocol = query.protocolTag();
295 if (protocol.compare(
"http"_L1, Qt::CaseInsensitive) == 0) {
296 protocolSpecificProxy =
297 proxyFromDictionary(dict, QNetworkProxy::HttpProxy,
298 kCFNetworkProxiesHTTPEnable,
299 kCFNetworkProxiesHTTPProxy,
300 kCFNetworkProxiesHTTPPort);
305 if (protocolSpecificProxy.type() != QNetworkProxy::DefaultProxy
306 && protocolSpecificProxy.type() != QNetworkProxy::DefaultProxy) {
309 result << protocolSpecificProxy;
315 const auto proxiesForUrl = proxiesForQueryUrl(dict, query.url());
316 for (
const auto &proxy : proxiesForUrl) {
317 if (!result.contains(proxy))
321 bool isHttps =
false;
322 if (protocol.compare(
"ftp"_L1, Qt::CaseInsensitive) == 0) {
323 protocolSpecificProxy =
324 proxyFromDictionary(dict, QNetworkProxy::FtpCachingProxy,
325 kCFNetworkProxiesFTPEnable,
326 kCFNetworkProxiesFTPProxy,
327 kCFNetworkProxiesFTPPort);
328 }
else if (protocol.compare(
"https"_L1, Qt::CaseInsensitive) == 0) {
330 protocolSpecificProxy =
331 proxyFromDictionary(dict, QNetworkProxy::HttpProxy,
332 kCFNetworkProxiesHTTPSEnable,
333 kCFNetworkProxiesHTTPSProxy,
334 kCFNetworkProxiesHTTPSPort);
337 if (protocolSpecificProxy.type() != QNetworkProxy::DefaultProxy)
338 result << protocolSpecificProxy;
341 QNetworkProxy socks5 = proxyFromDictionary(dict, QNetworkProxy::Socks5Proxy,
342 kCFNetworkProxiesSOCKSEnable,
343 kCFNetworkProxiesSOCKSProxy,
344 kCFNetworkProxiesSOCKSPort);
345 if (socks5.type() != QNetworkProxy::DefaultProxy)
352 https = proxyFromDictionary(dict, QNetworkProxy::HttpProxy,
353 kCFNetworkProxiesHTTPSEnable,
354 kCFNetworkProxiesHTTPSProxy,
355 kCFNetworkProxiesHTTPSPort);
358 if (https.type() != QNetworkProxy::DefaultProxy && https != protocolSpecificProxy)