Move all keyring management functions to a separate class.
KeyringIO imports, creates and deletes keys. Everything is declared private in this class, and it can be called by K7Main only.
This commit is contained in:
199
K7Main.cpp
199
K7Main.cpp
@@ -29,7 +29,7 @@ K7Main::K7Main(const WEnvironment& env)
|
|||||||
{
|
{
|
||||||
m_config = NULL;
|
m_config = NULL;
|
||||||
m_btnUpload = NULL; m_btnImport = NULL; m_btnDelete = NULL;
|
m_btnUpload = NULL; m_btnImport = NULL; m_btnDelete = NULL;
|
||||||
m_btnCreate = NULL; m_popupCreate = NULL;
|
m_btnCreate = NULL;
|
||||||
WApplication::setTitle(_APPNAME_);
|
WApplication::setTitle(_APPNAME_);
|
||||||
const WString bundle = WApplication::appRoot() + _APPNAME_;
|
const WString bundle = WApplication::appRoot() + _APPNAME_;
|
||||||
WApplication::instance()->messageResourceBundle().use(bundle.toUTF8());
|
WApplication::instance()->messageResourceBundle().use(bundle.toUTF8());
|
||||||
@@ -58,7 +58,6 @@ K7Main::K7Main(const WEnvironment& env)
|
|||||||
OwnerTrustLevel[GpgME::Key::OwnerTrust::Ultimate] = TR("UidUltimate");
|
OwnerTrustLevel[GpgME::Key::OwnerTrust::Ultimate] = TR("UidUltimate");
|
||||||
OwnerTrustLevel[GpgME::Key::OwnerTrust::Undefined] = TR("UidUndefined");
|
OwnerTrustLevel[GpgME::Key::OwnerTrust::Undefined] = TR("UidUndefined");
|
||||||
OwnerTrustLevel[GpgME::Key::OwnerTrust::Unknown] = TR("UidUnknown");
|
OwnerTrustLevel[GpgME::Key::OwnerTrust::Unknown] = TR("UidUnknown");
|
||||||
m_popupUpload = NULL; m_popupDelete = NULL;
|
|
||||||
m_keyEdit = new KeyEdit(this);
|
m_keyEdit = new KeyEdit(this);
|
||||||
|
|
||||||
WLink link;
|
WLink link;
|
||||||
@@ -70,8 +69,8 @@ K7Main::K7Main(const WEnvironment& env)
|
|||||||
|
|
||||||
K7Main::~K7Main()
|
K7Main::~K7Main()
|
||||||
{
|
{
|
||||||
delete m_config; delete m_popupUpload; delete m_popupDelete;
|
delete m_config;
|
||||||
delete m_keyEdit; delete m_popupCreate;
|
delete m_keyEdit; delete m_keyringIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -122,11 +121,9 @@ K7Main::Create()
|
|||||||
m_btnUpload = new WPushButton(TR("Upload"));
|
m_btnUpload = new WPushButton(TR("Upload"));
|
||||||
m_btnUpload->setToolTip(TR("TTTUpload"));
|
m_btnUpload->setToolTip(TR("TTTUpload"));
|
||||||
vblButtons->addWidget(unique_ptr<WPushButton> (m_btnUpload));
|
vblButtons->addWidget(unique_ptr<WPushButton> (m_btnUpload));
|
||||||
m_btnUpload->clicked().connect(this, &K7Main::ShowPopupUpload);
|
|
||||||
m_btnImport = new WPushButton(TR("Import"));
|
m_btnImport = new WPushButton(TR("Import"));
|
||||||
m_btnImport->setToolTip(TR("TTTImport"));
|
m_btnImport->setToolTip(TR("TTTImport"));
|
||||||
vblButtons->addWidget(unique_ptr<WPushButton> (m_btnImport));
|
vblButtons->addWidget(unique_ptr<WPushButton> (m_btnImport));
|
||||||
m_btnImport->clicked().connect(this, &K7Main::DoImportKey);
|
|
||||||
m_btnImport->hide();
|
m_btnImport->hide();
|
||||||
}
|
}
|
||||||
// Add a delete button if current user is allowed
|
// Add a delete button if current user is allowed
|
||||||
@@ -135,16 +132,15 @@ K7Main::Create()
|
|||||||
m_btnDelete = new WPushButton(TR("Delete"));
|
m_btnDelete = new WPushButton(TR("Delete"));
|
||||||
m_btnDelete->setToolTip(TR("TTTDelete"));
|
m_btnDelete->setToolTip(TR("TTTDelete"));
|
||||||
vblButtons->addWidget(unique_ptr<WPushButton> (m_btnDelete));
|
vblButtons->addWidget(unique_ptr<WPushButton> (m_btnDelete));
|
||||||
m_btnDelete->clicked().connect(this, &K7Main::ShowPopupDelete);
|
|
||||||
m_btnDelete->hide();
|
m_btnDelete->hide();
|
||||||
}
|
}
|
||||||
vblButtons->addSpacing(150);
|
vblButtons->addSpacing(150);
|
||||||
vblButtons->addStretch(1);
|
vblButtons->addStretch(1);
|
||||||
if (m_config->CanCreateKeys()) {
|
if (m_config->CanCreateKeys())
|
||||||
|
{
|
||||||
m_btnCreate = new WPushButton(TR("Create"));
|
m_btnCreate = new WPushButton(TR("Create"));
|
||||||
m_btnCreate->setToolTip(TR("TTTCreate"));
|
m_btnCreate->setToolTip(TR("TTTCreate"));
|
||||||
vblButtons->addWidget(unique_ptr<WPushButton> (m_btnCreate));
|
vblButtons->addWidget(unique_ptr<WPushButton> (m_btnCreate));
|
||||||
m_btnCreate->clicked().connect(this, &K7Main::ShowPopupCreate);
|
|
||||||
}
|
}
|
||||||
grlMain->addWidget(unique_ptr<WContainerWidget> (cwButtons), 1, 1);
|
grlMain->addWidget(unique_ptr<WContainerWidget> (cwButtons), 1, 1);
|
||||||
|
|
||||||
@@ -158,6 +154,9 @@ K7Main::Create()
|
|||||||
|
|
||||||
root()->addWidget(cpp14::make_unique<WBreak>());
|
root()->addWidget(cpp14::make_unique<WBreak>());
|
||||||
root()->addWidget(unique_ptr<WContainerWidget> (m_cwMain));
|
root()->addWidget(unique_ptr<WContainerWidget> (m_cwMain));
|
||||||
|
|
||||||
|
m_keyringIO = new KeyringIO(this);
|
||||||
|
|
||||||
#ifdef DEVTIME
|
#ifdef DEVTIME
|
||||||
// Save my fingertips.
|
// Save my fingertips.
|
||||||
m_leSearch->setText("s");
|
m_leSearch->setText("s");
|
||||||
@@ -300,7 +299,7 @@ void K7Main::OnKeyAnchorClicked(WAnchor * source)
|
|||||||
DisplayUids(id);
|
DisplayUids(id);
|
||||||
DisplaySubKeys(id, secret);
|
DisplaySubKeys(id, secret);
|
||||||
if (m_config->CanDelete()) // m_btnDelete is NULL otherwise
|
if (m_config->CanDelete()) // m_btnDelete is NULL otherwise
|
||||||
m_btnDelete->setHidden(!CanKeyBeDeleted(id));
|
m_btnDelete->setHidden(!m_keyringIO->CanKeyBeDeleted(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
void K7Main::DisplayUids(const WString& fullKeyID, bool secret)
|
void K7Main::DisplayUids(const WString& fullKeyID, bool secret)
|
||||||
@@ -415,183 +414,3 @@ void K7Main::DisplaySubKeys(const WString& fullKeyID, bool secret)
|
|||||||
}
|
}
|
||||||
m_ttbSubKeys->show();
|
m_ttbSubKeys->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void K7Main::ShowPopupUpload() {
|
|
||||||
if (m_popupUpload == NULL) {
|
|
||||||
m_popupUpload = new PopupUpload(m_btnUpload, m_tmwMessage);
|
|
||||||
m_popupUpload->Create();
|
|
||||||
m_popupUpload->UploadDone().connect(this, &K7Main::OnUploadCompleted);
|
|
||||||
}
|
|
||||||
m_popupUpload->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void K7Main::OnUploadCompleted(const WString& spool) {
|
|
||||||
// Buffer the spool file name in the import button
|
|
||||||
m_btnImport->setAttributeValue("spool", spool);
|
|
||||||
m_btnImport->show();
|
|
||||||
m_popupUpload->hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
void K7Main::DoImportKey() {
|
|
||||||
const WString spool = m_btnImport->attributeValue("spool");
|
|
||||||
Error e;
|
|
||||||
GpgMEWorker gpgw;
|
|
||||||
const WString fpr = gpgw.ImportKey(spool.toUTF8().c_str(), e);
|
|
||||||
m_btnImport->hide();
|
|
||||||
m_btnImport->setAttributeValue("spool", "");
|
|
||||||
if (e.code() != 0) {
|
|
||||||
m_tmwMessage->SetText(e.asString());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (fpr.empty()) {
|
|
||||||
m_tmwMessage->SetText(TR("ImportError") + fpr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Show the imported key
|
|
||||||
GpgME::Key k = gpgw.FindKey(fpr.toUTF8().c_str(), e, false); // A public is present anyway
|
|
||||||
if (e.code() != 0) {
|
|
||||||
m_tmwMessage->SetText(e.asString());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
m_tmwMessage->SetText(TR("ImportSuccess") + fpr + WString(" - ") + WString(k.userID(0).name()));
|
|
||||||
m_leSearch->setText(fpr);
|
|
||||||
if (Tools::KeyHasSecret(fpr))
|
|
||||||
m_config->UpdateSecretKeyOwnership(fpr, true);
|
|
||||||
Search();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool K7Main::CanKeyBeDeleted(const WString& fullKeyID) {
|
|
||||||
// Caller should check m_config->canDelete first. m_btnDelete is null if can't delete.
|
|
||||||
Error e;
|
|
||||||
GpgMEWorker gpgw;
|
|
||||||
GpgME::Key k = gpgw.FindKey(fullKeyID.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
|
|
||||||
m_tmwMessage->SetText(e.asString());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// k can now be secret or public
|
|
||||||
if (k.isNull()) {// Is a public key
|
|
||||||
k = gpgw.FindKey(fullKeyID.toUTF8().c_str(), e, false);
|
|
||||||
// Prepare actual delete
|
|
||||||
m_btnDelete->setAttributeValue("keyid", k.keyID());
|
|
||||||
m_btnDelete->setAttributeValue("hasSecret", "0");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* k is now secret
|
|
||||||
* Is selected private key one of those that the current user manages ?
|
|
||||||
*/
|
|
||||||
vector<WString> curUserPrivKeys = m_config->PrivateKeyIds();
|
|
||||||
vector<WString>::iterator it;
|
|
||||||
for (it = curUserPrivKeys.begin(); it != curUserPrivKeys.end(); it++) {
|
|
||||||
if (Tools::ConfigKeyIdMatchesKey(k, *it)) {
|
|
||||||
m_btnDelete->setAttributeValue("keyid", k.keyID());
|
|
||||||
m_btnDelete->setAttributeValue("hasSecret", "1");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void K7Main::ShowPopupDelete() {
|
|
||||||
if (m_popupDelete == NULL) {
|
|
||||||
m_popupDelete = new PopupDelete(m_btnDelete, m_tmwMessage);
|
|
||||||
m_popupDelete->Create();
|
|
||||||
m_popupDelete->GetDeleteButton()->clicked().connect(this, &K7Main::DoDeleteKey);
|
|
||||||
}
|
|
||||||
m_popupDelete->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void K7Main::DoDeleteKey() {
|
|
||||||
// Deleting keys requires the GPGME C API
|
|
||||||
Error c_e, e;
|
|
||||||
GpgMECWorker gpgcw;
|
|
||||||
GpgMEWorker gpgw;
|
|
||||||
const WString fullKeyID = m_btnDelete->attributeValue("keyid");
|
|
||||||
const WString hasSecret = m_btnDelete->attributeValue("hasSecret");
|
|
||||||
bool secret = true;
|
|
||||||
if (hasSecret == WString("0"))
|
|
||||||
secret = false;
|
|
||||||
// Get the key before deletion, to show its ID on success
|
|
||||||
GpgME::Key k = gpgw.FindKey(fullKeyID.toUTF8().c_str(), e, secret);
|
|
||||||
if (e.code() != 0) {
|
|
||||||
m_tmwMessage->SetText(e.asString());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Delete the key using the C API
|
|
||||||
const WString fpr(k.primaryFingerprint());
|
|
||||||
bool res = gpgcw.DeleteKey(k.primaryFingerprint(), secret, c_e);
|
|
||||||
if (c_e.code() != 0) {
|
|
||||||
m_tmwMessage->SetText(c_e.asString());
|
|
||||||
} else {
|
|
||||||
m_tmwMessage->SetText(TR("DeleteSuccess") + fpr + WString(" - ") + WString(k.userID(0).name()));
|
|
||||||
}
|
|
||||||
m_btnDelete->hide();
|
|
||||||
m_popupDelete->hide();
|
|
||||||
if (secret)
|
|
||||||
m_config->UpdateSecretKeyOwnership(fpr, false);
|
|
||||||
// Show that the key is no longer available
|
|
||||||
m_leSearch->setText(fpr);
|
|
||||||
Search();
|
|
||||||
}
|
|
||||||
|
|
||||||
void K7Main::ShowPopupCreate()
|
|
||||||
{
|
|
||||||
if (m_popupCreate == NULL)
|
|
||||||
{
|
|
||||||
m_popupCreate = new PopupCreate(m_btnCreate, m_tmwMessage);
|
|
||||||
m_popupCreate->Create();
|
|
||||||
m_popupCreate->GetApplyButton()->clicked().connect(this, &K7Main::DoCreateKey);
|
|
||||||
}
|
|
||||||
m_popupCreate->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void K7Main::DoCreateKey()
|
|
||||||
{
|
|
||||||
if (!m_popupCreate->Validate())
|
|
||||||
return;
|
|
||||||
Error e;
|
|
||||||
GpgME::Key k;
|
|
||||||
GpgMEWorker gpgw;
|
|
||||||
if (m_popupCreate->UseDefaultEngineAlgorithms())
|
|
||||||
{
|
|
||||||
e = gpgw.CreateKeyWithEngineDefaultAlgo(k, m_popupCreate->GetName().toUTF8(),
|
|
||||||
m_popupCreate->GetEmail().toUTF8(),
|
|
||||||
m_popupCreate->GetComment().toUTF8(),
|
|
||||||
m_popupCreate->GetPassphrase().toUTF8(),
|
|
||||||
m_popupCreate->GetExpiry());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
e = gpgw.CreateKey(k, m_popupCreate->GetName().toUTF8(),
|
|
||||||
m_popupCreate->GetEmail().toUTF8(),
|
|
||||||
m_popupCreate->GetComment().toUTF8(),
|
|
||||||
m_popupCreate->GetArbitraryKeyAlgo().toUTF8().c_str(),
|
|
||||||
m_popupCreate->GetPassphrase().toUTF8(),
|
|
||||||
m_popupCreate->GetExpiry());
|
|
||||||
// GPGME accepts a missing subkey.
|
|
||||||
if (e.code() == 0 && !m_popupCreate->GetArbitrarySubkeyAlgo().empty())
|
|
||||||
e = gpgw.CreateSubKey(k,
|
|
||||||
m_popupCreate->GetArbitrarySubkeyAlgo().toUTF8().c_str(),
|
|
||||||
m_popupCreate->GetPassphrase().toUTF8(),
|
|
||||||
m_popupCreate->GetExpiry());
|
|
||||||
}
|
|
||||||
if (e.code() != 0)
|
|
||||||
{
|
|
||||||
m_tmwMessage->SetText(e.asString());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const WString fpr(k.primaryFingerprint());
|
|
||||||
m_tmwMessage->SetText(TR("CreateSuccess")
|
|
||||||
+ fpr + WString(" - ") + WString(k.userID(0).name()));
|
|
||||||
// Add the key fingerprint to the list of keys managed by the user.
|
|
||||||
m_config->UpdateSecretKeyOwnership(fpr, true);
|
|
||||||
m_popupCreate->hide();
|
|
||||||
#ifndef DEVTIME
|
|
||||||
m_popupCreate->Reset();
|
|
||||||
#endif
|
|
||||||
m_leSearch->setText(fpr);
|
|
||||||
Search();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
48
K7Main.h
48
K7Main.h
@@ -22,20 +22,20 @@
|
|||||||
#include <gpgme++/key.h>
|
#include <gpgme++/key.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "AppConfig.h"
|
#include "AppConfig.h"
|
||||||
#include "PopupUploader.h"
|
|
||||||
#include "PopupDeleter.h"
|
|
||||||
#include "PopupCreate.h"
|
|
||||||
#include "TransientMessageWidget.h"
|
#include "TransientMessageWidget.h"
|
||||||
#include "KeyEdit.h"
|
#include "KeyEdit.h"
|
||||||
|
#include "KeyringIO.h"
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
|
|
||||||
using namespace Wt;
|
using namespace Wt;
|
||||||
|
|
||||||
class KeyEdit;
|
class KeyEdit;
|
||||||
|
class KeyringIO;
|
||||||
|
|
||||||
class K7Main : public WApplication
|
class K7Main : public WApplication
|
||||||
{
|
{
|
||||||
friend class KeyEdit;
|
friend class KeyEdit;
|
||||||
|
friend class KeyringIO;
|
||||||
public:
|
public:
|
||||||
K7Main(const WEnvironment& env);
|
K7Main(const WEnvironment& env);
|
||||||
virtual ~K7Main();
|
virtual ~K7Main();
|
||||||
@@ -59,10 +59,8 @@ private:
|
|||||||
WTreeTable * m_ttbKeys;
|
WTreeTable * m_ttbKeys;
|
||||||
WTreeTable * m_ttbUids;
|
WTreeTable * m_ttbUids;
|
||||||
WTreeTable * m_ttbSubKeys;
|
WTreeTable * m_ttbSubKeys;
|
||||||
PopupUpload * m_popupUpload;
|
|
||||||
PopupDelete * m_popupDelete;
|
|
||||||
KeyEdit * m_keyEdit;
|
KeyEdit * m_keyEdit;
|
||||||
PopupCreate * m_popupCreate;
|
KeyringIO * m_keyringIO;
|
||||||
/**
|
/**
|
||||||
* Finds public keys as per criteria,
|
* Finds public keys as per criteria,
|
||||||
* and private keys if any is declared in config file for current client.
|
* and private keys if any is declared in config file for current client.
|
||||||
@@ -90,48 +88,10 @@ private:
|
|||||||
* @param secret
|
* @param secret
|
||||||
*/
|
*/
|
||||||
void DisplaySubKeys(const WString& fullKeyID, bool secret = false);
|
void DisplaySubKeys(const WString& fullKeyID, bool secret = false);
|
||||||
/**
|
|
||||||
* Shows a non-blocking popup to upload a key,
|
|
||||||
* with forward confirmation for upload.
|
|
||||||
*/
|
|
||||||
void ShowPopupUpload();
|
|
||||||
/**
|
|
||||||
* Shows a button to import an uploaded key
|
|
||||||
* @param spool
|
|
||||||
*/
|
|
||||||
void OnUploadCompleted(const WString& spool);
|
|
||||||
/**
|
|
||||||
* Actually import the uploaded file.
|
|
||||||
*/
|
|
||||||
void DoImportKey();
|
|
||||||
/**
|
|
||||||
* Shows a non-blocking popup to delete a key
|
|
||||||
*/
|
|
||||||
void ShowPopupDelete();
|
|
||||||
/**
|
|
||||||
* All public keys can be deleted.
|
|
||||||
* Private keys can be deleted only if the user
|
|
||||||
* manages that key, as declared in the configuration file.
|
|
||||||
* @param fullKeyID
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
bool CanKeyBeDeleted(const WString& fullKeyID);
|
|
||||||
/**
|
|
||||||
* Actually delete the key, with forward confirmation in the popup.
|
|
||||||
*/
|
|
||||||
void DoDeleteKey();
|
|
||||||
/**
|
/**
|
||||||
* Translates unit time to readable date.
|
* Translates unit time to readable date.
|
||||||
*/
|
*/
|
||||||
WString MakeDateTimeLabel(time_t ticks);
|
WString MakeDateTimeLabel(time_t ticks);
|
||||||
/**
|
|
||||||
* Shows a non-blocking popup to create keys.
|
|
||||||
*/
|
|
||||||
void ShowPopupCreate();
|
|
||||||
/**
|
|
||||||
* Validates input and creates the keys.
|
|
||||||
*/
|
|
||||||
void DoCreateKey();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* K7MAIN_H */
|
#endif /* K7MAIN_H */
|
||||||
|
|||||||
246
KeyringIO.cpp
Normal file
246
KeyringIO.cpp
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
/*
|
||||||
|
* File: KeyringIO.cpp
|
||||||
|
* Author: SET - nmset@yandex.com
|
||||||
|
* License : GPL v2
|
||||||
|
* Copyright SET - © 2019
|
||||||
|
*
|
||||||
|
* Created on November 13, 2020, 6:46 PM
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "KeyringIO.h"
|
||||||
|
#include "GpgMEWorker.h"
|
||||||
|
#include "GpgMECWorker.h"
|
||||||
|
#include "Tools.h"
|
||||||
|
|
||||||
|
KeyringIO::KeyringIO(K7Main * owner)
|
||||||
|
{
|
||||||
|
m_owner = owner;
|
||||||
|
m_popupUpload = NULL;
|
||||||
|
m_popupDelete = NULL;
|
||||||
|
m_popupCreate = NULL;
|
||||||
|
m_config = m_owner->m_config;
|
||||||
|
m_tmwMessage = m_owner->m_tmwMessage;
|
||||||
|
m_btnUpload = m_owner->m_btnUpload;
|
||||||
|
m_btnImport = m_owner->m_btnImport;
|
||||||
|
m_btnDelete = m_owner->m_btnDelete;
|
||||||
|
m_btnCreate = m_owner->m_btnCreate;
|
||||||
|
m_leSearch = m_owner->m_leSearch;
|
||||||
|
|
||||||
|
if (m_config->CanImport())
|
||||||
|
{
|
||||||
|
m_btnUpload->clicked().connect(this, &KeyringIO::ShowPopupUpload);
|
||||||
|
m_btnImport->clicked().connect(this, &KeyringIO::DoImportKey);
|
||||||
|
}
|
||||||
|
if (m_config->CanDelete())
|
||||||
|
m_btnDelete->clicked().connect(this, &KeyringIO::ShowPopupDelete);
|
||||||
|
if (m_config->CanCreateKeys())
|
||||||
|
m_btnCreate->clicked().connect(this, &KeyringIO::ShowPopupCreate);
|
||||||
|
}
|
||||||
|
|
||||||
|
KeyringIO::~KeyringIO()
|
||||||
|
{
|
||||||
|
delete m_popupUpload;
|
||||||
|
delete m_popupDelete;
|
||||||
|
delete m_popupCreate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyringIO::ShowPopupUpload()
|
||||||
|
{
|
||||||
|
if (m_popupUpload == NULL)
|
||||||
|
{
|
||||||
|
m_popupUpload = new PopupUpload(m_btnUpload,
|
||||||
|
m_tmwMessage);
|
||||||
|
m_popupUpload->Create();
|
||||||
|
m_popupUpload->UploadDone().connect(this, &KeyringIO::OnUploadCompleted);
|
||||||
|
}
|
||||||
|
m_popupUpload->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyringIO::OnUploadCompleted(const WString& spool)
|
||||||
|
{
|
||||||
|
// Buffer the spool file name in the import button
|
||||||
|
m_btnImport->setAttributeValue("spool", spool);
|
||||||
|
m_btnImport->show();
|
||||||
|
m_popupUpload->hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyringIO::DoImportKey()
|
||||||
|
{
|
||||||
|
const WString spool = m_btnImport->attributeValue("spool");
|
||||||
|
Error e;
|
||||||
|
GpgMEWorker gpgw;
|
||||||
|
const WString fpr = gpgw.ImportKey(spool.toUTF8().c_str(), e);
|
||||||
|
m_btnImport->hide();
|
||||||
|
m_btnImport->setAttributeValue("spool", "");
|
||||||
|
if (e.code() != 0)
|
||||||
|
{
|
||||||
|
m_tmwMessage->SetText(e.asString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fpr.empty())
|
||||||
|
{
|
||||||
|
m_tmwMessage->SetText(TR("ImportError") + fpr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Show the imported key
|
||||||
|
GpgME::Key k = gpgw.FindKey(fpr.toUTF8().c_str(), e, false); // A public is present anyway
|
||||||
|
if (e.code() != 0)
|
||||||
|
{
|
||||||
|
m_tmwMessage->SetText(e.asString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_tmwMessage->SetText(TR("ImportSuccess") + fpr + WString(" - ") + WString(k.userID(0).name()));
|
||||||
|
m_leSearch->setText(fpr);
|
||||||
|
if (Tools::KeyHasSecret(fpr))
|
||||||
|
m_config->UpdateSecretKeyOwnership(fpr, true);
|
||||||
|
m_owner->Search();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KeyringIO::CanKeyBeDeleted(const WString& fullKeyID)
|
||||||
|
{
|
||||||
|
// Caller should check m_config->canDelete first. m_btnDelete is null if can't delete.
|
||||||
|
Error e;
|
||||||
|
GpgMEWorker gpgw;
|
||||||
|
GpgME::Key k = gpgw.FindKey(fullKeyID.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
|
||||||
|
m_tmwMessage->SetText(e.asString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// k can now be secret or public
|
||||||
|
if (k.isNull())
|
||||||
|
{// Is a public key
|
||||||
|
k = gpgw.FindKey(fullKeyID.toUTF8().c_str(), e, false);
|
||||||
|
// Prepare actual delete
|
||||||
|
m_btnDelete->setAttributeValue("keyid", k.keyID());
|
||||||
|
m_btnDelete->setAttributeValue("hasSecret", "0");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* k is now secret
|
||||||
|
* Is selected private key one of those that the current user manages ?
|
||||||
|
*/
|
||||||
|
vector<WString> curUserPrivKeys = m_config->PrivateKeyIds();
|
||||||
|
vector<WString>::iterator it;
|
||||||
|
for (it = curUserPrivKeys.begin(); it != curUserPrivKeys.end(); it++)
|
||||||
|
{
|
||||||
|
if (Tools::ConfigKeyIdMatchesKey(k, *it))
|
||||||
|
{
|
||||||
|
m_btnDelete->setAttributeValue("keyid", k.keyID());
|
||||||
|
m_btnDelete->setAttributeValue("hasSecret", "1");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyringIO::ShowPopupDelete()
|
||||||
|
{
|
||||||
|
if (m_popupDelete == NULL)
|
||||||
|
{
|
||||||
|
m_popupDelete = new PopupDelete(m_btnDelete,
|
||||||
|
m_tmwMessage);
|
||||||
|
m_popupDelete->Create();
|
||||||
|
m_popupDelete->GetDeleteButton()->clicked().connect(this, &KeyringIO::DoDeleteKey);
|
||||||
|
}
|
||||||
|
m_popupDelete->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyringIO::DoDeleteKey()
|
||||||
|
{
|
||||||
|
// Deleting keys requires the GPGME C API
|
||||||
|
Error c_e, e;
|
||||||
|
GpgMECWorker gpgcw;
|
||||||
|
GpgMEWorker gpgw;
|
||||||
|
const WString fullKeyID = m_btnDelete->attributeValue("keyid");
|
||||||
|
const WString hasSecret = m_btnDelete->attributeValue("hasSecret");
|
||||||
|
bool secret = true;
|
||||||
|
if (hasSecret == WString("0"))
|
||||||
|
secret = false;
|
||||||
|
// Get the key before deletion, to show its ID on success
|
||||||
|
GpgME::Key k = gpgw.FindKey(fullKeyID.toUTF8().c_str(), e, secret);
|
||||||
|
if (e.code() != 0)
|
||||||
|
{
|
||||||
|
m_tmwMessage->SetText(e.asString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Delete the key using the C API
|
||||||
|
const WString fpr(k.primaryFingerprint());
|
||||||
|
bool res = gpgcw.DeleteKey(k.primaryFingerprint(), secret, c_e);
|
||||||
|
if (c_e.code() != 0)
|
||||||
|
{
|
||||||
|
m_tmwMessage->SetText(c_e.asString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_tmwMessage->SetText(TR("DeleteSuccess") + fpr + WString(" - ") + WString(k.userID(0).name()));
|
||||||
|
}
|
||||||
|
m_btnDelete->hide();
|
||||||
|
m_popupDelete->hide();
|
||||||
|
if (secret)
|
||||||
|
m_config->UpdateSecretKeyOwnership(fpr, false);
|
||||||
|
// Show that the key is no longer available
|
||||||
|
m_leSearch->setText(fpr);
|
||||||
|
m_owner->Search();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyringIO::ShowPopupCreate()
|
||||||
|
{
|
||||||
|
if (m_popupCreate == NULL)
|
||||||
|
{
|
||||||
|
m_popupCreate = new PopupCreate(m_btnCreate, m_tmwMessage);
|
||||||
|
m_popupCreate->Create();
|
||||||
|
m_popupCreate->GetApplyButton()->clicked().connect(this, &KeyringIO::DoCreateKey);
|
||||||
|
}
|
||||||
|
m_popupCreate->show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyringIO::DoCreateKey()
|
||||||
|
{
|
||||||
|
if (!m_popupCreate->Validate())
|
||||||
|
return;
|
||||||
|
Error e;
|
||||||
|
GpgME::Key k;
|
||||||
|
GpgMEWorker gpgw;
|
||||||
|
if (m_popupCreate->UseDefaultEngineAlgorithms())
|
||||||
|
{
|
||||||
|
e = gpgw.CreateKeyWithEngineDefaultAlgo(k, m_popupCreate->GetName().toUTF8(),
|
||||||
|
m_popupCreate->GetEmail().toUTF8(),
|
||||||
|
m_popupCreate->GetComment().toUTF8(),
|
||||||
|
m_popupCreate->GetPassphrase().toUTF8(),
|
||||||
|
m_popupCreate->GetExpiry());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
e = gpgw.CreateKey(k, m_popupCreate->GetName().toUTF8(),
|
||||||
|
m_popupCreate->GetEmail().toUTF8(),
|
||||||
|
m_popupCreate->GetComment().toUTF8(),
|
||||||
|
m_popupCreate->GetArbitraryKeyAlgo().toUTF8().c_str(),
|
||||||
|
m_popupCreate->GetPassphrase().toUTF8(),
|
||||||
|
m_popupCreate->GetExpiry());
|
||||||
|
// GPGME accepts a missing subkey.
|
||||||
|
if (e.code() == 0 && !m_popupCreate->GetArbitrarySubkeyAlgo().empty())
|
||||||
|
e = gpgw.CreateSubKey(k,
|
||||||
|
m_popupCreate->GetArbitrarySubkeyAlgo().toUTF8().c_str(),
|
||||||
|
m_popupCreate->GetPassphrase().toUTF8(),
|
||||||
|
m_popupCreate->GetExpiry());
|
||||||
|
}
|
||||||
|
if (e.code() != 0)
|
||||||
|
{
|
||||||
|
m_tmwMessage->SetText(e.asString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const WString fpr(k.primaryFingerprint());
|
||||||
|
m_tmwMessage->SetText(TR("CreateSuccess")
|
||||||
|
+ fpr + WString(" - ") + WString(k.userID(0).name()));
|
||||||
|
// Add the key fingerprint to the list of keys managed by the user.
|
||||||
|
m_config->UpdateSecretKeyOwnership(fpr, true);
|
||||||
|
m_popupCreate->hide();
|
||||||
|
#ifndef DEVTIME
|
||||||
|
m_popupCreate->Reset();
|
||||||
|
#endif
|
||||||
|
m_leSearch->setText(fpr);
|
||||||
|
m_owner->Search();
|
||||||
|
}
|
||||||
|
}
|
||||||
96
KeyringIO.h
Normal file
96
KeyringIO.h
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* File: KeyringIO.h
|
||||||
|
* Author: SET - nmset@yandex.com
|
||||||
|
* License : GPL v2
|
||||||
|
* Copyright SET - © 2019
|
||||||
|
*
|
||||||
|
* Created on November 13, 2020, 6:46 PM
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KEYRINGIO_H
|
||||||
|
#define KEYRINGIO_H
|
||||||
|
|
||||||
|
#include "K7Main.h"
|
||||||
|
#include <Wt/WComboBox.h>
|
||||||
|
#include "PopupUploader.h"
|
||||||
|
#include "PopupDeleter.h"
|
||||||
|
#include "PopupCreate.h"
|
||||||
|
|
||||||
|
using namespace Wt;
|
||||||
|
|
||||||
|
class K7Main;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages the keyring : import, create and delete keys.
|
||||||
|
* Is a pseudo-extension of K7Main. Both classes are friends to each other, and
|
||||||
|
* everything is private here.
|
||||||
|
* Does not edit keys.
|
||||||
|
* @param owner
|
||||||
|
*/
|
||||||
|
class KeyringIO : public WObject
|
||||||
|
{
|
||||||
|
friend class K7Main;
|
||||||
|
public:
|
||||||
|
|
||||||
|
private:
|
||||||
|
KeyringIO(K7Main * owner);
|
||||||
|
virtual ~KeyringIO();
|
||||||
|
|
||||||
|
K7Main * m_owner;
|
||||||
|
PopupUpload * m_popupUpload;
|
||||||
|
PopupDelete * m_popupDelete;
|
||||||
|
PopupCreate * m_popupCreate;
|
||||||
|
|
||||||
|
// Variables from m_owner mapped here.
|
||||||
|
AppConfig * m_config;
|
||||||
|
TransientMessageWidget * m_tmwMessage;
|
||||||
|
WPushButton * m_btnUpload;
|
||||||
|
WPushButton * m_btnImport;
|
||||||
|
WPushButton * m_btnDelete;
|
||||||
|
WPushButton * m_btnCreate ;
|
||||||
|
WLineEdit * m_leSearch;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows a non-blocking popup to upload a key,
|
||||||
|
* with forward confirmation for upload.
|
||||||
|
*/
|
||||||
|
void ShowPopupUpload();
|
||||||
|
/**
|
||||||
|
* Actually import the uploaded file.
|
||||||
|
*/
|
||||||
|
void DoImportKey();
|
||||||
|
/**
|
||||||
|
* Shows a non-blocking popup to delete a key
|
||||||
|
*/
|
||||||
|
void ShowPopupDelete();
|
||||||
|
/**
|
||||||
|
* All public keys can be deleted.
|
||||||
|
* Private keys can be deleted only if the user
|
||||||
|
* manages that key, as declared in the configuration file.
|
||||||
|
* @param fullKeyID
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
bool CanKeyBeDeleted(const WString& fullKeyID);
|
||||||
|
/**
|
||||||
|
* Actually delete the key, with forward confirmation in the popup.
|
||||||
|
*/
|
||||||
|
void DoDeleteKey();
|
||||||
|
/**
|
||||||
|
* Shows a non-blocking popup to create keys.
|
||||||
|
*/
|
||||||
|
void ShowPopupCreate();
|
||||||
|
/**
|
||||||
|
* Validates input and creates the keys.
|
||||||
|
*/
|
||||||
|
void DoCreateKey();
|
||||||
|
/**
|
||||||
|
* Shows a button to import an uploaded key
|
||||||
|
* @param spool
|
||||||
|
*/
|
||||||
|
void OnUploadCompleted(const WString& spool);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* KEYRINGIO_H */
|
||||||
|
|
||||||
@@ -40,6 +40,7 @@ OBJECTFILES= \
|
|||||||
${OBJECTDIR}/GpgMEWorker.o \
|
${OBJECTDIR}/GpgMEWorker.o \
|
||||||
${OBJECTDIR}/K7Main.o \
|
${OBJECTDIR}/K7Main.o \
|
||||||
${OBJECTDIR}/KeyEdit.o \
|
${OBJECTDIR}/KeyEdit.o \
|
||||||
|
${OBJECTDIR}/KeyringIO.o \
|
||||||
${OBJECTDIR}/LoopbackPassphraseProvider.o \
|
${OBJECTDIR}/LoopbackPassphraseProvider.o \
|
||||||
${OBJECTDIR}/PopupCertifyUserId.o \
|
${OBJECTDIR}/PopupCertifyUserId.o \
|
||||||
${OBJECTDIR}/PopupCreate.o \
|
${OBJECTDIR}/PopupCreate.o \
|
||||||
@@ -101,6 +102,11 @@ ${OBJECTDIR}/KeyEdit.o: KeyEdit.cpp
|
|||||||
${RM} "$@.d"
|
${RM} "$@.d"
|
||||||
$(COMPILE.cc) -O2 -s -DLARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -I/usr/local/Wt/include -I/usr/include/gpgme++ -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/KeyEdit.o KeyEdit.cpp
|
$(COMPILE.cc) -O2 -s -DLARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -I/usr/local/Wt/include -I/usr/include/gpgme++ -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/KeyEdit.o KeyEdit.cpp
|
||||||
|
|
||||||
|
${OBJECTDIR}/KeyringIO.o: KeyringIO.cpp
|
||||||
|
${MKDIR} -p ${OBJECTDIR}
|
||||||
|
${RM} "$@.d"
|
||||||
|
$(COMPILE.cc) -O2 -s -DLARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 -I/usr/local/Wt/include -I/usr/include/gpgme++ -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/KeyringIO.o KeyringIO.cpp
|
||||||
|
|
||||||
${OBJECTDIR}/LoopbackPassphraseProvider.o: LoopbackPassphraseProvider.cpp
|
${OBJECTDIR}/LoopbackPassphraseProvider.o: LoopbackPassphraseProvider.cpp
|
||||||
${MKDIR} -p ${OBJECTDIR}
|
${MKDIR} -p ${OBJECTDIR}
|
||||||
${RM} "$@.d"
|
${RM} "$@.d"
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ OBJECTFILES= \
|
|||||||
${OBJECTDIR}/GpgMEWorker.o \
|
${OBJECTDIR}/GpgMEWorker.o \
|
||||||
${OBJECTDIR}/K7Main.o \
|
${OBJECTDIR}/K7Main.o \
|
||||||
${OBJECTDIR}/KeyEdit.o \
|
${OBJECTDIR}/KeyEdit.o \
|
||||||
|
${OBJECTDIR}/KeyringIO.o \
|
||||||
${OBJECTDIR}/LoopbackPassphraseProvider.o \
|
${OBJECTDIR}/LoopbackPassphraseProvider.o \
|
||||||
${OBJECTDIR}/PopupCertifyUserId.o \
|
${OBJECTDIR}/PopupCertifyUserId.o \
|
||||||
${OBJECTDIR}/PopupCreate.o \
|
${OBJECTDIR}/PopupCreate.o \
|
||||||
@@ -101,6 +102,11 @@ ${OBJECTDIR}/KeyEdit.o: KeyEdit.cpp
|
|||||||
${RM} "$@.d"
|
${RM} "$@.d"
|
||||||
$(COMPILE.cc) -g -DDEVTIME -I/usr/local/Wt-Debug/include -I/usr/include/gpgme++ -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/KeyEdit.o KeyEdit.cpp
|
$(COMPILE.cc) -g -DDEVTIME -I/usr/local/Wt-Debug/include -I/usr/include/gpgme++ -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/KeyEdit.o KeyEdit.cpp
|
||||||
|
|
||||||
|
${OBJECTDIR}/KeyringIO.o: KeyringIO.cpp
|
||||||
|
${MKDIR} -p ${OBJECTDIR}
|
||||||
|
${RM} "$@.d"
|
||||||
|
$(COMPILE.cc) -g -DDEVTIME -I/usr/local/Wt-Debug/include -I/usr/include/gpgme++ -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/KeyringIO.o KeyringIO.cpp
|
||||||
|
|
||||||
${OBJECTDIR}/LoopbackPassphraseProvider.o: LoopbackPassphraseProvider.cpp
|
${OBJECTDIR}/LoopbackPassphraseProvider.o: LoopbackPassphraseProvider.cpp
|
||||||
${MKDIR} -p ${OBJECTDIR}
|
${MKDIR} -p ${OBJECTDIR}
|
||||||
${RM} "$@.d"
|
${RM} "$@.d"
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ OBJECTFILES= \
|
|||||||
${OBJECTDIR}/GpgMEWorker.o \
|
${OBJECTDIR}/GpgMEWorker.o \
|
||||||
${OBJECTDIR}/K7Main.o \
|
${OBJECTDIR}/K7Main.o \
|
||||||
${OBJECTDIR}/KeyEdit.o \
|
${OBJECTDIR}/KeyEdit.o \
|
||||||
|
${OBJECTDIR}/KeyringIO.o \
|
||||||
${OBJECTDIR}/LoopbackPassphraseProvider.o \
|
${OBJECTDIR}/LoopbackPassphraseProvider.o \
|
||||||
${OBJECTDIR}/PopupCertifyUserId.o \
|
${OBJECTDIR}/PopupCertifyUserId.o \
|
||||||
${OBJECTDIR}/PopupCreate.o \
|
${OBJECTDIR}/PopupCreate.o \
|
||||||
@@ -101,6 +102,11 @@ ${OBJECTDIR}/KeyEdit.o: KeyEdit.cpp
|
|||||||
${RM} "$@.d"
|
${RM} "$@.d"
|
||||||
$(COMPILE.cc) -O2 -s -I/usr/local/Wt/include -I/usr/include/gpgme++ -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/KeyEdit.o KeyEdit.cpp
|
$(COMPILE.cc) -O2 -s -I/usr/local/Wt/include -I/usr/include/gpgme++ -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/KeyEdit.o KeyEdit.cpp
|
||||||
|
|
||||||
|
${OBJECTDIR}/KeyringIO.o: KeyringIO.cpp
|
||||||
|
${MKDIR} -p ${OBJECTDIR}
|
||||||
|
${RM} "$@.d"
|
||||||
|
$(COMPILE.cc) -O2 -s -I/usr/local/Wt/include -I/usr/include/gpgme++ -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/KeyringIO.o KeyringIO.cpp
|
||||||
|
|
||||||
${OBJECTDIR}/LoopbackPassphraseProvider.o: LoopbackPassphraseProvider.cpp
|
${OBJECTDIR}/LoopbackPassphraseProvider.o: LoopbackPassphraseProvider.cpp
|
||||||
${MKDIR} -p ${OBJECTDIR}
|
${MKDIR} -p ${OBJECTDIR}
|
||||||
${RM} "$@.d"
|
${RM} "$@.d"
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
<itemPath>GpgMEWorker.h</itemPath>
|
<itemPath>GpgMEWorker.h</itemPath>
|
||||||
<itemPath>K7Main.h</itemPath>
|
<itemPath>K7Main.h</itemPath>
|
||||||
<itemPath>KeyEdit.h</itemPath>
|
<itemPath>KeyEdit.h</itemPath>
|
||||||
|
<itemPath>KeyringIO.h</itemPath>
|
||||||
<itemPath>LoopbackPassphraseProvider.h</itemPath>
|
<itemPath>LoopbackPassphraseProvider.h</itemPath>
|
||||||
<itemPath>PopupCertifyUserId.h</itemPath>
|
<itemPath>PopupCertifyUserId.h</itemPath>
|
||||||
<itemPath>PopupCreate.h</itemPath>
|
<itemPath>PopupCreate.h</itemPath>
|
||||||
@@ -36,6 +37,7 @@
|
|||||||
<itemPath>GpgMEWorker.cpp</itemPath>
|
<itemPath>GpgMEWorker.cpp</itemPath>
|
||||||
<itemPath>K7Main.cpp</itemPath>
|
<itemPath>K7Main.cpp</itemPath>
|
||||||
<itemPath>KeyEdit.cpp</itemPath>
|
<itemPath>KeyEdit.cpp</itemPath>
|
||||||
|
<itemPath>KeyringIO.cpp</itemPath>
|
||||||
<itemPath>LoopbackPassphraseProvider.cpp</itemPath>
|
<itemPath>LoopbackPassphraseProvider.cpp</itemPath>
|
||||||
<itemPath>PopupCertifyUserId.cpp</itemPath>
|
<itemPath>PopupCertifyUserId.cpp</itemPath>
|
||||||
<itemPath>PopupCreate.cpp</itemPath>
|
<itemPath>PopupCreate.cpp</itemPath>
|
||||||
@@ -58,17 +60,6 @@
|
|||||||
kind="IMPORTANT_FILES_FOLDER">
|
kind="IMPORTANT_FILES_FOLDER">
|
||||||
<itemPath>Makefile</itemPath>
|
<itemPath>Makefile</itemPath>
|
||||||
</logicalFolder>
|
</logicalFolder>
|
||||||
<logicalFolder name="TestFiles"
|
|
||||||
displayName="Test Files"
|
|
||||||
projectFiles="false"
|
|
||||||
kind="TEST_LOGICAL_FOLDER">
|
|
||||||
</logicalFolder>
|
|
||||||
<logicalFolder name="ExternalFiles"
|
|
||||||
displayName="Important Files"
|
|
||||||
projectFiles="false"
|
|
||||||
kind="IMPORTANT_FILES_FOLDER">
|
|
||||||
<itemPath>Makefile</itemPath>
|
|
||||||
</logicalFolder>
|
|
||||||
</logicalFolder>
|
</logicalFolder>
|
||||||
<projectmakefile>Makefile</projectmakefile>
|
<projectmakefile>Makefile</projectmakefile>
|
||||||
<confs>
|
<confs>
|
||||||
@@ -121,6 +112,10 @@
|
|||||||
</item>
|
</item>
|
||||||
<item path="KeyEdit.h" ex="false" tool="3" flavor2="0">
|
<item path="KeyEdit.h" ex="false" tool="3" flavor2="0">
|
||||||
</item>
|
</item>
|
||||||
|
<item path="KeyringIO.cpp" ex="false" tool="1" flavor2="0">
|
||||||
|
</item>
|
||||||
|
<item path="KeyringIO.h" ex="false" tool="3" flavor2="0">
|
||||||
|
</item>
|
||||||
<item path="LoopbackPassphraseProvider.cpp" ex="false" tool="1" flavor2="0">
|
<item path="LoopbackPassphraseProvider.cpp" ex="false" tool="1" flavor2="0">
|
||||||
</item>
|
</item>
|
||||||
<item path="LoopbackPassphraseProvider.h" ex="false" tool="3" flavor2="0">
|
<item path="LoopbackPassphraseProvider.h" ex="false" tool="3" flavor2="0">
|
||||||
@@ -229,6 +224,10 @@
|
|||||||
</item>
|
</item>
|
||||||
<item path="KeyEdit.h" ex="false" tool="3" flavor2="0">
|
<item path="KeyEdit.h" ex="false" tool="3" flavor2="0">
|
||||||
</item>
|
</item>
|
||||||
|
<item path="KeyringIO.cpp" ex="false" tool="1" flavor2="0">
|
||||||
|
</item>
|
||||||
|
<item path="KeyringIO.h" ex="false" tool="3" flavor2="0">
|
||||||
|
</item>
|
||||||
<item path="LoopbackPassphraseProvider.cpp" ex="false" tool="1" flavor2="0">
|
<item path="LoopbackPassphraseProvider.cpp" ex="false" tool="1" flavor2="0">
|
||||||
</item>
|
</item>
|
||||||
<item path="LoopbackPassphraseProvider.h" ex="false" tool="3" flavor2="0">
|
<item path="LoopbackPassphraseProvider.h" ex="false" tool="3" flavor2="0">
|
||||||
@@ -341,6 +340,10 @@
|
|||||||
</item>
|
</item>
|
||||||
<item path="KeyEdit.h" ex="false" tool="3" flavor2="0">
|
<item path="KeyEdit.h" ex="false" tool="3" flavor2="0">
|
||||||
</item>
|
</item>
|
||||||
|
<item path="KeyringIO.cpp" ex="false" tool="1" flavor2="0">
|
||||||
|
</item>
|
||||||
|
<item path="KeyringIO.h" ex="false" tool="3" flavor2="0">
|
||||||
|
</item>
|
||||||
<item path="LoopbackPassphraseProvider.cpp" ex="false" tool="1" flavor2="0">
|
<item path="LoopbackPassphraseProvider.cpp" ex="false" tool="1" flavor2="0">
|
||||||
</item>
|
</item>
|
||||||
<item path="LoopbackPassphraseProvider.h" ex="false" tool="3" flavor2="0">
|
<item path="LoopbackPassphraseProvider.h" ex="false" tool="3" flavor2="0">
|
||||||
|
|||||||
Reference in New Issue
Block a user