Qt 4.8
proxyconf.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
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 
57 namespace Maemo {
58 
59 static QString convertKey(const char *key)
60 {
61  return QString::fromUtf8(key);
62 }
63 
64 static QVariant convertValue(GConfValue *src)
65 {
66  if (!src) {
67  return QVariant();
68  } else {
69  switch (src->type) {
70  case GCONF_VALUE_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 */
107 public:
108  GConfItemFast(const QString &k) : key(k) {}
110 
111 private:
113 };
114 
115 #define withClient(c) for (GConfClient *c = gconf_client_get_default(); c; c=0)
116 
117 
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 
146 {
149 
150 public:
151  NetworkProxyFactory() : proxy_data_read(false) { }
152  QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query = QNetworkProxyQuery());
153 };
154 
155 
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 
172 private:
173  // proxy values from gconf
188 
189  bool isHostExcluded(const QString &host);
190 
191 public:
194 
195  void readProxyData();
197 };
198 
199 
201 {
202  GConfItemFast item(prefix);
203  return item.getEntries();
204 }
205 
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 
228 {
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 
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
275  if (rx.exactMatch(host))
276  return true;
277  }
278  }
279 
280  // host was not excluded
281  return false;
282 }
283 
284 
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;
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()) {
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 
375  : d_ptr(new ProxyConfPrivate)
376 {
377  g_type_init();
380 }
381 
383 {
384  delete d_ptr;
385 }
386 
388 {
389  d_ptr->readProxyData();
390 }
391 
393 {
394  return d_ptr->flush(query);
395 }
396 
397 
398 static int refcount = 0;
400 
402 {
403  QWriteLocker locker(&lock);
404  NetworkProxyFactory *factory = new NetworkProxyFactory();
406  refcount++;
407 }
408 
409 
411 {
412  QWriteLocker locker(&lock);
413  refcount--;
414  if (refcount == 0)
416 
417  if (refcount<0)
418  refcount = 0;
419 }
420 
421 
422 } // namespace Maemo
The QVariant class acts like a union for the most common Qt data types.
Definition: qvariant.h:92
QNetworkProxy::ProxyType type() const
Returns the proxy type for this instance.
void readProxyData()
Definition: proxyconf.cpp:387
#define GET(var, type)
Definition: proxyconf.cpp:212
#define CONF_PROXY
Definition: proxyconf.cpp:53
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
The QRegExp class provides pattern matching using regular expressions.
Definition: qregexp.h:61
QString peerHostName() const
Returns the host name or IP address being of the outgoing connection being requested, or an empty string if the remote hostname is not known.
QByteArray toUtf8() const Q_REQUIRED_RESULT
Returns a UTF-8 representation of the string as a QByteArray.
Definition: qstring.cpp:4074
static int refcount
Definition: proxyconf.cpp:398
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
static QHash< QString, QVariant > getHttpValues(const QString &prefix)
Definition: proxyconf.cpp:206
QList< QNetworkProxy > flush(const QNetworkProxyQuery &query=QNetworkProxyQuery())
Definition: proxyconf.cpp:392
QString toString() const
Returns the variant as a QString if the variant has type() String , Bool , ByteArray ...
Definition: qvariant.cpp:2270
QHash< QString, QVariant > getEntries() const
Definition: proxyconf.cpp:118
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
QList< QNetworkProxy > flush(const QNetworkProxyQuery &query)
Definition: proxyconf.cpp:285
QList< QNetworkProxy > queryProxy(const QNetworkProxyQuery &query=QNetworkProxyQuery())
This function takes the query request, query, examines the details of the type of socket or request a...
Definition: proxyconf.cpp:156
The QString class provides a Unicode character string.
Definition: qstring.h:83
The QNetworkProxyFactory class provides fine-grained proxy selection.
#define withClient(c)
Definition: proxyconf.cpp:115
static QVariant convertValue(GConfValue *src)
Definition: proxyconf.cpp:64
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition: qhash.h:753
Q_CORE_EXPORT void qDebug(const char *,...)
The QNetworkProxy class provides a network layer proxy.
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
QString protocolTag() const
Returns the protocol tag for this QNetworkProxyQuery object, or an empty QString in case the protocol...
static QString convertKey(const char *key)
Definition: proxyconf.cpp:59
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
static void setApplicationProxyFactory(QNetworkProxyFactory *factory)
Sets the application-wide proxy factory to be factory.
static QPair< QHostAddress, int > parseSubnet(const QString &subnet)
Parses the IP and subnet information contained in subnet and returns the network prefix for that netw...
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
static QString fromUtf8(const char *, int size=-1)
Returns a QString initialized with the first size bytes of the UTF-8 string str.
Definition: qstring.cpp:4302
unsigned short quint16
Definition: qglobal.h:936
void setHostName(const QString &hostName)
Sets the host name of the proxy host to be hostName.
virtual ~ProxyConf()
Definition: proxyconf.cpp:382
#define HTTP_PROXY
Definition: proxyconf.cpp:54
quint16 values[128]
GConfItemFast(const QString &k)
Definition: proxyconf.cpp:108
static bool isHostExcluded(CFDictionaryRef dict, const QString &host)
bool isInSubnet(const QHostAddress &subnet, int netmask) const
Returns true if this IP is in the subnet described by the network prefix subnet and netmask netmask...
The QWriteLocker class is a convenience class that simplifies locking and unlocking read-write locks ...
static void update(void)
Definition: proxyconf.cpp:401
The QNetworkProxyQuery class is used to query the proxy settings for a socket.
Definition: qnetworkproxy.h:60
#define GET_HTTP(var, name, type)
Definition: proxyconf.cpp:219
static const MacSpecialKey entries[NumEntries]
QList< QVariant > ignore_hosts
Definition: proxyconf.cpp:179
void setAddress(quint32 ip4Addr)
Set the IPv4 address specified by ip4Addr.
The QReadWriteLock class provides read-write locking.
int key
QString toLower() const Q_REQUIRED_RESULT
Returns a lowercase copy of the string.
Definition: qstring.cpp:5389
static QReadWriteLock lock
Definition: proxyconf.cpp:399
void setType(QNetworkProxy::ProxyType type)
Sets the proxy type for this instance to be type.
bool exactMatch(const QString &str) const
Returns true if str is matched exactly by this regular expression; otherwise returns false...
Definition: qregexp.cpp:4094
Q_CORE_EXPORT QTextStream & flush(QTextStream &s)
static QHash< QString, QVariant > getValues(const QString &prefix)
Definition: proxyconf.cpp:200
The QHostAddress class provides an IP address.
Definition: qhostaddress.h:70
bool isHostExcluded(const QString &host)
Definition: proxyconf.cpp:257
static void clear(void)
Definition: proxyconf.cpp:410
void setPort(quint16 port)
Sets the port of the proxy host to be port.
ProxyConfPrivate * d_ptr
Definition: proxyconf.h:54