diff --git a/K7Main.cpp b/K7Main.cpp index 58c3052..a7e8f55 100644 --- a/K7Main.cpp +++ b/K7Main.cpp @@ -265,7 +265,7 @@ void K7Main::DisplayKeys(const vector& kList, const WString& grpLabe * Here we allow the owner trust level of primary keys to be changed anytime. * Kleopatra doesn't do that for primary keys having ultimate trust level. */ - lblOwnerTrust->doubleClicked().connect(std::bind(&KeyEdit::OnOwnerTrustDoubleClicked, m_keyEdit, keyNode)); + lblOwnerTrust->doubleClicked().connect(std::bind(&KeyEdit::OnOwnerTrustDoubleClicked, m_keyEdit, keyNode, k.hasSecret())); lblOwnerTrust->setToolTip(TR("TTTDoubleCLick")); } keyNode->setColumnWidget(2, unique_ptr (lblOwnerTrust)); diff --git a/KeyEdit.cpp b/KeyEdit.cpp index 57c6d55..22f24fb 100644 --- a/KeyEdit.cpp +++ b/KeyEdit.cpp @@ -12,6 +12,7 @@ #include #include #include "GpgMEWorker.h" +#include "Tools.h" using namespace std; @@ -28,29 +29,48 @@ KeyEdit::~KeyEdit() delete m_popupUid; } -void KeyEdit::OnOwnerTrustDoubleClicked(WTreeTableNode * keyNode) +void KeyEdit::OnOwnerTrustDoubleClicked(WTreeTableNode * keyNode, bool keyHasSecret) { /* - * TODO : decide if we should exclude any primary key with ultimate trust - * level for any further change. + * A private key that a user does not manage will have its public part + * listed in the public WTreeTableNode. The certification trust level must + * not be editable by anyone. + */ + WText * lblFpr = static_cast (keyNode->columnWidget(3)); + if (!IsOurKey(lblFpr->text()) && Tools::KeyHasSecret(lblFpr->text())) { + m_owner->m_tmwMessage->SetText(TR("OwnerTrustReadOnly")); + return; + } + /* + * We leave a primary key with ultimate trust level for further change. + * kleopatra does not do that. */ WComboBox * cmbOwnerTrust = new WComboBox(); - FillOwnerTrustCombo(cmbOwnerTrust); - cmbOwnerTrust->blurred().connect(std::bind(&KeyEdit::OnOwnerTrustBlurred, this, keyNode)); + FillOwnerTrustCombo(cmbOwnerTrust, keyHasSecret); + cmbOwnerTrust->blurred().connect(std::bind(&KeyEdit::OnOwnerTrustBlurred, this, keyNode, keyHasSecret)); WText * lblOwnerTrust = static_cast (keyNode->columnWidget(2)); cmbOwnerTrust->setCurrentIndex(cmbOwnerTrust->findText(lblOwnerTrust->text())); - // If nothing gets changed, don't go to engine. + /* + * Prepare to check for change in combobox item. + * Change is detected by index, not value. + */ cmbOwnerTrust->setAttributeValue("previousTrustLevel", std::to_string(cmbOwnerTrust->currentIndex())); keyNode->setColumnWidget(2, unique_ptr (cmbOwnerTrust)); // +++ cmbOwnerTrust->setFocus(); } -void KeyEdit::OnOwnerTrustBlurred(WTreeTableNode* keyNode) +void KeyEdit::OnOwnerTrustBlurred(WTreeTableNode* keyNode, bool keyHasSecret) { + // Get new level (not index) WComboBox * cmbOwnerTrust = static_cast (keyNode->columnWidget(2)); + shared_ptr aiModel = cmbOwnerTrust->model(); + WStandardItemModel * iModel = static_cast (aiModel.get()); + WStandardItem * item = iModel->item(cmbOwnerTrust->currentIndex(), 0); + int newLevel = Tools::ToInt(item->text().toUTF8()); + WText * lblOwnerTrust = new WText(cmbOwnerTrust->currentText()); - lblOwnerTrust->doubleClicked().connect(std::bind(&KeyEdit::OnOwnerTrustDoubleClicked, this, keyNode)); + lblOwnerTrust->doubleClicked().connect(std::bind(&KeyEdit::OnOwnerTrustDoubleClicked, this, keyNode, keyHasSecret)); const WText * lblFpr = static_cast (keyNode->columnWidget(3)); const uint newTrustLevel = cmbOwnerTrust->currentIndex(); const WString previousTrustLevel = cmbOwnerTrust->attributeValue("previousTrustLevel"); @@ -58,9 +78,9 @@ void KeyEdit::OnOwnerTrustBlurred(WTreeTableNode* keyNode) // If nothing was changed, don't go to engine. if (WString(std::to_string(newTrustLevel)) == previousTrustLevel) return; - + GpgMEWorker gpgWorker; - GpgME::Error e = gpgWorker.EditOwnerTrust(lblFpr->text().toUTF8().c_str(), (GpgME::Key::OwnerTrust) newTrustLevel); + GpgME::Error e = gpgWorker.EditOwnerTrust(lblFpr->text().toUTF8().c_str(), (GpgME::Key::OwnerTrust) newLevel); if (e.code() != 0) { lblOwnerTrust->setText(previousTrustLevel); @@ -70,21 +90,24 @@ void KeyEdit::OnOwnerTrustBlurred(WTreeTableNode* keyNode) m_owner->m_tmwMessage->SetText(TR("OwnerTrustSuccess")); } -void KeyEdit::FillOwnerTrustCombo(WComboBox * cmb) +void KeyEdit::FillOwnerTrustCombo(WComboBox * cmb, bool keyHasSecret) { - /* - * We should perhaps exclude OwnerTrust::Ultimate. - * kleopatra doesn't do that. - */ shared_ptr siModel = make_shared (); OwnerTrustMap OwnerTrustLevel = m_owner->OwnerTrustLevel; vector> colIndex; vector> colText; - OwnerTrustMap::iterator it; - for (it = OwnerTrustLevel.begin(); it != OwnerTrustLevel.end(); it++) - { - colIndex.push_back(cpp14::make_unique (std::to_string((*it).first))); - colText.push_back(cpp14::make_unique ((*it).second)); + colIndex.push_back(cpp14::make_unique (std::to_string(UserID::Validity::Unknown))); + colText.push_back(cpp14::make_unique (TR("UidUnknown"))); + if (keyHasSecret) { + colIndex.push_back(cpp14::make_unique (std::to_string(UserID::Validity::Ultimate))); + colText.push_back(cpp14::make_unique (TR("UidUltimate"))); + } else { + colIndex.push_back(cpp14::make_unique (std::to_string(UserID::Validity::Never))); + colText.push_back(cpp14::make_unique (TR("UidNever"))); + colIndex.push_back(cpp14::make_unique (std::to_string(UserID::Validity::Marginal))); + colText.push_back(cpp14::make_unique (TR("UidMarginal"))); + colIndex.push_back(cpp14::make_unique (std::to_string(UserID::Validity::Full))); + colText.push_back(cpp14::make_unique (TR("UidFull"))); } siModel->appendColumn(std::move(colIndex)); siModel->appendColumn(std::move(colText)); diff --git a/KeyEdit.h b/KeyEdit.h index 044347d..e1a9677 100644 --- a/KeyEdit.h +++ b/KeyEdit.h @@ -31,13 +31,15 @@ public: /** * Shows a combobox with all trust levels * @param keyNode + * @param keyHasSecret */ - void OnOwnerTrustDoubleClicked(WTreeTableNode * keyNode); + void OnOwnerTrustDoubleClicked(WTreeTableNode * keyNode, bool keyHasSecret); /** * Saves any changes in trust level * @param keyNode + * @param keyHasSecret */ - void OnOwnerTrustBlurred(WTreeTableNode * keyNode); + void OnOwnerTrustBlurred(WTreeTableNode * keyNode, bool keyHasSecret); /** * If the fingerprint is that of a private key we manage, returns true. * @param fpr @@ -56,8 +58,15 @@ private: K7Main * m_owner; PopupCertifyUserId * m_popupUid; WString m_targetKeyFpr; - - void FillOwnerTrustCombo(WComboBox * cmb); + /** + * Unknown is common. + * \n If keyHasSecret is true, show only Ultimate level. + * \n Else, show everything except Ultimate. + * \n Undefined is not included. + * @param cmb + * @param keyHasSecret + */ + void FillOwnerTrustCombo(WComboBox * cmb, bool keyHasSecret); void CertifyKey(); }; diff --git a/Tools.cpp b/Tools.cpp index 6b59968..80cb4bc 100644 --- a/Tools.cpp +++ b/Tools.cpp @@ -13,10 +13,12 @@ using namespace std; -Tools::Tools() { +Tools::Tools() +{ } -Tools::~Tools() { +Tools::~Tools() +{ } bool Tools::ConfigKeyIdMatchesKey(const GpgME::Key& k, const WString& configKeyId) @@ -27,7 +29,8 @@ bool Tools::ConfigKeyIdMatchesKey(const GpgME::Key& k, const WString& configKeyI || configKeyId == WString(k.primaryFingerprint())); } -int Tools::ToInt(const string& s) { +int Tools::ToInt(const string& s) +{ istringstream buffer(s.c_str()); int num; buffer >> num; @@ -37,8 +40,8 @@ int Tools::ToInt(const string& s) { WString Tools::TexttualBool(bool value) { const WString res = value - ? WString::tr("Yes") - : WString::tr("No"); + ? WString::tr("Yes") + : WString::tr("No"); return res; } @@ -55,8 +58,8 @@ WString Tools::GetKeyStatus(const GpgME::Key& k) status += WString(WString::tr("KeyStatusIsDisabled")) + sep + TexttualBool(k.isDisabled()) + nl; status += WString(WString::tr("KeyStatusIsExpired")) + sep + TexttualBool(k.isExpired()) + nl; status += WString(WString::tr("KeyStatusIsRevoked")) + sep + TexttualBool(k.isRevoked()) + nl + nl; - status += WString(WString::tr("KeyTypeIsSecret")) + sep + TexttualBool(k.isSecret()); - + status += WString(WString::tr("KeyTypeIsSecret")) + sep + TexttualBool(KeyHasSecret(k.primaryFingerprint())); + return status; } @@ -70,7 +73,7 @@ WString Tools::GetUidStatus(const GpgME::UserID& uid) status += WString(WString::tr("UserStatusIsNull")) + sep + TexttualBool(uid.isNull()) + nl; status += WString(WString::tr("UserStatusIsInvalid")) + sep + TexttualBool(uid.isInvalid()) + nl; status += WString(WString::tr("UserStatusIsRevoked")) + sep + TexttualBool(uid.isRevoked()); - + return status; } @@ -86,7 +89,18 @@ WString Tools::GetSigStatus(const GpgME::UserID::Signature& sig) status += WString(WString::tr("SigStatusIsExportable")) + sep + TexttualBool(sig.isExportable()) + nl; status += WString(WString::tr("SigStatusIsExpired")) + sep + TexttualBool(sig.isExpired()) + nl; status += WString(WString::tr("SigStatusIsRevokation")) + sep + TexttualBool(sig.isRevokation()); - + return status; } +bool Tools::KeyHasSecret(const WString& fpr) +{ + Error e; + GpgMEWorker gpgw; + GpgME::Key k = gpgw.FindKey(fpr.toUTF8().c_str(), e, true); // Look for a private key + if (e.code() != 0 && e.code() != 16383) + { // 16383 : end of file, when key is not private + return false; + } + return (!k.isNull()); +} diff --git a/Tools.h b/Tools.h index 54258dd..f474c3d 100644 --- a/Tools.h +++ b/Tools.h @@ -43,6 +43,7 @@ public: static WString GetKeyStatus(const GpgME::Key& k); static WString GetUidStatus(const GpgME::UserID& uid); static WString GetSigStatus(const GpgME::UserID::Signature& sig); + static bool KeyHasSecret(const WString& fpr); private: diff --git a/WTAPPROOT/K7/K7.xml b/WTAPPROOT/K7/K7.xml index 415dc44..e2c8348 100644 --- a/WTAPPROOT/K7/K7.xml +++ b/WTAPPROOT/K7/K7.xml @@ -66,6 +66,7 @@ Double click to edit This is your key + Owner trust level read only; a primary key coexists and you don't manage it. Owner trust level succesfully changed Owner trust level failed to be changed @@ -89,7 +90,7 @@ Disabled Expired Revoked - Secret + Coexists with a secret key User status Bad diff --git a/WTAPPROOT/K7/K7_fr.xml b/WTAPPROOT/K7/K7_fr.xml index 6dcd5a2..ae48ee0 100644 --- a/WTAPPROOT/K7/K7_fr.xml +++ b/WTAPPROOT/K7/K7_fr.xml @@ -66,6 +66,7 @@ Double cliquez pour éditer C'est votre clé + Confiance dans la certification en lecture seule; une clé primaire coexiste et vous ne la gérez pas. Confiance dans la certification changée avec succès Échec de changement de la confiance dans la certification @@ -89,7 +90,7 @@ Désactivé Expiré Revoqué - Secret + Coexiste avec une clé secrète État de l'utilisateur Mauvais diff --git a/nbproject/private/configurations.xml b/nbproject/private/configurations.xml index 2c9b830..1f82c50 100644 --- a/nbproject/private/configurations.xml +++ b/nbproject/private/configurations.xml @@ -13,6 +13,8 @@ + + diff --git a/nbproject/private/private.xml b/nbproject/private/private.xml index 850251b..14a195b 100644 --- a/nbproject/private/private.xml +++ b/nbproject/private/private.xml @@ -7,14 +7,9 @@ - file:/home/user/Documents/published/K7/PopupDeleter.h - file:/home/user/Documents/published/K7/K7Main.h - file:/home/user/Documents/published/K7/PopupUploader.h + file:/home/user/Documents/published/K7/AppConfig.cpp file:/home/user/Documents/published/K7/K7Main.cpp - file:/home/user/Documents/published/K7/PopupCertifyUserId.cpp - file:/home/user/Documents/published/K7/PopupUploader.cpp - file:/home/user/Documents/published/K7/PopupCertifyUserId.h - file:/home/user/Documents/published/K7/PopupDeleter.cpp + file:/home/user/Documents/published/K7/main.cpp