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