aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorubbo <ubbo@34ebc366-c3a9-4b3c-9f84-69acf7962910>2012-08-03 20:38:27 +0000
committerubbo <ubbo@34ebc366-c3a9-4b3c-9f84-69acf7962910>2012-08-03 20:38:27 +0000
commita274da36798b7aa7a7cbc9e85ec30748fa66047e (patch)
treeb5f4e5403ecae4a86a28f8e58925c2a2f1e01db0
parentreorganize kgpg source tree (diff)
downloadgpg4usb-a274da36798b7aa7a7cbc9e85ec30748fa66047e.tar.gz
gpg4usb-a274da36798b7aa7a7cbc9e85ec30748fa66047e.zip
start porting encrypt from kgpg, not yet working
git-svn-id: http://cpunk.de/svn/src/gpg4usb/branches/0.3.2-mac@932 34ebc366-c3a9-4b3c-9f84-69acf7962910
-rw-r--r--gpg4usb.pro11
-rw-r--r--gpgcontext.cpp17
-rw-r--r--kgpg/kgpginterface.cpp20
-rw-r--r--kgpg/kprocess.cpp2
-rw-r--r--kgpg/transactions/kgpgencrypt.cpp154
-rw-r--r--kgpg/transactions/kgpgencrypt.h94
-rw-r--r--kgpg/transactions/kgpgtextorfiletransaction.cpp150
-rw-r--r--kgpg/transactions/kgpgtextorfiletransaction.h109
-rw-r--r--kgpg/transactions/kgpgtransaction.cpp543
-rw-r--r--kgpg/transactions/kgpgtransaction.h465
-rw-r--r--mainwindow.cpp27
-rw-r--r--mainwindow.h2
12 files changed, 1581 insertions, 13 deletions
diff --git a/gpg4usb.pro b/gpg4usb.pro
index 84bc18c..5d90051 100644
--- a/gpg4usb.pro
+++ b/gpg4usb.pro
@@ -46,6 +46,7 @@ HEADERS += attachments.h \
kgpg/kprocess.h \
kgpg/kprocess_p.h \
kgpg/kgpginterface.h \
+ gpgconstants.h \
kgpg/core/kgpgkey.h \
kgpg/core/KGpgSignableNode.h \
kgpg/core/KGpgExpandableNode.h \
@@ -62,7 +63,10 @@ HEADERS += attachments.h \
kgpg/core/KGpgOrphanNode.h \
kgpg/core/convert.h \
kgpg/core/images.h \
- gpgconstants.h
+ kgpg/transactions/kgpgtransaction.h \
+ kgpg/transactions/kgpgtextorfiletransaction.h \
+ kgpg/transactions/kgpgencrypt.h
+
SOURCES += attachments.cpp \
gpgcontext.cpp \
@@ -87,6 +91,7 @@ SOURCES += attachments.cpp \
verifykeydetailbox.cpp \
wizard.cpp \
helppage.cpp \
+ gpgconstants.cpp \
kgpg/gpgproc.cpp \
kgpg/klinebufferedprocess.cpp \
kgpg/kprocess.cpp \
@@ -107,7 +112,9 @@ SOURCES += attachments.cpp \
kgpg/core/KGpgOrphanNode.cpp \
kgpg/core/convert.cpp \
kgpg/core/images.cpp \
- gpgconstants.cpp
+ kgpg/transactions/kgpgtransaction.cpp \
+ kgpg/transactions/kgpgtextorfiletransaction.cpp \
+ kgpg/transactions/kgpgencrypt.cpp
RC_FILE = gpg4usb.rc
diff --git a/gpgcontext.cpp b/gpgcontext.cpp
index f87ed11..a6dec21 100644
--- a/gpgcontext.cpp
+++ b/gpgcontext.cpp
@@ -24,6 +24,7 @@
#include "kgpg/kgpginterface.h"
#include "kgpg/klinebufferedprocess.h"
#include "kgpg/core/kgpgkey.h"
+#include "kgpg/transactions/kgpgencrypt.h"
#ifdef _WIN32
#include <windows.h>
#include <unistd.h> /* contains read/write */
@@ -274,7 +275,7 @@ void GpgContext::deleteKeys(QStringList *uidList)
bool GpgContext::encrypt(QStringList *uidList, const QByteArray &inBuffer, QByteArray *outBuffer)
{
- gpgme_data_t in = 0, out = 0;
+ /*gpgme_data_t in = 0, out = 0;
outBuffer->resize(0);
if (uidList->count() == 0) {
@@ -285,7 +286,7 @@ bool GpgContext::encrypt(QStringList *uidList, const QByteArray &inBuffer, QByte
//gpgme_encrypt_result_t e_result;
gpgme_key_t recipients[uidList->count()+1];
- /* get key for user */
+ // get key for user
for (int i = 0; i < uidList->count(); i++) {
// the last 0 is for public keys, 1 would return private keys
gpgme_op_keylist_start(mCtx, uidList->at(i).toAscii().constData(), 0);
@@ -312,7 +313,7 @@ bool GpgContext::encrypt(QStringList *uidList, const QByteArray &inBuffer, QByte
}
}
}
- /* unref all keys */
+ // unref all keys
for (int i = 0; i <= uidList->count(); i++) {
gpgme_key_unref(recipients[i]);
}
@@ -322,9 +323,17 @@ bool GpgContext::encrypt(QStringList *uidList, const QByteArray &inBuffer, QByte
if (out) {
gpgme_data_release(out);
}
- return (err == GPG_ERR_NO_ERROR);
+ return (err == GPG_ERR_NO_ERROR);*/
+ QStringList options;
+ KGpgEncrypt::EncryptOptions opts = KGpgEncrypt::DefaultEncryption;
+
+ //KGpgEncrypt *encr = new KGpgEncrypt(this, uidList, toPlainText(), opts, options);
+ //encr->start();
+ //connect(encr, SIGNAL(done(int)), SLOT(slotEncodeUpdate(int)));
}
+
+
/** Decrypt QByteAarray, return QByteArray
* mainly from http://basket.kde.org/ (kgpgme.cpp)
*/
diff --git a/kgpg/kgpginterface.cpp b/kgpg/kgpginterface.cpp
index 0c14b33..a907fe3 100644
--- a/kgpg/kgpginterface.cpp
+++ b/kgpg/kgpginterface.cpp
@@ -35,6 +35,7 @@
#include <QString>
#include <QTextStream>
#include <QDebug>
+#include <QInputDialog>
using namespace KgpgCore;
@@ -143,28 +144,37 @@ void KgpgInterface::setGpgBoolSetting(const QString &name, const bool enable, co
}
}
-/*int KgpgInterface::sendPassphrase(const QString &text, KProcess *process, QWidget *widget)
+int KgpgInterface::sendPassphrase(const QString &text, KProcess *process, QWidget *widget)
{
QPointer<KProcess> gpgprocess = process;
QByteArray passphrase;
- int code;
+ //int code;
+ bool result;
- QPointer<KPasswordDialog> dlg = new KPasswordDialog(widget);
+ /*QPointer<KPasswordDialog> dlg = new KPasswordDialog(widget);
QObject::connect(process, SIGNAL(processExited()), dlg->button(KDialog::Cancel), SLOT(click()));
dlg->setPrompt(text);
- code = dlg->exec();
+ code = dlg->exec();
+
if (!dlg.isNull())
passphrase = dlg->password().toUtf8();
delete dlg;
if (code != KPasswordDialog::Accepted)
return 1;
+*/
+
+ QString password = QInputDialog::getText(QApplication::activeWindow(), QObject::tr("Enter Password"),
+ text, QLineEdit::Password,
+ "", &result);
+
+ passphrase = password.toAscii();
if (!gpgprocess.isNull())
gpgprocess->write(passphrase + '\n');
return 0;
-}*/
+}
/**
* @param p the process that reads the GnuPG data
diff --git a/kgpg/kprocess.cpp b/kgpg/kprocess.cpp
index ba71ebd..907c75c 100644
--- a/kgpg/kprocess.cpp
+++ b/kgpg/kprocess.cpp
@@ -341,7 +341,7 @@ QStringList KProcess::program() const
void KProcess::start()
{
Q_D(KProcess);
- //qDebug() << "prog: " << d->prog << " | args: " << d->args;
+ qDebug() << "prog: " << d->prog << " | args: " << d->args;
QProcess::start(d->prog, d->args, d->openMode);
}
diff --git a/kgpg/transactions/kgpgencrypt.cpp b/kgpg/transactions/kgpgencrypt.cpp
new file mode 100644
index 0000000..4891bf0
--- /dev/null
+++ b/kgpg/transactions/kgpgencrypt.cpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2011,2012 Rolf Eike Beer <[email protected]>
+ */
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+
+#include "kgpgencrypt.h"
+
+//#include "kgpgsettings.h"
+#include "../gpgproc.h"
+
+//#include <kio/renamedialog.h>
+//#include <KLocale>
+#include <QPointer>
+
+static QStringList trustOptions(const QString &binary)
+{
+ const int gpgver = GPGProc::gpgVersion(GPGProc::gpgVersionString(binary));
+ QStringList args;
+ if (gpgver >= 0x10302)
+ args << QLatin1String("--trust-model")
+ << QLatin1String("always");
+ else
+ args << QLatin1String("--always-trust");
+
+ return args;
+}
+
+KGpgEncrypt::KGpgEncrypt(QObject *parent, const QStringList &userIds, const QString &text, const EncryptOptions &options, const QStringList &extraOptions)
+ : KGpgTextOrFileTransaction(parent, text),
+ m_fileIndex(-1),
+ m_options(options),
+ m_userIds(userIds),
+ m_extraOptions(extraOptions)
+{
+ if ((m_options & AllowUntrustedEncryption) && !m_userIds.isEmpty())
+ m_extraOptions << trustOptions(getProcess()->program().at(0));
+}
+
+KGpgEncrypt::KGpgEncrypt(QObject *parent, const QStringList &userIds, const QList<QUrl> &files, const EncryptOptions &options, const QStringList &extraOptions)
+ : KGpgTextOrFileTransaction(parent, files),
+ m_fileIndex(0),
+ m_options(options),
+ m_userIds(userIds),
+ m_extraOptions(extraOptions)
+{
+ if ((m_options & AllowUntrustedEncryption) && !m_userIds.isEmpty())
+ m_extraOptions << trustOptions(getProcess()->program().at(0));
+}
+
+KGpgEncrypt::~KGpgEncrypt()
+{
+}
+
+QStringList
+KGpgEncrypt::command() const
+{
+ QStringList ret = m_extraOptions;
+
+ if (m_options.testFlag(AsciiArmored))
+ ret << QLatin1String("--armor");
+
+ if (m_userIds.isEmpty()) {
+ ret << QLatin1String( "--symmetric" );
+ } else {
+ if (m_options.testFlag(HideKeyId))
+ ret << QLatin1String("--throw-keyid");
+
+ foreach (const QString &uid, m_userIds)
+ ret << QLatin1String( "--recipient" ) << uid;
+ ret << QLatin1String( "--encrypt" );
+ }
+
+ return ret;
+}
+
+QStringList
+KGpgEncrypt::encryptedText() const
+{
+ QStringList result;
+ int txtlength = 0;
+
+ foreach (const QString &line, getMessages())
+ if (!line.startsWith(QLatin1String("[GNUPG:] "))) {
+ result.append(line);
+ txtlength += line.length() + 1;
+ }
+
+ return result;
+}
+
+bool
+KGpgEncrypt::nextLine(const QString &line)
+{
+ const QList<QUrl> &inputFiles = getInputFiles();
+
+ if (line.startsWith(QLatin1String("[GNUPG:] MISSING_PASSPHRASE"))) {
+ setSuccess(KGpgTransaction::TS_BAD_PASSPHRASE);
+ return true;
+ }
+
+ if (!inputFiles.isEmpty()) {
+ static const QString encStart = QLatin1String("[GNUPG:] FILE_START 2 ");
+ static const QString encDone = QLatin1String("[GNUPG:] FILE_DONE");
+ static const QString askName = QLatin1String("[GNUPG:] GET_LINE openfile.askoutname");
+
+ if (line.startsWith(encStart)) {
+ m_currentFile = line.mid(encStart.length());
+ emit statusMessage(tr("Status message 'Encrypting <filename>' (operation starts)", "Encrypting %1").arg(m_currentFile));
+ emit infoProgress(2 * m_fileIndex + 1, inputFiles.count() * 2);
+ } else if (line == encDone) {
+ emit statusMessage(tr("Status message 'Encrypted <filename>' (operation was completed)", "Encrypted %1").arg(m_currentFile));
+ m_fileIndex++;
+ emit infoProgress(2 * m_fileIndex, inputFiles.count() * 2);
+// TODO
+/* } else if (line == askName) {
+ QPointer<KIO::RenameDialog> over = new KIO::RenameDialog(qobject_cast<QWidget *>(parent()),
+ i18n("File Already Exists"), KUrl(),
+ KUrl::fromPath(m_currentFile + encryptExtension(m_options.testFlag(AsciiArmored))),
+ KIO::M_OVERWRITE);
+
+ if (over->exec() != QDialog::Accepted) {
+ delete over;
+ setSuccess(KGpgTransaction::TS_USER_ABORTED);
+ return true;
+ }
+ write(over->newDestUrl().path().toUtf8());
+ delete over;*/
+ }
+ }
+
+ return KGpgTextOrFileTransaction::nextLine(line);
+}
+
+QString
+KGpgEncrypt::encryptExtension(const bool ascii)
+{
+ if (ascii)
+ return QLatin1String( ".asc" );
+ /*else if (KGpgSettings::pgpExtension())
+ return QLatin1String( ".pgp" );*/
+ else
+ return QLatin1String( ".gpg" );
+}
+
+//#include "kgpgencrypt.moc"
diff --git a/kgpg/transactions/kgpgencrypt.h b/kgpg/transactions/kgpgencrypt.h
new file mode 100644
index 0000000..ad9d89c
--- /dev/null
+++ b/kgpg/transactions/kgpgencrypt.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2011 Rolf Eike Beer <[email protected]>
+ */
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KGPGENCRYPT_H
+#define KGPGENCRYPT_H
+
+#include <QObject>
+#include <QString>
+#include <QStringList>
+
+#include <QUrl>
+
+#include "kgpgtextorfiletransaction.h"
+
+class QProcess;
+
+/**
+ * @brief encrypt the given text or files
+ */
+class KGpgEncrypt: public KGpgTextOrFileTransaction {
+ Q_OBJECT
+
+ Q_DISABLE_COPY(KGpgEncrypt)
+ KGpgEncrypt(); // = delete C++0x
+public:
+ enum EncryptOption {
+ DefaultEncryption = 0, ///< use whatever GnuPGs defaults are
+ AsciiArmored = 0x1, ///< output the data as printable ASCII as opposed to binary data
+ AllowUntrustedEncryption = 0x2, ///< allow encryption with untrusted keys, ignored for symmetric encryption
+ HideKeyId = 0x4 ///< remove anything that shows which key ids this data is encrypted to, ignored for symmetric encryption
+ };
+ Q_DECLARE_FLAGS(EncryptOptions, EncryptOption);
+
+ /**
+ * @brief encrypt given text
+ * @param parent parent object
+ * @param userIds ids to encrypt to or empty list to use symmetric encryption with passphrase
+ * @param text text to encrypt
+ * @param options encryption options
+ */
+ explicit KGpgEncrypt(QObject *parent, const QStringList &userIds = QStringList(), const QString &text = QString(), const EncryptOptions &options = DefaultEncryption, const QStringList &extraOptions = QStringList());
+
+ /**
+ * @brief encrypt file(s)
+ * @param parent parent object
+ * @param userIds ids to encrypt to or empty list to use symmetric encryption with passphrase
+ * @param files list of file locations to encrypt
+ * @param options encryption options
+ */
+ KGpgEncrypt(QObject *parent, const QStringList &userIds, const QList<QUrl> &files, const EncryptOptions &options = DefaultEncryption, const QStringList &extraOptions = QStringList());
+
+ /**
+ * @brief destructor
+ */
+ virtual ~KGpgEncrypt();
+
+ /**
+ * @brief get decryption result
+ * @return decrypted text
+ */
+ QStringList encryptedText() const;
+
+ /**
+ * @brief return the preferred extension for encrypted files
+ * @param ascii if the file is encrypted with ASCII armor
+ * @return the file extension with leading dot
+ */
+ static QString encryptExtension(const bool ascii);
+
+protected:
+ virtual QStringList command() const;
+ virtual bool nextLine(const QString &line);
+
+private:
+ int m_fileIndex;
+ const EncryptOptions m_options;
+ const QStringList m_userIds;
+ QStringList m_extraOptions;
+ QString m_currentFile;
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(KGpgEncrypt::EncryptOptions);
+
+#endif // KGPGENCRYPT_H
diff --git a/kgpg/transactions/kgpgtextorfiletransaction.cpp b/kgpg/transactions/kgpgtextorfiletransaction.cpp
new file mode 100644
index 0000000..6989353
--- /dev/null
+++ b/kgpg/transactions/kgpgtextorfiletransaction.cpp
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2008,2009,2010,2011,2012 Rolf Eike Beer <[email protected]>
+ */
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "kgpgtextorfiletransaction.h"
+
+#include "../gpgproc.h"
+
+//#include <KIO/NetAccess>
+//#include <KLocale>
+
+KGpgTextOrFileTransaction::KGpgTextOrFileTransaction(QObject *parent, const QString &text, const bool allowChaining)
+ : KGpgTransaction(parent, allowChaining),
+ m_text(text)
+{
+}
+
+KGpgTextOrFileTransaction::KGpgTextOrFileTransaction(QObject *parent, const QList<QUrl> &files, const bool allowChaining)
+ : KGpgTransaction(parent, allowChaining)
+{
+ setUrls(files);
+}
+
+KGpgTextOrFileTransaction::~KGpgTextOrFileTransaction()
+{
+ cleanUrls();
+}
+
+void
+KGpgTextOrFileTransaction::setText(const QString &text)
+{
+ m_text = text;
+ cleanUrls();
+}
+
+void
+KGpgTextOrFileTransaction::setUrls(const QList<QUrl> &files)
+{
+ m_text.clear();
+ m_inpfiles = files;
+}
+
+bool
+KGpgTextOrFileTransaction::preStart()
+{
+ QStringList locfiles;
+
+ foreach (const QUrl &url, m_inpfiles) {
+ if (url.isLocalFile()) {
+ locfiles.append(url.toLocalFile());
+ } else {
+ QString tmpfile;
+ //TODO: QIODevice ...?
+/* if (KIO::NetAccess::download(url, tmpfile, 0)) {
+ m_tempfiles.append(tmpfile);
+ } else {
+ m_messages.append(KIO::NetAccess::lastErrorString());
+ cleanUrls();
+ setSuccess(TS_KIO_FAILED);
+ return false;
+ }*/
+ }
+ }
+
+ if (locfiles.isEmpty() && m_tempfiles.isEmpty() && m_text.isEmpty() && !hasInputTransaction()) {
+ setSuccess(TS_MSG_SEQUENCE);
+ return false;
+ }
+
+ QStringList args(QLatin1String("--status-fd=1"));
+
+ args << command();
+ // if the input is not stdin set command-fd so GnuPG
+ // can ask if e.g. the file already exists
+ if (!locfiles.isEmpty() && !m_tempfiles.isEmpty()) {
+ args << QLatin1String("--command-fd=0");
+ m_closeInput = false;
+ } else {
+ m_closeInput = !args.contains(QLatin1String("--command-fd=0"));
+ }
+ if (locfiles.count() + m_tempfiles.count() > 1)
+ args << QLatin1String("--multifile");
+ args << locfiles << m_tempfiles;
+ addArguments(args);
+
+ return true;
+}
+
+void
+KGpgTextOrFileTransaction::postStart()
+{
+ if (!m_text.isEmpty()){
+ GPGProc *proc = getProcess();
+ proc->write(m_text.toUtf8());
+ if (m_closeInput)
+ proc->closeWriteChannel();
+ }
+}
+
+bool
+KGpgTextOrFileTransaction::nextLine(const QString &line)
+{
+ if (!line.startsWith(QLatin1String("[GNUPG:] SIGEXPIRED")) && !line.startsWith(QLatin1String("[GNUPG:] KEYEXPIRED ")))
+ m_messages.append(line);
+
+ return false;
+}
+
+void
+KGpgTextOrFileTransaction::finish()
+{
+ if (getProcess()->exitCode() != 0) {
+ setSuccess(TS_MSG_SEQUENCE);
+ }
+}
+
+const QStringList &
+KGpgTextOrFileTransaction::getMessages() const
+{
+ return m_messages;
+}
+
+void
+KGpgTextOrFileTransaction::cleanUrls()
+{
+// TODO
+/* foreach (const QString &u, m_tempfiles)
+ KIO::NetAccess::removeTempFile(u);
+*/
+ m_tempfiles.clear();
+ m_locfiles.clear();
+ m_inpfiles.clear();
+}
+
+const QList<QUrl> &
+KGpgTextOrFileTransaction::getInputFiles() const
+{
+ return m_inpfiles;
+}
+
+//#include "kgpgtextorfiletransaction.moc"
diff --git a/kgpg/transactions/kgpgtextorfiletransaction.h b/kgpg/transactions/kgpgtextorfiletransaction.h
new file mode 100644
index 0000000..46bf190
--- /dev/null
+++ b/kgpg/transactions/kgpgtextorfiletransaction.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2008,2009,2010 Rolf Eike Beer <[email protected]>
+ */
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KGPGTEXTORFILETRANSACTION_H
+#define KGPGTEXTORFILETRANSACTION_H
+
+#include <QObject>
+#include <QList>
+#include <QString>
+#include <QStringList>
+
+#include <QUrl>
+
+#include "kgpgtransaction.h"
+
+/**
+ * @brief feed a text or file through gpg
+ */
+class KGpgTextOrFileTransaction: public KGpgTransaction {
+ Q_OBJECT
+
+ Q_DISABLE_COPY(KGpgTextOrFileTransaction)
+
+public:
+ /**
+ * @brief additional status codes for KGpgImport
+ */
+ enum ts_import {
+ TS_KIO_FAILED = TS_COMMON_END + 1 ///< download of remote file failed
+ };
+
+protected:
+ /**
+ * @brief work with given text
+ * @param parent parent object
+ * @param text text to work with
+ */
+ explicit KGpgTextOrFileTransaction(QObject *parent = 0, const QString &text = QString(), const bool allowChaining = false);
+
+ /**
+ * @brief work with given file(s)
+ * @param parent parent object
+ * @param keys list of file locations to work with
+ */
+ KGpgTextOrFileTransaction(QObject *parent, const QList<QUrl> &files, const bool allowChaining = false);
+
+public:
+ /**
+ * @brief destructor
+ */
+ virtual ~KGpgTextOrFileTransaction();
+
+ /**
+ * @brief set text to work with
+ * @param text text to work with
+ */
+ void setText(const QString &text);
+ /**
+ * @brief set file locations to work with
+ * @param keys list of file locations to work with
+ */
+ void setUrls(const QList<QUrl> &files);
+
+ /**
+ * @brief get gpg info message
+ * @return the raw messages from gpg during the operation
+ */
+ const QStringList &getMessages() const;
+
+protected:
+ /**
+ * @brief construct the command line of the process
+ */
+ virtual bool preStart();
+ virtual bool nextLine(const QString &line);
+ /**
+ * @brief implement special handling for GnuPG return codes
+ */
+ virtual void finish();
+
+ virtual QStringList command() const = 0;
+
+ const QList<QUrl> &getInputFiles() const;
+
+private:
+ QStringList m_tempfiles;
+ QStringList m_locfiles;
+ QList<QUrl> m_inpfiles;
+ QString m_text;
+ QStringList m_messages;
+ bool m_closeInput; ///< if input channel of GnuPG should be closed after m_text is written
+
+ void cleanUrls();
+
+private slots:
+ void postStart();
+};
+
+#endif // KGPGTEXTORFILETRANSACTION_H
diff --git a/kgpg/transactions/kgpgtransaction.cpp b/kgpg/transactions/kgpgtransaction.cpp
new file mode 100644
index 0000000..84783aa
--- /dev/null
+++ b/kgpg/transactions/kgpgtransaction.cpp
@@ -0,0 +1,543 @@
+/*
+ * Copyright (C) 2008,2009,2010,2011,2012 Rolf Eike Beer <[email protected]>
+ */
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include "kgpgtransaction.h"
+
+#include "../gpgproc.h"
+#include "../kgpginterface.h"
+
+//#include <KDebug>
+#include <QDebug>
+//#include <knewpassworddialog.h>
+//#include <KLocale>
+//#include <KPushButton>
+#include <QByteArray>
+#include <QStringList>
+#include <QWeakPointer>
+#include <QWidget>
+
+
+
+KGpgTransactionPrivate::KGpgTransactionPrivate(KGpgTransaction *parent, bool allowChaining)
+ : QObject(parent),
+ m_parent(parent),
+ m_process(new GPGProc()),
+ m_inputTransaction(NULL),
+ //m_passwordDialog(NULL),
+ m_success(KGpgTransaction::TS_OK),
+ m_tries(3),
+ m_chainingAllowed(allowChaining),
+ m_passphraseAction(KGpgTransaction::PA_NONE),
+ m_inputProcessDone(false),
+ m_inputProcessResult(KGpgTransaction::TS_OK),
+ m_ownProcessFinished(false),
+ m_quitTries(0)
+{
+}
+
+KGpgTransactionPrivate::~KGpgTransactionPrivate()
+{
+ /*if (m_passwordDialog) {
+ m_passwordDialog->close();
+ m_passwordDialog->deleteLater();
+ }*/
+ if (m_process->state() == QProcess::Running) {
+ m_process->closeWriteChannel();
+ m_process->terminate();
+ }
+ delete m_inputTransaction;
+ delete m_process;
+}
+
+KGpgTransaction::KGpgTransaction(QObject *parent, const bool allowChaining)
+ : QObject(parent),
+ d(new KGpgTransactionPrivate(this, allowChaining))
+{
+ connect(d->m_process, SIGNAL(readReady()), SLOT(slotReadReady()));
+ connect(d->m_process, SIGNAL(processExited()), SLOT(slotProcessExited()));
+ connect(d->m_process, SIGNAL(started()), SLOT(slotProcessStarted()));
+}
+
+KGpgTransaction::~KGpgTransaction()
+{
+ delete d;
+}
+
+void
+KGpgTransactionPrivate::slotReadReady()
+{
+ QString line;
+ QWeakPointer<GPGProc> process(m_process);
+ QWeakPointer<KGpgTransaction> par(m_parent);
+
+ while (!process.isNull() && (m_process->readln(line, true) >= 0)) {
+ if (m_quitTries)
+ m_quitLines << line;
+#ifdef KGPG_DEBUG_TRANSACTIONS
+ kDebug(2100) << m_parent << line;
+#endif /* KGPG_DEBUG_TRANSACTIONS */
+
+ if (line.startsWith(QLatin1String("[GNUPG:] USERID_HINT "))) {
+ m_parent->addIdHint(line);
+ } else if (line.startsWith(QLatin1String("[GNUPG:] BAD_PASSPHRASE "))) {
+ m_success = KGpgTransaction::TS_BAD_PASSPHRASE;
+ } else if (line.startsWith(QLatin1String("[GNUPG:] GET_HIDDEN passphrase.enter"))) {
+ // Do not directly assign to the member here, the object could
+ // get deleted while waiting for the result
+ const KGpgTransaction::ts_passphrase_actions action = m_parent->passphraseRequested();
+
+ if (par.isNull())
+ return;
+
+ m_passphraseAction = action;
+
+ switch (action) {
+ case KGpgTransaction::PA_USER_ABORTED:
+ m_parent->setSuccess(KGpgTransaction::TS_USER_ABORTED);
+ // sending "quit" here is useless as it would be interpreted as the passphrase
+ m_process->closeWriteChannel();
+ break;
+ default:
+ break;
+ }
+ } else if ((m_passphraseAction == KGpgTransaction::PA_CLOSE_GOOD) &&
+ line.startsWith(QLatin1String("[GNUPG:] GOOD_PASSPHRASE"))) {
+ // signal GnuPG that there will be no further input and it can
+ // begin sending output.
+ m_process->closeWriteChannel();
+ } else if (line.startsWith(QLatin1String("[GNUPG:] GET_BOOL "))) {
+ switch (m_parent->boolQuestion(line.mid(18))) {
+ case KGpgTransaction::BA_YES:
+ write("YES\n");
+ break;
+ case KGpgTransaction::BA_NO:
+ write("NO\n");
+ break;
+ case KGpgTransaction::BA_UNKNOWN:
+ m_parent->setSuccess(KGpgTransaction::TS_MSG_SEQUENCE);
+ m_parent->unexpectedLine(line);
+ sendQuit();
+ }
+ } else if (line.startsWith(QLatin1String("[GNUPG:] CARDCTRL "))) {
+ // just ignore them, pinentry should handle that
+ } else if (m_parent->nextLine(line)) {
+ sendQuit();
+ }
+ }
+}
+
+void
+KGpgTransactionPrivate::slotProcessExited()
+{
+ Q_ASSERT(m_parent->sender() == m_process);
+ m_ownProcessFinished = true;
+
+ if (m_inputProcessDone)
+ processDone();
+}
+
+void
+KGpgTransactionPrivate::slotProcessStarted()
+{
+ m_parent->postStart();
+}
+
+void
+KGpgTransactionPrivate::sendQuit(void)
+{
+ write("quit\n");
+
+#ifdef KGPG_DEBUG_TRANSACTIONS
+ if (m_quitTries == 0)
+ qDebug() << "sending quit";
+#endif /* KGPG_DEBUG_TRANSACTIONS */
+
+ if (m_quitTries++ >= 3) {
+ qDebug() << "tried" << m_quitTries << "times to quit the GnuPG session";
+ qDebug() << "last input was" << m_quitLines;
+ qDebug() << "please file a bug report at https://bugs.kde.org";
+ m_process->closeWriteChannel();
+ m_success = KGpgTransaction::TS_MSG_SEQUENCE;
+ }
+}
+
+void
+KGpgTransactionPrivate::slotInputTransactionDone(int result)
+{
+ Q_ASSERT(m_parent->sender() == m_inputTransaction);
+
+ m_inputProcessDone = true;
+ m_inputProcessResult = result;
+
+ if (m_ownProcessFinished)
+ processDone();
+}
+
+void
+KGpgTransactionPrivate::slotPasswordEntered(const QString &password)
+{
+ sender()->deleteLater();
+ //m_passwordDialog = NULL;
+ m_process->write(password.toUtf8() + '\n');
+ m_parent->newPasswordEntered();
+}
+
+void
+KGpgTransactionPrivate::slotPasswordAborted()
+{
+ sender()->deleteLater();
+ //m_passwordDialog = NULL;
+ m_process->closeWriteChannel();
+ m_success = KGpgTransaction::TS_USER_ABORTED;
+}
+
+void
+KGpgTransactionPrivate::write(const QByteArray &a)
+{
+ m_process->write(a);
+#ifdef KGPG_DEBUG_TRANSACTIONS
+ kDebug(2100) << m_parent << a;
+#endif /* KGPG_DEBUG_TRANSACTIONS */
+}
+
+void
+KGpgTransactionPrivate::processDone()
+{
+ m_parent->finish();
+ emit m_parent->infoProgress(100, 100);
+ emit m_parent->done(m_success);
+}
+
+void
+KGpgTransaction::start()
+{
+ d->m_inputProcessResult = false;
+ d->m_inputProcessDone = (d->m_inputTransaction == NULL);
+
+ setSuccess(TS_OK);
+ d->m_idhints.clear();
+ d->m_tries = 3;
+ if (preStart()) {
+ d->m_ownProcessFinished = false;
+ if (d->m_inputTransaction != NULL)
+ d->m_inputTransaction->start();
+#ifdef KGPG_DEBUG_TRANSACTIONS
+ kDebug(2100) << this << d->m_process->program();
+#endif /* KGPG_DEBUG_TRANSACTIONS */
+ d->m_process->start();
+ emit infoProgress(0, 1);
+ } else {
+ emit done(d->m_success);
+ }
+}
+
+void
+KGpgTransaction::write(const QByteArray &a, const bool lf)
+{
+ if (lf)
+ d->write(a + '\n');
+ else
+ d->write(a);
+}
+
+void
+KGpgTransaction::write(const int i)
+{
+ write(QByteArray::number(i));
+}
+
+void
+KGpgTransaction::askNewPassphrase(const QString& text)
+{
+ emit statusMessage(tr("Requesting Passphrase"));
+
+ /*d->m_passwordDialog = new KNewPasswordDialog(qobject_cast<QWidget *>(parent()));
+ d->m_passwordDialog->setPrompt(text);
+ d->m_passwordDialog->setAllowEmptyPasswords(false);
+ connect(d->m_passwordDialog, SIGNAL(newPassword(QString)), SLOT(slotPasswordEntered(QString)));
+ connect(d->m_passwordDialog, SIGNAL(rejected()), SLOT(slotPasswordAborted()));
+ connect(d->m_process, SIGNAL(processExited()), d->m_passwordDialog->button(KDialog::Cancel), SLOT(clicked()));
+ d->m_passwordDialog->show();*/
+}
+
+int
+KGpgTransaction::getSuccess() const
+{
+ return d->m_success;
+}
+
+void
+KGpgTransaction::setSuccess(const int v)
+{
+#ifdef KGPG_DEBUG_TRANSACTIONS
+ qDebug() << d->m_success << v;
+#endif /* KGPG_DEBUG_TRANSACTIONS */
+ d->m_success = v;
+}
+
+KGpgTransaction::ts_boolanswer
+KGpgTransaction::boolQuestion(const QString& line)
+{
+ Q_UNUSED(line);
+
+ return BA_UNKNOWN;
+}
+
+void
+KGpgTransaction::finish()
+{
+}
+
+void
+KGpgTransaction::setDescription(const QString &description)
+{
+ d->m_description = description;
+}
+
+void
+KGpgTransaction::waitForInputTransaction()
+{
+ Q_ASSERT(d->m_inputTransaction != NULL);
+
+ if (d->m_inputProcessDone)
+ return;
+
+ d->m_inputTransaction->waitForFinished();
+}
+
+void
+KGpgTransaction::unexpectedLine(const QString &line)
+{
+ qDebug() << this << "unexpected input line" << line << "for command" << d->m_process->program();
+}
+
+KGpgTransaction::ts_passphrase_actions
+KGpgTransaction::passphraseRequested()
+{
+ if (!askPassphrase())
+ return PA_USER_ABORTED;
+ else
+ return PA_CLOSE_GOOD;
+}
+
+bool
+KGpgTransaction::preStart()
+{
+ return true;
+}
+
+void
+KGpgTransaction::postStart()
+{
+}
+
+void
+KGpgTransaction::addIdHint(QString txt)
+{
+ int cut = txt.indexOf(QLatin1Char( ' ' ), 22, Qt::CaseInsensitive);
+ txt.remove(0, cut);
+
+ if (txt.contains(QLatin1Char( '(' ), Qt::CaseInsensitive))
+ txt = txt.section(QLatin1Char( '(' ), 0, 0) + txt.section(QLatin1Char( ')' ), -1);
+
+ txt.replace(QLatin1Char( '<' ), QLatin1String( "&lt;" ));
+
+ if (!d->m_idhints.contains(txt))
+ d->m_idhints << txt;
+}
+
+QString
+KGpgTransaction::getIdHints() const
+{
+ return d->m_idhints.join( tr(" or " ));
+}
+
+GPGProc *
+KGpgTransaction::getProcess()
+{
+ return d->m_process;
+}
+
+int
+KGpgTransaction::addArgument(const QString &arg)
+{
+ int r = d->m_process->program().count();
+
+ *d->m_process << arg;
+
+ return r;
+}
+
+int
+KGpgTransaction::addArguments(const QStringList &args)
+{
+ int r = d->m_process->program().count();
+
+ *d->m_process << args;
+
+ return r;
+}
+
+void
+KGpgTransaction::replaceArgument(const int pos, const QString &arg)
+{
+ QStringList args(d->m_process->program());
+ d->m_process->clearProgram();
+
+ args.replace(pos, arg);
+
+ d->m_process->setProgram(args);
+}
+
+void
+KGpgTransaction::insertArgument(const int pos, const QString &arg)
+{
+ insertArguments(pos, QStringList(arg));
+}
+
+void
+KGpgTransaction::insertArguments(const int pos, const QStringList &args)
+{
+ QStringList tmp(d->m_process->program());
+
+ int tmppos = pos;
+ foreach (const QString &s, args) {
+ tmp.insert(tmppos++, s);
+ }
+ d->m_process->setProgram(tmp);
+
+ int move = args.count();
+ foreach (int *ref, d->m_argRefs) {
+ if (*ref >= pos)
+ *ref += move;
+ }
+}
+
+void
+KGpgTransaction::addArgumentRef(int *ref)
+{
+ d->m_argRefs.append(ref);
+}
+
+bool
+KGpgTransaction::askPassphrase(const QString &message)
+{
+ if (d->m_passphraseAction == PA_USER_ABORTED)
+ return false;
+
+ QString passdlgmessage;
+ QString userIDs(getIdHints());
+ if (userIDs.isEmpty())
+ userIDs = tr("[No user id found]");
+ else
+ userIDs.replace(QLatin1Char( '<' ), QLatin1String( "&lt;" ));
+
+ if (d->m_tries < 3)
+ passdlgmessage = tr("<p><b>Bad passphrase</b>. You have 1 try left.</p>", "<p><b>Bad passphrase</b>. You have %1 tries left.</p>", d->m_tries);
+ if (message.isEmpty()) {
+ passdlgmessage += tr("Enter passphrase for <b>%1</b>").arg(userIDs);
+ } else {
+ passdlgmessage += message;
+ }
+
+ --d->m_tries;
+
+ emit statusMessage(tr("Requesting Passphrase"));
+ return (KgpgInterface::sendPassphrase(passdlgmessage, d->m_process, qobject_cast<QWidget *>(parent())) == 0);
+}
+
+void
+KGpgTransaction::setGnuPGHome(const QString &home)
+{
+ QStringList tmp(d->m_process->program());
+
+ Q_ASSERT(tmp.count() > 3);
+ int homepos = tmp.indexOf(QLatin1String("--options"), 1);
+ if (homepos == -1)
+ homepos = tmp.indexOf(QLatin1String("--homedir"), 1);
+ Q_ASSERT(homepos != -1);
+ Q_ASSERT(homepos + 1 < tmp.count());
+
+ tmp[homepos] = QLatin1String("--homedir");
+ tmp[homepos + 1] = home;
+
+ d->m_process->setProgram(tmp);
+}
+
+int
+KGpgTransaction::waitForFinished(const int msecs)
+{
+ int ret = TS_OK;
+
+ if (d->m_inputTransaction != NULL) {
+ int ret = d->m_inputTransaction->waitForFinished(msecs);
+ if ((ret != TS_OK) && (msecs != -1))
+ return ret;
+ }
+
+ bool b = d->m_process->waitForFinished(msecs);
+
+ if (ret != TS_OK)
+ return ret;
+
+ if (!b)
+ return TS_USER_ABORTED;
+ else
+ return getSuccess();
+}
+
+const QString &
+KGpgTransaction::getDescription() const
+{
+ return d->m_description;
+}
+
+void
+KGpgTransaction::setInputTransaction(KGpgTransaction *ta)
+{
+ Q_ASSERT(d->m_chainingAllowed);
+
+ if (d->m_inputTransaction != NULL)
+ clearInputTransaction();
+ d->m_inputTransaction = ta;
+
+ GPGProc *proc = ta->getProcess();
+ proc->setStandardOutputProcess(d->m_process);
+ connect(ta, SIGNAL(done(int)), SLOT(slotInputTransactionDone(int)));
+}
+
+void
+KGpgTransaction::clearInputTransaction()
+{
+ disconnect(d->m_inputTransaction, SIGNAL(done(int)), this, SLOT(slotInputTransactionDone(int)));
+ d->m_inputTransaction = NULL;
+}
+
+bool
+KGpgTransaction::hasInputTransaction() const
+{
+ return (d->m_inputTransaction != NULL);
+}
+
+void
+KGpgTransaction::kill()
+{
+ d->m_process->kill();
+}
+
+void
+KGpgTransaction::newPasswordEntered()
+{
+}
+
+//#include "moc_kgpgtransaction.cpp"
diff --git a/kgpg/transactions/kgpgtransaction.h b/kgpg/transactions/kgpgtransaction.h
new file mode 100644
index 0000000..8fc76a5
--- /dev/null
+++ b/kgpg/transactions/kgpgtransaction.h
@@ -0,0 +1,465 @@
+/*
+ * Copyright (C) 2008,2009 Rolf Eike Beer <[email protected]>
+ */
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef KGPGTRANSACTION_H
+#define KGPGTRANSACTION_H
+
+#include <QObject>
+#include <QString>
+#include <QStringList>
+
+class GPGProc;
+class KGpgSignTransactionHelper;
+class KGpgTransactionPrivate;
+class QByteArray;
+class QProcess;
+
+/**
+ * @brief Process one GnuPG operation
+ *
+ * This class encapsulates one GnuPG operation. It will care for all
+ * interaction with the gpg process. Everything you have to care about
+ * is to set up the object properly, call start() and catch the done signal.
+ *
+ * This is an abstract base class for specific operations that implements
+ * the basic I/O loop, the process setup and interaction and some convenience
+ * members to set extra arguments for the process.
+ *
+ * If you want to add a new operation create a child class that implements
+ * nextLine(). Ususally you also need a constructor that takes some information
+ * like the id of the key to modify.
+ *
+ * @author Rolf Eike Beer
+ */
+class KGpgTransaction: public QObject {
+ Q_OBJECT
+
+ friend class KGpgTransactionPrivate;
+ friend class KGpgSignTransactionHelper;
+
+ Q_DISABLE_COPY(KGpgTransaction)
+
+public:
+ /**
+ * @brief return codes common to many transactions
+ *
+ * Every transaction may define additional return codes, which
+ * should start at TS_COMMON_END + 1.
+ */
+ enum ts_transaction {
+ TS_OK = 0, ///< everything went fine
+ TS_BAD_PASSPHRASE = 1, ///< the passphrase was not correct
+ TS_MSG_SEQUENCE = 2, ///< unexpected sequence of GnuPG messages
+ TS_USER_ABORTED = 3, ///< the user aborted the transaction
+ TS_INVALID_EMAIL = 4, ///< the given email address is invalid
+ TS_INPUT_PROCESS_ERROR = 5, ///< the connected input process returned an error
+ TS_COMMON_END = 100 ///< placeholder for return values of derived classes
+ };
+ /**
+ * @brief result codes for GnuPG boolean questions
+ *
+ * These are the possible answers to a boolean question of a GnuPG process.
+ */
+ enum ts_boolanswer {
+ BA_UNKNOWN = 0, ///< the question is not supported (this is an error)
+ BA_YES = 1, ///< answer "YES"
+ BA_NO = 2 ///< answer "NO"
+ };
+ /**
+ * @brief actions to do after a passphrase was sent to GnuPG
+ */
+ enum ts_passphrase_actions {
+ PA_NONE = 0, ///< do nothing special
+ PA_CLOSE_GOOD = 1, ///< close command channel if passphrase was accepted
+ PA_USER_ABORTED = 2 ///< the user has cancelled the dialog, abort the transaction
+ };
+
+ /**
+ * @brief KGpgTransaction constructor
+ */
+ explicit KGpgTransaction(QObject *parent = 0, const bool allowChaining = false);
+ /**
+ * @brief KGpgTransaction destructor
+ */
+ virtual ~KGpgTransaction();
+
+ /**
+ * @brief Start the operation.
+ */
+ void start();
+
+ /**
+ * @brief sets the home directory of GnuPG called for this transaction
+ */
+ void setGnuPGHome(const QString &home);
+
+ /**
+ * @brief blocks until the transaction is complete
+ * @return the result of the transaction like done() would
+ * @retval TS_USER_ABORTED the timeout expired
+ *
+ * If this transaction has another transaction set as input then
+ * it would wait for those transaction to finish first. The msecs
+ * argument is used as limit for both transactions then so you
+ * can end up waiting twice the given time (or longer if you have
+ * more transactions chained).
+ */
+ int waitForFinished(const int msecs = -1);
+
+ /**
+ * @brief return description of this transaction
+ * @return string used to describe what's going on
+ *
+ * This is especially useful when using this transaction from a KJob.
+ */
+ const QString &getDescription() const;
+
+ /**
+ * @brief connect the standard input of this transaction to another process
+ * @param proc process to read data from
+ *
+ * Once the input process is connected this transaction will not emit
+ * the done signal until the input process sends the done signal.
+ *
+ * The basic idea is that when an input transaction is set you only need
+ * to care about this transaction. The other transaction is automatically
+ * started when this one is started and is destroyed when this one is.
+ */
+ void setInputTransaction(KGpgTransaction *ta);
+
+ /**
+ * @brief tell the process the standard input is no longer connected
+ *
+ * If you had connected an input process you need to tell the transaction
+ * once this input process is gone. Otherwise you will not get a done
+ * signal from this transaction as it will wait for the finished signal
+ * from the process that will never come.
+ */
+ void clearInputTransaction();
+
+ /**
+ * @brief check if another transaction will sent input to this
+ */
+ bool hasInputTransaction() const;
+
+ /**
+ * @brief abort this operation as soon as possible
+ */
+ void kill();
+
+signals:
+ /**
+ * @brief Emitted when the operation was completed.
+ * @param result return status of the transaction
+ *
+ * @see ts_transaction for the common status codes. Each transaction
+ * may define additional status codes.
+ */
+ void done(int result);
+
+ /**
+ * @brief emits textual status information
+ * @param msg the status message
+ */
+ void statusMessage(const QString &msg);
+
+ /**
+ * @brief emits procentual status information
+ * @param processedAmount how much of the job is done
+ * @param totalAmount how much needs to be done to complete this job
+ */
+ void infoProgress(qulonglong processedAmount, qulonglong totalAmount);
+
+protected:
+ /**
+ * @brief Called before the gpg process is started.
+ * @return true if the process should be started
+ *
+ * You may reimplement this member if you need to do some special
+ * operations before the process is started. The command line of the
+ * process may be modified for the last time here.
+ *
+ * When you notice that some values passed are invalid or the
+ * transaction does not need to be run for some other reason you should
+ * call setSuccess() to set the return value and return false. In this
+ * case the process is not started but the value is immediately
+ * returned.
+ */
+ virtual bool preStart();
+ /**
+ * @brief Called when the gpg process is up and running.
+ *
+ * This functions is connected to the started() signal of the gpg process.
+ */
+ virtual void postStart();
+ /**
+ * @brief Called for every line the gpg process writes.
+ * @param line the input from the process
+ * @return true if "quit" should be sent to process
+ *
+ * You need to implement this member to get a usable subclass.
+ *
+ * When this function returns true "quit" is written to the process.
+ */
+ virtual bool nextLine(const QString &line) = 0;
+ /**
+ * @brief Called for every boolean question GnuPG answers
+ * @param line the question GnuPG asked
+ * @return what to answer GnuPG
+ *
+ * This is called instead of nextLine() if the line contains a boolean
+ * question. Returning BA_UNKNOWN will cancel the current transaction
+ * and will set the transaction result to TS_MSG_SEQUENCE.
+ *
+ * The default implementation will answer BA_UNKNOWN to every question.
+ */
+ virtual ts_boolanswer boolQuestion(const QString &line);
+ /**
+ * @brief Called when the gpg process finishes.
+ *
+ * You may reimplement this member if you need to do some special
+ * operations after process completion. The provided one simply
+ * does nothing which should be enough for most cases.
+ */
+ virtual void finish();
+ /**
+ * @brief called when the user entered a new password
+ *
+ * This is called after askNewPassphrase() was called, the user has
+ * entered a new password and it was sent to the GnuPG process.
+ *
+ * The default implementation does nothing.
+ */
+ virtual void newPasswordEntered();
+ /**
+ * @brief set the description returned in getDescription()
+ * @param description the new description of this transaction
+ */
+ void setDescription(const QString &description);
+
+ /**
+ * @brief wait until the input transaction has finished
+ */
+ void waitForInputTransaction();
+
+ /**
+ * @brief notify of an unexpected line
+ *
+ * This will print out the line to the console to ease debugging.
+ */
+ void unexpectedLine(const QString &line);
+
+ /**
+ * @brief called when GnuPG asks for a passphrase
+ * @return true if "quit" should be sent to process
+ *
+ * This allows a transaction to implement special handling for
+ * passphrases, e.g. when both old and new passphrase must be
+ * requested when changing it. The default implementation will just
+ * call askPassphrase().
+ */
+ virtual ts_passphrase_actions passphraseRequested();
+
+private:
+ KGpgTransactionPrivate* const d;
+
+ Q_PRIVATE_SLOT(d, void slotReadReady())
+ Q_PRIVATE_SLOT(d, void slotProcessExited())
+ Q_PRIVATE_SLOT(d, void slotProcessStarted())
+ Q_PRIVATE_SLOT(d, void slotInputTransactionDone(int))
+ Q_PRIVATE_SLOT(d, void slotPasswordEntered(const QString &))
+ Q_PRIVATE_SLOT(d, void slotPasswordAborted())
+
+protected:
+ /**
+ * @brief Ask user for passphrase and send it to gpg process.
+ *
+ * If the gpg process asks for a new passphrase this function will do
+ * all necessary steps for you: ask the user for the password and write
+ * it to the gpg process. If the password is wrong the user is prompted
+ * again for the correct password. If the user aborts the password
+ * entry the gpg process will be killed and the transaction result will
+ * be set to TS_USER_ABORTED.
+ *
+ * In contrast to sendPassphrase() this function will not block, but
+ * handle everything using signals and slots.
+ *
+ * @see KgpgInterface::sendPassphrase
+ * @see askPassphrase
+ */
+ void askNewPassphrase(const QString &text);
+
+ /**
+ * @brief get the success value that will be returned with the done signal
+ */
+ int getSuccess() const;
+ /**
+ * @brief set the success value that will be returned with the done signal
+ * @param v the new success value
+ *
+ * You should use 0 as success value. Other values can be defined as needed.
+ */
+ void setSuccess(const int v);
+
+ /**
+ * @brief add a userid hint
+ * @param txt userid description
+ *
+ * Before GnuPG asks for a passphrase it usually sends out a hint message
+ * for which key the passphrase will be needed. There may be several hint
+ * messages, e.g. if a text was encrypted with multiple keys.
+ */
+ void addIdHint(QString txt);
+ /**
+ * @brief get string of all userid hints
+ * @returns concatenation of all ids previously added with addIdHint().
+ */
+ QString getIdHints() const;
+
+ /**
+ * @brief get a reference to the gpg process object
+ * @returns gpg process object
+ *
+ * This returns a reference to the gpg process object used internally.
+ * In case you need to do some special things (e.g. changing the output
+ * mode) you can modify this object.
+ *
+ * Usually you will not need this.
+ *
+ * @warning Never free this object!
+ */
+ GPGProc *getProcess();
+ /**
+ * @brief add a command line argument to gpg process
+ * @param arg new argument
+ * @returns the position of the new argument
+ *
+ * This is a convenience function that allows adding one additional
+ * argument to the command line of the process. This must be called
+ * before start() is called. Usually you will call this from your
+ * constructor.
+ */
+ int addArgument(const QString &arg);
+ /**
+ * @brief add command line arguments to gpg process
+ * @param args new arguments
+ * @returns the position of the first argument added
+ *
+ * This is a convenience function that allows adding additional
+ * arguments to the command line of the process. This must be called
+ * before start() is called.
+ */
+ int addArguments(const QStringList &args);
+ /**
+ * @brief replace the argument at the given position
+ * @param pos position of old argument
+ * @param arg new argument
+ */
+ void replaceArgument(const int pos, const QString &arg);
+ /**
+ * @brief insert an argument at the given position
+ * @param pos position to insert at
+ * @param arg new argument
+ */
+ void insertArgument(const int pos, const QString &arg);
+ /**
+ * @brief insert arguments at the given position
+ * @param pos position to insert at
+ * @param args new arguments
+ */
+ void insertArguments(const int pos, const QStringList &args);
+ /**
+ * @brief make sure the reference to a specific argument is kept up to date
+ * @param ref the value where the position is stored
+ *
+ * You might want to keep the position of a specific argument to
+ * later be able to repace it easily. In that case put it into
+ * this function too so every time someone mofifies the argument
+ * list (especially by insertArgument() and insertArguments())
+ * this reference will be kept up to date.
+ */
+ void addArgumentRef(int *ref);
+ /**
+ * @brief write data to standard input of gpg process
+ * @param a data to write
+ * @param lf if line feed should be appended to message
+ *
+ * Use this function to interact with the gpg process. A carriage
+ * return is appended to the data automatically. Usually you will
+ * call this function from nextLine().
+ */
+ void write(const QByteArray &a, const bool lf = true);
+ /**
+ * @brief write data to standard input of gpg process
+ * @param i data to write
+ *
+ * @overload
+ */
+ void write(const int i);
+ /**
+ * @brief ask user for password
+ * @param message message to display to the user. If message is empty
+ * "Enter password for [UID]" will be used.
+ * @return true if the authorization was successful
+ *
+ * This function handles user authorization for key changes. It will
+ * take care to display the message asking the user for the password
+ * and the number of tries left.
+ */
+ bool askPassphrase(const QString &message = QString());
+};
+
+class KGpgTransactionPrivate: QObject {
+public:
+ KGpgTransactionPrivate(KGpgTransaction *parent, bool allowChaining);
+ ~KGpgTransactionPrivate();
+
+ KGpgTransaction *m_parent;
+ GPGProc *m_process;
+ KGpgTransaction *m_inputTransaction;
+ //KNewPasswordDialog *m_passwordDialog;
+ int m_success;
+ int m_tries;
+ QString m_description;
+ bool m_chainingAllowed;
+ KGpgTransaction::ts_passphrase_actions m_passphraseAction; ///< ignore further request for passphrase
+
+ QStringList m_idhints;
+
+ void slotReadReady();
+ void slotProcessExited();
+ void slotProcessStarted();
+ void slotInputTransactionDone(int result);
+ void slotPasswordEntered(const QString &password);
+ void slotPasswordAborted();
+
+ QList<int *> m_argRefs;
+ bool m_inputProcessDone;
+ int m_inputProcessResult;
+ bool m_ownProcessFinished;
+
+ /**
+ * terminate GnuPG session
+ */
+ void sendQuit(void);
+
+ void write(const QByteArray &a);
+
+private:
+ void processDone();
+
+ unsigned int m_quitTries; ///< how many times we tried to quit
+ QStringList m_quitLines; ///< what we received after we tried to quit
+};
+
+#endif // KGPGTRANSACTION_H
diff --git a/mainwindow.cpp b/mainwindow.cpp
index 024fb35..6f9efc2 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -775,10 +775,35 @@ void MainWindow::encrypt()
QStringList *uidList = mKeyList->getChecked();
QByteArray *tmp = new QByteArray();
- if (mCtx->encrypt(uidList, edit->curTextPage()->toPlainText().toUtf8(), tmp)) {
+ /*if (mCtx->encrypt(uidList, edit->curTextPage()->toPlainText().toUtf8(), tmp)) {
QString *tmp2 = new QString(*tmp);
edit->fillTextEditWithText(*tmp2);
+ }*/
+
+ QStringList options;
+ KGpgEncrypt::EncryptOptions opts = KGpgEncrypt::DefaultEncryption;
+
+ KGpgEncrypt *encr = new KGpgEncrypt(this, *uidList, edit->curTextPage()->toPlainText(), opts, options);
+ encr->start();
+ connect(encr, SIGNAL(done(int)), SLOT(slotEncryptDone(int)));
+}
+
+void MainWindow::slotEncryptDone(int result)
+{
+ KGpgEncrypt *enc = qobject_cast<KGpgEncrypt *>(sender());
+ Q_ASSERT(enc != NULL);
+
+ if (result == KGpgTransaction::TS_OK) {
+ const QString lf = QLatin1String("\n");
+ //setPlainText(enc->encryptedText().join(lf) + lf);
+ edit->fillTextEditWithText(enc->encryptedText().join(lf) + lf);
+ } else {
+ /*KMessageBox::sorry(this, i18n("The encryption failed with error code %1", result),
+ i18n("Encryption failed."));*/
+ qDebug() << "The encryption failed with error code " << result;
}
+
+ sender()->deleteLater();
}
void MainWindow::sign()
diff --git a/mainwindow.h b/mainwindow.h
index 6df5ab4..bbf940b 100644
--- a/mainwindow.h
+++ b/mainwindow.h
@@ -31,6 +31,7 @@
#include "verifynotification.h"
#include "wizard.h"
#include "kgpg/core/kgpgkey.h"
+#include "kgpg/transactions/kgpgencrypt.h"
QT_BEGIN_NAMESPACE
class QMainWindow;
@@ -87,6 +88,7 @@ private slots:
* with the currently checked keys
*/
void encrypt();
+ void slotEncryptDone(int result);
/**
* @details Show a passphrase dialog and decrypt the text of currently active tab.