File indexing completed on 2024-05-12 04:44:57
0001 /* 0002 Copyright (C) 2007 Justin Karneges <justin@affinix.com> 0003 0004 Permission is hereby granted, free of charge, to any person obtaining a copy 0005 of this software and associated documentation files (the "Software"), to deal 0006 in the Software without restriction, including without limitation the rights 0007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 0008 copies of the Software, and to permit persons to whom the Software is 0009 furnished to do so, subject to the following conditions: 0010 0011 The above copyright notice and this permission notice shall be included in 0012 all copies or substantial portions of the Software. 0013 0014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 0015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 0016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 0017 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 0018 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 0019 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 0020 */ 0021 0022 #include "pkcs11configdlg.h" 0023 0024 #include "ui_pkcs11config.h" 0025 #include <QFileDialog> 0026 #include <QMessageBox> 0027 #include <QtCore> 0028 #include <QtCrypto> 0029 #include <QtGui> 0030 0031 //---------------------------------------------------------------------------- 0032 // Pkcs11ProviderConfig 0033 //---------------------------------------------------------------------------- 0034 class Pkcs11ProviderConfig 0035 { 0036 public: 0037 bool allow_protected_authentication; 0038 bool cert_private; 0039 bool enabled; 0040 QString library; 0041 QString name; 0042 int private_mask; 0043 QString slotevent_method; 0044 int slotevent_timeout; 0045 0046 Pkcs11ProviderConfig() 0047 : allow_protected_authentication(true) 0048 , cert_private(false) 0049 , enabled(false) 0050 , private_mask(0) 0051 , slotevent_method("auto") 0052 , slotevent_timeout(0) 0053 { 0054 } 0055 0056 QVariantMap toVariantMap() const 0057 { 0058 QVariantMap out; 0059 out["allow_protected_authentication"] = allow_protected_authentication; 0060 out["cert_private"] = cert_private; 0061 out["enabled"] = enabled; 0062 out["library"] = library; 0063 out["name"] = name; 0064 out["private_mask"] = private_mask; 0065 out["slotevent_method"] = slotevent_method; 0066 out["slotevent_timeout"] = slotevent_timeout; 0067 return out; 0068 } 0069 0070 bool fromVariantMap(const QVariantMap &in) 0071 { 0072 allow_protected_authentication = in["allow_protected_authentication"].toBool(); 0073 cert_private = in["cert_private"].toBool(); 0074 enabled = in["enabled"].toBool(); 0075 library = in["library"].toString(); 0076 name = in["name"].toString(); 0077 private_mask = in["private_mask"].toInt(); 0078 slotevent_method = in["slotevent_method"].toString(); 0079 slotevent_timeout = in["slotevent_timeout"].toInt(); 0080 return true; 0081 } 0082 }; 0083 0084 //---------------------------------------------------------------------------- 0085 // Pkcs11Config 0086 //---------------------------------------------------------------------------- 0087 class Pkcs11Config 0088 { 0089 public: 0090 bool allow_load_rootca; 0091 bool allow_protected_authentication; 0092 int log_level; 0093 int pin_cache; 0094 QList<Pkcs11ProviderConfig> providers; 0095 0096 QVariantMap orig_config; 0097 0098 Pkcs11Config() 0099 : allow_load_rootca(false) 0100 , allow_protected_authentication(true) 0101 , log_level(0) 0102 , pin_cache(-1) 0103 { 0104 } 0105 0106 QVariantMap toVariantMap() const 0107 { 0108 QVariantMap out = orig_config; 0109 0110 // form type 0111 out["formtype"] = "http://affinix.com/qca/forms/qca-pkcs11#1.0"; 0112 0113 // base settings 0114 out["allow_load_rootca"] = allow_load_rootca; 0115 out["allow_protected_authentication"] = allow_protected_authentication; 0116 out["log_level"] = log_level; 0117 out["pin_cache"] = pin_cache; 0118 0119 // provider settings (always write at least 10 providers) 0120 for (int n = 0; n < 10 || n < providers.count(); ++n) { 0121 QString prefix = QString().sprintf("provider_%02d_", n); 0122 0123 Pkcs11ProviderConfig provider; 0124 if (n < providers.count()) 0125 provider = providers[n]; 0126 0127 QVariantMap subconfig = provider.toVariantMap(); 0128 QMapIterator<QString, QVariant> it(subconfig); 0129 while (it.hasNext()) { 0130 it.next(); 0131 out.insert(prefix + it.key(), it.value()); 0132 } 0133 } 0134 0135 return out; 0136 } 0137 0138 bool fromVariantMap(const QVariantMap &in) 0139 { 0140 if (in["formtype"] != "http://affinix.com/qca/forms/qca-pkcs11#1.0") 0141 return false; 0142 0143 allow_load_rootca = in["allow_load_rootca"].toBool(); 0144 allow_protected_authentication = in["allow_protected_authentication"].toBool(); 0145 log_level = in["log_level"].toInt(); 0146 pin_cache = in["pin_cache"].toInt(); 0147 0148 for (int n = 0;; ++n) { 0149 QString prefix = QString().sprintf("provider_%02d_", n); 0150 0151 // collect all key/values with this prefix into a 0152 // a separate container, leaving out the prefix 0153 // from the keys. 0154 QVariantMap subconfig; 0155 QMapIterator<QString, QVariant> it(in); 0156 while (it.hasNext()) { 0157 it.next(); 0158 if (it.key().startsWith(prefix)) 0159 subconfig.insert(it.key().mid(prefix.length()), it.value()); 0160 } 0161 0162 // if there are no config items with this prefix, we're done 0163 if (subconfig.isEmpty()) 0164 break; 0165 0166 Pkcs11ProviderConfig provider; 0167 if (!provider.fromVariantMap(subconfig)) 0168 return false; 0169 0170 // skip unnamed entries 0171 if (provider.name.isEmpty()) 0172 continue; 0173 0174 // skip duplicate entries 0175 bool have_name_already = false; 0176 foreach (const Pkcs11ProviderConfig &i, providers) { 0177 if (i.name == provider.name) { 0178 have_name_already = true; 0179 break; 0180 } 0181 } 0182 if (have_name_already) 0183 continue; 0184 0185 providers += provider; 0186 } 0187 0188 orig_config = in; 0189 return true; 0190 } 0191 }; 0192 0193 //---------------------------------------------------------------------------- 0194 // ModuleListModel 0195 //---------------------------------------------------------------------------- 0196 class ModuleListModel : public QAbstractListModel 0197 { 0198 Q_OBJECT 0199 public: 0200 QList<Pkcs11ProviderConfig> list; 0201 0202 ModuleListModel(QObject *parent = 0) 0203 : QAbstractListModel(parent) 0204 { 0205 } 0206 0207 int rowCount(const QModelIndex &parent = QModelIndex()) const 0208 { 0209 Q_UNUSED(parent); 0210 return list.count(); 0211 } 0212 0213 QVariant data(const QModelIndex &index, int role) const 0214 { 0215 if (!index.isValid()) 0216 return QVariant(); 0217 0218 if (index.row() >= list.count()) 0219 return QVariant(); 0220 0221 if (role == Qt::DisplayRole) 0222 return list[index.row()].name; 0223 else if (role == Qt::EditRole) 0224 return list[index.row()].name; 0225 else 0226 return QVariant(); 0227 } 0228 0229 Qt::ItemFlags flags(const QModelIndex &index) const 0230 { 0231 if (!index.isValid()) 0232 return Qt::ItemIsEnabled; 0233 0234 return QAbstractItemModel::flags(index) | Qt::ItemIsEditable; 0235 } 0236 0237 bool setData(const QModelIndex &index, const QVariant &value, int role) 0238 { 0239 if (index.isValid() && role == Qt::EditRole) { 0240 QString str = value.toString(); 0241 0242 if (str.isEmpty()) { 0243 emit editFailed(index, tr("Module name cannot be blank.")); 0244 return false; 0245 } 0246 0247 bool have_name_already = false; 0248 int at = index.row(); 0249 for (int n = 0; n < list.count(); ++n) { 0250 const Pkcs11ProviderConfig &i = list[n]; 0251 0252 // skip self 0253 if (n == at) 0254 continue; 0255 0256 if (i.name == str) { 0257 have_name_already = true; 0258 break; 0259 } 0260 } 0261 if (have_name_already) { 0262 emit editFailed(index, tr("There is already a module with this name.")); 0263 return false; 0264 } 0265 0266 list[index.row()].name = str; 0267 emit dataChanged(index, index); 0268 return true; 0269 } 0270 return false; 0271 } 0272 0273 void addItems(const QList<Pkcs11ProviderConfig> &items) 0274 { 0275 if (items.isEmpty()) 0276 return; 0277 0278 beginInsertRows(QModelIndex(), list.size(), list.size() + items.count() - 1); 0279 list += items; 0280 endInsertRows(); 0281 } 0282 0283 void addItem(const Pkcs11ProviderConfig &i) 0284 { 0285 beginInsertRows(QModelIndex(), list.size(), list.size()); 0286 list += i; 0287 endInsertRows(); 0288 } 0289 0290 void removeItem(int at) 0291 { 0292 beginRemoveRows(QModelIndex(), at, at); 0293 list.removeAt(at); 0294 endRemoveRows(); 0295 } 0296 0297 Q_SIGNALS: 0298 void editFailed(const QModelIndex &index, const QString &reasonString); 0299 }; 0300 0301 //---------------------------------------------------------------------------- 0302 // Pkcs11ConfigDlg 0303 //---------------------------------------------------------------------------- 0304 static QCA::Provider *get_pkcs11_provider(QVariantMap *_config = 0) 0305 { 0306 QCA::ProviderList providers = QCA::providers(); 0307 providers += QCA::defaultProvider(); 0308 0309 QCA::Provider *provider = 0; 0310 QVariantMap config; 0311 foreach (QCA::Provider *p, providers) { 0312 config = QCA::getProviderConfig(p->name()); 0313 if (!config.isEmpty() && config["formtype"] == "http://affinix.com/qca/forms/qca-pkcs11#1.0") { 0314 provider = p; 0315 break; 0316 } 0317 } 0318 0319 if (provider && _config) 0320 *_config = config; 0321 0322 return provider; 0323 } 0324 0325 class Pkcs11ConfigDlg::Private : public QObject 0326 { 0327 Q_OBJECT 0328 public: 0329 Pkcs11ConfigDlg *q; 0330 Ui_Pkcs11Config ui; 0331 QString providerName; 0332 ModuleListModel *model; 0333 Pkcs11Config config; 0334 bool dirty; 0335 0336 // for safe dialog closing behavior during QListView editing 0337 bool allow_close; 0338 bool done; 0339 0340 // for ignoring modifications that we cause when populating fields 0341 bool ignore_dataChanged; 0342 0343 Private(Pkcs11ConfigDlg *_q, const QString &_providerName, const QVariantMap &configmap) 0344 : QObject(_q) 0345 , q(_q) 0346 , providerName(_providerName) 0347 , dirty(false) 0348 , allow_close(true) 0349 , done(false) 0350 , ignore_dataChanged(true) 0351 { 0352 ui.setupUi(q); 0353 q->resize(q->minimumSize()); 0354 0355 model = new ModuleListModel(this); 0356 qRegisterMetaType<QModelIndex>("QModelIndex"); 0357 // do this queued for two reasons: 0358 // 1) if we throw an error dialog, it will occur after the 0359 // row text has reverted, and the call stack completed 0360 // (the latter may not be required, but it helps me 0361 // sleep). 0362 // 2) if the user accepts/rejects the dialog while editing, 0363 // it is easy to ensure that the signal is not processed 0364 // (if it gets delivered at all). 0365 connect(model, 0366 SIGNAL(editFailed(const QModelIndex &, const QString &)), 0367 SLOT(model_editFailed(const QModelIndex &, const QString &)), 0368 Qt::QueuedConnection); 0369 0370 // set up widgets 0371 ui.rb_pincache_nolimit->setChecked(true); 0372 ui.sb_pincache_time->setEnabled(false); 0373 ui.sb_pincache_time->setValue(300); 0374 ui.lv_modules->setModel(model); 0375 ui.lv_modules->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::SelectedClicked | 0376 QAbstractItemView::EditKeyPressed); 0377 ui.pb_remove->setEnabled(false); 0378 ui.tb_details->setEnabled(false); 0379 ui.gb_poll->setEnabled(false); 0380 ui.rb_polldefault->setChecked(true); 0381 ui.sb_pollcustom->setEnabled(false); 0382 ui.sb_pollcustom->setValue(5); 0383 ui.ck_modeauto->setChecked(true); 0384 0385 // disable this by default, enable on dataChanged 0386 ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); 0387 0388 // general 0389 connect(ui.ck_allowroot, SIGNAL(toggled(bool)), SLOT(dataChanged())); 0390 connect(ui.ck_allowprotected, SIGNAL(toggled(bool)), SLOT(dataChanged())); 0391 connect(ui.sb_loglevel, SIGNAL(valueChanged(int)), SLOT(dataChanged())); 0392 connect(ui.gb_pincache, SIGNAL(toggled(bool)), SLOT(dataChanged())); 0393 connect(ui.rb_pincache_nolimit, SIGNAL(toggled(bool)), SLOT(dataChanged())); 0394 connect(ui.rb_pincache_time, SIGNAL(toggled(bool)), ui.sb_pincache_time, SLOT(setEnabled(bool))); 0395 connect(ui.rb_pincache_time, SIGNAL(toggled(bool)), SLOT(dataChanged())); 0396 connect(ui.sb_pincache_time, SIGNAL(valueChanged(int)), SLOT(dataChanged())); 0397 0398 // modules 0399 connect(model, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), SLOT(dataChanged())); 0400 connect(ui.lv_modules->selectionModel(), 0401 SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), 0402 SLOT(module_selectionChanged(const QItemSelection &, const QItemSelection &))); 0403 connect(ui.pb_add, SIGNAL(clicked()), SLOT(module_add())); 0404 connect(ui.pb_remove, SIGNAL(clicked()), SLOT(module_remove())); 0405 connect(ui.le_library, SIGNAL(textChanged(const QString &)), SLOT(dataChanged())); 0406 connect(ui.pb_browse, SIGNAL(clicked()), SLOT(library_browse())); 0407 connect(ui.cb_slotmethod, SIGNAL(currentIndexChanged(int)), SLOT(slotmethod_currentIndexChanged(int))); 0408 connect(ui.rb_polldefault, SIGNAL(toggled(bool)), SLOT(dataChanged())); 0409 connect(ui.rb_pollcustom, SIGNAL(toggled(bool)), ui.sb_pollcustom, SLOT(setEnabled(bool))); 0410 connect(ui.rb_pollcustom, SIGNAL(toggled(bool)), SLOT(dataChanged())); 0411 connect(ui.sb_pollcustom, SIGNAL(valueChanged(int)), SLOT(dataChanged())); 0412 connect(ui.ck_modallowprotected, SIGNAL(toggled(bool)), SLOT(dataChanged())); 0413 connect(ui.ck_certprivate, SIGNAL(toggled(bool)), SLOT(dataChanged())); 0414 connect(ui.ck_modeauto, SIGNAL(toggled(bool)), SLOT(modeauto_toggled(bool))); 0415 connect(ui.ck_modesign, SIGNAL(toggled(bool)), SLOT(modenonauto_toggled(bool))); 0416 connect(ui.ck_modesignrecover, SIGNAL(toggled(bool)), SLOT(modenonauto_toggled(bool))); 0417 connect(ui.ck_modedecrypt, SIGNAL(toggled(bool)), SLOT(modenonauto_toggled(bool))); 0418 connect(ui.ck_modeunwrap, SIGNAL(toggled(bool)), SLOT(modenonauto_toggled(bool))); 0419 0420 // is this a valid config? 0421 if (!providerName.isEmpty() && config.fromVariantMap(configmap)) { 0422 // if so, load everything up 0423 ui.ck_allowroot->setChecked(config.allow_load_rootca); 0424 ui.ck_allowprotected->setChecked(config.allow_protected_authentication); 0425 ui.sb_loglevel->setValue(config.log_level); 0426 if (config.pin_cache != 0) { 0427 ui.gb_pincache->setChecked(true); 0428 if (config.pin_cache <= -1) 0429 ui.rb_pincache_nolimit->setChecked(true); 0430 else { 0431 ui.rb_pincache_time->setChecked(true); 0432 ui.sb_pincache_time->setValue(config.pin_cache); 0433 } 0434 } 0435 0436 model->addItems(config.providers); 0437 if (!model->list.isEmpty()) { 0438 QModelIndex index = model->index(0); 0439 ui.lv_modules->setCurrentIndex(index); 0440 ui.lv_modules->selectionModel()->select( 0441 index, QItemSelectionModel::Clear | QItemSelectionModel::Select | QItemSelectionModel::Current); 0442 } 0443 ui.buttonBox->setFocus(); 0444 ui.buttonBox->button(QDialogButtonBox::Cancel)->setFocus(); 0445 } else { 0446 // otherwise, disable everything 0447 ui.gb_general->setEnabled(false); 0448 ui.gb_modules->setEnabled(false); 0449 ui.buttonBox->setFocus(); 0450 ui.buttonBox->button(QDialogButtonBox::Cancel)->setFocus(); 0451 } 0452 0453 ignore_dataChanged = false; 0454 } 0455 0456 void save_module(int at) 0457 { 0458 // save all options (except the name, which is handled by the model) 0459 Pkcs11ProviderConfig &i = model->list[at]; 0460 0461 i.library = ui.le_library->text(); 0462 i.enabled = true; 0463 0464 int x = ui.cb_slotmethod->currentIndex(); 0465 if (x == 0) 0466 i.slotevent_method = "auto"; 0467 else if (x == 1) 0468 i.slotevent_method = "trigger"; 0469 else // 2 0470 i.slotevent_method = "poll"; 0471 if (x == 2) { 0472 if (ui.rb_polldefault->isChecked()) 0473 i.slotevent_timeout = 0; 0474 else 0475 i.slotevent_timeout = ui.sb_pollcustom->value(); 0476 } else 0477 i.slotevent_timeout = 0; 0478 0479 i.allow_protected_authentication = ui.ck_modallowprotected->isChecked(); 0480 i.cert_private = ui.ck_certprivate->isChecked(); 0481 0482 i.private_mask = 0; 0483 if (ui.ck_modesign->isChecked()) 0484 i.private_mask |= 1; 0485 if (ui.ck_modesignrecover->isChecked()) 0486 i.private_mask |= 2; 0487 if (ui.ck_modedecrypt->isChecked()) 0488 i.private_mask |= 4; 0489 if (ui.ck_modeunwrap->isChecked()) 0490 i.private_mask |= 8; 0491 } 0492 0493 void save() 0494 { 0495 // save currently selected module, which may not be saved yet 0496 QItemSelection selection = ui.lv_modules->selectionModel()->selection(); 0497 if (!selection.indexes().isEmpty()) { 0498 QModelIndex index = selection.indexes().first(); 0499 save_module(index.row()); 0500 } 0501 0502 config.allow_load_rootca = ui.ck_allowroot->isChecked(); 0503 config.allow_protected_authentication = ui.ck_allowprotected->isChecked(); 0504 config.log_level = ui.sb_loglevel->value(); 0505 if (ui.gb_pincache->isChecked()) { 0506 if (ui.rb_pincache_nolimit->isChecked()) 0507 config.pin_cache = -1; 0508 else 0509 config.pin_cache = ui.sb_pincache_time->value(); 0510 } else 0511 config.pin_cache = 0; 0512 0513 config.providers = model->list; 0514 0515 QVariantMap configmap = config.toVariantMap(); 0516 QCA::setProviderConfig(providerName, configmap); 0517 QCA::saveProviderConfig(providerName); 0518 } 0519 0520 private Q_SLOTS: 0521 void model_editFailed(const QModelIndex &index, const QString &reasonString) 0522 { 0523 // if the dialog has already been dismissed, then don't 0524 // bother with handling the editing failure 0525 if (done) 0526 return; 0527 0528 // show error dialog, and don't allow dimissing the dialog 0529 // during. we need this, because the dismiss request 0530 // can be queued, and end up being invoked during the 0531 // QMessageBox nested eventloop. 0532 allow_close = false; 0533 QMessageBox::information(q, tr("Module Configuration"), reasonString); 0534 allow_close = true; 0535 0536 // return to edit mode for the item 0537 ui.lv_modules->setFocus(); 0538 ui.lv_modules->setCurrentIndex(index); 0539 ui.lv_modules->selectionModel()->select( 0540 index, QItemSelectionModel::Clear | QItemSelectionModel::Select | QItemSelectionModel::Current); 0541 ui.lv_modules->edit(index); 0542 } 0543 0544 void dataChanged() 0545 { 0546 if (ignore_dataChanged) 0547 return; 0548 0549 if (dirty) 0550 return; 0551 0552 dirty = true; 0553 ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); 0554 } 0555 0556 void module_selectionChanged(const QItemSelection &selected, const QItemSelection &deselected) 0557 { 0558 if (!deselected.indexes().isEmpty()) { 0559 QModelIndex index = deselected.indexes().first(); 0560 save_module(index.row()); 0561 } 0562 0563 ignore_dataChanged = true; 0564 0565 if (!selected.indexes().isEmpty()) { 0566 if (deselected.indexes().isEmpty()) { 0567 ui.pb_remove->setEnabled(true); 0568 ui.tb_details->setEnabled(true); 0569 } 0570 0571 QModelIndex index = selected.indexes().first(); 0572 const Pkcs11ProviderConfig &i = model->list[index.row()]; 0573 0574 ui.le_library->setText(i.library); 0575 0576 if (i.slotevent_method == "trigger") 0577 ui.cb_slotmethod->setCurrentIndex(1); 0578 else if (i.slotevent_method == "poll") { 0579 ui.cb_slotmethod->setCurrentIndex(2); 0580 if (i.slotevent_timeout <= 0) 0581 ui.rb_polldefault->setChecked(true); 0582 else { 0583 ui.rb_pollcustom->setChecked(true); 0584 ui.sb_pollcustom->setValue(i.slotevent_timeout); 0585 } 0586 } else // auto 0587 ui.cb_slotmethod->setCurrentIndex(0); 0588 if (i.slotevent_method != "poll") { 0589 ui.rb_polldefault->setChecked(true); 0590 ui.sb_pollcustom->setValue(5); 0591 } 0592 0593 ui.ck_modallowprotected->setChecked(i.allow_protected_authentication); 0594 ui.ck_certprivate->setChecked(i.cert_private); 0595 0596 if (i.private_mask == 0) 0597 ui.ck_modeauto->setChecked(true); 0598 else { 0599 ui.ck_modesign->setChecked(i.private_mask & 1); 0600 ui.ck_modesignrecover->setChecked(i.private_mask & 2); 0601 ui.ck_modedecrypt->setChecked(i.private_mask & 4); 0602 ui.ck_modeunwrap->setChecked(i.private_mask & 8); 0603 } 0604 } else if (selected.indexes().isEmpty() && !deselected.indexes().isEmpty()) { 0605 // restore defaults for all details widgets 0606 ui.le_library->setText(QString()); 0607 ui.cb_slotmethod->setCurrentIndex(0); 0608 ui.rb_polldefault->setChecked(true); 0609 ui.sb_pollcustom->setValue(5); 0610 ui.ck_modallowprotected->setChecked(false); 0611 ui.ck_certprivate->setChecked(false); 0612 ui.ck_modeauto->setChecked(true); 0613 0614 // flip to first page, disable 0615 ui.tb_details->setCurrentIndex(0); 0616 ui.pb_remove->setEnabled(false); 0617 ui.tb_details->setEnabled(false); 0618 } 0619 0620 ignore_dataChanged = false; 0621 } 0622 0623 void module_add() 0624 { 0625 // find unused default name 0626 QString name; 0627 for (int n = 1;; ++n) { 0628 if (n == 1) 0629 name = tr("New Module"); 0630 else 0631 name = tr("New Module (%1)").arg(n); 0632 0633 bool have_name_already = false; 0634 for (int n = 0; n < model->list.count(); ++n) { 0635 const Pkcs11ProviderConfig &i = model->list[n]; 0636 if (i.name == name) { 0637 have_name_already = true; 0638 break; 0639 } 0640 } 0641 if (!have_name_already) 0642 break; 0643 } 0644 0645 Pkcs11ProviderConfig i; 0646 i.name = name; 0647 i.enabled = true; 0648 model->addItem(i); 0649 0650 dataChanged(); 0651 0652 QModelIndex index = model->index(model->list.count() - 1); 0653 0654 // flip to first page 0655 ui.tb_details->setCurrentIndex(0); 0656 0657 // edit this item 0658 ui.lv_modules->setFocus(); 0659 ui.lv_modules->setCurrentIndex(index); 0660 ui.lv_modules->selectionModel()->select( 0661 index, QItemSelectionModel::Clear | QItemSelectionModel::Select | QItemSelectionModel::Current); 0662 ui.lv_modules->edit(index); 0663 } 0664 0665 void module_remove() 0666 { 0667 QItemSelection selection = ui.lv_modules->selectionModel()->selection(); 0668 if (selection.indexes().isEmpty()) 0669 return; 0670 QModelIndex index = selection.indexes().first(); 0671 model->removeItem(index.row()); 0672 0673 dataChanged(); 0674 } 0675 0676 void library_browse() 0677 { 0678 QString fileName = 0679 QFileDialog::getOpenFileName(q, tr("Select PKCS#11 Module"), QString(), tr("PKCS#11 Modules (*.*)")); 0680 if (fileName.isEmpty()) 0681 return; 0682 0683 ui.le_library->setText(fileName); 0684 } 0685 0686 void slotmethod_currentIndexChanged(int index) 0687 { 0688 if (index == 2) // Polling 0689 ui.gb_poll->setEnabled(true); 0690 else 0691 ui.gb_poll->setEnabled(false); 0692 0693 dataChanged(); 0694 } 0695 0696 void modeauto_toggled(bool checked) 0697 { 0698 if (checked) { 0699 if (ui.ck_modesign->isChecked()) 0700 ui.ck_modesign->setChecked(false); 0701 if (ui.ck_modesignrecover->isChecked()) 0702 ui.ck_modesignrecover->setChecked(false); 0703 if (ui.ck_modedecrypt->isChecked()) 0704 ui.ck_modedecrypt->setChecked(false); 0705 if (ui.ck_modeunwrap->isChecked()) 0706 ui.ck_modeunwrap->setChecked(false); 0707 } else { 0708 if (!ui.ck_modesign->isChecked() && !ui.ck_modesignrecover->isChecked() && 0709 !ui.ck_modedecrypt->isChecked() && !ui.ck_modeunwrap->isChecked()) { 0710 ui.ck_modesign->setChecked(true); 0711 ui.ck_modesignrecover->setChecked(true); 0712 ui.ck_modedecrypt->setChecked(true); 0713 ui.ck_modeunwrap->setChecked(true); 0714 } 0715 } 0716 0717 dataChanged(); 0718 } 0719 0720 void modenonauto_toggled(bool checked) 0721 { 0722 if (checked) { 0723 if (ui.ck_modeauto->isChecked()) 0724 ui.ck_modeauto->setChecked(false); 0725 } else { 0726 if (!ui.ck_modesign->isChecked() && !ui.ck_modesignrecover->isChecked() && 0727 !ui.ck_modedecrypt->isChecked() && !ui.ck_modeunwrap->isChecked()) { 0728 ui.ck_modeauto->setChecked(true); 0729 } 0730 } 0731 0732 dataChanged(); 0733 } 0734 }; 0735 0736 Pkcs11ConfigDlg::Pkcs11ConfigDlg(QWidget *parent) 0737 : QDialog(parent) 0738 { 0739 QVariantMap config; 0740 QCA::Provider *p = get_pkcs11_provider(&config); 0741 if (p) 0742 d = new Private(this, p->name(), config); 0743 else 0744 d = new Private(this, QString(), QVariantMap()); 0745 } 0746 0747 Pkcs11ConfigDlg::Pkcs11ConfigDlg(const QString &providerName, const QVariantMap &config, QWidget *parent) 0748 : QDialog(parent) 0749 { 0750 d = new Private(this, providerName, config); 0751 } 0752 0753 Pkcs11ConfigDlg::~Pkcs11ConfigDlg() 0754 { 0755 delete d; 0756 } 0757 0758 void Pkcs11ConfigDlg::done(int r) 0759 { 0760 if (!d->allow_close) 0761 return; 0762 0763 d->done = true; 0764 if (r == Accepted) 0765 d->save(); 0766 QDialog::done(r); 0767 } 0768 0769 bool Pkcs11ConfigDlg::isSupported() 0770 { 0771 return (get_pkcs11_provider() ? true : false); 0772 } 0773 0774 #include "pkcs11configdlg.moc"