Changeset View
Changeset View
Standalone View
Standalone View
ui/certificateviewer.cpp
- This file was added.
1 | /*************************************************************************** | ||||
---|---|---|---|---|---|
2 | * Copyright (C) 2018 by Chinmoy Ranjan Pradhan <chinmoyrp65@gmail.com> * | ||||
3 | * * | ||||
4 | * This program is free software; you can redistribute it and/or modify * | ||||
5 | * it under the terms of the GNU General Public License as published by * | ||||
6 | * the Free Software Foundation; either version 2 of the License, or * | ||||
7 | * (at your option) any later version. * | ||||
8 | ***************************************************************************/ | ||||
9 | | ||||
10 | #include "certificateviewer.h" | ||||
11 | | ||||
12 | #include <KMessageBox> | ||||
13 | #include <KLocalizedString> | ||||
14 | #include <KColumnResizer> | ||||
15 | | ||||
16 | #include <QLabel> | ||||
17 | #include <QTextEdit> | ||||
18 | #include <QTreeView> | ||||
19 | #include <QGroupBox> | ||||
20 | #include <QFormLayout> | ||||
21 | #include <QPushButton> | ||||
22 | #include <QVBoxLayout> | ||||
23 | #include <QFileDialog> | ||||
24 | #include <QDialogButtonBox> | ||||
25 | #include <QCryptographicHash> | ||||
26 | | ||||
27 | #include "signatureguiutils.h" | ||||
28 | | ||||
29 | CertificateModel::CertificateModel( Okular::CertificateInfo *certInfo, QObject * parent ) | ||||
30 | : QAbstractTableModel( parent ), m_certificateInfo( certInfo ) | ||||
31 | { | ||||
32 | m_certificateProperties.append( qMakePair( i18n("Version"), i18n("V%1", QString::number( m_certificateInfo->version() )) ) ); | ||||
33 | m_certificateProperties.append( qMakePair( i18n("Serial Number"), m_certificateInfo->serialNumber().toHex(' ') ) ); | ||||
34 | m_certificateProperties.append( qMakePair( i18n("Issuer"), m_certificateInfo->issuerInfo(Okular::CertificateInfo::DistinguishedName) ) ); | ||||
35 | m_certificateProperties.append( qMakePair( i18n("Issued On"), m_certificateInfo->validityStart().toString( QStringLiteral("MMM dd yyyy hh:mm:ss") ) ) ); | ||||
36 | m_certificateProperties.append( qMakePair( i18n("Expires On"), m_certificateInfo->validityEnd().toString( QStringLiteral("MMM dd yyyy hh:mm:ss") ) ) ); | ||||
37 | m_certificateProperties.append( qMakePair( i18n("Subject"), m_certificateInfo->subjectInfo(Okular::CertificateInfo::DistinguishedName) ) ); | ||||
38 | m_certificateProperties.append( qMakePair( i18n("Public Key"), i18n("%1 (%2 bits)", SignatureGuiUtils::getReadablePublicKeyType( m_certificateInfo->publicKeyType() ), | ||||
39 | m_certificateInfo->publicKeyStrength()) ) ); | ||||
40 | m_certificateProperties.append( qMakePair( i18n("Key Usage"), SignatureGuiUtils::getReadableKeyUsage( m_certificateInfo->keyUsageExtensions() ) ) ); | ||||
41 | } | ||||
42 | | ||||
43 | | ||||
44 | int CertificateModel::columnCount( const QModelIndex & ) const | ||||
45 | { | ||||
46 | return 2; | ||||
47 | } | ||||
48 | | ||||
49 | int CertificateModel::rowCount( const QModelIndex & ) const | ||||
50 | { | ||||
51 | return m_certificateProperties.size(); | ||||
52 | } | ||||
53 | | ||||
54 | QVariant CertificateModel::data( const QModelIndex &index, int role ) const | ||||
55 | { | ||||
56 | int row = index.row(); | ||||
57 | if ( !index.isValid() || row < 0 || row >= m_certificateProperties.count() ) | ||||
58 | return QVariant(); | ||||
59 | | ||||
60 | switch ( role ) | ||||
61 | { | ||||
62 | case Qt::DisplayRole: | ||||
63 | case Qt::ToolTipRole: | ||||
64 | switch ( index.column() ) | ||||
65 | { | ||||
66 | case 0: | ||||
67 | return m_certificateProperties[row].first; | ||||
68 | case 1: | ||||
69 | return m_certificateProperties[row].second; | ||||
70 | default: | ||||
71 | return QString(); | ||||
72 | } | ||||
73 | case PropertyKeyRole: | ||||
74 | return m_certificateProperties[row].first; | ||||
75 | case PropertyValueRole: | ||||
76 | return m_certificateProperties[row].second; | ||||
77 | case PublicKeyRole: | ||||
78 | return QString( m_certificateInfo->publicKey().toHex(' ') ); | ||||
79 | } | ||||
80 | | ||||
81 | return QVariant(); | ||||
82 | } | ||||
83 | | ||||
84 | QVariant CertificateModel::headerData( int section, Qt::Orientation orientation, int role ) const | ||||
85 | { | ||||
86 | if ( role == Qt::TextAlignmentRole ) | ||||
87 | return QVariant( Qt::AlignLeft ); | ||||
88 | | ||||
89 | if ( orientation != Qt::Horizontal || role != Qt::DisplayRole) | ||||
90 | return QVariant(); | ||||
91 | | ||||
92 | switch ( section ) | ||||
93 | { | ||||
94 | case 0: | ||||
95 | return i18n("Property"); | ||||
96 | case 1: | ||||
97 | return i18n("Value"); | ||||
98 | default: | ||||
99 | return QVariant(); | ||||
100 | } | ||||
101 | } | ||||
102 | | ||||
103 | CertificateViewer::CertificateViewer( Okular::CertificateInfo *certInfo, QWidget *parent ) | ||||
104 | : KPageDialog( parent ), m_certificateInfo( certInfo ) | ||||
105 | { | ||||
106 | setModal( true ); | ||||
107 | setMinimumSize( QSize( 500, 500 )); | ||||
108 | setFaceType( Tabbed ); | ||||
109 | setWindowTitle( i18n("Certificate Viewer") ); | ||||
110 | setStandardButtons( QDialogButtonBox::Close ); | ||||
111 | | ||||
112 | auto exportBtn = new QPushButton( i18n("Export...") ); | ||||
113 | connect( exportBtn, &QPushButton::clicked, this, &CertificateViewer::exportCertificate ); | ||||
114 | addActionButton( exportBtn ); | ||||
115 | | ||||
116 | // General tab | ||||
117 | auto generalPage = new QFrame( this ); | ||||
118 | addPage( generalPage, i18n("General") ); | ||||
119 | | ||||
120 | auto issuerBox = new QGroupBox( i18n("Issued By"), generalPage ); | ||||
121 | auto issuerFormLayout = new QFormLayout( issuerBox ); | ||||
122 | issuerFormLayout->setLabelAlignment( Qt::AlignLeft ); | ||||
123 | issuerFormLayout->addRow( i18n("Common Name(CN)"), new QLabel( m_certificateInfo->issuerInfo( Okular::CertificateInfo::CommonName ) ) ); | ||||
124 | issuerFormLayout->addRow( i18n("EMail"), new QLabel( m_certificateInfo->issuerInfo( Okular::CertificateInfo::EmailAddress ) ) ); | ||||
125 | issuerFormLayout->addRow( i18n("Organization(O)"), new QLabel( m_certificateInfo->issuerInfo( Okular::CertificateInfo::Organization ) ) ); | ||||
126 | | ||||
127 | auto subjectBox = new QGroupBox( i18n("Issued To"), generalPage ); | ||||
128 | auto subjectFormLayout = new QFormLayout( subjectBox ); | ||||
129 | subjectFormLayout->setLabelAlignment( Qt::AlignLeft ); | ||||
130 | subjectFormLayout->addRow( i18n("Common Name(CN)"), new QLabel( m_certificateInfo->subjectInfo( Okular::CertificateInfo::CommonName ) ) ); | ||||
131 | subjectFormLayout->addRow( i18n("EMail"), new QLabel( m_certificateInfo->subjectInfo( Okular::CertificateInfo::EmailAddress ) ) ); | ||||
132 | subjectFormLayout->addRow( i18n("Organization(O)"), new QLabel( m_certificateInfo->subjectInfo( Okular::CertificateInfo::Organization ) ) ); | ||||
133 | | ||||
134 | auto validityBox = new QGroupBox( i18n("Validity"), generalPage ); | ||||
135 | auto validityFormLayout = new QFormLayout( validityBox ); | ||||
136 | validityFormLayout->setLabelAlignment( Qt::AlignLeft ); | ||||
137 | validityFormLayout->addRow( i18n("Issued On"), new QLabel( m_certificateInfo->validityStart().toString( QStringLiteral("MMM dd yyyy hh:mm:ss") ) ) ); | ||||
138 | validityFormLayout->addRow( i18n("Expires On"), new QLabel( m_certificateInfo->validityEnd().toString( QStringLiteral("MMM dd yyyy hh:mm:ss") ) ) ); | ||||
139 | | ||||
140 | auto fingerprintBox = new QGroupBox( i18n("Fingerprints"), generalPage ); | ||||
141 | auto fingerprintFormLayout = new QFormLayout( fingerprintBox ); | ||||
142 | fingerprintFormLayout->setLabelAlignment( Qt::AlignLeft ); | ||||
143 | QByteArray certData = m_certificateInfo->certificateData(); | ||||
144 | auto sha1Label = new QLabel( QString( QCryptographicHash::hash( certData, QCryptographicHash::Sha1 ).toHex(' ') ) ); | ||||
145 | sha1Label->setWordWrap( true ); | ||||
146 | auto sha256Label = new QLabel( QString( QCryptographicHash::hash( certData, QCryptographicHash::Sha256 ).toHex(' ') ) ); | ||||
147 | sha256Label->setWordWrap( true ); | ||||
148 | fingerprintFormLayout->addRow( i18n("SHA-1 Fingerprint"), sha1Label ); | ||||
149 | fingerprintFormLayout->addRow( i18n("SHA-256 Fingerprint"), sha256Label ); | ||||
150 | | ||||
151 | auto generalPageLayout = new QVBoxLayout( generalPage ); | ||||
152 | generalPageLayout->addWidget( issuerBox ); | ||||
153 | generalPageLayout->addWidget( subjectBox ); | ||||
154 | generalPageLayout->addWidget( validityBox ); | ||||
155 | generalPageLayout->addWidget( fingerprintBox ); | ||||
156 | | ||||
157 | //force column 1 to have same width | ||||
158 | auto resizer = new KColumnResizer( this ); | ||||
159 | resizer->addWidgetsFromLayout( issuerBox->layout(), 0 ); | ||||
160 | resizer->addWidgetsFromLayout( subjectBox->layout(), 0 ); | ||||
161 | resizer->addWidgetsFromLayout( validityBox->layout(), 0 ); | ||||
162 | resizer->addWidgetsFromLayout( fingerprintBox->layout(), 0 ); | ||||
163 | | ||||
164 | // Details tab | ||||
165 | auto detailsFrame = new QFrame( this ); | ||||
166 | addPage( detailsFrame, i18n("Details") ); | ||||
167 | auto certDataLabel = new QLabel( i18n("Certificate Data:") ); | ||||
168 | auto certTree = new QTreeView( this ); | ||||
169 | certTree->setIndentation( 0 ); | ||||
170 | m_certificateModel = new CertificateModel( m_certificateInfo, this ); | ||||
171 | certTree->setModel( m_certificateModel ); | ||||
172 | //QItemSelectionModel::currentChanged because QTreeView::activated only works for mouse. | ||||
173 | connect( certTree->selectionModel(), &QItemSelectionModel::currentChanged, this, &CertificateViewer::updateText ); | ||||
174 | m_propertyText = new QTextEdit( this ); | ||||
175 | m_propertyText->setReadOnly( true ); | ||||
176 | | ||||
177 | auto detailsPageLayout = new QVBoxLayout( detailsFrame ); | ||||
178 | detailsPageLayout->addWidget( certDataLabel ); | ||||
179 | detailsPageLayout->addWidget( certTree ); | ||||
180 | detailsPageLayout->addWidget( m_propertyText ); | ||||
181 | } | ||||
182 | | ||||
183 | void CertificateViewer::updateText( const QModelIndex &index ) | ||||
184 | { | ||||
185 | QString key = m_certificateModel->data( index, CertificateModel::PropertyKeyRole ).toString(); | ||||
186 | if ( key == QLatin1String("Public Key") ) | ||||
187 | m_propertyText->setText( m_certificateModel->data( index, CertificateModel::PublicKeyRole ).toString() ); | ||||
188 | else | ||||
189 | { | ||||
190 | const QString propertyValue = m_certificateModel->data( index, CertificateModel::PropertyValueRole ).toString(); | ||||
191 | QString textToView; | ||||
192 | foreach ( auto c, propertyValue ) | ||||
193 | { | ||||
194 | if ( c == ',' ) | ||||
195 | textToView += '\n'; | ||||
196 | else | ||||
197 | textToView += c; | ||||
198 | } | ||||
199 | m_propertyText->setText( textToView ); | ||||
200 | } | ||||
201 | } | ||||
202 | | ||||
203 | void CertificateViewer::exportCertificate() | ||||
204 | { | ||||
205 | const QString caption = i18n("Where do you want to save this certificate?"); | ||||
206 | const QString path = QFileDialog::getSaveFileName( this, caption, QStringLiteral("Certificate.cer"), i18n("Certificate File (*.cer)") ); | ||||
207 | if ( !path.isEmpty() ) | ||||
208 | { | ||||
209 | QFile targetFile( path ); | ||||
210 | targetFile.open( QIODevice::WriteOnly ); | ||||
211 | if ( targetFile.write( m_certificateInfo->certificateData() ) == -1 ) | ||||
212 | { | ||||
213 | KMessageBox::error( this, i18n("Unable to export certificate!") ); | ||||
214 | } | ||||
215 | targetFile.close(); | ||||
216 | } | ||||
217 | } |