|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2019 - 2022 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a dialog to select a SSL certificate. |
|
8 """ |
|
9 |
|
10 import contextlib |
|
11 |
|
12 from PyQt6.QtCore import pyqtSlot, Qt |
|
13 from PyQt6.QtWidgets import QDialog, QDialogButtonBox, QTreeWidgetItem |
|
14 with contextlib.suppress(ImportError): |
|
15 from PyQt6.QtNetwork import QSslCertificate |
|
16 |
|
17 from .Ui_EricSslCertificateSelectionDialog import ( |
|
18 Ui_EricSslCertificateSelectionDialog |
|
19 ) |
|
20 |
|
21 import Utilities |
|
22 import UI.PixmapCache |
|
23 |
|
24 |
|
25 class EricSslCertificateSelectionDialog(QDialog, |
|
26 Ui_EricSslCertificateSelectionDialog): |
|
27 """ |
|
28 Class implementing a dialog to select a SSL certificate. |
|
29 """ |
|
30 CertRole = Qt.ItemDataRole.UserRole + 1 |
|
31 |
|
32 def __init__(self, certificates, parent=None): |
|
33 """ |
|
34 Constructor |
|
35 |
|
36 @param certificates list of SSL certificates to select from |
|
37 @type list of QSslCertificate |
|
38 @param parent reference to the parent widget |
|
39 @type QWidget |
|
40 """ |
|
41 super().__init__(parent) |
|
42 self.setupUi(self) |
|
43 |
|
44 self.viewButton.setIcon( |
|
45 UI.PixmapCache.getIcon("certificates")) |
|
46 |
|
47 self.buttonBox.button(QDialogButtonBox.OK).setEnabled(False) |
|
48 self.viewButton.setEnabled(False) |
|
49 |
|
50 self.__populateCertificatesTree(certificates) |
|
51 |
|
52 def __populateCertificatesTree(self, certificates): |
|
53 """ |
|
54 Private slot to populate the certificates tree. |
|
55 |
|
56 @param certificates list of SSL certificates to select from |
|
57 @type list of QSslCertificate |
|
58 """ |
|
59 for cert in certificates(): |
|
60 self.__createCertificateEntry(cert) |
|
61 |
|
62 self.certificatesTree.expandAll() |
|
63 for i in range(self.certificatesTree.columnCount()): |
|
64 self.certificatesTree.resizeColumnToContents(i) |
|
65 self.certificatesTree.sortItems(0, Qt.SortOrder.AscendingOrder) |
|
66 |
|
67 def __createCaCertificateEntry(self, cert): |
|
68 """ |
|
69 Private method to create a certificate entry. |
|
70 |
|
71 @param cert certificate to insert |
|
72 @type QSslCertificate |
|
73 """ |
|
74 # step 1: extract the info to be shown |
|
75 organisation = Utilities.decodeString( |
|
76 ", ".join(cert.subjectInfo( |
|
77 QSslCertificate.SubjectInfo.Organization))) |
|
78 commonName = Utilities.decodeString( |
|
79 ", ".join(cert.subjectInfo( |
|
80 QSslCertificate.SubjectInfo.CommonName))) |
|
81 if organisation is None or organisation == "": |
|
82 organisation = self.tr("(Unknown)") |
|
83 if commonName is None or commonName == "": |
|
84 commonName = self.tr("(Unknown common name)") |
|
85 expiryDate = cert.expiryDate().toString("yyyy-MM-dd") |
|
86 |
|
87 # step 2: create the entry |
|
88 items = self.certificatesTree.findItems( |
|
89 organisation, |
|
90 Qt.MatchFlag.MatchFixedString | Qt.MatchFlag.MatchCaseSensitive) |
|
91 if len(items) == 0: |
|
92 parent = QTreeWidgetItem(self.certificatesTree, [organisation]) |
|
93 parent.setFirstColumnSpanned(True) |
|
94 else: |
|
95 parent = items[0] |
|
96 |
|
97 itm = QTreeWidgetItem(parent, [commonName, expiryDate]) |
|
98 itm.setData(0, self.CertRole, cert.toPem()) |
|
99 |
|
100 @pyqtSlot() |
|
101 def on_certificatesTree_itemSelectionChanged(self): |
|
102 """ |
|
103 Private slot to handle the selection of an item. |
|
104 """ |
|
105 enable = ( |
|
106 len(self.certificatesTree.selectedItems()) > 0 and |
|
107 self.certificatesTree.selectedItems()[0].parent() is not None |
|
108 ) |
|
109 self.buttonBox.button(QDialogButtonBox.OK).setEnabled(enable) |
|
110 self.viewButton.setEnabled(enable) |
|
111 |
|
112 @pyqtSlot() |
|
113 def on_viewButton_clicked(self): |
|
114 """ |
|
115 Private slot to show data of the selected certificate. |
|
116 """ |
|
117 with contextlib.suppress(ImportError): |
|
118 from EricNetwork.EricSslCertificatesInfoDialog import ( |
|
119 EricSslCertificatesInfoDialog |
|
120 ) |
|
121 cert = QSslCertificate.fromData( |
|
122 self.certificatesTree.selectedItems()[0].data( |
|
123 0, self.CertRole)) |
|
124 dlg = EricSslCertificatesInfoDialog(cert, self) |
|
125 dlg.exec() |
|
126 |
|
127 def getSelectedCertificate(self): |
|
128 """ |
|
129 Public method to get the selected certificate. |
|
130 |
|
131 @return selected certificate |
|
132 @rtype QSslCertificate |
|
133 """ |
|
134 valid = ( |
|
135 len(self.certificatesTree.selectedItems()) > 0 and |
|
136 self.certificatesTree.selectedItems()[0].parent() is not None |
|
137 ) |
|
138 |
|
139 certificate = ( |
|
140 QSslCertificate.fromData( |
|
141 self.certificatesTree.selectedItems()[0].data( |
|
142 0, self.CertRole)) |
|
143 if valid else |
|
144 None |
|
145 ) |
|
146 |
|
147 return certificate |