• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.14.38 API Reference
  • KDE Home
  • Contact Us
 

KIO

  • kio
  • kssl
  • kcm
cacertificatespage.cpp
Go to the documentation of this file.
1/* This file is part of the KDE project
2 Copyright (C) 2010 Andreas Hartmetz <ahartmetz@gmail.com>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19
20#include "cacertificatespage.h"
21#include "displaycertdialog_p.h"
22
23#include <ksslcertificatemanager.h>
24#include <ksslcertificatemanager_p.h>
25
26#include <kdebug.h>
27#include <kfiledialog.h>
28
29#include <QList>
30#include <QSslCertificate>
31#include <QtGui/QTreeWidgetItem>
32#include <QtGui/QStandardItemModel>
33
34enum Columns {
35 OrgCnColumn = 0,
36 OrgUnitColumn,
37 HiddenSortColumn
38};
39
40
41static QString nonemptyIssuer(const QSslCertificate &cert)
42{
43 QString issuerText;
44 static const QSslCertificate::SubjectInfo fields[3] = {
45 QSslCertificate::Organization,
46 QSslCertificate::CommonName,
47 QSslCertificate::OrganizationalUnitName
48 };
49 for (int i = 0; i < 3; i++) {
50 issuerText = cert.issuerInfo(fields[i]);
51 if (!issuerText.isEmpty()) {
52 return issuerText;
53 }
54 }
55 return issuerText;
56}
57
58
59class CaCertificateItem : public QTreeWidgetItem
60{
61public:
62 CaCertificateItem(QTreeWidgetItem *parent, const QSslCertificate &cert, bool isEnabled)
63 : QTreeWidgetItem(parent, m_type),
64 m_cert(cert)
65 {
66 setEnabled(isEnabled);
67 }
68
69 QVariant data(int column, int role) const
70 {
71 switch (role) {
72 case Qt::DisplayRole:
73 switch (column) {
74 case OrgCnColumn:
75 case HiddenSortColumn: {
76 QString subjectText = m_cert.issuerInfo(QSslCertificate::CommonName);
77 if (column == HiddenSortColumn) {
78 return subjectText.toLower();
79 }
80 return subjectText; }
81 case OrgUnitColumn:
82 return m_cert.issuerInfo(QSslCertificate::OrganizationalUnitName);
83 }
84 }
85
86 return QTreeWidgetItem::data(column, role);
87 }
88
89 bool isEnabled() const
90 {
91 return data(OrgCnColumn, Qt::CheckStateRole).toInt() == Qt::Checked;
92 }
93
94 void setEnabled(bool enabled)
95 {
96 setData(OrgCnColumn, Qt::CheckStateRole, enabled ? Qt::Checked : Qt::Unchecked);
97 }
98
99 static const int m_type = QTreeWidgetItem::UserType;
100 QSslCertificate m_cert;
101};
102
103CaCertificatesPage::CaCertificatesPage(QWidget *parent)
104 : QWidget(parent),
105 m_firstShowEvent(true),
106 m_blockItemChanged(false)
107{
108 m_ui.setupUi(this);
109 connect(m_ui.displaySelection, SIGNAL(clicked()), SLOT(displaySelectionClicked()));
110 connect(m_ui.disableSelection, SIGNAL(clicked()), SLOT(disableSelectionClicked()));
111 connect(m_ui.enableSelection, SIGNAL(clicked()), SLOT(enableSelectionClicked()));
112 connect(m_ui.removeSelection, SIGNAL(clicked()), SLOT(removeSelectionClicked()));
113 connect(m_ui.add, SIGNAL(clicked()), SLOT(addCertificateClicked()));
114 connect(m_ui.treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
115 SLOT(itemChanged(QTreeWidgetItem*,int)));
116 connect(m_ui.treeWidget, SIGNAL(itemSelectionChanged()),
117 SLOT(itemSelectionChanged()));
118
119 m_ui.treeWidget->setColumnCount(HiddenSortColumn + 1);
120 m_ui.treeWidget->setColumnHidden(HiddenSortColumn, true);
121}
122
123
124void CaCertificatesPage::load()
125{
126 m_ui.treeWidget->clear();
127 m_ui.treeWidget->sortByColumn(-1); // disable during mass insertion
128 m_knownCertificates.clear();
129
130 m_systemCertificatesParent = new QTreeWidgetItem(m_ui.treeWidget);
131 m_systemCertificatesParent->setText(0, i18n("System certificates"));
132 // make system certificates come first in the sorted view
133 m_systemCertificatesParent->setText(HiddenSortColumn, QLatin1String("a"));
134 m_systemCertificatesParent->setExpanded(true);
135 m_systemCertificatesParent->setFlags(m_systemCertificatesParent->flags() & ~Qt::ItemIsSelectable);
136
137 m_userCertificatesParent = new QTreeWidgetItem(m_ui.treeWidget);
138 m_userCertificatesParent->setText(0, i18n("User-added certificates"));
139 m_userCertificatesParent->setText(HiddenSortColumn, QLatin1String("b"));
140 m_userCertificatesParent->setExpanded(true);
141 m_userCertificatesParent->setFlags(m_userCertificatesParent->flags() & ~Qt::ItemIsSelectable);
142
143 QList<KSslCaCertificate> caCerts = _allKsslCaCertificates(KSslCertificateManager::self());
144 kDebug(7029) << "# certs:" << caCerts.count();
145 foreach (const KSslCaCertificate &caCert, caCerts) {
146 addCertificateItem(caCert);
147 }
148
149 m_ui.treeWidget->sortByColumn(HiddenSortColumn, Qt::AscendingOrder);
150}
151
152void CaCertificatesPage::showEvent(QShowEvent *event)
153{
154 if (m_firstShowEvent) {
155 // TODO use QTextMetrics
156 m_ui.treeWidget->setColumnWidth(OrgCnColumn, 420);
157 m_firstShowEvent = false;
158 }
159 QWidget::showEvent(event);
160}
161
162void CaCertificatesPage::save()
163{
164 QList<KSslCaCertificate> newState;
165
166 KSslCaCertificate::Store store = KSslCaCertificate::SystemStore;
167 QTreeWidgetItem *grandParent = m_systemCertificatesParent;
168
169 for (int i = 0; i < 2; i++) {
170 for (int j = 0; j < grandParent->childCount(); j++) {
171
172 QTreeWidgetItem *parentItem = grandParent->child(j);
173 for (int k = 0; k < parentItem->childCount(); k++) {
174 CaCertificateItem *item = static_cast<CaCertificateItem *>(parentItem->child(k));
175 newState += KSslCaCertificate(item->m_cert, store, !item->isEnabled());
176 }
177 }
178 store = KSslCaCertificate::UserStore;
179 grandParent = m_userCertificatesParent;
180 }
181
182 kDebug(7029) << "# certs:" << newState.count();
183 _setAllKsslCaCertificates(KSslCertificateManager::self(), newState);
184 emit changed(false);
185}
186
187
188void CaCertificatesPage::defaults()
189{
190 //### is that all?
191 load();
192 emit changed(false);
193}
194
195// private slot
196void CaCertificatesPage::itemSelectionChanged()
197{
198 kDebug(7029) << m_ui.treeWidget->selectionModel()->hasSelection();
199 int numRemovable = 0;
200 int numEnabled = 0;
201 int numDisplayable = 0;
202 foreach(const QTreeWidgetItem *twItem, m_ui.treeWidget->selectedItems()) {
203 const CaCertificateItem *item = dynamic_cast<const CaCertificateItem *>(twItem);
204 Q_ASSERT(item);
205 if (item) {
206 numDisplayable++;
207 if (item->parent()->parent() == m_userCertificatesParent) {
208 numRemovable++;
209 }
210 if (item->isEnabled()) {
211 numEnabled++;
212 }
213 }
214 }
215 m_ui.displaySelection->setEnabled(numDisplayable);
216 m_ui.removeSelection->setEnabled(numRemovable);
217 m_ui.disableSelection->setEnabled(numEnabled);
218 m_ui.enableSelection->setEnabled(numDisplayable > numEnabled); // the rest is disabled
219}
220
221// private slot
222void CaCertificatesPage::displaySelectionClicked()
223{
224 QList<QSslCertificate> certs;
225 foreach(const QTreeWidgetItem *twItem, m_ui.treeWidget->selectedItems()) {
226 const CaCertificateItem *item = dynamic_cast<const CaCertificateItem *>(twItem);
227 Q_ASSERT(item);
228 if (item) {
229 certs += item->m_cert;
230 }
231 }
232 DisplayCertDialog dc(this);
233 dc.setCertificates(certs);
234 dc.exec();
235}
236
237// private slot
238void CaCertificatesPage::disableSelectionClicked()
239{
240 enableDisableSelectionClicked(false);
241}
242
243// private slot
244void CaCertificatesPage::enableSelectionClicked()
245{
246 enableDisableSelectionClicked(true);
247}
248
249void CaCertificatesPage::enableDisableSelectionClicked(bool isEnable)
250{
251 const bool prevBlockItemChanged = m_blockItemChanged;
252 m_blockItemChanged = true;
253 foreach(QTreeWidgetItem *twItem, m_ui.treeWidget->selectedItems()) {
254 CaCertificateItem *item = dynamic_cast<CaCertificateItem *>(twItem);
255 Q_ASSERT(item);
256 if (item) {
257 item->setEnabled(isEnable);
258 }
259 }
260 emit changed(true);
261 m_blockItemChanged = prevBlockItemChanged;
262 // now make sure that the buttons are enabled as appropriate
263 itemSelectionChanged();
264}
265
266
267// private slot
268void CaCertificatesPage::removeSelectionClicked()
269{
270 bool didRemove = false;
271 foreach(QTreeWidgetItem *twItem, m_ui.treeWidget->selectedItems()) {
272 const CaCertificateItem *item = dynamic_cast<const CaCertificateItem *>(twItem);
273 Q_ASSERT(item);
274 if (!item || item->parent()->parent() != m_userCertificatesParent) {
275 continue;
276 }
277 QTreeWidgetItem *parent = item->parent();
278 m_knownCertificates.remove(item->m_cert.digest().toHex());
279 delete item;
280 didRemove = true;
281 if (parent->childCount() == 0) {
282 delete parent;
283 }
284 }
285 if (didRemove) {
286 emit changed(true);
287 }
288}
289
290// private slot
291void CaCertificatesPage::addCertificateClicked()
292{
293 QStringList certFiles
294 = KFileDialog::getOpenFileNames(KUrl(), QLatin1String("*.pem *.cert *.crt *.der"),
295 this, i18n("Pick Certificates"));
296
297 QList<QSslCertificate> certs;
298 foreach (const QString &certFile, certFiles) {
299 // trying both formats is easiest to program and most user-friendly if somewhat sloppy
300 const int prevCertCount = certs.count();
301 QFile file (certFile);
302 if (file.open(QIODevice::ReadOnly)) {
303 certs += QSslCertificate::fromDevice(&file, QSsl::Pem);
304 if (prevCertCount == certs.count()) {
305 file.reset();
306 certs += QSslCertificate::fromDevice(&file, QSsl::Der);
307 }
308 }
309 if (prevCertCount == certs.count()) {
310 kDebug(7029) << "failed to load certificate file" << certFile;
311 }
312 }
313
314 bool didAddCertificates = false;
315 foreach (const QSslCertificate &cert, certs) {
316 KSslCaCertificate caCert(cert, KSslCaCertificate::UserStore, false);
317 if (!addCertificateItem(caCert)) {
318 // ### tell the user?
319 } else {
320 didAddCertificates = true;
321 }
322 }
323 if (didAddCertificates) {
324 emit changed(true);
325 }
326}
327
328// private slot
329void CaCertificatesPage::itemChanged(QTreeWidgetItem *item, int column)
330{
331 Q_UNUSED(item)
332 Q_UNUSED(column)
333
334 if (m_blockItemChanged) {
335 return;
336 }
337 kDebug(7029);
338 // we could try to emit changed(false) if everything was changed back to status quo
339
340 // a click on the checkbox of an unselected item first invokes itemSelectionChanged(),
341 // then itemChanged(). we'll have to rerun the checks in itemSelectionChanged().
342 itemSelectionChanged();
343 emit changed(true);
344}
345
346static QTreeWidgetItem *findImmediateChild(QTreeWidgetItem *parent, const QString &issuerText)
347{
348 for (int i = 0; i < parent->childCount(); i ++) {
349 QTreeWidgetItem *candidate = parent->child(i);
350 if (candidate->text(OrgCnColumn) == issuerText) {
351 return candidate;
352 }
353 }
354 return 0;
355}
356
357bool CaCertificatesPage::addCertificateItem(const KSslCaCertificate &caCert)
358{
359 if (m_knownCertificates.contains(caCert.certHash)) {
360 kDebug(7029) << "CaCertificatesPage::addCertificateItem(): refusing duplicate";
361 return false;
362 }
363 const bool prevBlockItemChanged = m_blockItemChanged;
364 m_blockItemChanged = true;
365 QTreeWidgetItem *grandParent = caCert.store == KSslCaCertificate::SystemStore ?
366 m_systemCertificatesParent : m_userCertificatesParent;
367 const QString issuerOrganization = nonemptyIssuer(caCert.cert);
368
369 QTreeWidgetItem *parent = findImmediateChild(grandParent, issuerOrganization);
370 if (!parent) {
371 parent = new QTreeWidgetItem(grandParent);
372 parent->setText(OrgCnColumn, issuerOrganization);
373 parent->setText(HiddenSortColumn, issuerOrganization.toLower());
374 parent->setExpanded(true);
375 parent->setFlags(parent->flags() & ~Qt::ItemIsSelectable);
376 }
377
378 (void) new CaCertificateItem(parent, caCert.cert, !caCert.isBlacklisted);
379 m_knownCertificates.insert(caCert.certHash);
380 m_blockItemChanged = prevBlockItemChanged;
381 return true;
382}
383
384#include "cacertificatespage.moc"
Columns
Columns
Definition: cacertificatespage.cpp:34
HiddenSortColumn
@ HiddenSortColumn
Definition: cacertificatespage.cpp:37
OrgUnitColumn
@ OrgUnitColumn
Definition: cacertificatespage.cpp:36
OrgCnColumn
@ OrgCnColumn
Definition: cacertificatespage.cpp:35
findImmediateChild
static QTreeWidgetItem * findImmediateChild(QTreeWidgetItem *parent, const QString &issuerText)
Definition: cacertificatespage.cpp:346
nonemptyIssuer
static QString nonemptyIssuer(const QSslCertificate &cert)
Definition: cacertificatespage.cpp:41
cacertificatespage.h
CaCertificatesPage::CaCertificatesPage
CaCertificatesPage(QWidget *parent)
Definition: cacertificatespage.cpp:103
CaCertificatesPage::defaults
void defaults()
Definition: cacertificatespage.cpp:188
CaCertificatesPage::load
void load()
Definition: cacertificatespage.cpp:124
CaCertificatesPage::showEvent
void showEvent(QShowEvent *event)
Definition: cacertificatespage.cpp:152
CaCertificatesPage::save
void save()
Definition: cacertificatespage.cpp:162
CaCertificatesPage::changed
void changed(bool state)
DisplayCertDialog
Definition: displaycertdialog_p.h:27
KFileDialog::getOpenFileNames
static QStringList getOpenFileNames(const KUrl &startDir=KUrl(), const QString &filter=QString(), QWidget *parent=0, const QString &caption=QString())
Creates a modal file dialog and returns the selected filenames or an empty list if none was chosen.
Definition: kfiledialog.cpp:518
KSslCertificateManager::self
static KSslCertificateManager * self()
KUrl
QList
QWidget
displaycertdialog_p.h
kDebug
#define kDebug
kdebug.h
kfiledialog.h
i18n
QString i18n(const char *text)
_allKsslCaCertificates
QList< KSslCaCertificate > _allKsslCaCertificates(KSslCertificateManager *cm)
_setAllKsslCaCertificates
void _setAllKsslCaCertificates(KSslCertificateManager *cm, const QList< KSslCaCertificate > &certsIn)
ksslcertificatemanager.h
ksslcertificatemanager_p.h
KSslCaCertificate
KSslCaCertificate::certHash
const QByteArray certHash
KSslCaCertificate::store
const Store store
KSslCaCertificate::cert
const QSslCertificate cert
KSslCaCertificate::Store
Store
KSslCaCertificate::SystemStore
SystemStore
KSslCaCertificate::UserStore
UserStore
KSslCaCertificate::isBlacklisted
bool isBlacklisted
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Feb 20 2023 00:00:00 by doxygen 1.9.6 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KIO

Skip menu "KIO"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdelibs-4.14.38 API Reference

Skip menu "kdelibs-4.14.38 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal