summaryrefslogtreecommitdiffstats
path: root/src/plugins/bearer/icd/proxyconf.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/bearer/icd/proxyconf.cpp')
-rw-r--r--src/plugins/bearer/icd/proxyconf.cpp412
1 files changed, 412 insertions, 0 deletions
diff --git a/src/plugins/bearer/icd/proxyconf.cpp b/src/plugins/bearer/icd/proxyconf.cpp
new file mode 100644
index 0000000..e5c8f4e
--- /dev/null
+++ b/src/plugins/bearer/icd/proxyconf.cpp
@@ -0,0 +1,412 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins 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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QVariant>
+#include <QStringList>
+#include <QDebug>
+#include <QWriteLocker>
+#include <QNetworkProxyFactory>
+#include <QNetworkProxy>
+#include <gconf/gconf-value.h>
+#include <gconf/gconf-client.h>
+#include "proxyconf.h"
+
+#define CONF_PROXY "/system/proxy"
+#define HTTP_PROXY "/system/http_proxy"
+
+
+namespace Maemo {
+
+static QString convertKey(const char *key)
+{
+ return QString::fromUtf8(key);
+}
+
+static QVariant convertValue(GConfValue *src)
+{
+ if (!src) {
+ return QVariant();
+ } else {
+ switch (src->type) {
+ case GCONF_VALUE_INVALID:
+ return QVariant(QVariant::Invalid);
+ case GCONF_VALUE_BOOL:
+ return QVariant((bool)gconf_value_get_bool(src));
+ case GCONF_VALUE_INT:
+ return QVariant(gconf_value_get_int(src));
+ case GCONF_VALUE_FLOAT:
+ return QVariant(gconf_value_get_float(src));
+ case GCONF_VALUE_STRING:
+ return QVariant(QString::fromUtf8(gconf_value_get_string(src)));
+ case GCONF_VALUE_LIST:
+ switch (gconf_value_get_list_type(src)) {
+ case GCONF_VALUE_STRING:
+ {
+ QStringList result;
+ for (GSList *elts = gconf_value_get_list(src); elts; elts = elts->next)
+ result.append(QString::fromUtf8(gconf_value_get_string((GConfValue *)elts->data)));
+ return QVariant(result);
+ }
+ default:
+ {
+ QList<QVariant> result;
+ for (GSList *elts = gconf_value_get_list(src); elts; elts = elts->next)
+ result.append(convertValue((GConfValue *)elts->data));
+ return QVariant(result);
+ }
+ }
+ case GCONF_VALUE_SCHEMA:
+ default:
+ return QVariant();
+ }
+ }
+}
+
+
+/* Fast version of GConfItem, allows reading subtree at a time */
+class GConfItemFast {
+public:
+ GConfItemFast(const QString &k) : key(k) {}
+ QHash<QString,QVariant> getEntries() const;
+
+private:
+ QString key;
+};
+
+#define withClient(c) for (GConfClient *c = gconf_client_get_default(); c; c=0)
+
+
+QHash<QString,QVariant> GConfItemFast::getEntries() const
+{
+ QHash<QString,QVariant> children;
+
+ withClient(client) {
+ QByteArray k = key.toUtf8();
+ GSList *entries = gconf_client_all_entries(client, k.data(), NULL);
+ for (GSList *e = entries; e; e = e->next) {
+ char *key_name = strrchr(((GConfEntry *)e->data)->key, '/');
+ if (!key_name)
+ key_name = ((GConfEntry *)e->data)->key;
+ else
+ key_name++;
+ QString key(convertKey(key_name));
+ QVariant value = convertValue(((GConfEntry *)e->data)->value);
+ gconf_entry_unref((GConfEntry *)e->data);
+ //qDebug()<<"key="<<key<<"value="<<value;
+ children.insert(key, value);
+ }
+ g_slist_free (entries);
+ }
+
+ return children;
+}
+
+
+
+class NetworkProxyFactory : QNetworkProxyFactory {
+public:
+ NetworkProxyFactory() { }
+ QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query = QNetworkProxyQuery());
+};
+
+
+QList<QNetworkProxy> NetworkProxyFactory::queryProxy(const QNetworkProxyQuery &query)
+{
+ ProxyConf proxy_conf;
+
+ QList<QNetworkProxy> result = proxy_conf.flush(query);
+ if (result.isEmpty())
+ result << QNetworkProxy::NoProxy;
+
+ return result;
+}
+
+
+class ProxyConfPrivate {
+private:
+ // proxy values from gconf
+ QString mode;
+ bool use_http_host;
+ QString autoconfig_url;
+ QString http_proxy;
+ quint16 http_port;
+ QList<QVariant> ignore_hosts;
+ QString secure_host;
+ quint16 secure_port;
+ QString ftp_host;
+ quint16 ftp_port;
+ QString socks_host;
+ quint16 socks_port;
+ QString rtsp_host;
+ quint16 rtsp_port;
+
+ bool isHostExcluded(const QString &host);
+
+public:
+ QString prefix;
+ QString http_prefix;
+
+ void readProxyData();
+ QList<QNetworkProxy> flush(const QNetworkProxyQuery &query);
+};
+
+
+static QHash<QString,QVariant> getValues(const QString& prefix)
+{
+ GConfItemFast item(prefix);
+ return item.getEntries();
+}
+
+static QHash<QString,QVariant> getHttpValues(const QString& prefix)
+{
+ GConfItemFast item(prefix);
+ return item.getEntries();
+}
+
+#define GET(var, type) \
+ do { \
+ QVariant v = values.value(#var); \
+ if (v.isValid()) \
+ var = v.to##type (); \
+ } while(0)
+
+#define GET_HTTP(var, name, type) \
+ do { \
+ QVariant v = httpValues.value(#name); \
+ if (v.isValid()) \
+ var = v.to##type (); \
+ } while(0)
+
+
+void ProxyConfPrivate::readProxyData()
+{
+ QHash<QString,QVariant> values = getValues(prefix);
+ QHash<QString,QVariant> httpValues = getHttpValues(http_prefix);
+
+ //qDebug()<<"values="<<values;
+
+ /* Read the proxy settings from /system/proxy* */
+ GET_HTTP(http_proxy, host, String);
+ GET_HTTP(http_port, port, Int);
+ GET_HTTP(ignore_hosts, ignore_hosts, List);
+
+ GET(mode, String);
+ GET(autoconfig_url, String);
+ GET(secure_host, String);
+ GET(secure_port, Int);
+ GET(ftp_host, String);
+ GET(ftp_port, Int);
+ GET(socks_host, String);
+ GET(socks_port, Int);
+ GET(rtsp_host, String);
+ GET(rtsp_port, Int);
+
+ if (http_proxy.isEmpty())
+ use_http_host = false;
+ else
+ use_http_host = true;
+}
+
+
+bool ProxyConfPrivate::isHostExcluded(const QString &host)
+{
+ if (host.isEmpty())
+ return true;
+
+ if (ignore_hosts.isEmpty())
+ return false;
+
+ QHostAddress ipAddress;
+ bool isIpAddress = ipAddress.setAddress(host);
+
+ foreach (QVariant h, ignore_hosts) {
+ QString entry = h.toString();
+ 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;
+}
+
+
+QList<QNetworkProxy> ProxyConfPrivate::flush(const QNetworkProxyQuery &query)
+{
+ QList<QNetworkProxy> result;
+
+#if 0
+ qDebug()<<"http_proxy" << http_proxy;
+ qDebug()<<"http_port" << http_port;
+ qDebug()<<"ignore_hosts" << ignore_hosts;
+ qDebug()<<"use_http_host" << use_http_host;
+ qDebug()<<"mode" << mode;
+ qDebug()<<"autoconfig_url" << autoconfig_url;
+ qDebug()<<"secure_host" << secure_host;
+ qDebug()<<"secure_port" << secure_port;
+ qDebug()<<"ftp_host" << ftp_host;
+ qDebug()<<"ftp_port" << ftp_port;
+ qDebug()<<"socks_host" << socks_host;
+ qDebug()<<"socks_port" << socks_port;
+ qDebug()<<"rtsp_host" << rtsp_host;
+ qDebug()<<"rtsp_port" << rtsp_port;
+#endif
+
+ if (isHostExcluded(query.peerHostName()))
+ return result; // no proxy for this host
+
+ if (mode == "auto") {
+ // TODO: pac currently not supported, fix me
+ return result;
+ }
+
+ if (mode == "manual") {
+ bool isHttps = false;
+ QString protocol = query.protocolTag().toLower();
+
+ // try the protocol-specific proxy
+ QNetworkProxy protocolSpecificProxy;
+
+ if (protocol == QLatin1String("ftp")) {
+ if (!ftp_host.isEmpty()) {
+ protocolSpecificProxy.setType(QNetworkProxy::FtpCachingProxy);
+ protocolSpecificProxy.setHostName(ftp_host);
+ protocolSpecificProxy.setPort(ftp_port);
+ }
+ } else if (protocol == QLatin1String("http")) {
+ if (!http_proxy.isEmpty()) {
+ protocolSpecificProxy.setType(QNetworkProxy::HttpProxy);
+ protocolSpecificProxy.setHostName(http_proxy);
+ protocolSpecificProxy.setPort(http_port);
+ }
+ } else if (protocol == QLatin1String("https")) {
+ isHttps = true;
+ if (!secure_host.isEmpty()) {
+ protocolSpecificProxy.setType(QNetworkProxy::HttpProxy);
+ protocolSpecificProxy.setHostName(secure_host);
+ protocolSpecificProxy.setPort(secure_port);
+ }
+ }
+
+ if (protocolSpecificProxy.type() != QNetworkProxy::DefaultProxy)
+ result << protocolSpecificProxy;
+
+
+ if (!socks_host.isEmpty()) {
+ QNetworkProxy proxy;
+ proxy.setType(QNetworkProxy::Socks5Proxy);
+ proxy.setHostName(socks_host);
+ proxy.setPort(socks_port);
+ result << proxy;
+ }
+
+
+ // Add the HTTPS proxy if present (and if we haven't added yet)
+ if (!isHttps) {
+ QNetworkProxy https;
+ if (!secure_host.isEmpty()) {
+ https.setType(QNetworkProxy::HttpProxy);
+ https.setHostName(secure_host);
+ https.setPort(secure_port);
+ }
+
+ if (https.type() != QNetworkProxy::DefaultProxy &&
+ https != protocolSpecificProxy)
+ result << https;
+ }
+ }
+
+ return result;
+}
+
+
+ProxyConf::ProxyConf()
+ : d_ptr(new ProxyConfPrivate)
+{
+ g_type_init();
+ d_ptr->prefix = CONF_PROXY;
+ d_ptr->http_prefix = HTTP_PROXY;
+}
+
+ProxyConf::~ProxyConf()
+{
+ delete d_ptr;
+}
+
+
+QList<QNetworkProxy> ProxyConf::flush(const QNetworkProxyQuery &query)
+{
+ d_ptr->readProxyData();
+ return d_ptr->flush(query);
+}
+
+
+static int refcount = 0;
+static QReadWriteLock lock;
+
+void ProxyConf::update()
+{
+ QWriteLocker locker(&lock);
+ NetworkProxyFactory *factory = new NetworkProxyFactory();
+ QNetworkProxyFactory::setApplicationProxyFactory((QNetworkProxyFactory*)factory);
+ refcount++;
+}
+
+
+void ProxyConf::clear(void)
+{
+ QWriteLocker locker(&lock);
+ refcount--;
+ if (refcount == 0)
+ QNetworkProxyFactory::setApplicationProxyFactory(NULL);
+
+ if (refcount<0)
+ refcount = 0;
+}
+
+
+} // namespace Maemo