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

KIO

  • sources
  • kde-4.14
  • kdelibs
  • 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 
34 enum Columns {
35  OrgCnColumn = 0,
36  OrgUnitColumn,
37  HiddenSortColumn
38 };
39 
40 
41 static 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 
59 class CaCertificateItem : public QTreeWidgetItem
60 {
61 public:
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 
103 CaCertificatesPage::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 
124 void 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 
152 void 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 
162 void 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 
188 void CaCertificatesPage::defaults()
189 {
190  //### is that all?
191  load();
192  emit changed(false);
193 }
194 
195 // private slot
196 void 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
222 void 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
238 void CaCertificatesPage::disableSelectionClicked()
239 {
240  enableDisableSelectionClicked(false);
241 }
242 
243 // private slot
244 void CaCertificatesPage::enableSelectionClicked()
245 {
246  enableDisableSelectionClicked(true);
247 }
248 
249 void 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
268 void 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
291 void CaCertificatesPage::addCertificateClicked()
292 {
293  QStringList certFiles
294  = KFileDialog::getOpenFileNames(KUrl(), QLatin1String("application/x-x509-ca-cert"),
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
329 void 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 
346 static 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 
357 bool 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"
i18n
QString i18n(const char *text)
KSslCaCertificate::certHash
const QByteArray certHash
QWidget
CaCertificatesPage::changed
void changed(bool state)
kdebug.h
_allKsslCaCertificates
QList< KSslCaCertificate > _allKsslCaCertificates(KSslCertificateManager *cm)
ksslcertificatemanager_p.h
QTreeWidgetItem::child
QTreeWidgetItem * child(int index) const
_setAllKsslCaCertificates
void _setAllKsslCaCertificates(KSslCertificateManager *cm, const QList< KSslCaCertificate > &certsIn)
kfiledialog.h
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
KSslCaCertificate::UserStore
KSslCertificateManager::self
static KSslCertificateManager * self()
KSslCaCertificate::cert
const QSslCertificate cert
KSslCaCertificate::isBlacklisted
bool isBlacklisted
QTreeWidgetItem::setData
virtual void setData(int column, int role, const QVariant &value)
DisplayCertDialog
Definition: displaycertdialog_p.h:26
QSet::insert
const_iterator insert(const T &value)
QTreeWidgetItem::data
virtual QVariant data(int column, int role) const
kDebug
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
ksslcertificatemanager.h
QFile
KUrl
QTreeWidgetItem::setFlags
void setFlags(QFlags< Qt::ItemFlag > flags)
QWidget::showEvent
virtual void showEvent(QShowEvent *event)
CaCertificatesPage::save
void save()
Definition: cacertificatespage.cpp:162
QList::count
int count(const T &value) const
KSslCaCertificate::store
const Store store
QVariant::toInt
int toInt(bool *ok) const
QShowEvent
QString::isEmpty
bool isEmpty() const
cacertificatespage.h
KSslCaCertificate
KSslCaCertificate::SystemStore
QString
QList
QStringList
QString::toLower
QString toLower() const
CaCertificatesPage::load
void load()
Definition: cacertificatespage.cpp:124
QSslCertificate::fromDevice
QList< QSslCertificate > fromDevice(QIODevice *device, QSsl::EncodingFormat format)
QSet::contains
bool contains(const T &value) const
findImmediateChild
static QTreeWidgetItem * findImmediateChild(QTreeWidgetItem *parent, const QString &issuerText)
Definition: cacertificatespage.cpp:346
QTreeWidgetItem::setExpanded
void setExpanded(bool expand)
CaCertificatesPage::defaults
void defaults()
Definition: cacertificatespage.cpp:188
QTreeWidgetItem::flags
Qt::ItemFlags flags() const
QSet::remove
bool remove(const T &value)
QTreeWidgetItem
OrgCnColumn
Definition: cacertificatespage.cpp:35
QLatin1String
QSslCertificate::issuerInfo
QString issuerInfo(SubjectInfo subject) const
QTreeWidgetItem::setText
void setText(int column, const QString &text)
Columns
Columns
Definition: cacertificatespage.cpp:34
OrgUnitColumn
Definition: cacertificatespage.cpp:36
CaCertificatesPage::CaCertificatesPage
CaCertificatesPage(QWidget *parent)
Definition: cacertificatespage.cpp:103
KSslCaCertificate::Store
Store
CaCertificatesPage::showEvent
void showEvent(QShowEvent *event)
Definition: cacertificatespage.cpp:152
HiddenSortColumn
Definition: cacertificatespage.cpp:37
displaycertdialog_p.h
QSet::clear
void clear()
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject::parent
QObject * parent() const
QTreeWidgetItem::childCount
int childCount() const
nonemptyIssuer
static QString nonemptyIssuer(const QSslCertificate &cert)
Definition: cacertificatespage.cpp:41
QTreeWidgetItem::text
QString text(int column) const
QVariant
QSslCertificate
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:24:52 by doxygen 1.8.7 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 API Reference

Skip menu "kdelibs 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

Search



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