Generate key data before download is requested.

Once ExportKeyStreamResource::handleRequest is entered, a 'Save As'
dialog will be opened by the browser, even if key data is empty. This
may happen if passphrase is wrong.

If key data is generated before the download is actually requested, we
can check if there is anything to push to browser and prevent the
download request.
This commit is contained in:
SET
2020-11-25 22:03:12 +01:00
parent 4d5d426f30
commit 608ccbc1bb
4 changed files with 44 additions and 45 deletions

View File

@@ -281,10 +281,20 @@ void KeyringIO::PrepareExport(const WString& fpr, bool isSecret)
} }
else else
{ {
string keyData;
Error e;
GpgMEWorker gpgw;
e = gpgw.ExportPublicKey(fpr.toUTF8().c_str(), keyData);
if (e.code() != 0)
{
m_tmwMessage->SetText(e.asString());
LGE(e);
return;
}
WLink link; WLink link;
shared_ptr<ExportKeyStreamResource> shResource = shared_ptr<ExportKeyStreamResource> shResource =
make_shared<ExportKeyStreamResource> make_shared<ExportKeyStreamResource>
(fpr, isSecret, "appliation/pgp-keys", m_tmwMessage); (keyData, fpr, "application/pgp-keys", m_tmwMessage);
link.setResource(shResource); link.setResource(shResource);
m_btnExport->setLink(link); m_btnExport->setLink(link);
} }
@@ -297,48 +307,55 @@ void KeyringIO::OnPreExportSecretKey(const WString& fpr)
{ {
// On preExport button of popup // On preExport button of popup
WLink link; WLink link;
/*
* Private keys can be exported as from GPGME 1.15.0.
*/
string keyData;
Error e;
GpgMEWorker gpgw; GpgMEWorker gpgw;
Error e = gpgw.CheckPassphrase(fpr.toUTF8().c_str(), e = gpgw.ExportPrivateKey(fpr.toUTF8().c_str(), keyData,
m_popupExportSecretKey->GetPassphrase()); m_popupExportSecretKey->GetPassphrase());
// With bad passphrase, e.code() is still 0.
if (e.code() != 0) if (e.code() != 0)
{ {
m_tmwMessage->SetText(e.asString()); m_tmwMessage->SetText(e.asString());
m_popupExportSecretKey->GetApplyButton()->setLink(link);
m_popupExportSecretKey->GetApplyButton()->disable();
LGE(e); LGE(e);
return; return;
} }
// But keyData.size() is 0.
if (keyData.size() == 0)
{
m_tmwMessage->SetText(TR("NoKeyData"));
m_popupExportSecretKey->GetApplyButton()->setLink(link);
m_popupExportSecretKey->GetApplyButton()->disable();
return;
}
shared_ptr<ExportKeyStreamResource> shResource = shared_ptr<ExportKeyStreamResource> shResource =
make_shared<ExportKeyStreamResource> make_shared<ExportKeyStreamResource>
(fpr, true, "appliation/pgp-keys", m_tmwMessage); (keyData, fpr, "application/pgp-keys", m_tmwMessage);
link.setResource(shResource); link.setResource(shResource);
shResource->SetPassphrase(m_popupExportSecretKey->GetPassphrase());
m_popupExportSecretKey->GetApplyButton()->setLink(link); m_popupExportSecretKey->GetApplyButton()->setLink(link);
m_popupExportSecretKey->GetApplyButton()->enable(); m_popupExportSecretKey->GetApplyButton()->enable();
} }
ExportKeyStreamResource::ExportKeyStreamResource(const WString& fpr, ExportKeyStreamResource::ExportKeyStreamResource(const string& keyData,
bool isSecret, const WString& fpr,
TransientMessageWidget * tmw) TransientMessageWidget * tmw)
: WStreamResource() : WStreamResource()
{ {
m_fpr = fpr; m_fpr = fpr;
m_isSecret = isSecret; m_keyData = keyData;
m_passphrase = WString::Empty;
m_tmwMessage = tmw; m_tmwMessage = tmw;
} }
ExportKeyStreamResource::ExportKeyStreamResource(const WString& fpr, ExportKeyStreamResource::ExportKeyStreamResource(const string& keyData,
bool isSecret, const WString& fpr,
const string& mimeType, const string& mimeType,
TransientMessageWidget * tmw) TransientMessageWidget * tmw)
: WStreamResource(mimeType) : WStreamResource(mimeType)
{ {
m_fpr = fpr; m_fpr = fpr;
m_isSecret = isSecret; m_keyData = keyData;
m_passphrase = WString::Empty;
m_tmwMessage = tmw; m_tmwMessage = tmw;
} }
@@ -350,25 +367,8 @@ ExportKeyStreamResource::~ExportKeyStreamResource()
void ExportKeyStreamResource::handleRequest(const Http::Request& request, void ExportKeyStreamResource::handleRequest(const Http::Request& request,
Http::Response& response) Http::Response& response)
{ {
/*
* Private keys can be exported as from GPGME 1.15.0.
*/
string buffer;
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());
LGE(e);
return;
}
suggestFileName(m_fpr + WString(".asc"), ContentDisposition::Attachment); suggestFileName(m_fpr + WString(".asc"), ContentDisposition::Attachment);
istrstream bufStream(buffer.c_str()); istrstream bufStream(m_keyData.c_str());
handleRequestPiecewise(request, response, bufStream); handleRequestPiecewise(request, response, bufStream);
} }

View File

@@ -53,7 +53,7 @@ private:
WPushButton * m_btnCreate; WPushButton * m_btnCreate;
WPushButton * m_btnExport; WPushButton * m_btnExport;
WLineEdit * m_leSearch; WLineEdit * m_leSearch;
// Used to disconnect m_btnExport from previous slot. // Used to disconnect m_btnExport from previous slot.
Signals::connection m_exportSecretConnection; Signals::connection m_exportSecretConnection;
@@ -122,9 +122,11 @@ private:
class ExportKeyStreamResource : public WStreamResource class ExportKeyStreamResource : public WStreamResource
{ {
public: public:
ExportKeyStreamResource(const WString& fpr, bool isSecret, ExportKeyStreamResource(const string& keyData,
const WString& fpr,
TransientMessageWidget * tmw); TransientMessageWidget * tmw);
ExportKeyStreamResource(const WString& fpr, bool isSecret, ExportKeyStreamResource(const string& keyData,
const WString& fpr,
const string& mimeType, const string& mimeType,
TransientMessageWidget * tmw); TransientMessageWidget * tmw);
virtual ~ExportKeyStreamResource(); virtual ~ExportKeyStreamResource();
@@ -135,15 +137,10 @@ public:
*/ */
void handleRequest(const Http::Request& request, void handleRequest(const Http::Request& request,
Http::Response& response) override; Http::Response& response) override;
void SetPassphrase(const WString& passphrase)
{
m_passphrase = passphrase;
}
private: private:
WString m_fpr; WString m_fpr;
bool m_isSecret; string m_keyData;
WString m_passphrase;
TransientMessageWidget * m_tmwMessage; TransientMessageWidget * m_tmwMessage;
}; };

View File

@@ -136,6 +136,7 @@
<message id='PreExportSecretKey'>Prepare download link</message> <message id='PreExportSecretKey'>Prepare download link</message>
<message id='ExportSecretKey'>Export secret key</message> <message id='ExportSecretKey'>Export secret key</message>
<message id='TTTExportSecretKey'>Requires GPGME >= 1.15.0</message> <message id='TTTExportSecretKey'>Requires GPGME >= 1.15.0</message>
<message id='NoKeyData'>No data</message>
<message id='AddUid'>Add an identity</message> <message id='AddUid'>Add an identity</message>
<message id='RevokeUid'>Revoke identity</message> <message id='RevokeUid'>Revoke identity</message>

View File

@@ -134,8 +134,9 @@
<message id='Export'>Exporter</message> <message id='Export'>Exporter</message>
<message id='PreExportSecretKey'>Préparer le téléchargement</message> <message id='PreExportSecretKey'>Préparer le téléchargement</message>
<message id='ExportSecretKey'>Exporter la secrète</message> <message id='ExportSecretKey'>Exporter la clé secrète</message>
<message id='TTTExportSecretKey'>Requiert GPGME >= 1.15.0</message> <message id='TTTExportSecretKey'>Requiert GPGME >= 1.15.0</message>
<message id='NoKeyData'>Aucune donnée</message>
<message id='AddUid'>Ajouter une identité</message> <message id='AddUid'>Ajouter une identité</message>
<message id='RevokeUid'>Revoquer une identité</message> <message id='RevokeUid'>Revoquer une identité</message>