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

KIO

  • sources
  • kde-4.12
  • 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  certs += QSslCertificate::fromPath(certFile, QSsl::Pem);
302  if (prevCertCount == certs.count()) {
303  certs += QSslCertificate::fromPath(certFile, QSsl::Der);
304  }
305  if (prevCertCount == certs.count()) {
306  kDebug(7029) << "failed to load certificate file" << certFile;
307  }
308  }
309 
310  bool didAddCertificates = false;
311  foreach (const QSslCertificate &cert, certs) {
312  KSslCaCertificate caCert(cert, KSslCaCertificate::UserStore, false);
313  if (!addCertificateItem(caCert)) {
314  // ### tell the user?
315  } else {
316  didAddCertificates = true;
317  }
318  }
319  if (didAddCertificates) {
320  emit changed(true);
321  }
322 }
323 
324 // private slot
325 void CaCertificatesPage::itemChanged(QTreeWidgetItem *item, int column)
326 {
327  Q_UNUSED(item)
328  Q_UNUSED(column)
329 
330  if (m_blockItemChanged) {
331  return;
332  }
333  kDebug(7029);
334  // we could try to emit changed(false) if everything was changed back to status quo
335 
336  // a click on the checkbox of an unselected item first invokes itemSelectionChanged(),
337  // then itemChanged(). we'll have to rerun the checks in itemSelectionChanged().
338  itemSelectionChanged();
339  emit changed(true);
340 }
341 
342 static QTreeWidgetItem *findImmediateChild(QTreeWidgetItem *parent, const QString &issuerText)
343 {
344  for (int i = 0; i < parent->childCount(); i ++) {
345  QTreeWidgetItem *candidate = parent->child(i);
346  if (candidate->text(OrgCnColumn) == issuerText) {
347  return candidate;
348  }
349  }
350  return 0;
351 }
352 
353 bool CaCertificatesPage::addCertificateItem(const KSslCaCertificate &caCert)
354 {
355  if (m_knownCertificates.contains(caCert.certHash)) {
356  kDebug(7029) << "CaCertificatesPage::addCertificateItem(): refusing duplicate";
357  return false;
358  }
359  const bool prevBlockItemChanged = m_blockItemChanged;
360  m_blockItemChanged = true;
361  QTreeWidgetItem *grandParent = caCert.store == KSslCaCertificate::SystemStore ?
362  m_systemCertificatesParent : m_userCertificatesParent;
363  const QString issuerOrganization = nonemptyIssuer(caCert.cert);
364 
365  QTreeWidgetItem *parent = findImmediateChild(grandParent, issuerOrganization);
366  if (!parent) {
367  parent = new QTreeWidgetItem(grandParent);
368  parent->setText(OrgCnColumn, issuerOrganization);
369  parent->setText(HiddenSortColumn, issuerOrganization.toLower());
370  parent->setExpanded(true);
371  parent->setFlags(parent->flags() & ~Qt::ItemIsSelectable);
372  }
373 
374  (void) new CaCertificateItem(parent, caCert.cert, !caCert.isBlacklisted);
375  m_knownCertificates.insert(caCert.certHash);
376  m_blockItemChanged = prevBlockItemChanged;
377  return true;
378 }
379 
380 #include "cacertificatespage.moc"
QVariant
i18n
QString i18n(const char *text)
KSslCaCertificate::certHash
const QByteArray certHash
CaCertificatesPage::changed
void changed(bool state)
kdebug.h
_allKsslCaCertificates
QList< KSslCaCertificate > _allKsslCaCertificates(KSslCertificateManager *cm)
ksslcertificatemanager_p.h
_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
QWidget
KSslCaCertificate::UserStore
KSslCertificateManager::self
static KSslCertificateManager * self()
KSslCaCertificate::cert
const QSslCertificate cert
KSslCaCertificate::isBlacklisted
bool isBlacklisted
DisplayCertDialog
Definition: displaycertdialog_p.h:26
QString
kDebug
static QDebug kDebug(bool cond, int area=KDE_DEFAULT_DEBUG_AREA)
ksslcertificatemanager.h
KUrl
CaCertificatesPage::save
void save()
Definition: cacertificatespage.cpp:162
KSslCaCertificate::store
const Store store
QStringList
cacertificatespage.h
KSslCaCertificate
KSslCaCertificate::SystemStore
CaCertificatesPage::load
void load()
Definition: cacertificatespage.cpp:124
findImmediateChild
static QTreeWidgetItem * findImmediateChild(QTreeWidgetItem *parent, const QString &issuerText)
Definition: cacertificatespage.cpp:342
CaCertificatesPage::defaults
void defaults()
Definition: cacertificatespage.cpp:188
OrgCnColumn
Definition: cacertificatespage.cpp:35
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
nonemptyIssuer
static QString nonemptyIssuer(const QSslCertificate &cert)
Definition: cacertificatespage.cpp:41
QList
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:50:01 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
  • kjsembed
  •   WTF
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Nepomuk-Core
  • 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