Merge branch 'master' into TestExportPrivateKeys
This commit is contained in:
57
GpgMELogger.h
Normal file
57
GpgMELogger.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* File: GpgMELogger.h
|
||||
* Author: SET - nmset@yandex.com
|
||||
* License : GPL v2
|
||||
* Copyright SET - © 2019
|
||||
*
|
||||
* Created on November 23, 2020, 4:00 PM
|
||||
*/
|
||||
|
||||
#ifndef GPGMELOGGER_H
|
||||
#define GPGMELOGGER_H
|
||||
|
||||
#include <Wt/WLogger.h>
|
||||
#include <Wt/WApplication.h>
|
||||
#include <Wt/WEnvironment.h>
|
||||
#include <Wt/WSslCertificate.h>
|
||||
#include <Wt/WSslInfo.h>
|
||||
#include <gpgme++/error.h>
|
||||
#include <mutex>
|
||||
|
||||
using namespace Wt;
|
||||
|
||||
static std::mutex gs_logGpgMEError;
|
||||
#define LGE(e) LogGpgMEError(e)
|
||||
|
||||
static void LogGpgMEError(const GpgME::Error& e)
|
||||
{
|
||||
if (e.code() == 0)
|
||||
return;
|
||||
std::unique_lock<std::mutex> lock(gs_logGpgMEError);
|
||||
|
||||
const vector<WSslCertificate::DnAttribute> * dnAttr
|
||||
= &(WApplication::instance()->environment().sslInfo()
|
||||
->clientCertificate().subjectDn());
|
||||
WString subjectCommonName = WString::Empty;
|
||||
for (uint i = 0; i < dnAttr->size(); i++)
|
||||
{
|
||||
if (dnAttr->at(i).name() == WSslCertificate::DnAttributeName::CommonName)
|
||||
{
|
||||
subjectCommonName = dnAttr->at(i).value();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const string logfile = WApplication::appRoot() + string("gpgme.log");
|
||||
WLogger logger;
|
||||
logger.setFile(logfile);
|
||||
logger.entry("") << WLogger::timestamp
|
||||
<< WLogger::sep << subjectCommonName
|
||||
<< WLogger::sep << WApplication::instance()->environment().userAgent()
|
||||
<< WLogger::sep << std::to_string(e.code())
|
||||
<< WLogger::sep << e.asString();
|
||||
}
|
||||
|
||||
#endif /* GPGMELOGGER_H */
|
||||
|
||||
@@ -145,9 +145,38 @@ const Error GpgMEWorker::CertifyKey(const char* fprSigningKey,
|
||||
return e;
|
||||
}
|
||||
|
||||
const Error GpgMEWorker::SetExpiryTime(const char * keyFpr,
|
||||
const string& passphrase,
|
||||
const string& timeString)
|
||||
const Error GpgMEWorker::RevokeKeyCertifications(const char* fprSigningKey,
|
||||
const char* fprKeyToSign,
|
||||
vector<GpgME::UserID>& userIDsToRevoke,
|
||||
const string& passphrase)
|
||||
{
|
||||
Error e;
|
||||
Key signingKey = FindKey(fprSigningKey, e, true);
|
||||
if (e.code() != 0)
|
||||
return e;
|
||||
e = m_ctx->addSigningKey(signingKey); // +++
|
||||
if (e.code() != 0)
|
||||
return e;
|
||||
Key keyToSign = FindKey(fprKeyToSign, e, false);
|
||||
if (e.code() != 0)
|
||||
return e;
|
||||
|
||||
m_ctx->setPinentryMode(Context::PinentryMode::PinentryLoopback);
|
||||
if (m_ppp == NULL)
|
||||
m_ppp = new LoopbackPassphraseProvider();
|
||||
m_ppp->SetPassphrase(passphrase);
|
||||
m_ctx->setPassphraseProvider(m_ppp);
|
||||
|
||||
e = m_ctx->revokeSignature(keyToSign, signingKey, userIDsToRevoke);
|
||||
m_ctx->clearSigningKeys();
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
const Error GpgMEWorker::SetKeyExpiryTime(const char* keyFpr,
|
||||
const char* subkeyFpr,
|
||||
const string& passphrase,
|
||||
ulong expires)
|
||||
{
|
||||
Error e;
|
||||
Key k = FindKey(keyFpr, e, true);
|
||||
@@ -157,17 +186,26 @@ const Error GpgMEWorker::SetExpiryTime(const char * keyFpr,
|
||||
if (e.code() != 0)
|
||||
return e;
|
||||
|
||||
vector<GpgME::Subkey> subkey;
|
||||
for (uint i = 0; i < k.subkeys().size(); i++)
|
||||
{
|
||||
GpgME::Subkey sk = k.subkey(i);
|
||||
if (string(sk.fingerprint()) == string(subkeyFpr))
|
||||
{
|
||||
subkey.push_back(sk);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// There should always be at least one subkey (the key itself).
|
||||
|
||||
m_ctx->setPinentryMode(Context::PinentryMode::PinentryLoopback);
|
||||
if (m_ppp == NULL)
|
||||
m_ppp = new LoopbackPassphraseProvider();
|
||||
m_ppp->SetPassphrase(passphrase);
|
||||
m_ctx->setPassphraseProvider(m_ppp);
|
||||
|
||||
SetExpiryTimeEditInteractor * interactor
|
||||
= new SetExpiryTimeEditInteractor(timeString);
|
||||
GpgME::Data d;
|
||||
e = m_ctx->edit(k, std::unique_ptr<SetExpiryTimeEditInteractor> (interactor), d);
|
||||
m_ctx->clearSigningKeys();
|
||||
// setExpire() allows to expire all subkeys at once. Not implemented here.
|
||||
e = m_ctx->setExpire(k, expires, subkey);
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
@@ -78,13 +78,32 @@ public:
|
||||
vector<uint>& userIDsToSign, int options,
|
||||
const string& passphrase);
|
||||
/**
|
||||
* Set new expiry time of a secret key.
|
||||
* @param timeString
|
||||
* Revoke UserID certifications.
|
||||
* \n Requires GnuPG >= 2.2.24
|
||||
* @param fprSigningKey
|
||||
* @param fprKeyToSign
|
||||
* @param userIDsToRevoke : vector of ::UserID
|
||||
* @param passphrase
|
||||
* @return
|
||||
*/
|
||||
const Error SetExpiryTime(const char * keyFpr,
|
||||
const string& passphrase,
|
||||
const string& timeString = "0");
|
||||
const Error RevokeKeyCertifications(const char * fprSigningKey,
|
||||
const char * fprKeyToSign,
|
||||
vector<GpgME::UserID>& userIDsToRevoke,
|
||||
const string& passphrase);
|
||||
/**
|
||||
* Sets the expiry time of a single (sub)key. Requires GPGME >= 1.15.0.
|
||||
* \n If no subkey is found (wrong fpr) or not provided, the expiry time of
|
||||
* key is set instead.
|
||||
* @param keyFpr
|
||||
* @param subkeyFpr
|
||||
* @param passphrase
|
||||
* @param expires : seconds from now. Use 0 for no expiry.
|
||||
* @return
|
||||
*/
|
||||
const Error SetKeyExpiryTime(const char * keyFpr,
|
||||
const char * subkeyFpr,
|
||||
const string& passphrase,
|
||||
ulong expires = 63072000);
|
||||
/**
|
||||
* Adds a user identity to a key.
|
||||
* \n The email parameter must have a valid email address format here, else
|
||||
@@ -111,8 +130,8 @@ public:
|
||||
* @return
|
||||
*/
|
||||
const Error RevokeUserID(const char * keyFpr, const string& passphrase,
|
||||
const string& name, const string& email,
|
||||
const string& comment);
|
||||
const string& name, const string& email,
|
||||
const string& comment);
|
||||
/**
|
||||
* Creates a pair of secret and public keys with the default engine
|
||||
* algorithms. Default expiry time is 2 * 365 days.
|
||||
@@ -225,20 +244,6 @@ public:
|
||||
|
||||
};
|
||||
|
||||
class SetExpiryTimeEditInteractor : public GpgSetExpiryTimeEditInteractor
|
||||
{
|
||||
public:
|
||||
|
||||
SetExpiryTimeEditInteractor(const std::string& timeString = "0")
|
||||
: GpgSetExpiryTimeEditInteractor(timeString)
|
||||
{
|
||||
};
|
||||
|
||||
virtual ~SetExpiryTimeEditInteractor()
|
||||
{
|
||||
};
|
||||
};
|
||||
|
||||
class AddUserIDEditInteractor : public GpgAddUserIDEditInteractor
|
||||
{
|
||||
public:
|
||||
|
||||
24
K7Main.cpp
24
K7Main.cpp
@@ -21,6 +21,7 @@
|
||||
#include "GpgMECWorker.h"
|
||||
#include "Tools.h"
|
||||
#include "SensitiveTreeTableNodeText.h"
|
||||
#include "GpgMELogger.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -83,7 +84,9 @@ K7Main::Create()
|
||||
WContainerWidget * cwHeader = new WContainerWidget();
|
||||
WHBoxLayout * hblHeader = new WHBoxLayout();
|
||||
cwHeader->setLayout(unique_ptr<WHBoxLayout> (hblHeader));
|
||||
hblHeader->addWidget(cpp14::make_unique<WText>(_APPNAME_));
|
||||
WText * lblTitle =
|
||||
hblHeader->addWidget(cpp14::make_unique<WText>(_APPNAME_));
|
||||
lblTitle->setStyleClass("title");
|
||||
// Error messages will go here
|
||||
m_tmwMessage = new TransientMessageWidget();
|
||||
m_tmwMessage->setTextAlignment(AlignmentFlag::Right);
|
||||
@@ -204,6 +207,7 @@ void K7Main::Search()
|
||||
{
|
||||
privkList.clear();
|
||||
m_tmwMessage->SetText(e.asString());
|
||||
LGE(e);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
@@ -229,6 +233,7 @@ void K7Main::Search()
|
||||
{
|
||||
pubkList.clear();
|
||||
m_tmwMessage->SetText(e.asString());
|
||||
LGE(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -293,6 +298,10 @@ void K7Main::DisplayKeys(const vector<GpgME::Key>& kList, const WString& grpLabe
|
||||
}
|
||||
keyNode->setColumnWidget(2, unique_ptr<WText> (lblOwnerTrust));
|
||||
TreeTableNodeText * ttntFpr = new TreeTableNodeText(k.primaryFingerprint(), keyNode, 3);
|
||||
if (k.isBad())
|
||||
ttntFpr->addStyleClass("red", true);
|
||||
if (!k.hasSecret() && Tools::KeyHasSecret(k.primaryFingerprint()))
|
||||
ttntFpr->addStyleClass("bold", true);
|
||||
keyNode->setColumnWidget(3, unique_ptr<TreeTableNodeText> (ttntFpr));
|
||||
grpNode->addChildNode(unique_ptr<WTreeTableNode> (keyNode));
|
||||
}
|
||||
@@ -328,6 +337,7 @@ void K7Main::DisplayUids(const WString& fullKeyID, bool secret)
|
||||
if (e.code() != 0)
|
||||
{
|
||||
m_tmwMessage->SetText(e.asString());
|
||||
LGE(e);
|
||||
return;
|
||||
}
|
||||
if (m_ttbUids->columnCount() == 1)
|
||||
@@ -355,6 +365,8 @@ void K7Main::DisplayUids(const WString& fullKeyID, bool secret)
|
||||
lblUidEmail->setToolTip(TR("TTTDoubleCLick"));
|
||||
lblUidEmail->doubleClicked().connect(std::bind(&KeyEdit::OnUidEmailClicked, m_keyEdit, uidNode, WString(k.primaryFingerprint())));
|
||||
}
|
||||
if (uid.isBad())
|
||||
lblUidEmail->setStyleClass("red");
|
||||
uidNode->setColumnWidget(1, unique_ptr<WText> (lblUidEmail));
|
||||
// Show key certify popup on double click
|
||||
WText * lblUidValidity = new WText(UidValidities[uid.validity()]);
|
||||
@@ -376,6 +388,8 @@ void K7Main::DisplayUids(const WString& fullKeyID, bool secret)
|
||||
WTreeTableNode * sigNode = new WTreeTableNode(signer);
|
||||
sigNode->setToolTip(Tools::GetSigStatus(sig));
|
||||
TreeTableNodeText * ttntEmail = new TreeTableNodeText(sig.signerEmail(), sigNode, 1);
|
||||
if (sig.isBad())
|
||||
ttntEmail->addStyleClass("red", true);
|
||||
sigNode->setColumnWidget(1, unique_ptr<TreeTableNodeText> (ttntEmail));
|
||||
WString exp = TR("Expiration") + _SPACE_ + _COLON_ + _SPACE_;
|
||||
exp += sig.neverExpires() ? TR("Never") : MakeDateTimeLabel(sig.expirationTime());
|
||||
@@ -398,6 +412,7 @@ void K7Main::DisplaySubKeys(const WString& fullKeyID, bool secret)
|
||||
if (e.code() != 0)
|
||||
{
|
||||
m_tmwMessage->SetText(e.asString());
|
||||
LGE(e);
|
||||
return;
|
||||
}
|
||||
if (m_ttbSubKeys->columnCount() == 1)
|
||||
@@ -422,13 +437,18 @@ void K7Main::DisplaySubKeys(const WString& fullKeyID, bool secret)
|
||||
WTreeTableNode * skNode = new WTreeTableNode(sk.keyID());
|
||||
skNode->setToolTip(Tools::GetKeyStatus(k));
|
||||
TreeTableNodeText * ttntFpr = new TreeTableNodeText(sk.fingerprint(), skNode, 1);
|
||||
if (sk.isBad())
|
||||
ttntFpr->setStyleClass("red");
|
||||
skNode->setColumnWidget(1, unique_ptr<TreeTableNodeText> (ttntFpr));
|
||||
WString exp = sk.neverExpires() ? TR("Never") : MakeDateTimeLabel(sk.expirationTime());
|
||||
WText * lblExpiry = new WText(exp);
|
||||
if (canEditExpiry)
|
||||
{
|
||||
lblExpiry->setToolTip(TR("TTTDoubleCLick"));
|
||||
lblExpiry->doubleClicked().connect(std::bind(&KeyEdit::OnExpiryClicked, m_keyEdit, skNode, WString(k.primaryFingerprint())));
|
||||
lblExpiry->doubleClicked().connect(std::bind(&KeyEdit::OnExpiryClicked,
|
||||
m_keyEdit, skNode,
|
||||
WString(k.primaryFingerprint()),
|
||||
WString(sk.fingerprint())));
|
||||
}
|
||||
skNode->setColumnWidget(2, unique_ptr<WText> (lblExpiry));
|
||||
WString usage = sk.canAuthenticate() ? WString("A") : WString::Empty;
|
||||
|
||||
91
KeyEdit.cpp
91
KeyEdit.cpp
@@ -13,6 +13,7 @@
|
||||
#include <Wt/WStandardItem.h>
|
||||
#include "GpgMEWorker.h"
|
||||
#include "Tools.h"
|
||||
#include "GpgMELogger.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -20,7 +21,7 @@ KeyEdit::KeyEdit(K7Main * owner)
|
||||
: WObject()
|
||||
{
|
||||
m_owner = owner;
|
||||
m_popupUid = NULL;
|
||||
m_popupCertifyUid = NULL;
|
||||
m_popupExpiryTime = NULL;
|
||||
m_popupAddUid = NULL;
|
||||
m_targetUidValidityKeyFpr = WString::Empty;
|
||||
@@ -29,7 +30,7 @@ KeyEdit::KeyEdit(K7Main * owner)
|
||||
|
||||
KeyEdit::~KeyEdit()
|
||||
{
|
||||
delete m_popupUid;
|
||||
delete m_popupCertifyUid;
|
||||
}
|
||||
|
||||
void KeyEdit::OnOwnerTrustDoubleClicked(WTreeTableNode * keyNode, bool keyHasSecret)
|
||||
@@ -91,6 +92,7 @@ void KeyEdit::OnOwnerTrustBlurred(WTreeTableNode* keyNode, bool keyHasSecret)
|
||||
{
|
||||
lblOwnerTrust->setText(previousTrustLevel);
|
||||
m_owner->m_tmwMessage->SetText(TR("OwnerTrustFailure"));
|
||||
LGE(e);
|
||||
return;
|
||||
}
|
||||
m_owner->m_tmwMessage->SetText(TR("OwnerTrustSuccess"));
|
||||
@@ -130,47 +132,65 @@ void KeyEdit::OnUidValidityClicked(WTreeTableNode* uidNode, vector<WString>& pri
|
||||
if (targetKeyFpr != m_targetUidValidityKeyFpr)
|
||||
{
|
||||
bool passwordVisibility = true;
|
||||
if (m_popupUid)
|
||||
passwordVisibility = m_popupUid->IsPasswordVisible();
|
||||
delete m_popupUid;
|
||||
if (m_popupCertifyUid)
|
||||
passwordVisibility = m_popupCertifyUid->IsPasswordVisible();
|
||||
delete m_popupCertifyUid;
|
||||
WText * lblUidValidity = static_cast<WText*> (uidNode->columnWidget(2));
|
||||
m_popupUid = new PopupCertifyUserId(lblUidValidity, m_owner->m_tmwMessage);
|
||||
m_popupUid->Create(privateKeys, targetKeyFpr);
|
||||
m_popupUid->ShowPassphrase(passwordVisibility);
|
||||
m_popupCertifyUid = new PopupCertifyUserId(lblUidValidity, m_owner->m_tmwMessage);
|
||||
m_popupCertifyUid->Create(privateKeys, targetKeyFpr);
|
||||
m_popupCertifyUid->ShowPassphrase(passwordVisibility);
|
||||
m_targetUidValidityKeyFpr = targetKeyFpr;
|
||||
m_popupUid->GetCertifyButton()->clicked().connect(this, &KeyEdit::CertifyKey);
|
||||
m_popupCertifyUid->GetCertifyButton()->clicked().connect(this, &KeyEdit::EditUidValidity);
|
||||
}
|
||||
m_popupUid->show();
|
||||
m_popupCertifyUid->show();
|
||||
}
|
||||
|
||||
void KeyEdit::CertifyKey()
|
||||
void KeyEdit::EditUidValidity()
|
||||
{
|
||||
vector<uint>& uidsToSign = m_popupUid->GetUidsToSign();
|
||||
if (uidsToSign.size() == 0)
|
||||
if (!m_popupCertifyUid->Validate())
|
||||
{
|
||||
m_owner->m_tmwMessage->SetText(TR("NoUidSelected"));
|
||||
m_owner->m_tmwMessage->SetText(TR("InvalidInput"));
|
||||
return;
|
||||
}
|
||||
const WString signingKey = m_popupUid->GetSelectedKey();
|
||||
const WString keyToSign = m_popupUid->GetKeyToSign();
|
||||
int options = m_popupUid->GetCertifyOptions();
|
||||
const WString signingKey = m_popupCertifyUid->GetSelectedKey();
|
||||
const WString keyToSign = m_popupCertifyUid->GetKeyToSign();
|
||||
GpgMEWorker gpgWorker;
|
||||
GpgME::Error e = gpgWorker.CertifyKey(signingKey.toUTF8().c_str(),
|
||||
keyToSign.toUTF8().c_str(),
|
||||
uidsToSign, options,
|
||||
m_popupUid->GetPassphrase());
|
||||
GpgME::Error e;
|
||||
if (m_popupCertifyUid->WhatToDo() == PopupCertifyUserId::CertifyUid)
|
||||
{
|
||||
vector<uint>& uidsToSign = m_popupCertifyUid->GetUidsToSign();
|
||||
int options = m_popupCertifyUid->GetCertifyOptions();
|
||||
e = gpgWorker.CertifyKey(signingKey.toUTF8().c_str(),
|
||||
keyToSign.toUTF8().c_str(),
|
||||
uidsToSign, options,
|
||||
m_popupCertifyUid->GetPassphrase());
|
||||
}
|
||||
else
|
||||
{
|
||||
vector<GpgME::UserID> uidsToRevoke
|
||||
= m_popupCertifyUid->GetUidsToRevokeCertification();
|
||||
e = gpgWorker.RevokeKeyCertifications(signingKey.toUTF8().c_str(),
|
||||
keyToSign.toUTF8().c_str(),
|
||||
uidsToRevoke,
|
||||
m_popupCertifyUid->GetPassphrase());
|
||||
}
|
||||
if (e.code() != 0)
|
||||
{
|
||||
m_owner->m_tmwMessage->SetText(TR("CertificationFailure"));
|
||||
m_popupUid->ShowPassphrase(true);
|
||||
m_owner->m_tmwMessage->SetText(e.asString());
|
||||
m_popupCertifyUid->ShowPassphrase(true);
|
||||
LGE(e);
|
||||
return;
|
||||
}
|
||||
m_owner->m_tmwMessage->SetText(TR("CertificationSuccess"));
|
||||
m_popupUid->ShowPassphrase(false);
|
||||
if (m_popupCertifyUid->WhatToDo() == PopupCertifyUserId::CertifyUid)
|
||||
m_owner->m_tmwMessage->SetText(TR("CertificationSuccess"));
|
||||
else
|
||||
m_owner->m_tmwMessage->SetText(TR("RevocationSuccess"));
|
||||
m_popupCertifyUid->ShowPassphrase(false);
|
||||
m_owner->DisplayUids(keyToSign);
|
||||
}
|
||||
|
||||
void KeyEdit::OnExpiryClicked(WTreeTableNode* subkeyNode, const WString& keyFpr)
|
||||
void KeyEdit::OnExpiryClicked(WTreeTableNode* subkeyNode, const WString& keyFpr,
|
||||
const WString& subkeyFpr)
|
||||
{
|
||||
if (keyFpr != m_expiryEditedKeyFpr)
|
||||
{
|
||||
@@ -179,21 +199,29 @@ void KeyEdit::OnExpiryClicked(WTreeTableNode* subkeyNode, const WString& keyFpr)
|
||||
m_popupExpiryTime = new PopupExpiryTime(lblExpiry, m_owner->m_tmwMessage);
|
||||
m_popupExpiryTime->Create(keyFpr);
|
||||
m_expiryEditedKeyFpr = keyFpr;
|
||||
m_popupExpiryTime->GetApplyButton()->clicked().connect(this, &KeyEdit::SetExpiryTime);
|
||||
m_popupExpiryTime->GetApplyButton()->clicked().connect(this, &KeyEdit::SetKeyExpiryTime);
|
||||
}
|
||||
m_popupExpiryTime->SetSubkeyFpr(subkeyFpr);
|
||||
m_popupExpiryTime->show();
|
||||
}
|
||||
|
||||
void KeyEdit::SetExpiryTime()
|
||||
void KeyEdit::SetKeyExpiryTime()
|
||||
{
|
||||
GpgMEWorker gpgWorker;
|
||||
GpgME::Error e = gpgWorker.SetExpiryTime(m_expiryEditedKeyFpr.toUTF8().c_str(),
|
||||
m_popupExpiryTime->GetPassphrase(),
|
||||
m_popupExpiryTime->GetExpiryTime());
|
||||
GpgME::Error e;
|
||||
const WString keyFpr = m_popupExpiryTime->GetKeyFpr();
|
||||
WString subkeyFpr = m_popupExpiryTime->GetSubkeyFpr();
|
||||
if (keyFpr == subkeyFpr)
|
||||
subkeyFpr = WString::Empty;
|
||||
e = gpgWorker.SetKeyExpiryTime(keyFpr.toUTF8().c_str(),
|
||||
subkeyFpr.toUTF8().c_str(),
|
||||
m_popupExpiryTime->GetPassphrase(),
|
||||
m_popupExpiryTime->GetExpiry());
|
||||
if (e.code() != 0)
|
||||
{
|
||||
m_owner->m_tmwMessage->SetText(TR("SetExpirationTimeFailure"));
|
||||
m_popupExpiryTime->ShowPassphrase(true);
|
||||
LGE(e);
|
||||
return;
|
||||
}
|
||||
m_owner->m_tmwMessage->SetText(TR("SetExpirationTimeSuccess"));
|
||||
@@ -250,6 +278,7 @@ void KeyEdit::AddOrRevokeUid()
|
||||
{
|
||||
m_popupAddUid->ShowPassphrase(true);
|
||||
m_owner->m_tmwMessage->SetText(e.asString());
|
||||
LGE(e);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ private:
|
||||
virtual ~KeyEdit();
|
||||
|
||||
K7Main * m_owner;
|
||||
PopupCertifyUserId * m_popupUid;
|
||||
PopupCertifyUserId * m_popupCertifyUid;
|
||||
WString m_targetUidValidityKeyFpr;
|
||||
|
||||
PopupExpiryTime * m_popupExpiryTime;
|
||||
@@ -57,8 +57,8 @@ private:
|
||||
* @param keyHasSecret
|
||||
*/
|
||||
void FillOwnerTrustCombo(WComboBox * cmb, bool keyHasSecret);
|
||||
void CertifyKey();
|
||||
void SetExpiryTime();
|
||||
void EditUidValidity();
|
||||
void SetKeyExpiryTime();
|
||||
void AddOrRevokeUid();
|
||||
|
||||
/**
|
||||
@@ -85,7 +85,8 @@ private:
|
||||
* @param subkeyNode
|
||||
* @param keyFpr
|
||||
*/
|
||||
void OnExpiryClicked(WTreeTableNode * subkeyNode, const WString& keyFpr);
|
||||
void OnExpiryClicked(WTreeTableNode * subkeyNode, const WString& keyFpr,
|
||||
const WString& subkeyFpr);
|
||||
|
||||
void OnUidEmailClicked(WTreeTableNode * uidNode, const WString& keyFpr);
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "Tools.h"
|
||||
#include <Wt/WLink.h>
|
||||
#include <strstream>
|
||||
#include "GpgMELogger.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -81,6 +82,7 @@ void KeyringIO::DoImportKey()
|
||||
if (e.code() != 0)
|
||||
{
|
||||
m_tmwMessage->SetText(e.asString());
|
||||
LGE(e);
|
||||
return;
|
||||
}
|
||||
if (fpr.empty())
|
||||
@@ -93,6 +95,7 @@ void KeyringIO::DoImportKey()
|
||||
if (e.code() != 0)
|
||||
{
|
||||
m_tmwMessage->SetText(e.asString());
|
||||
LGE(e);
|
||||
return;
|
||||
}
|
||||
m_tmwMessage->SetText(TR("ImportSuccess") + fpr + WString(" - ") + WString(k.userID(0).name()));
|
||||
@@ -111,6 +114,7 @@ bool KeyringIO::CanKeyBeDeleted(const WString& fullKeyID)
|
||||
if (e.code() != 0 && e.code() != 16383)
|
||||
{ // 16383 : end of file, when key is not private
|
||||
m_tmwMessage->SetText(e.asString());
|
||||
LGE(e);
|
||||
return false;
|
||||
}
|
||||
// k can now be secret or public
|
||||
@@ -168,6 +172,7 @@ void KeyringIO::DoDeleteKey()
|
||||
if (e.code() != 0)
|
||||
{
|
||||
m_tmwMessage->SetText(e.asString());
|
||||
LGE(e);
|
||||
return;
|
||||
}
|
||||
// Delete the key using the C API
|
||||
@@ -234,6 +239,7 @@ void KeyringIO::DoCreateKey()
|
||||
if (e.code() != 0)
|
||||
{
|
||||
m_tmwMessage->SetText(e.asString());
|
||||
LGE(e);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -337,21 +343,19 @@ void ExportKeyStreamResource::handleRequest(const Http::Request& request,
|
||||
*/
|
||||
|
||||
string buffer;
|
||||
if (!request.continuation()) // Needed for WStreamResource ?
|
||||
{
|
||||
Error e;
|
||||
GpgMEWorker gpgw;
|
||||
e = m_isSecret
|
||||
Error e;
|
||||
GpgMEWorker gpgw;
|
||||
e = m_isSecret
|
||||
? gpgw.ExportPrivateKey(m_fpr.toUTF8().c_str(), buffer,
|
||||
m_passphrase.toUTF8())
|
||||
: gpgw.ExportPublicKey(m_fpr.toUTF8().c_str(), buffer);
|
||||
if (e.code() != 0)
|
||||
{
|
||||
m_tmwMessage->SetText(e.asString());
|
||||
return;
|
||||
}
|
||||
suggestFileName(m_fpr + WString(".asc"), ContentDisposition::Attachment);
|
||||
if (e.code() != 0)
|
||||
{
|
||||
m_tmwMessage->SetText(e.asString());
|
||||
LGE(e);
|
||||
return;
|
||||
}
|
||||
suggestFileName(m_fpr + WString(".asc"), ContentDisposition::Attachment);
|
||||
|
||||
istrstream bufStream(buffer.c_str());
|
||||
handleRequestPiecewise(request, response, bufStream);
|
||||
|
||||
@@ -12,7 +12,10 @@
|
||||
#include "Tools.h"
|
||||
#include <Wt/WStandardItem.h>
|
||||
#include <Wt/WStandardItemModel.h>
|
||||
#include <Wt/WRadioButton.h>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include "GpgMELogger.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -26,6 +29,7 @@ PopupCertifyUserId::PopupCertifyUserId(WWidget * anchorWidget, TransientMessageW
|
||||
m_cbOptionExportable = NULL;
|
||||
m_cbOptionNonRevocable = NULL;
|
||||
// m_cbOptionTrust = NULL;
|
||||
m_cbConfirm = NULL;
|
||||
m_lblPassphrase = NULL;
|
||||
m_lePassphrase = NULL;
|
||||
m_btnApply = NULL;
|
||||
@@ -63,10 +67,10 @@ void PopupCertifyUserId::Create(vector<WString>& privateKeys,
|
||||
m_hblPreferences->addLayout(unique_ptr<WVBoxLayout> (m_vblEmail));
|
||||
PresentEmail();
|
||||
// Column 1
|
||||
m_gbOptions = new WGroupBox(TR("Options"));
|
||||
WVBoxLayout * vblOptions = new WVBoxLayout();
|
||||
m_hblPreferences->addLayout(unique_ptr<WVBoxLayout> (vblOptions));
|
||||
WText * lblOptions = new WText(TR("Options"));
|
||||
vblOptions->addWidget(unique_ptr<WText> (lblOptions));
|
||||
m_gbOptions->setLayout(unique_ptr<WVBoxLayout> (vblOptions));
|
||||
m_hblPreferences->addWidget(unique_ptr<WGroupBox> (m_gbOptions));
|
||||
m_cbOptionExportable = new WCheckBox(TR("ExportableCertification"));
|
||||
m_cbOptionExportable->setToolTip(TR("OneWayHint"));
|
||||
vblOptions->addWidget(unique_ptr<WCheckBox> (m_cbOptionExportable));
|
||||
@@ -74,7 +78,7 @@ void PopupCertifyUserId::Create(vector<WString>& privateKeys,
|
||||
m_cbOptionNonRevocable->setToolTip(TR("OneWayHint"));
|
||||
vblOptions->addWidget(unique_ptr<WCheckBox> (m_cbOptionNonRevocable));
|
||||
/*m_cbOptionTrust = new WCheckBox(TR("TrustCertification"));
|
||||
vblOptions->addWidget(unique_ptr<WCheckBox> (m_cbOptionTrust));*/
|
||||
gbOptions->addWidget(unique_ptr<WCheckBox> (m_cbOptionTrust));*/
|
||||
|
||||
WHBoxLayout * hblPassphrase = new WHBoxLayout();
|
||||
m_lblPassphrase = new WText(TR("Passphrase"));
|
||||
@@ -84,6 +88,21 @@ void PopupCertifyUserId::Create(vector<WString>& privateKeys,
|
||||
hblPassphrase->addWidget(unique_ptr<WLineEdit> (m_lePassphrase), 1);
|
||||
vblMain->addLayout(unique_ptr<WHBoxLayout> (hblPassphrase));
|
||||
|
||||
WHBoxLayout * hblWhat = new WHBoxLayout();
|
||||
WRadioButton * rbCertifyUid = new WRadioButton(TR("CertifyUid"));
|
||||
hblWhat->addWidget(unique_ptr<WRadioButton> (rbCertifyUid));
|
||||
WRadioButton * rbRevokeCertification =
|
||||
new WRadioButton(TR("RevokeUidCertification"));
|
||||
hblWhat->addWidget(unique_ptr<WRadioButton> (rbRevokeCertification));
|
||||
m_bgWhat = make_shared<WButtonGroup>();
|
||||
m_bgWhat->addButton(rbCertifyUid, What::CertifyUid);
|
||||
m_bgWhat->addButton(rbRevokeCertification, What::RevokeUidCertification);
|
||||
m_bgWhat->setCheckedButton(rbCertifyUid);
|
||||
vblMain->addLayout(unique_ptr<WHBoxLayout> (hblWhat));
|
||||
|
||||
m_cbConfirm = new WCheckBox(TR("Confirm"));
|
||||
vblMain->addWidget(unique_ptr<WCheckBox> (m_cbConfirm));
|
||||
|
||||
WHBoxLayout * hblButtons = new WHBoxLayout();
|
||||
WPushButton * btnClose = new WPushButton(TR("Close"));
|
||||
hblButtons->addWidget(unique_ptr<WPushButton> (btnClose));
|
||||
@@ -99,6 +118,7 @@ void PopupCertifyUserId::Create(vector<WString>& privateKeys,
|
||||
m_cbOptionNonRevocable->unChecked().connect(std::bind(&PopupCertifyUserId::OnCertifyOptionUnChecked, this, 2));
|
||||
// m_cbOptionTrust->unChecked().connect(std::bind(&PopupCertifyUserId::OnCertifyOptionUnChecked, this, 4));
|
||||
btnClose->clicked().connect(this, &WPopupWidget::hide);
|
||||
m_bgWhat->checkedChanged().connect(this, &PopupCertifyUserId::OnButtonGroupWhat);
|
||||
}
|
||||
|
||||
void PopupCertifyUserId::FillPrivateKeyComboBox(vector<WString>& privateKeys)
|
||||
@@ -116,6 +136,7 @@ void PopupCertifyUserId::FillPrivateKeyComboBox(vector<WString>& privateKeys)
|
||||
if (e.code() != 0)
|
||||
{
|
||||
m_tmwMessage->SetText(e.asString());
|
||||
LGE(e);
|
||||
return;
|
||||
}
|
||||
/*
|
||||
@@ -158,6 +179,7 @@ void PopupCertifyUserId::PresentEmail()
|
||||
if (e.code() != 0)
|
||||
{
|
||||
m_tmwMessage->SetText(e.asString());
|
||||
LGE(e);
|
||||
return;
|
||||
}
|
||||
if (lst.size() != 1)
|
||||
@@ -175,8 +197,8 @@ void PopupCertifyUserId::PresentEmail()
|
||||
WCheckBox * cbEmail = new WCheckBox(it->email());
|
||||
m_vblEmail->addWidget(unique_ptr<WCheckBox> (cbEmail));
|
||||
cbEmail->setId(std::to_string(id));
|
||||
cbEmail->checked().connect(std::bind(&PopupCertifyUserId::OnEmailChecked, this, cbEmail));
|
||||
cbEmail->unChecked().connect(std::bind(&PopupCertifyUserId::OnEmailUnChecked, this, cbEmail));
|
||||
cbEmail->checked().connect(std::bind(&PopupCertifyUserId::OnEmailChecked, this, cbEmail, (*it)));
|
||||
cbEmail->unChecked().connect(std::bind(&PopupCertifyUserId::OnEmailUnChecked, this, cbEmail, (*it)));
|
||||
id++;
|
||||
}
|
||||
}
|
||||
@@ -220,25 +242,32 @@ void PopupCertifyUserId::ShowPassphrase(bool show)
|
||||
}
|
||||
}
|
||||
|
||||
void PopupCertifyUserId::OnEmailChecked(WCheckBox* cb)
|
||||
void PopupCertifyUserId::OnEmailChecked(WCheckBox* cb, GpgME::UserID& uid)
|
||||
{
|
||||
int id = Tools::ToInt(cb->id());
|
||||
m_uidsToSign.push_back(id);
|
||||
m_uidsToRevokeCertification.push_back(uid);
|
||||
}
|
||||
|
||||
void PopupCertifyUserId::OnEmailUnChecked(WCheckBox* cb)
|
||||
void PopupCertifyUserId::OnEmailUnChecked(WCheckBox* cb, GpgME::UserID& uid)
|
||||
{
|
||||
// Any tip to locate a known value in a vector without iterating over?
|
||||
const uint id = Tools::ToInt(cb->id());
|
||||
vector<uint>::iterator it;
|
||||
for (it = m_uidsToSign.begin(); it != m_uidsToSign.end(); it++)
|
||||
vector<uint>::iterator it =
|
||||
std::find(m_uidsToSign.begin(), m_uidsToSign.end(), id);
|
||||
if (it != m_uidsToSign.end())
|
||||
m_uidsToSign.erase(it);
|
||||
|
||||
vector<GpgME::UserID>::iterator uit;
|
||||
for (uit = m_uidsToRevokeCertification.begin();
|
||||
uit != m_uidsToRevokeCertification.end(); uit++)
|
||||
{
|
||||
if ((*it) == id)
|
||||
if ((*uit).uidhash() == uid.uidhash())
|
||||
{
|
||||
m_uidsToSign.erase(it);
|
||||
return;
|
||||
m_uidsToRevokeCertification.erase(uit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PopupCertifyUserId::OnCertifyOptionChecked(int id)
|
||||
@@ -250,3 +279,27 @@ void PopupCertifyUserId::OnCertifyOptionUnChecked(int id)
|
||||
{
|
||||
m_certifyOptions -= id;
|
||||
}
|
||||
|
||||
void PopupCertifyUserId::OnButtonGroupWhat(WRadioButton* btn)
|
||||
{
|
||||
m_gbOptions->setDisabled(m_bgWhat->checkedId()
|
||||
== What::RevokeUidCertification);
|
||||
|
||||
}
|
||||
|
||||
bool PopupCertifyUserId::Validate() const
|
||||
{
|
||||
if (!m_cbConfirm->isChecked() || m_lePassphrase->text().empty())
|
||||
return false;
|
||||
if (m_bgWhat->checkedId() == What::CertifyUid)
|
||||
{
|
||||
if (m_uidsToSign.size() == 0)
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_uidsToRevokeCertification.size() == 0)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -19,28 +19,32 @@
|
||||
#include <Wt/WLineEdit.h>
|
||||
#include <Wt/WVBoxLayout.h>
|
||||
#include <Wt/WHBoxLayout.h>
|
||||
#include <Wt/WGroupBox.h>
|
||||
#include <Wt/WButtonGroup.h>
|
||||
#include <vector>
|
||||
#include <gpgme++/key.h>
|
||||
#include "TransientMessageWidget.h"
|
||||
|
||||
using namespace Wt;
|
||||
|
||||
/**
|
||||
* A popup with required parameters to certify a key :
|
||||
* A popup with required parameters to certify or revoke a key uid :
|
||||
* <ul>
|
||||
* <li>Signer's private keys</li>
|
||||
* <li>Target key user identities (email)</li>
|
||||
* <li>Signing options : Exportable and non-revocable</li>
|
||||
* <li>Passphrase for selected private key</li>
|
||||
* </ul>
|
||||
* The passphrase is cached by gpg-agent for default 10 mins.
|
||||
* \n The popup hides the passphrase widget until a certify op fails.
|
||||
* \n UserID::Validity:: lists many validity levels. How to selectively apply
|
||||
* an arbitrary level ? Before signing, it's 'Unknown'. After signing, it's
|
||||
* always 'Full'.
|
||||
* \n For revocation, GnuPG >= 2.2.24 is required.
|
||||
*/
|
||||
class PopupCertifyUserId : public WPopupWidget
|
||||
{
|
||||
public:
|
||||
|
||||
enum What
|
||||
{
|
||||
RevokeUidCertification = 0, CertifyUid
|
||||
};
|
||||
PopupCertifyUserId(WWidget * anchorWidget, TransientMessageWidget * txtMessage,
|
||||
const WLength& width = 500);
|
||||
virtual ~PopupCertifyUserId();
|
||||
@@ -102,6 +106,27 @@ public:
|
||||
return m_uidsToSign;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the certifications to revoke.
|
||||
* \n GPGME >= 1.15.0 is required. It expects
|
||||
* it as a vector of GpgME::UserID, instead of a vector of indices used in
|
||||
* GetUidsToSign().
|
||||
* @return
|
||||
*/
|
||||
vector<GpgME::UserID>& GetUidsToRevokeCertification()
|
||||
{
|
||||
return m_uidsToRevokeCertification;
|
||||
}
|
||||
|
||||
/**
|
||||
* Certify selected user identities or revoke certifications.
|
||||
* @return
|
||||
*/
|
||||
const What WhatToDo() const
|
||||
{
|
||||
return (What) m_bgWhat->checkedId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sum of option values
|
||||
* <ul>
|
||||
@@ -124,6 +149,11 @@ public:
|
||||
{
|
||||
return m_btnApply;
|
||||
}
|
||||
/**
|
||||
* Check required parameters are set and confirmed.
|
||||
* @return
|
||||
*/
|
||||
bool Validate() const;
|
||||
private:
|
||||
TransientMessageWidget * m_tmwMessage;
|
||||
WContainerWidget * m_cwMain;
|
||||
@@ -138,10 +168,14 @@ private:
|
||||
// WCheckBox * m_cbOptionTrust; // Always fails
|
||||
WText * m_lblPassphrase;
|
||||
WLineEdit * m_lePassphrase;
|
||||
WCheckBox * m_cbConfirm;
|
||||
WPushButton * m_btnApply;
|
||||
|
||||
vector<uint> m_uidsToSign;
|
||||
vector<GpgME::UserID> m_uidsToRevokeCertification;
|
||||
int m_certifyOptions;
|
||||
WGroupBox * m_gbOptions;
|
||||
shared_ptr<WButtonGroup> m_bgWhat;
|
||||
/**
|
||||
* Available private fingerprints in a combobox. The selected item is the
|
||||
* signing key.
|
||||
@@ -154,15 +188,17 @@ private:
|
||||
*/
|
||||
void PresentEmail();
|
||||
/**
|
||||
* Add the identity index in a vector.
|
||||
* Add the identity index in a vector for certification.
|
||||
* \n Add the ::UserID in a vector for signature revocation.
|
||||
* @param cb
|
||||
*/
|
||||
void OnEmailChecked(WCheckBox * cb);
|
||||
void OnEmailChecked(WCheckBox * cb, GpgME::UserID& uid);
|
||||
/**
|
||||
* Removes the identity index in a vector.
|
||||
* Removes the identity index from a vector for certification.
|
||||
* \n Removes the ::UserID from a vector for signature revocation.
|
||||
* @param cb
|
||||
*/
|
||||
void OnEmailUnChecked(WCheckBox * cb);
|
||||
void OnEmailUnChecked(WCheckBox * cb, GpgME::UserID& uid);
|
||||
/**
|
||||
* Adds the option value in m_certifyOptions.
|
||||
* @param id
|
||||
@@ -173,6 +209,11 @@ private:
|
||||
* @param id
|
||||
*/
|
||||
void OnCertifyOptionUnChecked(int id);
|
||||
/**
|
||||
* Show certification options if certifying, else hide them.
|
||||
* @param btn
|
||||
*/
|
||||
void OnButtonGroupWhat(WRadioButton * btn);
|
||||
};
|
||||
|
||||
#endif /* POPUPCERTIFYUSERID_H */
|
||||
|
||||
@@ -22,6 +22,7 @@ PopupExpiryTime::PopupExpiryTime(WWidget * anchorWidget, TransientMessageWidget
|
||||
m_tmwMessage = txtMessage;
|
||||
m_cwMain = NULL;
|
||||
m_keyFpr = WString::Empty;
|
||||
m_subkeyFpr = WString::Empty;
|
||||
/*
|
||||
* Trade-off.
|
||||
* When the calendar of WDateEdit is clicked, this popup gets hidden,
|
||||
@@ -82,6 +83,11 @@ const string PopupExpiryTime::GetExpiryTime() const
|
||||
return m_deExpiry->text().toUTF8();
|
||||
}
|
||||
|
||||
const ulong PopupExpiryTime::GetExpiry() const
|
||||
{
|
||||
return ((WDate::currentDate().daysTo(m_deExpiry->date())) * 24 * 3600);
|
||||
}
|
||||
|
||||
void PopupExpiryTime::ShowPassphrase(bool show)
|
||||
{
|
||||
// See comments in PopupCertifyUserId::ShowPassphrase
|
||||
|
||||
@@ -23,9 +23,24 @@ class PopupExpiryTime : public WPopupWidget
|
||||
{
|
||||
public:
|
||||
PopupExpiryTime(WWidget * anchorWidget, TransientMessageWidget * txtMessage,
|
||||
const WLength& width = 300);
|
||||
const WLength& width = 300);
|
||||
virtual ~PopupExpiryTime();
|
||||
void Create(const WString& keyFpr);
|
||||
|
||||
const WString GetKeyFpr()
|
||||
{
|
||||
return m_keyFpr;
|
||||
}
|
||||
|
||||
void SetSubkeyFpr(const WString& subkeyFpr)
|
||||
{
|
||||
m_subkeyFpr = subkeyFpr;
|
||||
}
|
||||
|
||||
const WString GetSubkeyFpr()
|
||||
{
|
||||
return m_subkeyFpr;
|
||||
}
|
||||
/**
|
||||
* Controls visibility of passphrase widgets.
|
||||
* \n Need not be always visible as the passphrase is cached by gpg-agent.
|
||||
@@ -34,6 +49,7 @@ public:
|
||||
* @param show
|
||||
*/
|
||||
void ShowPassphrase(bool show = true);
|
||||
|
||||
/**
|
||||
* Used to forward the passphrase to the loopback passphrase provider.
|
||||
* @return
|
||||
@@ -43,9 +59,15 @@ public:
|
||||
return m_lePassphrase->text().toUTF8();
|
||||
}
|
||||
/**
|
||||
* Returns the new expiry date.
|
||||
* Returns the new expiry date, or 0 if date is invalid.
|
||||
*/
|
||||
const std::string GetExpiryTime() const;
|
||||
/**
|
||||
* Number of seconds from now.
|
||||
* @return
|
||||
*/
|
||||
const ulong GetExpiry() const;
|
||||
|
||||
/**
|
||||
* Caller binds its function here.
|
||||
* @return
|
||||
@@ -54,7 +76,7 @@ public:
|
||||
{
|
||||
return m_btnApply;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
TransientMessageWidget * m_tmwMessage;
|
||||
WContainerWidget * m_cwMain;
|
||||
@@ -63,6 +85,7 @@ private:
|
||||
WPushButton * m_btnApply;
|
||||
WText * m_lblPassphrase;
|
||||
WString m_keyFpr;
|
||||
WString m_subkeyFpr;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@ void TreeTableNodeText::OnClick()
|
||||
m_lineEdit->setReadOnly(true);
|
||||
m_lineEdit->blurred().connect(m_lineEdit, &TreeTableNodeLineEdit::OnBlurred);
|
||||
m_lineEdit->setSelection(0, text().toUTF8().length());
|
||||
m_lineEdit->HoldSourceWidget(removeFromParent());
|
||||
m_node->setColumnWidget(m_colIndex, unique_ptr<WLineEdit> (m_lineEdit));
|
||||
m_lineEdit->setFocus(true); // +++
|
||||
}
|
||||
@@ -78,13 +79,15 @@ void TreeTableNodeLineEdit::Init(WTreeTableNode* node, uint colIndex)
|
||||
{
|
||||
m_node = node;
|
||||
m_colIndex = colIndex;
|
||||
m_text = NULL;
|
||||
clicked().connect(this, &TreeTableNodeLineEdit::OnBlurred);
|
||||
}
|
||||
|
||||
void TreeTableNodeLineEdit::OnBlurred()
|
||||
{
|
||||
m_text = new TreeTableNodeText(text(), m_node, m_colIndex);
|
||||
m_text->clicked().connect(m_text, &TreeTableNodeText::OnClick);
|
||||
m_node->setColumnWidget(m_colIndex, unique_ptr<TreeTableNodeText> (m_text));
|
||||
m_node->setColumnWidget(m_colIndex, std::move(m_sourceWidget));
|
||||
}
|
||||
|
||||
void TreeTableNodeLineEdit::HoldSourceWidget(std::unique_ptr<WWidget> sourceWidget)
|
||||
{
|
||||
m_sourceWidget.swap(sourceWidget);
|
||||
}
|
||||
|
||||
@@ -58,13 +58,19 @@ public:
|
||||
WTreeTableNode * node, uint colIndex);
|
||||
virtual ~TreeTableNodeLineEdit();
|
||||
/**
|
||||
* Creates back a TreeTableNodeText replacing this TreeTableNodeLineEdit.
|
||||
* Move back the original TreeTableNodeText replacing this
|
||||
* TreeTableNodeLineEdit.
|
||||
*/
|
||||
void OnBlurred();
|
||||
/**
|
||||
* Keep the original TreeTableNodeText verbatim.
|
||||
* @param text
|
||||
*/
|
||||
void HoldSourceWidget(std::unique_ptr<WWidget> sourceWidget);
|
||||
private:
|
||||
WTreeTableNode * m_node;
|
||||
uint m_colIndex;
|
||||
TreeTableNodeText * m_text;
|
||||
std::unique_ptr<WWidget> m_sourceWidget;
|
||||
|
||||
void Init(WTreeTableNode * node, uint colIndex);
|
||||
};
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "Tools.h"
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include "GpgMELogger.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -101,6 +102,7 @@ bool Tools::KeyHasSecret(const WString& fpr)
|
||||
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
|
||||
LGE(e);
|
||||
return false;
|
||||
}
|
||||
return (!k.isNull());
|
||||
|
||||
@@ -6,5 +6,15 @@
|
||||
* are all 0.
|
||||
*/
|
||||
div.popup {
|
||||
background-color: lavender;
|
||||
background-color: floralwhite;
|
||||
}
|
||||
div.red {
|
||||
color: red;
|
||||
}
|
||||
div.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
span.title {
|
||||
font-size: 125%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@@ -83,8 +83,10 @@
|
||||
<message id='NoUidSelected'>No email address is selected</message>
|
||||
<message id='Apply'>Apply</message>
|
||||
<message id='CertificationSuccess'>Key succesfully certified</message>
|
||||
<message id='CertificationFailure'>Key certification failed</message>
|
||||
<message id='RevocationSuccess'>Identity certification succesfully revoked</message>
|
||||
<message id='OneWayHint'>Once set, this option cannot be removed. Use gpg cli for further edit.</message>
|
||||
<message id='CertifyUid'>Certify identities</message>
|
||||
<message id='RevokeUidCertification'>Revoke certifications</message>
|
||||
|
||||
<message id='PrepareCopy'>Click to be able to copy next</message>
|
||||
|
||||
|
||||
@@ -83,8 +83,10 @@
|
||||
<message id='NoUidSelected'>Aucun courriel n'est sélectionné</message>
|
||||
<message id='Apply'>Appliquer</message>
|
||||
<message id='CertificationSuccess'>Succès de certification de la clé</message>
|
||||
<message id='CertificationFailure'>Échec de certification de la clé</message>
|
||||
<message id='RevocationSuccess'>Succès de révocation de l'identité</message>
|
||||
<message id='OneWayHint'>Une fois appliquée, cette option ne pourra plus être enlevée. Utilisez gpg en ligne de commande pour édition ultérieure.</message>
|
||||
<message id='CertifyUid'>Certifier les identités</message>
|
||||
<message id='RevokeUidCertification'>Revoquer les certifications</message>
|
||||
|
||||
<message id='PrepareCopy'>Cliquez pour pouvoir ensuite copier</message>
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
projectFiles="true">
|
||||
<itemPath>AppConfig.h</itemPath>
|
||||
<itemPath>GpgMECWorker.h</itemPath>
|
||||
<itemPath>GpgMELogger.h</itemPath>
|
||||
<itemPath>GpgMEWorker.h</itemPath>
|
||||
<itemPath>K7Main.h</itemPath>
|
||||
<itemPath>KeyEdit.h</itemPath>
|
||||
@@ -104,6 +105,8 @@
|
||||
</item>
|
||||
<item path="GpgMECWorker.h" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="GpgMELogger.h" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="GpgMEWorker.cpp" ex="false" tool="1" flavor2="0">
|
||||
</item>
|
||||
<item path="GpgMEWorker.h" ex="false" tool="3" flavor2="0">
|
||||
@@ -224,6 +227,8 @@
|
||||
</item>
|
||||
<item path="GpgMECWorker.h" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="GpgMELogger.h" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="GpgMEWorker.cpp" ex="false" tool="1" flavor2="0">
|
||||
</item>
|
||||
<item path="GpgMEWorker.h" ex="false" tool="3" flavor2="0">
|
||||
@@ -348,6 +353,8 @@
|
||||
</item>
|
||||
<item path="GpgMECWorker.h" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="GpgMELogger.h" ex="false" tool="3" flavor2="0">
|
||||
</item>
|
||||
<item path="GpgMEWorker.cpp" ex="false" tool="1" flavor2="0">
|
||||
</item>
|
||||
<item path="GpgMEWorker.h" ex="false" tool="3" flavor2="0">
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
<gdb_interceptlist>
|
||||
<gdbinterceptoptions gdb_all="false" gdb_unhandled="true" gdb_unexpected="true"/>
|
||||
</gdb_interceptlist>
|
||||
<gdb_signals>
|
||||
</gdb_signals>
|
||||
<gdb_options>
|
||||
<DebugOptions>
|
||||
</DebugOptions>
|
||||
|
||||
Reference in New Issue
Block a user