1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qnetworkproxy.h"
5
6#include <QtCore/QByteArray>
7#include <QtCore/QUrl>
8
9#ifndef QT_NO_NETWORKPROXY
10
11/*
12 * Construct a proxy from the environment variables http_proxy and no_proxy.
13 * Or no system proxy. Just return a list with NoProxy.
14 */
15
16QT_BEGIN_NAMESPACE
17
18using namespace Qt::StringLiterals;
19
20static bool ignoreProxyFor(const QNetworkProxyQuery &query)
21{
22 const QByteArray noProxy = qgetenv(varName: "no_proxy").trimmed();
23 if (noProxy.isEmpty())
24 return false;
25
26 const QString host = query.peerHostName();
27
28 const QList<QByteArray> noProxyTokens = noProxy.split(sep: ',');
29
30 for (const QByteArray &rawToken : noProxyTokens) {
31 auto token = QLatin1StringView(rawToken).trimmed();
32
33 // Since we use suffix matching, "*" is our 'default' behaviour
34 if (token.startsWith(c: u'*'))
35 token = token.mid(pos: 1);
36
37 // Harmonize trailing dot notation
38 if (token.endsWith(c: u'.') && !host.endsWith(c: u'.'))
39 token = token.chopped(n: 1);
40
41 if (token.startsWith(c: u'.')) // leading dot is implied
42 token = token.mid(pos: 1);
43
44 if (host.endsWith(s: token)) {
45
46 // Make sure that when we have a suffix match,
47 // we don't match "donotmatch.com" with "match.com"
48
49 if (host.size() == token.size()) // iow: host == token
50 return true;
51 if (host[host.size() - token.size() - 1] == u'.') // match follows a dot
52 return true;
53 }
54 }
55
56 return false;
57}
58
59QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkProxyQuery &query)
60{
61 QList<QNetworkProxy> proxyList;
62
63 if (ignoreProxyFor(query))
64 return proxyList << QNetworkProxy::NoProxy;
65
66 // No need to care about casing here, QUrl lowercases values already
67 const QString queryProtocol = query.protocolTag();
68 QByteArray proxy_env;
69
70 if (queryProtocol == "http"_L1)
71 proxy_env = qgetenv(varName: "http_proxy");
72 else if (queryProtocol == "https"_L1)
73 proxy_env = qgetenv(varName: "https_proxy");
74 else if (queryProtocol == "ftp"_L1)
75 proxy_env = qgetenv(varName: "ftp_proxy");
76 else
77 proxy_env = qgetenv(varName: "all_proxy");
78
79 // Fallback to http_proxy is no protocol specific proxy was found
80 if (proxy_env.isEmpty())
81 proxy_env = qgetenv(varName: "http_proxy");
82
83 if (!proxy_env.isEmpty()) {
84 QUrl url = QUrl(QString::fromLocal8Bit(ba: proxy_env));
85 const QString scheme = url.scheme();
86 if (scheme == "socks5"_L1) {
87 QNetworkProxy proxy(QNetworkProxy::Socks5Proxy, url.host(),
88 url.port() ? url.port() : 1080, url.userName(), url.password());
89 proxyList << proxy;
90 } else if (scheme == "socks5h"_L1) {
91 QNetworkProxy proxy(QNetworkProxy::Socks5Proxy, url.host(),
92 url.port() ? url.port() : 1080, url.userName(), url.password());
93 proxy.setCapabilities(QNetworkProxy::HostNameLookupCapability);
94 proxyList << proxy;
95 } else if ((scheme.isEmpty() || scheme == "http"_L1)
96 && query.queryType() != QNetworkProxyQuery::UdpSocket
97 && query.queryType() != QNetworkProxyQuery::TcpServer) {
98 QNetworkProxy proxy(QNetworkProxy::HttpProxy, url.host(),
99 url.port() ? url.port() : 8080, url.userName(), url.password());
100 proxyList << proxy;
101 }
102 }
103 if (proxyList.isEmpty())
104 proxyList << QNetworkProxy::NoProxy;
105
106 return proxyList;
107}
108
109QT_END_NAMESPACE
110
111#endif
112

source code of qtbase/src/network/kernel/qnetworkproxy_generic.cpp