File indexing completed on 2024-04-28 15:51:42
0001 /* 0002 SPDX-FileCopyrightText: 2018 Chinmoy Ranjan Pradhan <chinmoyrp65@gmail.com> 0003 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "certificateviewer.h" 0008 0009 #include "gui/certificatemodel.h" 0010 0011 #include <KColumnResizer> 0012 #include <KLocalizedString> 0013 #include <KMessageBox> 0014 0015 #include <QCryptographicHash> 0016 #include <QDebug> 0017 #include <QDialogButtonBox> 0018 #include <QFileDialog> 0019 #include <QFormLayout> 0020 #include <QGroupBox> 0021 #include <QLabel> 0022 #include <QPushButton> 0023 #include <QTextEdit> 0024 #include <QTreeView> 0025 #include <QVBoxLayout> 0026 0027 #include "DistinguishedNameParser.h" 0028 #include "gui/signatureguiutils.h" 0029 0030 QString splitDNAttributes(const QString &input) 0031 { 0032 auto parsed = DN::parseString(input.toStdString()); 0033 QStringList result; 0034 for (auto &&[key, value] : parsed) { 0035 result.push_back(QString::fromStdString(key) + QLatin1Char('=') + QString::fromStdString(value)); 0036 } 0037 return result.join(QStringLiteral("\n")); 0038 } 0039 0040 CertificateViewer::CertificateViewer(const Okular::CertificateInfo &certInfo, QWidget *parent) 0041 : KPageDialog(parent) 0042 , m_certificateInfo(certInfo) 0043 { 0044 setModal(true); 0045 setMinimumSize(QSize(500, 500)); 0046 setFaceType(Tabbed); 0047 setWindowTitle(i18n("Certificate Viewer")); 0048 setStandardButtons(QDialogButtonBox::Close); 0049 0050 auto exportBtn = new QPushButton(i18n("Export...")); 0051 connect(exportBtn, &QPushButton::clicked, this, &CertificateViewer::exportCertificate); 0052 addActionButton(exportBtn); 0053 0054 // General tab 0055 auto generalPage = new QFrame(this); 0056 addPage(generalPage, i18n("General")); 0057 0058 auto issuerBox = new QGroupBox(i18n("Issued By"), generalPage); 0059 auto issuerFormLayout = new QFormLayout(issuerBox); 0060 issuerFormLayout->setLabelAlignment(Qt::AlignLeft); 0061 issuerFormLayout->addRow(i18n("Common Name(CN)"), new QLabel(m_certificateInfo.issuerInfo(Okular::CertificateInfo::CommonName, Okular::CertificateInfo::EmptyString::TranslatedNotAvailable))); 0062 issuerFormLayout->addRow(i18n("EMail"), new QLabel(m_certificateInfo.issuerInfo(Okular::CertificateInfo::EmailAddress, Okular::CertificateInfo::EmptyString::TranslatedNotAvailable))); 0063 issuerFormLayout->addRow(i18n("Organization(O)"), new QLabel(m_certificateInfo.issuerInfo(Okular::CertificateInfo::Organization, Okular::CertificateInfo::EmptyString::TranslatedNotAvailable))); 0064 0065 auto subjectBox = new QGroupBox(i18n("Issued To"), generalPage); 0066 auto subjectFormLayout = new QFormLayout(subjectBox); 0067 subjectFormLayout->setLabelAlignment(Qt::AlignLeft); 0068 subjectFormLayout->addRow(i18n("Common Name(CN)"), new QLabel(m_certificateInfo.subjectInfo(Okular::CertificateInfo::CommonName, Okular::CertificateInfo::EmptyString::TranslatedNotAvailable))); 0069 subjectFormLayout->addRow(i18n("EMail"), new QLabel(m_certificateInfo.subjectInfo(Okular::CertificateInfo::EmailAddress, Okular::CertificateInfo::EmptyString::TranslatedNotAvailable))); 0070 subjectFormLayout->addRow(i18n("Organization(O)"), new QLabel(m_certificateInfo.subjectInfo(Okular::CertificateInfo::Organization, Okular::CertificateInfo::EmptyString::TranslatedNotAvailable))); 0071 0072 auto validityBox = new QGroupBox(i18n("Validity"), generalPage); 0073 auto validityFormLayout = new QFormLayout(validityBox); 0074 validityFormLayout->setLabelAlignment(Qt::AlignLeft); 0075 validityFormLayout->addRow(i18n("Issued On"), new QLabel(QLocale().toString(m_certificateInfo.validityStart(), QLocale::LongFormat))); 0076 validityFormLayout->addRow(i18n("Expires On"), new QLabel(QLocale().toString(m_certificateInfo.validityEnd(), QLocale::LongFormat))); 0077 0078 auto fingerprintBox = new QGroupBox(i18n("Fingerprints"), generalPage); 0079 auto fingerprintFormLayout = new QFormLayout(fingerprintBox); 0080 fingerprintFormLayout->setLabelAlignment(Qt::AlignLeft); 0081 QByteArray certData = m_certificateInfo.certificateData(); 0082 auto sha1Label = new QLabel(QString::fromLatin1(QCryptographicHash::hash(certData, QCryptographicHash::Sha1).toHex(' '))); 0083 sha1Label->setWordWrap(true); 0084 auto sha256Label = new QLabel(QString::fromLatin1(QCryptographicHash::hash(certData, QCryptographicHash::Sha256).toHex(' '))); 0085 sha256Label->setWordWrap(true); 0086 fingerprintFormLayout->addRow(i18n("SHA-1 Fingerprint"), sha1Label); 0087 fingerprintFormLayout->addRow(i18n("SHA-256 Fingerprint"), sha256Label); 0088 0089 auto generalPageLayout = new QVBoxLayout(generalPage); 0090 generalPageLayout->addWidget(issuerBox); 0091 generalPageLayout->addWidget(subjectBox); 0092 generalPageLayout->addWidget(validityBox); 0093 generalPageLayout->addWidget(fingerprintBox); 0094 generalPageLayout->addStretch(); 0095 0096 // force column 1 to have same width 0097 auto resizer = new KColumnResizer(this); 0098 resizer->addWidgetsFromLayout(issuerBox->layout(), 0); 0099 resizer->addWidgetsFromLayout(subjectBox->layout(), 0); 0100 resizer->addWidgetsFromLayout(validityBox->layout(), 0); 0101 resizer->addWidgetsFromLayout(fingerprintBox->layout(), 0); 0102 0103 // Details tab 0104 auto detailsFrame = new QFrame(this); 0105 addPage(detailsFrame, i18n("Details")); 0106 auto certDataLabel = new QLabel(i18n("Certificate Data:")); 0107 auto certTree = new QTreeView(this); 0108 certTree->setIndentation(0); 0109 m_certificateModel = new CertificateModel(m_certificateInfo, this); 0110 certTree->setModel(m_certificateModel); 0111 connect(certTree->selectionModel(), &QItemSelectionModel::currentChanged, this, &CertificateViewer::updateText); 0112 m_propertyText = new QTextEdit(this); 0113 m_propertyText->setReadOnly(true); 0114 0115 auto detailsPageLayout = new QVBoxLayout(detailsFrame); 0116 detailsPageLayout->addWidget(certDataLabel); 0117 detailsPageLayout->addWidget(certTree); 0118 detailsPageLayout->addWidget(m_propertyText); 0119 } 0120 0121 void CertificateViewer::updateText(const QModelIndex &index) 0122 { 0123 QString text; 0124 const CertificateModel::Property key = m_certificateModel->data(index, CertificateModel::PropertyKeyRole).value<CertificateModel::Property>(); 0125 switch (key) { 0126 case CertificateModel::SerialNumber: 0127 case CertificateModel::Version: 0128 case CertificateModel::IssuedOn: 0129 case CertificateModel::ExpiresOn: 0130 text = m_certificateModel->data(index, CertificateModel::PropertyVisibleValueRole).toString(); 0131 break; 0132 case CertificateModel::Issuer: 0133 case CertificateModel::Subject: 0134 text = splitDNAttributes(m_certificateModel->data(index, CertificateModel::PropertyVisibleValueRole).toString()); 0135 break; 0136 case CertificateModel::PublicKey: 0137 text = QString::fromLatin1(m_certificateInfo.publicKey().toHex(' ')); 0138 break; 0139 case CertificateModel::KeyUsage: 0140 text = SignatureGuiUtils::getReadableKeyUsageNewLineSeparated(m_certificateInfo.keyUsageExtensions()); 0141 break; 0142 case CertificateModel::IssuerName: 0143 case CertificateModel::IssuerEmail: 0144 case CertificateModel::IssuerOrganization: 0145 case CertificateModel::SubjectName: 0146 case CertificateModel::SubjectEmail: 0147 case CertificateModel::SubjectOrganization: 0148 case CertificateModel::Sha1: 0149 case CertificateModel::Sha256: 0150 Q_ASSERT(false); 0151 qWarning() << "Unused"; 0152 } 0153 m_propertyText->setText(text); 0154 } 0155 0156 void CertificateViewer::exportCertificate() 0157 { 0158 const QString caption = i18n("Where do you want to save this certificate?"); 0159 const QString path = QFileDialog::getSaveFileName(this, caption, QStringLiteral("Certificate.cer"), i18n("Certificate File (*.cer)")); 0160 if (!path.isEmpty()) { 0161 if (!m_certificateModel->exportCertificateTo(path)) { 0162 KMessageBox::error(this, i18n("Could not export the certificate")); 0163 } 0164 } 0165 }