27 |
28 |
28 class EricSslCertificatesDialog(QDialog, Ui_EricSslCertificatesDialog): |
29 class EricSslCertificatesDialog(QDialog, Ui_EricSslCertificatesDialog): |
29 """ |
30 """ |
30 Class implementing a dialog to show and edit all certificates. |
31 Class implementing a dialog to show and edit all certificates. |
31 """ |
32 """ |
|
33 |
32 CertRole = Qt.ItemDataRole.UserRole + 1 |
34 CertRole = Qt.ItemDataRole.UserRole + 1 |
33 |
35 |
34 def __init__(self, parent=None): |
36 def __init__(self, parent=None): |
35 """ |
37 """ |
36 Constructor |
38 Constructor |
37 |
39 |
38 @param parent reference to the parent widget (QWidget) |
40 @param parent reference to the parent widget (QWidget) |
39 """ |
41 """ |
40 super().__init__(parent) |
42 super().__init__(parent) |
41 self.setupUi(self) |
43 self.setupUi(self) |
42 |
44 |
43 self.serversViewButton.setIcon( |
45 self.serversViewButton.setIcon(UI.PixmapCache.getIcon("certificates")) |
44 UI.PixmapCache.getIcon("certificates")) |
46 self.serversDeleteButton.setIcon(UI.PixmapCache.getIcon("certificateDelete")) |
45 self.serversDeleteButton.setIcon( |
47 self.serversExportButton.setIcon(UI.PixmapCache.getIcon("certificateExport")) |
46 UI.PixmapCache.getIcon("certificateDelete")) |
48 self.serversImportButton.setIcon(UI.PixmapCache.getIcon("certificateImport")) |
47 self.serversExportButton.setIcon( |
49 |
48 UI.PixmapCache.getIcon("certificateExport")) |
50 self.caViewButton.setIcon(UI.PixmapCache.getIcon("certificates")) |
49 self.serversImportButton.setIcon( |
51 self.caDeleteButton.setIcon(UI.PixmapCache.getIcon("certificateDelete")) |
50 UI.PixmapCache.getIcon("certificateImport")) |
52 self.caExportButton.setIcon(UI.PixmapCache.getIcon("certificateExport")) |
51 |
53 self.caImportButton.setIcon(UI.PixmapCache.getIcon("certificateImport")) |
52 self.caViewButton.setIcon( |
54 |
53 UI.PixmapCache.getIcon("certificates")) |
|
54 self.caDeleteButton.setIcon( |
|
55 UI.PixmapCache.getIcon("certificateDelete")) |
|
56 self.caExportButton.setIcon( |
|
57 UI.PixmapCache.getIcon("certificateExport")) |
|
58 self.caImportButton.setIcon( |
|
59 UI.PixmapCache.getIcon("certificateImport")) |
|
60 |
|
61 self.__populateServerCertificatesTree() |
55 self.__populateServerCertificatesTree() |
62 self.__populateCaCertificatesTree() |
56 self.__populateCaCertificatesTree() |
63 |
57 |
64 def __populateServerCertificatesTree(self): |
58 def __populateServerCertificatesTree(self): |
65 """ |
59 """ |
66 Private slot to populate the server certificates tree. |
60 Private slot to populate the server certificates tree. |
67 """ |
61 """ |
68 certificateDict = Globals.toDict( |
62 certificateDict = Globals.toDict( |
69 Preferences.getSettings().value("Ssl/CaCertificatesDict")) |
63 Preferences.getSettings().value("Ssl/CaCertificatesDict") |
|
64 ) |
70 for server in certificateDict: |
65 for server in certificateDict: |
71 for cert in QSslCertificate.fromData(certificateDict[server]): |
66 for cert in QSslCertificate.fromData(certificateDict[server]): |
72 self.__createServerCertificateEntry(server, cert) |
67 self.__createServerCertificateEntry(server, cert) |
73 |
68 |
74 self.serversCertificatesTree.expandAll() |
69 self.serversCertificatesTree.expandAll() |
75 for i in range(self.serversCertificatesTree.columnCount()): |
70 for i in range(self.serversCertificatesTree.columnCount()): |
76 self.serversCertificatesTree.resizeColumnToContents(i) |
71 self.serversCertificatesTree.resizeColumnToContents(i) |
77 |
72 |
78 def __createServerCertificateEntry(self, server, cert): |
73 def __createServerCertificateEntry(self, server, cert): |
79 """ |
74 """ |
80 Private method to create a server certificate entry. |
75 Private method to create a server certificate entry. |
81 |
76 |
82 @param server server name of the certificate (string) |
77 @param server server name of the certificate (string) |
83 @param cert certificate to insert (QSslCertificate) |
78 @param cert certificate to insert (QSslCertificate) |
84 """ |
79 """ |
85 # step 1: extract the info to be shown |
80 # step 1: extract the info to be shown |
86 organisation = Utilities.decodeString( |
81 organisation = Utilities.decodeString( |
87 ", ".join(cert.subjectInfo( |
82 ", ".join(cert.subjectInfo(QSslCertificate.SubjectInfo.Organization)) |
88 QSslCertificate.SubjectInfo.Organization))) |
83 ) |
89 commonName = Utilities.decodeString( |
84 commonName = Utilities.decodeString( |
90 ", ".join(cert.subjectInfo( |
85 ", ".join(cert.subjectInfo(QSslCertificate.SubjectInfo.CommonName)) |
91 QSslCertificate.SubjectInfo.CommonName))) |
86 ) |
92 if organisation is None or organisation == "": |
87 if organisation is None or organisation == "": |
93 organisation = self.tr("(Unknown)") |
88 organisation = self.tr("(Unknown)") |
94 if commonName is None or commonName == "": |
89 if commonName is None or commonName == "": |
95 commonName = self.tr("(Unknown common name)") |
90 commonName = self.tr("(Unknown common name)") |
96 expiryDate = cert.expiryDate().toString("yyyy-MM-dd") |
91 expiryDate = cert.expiryDate().toString("yyyy-MM-dd") |
97 |
92 |
98 # step 2: create the entry |
93 # step 2: create the entry |
99 items = self.serversCertificatesTree.findItems( |
94 items = self.serversCertificatesTree.findItems( |
100 organisation, |
95 organisation, |
101 Qt.MatchFlag.MatchFixedString | Qt.MatchFlag.MatchCaseSensitive) |
96 Qt.MatchFlag.MatchFixedString | Qt.MatchFlag.MatchCaseSensitive, |
|
97 ) |
102 if len(items) == 0: |
98 if len(items) == 0: |
103 parent = QTreeWidgetItem( |
99 parent = QTreeWidgetItem(self.serversCertificatesTree, [organisation]) |
104 self.serversCertificatesTree, [organisation]) |
|
105 parent.setFirstColumnSpanned(True) |
100 parent.setFirstColumnSpanned(True) |
106 else: |
101 else: |
107 parent = items[0] |
102 parent = items[0] |
108 |
103 |
109 itm = QTreeWidgetItem(parent, [commonName, server, expiryDate]) |
104 itm = QTreeWidgetItem(parent, [commonName, server, expiryDate]) |
110 itm.setData(0, self.CertRole, cert.toPem()) |
105 itm.setData(0, self.CertRole, cert.toPem()) |
111 |
106 |
112 @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem) |
107 @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem) |
113 def on_serversCertificatesTree_currentItemChanged(self, current, previous): |
108 def on_serversCertificatesTree_currentItemChanged(self, current, previous): |
114 """ |
109 """ |
115 Private slot handling a change of the current item in the |
110 Private slot handling a change of the current item in the |
116 server certificates list. |
111 server certificates list. |
117 |
112 |
118 @param current new current item (QTreeWidgetItem) |
113 @param current new current item (QTreeWidgetItem) |
119 @param previous previous current item (QTreeWidgetItem) |
114 @param previous previous current item (QTreeWidgetItem) |
120 """ |
115 """ |
121 enable = current is not None and current.parent() is not None |
116 enable = current is not None and current.parent() is not None |
122 self.serversViewButton.setEnabled(enable) |
117 self.serversViewButton.setEnabled(enable) |
123 self.serversDeleteButton.setEnabled(enable) |
118 self.serversDeleteButton.setEnabled(enable) |
124 self.serversExportButton.setEnabled(enable) |
119 self.serversExportButton.setEnabled(enable) |
125 |
120 |
126 @pyqtSlot() |
121 @pyqtSlot() |
127 def on_serversViewButton_clicked(self): |
122 def on_serversViewButton_clicked(self): |
128 """ |
123 """ |
129 Private slot to show data of the selected server certificate. |
124 Private slot to show data of the selected server certificate. |
130 """ |
125 """ |
131 with contextlib.suppress(ImportError): |
126 with contextlib.suppress(ImportError): |
132 from EricNetwork.EricSslCertificatesInfoDialog import ( |
127 from EricNetwork.EricSslCertificatesInfoDialog import ( |
133 EricSslCertificatesInfoDialog |
128 EricSslCertificatesInfoDialog, |
134 ) |
129 ) |
|
130 |
135 cert = QSslCertificate.fromData( |
131 cert = QSslCertificate.fromData( |
136 self.serversCertificatesTree.currentItem().data( |
132 self.serversCertificatesTree.currentItem().data(0, self.CertRole) |
137 0, self.CertRole)) |
133 ) |
138 dlg = EricSslCertificatesInfoDialog(cert, self) |
134 dlg = EricSslCertificatesInfoDialog(cert, self) |
139 dlg.exec() |
135 dlg.exec() |
140 |
136 |
141 @pyqtSlot() |
137 @pyqtSlot() |
142 def on_serversDeleteButton_clicked(self): |
138 def on_serversDeleteButton_clicked(self): |
143 """ |
139 """ |
144 Private slot to delete the selected server certificate. |
140 Private slot to delete the selected server certificate. |
145 """ |
141 """ |
146 itm = self.serversCertificatesTree.currentItem() |
142 itm = self.serversCertificatesTree.currentItem() |
147 res = EricMessageBox.yesNo( |
143 res = EricMessageBox.yesNo( |
148 self, |
144 self, |
149 self.tr("Delete Server Certificate"), |
145 self.tr("Delete Server Certificate"), |
150 self.tr("""<p>Shall the server certificate really be""" |
146 self.tr( |
151 """ deleted?</p><p>{0}</p>""" |
147 """<p>Shall the server certificate really be""" |
152 """<p>If the server certificate is deleted, the""" |
148 """ deleted?</p><p>{0}</p>""" |
153 """ normal security checks will be reinstantiated""" |
149 """<p>If the server certificate is deleted, the""" |
154 """ and the server has to present a valid""" |
150 """ normal security checks will be reinstantiated""" |
155 """ certificate.</p>""") |
151 """ and the server has to present a valid""" |
156 .format(itm.text(0))) |
152 """ certificate.</p>""" |
|
153 ).format(itm.text(0)), |
|
154 ) |
157 if res: |
155 if res: |
158 server = itm.text(1) |
156 server = itm.text(1) |
159 cert = self.serversCertificatesTree.currentItem().data( |
157 cert = self.serversCertificatesTree.currentItem().data(0, self.CertRole) |
160 0, self.CertRole) |
158 |
161 |
|
162 # delete the selected entry and its parent entry, |
159 # delete the selected entry and its parent entry, |
163 # if it was the only one |
160 # if it was the only one |
164 parent = itm.parent() |
161 parent = itm.parent() |
165 parent.takeChild(parent.indexOfChild(itm)) |
162 parent.takeChild(parent.indexOfChild(itm)) |
166 if parent.childCount() == 0: |
163 if parent.childCount() == 0: |
167 self.serversCertificatesTree.takeTopLevelItem( |
164 self.serversCertificatesTree.takeTopLevelItem( |
168 self.serversCertificatesTree.indexOfTopLevelItem(parent)) |
165 self.serversCertificatesTree.indexOfTopLevelItem(parent) |
169 |
166 ) |
|
167 |
170 # delete the certificate from the user certificate store |
168 # delete the certificate from the user certificate store |
171 certificateDict = Globals.toDict( |
169 certificateDict = Globals.toDict( |
172 Preferences.getSettings().value("Ssl/CaCertificatesDict")) |
170 Preferences.getSettings().value("Ssl/CaCertificatesDict") |
|
171 ) |
173 if server in certificateDict: |
172 if server in certificateDict: |
174 certs = [c.toPem() for c in |
173 certs = [ |
175 QSslCertificate.fromData(certificateDict[server])] |
174 c.toPem() for c in QSslCertificate.fromData(certificateDict[server]) |
|
175 ] |
176 if cert in certs: |
176 if cert in certs: |
177 certs.remove(cert) |
177 certs.remove(cert) |
178 if certs: |
178 if certs: |
179 pems = QByteArray() |
179 pems = QByteArray() |
180 for cert in certs: |
180 for cert in certs: |
181 pems.append(cert + b'\n') |
181 pems.append(cert + b"\n") |
182 certificateDict[server] = pems |
182 certificateDict[server] = pems |
183 else: |
183 else: |
184 del certificateDict[server] |
184 del certificateDict[server] |
185 Preferences.getSettings().setValue( |
185 Preferences.getSettings().setValue( |
186 "Ssl/CaCertificatesDict", |
186 "Ssl/CaCertificatesDict", certificateDict |
187 certificateDict) |
187 ) |
188 |
188 |
189 # delete the certificate from the default certificates |
189 # delete the certificate from the default certificates |
190 self.__updateDefaultConfiguration() |
190 self.__updateDefaultConfiguration() |
191 |
191 |
192 @pyqtSlot() |
192 @pyqtSlot() |
193 def on_serversImportButton_clicked(self): |
193 def on_serversImportButton_clicked(self): |
194 """ |
194 """ |
195 Private slot to import server certificates. |
195 Private slot to import server certificates. |
196 """ |
196 """ |
197 certs = self.__importCertificate() |
197 certs = self.__importCertificate() |
198 if certs: |
198 if certs: |
199 server = "*" |
199 server = "*" |
200 certificateDict = Globals.toDict( |
200 certificateDict = Globals.toDict( |
201 Preferences.getSettings().value("Ssl/CaCertificatesDict")) |
201 Preferences.getSettings().value("Ssl/CaCertificatesDict") |
|
202 ) |
202 if server in certificateDict: |
203 if server in certificateDict: |
203 sCerts = QSslCertificate.fromData(certificateDict[server]) |
204 sCerts = QSslCertificate.fromData(certificateDict[server]) |
204 else: |
205 else: |
205 sCerts = [] |
206 sCerts = [] |
206 |
207 |
207 pems = QByteArray() |
208 pems = QByteArray() |
208 for cert in certs: |
209 for cert in certs: |
209 if cert in sCerts: |
210 if cert in sCerts: |
210 commonStr = ", ".join( |
211 commonStr = ", ".join( |
211 cert.subjectInfo( |
212 cert.subjectInfo(QSslCertificate.SubjectInfo.CommonName) |
212 QSslCertificate.SubjectInfo.CommonName)) |
213 ) |
213 EricMessageBox.warning( |
214 EricMessageBox.warning( |
214 self, |
215 self, |
215 self.tr("Import Certificate"), |
216 self.tr("Import Certificate"), |
216 self.tr( |
217 self.tr( |
217 """<p>The certificate <b>{0}</b> already exists.""" |
218 """<p>The certificate <b>{0}</b> already exists.""" |
218 """ Skipping.</p>""") |
219 """ Skipping.</p>""" |
219 .format(Utilities.decodeString(commonStr))) |
220 ).format(Utilities.decodeString(commonStr)), |
|
221 ) |
220 else: |
222 else: |
221 pems.append(cert.toPem() + b'\n') |
223 pems.append(cert.toPem() + b"\n") |
222 if server not in certificateDict: |
224 if server not in certificateDict: |
223 certificateDict[server] = QByteArray() |
225 certificateDict[server] = QByteArray() |
224 certificateDict[server].append(pems) |
226 certificateDict[server].append(pems) |
225 Preferences.getSettings().setValue( |
227 Preferences.getSettings().setValue( |
226 "Ssl/CaCertificatesDict", |
228 "Ssl/CaCertificatesDict", certificateDict |
227 certificateDict) |
229 ) |
228 |
230 |
229 self.serversCertificatesTree.clear() |
231 self.serversCertificatesTree.clear() |
230 self.__populateServerCertificatesTree() |
232 self.__populateServerCertificatesTree() |
231 |
233 |
232 self.__updateDefaultConfiguration() |
234 self.__updateDefaultConfiguration() |
233 |
235 |
234 @pyqtSlot() |
236 @pyqtSlot() |
235 def on_serversExportButton_clicked(self): |
237 def on_serversExportButton_clicked(self): |
236 """ |
238 """ |
237 Private slot to export the selected server certificate. |
239 Private slot to export the selected server certificate. |
238 """ |
240 """ |
239 cert = self.serversCertificatesTree.currentItem().data( |
241 cert = self.serversCertificatesTree.currentItem().data(0, self.CertRole) |
240 0, self.CertRole) |
|
241 fname = ( |
242 fname = ( |
242 self.serversCertificatesTree.currentItem().text(0).replace(" ", "") |
243 self.serversCertificatesTree.currentItem() |
|
244 .text(0) |
|
245 .replace(" ", "") |
243 .replace("\t", "") |
246 .replace("\t", "") |
244 ) |
247 ) |
245 self.__exportCertificate(fname, cert) |
248 self.__exportCertificate(fname, cert) |
246 |
249 |
247 def __updateDefaultConfiguration(self): |
250 def __updateDefaultConfiguration(self): |
248 """ |
251 """ |
249 Private method to update the default SSL configuration. |
252 Private method to update the default SSL configuration. |
250 """ |
253 """ |
251 caList = self.__getSystemCaCertificates() |
254 caList = self.__getSystemCaCertificates() |
252 certificateDict = Globals.toDict( |
255 certificateDict = Globals.toDict( |
253 Preferences.getSettings().value("Ssl/CaCertificatesDict")) |
256 Preferences.getSettings().value("Ssl/CaCertificatesDict") |
|
257 ) |
254 for server in certificateDict: |
258 for server in certificateDict: |
255 for cert in QSslCertificate.fromData(certificateDict[server]): |
259 for cert in QSslCertificate.fromData(certificateDict[server]): |
256 if cert not in caList: |
260 if cert not in caList: |
257 caList.append(cert) |
261 caList.append(cert) |
258 sslCfg = QSslConfiguration.defaultConfiguration() |
262 sslCfg = QSslConfiguration.defaultConfiguration() |
259 sslCfg.setCaCertificates(caList) |
263 sslCfg.setCaCertificates(caList) |
260 QSslConfiguration.setDefaultConfiguration(sslCfg) |
264 QSslConfiguration.setDefaultConfiguration(sslCfg) |
261 |
265 |
262 def __getSystemCaCertificates(self): |
266 def __getSystemCaCertificates(self): |
263 """ |
267 """ |
264 Private method to get the list of system certificates. |
268 Private method to get the list of system certificates. |
265 |
269 |
266 @return list of system certificates (list of QSslCertificate) |
270 @return list of system certificates (list of QSslCertificate) |
267 """ |
271 """ |
268 caList = QSslCertificate.fromData(Globals.toByteArray( |
272 caList = QSslCertificate.fromData( |
269 Preferences.getSettings().value("Help/SystemCertificates"))) |
273 Globals.toByteArray( |
|
274 Preferences.getSettings().value("Help/SystemCertificates") |
|
275 ) |
|
276 ) |
270 if not caList: |
277 if not caList: |
271 caList = QSslConfiguration.systemCaCertificates() |
278 caList = QSslConfiguration.systemCaCertificates() |
272 return caList |
279 return caList |
273 |
280 |
274 def __populateCaCertificatesTree(self): |
281 def __populateCaCertificatesTree(self): |
275 """ |
282 """ |
276 Private slot to populate the CA certificates tree. |
283 Private slot to populate the CA certificates tree. |
277 """ |
284 """ |
278 for cert in self.__getSystemCaCertificates(): |
285 for cert in self.__getSystemCaCertificates(): |
279 self.__createCaCertificateEntry(cert) |
286 self.__createCaCertificateEntry(cert) |
280 |
287 |
281 self.caCertificatesTree.expandAll() |
288 self.caCertificatesTree.expandAll() |
282 for i in range(self.caCertificatesTree.columnCount()): |
289 for i in range(self.caCertificatesTree.columnCount()): |
283 self.caCertificatesTree.resizeColumnToContents(i) |
290 self.caCertificatesTree.resizeColumnToContents(i) |
284 self.caCertificatesTree.sortItems(0, Qt.SortOrder.AscendingOrder) |
291 self.caCertificatesTree.sortItems(0, Qt.SortOrder.AscendingOrder) |
285 |
292 |
286 def __createCaCertificateEntry(self, cert): |
293 def __createCaCertificateEntry(self, cert): |
287 """ |
294 """ |
288 Private method to create a CA certificate entry. |
295 Private method to create a CA certificate entry. |
289 |
296 |
290 @param cert certificate to insert (QSslCertificate) |
297 @param cert certificate to insert (QSslCertificate) |
291 """ |
298 """ |
292 # step 1: extract the info to be shown |
299 # step 1: extract the info to be shown |
293 organisation = Utilities.decodeString( |
300 organisation = Utilities.decodeString( |
294 ", ".join(cert.subjectInfo( |
301 ", ".join(cert.subjectInfo(QSslCertificate.SubjectInfo.Organization)) |
295 QSslCertificate.SubjectInfo.Organization))) |
302 ) |
296 commonName = Utilities.decodeString( |
303 commonName = Utilities.decodeString( |
297 ", ".join(cert.subjectInfo( |
304 ", ".join(cert.subjectInfo(QSslCertificate.SubjectInfo.CommonName)) |
298 QSslCertificate.SubjectInfo.CommonName))) |
305 ) |
299 if organisation is None or organisation == "": |
306 if organisation is None or organisation == "": |
300 organisation = self.tr("(Unknown)") |
307 organisation = self.tr("(Unknown)") |
301 if commonName is None or commonName == "": |
308 if commonName is None or commonName == "": |
302 commonName = self.tr("(Unknown common name)") |
309 commonName = self.tr("(Unknown common name)") |
303 expiryDate = cert.expiryDate().toString("yyyy-MM-dd") |
310 expiryDate = cert.expiryDate().toString("yyyy-MM-dd") |
304 |
311 |
305 # step 2: create the entry |
312 # step 2: create the entry |
306 items = self.caCertificatesTree.findItems( |
313 items = self.caCertificatesTree.findItems( |
307 organisation, |
314 organisation, |
308 Qt.MatchFlag.MatchFixedString | Qt.MatchFlag.MatchCaseSensitive) |
315 Qt.MatchFlag.MatchFixedString | Qt.MatchFlag.MatchCaseSensitive, |
|
316 ) |
309 if len(items) == 0: |
317 if len(items) == 0: |
310 parent = QTreeWidgetItem(self.caCertificatesTree, [organisation]) |
318 parent = QTreeWidgetItem(self.caCertificatesTree, [organisation]) |
311 parent.setFirstColumnSpanned(True) |
319 parent.setFirstColumnSpanned(True) |
312 else: |
320 else: |
313 parent = items[0] |
321 parent = items[0] |
314 |
322 |
315 itm = QTreeWidgetItem(parent, [commonName, expiryDate]) |
323 itm = QTreeWidgetItem(parent, [commonName, expiryDate]) |
316 itm.setData(0, self.CertRole, cert.toPem()) |
324 itm.setData(0, self.CertRole, cert.toPem()) |
317 |
325 |
318 @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem) |
326 @pyqtSlot(QTreeWidgetItem, QTreeWidgetItem) |
319 def on_caCertificatesTree_currentItemChanged(self, current, previous): |
327 def on_caCertificatesTree_currentItemChanged(self, current, previous): |
320 """ |
328 """ |
321 Private slot handling a change of the current item |
329 Private slot handling a change of the current item |
322 in the CA certificates list. |
330 in the CA certificates list. |
323 |
331 |
324 @param current new current item (QTreeWidgetItem) |
332 @param current new current item (QTreeWidgetItem) |
325 @param previous previous current item (QTreeWidgetItem) |
333 @param previous previous current item (QTreeWidgetItem) |
326 """ |
334 """ |
327 enable = current is not None and current.parent() is not None |
335 enable = current is not None and current.parent() is not None |
328 self.caViewButton.setEnabled(enable) |
336 self.caViewButton.setEnabled(enable) |
329 self.caDeleteButton.setEnabled(enable) |
337 self.caDeleteButton.setEnabled(enable) |
330 self.caExportButton.setEnabled(enable) |
338 self.caExportButton.setEnabled(enable) |
331 |
339 |
332 @pyqtSlot() |
340 @pyqtSlot() |
333 def on_caViewButton_clicked(self): |
341 def on_caViewButton_clicked(self): |
334 """ |
342 """ |
335 Private slot to show data of the selected CA certificate. |
343 Private slot to show data of the selected CA certificate. |
336 """ |
344 """ |
337 with contextlib.suppress(ImportError): |
345 with contextlib.suppress(ImportError): |
338 from EricNetwork.EricSslCertificatesInfoDialog import ( |
346 from EricNetwork.EricSslCertificatesInfoDialog import ( |
339 EricSslCertificatesInfoDialog |
347 EricSslCertificatesInfoDialog, |
340 ) |
348 ) |
|
349 |
341 cert = QSslCertificate.fromData( |
350 cert = QSslCertificate.fromData( |
342 self.caCertificatesTree.currentItem().data(0, self.CertRole)) |
351 self.caCertificatesTree.currentItem().data(0, self.CertRole) |
|
352 ) |
343 dlg = EricSslCertificatesInfoDialog(cert, self) |
353 dlg = EricSslCertificatesInfoDialog(cert, self) |
344 dlg.exec() |
354 dlg.exec() |
345 |
355 |
346 @pyqtSlot() |
356 @pyqtSlot() |
347 def on_caDeleteButton_clicked(self): |
357 def on_caDeleteButton_clicked(self): |
348 """ |
358 """ |
349 Private slot to delete the selected CA certificate. |
359 Private slot to delete the selected CA certificate. |
350 """ |
360 """ |
391 if certs: |
402 if certs: |
392 caCerts = self.__getSystemCaCertificates() |
403 caCerts = self.__getSystemCaCertificates() |
393 for cert in certs: |
404 for cert in certs: |
394 if cert in caCerts: |
405 if cert in caCerts: |
395 commonStr = ", ".join( |
406 commonStr = ", ".join( |
396 cert.subjectInfo( |
407 cert.subjectInfo(QSslCertificate.SubjectInfo.CommonName) |
397 QSslCertificate.SubjectInfo.CommonName)) |
408 ) |
398 EricMessageBox.warning( |
409 EricMessageBox.warning( |
399 self, |
410 self, |
400 self.tr("Import Certificate"), |
411 self.tr("Import Certificate"), |
401 self.tr( |
412 self.tr( |
402 """<p>The certificate <b>{0}</b> already exists.""" |
413 """<p>The certificate <b>{0}</b> already exists.""" |
403 """ Skipping.</p>""") |
414 """ Skipping.</p>""" |
404 .format(Utilities.decodeString(commonStr))) |
415 ).format(Utilities.decodeString(commonStr)), |
|
416 ) |
405 else: |
417 else: |
406 caCerts.append(cert) |
418 caCerts.append(cert) |
407 |
419 |
408 pems = QByteArray() |
420 pems = QByteArray() |
409 for cert in caCerts: |
421 for cert in caCerts: |
410 pems.append(cert.toPem() + '\n') |
422 pems.append(cert.toPem() + "\n") |
411 Preferences.getSettings().setValue( |
423 Preferences.getSettings().setValue("Help/SystemCertificates", pems) |
412 "Help/SystemCertificates", pems) |
424 |
413 |
|
414 self.caCertificatesTree.clear() |
425 self.caCertificatesTree.clear() |
415 self.__populateCaCertificatesTree() |
426 self.__populateCaCertificatesTree() |
416 |
427 |
417 self.__updateDefaultConfiguration() |
428 self.__updateDefaultConfiguration() |
418 |
429 |
419 @pyqtSlot() |
430 @pyqtSlot() |
420 def on_caExportButton_clicked(self): |
431 def on_caExportButton_clicked(self): |
421 """ |
432 """ |
422 Private slot to export the selected CA certificate. |
433 Private slot to export the selected CA certificate. |
423 """ |
434 """ |
424 cert = self.caCertificatesTree.currentItem().data(0, self.CertRole) |
435 cert = self.caCertificatesTree.currentItem().data(0, self.CertRole) |
425 fname = ( |
436 fname = ( |
426 self.caCertificatesTree.currentItem().text(0).replace(" ", "") |
437 self.caCertificatesTree.currentItem() |
|
438 .text(0) |
|
439 .replace(" ", "") |
427 .replace("\t", "") |
440 .replace("\t", "") |
428 ) |
441 ) |
429 self.__exportCertificate(fname, cert) |
442 self.__exportCertificate(fname, cert) |
430 |
443 |
431 def __exportCertificate(self, name, cert): |
444 def __exportCertificate(self, name, cert): |
432 """ |
445 """ |
433 Private slot to export a certificate. |
446 Private slot to export a certificate. |
434 |
447 |
435 @param name default file name without extension |
448 @param name default file name without extension |
436 @type str |
449 @type str |
437 @param cert certificate to be exported encoded as PEM |
450 @param cert certificate to be exported encoded as PEM |
438 @type QByteArray |
451 @type QByteArray |
439 """ |
452 """ |
440 if cert is not None: |
453 if cert is not None: |
441 fname, selectedFilter = EricFileDialog.getSaveFileNameAndFilter( |
454 fname, selectedFilter = EricFileDialog.getSaveFileNameAndFilter( |
442 self, |
455 self, |
443 self.tr("Export Certificate"), |
456 self.tr("Export Certificate"), |
444 name, |
457 name, |
445 self.tr("Certificate File (PEM) (*.pem);;" |
458 self.tr( |
446 "Certificate File (DER) (*.der)"), |
459 "Certificate File (PEM) (*.pem);;" "Certificate File (DER) (*.der)" |
|
460 ), |
447 None, |
461 None, |
448 EricFileDialog.DontConfirmOverwrite) |
462 EricFileDialog.DontConfirmOverwrite, |
449 |
463 ) |
|
464 |
450 if fname: |
465 if fname: |
451 fpath = pathlib.Path(fname) |
466 fpath = pathlib.Path(fname) |
452 if not fpath.suffix: |
467 if not fpath.suffix: |
453 ex = selectedFilter.split("(*")[1].split(")")[0] |
468 ex = selectedFilter.split("(*")[1].split(")")[0] |
454 if ex: |
469 if ex: |
455 fpath = fpath.with_suffix(ex) |
470 fpath = fpath.with_suffix(ex) |
456 if fpath.exists(): |
471 if fpath.exists(): |
457 res = EricMessageBox.yesNo( |
472 res = EricMessageBox.yesNo( |
458 self, |
473 self, |
459 self.tr("Export Certificate"), |
474 self.tr("Export Certificate"), |
460 self.tr("<p>The file <b>{0}</b> already exists." |
475 self.tr( |
461 " Overwrite it?</p>").format(fname), |
476 "<p>The file <b>{0}</b> already exists." |
462 icon=EricMessageBox.Warning) |
477 " Overwrite it?</p>" |
|
478 ).format(fname), |
|
479 icon=EricMessageBox.Warning, |
|
480 ) |
463 if not res: |
481 if not res: |
464 return |
482 return |
465 |
483 |
466 if fpath.suffix == ".pem": |
484 if fpath.suffix == ".pem": |
467 crt = bytes(cert) |
485 crt = bytes(cert) |
468 else: |
486 else: |
469 crt = bytes( |
487 crt = bytes( |
470 QSslCertificate.fromData( |
488 QSslCertificate.fromData(crt, QSsl.EncodingFormat.Pem)[ |
471 crt, QSsl.EncodingFormat.Pem)[0].toDer() |
489 0 |
|
490 ].toDer() |
472 ) |
491 ) |
473 try: |
492 try: |
474 with fpath.open("wb") as f: |
493 with fpath.open("wb") as f: |
475 f.write(crt) |
494 f.write(crt) |
476 except OSError as err: |
495 except OSError as err: |
477 EricMessageBox.critical( |
496 EricMessageBox.critical( |
478 self, |
497 self, |
479 self.tr("Export Certificate"), |
498 self.tr("Export Certificate"), |
480 self.tr( |
499 self.tr( |
481 """<p>The certificate could not be written""" |
500 """<p>The certificate could not be written""" |
482 """ to file <b>{0}</b></p><p>Error: {1}</p>""") |
501 """ to file <b>{0}</b></p><p>Error: {1}</p>""" |
483 .format(fpath, str(err))) |
502 ).format(fpath, str(err)), |
484 |
503 ) |
|
504 |
485 def __importCertificate(self): |
505 def __importCertificate(self): |
486 """ |
506 """ |
487 Private method to read a certificate. |
507 Private method to read a certificate. |
488 |
508 |
489 @return certificates read |
509 @return certificates read |
490 @rtype list of QSslCertificate |
510 @rtype list of QSslCertificate |
491 """ |
511 """ |
492 fname = EricFileDialog.getOpenFileName( |
512 fname = EricFileDialog.getOpenFileName( |
493 self, |
513 self, |
494 self.tr("Import Certificate"), |
514 self.tr("Import Certificate"), |
495 "", |
515 "", |
496 self.tr("Certificate Files (*.pem *.crt *.der *.cer *.ca);;" |
516 self.tr( |
497 "All Files (*)")) |
517 "Certificate Files (*.pem *.crt *.der *.cer *.ca);;" "All Files (*)" |
498 |
518 ), |
|
519 ) |
|
520 |
499 if fname: |
521 if fname: |
500 try: |
522 try: |
501 with pathlib.Path(fname).open("rb") as f: |
523 with pathlib.Path(fname).open("rb") as f: |
502 crt = QByteArray(f.read()) |
524 crt = QByteArray(f.read()) |
503 cert = QSslCertificate.fromData( |
525 cert = QSslCertificate.fromData(crt, QSsl.EncodingFormat.Pem) |
504 crt, QSsl.EncodingFormat.Pem) |
|
505 if not cert: |
526 if not cert: |
506 cert = QSslCertificate.fromData( |
527 cert = QSslCertificate.fromData(crt, QSsl.EncodingFormat.Der) |
507 crt, QSsl.EncodingFormat.Der) |
528 |
508 |
|
509 return cert |
529 return cert |
510 except OSError as err: |
530 except OSError as err: |
511 EricMessageBox.critical( |
531 EricMessageBox.critical( |
512 self, |
532 self, |
513 self.tr("Import Certificate"), |
533 self.tr("Import Certificate"), |
514 self.tr( |
534 self.tr( |
515 """<p>The certificate could not be read from file""" |
535 """<p>The certificate could not be read from file""" |
516 """ <b>{0}</b></p><p>Error: {1}</p>""") |
536 """ <b>{0}</b></p><p>Error: {1}</p>""" |
517 .format(fname, str(err))) |
537 ).format(fname, str(err)), |
518 |
538 ) |
|
539 |
519 return [] |
540 return [] |