signon  8.58
my-network-proxy-factory.cpp
Go to the documentation of this file.
00001 /*
00002  * Copied from
00003  * https://codereview.qt-project.org/cat/29453%2C6%2Csrc/network/kernel/qnetworkproxy_libproxy.cpp%5E0
00004  *
00005  * With minor modifications by
00006  * Alberto Mardegan <alberto.mardegan@canonical.com>
00007  */
00008 
00009 /****************************************************************************
00010 **
00011 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
00012 ** Contact: http://www.qt-project.org/
00013 **
00014 ** This file is part of the QtNetwork module of the Qt Toolkit.
00015 **
00016 ** $QT_BEGIN_LICENSE:LGPL$
00017 ** GNU Lesser General Public License Usage
00018 ** This file may be used under the terms of the GNU Lesser General Public
00019 ** License version 2.1 as published by the Free Software Foundation and
00020 ** appearing in the file LICENSE.LGPL included in the packaging of this
00021 ** file. Please review the following information to ensure the GNU Lesser
00022 ** General Public License version 2.1 requirements will be met:
00023 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
00024 **
00025 ** In addition, as a special exception, Nokia gives you certain additional
00026 ** rights. These rights are described in the Nokia Qt LGPL Exception
00027 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
00028 **
00029 ** GNU General Public License Usage
00030 ** Alternatively, this file may be used under the terms of the GNU General
00031 ** Public License version 3.0 as published by the Free Software Foundation
00032 ** and appearing in the file LICENSE.GPL included in the packaging of this
00033 ** file. Please review the following information to ensure the GNU General
00034 ** Public License version 3.0 requirements will be met:
00035 ** http://www.gnu.org/copyleft/gpl.html.
00036 **
00037 ** Other Usage
00038 ** Alternatively, this file may be used in accordance with the terms and
00039 ** conditions contained in a signed written agreement between you and Nokia.
00040 **
00041 **
00042 **
00043 **
00044 **
00045 **
00046 ** $QT_END_LICENSE$
00047 **
00048 ****************************************************************************/
00049 
00050 #include "my-network-proxy-factory.h"
00051 
00052 #include <QNetworkProxy>
00053 
00054 #include <QtCore/QByteArray>
00055 #include <QtCore/QUrl>
00056 
00057 #include <proxy.h>
00058 
00059 class QLibProxyWrapper
00060 {
00061 public:
00062     QLibProxyWrapper()
00063         : factory(px_proxy_factory_new())
00064     {
00065     }
00066 
00067     ~QLibProxyWrapper()
00068     {
00069         px_proxy_factory_free(factory);
00070     }
00071 
00072     QList<QUrl> getProxies(const QUrl &url);
00073 
00074 private:
00075     pxProxyFactory *factory;
00076 };
00077 
00078 Q_GLOBAL_STATIC(QLibProxyWrapper, libProxyWrapper);
00079 
00080 /*
00081     Gets the list of proxies from libproxy, converted to QUrl list.
00082     Thread safe, according to libproxy documentation.
00083 */
00084 QList<QUrl> QLibProxyWrapper::getProxies(const QUrl &url)
00085 {
00086     QList<QUrl> ret;
00087 
00088     if (factory) {
00089         char **proxies = px_proxy_factory_get_proxies(factory, url.toEncoded());
00090         if (proxies) {
00091             for (int i = 0; proxies[i]; i++) {
00092                 ret.append(QUrl::fromEncoded(proxies[i]));
00093                 free(proxies[i]);
00094             }
00095             free(proxies);
00096         }
00097     }
00098 
00099     return ret;
00100 }
00101 
00102 QList<QNetworkProxy> MyNetworkProxyFactory::queryProxy(const QNetworkProxyQuery &query)
00103 {
00104     QList<QNetworkProxy> proxyList;
00105 
00106     QUrl queryUrl;
00107     QNetworkProxy::Capabilities requiredCapabilities(0);
00108     switch (query.queryType()) {
00109     //URL requests are directly supported by libproxy
00110     case QNetworkProxyQuery::UrlRequest:
00111         queryUrl = query.url();
00112         break;
00113     // fake URLs to get libproxy to tell us the SOCKS proxy
00114     case QNetworkProxyQuery::TcpSocket:
00115         queryUrl.setScheme(QLatin1String("tcp"));
00116         queryUrl.setHost(query.peerHostName());
00117         queryUrl.setPort(query.peerPort());
00118         requiredCapabilities |= QNetworkProxy::TunnelingCapability;
00119         break;
00120     case QNetworkProxyQuery::UdpSocket:
00121         queryUrl.setScheme(QLatin1String("udp"));
00122         queryUrl.setHost(query.peerHostName());
00123         queryUrl.setPort(query.peerPort());
00124         requiredCapabilities |= QNetworkProxy::UdpTunnelingCapability;
00125         break;
00126     default:
00127         proxyList.append(QNetworkProxy(QNetworkProxy::NoProxy));
00128         return proxyList;
00129     }
00130 
00131     QList<QUrl> rawProxies = libProxyWrapper()->getProxies(queryUrl);
00132 
00133     bool haveDirectConnection = false;
00134     foreach (const QUrl& url, rawProxies) {
00135         QNetworkProxy::ProxyType type;
00136         if (url.scheme() == QLatin1String("http")) {
00137             type = QNetworkProxy::HttpProxy;
00138         } else if (url.scheme() == QLatin1String("socks")
00139               || url.scheme() == QLatin1String("socks5")) {
00140             type = QNetworkProxy::Socks5Proxy;
00141         } else if (url.scheme() == QLatin1String("ftp")) {
00142             type = QNetworkProxy::FtpCachingProxy;
00143         } else if (url.scheme() == QLatin1String("direct")) {
00144             type = QNetworkProxy::NoProxy;
00145             haveDirectConnection = true;
00146         } else {
00147             continue; //unsupported proxy type e.g. socks4
00148         }
00149 
00150         QNetworkProxy proxy(type,
00151             url.host(),
00152             url.port(),
00153             url.userName(),
00154             url.password());
00155 
00156         if ((proxy.capabilities() & requiredCapabilities) == requiredCapabilities)
00157             proxyList.append(proxy);
00158     }
00159 
00160     // fallback is direct connection
00161     if (proxyList.isEmpty() || !haveDirectConnection)
00162         proxyList.append(QNetworkProxy(QNetworkProxy::NoProxy));
00163 
00164     return proxyList;
00165 }