7 Module implementing a network manager class. |
7 Module implementing a network manager class. |
8 """ |
8 """ |
9 |
9 |
10 from __future__ import unicode_literals |
10 from __future__ import unicode_literals |
11 |
11 |
|
12 import json |
|
13 |
|
14 from PyQt5.QtCore import pyqtSignal |
12 from PyQt5.QtWidgets import QDialog |
15 from PyQt5.QtWidgets import QDialog |
13 from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkProxy |
16 from PyQt5.QtNetwork import QNetworkAccessManager, QNetworkProxy |
14 |
17 |
15 from E5Gui import E5MessageBox |
18 from E5Gui import E5MessageBox |
16 |
19 |
21 except ImportError: |
24 except ImportError: |
22 SSL_AVAILABLE = False |
25 SSL_AVAILABLE = False |
23 |
26 |
24 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
27 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
25 |
28 |
|
29 from Utilities.AutoSaver import AutoSaver |
26 import Preferences |
30 import Preferences |
27 |
31 |
28 |
32 |
29 class NetworkManager(QNetworkAccessManager): |
33 class NetworkManager(QNetworkAccessManager): |
30 """ |
34 """ |
31 Class implementing a network manager. |
35 Class implementing a network manager. |
|
36 |
|
37 @signal changed() emitted to indicate a change |
32 """ |
38 """ |
|
39 changed = pyqtSignal() |
|
40 |
33 def __init__(self, parent=None): |
41 def __init__(self, parent=None): |
34 """ |
42 """ |
35 Constructor |
43 Constructor |
36 |
44 |
37 @param parent reference to the parent object (QObject) |
45 @param parent reference to the parent object (QObject) |
50 |
58 |
51 if SSL_AVAILABLE: |
59 if SSL_AVAILABLE: |
52 self.__sslErrorHandler = E5SslErrorHandler(self) |
60 self.__sslErrorHandler = E5SslErrorHandler(self) |
53 self.sslErrors.connect(self.__sslErrorHandler.sslErrorsReplySlot) |
61 self.sslErrors.connect(self.__sslErrorHandler.sslErrorsReplySlot) |
54 |
62 |
55 self.__ignoredSslErrors = {} |
63 self.__temporarilyIgnoredSslErrors = {} |
56 # dictionary of temporarily ignored SSL errors |
64 self.__permanentlyIgnoredSslErrors = {} |
57 |
65 # dictionaries of permanently and temporarily ignored SSL errors |
|
66 |
|
67 self.__loaded = False |
|
68 self.__saveTimer = AutoSaver(self, self.__save) |
|
69 |
|
70 self.changed.connect(self.__saveTimer.changeOccurred) |
58 self.proxyAuthenticationRequired.connect(proxyAuthenticationRequired) |
71 self.proxyAuthenticationRequired.connect(proxyAuthenticationRequired) |
59 self.authenticationRequired.connect( |
72 self.authenticationRequired.connect( |
60 lambda reply, auth: self.authentication(reply.url(), auth)) |
73 lambda reply, auth: self.authentication(reply.url(), auth)) |
|
74 |
|
75 def __save(self): |
|
76 """ |
|
77 Private slot to save the permanent SSL error exceptions. |
|
78 """ |
|
79 if not self.__loaded: |
|
80 return |
|
81 |
|
82 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
|
83 if not WebBrowserWindow.isPrivate(): |
|
84 dbString = json.dumps(self.__permanentlyIgnoredSslErrors) |
|
85 Preferences.setWebBrowser("SslExceptionsDB", dbString) |
|
86 |
|
87 def __load(self): |
|
88 """ |
|
89 Private method to load the permanent SSL error exceptions. |
|
90 """ |
|
91 if self.__loaded: |
|
92 return |
|
93 |
|
94 dbString = Preferences.getWebBrowser("SslExceptionsDB") |
|
95 if dbString: |
|
96 try: |
|
97 db = json.loads(dbString) |
|
98 self.__permanentlyIgnoredSslErrors = db |
|
99 except ValueError: |
|
100 # ignore silently |
|
101 pass |
|
102 |
|
103 self.__loaded = True |
|
104 |
|
105 def showSslErrorExceptionsDialog(self): |
|
106 """ |
|
107 Public method to show the SSL error exceptions dialog. |
|
108 """ |
|
109 self.__load() |
|
110 |
|
111 from .SslErrorExceptionsDialog import SslErrorExceptionsDialog |
|
112 dlg = SslErrorExceptionsDialog(self.__permanentlyIgnoredSslErrors) |
|
113 if dlg.exec_() == QDialog.Accepted: |
|
114 self.__permanentlyIgnoredSslErrors = dlg.getSslErrorExceptions() |
|
115 self.changed.emit() |
61 |
116 |
62 def certificateError(self, error, view): |
117 def certificateError(self, error, view): |
63 """ |
118 """ |
64 Public method to handle SSL certificate errors. |
119 Public method to handle SSL certificate errors. |
65 |
120 |
68 @param view reference to a view to be used as parent for the dialog |
123 @param view reference to a view to be used as parent for the dialog |
69 @type QWidget |
124 @type QWidget |
70 @return flag indicating to ignore this error |
125 @return flag indicating to ignore this error |
71 @rtype bool |
126 @rtype bool |
72 """ |
127 """ |
73 # TODO: permanent SSL certificate error exceptions |
128 self.__load() |
|
129 |
74 host = error.url().host() |
130 host = error.url().host() |
75 |
131 |
76 if host in self.__ignoredSslErrors and \ |
132 if host in self.__temporarilyIgnoredSslErrors and \ |
77 self.__ignoredSslErrors[host] == error.error(): |
133 error.error() in self.__temporarilyIgnoredSslErrors[host]: |
|
134 return True |
|
135 |
|
136 if host in self.__permanentlyIgnoredSslErrors and \ |
|
137 error.error() in self.__permanentlyIgnoredSslErrors[host]: |
78 return True |
138 return True |
79 |
139 |
80 title = self.tr("SSL Certificate Error") |
140 title = self.tr("SSL Certificate Error") |
81 accept = E5MessageBox.yesNo( |
141 msgBox = E5MessageBox.E5MessageBox( |
82 view, |
142 E5MessageBox.Warning, |
83 title, |
143 title, |
84 self.tr("""<b>{0}</b>""" |
144 self.tr("""<b>{0}</b>""" |
85 """<p>The page you are trying to access has errors""" |
145 """<p>The page you are trying to access has errors""" |
86 """ in the SSL certificate.</p>""" |
146 """ in the SSL certificate.</p>""" |
87 """<ul><li>{1}</li></ul>""" |
147 """<ul><li>{1}</li></ul>""" |
88 """<p>Would you like to make an exception?</p>""") |
148 """<p>Would you like to make an exception?</p>""") |
89 .format(title, error.errorDescription()), |
149 .format(title, error.errorDescription()), |
90 icon=E5MessageBox.Warning) |
150 modal=True, parent=view) |
91 if accept: |
151 permButton = msgBox.addButton(self.tr("&Permanent accept"), |
92 self.__ignoredSslErrors[error.url().host()] = error.error() |
152 E5MessageBox.AcceptRole) |
93 return True |
153 tempButton = msgBox.addButton(self.tr("&Temporary accept"), |
94 |
154 E5MessageBox.AcceptRole) |
95 return False |
155 msgBox.addButton(self.tr("&Reject"), E5MessageBox.RejectRole) |
|
156 msgBox.exec_() |
|
157 if msgBox.clickedButton() == permButton: |
|
158 if host not in self.__permanentlyIgnoredSslErrors: |
|
159 self.__permanentlyIgnoredSslErrors[host] = [] |
|
160 self.__permanentlyIgnoredSslErrors[host].append(error.error()) |
|
161 self.changed.emit() |
|
162 return True |
|
163 elif msgBox.clickedButton() == tempButton: |
|
164 if host not in self.__temporarilyIgnoredSslErrors: |
|
165 self.__temporarilyIgnoredSslErrors[host] = [] |
|
166 self.__temporarilyIgnoredSslErrors[host].append(error.error()) |
|
167 return True |
|
168 else: |
|
169 return False |
96 |
170 |
97 def authentication(self, url, auth): |
171 def authentication(self, url, auth): |
98 """ |
172 """ |
99 Public slot to handle an authentication request. |
173 Public slot to handle an authentication request. |
100 |
174 |