eric6/E5Network/E5NetworkProxyFactory.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
child 7229
53054eb5b15a
equal deleted inserted replaced
6941:f99d60d6b59b 6942:2602857055c5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2010 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a network proxy factory.
8 """
9
10 from __future__ import unicode_literals
11
12 import os
13
14 from PyQt5.QtCore import Qt, QUrl, QCoreApplication, QRegExp
15 from PyQt5.QtWidgets import QDialog
16 from PyQt5.QtNetwork import QNetworkProxyFactory, QNetworkProxy, \
17 QNetworkProxyQuery
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.HttpProxy:
35 scheme = "Http"
36 elif proxyType == QNetworkProxy.HttpCachingProxy:
37 scheme = "Https"
38 elif proxyType == QNetworkProxy.FtpCachingProxy:
39 scheme = "Ftp"
40 elif proxyType == QNetworkProxy.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 "E5NetworkProxyFactory",
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.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(object):
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 = QRegExp(regexp, Qt.CaseInsensitive)
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.indexIn(host) > -1
126
127
128 class E5NetworkProxyFactory(QNetworkProxyFactory):
129 """
130 Class implementing a network proxy factory.
131 """
132 def __init__(self):
133 """
134 Constructor
135 """
136 super(E5NetworkProxyFactory, self).__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 query.queryType() == QNetworkProxyQuery.UrlRequest and \
161 query.protocolTag() in ["http", "https", "ftp"]:
162 # use proxy at all ?
163 if not Preferences.getUI("UseProxy"):
164 return [QNetworkProxy(QNetworkProxy.NoProxy)]
165
166 # test for exceptions
167 exceptions = Preferences.getUI("ProxyExceptions")
168 if exceptions != self.__exceptions:
169 self.__setExceptions(exceptions)
170 urlHost = query.url().host()
171 for matcher in self.__hostnameMatchers:
172 if matcher.match(urlHost):
173 return [QNetworkProxy(QNetworkProxy.NoProxy)]
174
175 # determine proxy
176 if Preferences.getUI("UseSystemProxy"):
177 proxyList = QNetworkProxyFactory.systemProxyForQuery(query)
178 if not Globals.isWindowsPlatform() and \
179 len(proxyList) == 1 and \
180 proxyList[0].type() == QNetworkProxy.NoProxy:
181 # try it the Python way
182 # scan the environment for variables named <scheme>_proxy
183 # scan over whole environment to make this case insensitive
184 for name, value in os.environ.items():
185 name = name.lower()
186 if value and name[-6:] == '_proxy' and \
187 name[:-6] == query.protocolTag().lower():
188 url = QUrl(value)
189 if url.scheme() in ["http", "https"]:
190 proxyType = QNetworkProxy.HttpProxy
191 elif url.scheme() == "ftp":
192 proxyType = QNetworkProxy.FtpCachingProxy
193 else:
194 proxyType = QNetworkProxy.HttpProxy
195 proxy = QNetworkProxy(
196 proxyType, url.host(), url.port(),
197 url.userName(), url.password())
198 proxyList = [proxy]
199 break
200 if proxyList:
201 scheme = schemeFromProxyType(proxyList[0].type())
202 if scheme == "":
203 scheme = "Http"
204 if scheme != "NoProxy":
205 proxyList[0].setUser(
206 Preferences.getUI("ProxyUser/{0}".format(scheme)))
207 proxyList[0].setPassword(
208 Preferences.getUI(
209 "ProxyPassword/{0}".format(scheme)))
210 return proxyList
211 else:
212 return [QNetworkProxy(QNetworkProxy.NoProxy)]
213 else:
214 if Preferences.getUI("UseHttpProxyForAll"):
215 protocolKey = "Http"
216 else:
217 protocolKey = query.protocolTag().capitalize()
218 host = Preferences.getUI("ProxyHost/{0}".format(protocolKey))
219 if not host:
220 E5MessageBox.critical(
221 None,
222 QCoreApplication.translate(
223 "E5NetworkProxyFactory",
224 "Proxy Configuration Error"),
225 QCoreApplication.translate(
226 "E5NetworkProxyFactory",
227 """Proxy usage was activated"""
228 """ but no proxy host for protocol"""
229 """ '{0}' configured.""").format(protocolKey))
230 return [QNetworkProxy(QNetworkProxy.DefaultProxy)]
231 else:
232 if protocolKey in ["Http", "Https", "Ftp"]:
233 if query.protocolTag() == "ftp":
234 proxyType = QNetworkProxy.FtpCachingProxy
235 else:
236 proxyType = QNetworkProxy.HttpProxy
237 proxy = QNetworkProxy(
238 proxyType, host,
239 Preferences.getUI("ProxyPort/" + protocolKey),
240 Preferences.getUI("ProxyUser/" + protocolKey),
241 Preferences.getUI("ProxyPassword/" + protocolKey))
242 else:
243 proxy = QNetworkProxy(QNetworkProxy.DefaultProxy)
244 return [proxy, QNetworkProxy(QNetworkProxy.DefaultProxy)]
245 else:
246 return [QNetworkProxy(QNetworkProxy.NoProxy)]

eric ide

mercurial