summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndre Heinecke <aheinecke@intevation.de>2016-04-29 08:17:21 (GMT)
committerAndre Heinecke <aheinecke@intevation.de>2016-08-02 09:57:07 (GMT)
commit7e19bcc30084028fd2d344b6299ed09899dcbc12 (patch)
tree2ebd389090d81db17521523839f06c6c200022da
parent60e9f5d25b75e222ab8350aa9199a2267d097a00 (diff)
Add support for output file name changing
The Output filenames are also used to indicate the status of an operation. E.g. if you select CMS and OpenPGP Certificates together it will make it visibile that this will cause two files to be created. In case no operation is requested the Output group was otherwise empty.
-rw-r--r--src/crypto/gui/signencryptfileswizard.cpp123
-rw-r--r--src/crypto/gui/signencryptfileswizard.h12
-rw-r--r--src/crypto/gui/signencryptwidget.cpp4
-rw-r--r--src/crypto/gui/signencryptwidget.h4
-rw-r--r--src/crypto/signencryptfilescontroller.cpp117
5 files changed, 211 insertions, 49 deletions
diff --git a/src/crypto/gui/signencryptfileswizard.cpp b/src/crypto/gui/signencryptfileswizard.cpp
index 76010ab..f6a85a7 100644
--- a/src/crypto/gui/signencryptfileswizard.cpp
+++ b/src/crypto/gui/signencryptfileswizard.cpp
@@ -42,8 +42,13 @@
#include <KMessageBox>
#include "kleopatra_debug.h"
+
+#include <Libkleo/FileNameRequester>
#include <QVBoxLayout>
#include <QWizardPage>
+#include <QGroupBox>
+#include <QLabel>
+#include <QIcon>
#include <QPointer>
@@ -84,18 +89,31 @@ FIXME: Either show this warning or fix detached signatures for archives.
class SigEncPage: public QWizardPage
{
Q_OBJECT
+
public:
explicit SigEncPage(QWidget *parent = Q_NULLPTR)
: QWizardPage(parent),
- mWidget(new SignEncryptWidget)
+ mWidget(new SignEncryptWidget),
+ mOutLayout(new QVBoxLayout)
{
setTitle(i18nc("@title", "Sign / Encrypt Files"));
- QVBoxLayout *vLay = new QVBoxLayout(this);
+ auto vLay = new QVBoxLayout(this);
vLay->addWidget(mWidget);
connect(mWidget, &SignEncryptWidget::operationChanged, this,
&SigEncPage::updateCommitButton);
+ connect(mWidget, &SignEncryptWidget::keysChanged, this,
+ &SigEncPage::updateFileWidgets);
setLayout(vLay);
updateCommitButton(mWidget->currentOp());
+
+ auto outputGrp = new QGroupBox(i18n("Output"));
+ outputGrp->setLayout(mOutLayout);
+
+ mPlaceholderWidget = new QLabel(i18n("Please select an action."));
+ mOutLayout->addWidget(mPlaceholderWidget);
+
+ vLay->addWidget(outputGrp);
+ setMinimumHeight(480);
}
bool isComplete() const Q_DECL_OVERRIDE
@@ -108,11 +126,13 @@ public:
return ResultPageId;
}
- void initializePage() Q_DECL_OVERRIDE {
+ void initializePage() Q_DECL_OVERRIDE
+ {
setCommitPage(true);
}
- bool validatePage() Q_DECL_OVERRIDE {
+ bool validatePage() Q_DECL_OVERRIDE
+ {
if (!mWidget->selfKey().isNull()) {
return true;
}
@@ -158,6 +178,57 @@ public:
return ret;
}
+private:
+ QWidget *createRequester(int forKind, QBoxLayout *lay) {
+ static const QMap <int, QString> icons = {
+ { SignEncryptFilesWizard::SignatureCMS, QStringLiteral("document-sign") },
+ { SignEncryptFilesWizard::SignaturePGP, QStringLiteral("document-sign") },
+ { SignEncryptFilesWizard::CombinedPGP, QStringLiteral("document-edit-sign-encrypt") },
+ { SignEncryptFilesWizard::EncryptedPGP, QStringLiteral("document-encrypt") },
+ { SignEncryptFilesWizard::EncryptedCMS, QStringLiteral("document-encrypt") }
+ };
+ static const QMap <int, QString> toolTips = {
+ { SignEncryptFilesWizard::SignatureCMS, i18n("The S/MIME signature.") },
+ { SignEncryptFilesWizard::SignaturePGP, i18n("The signature.") },
+ { SignEncryptFilesWizard::CombinedPGP, i18n("The signed and encrypted file.") },
+ { SignEncryptFilesWizard::EncryptedPGP, i18n("The encrypted file.") },
+ { SignEncryptFilesWizard::EncryptedCMS, i18n("The S/MIME encrypted file.") }
+ };
+
+ FileNameRequester *req = new FileNameRequester(QDir::Files, this);
+ req->setFileName(mOutNames[forKind]);
+ QHBoxLayout *hLay = new QHBoxLayout;
+ QLabel *iconLabel = new QLabel;
+ QWidget *ret = new QWidget;
+ iconLabel->setPixmap(QIcon::fromTheme(icons[forKind]).pixmap(32,32));
+ hLay->addWidget(iconLabel);
+ iconLabel->setToolTip(toolTips[forKind]);
+ req->setToolTip(toolTips[forKind]);
+ hLay->addWidget(req);
+ ret->setLayout(hLay);
+ lay->addWidget(ret);
+
+ connect (req, &FileNameRequester::fileNameChanged, this,
+ [this, forKind](const QString &newName) {
+ mOutNames[forKind] = newName;
+ });
+ return ret;
+ }
+
+public:
+ void setOutputNames(const QMap<int, QString> &names) {
+ assert(mOutNames.isEmpty());
+ mOutNames = names;
+ Q_FOREACH (int i, mOutNames.keys()) {
+ mRequester[i] = createRequester(i, mOutLayout);
+ }
+ updateFileWidgets();
+ }
+
+ QMap <int, QString> outputNames() const {
+ return mOutNames;
+ }
+
private Q_SLOTS:
void updateCommitButton(const QString &label)
{
@@ -169,8 +240,42 @@ private Q_SLOTS:
Q_EMIT completeChanged();
}
+ void updateFileWidgets()
+ {
+ if (mRequester.isEmpty()) {
+ return;
+ }
+ const QVector<Key> recipients = mWidget->recipients();
+ const Key sigKey = mWidget->signKey();
+ bool pgp = false;
+ bool cms = false;
+
+ Q_FOREACH (const Key k, recipients) {
+ if (pgp && cms) {
+ break;
+ }
+ if (k.protocol() == Protocol::OpenPGP) {
+ pgp = true;
+ } else {
+ cms = true;
+ }
+ }
+ mOutLayout->setEnabled(false);
+ mPlaceholderWidget->setVisible(!cms && !pgp);
+ mRequester[SignEncryptFilesWizard::SignatureCMS]->setVisible(sigKey.protocol() == Protocol::CMS);
+ mRequester[SignEncryptFilesWizard::EncryptedCMS]->setVisible(cms);
+ mRequester[SignEncryptFilesWizard::CombinedPGP]->setVisible(sigKey.protocol() == Protocol::OpenPGP && pgp);
+ mRequester[SignEncryptFilesWizard::EncryptedPGP]->setVisible(pgp && sigKey.protocol() != Protocol::OpenPGP);
+ mRequester[SignEncryptFilesWizard::SignaturePGP]->setVisible(sigKey.protocol() == Protocol::OpenPGP && !pgp);
+ mOutLayout->setEnabled(true);
+ }
+
private:
SignEncryptWidget *mWidget;
+ QMap <int, QString> mOutNames;
+ QMap <int, QWidget *> mRequester;
+ QVBoxLayout *mOutLayout;
+ QWidget *mPlaceholderWidget;
};
class ResultPage : public NewResultPage
@@ -261,4 +366,14 @@ void SignEncryptFilesWizard::setTaskCollection(const boost::shared_ptr<Kleo::Cry
mResultPage->setTaskCollection(coll);
}
+void SignEncryptFilesWizard::setOutputNames(const QMap<int, QString> &map) const
+{
+ mSigEncPage->setOutputNames(map);
+}
+
+QMap<int, QString> SignEncryptFilesWizard::outputNames() const
+{
+ return mSigEncPage->outputNames();
+}
+
#include "signencryptfileswizard.moc"
diff --git a/src/crypto/gui/signencryptfileswizard.h b/src/crypto/gui/signencryptfileswizard.h
index 0a0030b..4468b24 100644
--- a/src/crypto/gui/signencryptfileswizard.h
+++ b/src/crypto/gui/signencryptfileswizard.h
@@ -40,6 +40,7 @@
#include <QWizard>
#include <QVector>
+#include <QMap>
#include <boost/shared_ptr.hpp>
@@ -69,6 +70,14 @@ class SignEncryptFilesWizard : public QWizard
{
Q_OBJECT
public:
+ enum KindNames{
+ SignatureCMS,
+ CombinedPGP,
+ EncryptedPGP,
+ EncryptedCMS,
+ SignaturePGP
+ };
+
explicit SignEncryptFilesWizard(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = 0);
~SignEncryptFilesWizard();
@@ -79,6 +88,9 @@ public:
void setEncryptionPreset(bool preset);
void setEncryptionUserMutable(bool mut);
+ void setOutputNames(const QMap<int, QString> &nameMap) const;
+ QMap<int, QString> outputNames() const;
+
void setTaskCollection(const boost::shared_ptr<Kleo::Crypto::TaskCollection> &coll);
// Outputs
diff --git a/src/crypto/gui/signencryptwidget.cpp b/src/crypto/gui/signencryptwidget.cpp
index 36aa5c1..c3e8064 100644
--- a/src/crypto/gui/signencryptwidget.cpp
+++ b/src/crypto/gui/signencryptwidget.cpp
@@ -127,7 +127,6 @@ void SignEncryptWidget::addRecipient()
true);
mRecpWidgets << certSel;
mRecpLayout->insertWidget(mRecpLayout->count() - 1, certSel);
- qCDebug(KLEOPATRA_LOG) << "Adding recipient widget.";
connect(certSel, &CertificateSelectionWidget::keyChanged,
this, &SignEncryptWidget::recipientsChanged);
}
@@ -144,6 +143,7 @@ void SignEncryptWidget::recipientsChanged()
if (!oneEmpty) {
addRecipient();
}
+ updateOp();
}
Key SignEncryptWidget::signKey() const
@@ -186,6 +186,7 @@ void SignEncryptWidget::updateOp()
{
const Key sigKey = signKey();
const QVector<Key> recp = recipients();
+
QString newOp;
if (!sigKey.isNull() && !recp.isEmpty()) {
newOp = i18nc("@action", "Sign / Encrypt");
@@ -200,6 +201,7 @@ void SignEncryptWidget::updateOp()
mOp = newOp;
Q_EMIT operationChanged(mOp);
}
+ Q_EMIT keysChanged();
}
QString SignEncryptWidget::currentOp() const
diff --git a/src/crypto/gui/signencryptwidget.h b/src/crypto/gui/signencryptwidget.h
index 487a280..1578774 100644
--- a/src/crypto/gui/signencryptwidget.h
+++ b/src/crypto/gui/signencryptwidget.h
@@ -33,6 +33,7 @@
#include <QWidget>
#include <QVector>
+#include <QMap>
#include <gpgme++/key.h>
class QVBoxLayout;
@@ -76,6 +77,9 @@ Q_SIGNALS:
* If no crypto operation is selected this returns a null string. */
void operationChanged(const QString &op);
+ /* Emitted when the certificate selection might be changed. */
+ void keysChanged();
+
private:
CertificateSelectionWidget *mSigSelect,
*mSelfSelect;
diff --git a/src/crypto/signencryptfilescontroller.cpp b/src/crypto/signencryptfilescontroller.cpp
index 14bcb9e..3a678d6 100644
--- a/src/crypto/signencryptfilescontroller.cpp
+++ b/src/crypto/signencryptfilescontroller.cpp
@@ -37,14 +37,15 @@
#include "signencryptfilestask.h"
#include "certificateresolver.h"
-#include <crypto/gui/signencryptfileswizard.h>
-#include <crypto/taskcollection.h>
+#include "crypto/gui/signencryptfileswizard.h"
+#include "crypto/taskcollection.h"
-#include <utils/input.h>
-#include <utils/output.h>
-#include <utils/classify.h>
-#include <utils/kleo_assert.h>
-#include <utils/archivedefinition.h>
+#include "utils/input.h"
+#include "utils/output.h"
+#include "utils/classify.h"
+#include "utils/kleo_assert.h"
+#include "utils/archivedefinition.h"
+#include "utils/path-helper.h"
#include <Libkleo/Stl_Util>
#include <Libkleo/Exception>
@@ -57,6 +58,7 @@
#include <QPointer>
#include <QTimer>
#include <QFileInfo>
+#include <QDir>
#include <boost/bind.hpp>
@@ -267,6 +269,47 @@ unsigned int SignEncryptFilesController::operationMode() const
return d->operation;
}
+static const char *extension(bool pgp, bool sign, bool encrypt, bool ascii, bool detached)
+{
+ unsigned int cls = pgp ? Class::OpenPGP : Class::CMS;
+ if (encrypt) {
+ cls |= Class::CipherText;
+ } else if (sign) {
+ cls |= detached ? Class::DetachedSignature : Class::OpaqueSignature;
+ }
+ cls |= ascii ? Class::Ascii : Class::Binary;
+ if (const char *const ext = outputFileExtension(cls)) {
+ return ext;
+ } else {
+ return "out";
+ }
+}
+
+static QMap <int, QString> buildOutputNames(const QStringList &files)
+{
+ QMap <int, QString> nameMap;
+
+ // Build the default names for the wizard.
+ QString baseName;
+ if (files.size() > 1) {
+ baseName = QDir(heuristicBaseDirectory(files)).absoluteFilePath(
+ i18nc("base name of an archive file, e.g. archive.zip or archive.tar.gz", "archive"));
+ std::vector<boost::shared_ptr<ArchiveDefinition> > ads = ArchiveDefinition::getArchiveDefinitions();
+ assert(!ads.empty());
+ // TODO read from config
+ boost::shared_ptr<ArchiveDefinition> ad = ads.front();
+ baseName += QStringLiteral(".") + ad->extensions(GpgME::CMS).first();
+ } else {
+ baseName = files.first() + QStringLiteral(".");
+ }
+ nameMap.insert(SignEncryptFilesWizard::SignatureCMS, baseName + extension(false, true, false, false, true));
+ nameMap.insert(SignEncryptFilesWizard::EncryptedCMS, baseName + extension(false, false, true, false, false));
+ nameMap.insert(SignEncryptFilesWizard::CombinedPGP, baseName + extension(true, true, true, false, false));
+ nameMap.insert(SignEncryptFilesWizard::EncryptedPGP, baseName + extension(true, false, true, false, false));
+ nameMap.insert(SignEncryptFilesWizard::SignaturePGP, baseName + extension(true, true, false, false, true));
+ return nameMap;
+}
+
void SignEncryptFilesController::setFiles(const QStringList &files)
{
kleo_assert(!files.empty());
@@ -275,6 +318,7 @@ void SignEncryptFilesController::setFiles(const QStringList &files)
setOperationMode((operationMode() & ~ArchiveMask) | ArchiveForced);
}
d->ensureWizardCreated();
+ d->wizard->setOutputNames(buildOutputNames(files));
}
void SignEncryptFilesController::Private::slotWizardCanceled()
@@ -288,22 +332,6 @@ void SignEncryptFilesController::start()
d->ensureWizardVisible();
}
-static const char *extension(bool pgp, bool sign, bool encrypt, bool ascii, bool detached)
-{
- unsigned int cls = pgp ? Class::OpenPGP : Class::CMS;
- if (encrypt) {
- cls |= Class::CipherText;
- } else if (sign) {
- cls |= detached ? Class::DetachedSignature : Class::OpaqueSignature;
- }
- cls |= ascii ? Class::Ascii : Class::Binary;
- if (const char *const ext = outputFileExtension(cls)) {
- return ext;
- } else {
- return "out";
- }
-}
-
static shared_ptr<SignEncryptFilesTask>
createSignEncryptTaskForFileInfo(const QFileInfo &fi, bool pgp, bool ascii, const std::vector<Key> &recipients, const std::vector<Key> &signers)
{
@@ -313,10 +341,14 @@ createSignEncryptTaskForFileInfo(const QFileInfo &fi, bool pgp, bool ascii, cons
task->setSign(true);
task->setSigners(signers);
task->setDetachedSignature(true);
+ } else {
+ task->setSign(false);
}
if (!recipients.empty()) {
task->setEncrypt(true);
task->setRecipients(recipients);
+ } else {
+ task->setSign(false);
}
const QString input = fi.absoluteFilePath();
@@ -333,18 +365,22 @@ createSignEncryptTaskForFileInfo(const QFileInfo &fi, bool pgp, bool ascii, cons
}
static shared_ptr<SignEncryptFilesTask>
-createArchiveSignEncryptTaskForFiles(const QStringList &files, const QString &outputFileBaseName, const shared_ptr<ArchiveDefinition> &ad, bool pgp, bool sign, bool encrypt, bool ascii, const std::vector<Key> &recipients, const std::vector<Key> &signers)
+createArchiveSignEncryptTaskForFiles(const QStringList &files, const QString &outputName, const shared_ptr<ArchiveDefinition> &ad, bool pgp, bool ascii, const std::vector<Key> &recipients, const std::vector<Key> &signers)
{
const shared_ptr<SignEncryptFilesTask> task(new SignEncryptFilesTask);
- task->setSign(sign);
- task->setEncrypt(encrypt);
task->setAsciiArmor(ascii);
- if (sign) {
+ if (!signers.empty()) {
+ task->setSign(true);
task->setSigners(signers);
task->setDetachedSignature(false);
+ } else {
+ task->setSign(false);
}
- if (encrypt) {
+ if (!recipients.empty()) {
+ task->setEncrypt(true);
task->setRecipients(recipients);
+ } else {
+ task->setEncrypt(false);
}
kleo_assert(ad);
@@ -354,17 +390,13 @@ createArchiveSignEncryptTaskForFiles(const QStringList &files, const QString &ou
task->setInputFileNames(files);
task->setInput(ad->createInputFromPackCommand(proto, files));
- const char *const ext = extension(pgp, sign, encrypt, ascii, false);
- kleo_assert(ext);
- kleo_assert(!ad->extensions(proto).empty());
-
- task->setOutputFileName(outputFileBaseName + QLatin1Char('.') + QLatin1String(ext));
+ task->setOutputFileName(outputName);
return task;
}
static std::vector< shared_ptr<SignEncryptFilesTask> >
-createSignEncryptTasksForFileInfo(const QFileInfo &fi, bool ascii, const std::vector<Key> &pgpRecipients, const std::vector<Key> &pgpSigners, const std::vector<Key> &cmsRecipients, const std::vector<Key> &cmsSigners)
+createSignEncryptTasksForFileInfo(const QFileInfo &fi, bool ascii, const std::vector<Key> &pgpRecipients, const std::vector<Key> &pgpSigners, const std::vector<Key> &cmsRecipients, const std::vector<Key> &cmsSigners, const QMap<int, QString> outNames)
{
std::vector< shared_ptr<SignEncryptFilesTask> > result;
@@ -385,25 +417,21 @@ createSignEncryptTasksForFileInfo(const QFileInfo &fi, bool ascii, const std::ve
}
static std::vector< shared_ptr<SignEncryptFilesTask> >
-createArchiveSignEncryptTasksForFiles(const QStringList &files, const QString &pgpOutputFileBaseName, const QString &cmsOutputFileBaseName, const shared_ptr<ArchiveDefinition> &ad, bool sign, bool encrypt, bool ascii, const std::vector<Key> &pgpRecipients, const std::vector<Key> &pgpSigners, const std::vector<Key> &cmsRecipients, const std::vector<Key> &cmsSigners)
+createArchiveSignEncryptTasksForFiles(const QStringList &files, const QString &pgpOutputFileName, const QString &cmsOutputFileName, const shared_ptr<ArchiveDefinition> &ad, bool sign, bool encrypt, bool ascii, const std::vector<Key> &pgpRecipients, const std::vector<Key> &pgpSigners, const std::vector<Key> &cmsRecipients, const std::vector<Key> &cmsSigners)
{
std::vector< shared_ptr<SignEncryptFilesTask> > result;
- const bool shallPgpSign = sign && !pgpSigners.empty();
- const bool shallPgpEncrypt = encrypt && !pgpRecipients.empty();
- const bool pgp = (shallPgpEncrypt && (!sign || shallPgpSign)) || (!encrypt && shallPgpSign);
+ const bool pgp = !pgpSigners.empty() || !pgpRecipients.empty();
- const bool shallCmsSign = sign && !cmsSigners.empty();
- const bool shallCmsEncrypt = encrypt && !cmsRecipients.empty();
- const bool cms = (shallCmsEncrypt && (!sign || shallCmsSign)) || (!encrypt && shallCmsSign);
+ const bool cms = !cmsSigners.empty() || !cmsRecipients.empty();
result.reserve(pgp + cms);
if (pgp) {
- result.push_back(createArchiveSignEncryptTaskForFiles(files, pgpOutputFileBaseName, ad, true, sign, encrypt, ascii, pgpRecipients, pgpSigners));
+ result.push_back(createArchiveSignEncryptTaskForFiles(files, pgpOutputFileName, ad, true, ascii, pgpRecipients, pgpSigners));
}
if (cms) {
- result.push_back(createArchiveSignEncryptTaskForFiles(files, cmsOutputFileBaseName, ad, false, sign, encrypt, ascii, cmsRecipients, cmsSigners));
+ result.push_back(createArchiveSignEncryptTaskForFiles(files, cmsOutputFileName, ad, false, ascii, cmsRecipients, cmsSigners));
}
return result;
@@ -462,7 +490,8 @@ void SignEncryptFilesController::Private::slotWizardOperationPrepared()
pgpRecipients.toStdVector(),
pgpSigners.toStdVector(),
cmsRecipients.toStdVector(),
- cmsSigners.toStdVector());
+ cmsSigners.toStdVector(),
+ wizard->outputNames());
tasks.insert(tasks.end(), created.begin(), created.end());
}
}