eric7/EricNetwork/EricNetworkProxyFactory.py

branch
eric7
changeset 8354
12ebd3934fef
parent 8318
962bce857696
child 8356
68ec9c3d4de5
equal deleted inserted replaced
8353:799196d0b05d 8354:12ebd3934fef
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2010 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a network proxy factory.
8 """
9
10 import os
11 import re
12
13 from PyQt6.QtCore import QUrl, QCoreApplication
14 from PyQt6.QtWidgets import QDialog
15 from PyQt6.QtNetwork import (
16 QNetworkProxyFactory, QNetworkProxy, QNetworkProxyQuery
17 )
18
19 from E5Gui import E5MessageBox
20
21 import Preferences
22 import Globals
23 import Utilities
24
25
26 def schemeFromProxyType(proxyType):
27 """
28 Module function to determine the scheme name from the proxy type.
29
30 @param proxyType type of the proxy (QNetworkProxy.ProxyType)
31 @return scheme (string, one of Http, Https, Ftp)
32 """
33 scheme = ""
34 if proxyType == QNetworkProxy.ProxyType.HttpProxy:
35 scheme = "Http"
36 elif proxyType == QNetworkProxy.ProxyType.HttpCachingProxy:
37 scheme = "Https"
38 elif proxyType == QNetworkProxy.ProxyType.FtpCachingProxy:
39 scheme = "Ftp"
40 elif proxyType == QNetworkProxy.ProxyType.NoProxy:
41 scheme = "NoProxy"
42 return scheme
43
44
45 def proxyAuthenticationRequired(proxy, auth):
46 """
47 Module slot to handle a proxy authentication request.
48
49 @param proxy reference to the proxy object (QNetworkProxy)
50 @param auth reference to the authenticator object (QAuthenticator)
51 """
52 info = QCoreApplication.translate(
53 "EricNetworkProxyFactory",
54 "<b>Connect to proxy '{0}' using:</b>"
55 ).format(Utilities.html_encode(proxy.hostName()))
56
57 from UI.AuthenticationDialog import AuthenticationDialog
58 dlg = AuthenticationDialog(info, proxy.user(), True)
59 dlg.setData(proxy.user(), proxy.password())
60 if dlg.exec() == QDialog.DialogCode.Accepted:
61 username, password = dlg.getData()
62 auth.setUser(username)
63 auth.setPassword(password)
64 if dlg.shallSave():
65 scheme = schemeFromProxyType(proxy.type())
66 if scheme and scheme != "NoProxy":
67 Preferences.setUI("ProxyUser/{0}".format(scheme), username)
68 Preferences.setUI("ProxyPassword/{0}".format(scheme), password)
69 proxy.setUser(username)
70 proxy.setPassword(password)
71
72
73 class HostnameMatcher:
74 """
75 Class implementing a matcher for host names.
76 """
77 def __init__(self, pattern):
78 """
79 Constructor
80
81 @param pattern pattern to be matched against
82 @type str
83 """
84 self.__regExp = None
85 self.setPattern(pattern)
86
87 def setPattern(self, pattern):
88 """
89 Public method to set the match pattern.
90
91 @param pattern pattern to be matched against
92 """
93 self.__pattern = pattern
94
95 if "?" in pattern or "*" in pattern:
96 regexp = "^.*{0}.*$".format(
97 pattern
98 .replace(".", "\\.")
99 .replace("*", ".*")
100 .replace("?", ".")
101 )
102 self.__regExp = re.compile(regexp, re.IGNORECASE)
103
104 def pattern(self):
105 """
106 Public method to get the match pattern.
107
108 @return match pattern
109 @rtype str
110 """
111 return self.__pattern
112
113 def match(self, host):
114 """
115 Public method to test the given string.
116
117 @param host host name to be matched
118 @type str
119 @return flag indicating a successful match
120 @rtype bool
121 """
122 if self.__regExp is None:
123 return self.__pattern in host
124
125 return self.__regExp.search(host) is not None
126
127
128 class EricNetworkProxyFactory(QNetworkProxyFactory):
129 """
130 Class implementing a network proxy factory.
131 """
132 def __init__(self):
133 """
134 Constructor
135 """
136 super().__init__()
137
138 self.__hostnameMatchers = []
139 self.__exceptions = ""
140
141 def __setExceptions(self, exceptions):
142 """
143 Private method to set the host name exceptions.
144
145 @param exceptions list of exceptions separated by ','
146 @type str
147 """
148 self.__hostnameMatchers = []
149 self.__exceptions = exceptions
150 for exception in self.__exceptions.split(","):
151 self.__hostnameMatchers.append(HostnameMatcher(exception.strip()))
152
153 def queryProxy(self, query):
154 """
155 Public method to determine a proxy for a given query.
156
157 @param query reference to the query object (QNetworkProxyQuery)
158 @return list of proxies in order of preference (list of QNetworkProxy)
159 """
160 if (
161 query.queryType() == QNetworkProxyQuery.QueryType.UrlRequest and
162 query.protocolTag() in ["http", "https", "ftp"]
163 ):
164 # use proxy at all ?
165 if not Preferences.getUI("UseProxy"):
166 return [QNetworkProxy(QNetworkProxy.ProxyType.NoProxy)]
167
168 # test for exceptions
169 exceptions = Preferences.getUI("ProxyExceptions")
170 if exceptions != self.__exceptions:
171 self.__setExceptions(exceptions)
172 urlHost = query.url().host()
173 for matcher in self.__hostnameMatchers:
174 if matcher.match(urlHost):
175 return [QNetworkProxy(QNetworkProxy.ProxyType.NoProxy)]
176
177 # determine proxy
178 if Preferences.getUI("UseSystemProxy"):
179 proxyList = QNetworkProxyFactory.systemProxyForQuery(query)
180 if (
181 not Globals.isWindowsPlatform() and
182 len(proxyList) == 1 and
183 proxyList[0].type() == QNetworkProxy.ProxyType.NoProxy
184 ):
185 # try it the Python way
186 # scan the environment for variables named <scheme>_proxy
187 # scan over whole environment to make this case insensitive
188 for name, value in os.environ.items():
189 name = name.lower()
190 if (
191 value and
192 name[-6:] == '_proxy' and
193 name[:-6] == query.protocolTag().lower()
194 ):
195 url = QUrl(value)
196 if url.scheme() in ["http", "https"]:
197 proxyType = QNetworkProxy.ProxyType.HttpProxy
198 elif url.scheme() == "ftp":
199 proxyType = (
200 QNetworkProxy.ProxyType.FtpCachingProxy
201 )
202 else:
203 proxyType = QNetworkProxy.ProxyType.HttpProxy
204 proxy = QNetworkProxy(
205 proxyType, url.host(), url.port(),
206 url.userName(), url.password())
207 proxyList = [proxy]
208 break
209 if proxyList:
210 scheme = schemeFromProxyType(proxyList[0].type())
211 if scheme == "":
212 scheme = "Http"
213 if scheme != "NoProxy":
214 proxyList[0].setUser(
215 Preferences.getUI("ProxyUser/{0}".format(scheme)))
216 proxyList[0].setPassword(
217 Preferences.getUI(
218 "ProxyPassword/{0}".format(scheme)))
219 return proxyList
220 else:
221 return [QNetworkProxy(QNetworkProxy.ProxyType.NoProxy)]
222 else:
223 if Preferences.getUI("UseHttpProxyForAll"):
224 protocolKey = "Http"
225 else:
226 protocolKey = query.protocolTag().capitalize()
227 host = Preferences.getUI("ProxyHost/{0}".format(protocolKey))
228 if not host:
229 E5MessageBox.critical(
230 None,
231 QCoreApplication.translate(
232 "EricNetworkProxyFactory",
233 "Proxy Configuration Error"),
234 QCoreApplication.translate(
235 "EricNetworkProxyFactory",
236 """Proxy usage was activated"""
237 """ but no proxy host for protocol"""
238 """ '{0}' configured.""").format(protocolKey))
239 return [
240 QNetworkProxy(QNetworkProxy.ProxyType.DefaultProxy)
241 ]
242 else:
243 if protocolKey in ["Http", "Https", "Ftp"]:
244 if query.protocolTag() == "ftp":
245 proxyType = QNetworkProxy.ProxyType.FtpCachingProxy
246 else:
247 proxyType = QNetworkProxy.ProxyType.HttpProxy
248 proxy = QNetworkProxy(
249 proxyType, host,
250 Preferences.getUI("ProxyPort/" + protocolKey),
251 Preferences.getUI("ProxyUser/" + protocolKey),
252 Preferences.getUI("ProxyPassword/" + protocolKey))
253 else:
254 proxy = QNetworkProxy(
255 QNetworkProxy.ProxyType.DefaultProxy)
256 return [
257 proxy,
258 QNetworkProxy(QNetworkProxy.ProxyType.DefaultProxy)
259 ]
260 else:
261 return [QNetworkProxy(QNetworkProxy.ProxyType.NoProxy)]

eric ide

mercurial