summaryrefslogtreecommitdiffstats
path: root/src/network/kernel/qnetworkproxy_mac.cpp
diff options
context:
space:
mode:
authoraxis <qt-info@nokia.com>2009-04-24 11:34:15 (GMT)
committeraxis <qt-info@nokia.com>2009-04-24 11:34:15 (GMT)
commit8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76 (patch)
treea17e1a767a89542ab59907462206d7dcf2e504b2 /src/network/kernel/qnetworkproxy_mac.cpp
downloadQt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.zip
Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.tar.gz
Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.tar.bz2
Long live Qt for S60!
Diffstat (limited to 'src/network/kernel/qnetworkproxy_mac.cpp')
-rw-r--r--src/network/kernel/qnetworkproxy_mac.cpp240
1 files changed, 240 insertions, 0 deletions
diff --git a/src/network/kernel/qnetworkproxy_mac.cpp b/src/network/kernel/qnetworkproxy_mac.cpp
new file mode 100644
index 0000000..5e6e3e8
--- /dev/null
+++ b/src/network/kernel/qnetworkproxy_mac.cpp
@@ -0,0 +1,240 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnetworkproxy.h"
+
+#ifndef QT_NO_NETWORKPROXY
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <SystemConfiguration/SystemConfiguration.h>
+
+#include <QtCore/QRegExp>
+#include <QtCore/QStringList>
+#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
+ * \o FTP proxy
+ * \o Web Proxy (HTTP)
+ * \o Secure Web Proxy (HTTPS)
+ * \o Streaming Proxy (RTSP)
+ * \o SOCKS Proxy
+ * \o Gopher Proxy
+ * \o URL for Automatic Proxy Configuration (PAC scripts)
+ * \o 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
+
+static bool isHostExcluded(CFDictionaryRef dict, const QString &host)
+{
+ if (host.isEmpty())
+ return true;
+
+ bool isSimple = !host.contains(QLatin1Char('.')) && !host.contains(QLatin1Char(':'));
+ 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 = QCFString::toQString(cfentry);
+
+ if (isIpAddress && ipAddress.isInSubnet(QHostAddress::parseSubnet(entry))) {
+ return true; // excluded
+ } else {
+ // do wildcard matching
+ QRegExp rx(entry, Qt::CaseInsensitive, QRegExp::Wildcard);
+ if (rx.exactMatch(host))
+ 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 = QCFString::toQString(protoHost);
+
+ int port;
+ CFNumberGetValue(protoPort, kCFNumberIntType, &port);
+
+ return QNetworkProxy(type, host, port);
+ }
+ }
+
+ // proxy not enabled
+ return QNetworkProxy();
+}
+
+QList<QNetworkProxy> macQueryInternal(const QNetworkProxyQuery &query)
+{
+ QList<QNetworkProxy> result;
+
+ // obtain a dictionary to the proxy settings:
+ 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
+ CFStringRef pacUrl =
+ (CFStringRef)CFDictionaryGetValue(dict, kSCPropNetProxiesProxyAutoConfigURLString);
+ QString url = QCFString::toQString(pacUrl);
+
+ // ### Use PAC somehow
+ qDebug("Mac system proxy: found PAC script at \"%s\"", qPrintable(url));
+ }
+ }
+
+ // 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 == QLatin1String("ftp")) {
+ protocolSpecificProxy =
+ proxyFromDictionary(dict, QNetworkProxy::FtpCachingProxy,
+ kSCPropNetProxiesFTPEnable,
+ kSCPropNetProxiesFTPProxy,
+ kSCPropNetProxiesFTPPort);
+ } else if (protocol == QLatin1String("http")) {
+ protocolSpecificProxy =
+ proxyFromDictionary(dict, QNetworkProxy::HttpProxy,
+ kSCPropNetProxiesHTTPEnable,
+ kSCPropNetProxiesHTTPProxy,
+ kSCPropNetProxiesHTTPPort);
+ } else if (protocol == QLatin1String("https")) {
+ 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