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

KIO

cacertificatespage.cpp
Go to the documentation of this file.
00001 /*  This file is part of the KDE project
00002     Copyright (C) 2010 Andreas Hartmetz <ahartmetz@gmail.com>
00003 
00004     This library is free software; you can redistribute it and/or
00005     modify it under the terms of the GNU Library General Public
00006     License as published by the Free Software Foundation; either
00007     version 2 of the License, or (at your option) any later version.
00008 
00009     This program is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012     GNU General Public License for more details.
00013 
00014     You should have received a copy of the GNU General Public License
00015     along with this program; if not, write to the Free Software
00016     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017     02110-1301, USA.
00018 */
00019 
00020 #include "cacertificatespage.h"
00021 #include "displaycertdialog_p.h"
00022 
00023 #include <ksslcertificatemanager.h>
00024 #include <ksslcertificatemanager_p.h>
00025 
00026 #include <kdebug.h>
00027 #include <kfiledialog.h>
00028 
00029 #include <QList>
00030 #include <QSslCertificate>
00031 #include <QtGui/QTreeWidgetItem>
00032 #include <QtGui/QStandardItemModel>
00033 
00034 enum Columns {
00035     OrgCnColumn = 0,
00036     OrgUnitColumn,
00037     HiddenSortColumn
00038 };
00039 
00040 
00041 static QString nonemptyIssuer(const QSslCertificate &cert)
00042 {
00043     QString issuerText;
00044     static const QSslCertificate::SubjectInfo fields[3] = {
00045                      QSslCertificate::Organization,
00046                      QSslCertificate::CommonName,
00047                      QSslCertificate::OrganizationalUnitName
00048     };
00049     for (int i = 0; i < 3; i++) {
00050         issuerText = cert.issuerInfo(fields[i]);
00051         if (!issuerText.isEmpty()) {
00052             return issuerText;
00053         }
00054     }
00055     return issuerText;
00056 }
00057 
00058 
00059 class CaCertificateItem : public QTreeWidgetItem
00060 {
00061 public:
00062     CaCertificateItem(QTreeWidgetItem *parent, const QSslCertificate &cert, bool isEnabled)
00063      : QTreeWidgetItem(parent, m_type),
00064        m_cert(cert)
00065     {
00066        setEnabled(isEnabled);
00067     }
00068 
00069     QVariant data(int column, int role) const
00070     {
00071         switch (role) {
00072         case Qt::DisplayRole:
00073             switch (column) {
00074             case OrgCnColumn:
00075             case HiddenSortColumn: {
00076                 QString subjectText = m_cert.issuerInfo(QSslCertificate::CommonName);
00077                 if (column == HiddenSortColumn) {
00078                     return subjectText.toLower();
00079                 }
00080                 return subjectText; }
00081             case OrgUnitColumn:
00082                 return m_cert.issuerInfo(QSslCertificate::OrganizationalUnitName);
00083             }
00084         }
00085 
00086         return QTreeWidgetItem::data(column, role);
00087     }
00088 
00089     bool isEnabled() const
00090     {
00091         return data(OrgCnColumn, Qt::CheckStateRole).toInt() == Qt::Checked;
00092     }
00093 
00094     void setEnabled(bool enabled)
00095     {
00096         setData(OrgCnColumn, Qt::CheckStateRole, enabled ? Qt::Checked : Qt::Unchecked);
00097     }
00098 
00099     static const int m_type = QTreeWidgetItem::UserType;
00100     QSslCertificate m_cert;
00101 };
00102 
00103 CaCertificatesPage::CaCertificatesPage(QWidget *parent)
00104  : QWidget(parent),
00105    m_firstShowEvent(true),
00106    m_blockItemChanged(false)
00107 {
00108     m_ui.setupUi(this);
00109     connect(m_ui.displaySelection, SIGNAL(clicked()), SLOT(displaySelectionClicked()));
00110     connect(m_ui.disableSelection, SIGNAL(clicked()), SLOT(disableSelectionClicked()));
00111     connect(m_ui.enableSelection, SIGNAL(clicked()), SLOT(enableSelectionClicked()));
00112     connect(m_ui.removeSelection, SIGNAL(clicked()), SLOT(removeSelectionClicked()));
00113     connect(m_ui.add, SIGNAL(clicked()), SLOT(addCertificateClicked()));
00114     connect(m_ui.treeWidget, SIGNAL(itemChanged(QTreeWidgetItem *, int)),
00115             SLOT(itemChanged(QTreeWidgetItem *, int)));
00116     connect(m_ui.treeWidget, SIGNAL(itemSelectionChanged()),
00117             SLOT(itemSelectionChanged()));
00118 
00119     m_ui.treeWidget->setColumnCount(HiddenSortColumn + 1);
00120     m_ui.treeWidget->setColumnHidden(HiddenSortColumn, true);
00121 }
00122 
00123 
00124 void CaCertificatesPage::load()
00125 {
00126     m_ui.treeWidget->clear();
00127     m_ui.treeWidget->sortByColumn(-1);  // disable during mass insertion
00128     m_knownCertificates.clear();
00129 
00130     m_systemCertificatesParent = new QTreeWidgetItem(m_ui.treeWidget);
00131     m_systemCertificatesParent->setText(0, i18n("System certificates"));
00132     // make system certificates come first in the sorted view
00133     m_systemCertificatesParent->setText(HiddenSortColumn, QLatin1String("a"));
00134     m_systemCertificatesParent->setExpanded(true);
00135     m_systemCertificatesParent->setFlags(m_systemCertificatesParent->flags() & ~Qt::ItemIsSelectable);
00136 
00137     m_userCertificatesParent = new QTreeWidgetItem(m_ui.treeWidget);
00138     m_userCertificatesParent->setText(0, i18n("User-added certificates"));
00139     m_userCertificatesParent->setText(HiddenSortColumn, QLatin1String("b"));
00140     m_userCertificatesParent->setExpanded(true);
00141     m_userCertificatesParent->setFlags(m_userCertificatesParent->flags() & ~Qt::ItemIsSelectable);
00142 
00143     QList<KSslCaCertificate> caCerts = _allKsslCaCertificates(KSslCertificateManager::self());
00144     kDebug(7029) << "# certs:" << caCerts.count();
00145     foreach (const KSslCaCertificate &caCert, caCerts) {
00146         addCertificateItem(caCert);
00147     }
00148 
00149     m_ui.treeWidget->sortByColumn(HiddenSortColumn, Qt::AscendingOrder);
00150 }
00151 
00152 void CaCertificatesPage::showEvent(QShowEvent *event)
00153 {
00154     if (m_firstShowEvent) {
00155         // TODO use QTextMetrics
00156         m_ui.treeWidget->setColumnWidth(OrgCnColumn, 420);
00157         m_firstShowEvent = false;
00158     }
00159     QWidget::showEvent(event);
00160 }
00161 
00162 void CaCertificatesPage::save()
00163 {
00164     QList<KSslCaCertificate> newState;
00165 
00166     KSslCaCertificate::Store store = KSslCaCertificate::SystemStore;
00167     QTreeWidgetItem *grandParent = m_systemCertificatesParent;
00168 
00169     for (int i = 0; i < 2; i++) {
00170         for (int j = 0; j < grandParent->childCount(); j++) {
00171 
00172             QTreeWidgetItem *parentItem = grandParent->child(j);
00173             for (int k = 0; k < parentItem->childCount(); k++) {
00174                 CaCertificateItem *item = static_cast<CaCertificateItem *>(parentItem->child(k));
00175                 newState += KSslCaCertificate(item->m_cert, store, !item->isEnabled());
00176             }
00177         }
00178         store = KSslCaCertificate::UserStore;
00179         grandParent = m_userCertificatesParent;
00180     }
00181 
00182     kDebug(7029) << "# certs:" << newState.count();
00183     _setAllKsslCaCertificates(KSslCertificateManager::self(), newState);
00184     emit changed(false);
00185 }
00186 
00187 
00188 void CaCertificatesPage::defaults()
00189 {
00190     //### is that all?
00191     load();
00192     emit changed(false);
00193 }
00194 
00195 // private slot
00196 void CaCertificatesPage::itemSelectionChanged()
00197 {
00198     kDebug(7029) << m_ui.treeWidget->selectionModel()->hasSelection();
00199     int numRemovable = 0;
00200     int numEnabled = 0;
00201     int numDisplayable = 0;
00202     foreach(const QTreeWidgetItem *twItem, m_ui.treeWidget->selectedItems()) {
00203         const CaCertificateItem *item = dynamic_cast<const CaCertificateItem *>(twItem);
00204         Q_ASSERT(item);
00205         if (item) {
00206             numDisplayable++;
00207             if (item->parent()->parent() == m_userCertificatesParent) {
00208                 numRemovable++;
00209             }
00210             if (item->isEnabled()) {
00211                 numEnabled++;
00212             }
00213         }
00214     }
00215     m_ui.displaySelection->setEnabled(numDisplayable);
00216     m_ui.removeSelection->setEnabled(numRemovable);
00217     m_ui.disableSelection->setEnabled(numEnabled);
00218     m_ui.enableSelection->setEnabled(numDisplayable > numEnabled); // the rest is disabled
00219 }
00220 
00221 // private slot
00222 void CaCertificatesPage::displaySelectionClicked()
00223 {
00224     QList<QSslCertificate> certs;
00225     foreach(const QTreeWidgetItem *twItem, m_ui.treeWidget->selectedItems()) {
00226         const CaCertificateItem *item = dynamic_cast<const CaCertificateItem *>(twItem);
00227         Q_ASSERT(item);
00228         if (item) {
00229             certs += item->m_cert;
00230         }
00231     }
00232     DisplayCertDialog dc(this);
00233     dc.setCertificates(certs);
00234     dc.exec();
00235 }
00236 
00237 // private slot
00238 void CaCertificatesPage::disableSelectionClicked()
00239 {
00240     enableDisableSelectionClicked(false);
00241 }
00242 
00243 // private slot
00244 void CaCertificatesPage::enableSelectionClicked()
00245 {
00246     enableDisableSelectionClicked(true);
00247 }
00248 
00249 void CaCertificatesPage::enableDisableSelectionClicked(bool isEnable)
00250 {
00251     const bool prevBlockItemChanged = m_blockItemChanged;
00252     m_blockItemChanged = true;
00253     foreach(QTreeWidgetItem *twItem, m_ui.treeWidget->selectedItems()) {
00254         CaCertificateItem *item = dynamic_cast<CaCertificateItem *>(twItem);
00255         Q_ASSERT(item);
00256         if (item) {
00257             item->setEnabled(isEnable);
00258         }
00259     }
00260     emit changed(true);
00261     m_blockItemChanged = prevBlockItemChanged;
00262     // now make sure that the buttons are enabled as appropriate
00263     itemSelectionChanged();
00264 }
00265 
00266 
00267 // private slot
00268 void CaCertificatesPage::removeSelectionClicked()
00269 {
00270     bool didRemove = false;
00271     foreach(QTreeWidgetItem *twItem, m_ui.treeWidget->selectedItems()) {
00272         const CaCertificateItem *item = dynamic_cast<const CaCertificateItem *>(twItem);
00273         Q_ASSERT(item);
00274         if (!item || item->parent()->parent() != m_userCertificatesParent) {
00275             continue;
00276         }
00277         QTreeWidgetItem *parent = item->parent();
00278         m_knownCertificates.remove(item->m_cert.digest().toHex());
00279         delete item;
00280         didRemove = true;
00281         if (parent->childCount() == 0) {
00282             delete parent;
00283         }
00284     }
00285     if (didRemove) {
00286         emit changed(true);
00287     }
00288 }
00289 
00290 // private slot
00291 void CaCertificatesPage::addCertificateClicked()
00292 {
00293     QStringList certFiles
00294       = KFileDialog::getOpenFileNames(KUrl(), QLatin1String("application/x-x509-ca-cert"),
00295                                       this, i18n("Pick Certificates"));
00296 
00297     QList<QSslCertificate> certs;
00298     foreach (const QString &certFile, certFiles) {
00299         // trying both formats is easiest to program and most user-friendly if somewhat sloppy
00300         const int prevCertCount = certs.count();
00301         certs += QSslCertificate::fromPath(certFile, QSsl::Pem);
00302         if (prevCertCount == certs.count()) {
00303             certs += QSslCertificate::fromPath(certFile, QSsl::Der);
00304         }
00305         if (prevCertCount == certs.count()) {
00306             kDebug(7029) << "failed to load certificate file" << certFile;
00307         }
00308     }
00309 
00310     bool didAddCertificates = false;
00311     foreach (const QSslCertificate &cert, certs) {
00312         KSslCaCertificate caCert(cert, KSslCaCertificate::UserStore, false);
00313         if (!addCertificateItem(caCert)) {
00314             // ### tell the user?
00315         } else {
00316             didAddCertificates = true;
00317         }
00318     }
00319     if (didAddCertificates) {
00320         emit changed(true);
00321     }
00322 }
00323 
00324 // private slot
00325 void CaCertificatesPage::itemChanged(QTreeWidgetItem *item, int column)
00326 {
00327     Q_UNUSED(item)
00328     Q_UNUSED(column)
00329 
00330     if (m_blockItemChanged) {
00331         return;
00332     }
00333     kDebug(7029);
00334     // we could try to emit changed(false) if everything was changed back to status quo
00335 
00336     // a click on the checkbox of an unselected item first invokes itemSelectionChanged(),
00337     // then itemChanged(). we'll have to rerun the checks in itemSelectionChanged().
00338     itemSelectionChanged();
00339     emit changed(true);
00340 }
00341 
00342 static QTreeWidgetItem *findImmediateChild(QTreeWidgetItem *parent, const QString &issuerText)
00343 {
00344     for (int i = 0; i < parent->childCount(); i ++) {
00345         QTreeWidgetItem *candidate = parent->child(i);
00346         if (candidate->text(OrgCnColumn) == issuerText) {
00347             return candidate;
00348         }
00349     }
00350     return 0;
00351 }
00352 
00353 bool CaCertificatesPage::addCertificateItem(const KSslCaCertificate &caCert)
00354 {
00355     if (m_knownCertificates.contains(caCert.certHash)) {
00356         kDebug(7029) << "CaCertificatesPage::addCertificateItem(): refusing duplicate";
00357         return false;
00358     }
00359     const bool prevBlockItemChanged = m_blockItemChanged;
00360     m_blockItemChanged = true;
00361     QTreeWidgetItem *grandParent = caCert.store == KSslCaCertificate::SystemStore ?
00362                                             m_systemCertificatesParent : m_userCertificatesParent;
00363     const QString issuerOrganization = nonemptyIssuer(caCert.cert);
00364 
00365     QTreeWidgetItem *parent = findImmediateChild(grandParent, issuerOrganization);
00366     if (!parent) {
00367         parent = new QTreeWidgetItem(grandParent);
00368         parent->setText(OrgCnColumn, issuerOrganization);
00369         parent->setText(HiddenSortColumn, issuerOrganization.toLower());
00370         parent->setExpanded(true);
00371         parent->setFlags(parent->flags() & ~Qt::ItemIsSelectable);
00372     }
00373 
00374     (void) new CaCertificateItem(parent, caCert.cert, !caCert.isBlacklisted);
00375     m_knownCertificates.insert(caCert.certHash);
00376     m_blockItemChanged = prevBlockItemChanged;
00377     return true;
00378 }
00379 
00380 #include "cacertificatespage.moc"

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

Skip menu "kdelibs"
  • 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
Generated for kdelibs by doxygen 1.7.5
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal