source: trunk/src/plugins/bearer/icd/proxyconf.cpp

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 11.4 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the plugins of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at qt-info@nokia.com.
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42
43#include <QVariant>
44#include <QStringList>
45#include <QDebug>
46#include <QWriteLocker>
47#include <QNetworkProxyFactory>
48#include <QNetworkProxy>
49#include <gconf/gconf-value.h>
50#include <gconf/gconf-client.h>
51#include "proxyconf.h"
52
53#define CONF_PROXY "/system/proxy"
54#define HTTP_PROXY "/system/http_proxy"
55
56
57namespace Maemo {
58
59static QString convertKey(const char *key)
60{
61 return QString::fromUtf8(key);
62}
63
64static QVariant convertValue(GConfValue *src)
65{
66 if (!src) {
67 return QVariant();
68 } else {
69 switch (src->type) {
70 case GCONF_VALUE_INVALID:
71 return QVariant(QVariant::Invalid);
72 case GCONF_VALUE_BOOL:
73 return QVariant((bool)gconf_value_get_bool(src));
74 case GCONF_VALUE_INT:
75 return QVariant(gconf_value_get_int(src));
76 case GCONF_VALUE_FLOAT:
77 return QVariant(gconf_value_get_float(src));
78 case GCONF_VALUE_STRING:
79 return QVariant(QString::fromUtf8(gconf_value_get_string(src)));
80 case GCONF_VALUE_LIST:
81 switch (gconf_value_get_list_type(src)) {
82 case GCONF_VALUE_STRING:
83 {
84 QStringList result;
85 for (GSList *elts = gconf_value_get_list(src); elts; elts = elts->next)
86 result.append(QString::fromUtf8(gconf_value_get_string((GConfValue *)elts->data)));
87 return QVariant(result);
88 }
89 default:
90 {
91 QList<QVariant> result;
92 for (GSList *elts = gconf_value_get_list(src); elts; elts = elts->next)
93 result.append(convertValue((GConfValue *)elts->data));
94 return QVariant(result);
95 }
96 }
97 case GCONF_VALUE_SCHEMA:
98 default:
99 return QVariant();
100 }
101 }
102}
103
104
105/* Fast version of GConfItem, allows reading subtree at a time */
106class GConfItemFast {
107public:
108 GConfItemFast(const QString &k) : key(k) {}
109 QHash<QString,QVariant> getEntries() const;
110
111private:
112 QString key;
113};
114
115#define withClient(c) for (GConfClient *c = gconf_client_get_default(); c; c=0)
116
117
118QHash<QString,QVariant> GConfItemFast::getEntries() const
119{
120 QHash<QString,QVariant> children;
121
122 withClient(client) {
123 QByteArray k = key.toUtf8();
124 GSList *entries = gconf_client_all_entries(client, k.data(), NULL);
125 for (GSList *e = entries; e; e = e->next) {
126 char *key_name = strrchr(((GConfEntry *)e->data)->key, '/');
127 if (!key_name)
128 key_name = ((GConfEntry *)e->data)->key;
129 else
130 key_name++;
131 QString key(convertKey(key_name));
132 QVariant value = convertValue(((GConfEntry *)e->data)->value);
133 gconf_entry_unref((GConfEntry *)e->data);
134 //qDebug()<<"key="<<key<<"value="<<value;
135 children.insert(key, value);
136 }
137 g_slist_free (entries);
138 }
139
140 return children;
141}
142
143
144
145class NetworkProxyFactory : QNetworkProxyFactory
146{
147 ProxyConf proxy_conf;
148 bool proxy_data_read;
149
150public:
151 NetworkProxyFactory() : proxy_data_read(false) { }
152 QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query = QNetworkProxyQuery());
153};
154
155
156QList<QNetworkProxy> NetworkProxyFactory::queryProxy(const QNetworkProxyQuery &query)
157{
158 if (proxy_data_read == false) {
159 proxy_data_read = true;
160 proxy_conf.readProxyData();
161 }
162
163 QList<QNetworkProxy> result = proxy_conf.flush(query);
164 if (result.isEmpty())
165 result << QNetworkProxy::NoProxy;
166
167 return result;
168}
169
170
171class ProxyConfPrivate {
172private:
173 // proxy values from gconf
174 QString mode;
175 bool use_http_host;
176 QString autoconfig_url;
177 QString http_proxy;
178 quint16 http_port;
179 QList<QVariant> ignore_hosts;
180 QString secure_host;
181 quint16 secure_port;
182 QString ftp_host;
183 quint16 ftp_port;
184 QString socks_host;
185 quint16 socks_port;
186 QString rtsp_host;
187 quint16 rtsp_port;
188
189 bool isHostExcluded(const QString &host);
190
191public:
192 QString prefix;
193 QString http_prefix;
194
195 void readProxyData();
196 QList<QNetworkProxy> flush(const QNetworkProxyQuery &query);
197};
198
199
200static QHash<QString,QVariant> getValues(const QString& prefix)
201{
202 GConfItemFast item(prefix);
203 return item.getEntries();
204}
205
206static QHash<QString,QVariant> getHttpValues(const QString& prefix)
207{
208 GConfItemFast item(prefix);
209 return item.getEntries();
210}
211
212#define GET(var, type) \
213 do { \
214 QVariant v = values.value(#var); \
215 if (v.isValid()) \
216 var = v.to##type (); \
217 } while(0)
218
219#define GET_HTTP(var, name, type) \
220 do { \
221 QVariant v = httpValues.value(#name); \
222 if (v.isValid()) \
223 var = v.to##type (); \
224 } while(0)
225
226
227void ProxyConfPrivate::readProxyData()
228{
229 QHash<QString,QVariant> values = getValues(prefix);
230 QHash<QString,QVariant> httpValues = getHttpValues(http_prefix);
231
232 //qDebug()<<"values="<<values;
233
234 /* Read the proxy settings from /system/proxy* */
235 GET_HTTP(http_proxy, host, String);
236 GET_HTTP(http_port, port, Int);
237 GET_HTTP(ignore_hosts, ignore_hosts, List);
238
239 GET(mode, String);
240 GET(autoconfig_url, String);
241 GET(secure_host, String);
242 GET(secure_port, Int);
243 GET(ftp_host, String);
244 GET(ftp_port, Int);
245 GET(socks_host, String);
246 GET(socks_port, Int);
247 GET(rtsp_host, String);
248 GET(rtsp_port, Int);
249
250 if (http_proxy.isEmpty())
251 use_http_host = false;
252 else
253 use_http_host = true;
254}
255
256
257bool ProxyConfPrivate::isHostExcluded(const QString &host)
258{
259 if (host.isEmpty())
260 return true;
261
262 if (ignore_hosts.isEmpty())
263 return false;
264
265 QHostAddress ipAddress;
266 bool isIpAddress = ipAddress.setAddress(host);
267
268 foreach (QVariant h, ignore_hosts) {
269 QString entry = h.toString();
270 if (isIpAddress && ipAddress.isInSubnet(QHostAddress::parseSubnet(entry))) {
271 return true; // excluded
272 } else {
273 // do wildcard matching
274 QRegExp rx(entry, Qt::CaseInsensitive, QRegExp::Wildcard);
275 if (rx.exactMatch(host))
276 return true;
277 }
278 }
279
280 // host was not excluded
281 return false;
282}
283
284
285QList<QNetworkProxy> ProxyConfPrivate::flush(const QNetworkProxyQuery &query)
286{
287 QList<QNetworkProxy> result;
288
289#if 0
290 qDebug()<<"http_proxy" << http_proxy;
291 qDebug()<<"http_port" << http_port;
292 qDebug()<<"ignore_hosts" << ignore_hosts;
293 qDebug()<<"use_http_host" << use_http_host;
294 qDebug()<<"mode" << mode;
295 qDebug()<<"autoconfig_url" << autoconfig_url;
296 qDebug()<<"secure_host" << secure_host;
297 qDebug()<<"secure_port" << secure_port;
298 qDebug()<<"ftp_host" << ftp_host;
299 qDebug()<<"ftp_port" << ftp_port;
300 qDebug()<<"socks_host" << socks_host;
301 qDebug()<<"socks_port" << socks_port;
302 qDebug()<<"rtsp_host" << rtsp_host;
303 qDebug()<<"rtsp_port" << rtsp_port;
304#endif
305
306 if (isHostExcluded(query.peerHostName()))
307 return result; // no proxy for this host
308
309 if (mode == QLatin1String("AUTO")) {
310 // TODO: pac currently not supported, fix me
311 return result;
312 }
313
314 if (mode == QLatin1String("MANUAL")) {
315 bool isHttps = false;
316 QString protocol = query.protocolTag().toLower();
317
318 // try the protocol-specific proxy
319 QNetworkProxy protocolSpecificProxy;
320
321 if (protocol == QLatin1String("ftp")) {
322 if (!ftp_host.isEmpty()) {
323 protocolSpecificProxy.setType(QNetworkProxy::FtpCachingProxy);
324 protocolSpecificProxy.setHostName(ftp_host);
325 protocolSpecificProxy.setPort(ftp_port);
326 }
327 } else if (protocol == QLatin1String("http")) {
328 if (!http_proxy.isEmpty()) {
329 protocolSpecificProxy.setType(QNetworkProxy::HttpProxy);
330 protocolSpecificProxy.setHostName(http_proxy);
331 protocolSpecificProxy.setPort(http_port);
332 }
333 } else if (protocol == QLatin1String("https")) {
334 isHttps = true;
335 if (!secure_host.isEmpty()) {
336 protocolSpecificProxy.setType(QNetworkProxy::HttpProxy);
337 protocolSpecificProxy.setHostName(secure_host);
338 protocolSpecificProxy.setPort(secure_port);
339 }
340 }
341
342 if (protocolSpecificProxy.type() != QNetworkProxy::DefaultProxy)
343 result << protocolSpecificProxy;
344
345
346 if (!socks_host.isEmpty()) {
347 QNetworkProxy proxy;
348 proxy.setType(QNetworkProxy::Socks5Proxy);
349 proxy.setHostName(socks_host);
350 proxy.setPort(socks_port);
351 result << proxy;
352 }
353
354
355 // Add the HTTPS proxy if present (and if we haven't added yet)
356 if (!isHttps) {
357 QNetworkProxy https;
358 if (!secure_host.isEmpty()) {
359 https.setType(QNetworkProxy::HttpProxy);
360 https.setHostName(secure_host);
361 https.setPort(secure_port);
362 }
363
364 if (https.type() != QNetworkProxy::DefaultProxy &&
365 https != protocolSpecificProxy)
366 result << https;
367 }
368 }
369
370 return result;
371}
372
373
374ProxyConf::ProxyConf()
375 : d_ptr(new ProxyConfPrivate)
376{
377 g_type_init();
378 d_ptr->prefix = CONF_PROXY;
379 d_ptr->http_prefix = HTTP_PROXY;
380}
381
382ProxyConf::~ProxyConf()
383{
384 delete d_ptr;
385}
386
387void ProxyConf::readProxyData()
388{
389 d_ptr->readProxyData();
390}
391
392QList<QNetworkProxy> ProxyConf::flush(const QNetworkProxyQuery &query)
393{
394 return d_ptr->flush(query);
395}
396
397
398static int refcount = 0;
399static QReadWriteLock lock;
400
401void ProxyConf::update()
402{
403 QWriteLocker locker(&lock);
404 NetworkProxyFactory *factory = new NetworkProxyFactory();
405 QNetworkProxyFactory::setApplicationProxyFactory((QNetworkProxyFactory*)factory);
406 refcount++;
407}
408
409
410void ProxyConf::clear(void)
411{
412 QWriteLocker locker(&lock);
413 refcount--;
414 if (refcount == 0)
415 QNetworkProxyFactory::setApplicationProxyFactory(NULL);
416
417 if (refcount<0)
418 refcount = 0;
419}
420
421
422} // namespace Maemo
Note: See TracBrowser for help on using the repository browser.