initial commit

This commit is contained in:
mikhail "synzr" 2025-12-25 01:37:49 +05:00
commit 9d20827c46
2469 changed files with 470994 additions and 0 deletions

1641
third-party/qca/qca-gnupg/gpgop.cpp vendored Normal file

File diff suppressed because it is too large Load diff

208
third-party/qca/qca-gnupg/gpgop.h vendored Normal file
View file

@ -0,0 +1,208 @@
/*
* Copyright (C) 2003-2005 Justin Karneges <justin@affinix.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
#ifndef GPGOP_H
#define GPGOP_H
#include <QtCrypto>
#include "qpipe.h"
namespace gpgQCAPlugin {
class GpgOp : public QObject
{
Q_OBJECT
public:
enum Type
{
Check, // --version
SecretKeyringFile, // --list-secret-keys
PublicKeyringFile, // --list-public-keys
SecretKeys, // --fixed-list-mode --with-colons --list-secret-keys
PublicKeys, // --fixed-list-mode --with-colons --list-public-keys
Encrypt, // --encrypt
Decrypt, // --decrypt
Sign, // --sign
SignAndEncrypt, // --sign --encrypt
SignClearsign, // --clearsign
SignDetached, // --detach-sign
Verify, // --verify
VerifyDetached, // --verify
Import, // --import
Export, // --export
DeleteKey // --delete-key
};
enum VerifyResult
{
VerifyGood, // good sig
VerifyBad, // bad sig
VerifyNoKey // we don't have signer's public key
};
enum Error
{
ErrorProcess, // startup, process, or ipc error
ErrorPassphrase, // passphrase was either wrong or not provided
ErrorFormat, // input format was bad
ErrorSignerExpired, // signing key is expired
ErrorEncryptExpired, // encrypting key is expired
ErrorEncryptUntrusted, // encrypting key is untrusted
ErrorEncryptInvalid, // encrypting key is invalid in some way
ErrorDecryptNoKey, // missing decrypt key
ErrorUnknown // other error
};
class Event
{
public:
enum Type
{
None,
ReadyRead,
BytesWritten,
Finished,
NeedPassphrase,
NeedCard,
ReadyReadDiagnosticText
};
Type type;
int written; // BytesWritten
QString keyId; // NeedPassphrase
Event() : type(None), written(0) {}
};
class KeyItem
{
public:
enum Type
{
RSA,
DSA,
ElGamal,
Unknown
};
enum Caps
{
Encrypt = 0x01,
Sign = 0x02,
Certify = 0x04,
Auth = 0x08
};
QString id;
Type type;
int bits;
QDateTime creationDate;
QDateTime expirationDate;
int caps; // flags OR'd together
QString fingerprint;
KeyItem() : type(Unknown), bits(0), caps(0) {}
};
class Key
{
public:
QList<KeyItem> keyItems; // first item is primary
QStringList userIds;
bool isTrusted;
Key() : isTrusted(false) {}
};
typedef QList<Key> KeyList;
explicit GpgOp(const QString &bin, QObject *parent = 0);
~GpgOp();
void reset();
bool isActive() const;
Type op() const;
void setAsciiFormat(bool b);
void setDisableAgent(bool b);
void setAlwaysTrust(bool b);
void setKeyrings(const QString &pubfile, const QString &secfile); // for keylists and import
void doCheck();
void doSecretKeyringFile();
void doPublicKeyringFile();
void doSecretKeys();
void doPublicKeys();
void doEncrypt(const QStringList &recip_ids);
void doDecrypt();
void doSign(const QString &signer_id);
void doSignAndEncrypt(const QString &signer_id, const QStringList &recip_ids);
void doSignClearsign(const QString &signer_id);
void doSignDetached(const QString &signer_id);
void doVerify();
void doVerifyDetached(const QByteArray &sig);
void doImport(const QByteArray &in);
void doExport(const QString &key_id);
void doDeleteKey(const QString &key_fingerprint);
#ifdef QPIPE_SECURE
void submitPassphrase(const QCA::SecureArray &a);
#else
void submitPassphrase(const QByteArray &a);
#endif
void cardOkay();
// for encrypt, decrypt, sign, verify, export
QByteArray read();
void write(const QByteArray &in);
void endWrite();
QString readDiagnosticText();
// for synchronous operation
Event waitForEvent(int msecs = -1);
// results
bool success() const;
Error errorCode() const;
KeyList keys() const; // Keys
QString keyringFile() const; // KeyringFile
QString encryptedToId() const; // Decrypt (for ErrorDecryptNoKey)
bool wasSigned() const; // Decrypt
QString signerId() const; // Verify
QDateTime timestamp() const; // Verify
VerifyResult verifyResult() const; // Verify
Q_SIGNALS:
void readyRead();
void bytesWritten(int bytes);
void finished();
void needPassphrase(const QString &keyId);
void needCard();
void readyReadDiagnosticText();
private:
class Private;
friend class Private;
Private *d;
};
}
#endif

View file

@ -0,0 +1,8 @@
GPGProc launches a single instance of GPG and provides a friendly API to
work with all six possible pipe channels. Theoretically, it should be
possible to build any GPG front end with it, even though qca-gnupg uses it
for only a handful of operations. If you are writing a Qt-based GPG front
end, please use this class.
GPGProc works on both Windows and Unix platforms.

View file

@ -0,0 +1,830 @@
/*
* Copyright (C) 2003-2007 Justin Karneges <justin@affinix.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
#include "gpgproc.h"
#include "sprocess.h"
#ifdef Q_OS_MAC
#define QT_PIPE_HACK
#endif
#define QPROC_SIGNAL_RELAY
using namespace QCA;
namespace gpgQCAPlugin {
void releaseAndDeleteLater(QObject *owner, QObject *obj)
{
obj->disconnect(owner);
obj->setParent(0);
obj->deleteLater();
}
//----------------------------------------------------------------------------
// SafeTimer
//----------------------------------------------------------------------------
SafeTimer::SafeTimer(QObject *parent) :
QObject(parent)
{
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), SIGNAL(timeout()));
}
SafeTimer::~SafeTimer()
{
releaseAndDeleteLater(this, timer);
}
int SafeTimer::interval() const
{
return timer->interval();
}
bool SafeTimer::isActive() const
{
return timer->isActive();
}
bool SafeTimer::isSingleShot() const
{
return timer->isSingleShot();
}
void SafeTimer::setInterval(int msec)
{
timer->setInterval(msec);
}
void SafeTimer::setSingleShot(bool singleShot)
{
timer->setSingleShot(singleShot);
}
int SafeTimer::timerId() const
{
return timer->timerId();
}
void SafeTimer::start(int msec)
{
timer->start(msec);
}
void SafeTimer::start()
{
timer->start();
}
void SafeTimer::stop()
{
timer->stop();
}
//----------------------------------------------------------------------------
// QProcessSignalRelay
//----------------------------------------------------------------------------
class QProcessSignalRelay : public QObject
{
Q_OBJECT
public:
QProcessSignalRelay(QProcess *proc, QObject *parent = 0)
:QObject(parent)
{
qRegisterMetaType<QProcess::ProcessError>("QProcess::ProcessError");
connect(proc, SIGNAL(started()), SLOT(proc_started()), Qt::QueuedConnection);
connect(proc, SIGNAL(readyReadStandardOutput()), SLOT(proc_readyReadStandardOutput()), Qt::QueuedConnection);
connect(proc, SIGNAL(readyReadStandardError()), SLOT(proc_readyReadStandardError()), Qt::QueuedConnection);
connect(proc, SIGNAL(bytesWritten(qint64)), SLOT(proc_bytesWritten(qint64)), Qt::QueuedConnection);
connect(proc, SIGNAL(finished(int)), SLOT(proc_finished(int)), Qt::QueuedConnection);
connect(proc, SIGNAL(error(QProcess::ProcessError)), SLOT(proc_error(QProcess::ProcessError)), Qt::QueuedConnection);
}
signals:
void started();
void readyReadStandardOutput();
void readyReadStandardError();
void bytesWritten(qint64);
void finished(int);
void error(QProcess::ProcessError);
public slots:
void proc_started()
{
emit started();
}
void proc_readyReadStandardOutput()
{
emit readyReadStandardOutput();
}
void proc_readyReadStandardError()
{
emit readyReadStandardError();
}
void proc_bytesWritten(qint64 x)
{
emit bytesWritten(x);
}
void proc_finished(int x)
{
emit finished(x);
}
void proc_error(QProcess::ProcessError x)
{
emit error(x);
}
};
//----------------------------------------------------------------------------
// GPGProc
//----------------------------------------------------------------------------
enum ResetMode
{
ResetSession = 0,
ResetSessionAndData = 1,
ResetAll = 2
};
class GPGProc::Private : public QObject
{
Q_OBJECT
public:
GPGProc *q;
QString bin;
QStringList args;
GPGProc::Mode mode;
SProcess *proc;
#ifdef QPROC_SIGNAL_RELAY
QProcessSignalRelay *proc_relay;
#endif
QPipe pipeAux, pipeCommand, pipeStatus;
QByteArray statusBuf;
QStringList statusLines;
GPGProc::Error error;
int exitCode;
SafeTimer startTrigger, doneTrigger;
QByteArray pre_stdin, pre_aux;
#ifdef QPIPE_SECURE
SecureArray pre_command;
#else
QByteArray pre_command;
#endif
bool pre_stdin_close, pre_aux_close, pre_command_close;
bool need_status, fin_process, fin_process_success, fin_status;
QByteArray leftover_stdout;
QByteArray leftover_stderr;
Private(GPGProc *_q) : QObject(_q), q(_q), pipeAux(this), pipeCommand(this), pipeStatus(this), startTrigger(this), doneTrigger(this)
{
qRegisterMetaType<gpgQCAPlugin::GPGProc::Error>("gpgQCAPlugin::GPGProc::Error");
proc = 0;
#ifdef QPROC_SIGNAL_RELAY
proc_relay = 0;
#endif
startTrigger.setSingleShot(true);
doneTrigger.setSingleShot(true);
connect(&pipeAux.writeEnd(), SIGNAL(bytesWritten(int)), SLOT(aux_written(int)));
connect(&pipeAux.writeEnd(), SIGNAL(error(QCA::QPipeEnd::Error)), SLOT(aux_error(QCA::QPipeEnd::Error)));
connect(&pipeCommand.writeEnd(), SIGNAL(bytesWritten(int)), SLOT(command_written(int)));
connect(&pipeCommand.writeEnd(), SIGNAL(error(QCA::QPipeEnd::Error)), SLOT(command_error(QCA::QPipeEnd::Error)));
connect(&pipeStatus.readEnd(), SIGNAL(readyRead()), SLOT(status_read()));
connect(&pipeStatus.readEnd(), SIGNAL(error(QCA::QPipeEnd::Error)), SLOT(status_error(QCA::QPipeEnd::Error)));
connect(&startTrigger, SIGNAL(timeout()), SLOT(doStart()));
connect(&doneTrigger, SIGNAL(timeout()), SLOT(doTryDone()));
reset(ResetSessionAndData);
}
~Private()
{
reset(ResetSession);
}
void closePipes()
{
#ifdef QT_PIPE_HACK
pipeAux.readEnd().reset();
pipeCommand.readEnd().reset();
pipeStatus.writeEnd().reset();
#endif
pipeAux.reset();
pipeCommand.reset();
pipeStatus.reset();
}
void reset(ResetMode mode)
{
#ifndef QT_PIPE_HACK
closePipes();
#endif
if(proc)
{
proc->disconnect(this);
if(proc->state() != QProcess::NotRunning)
proc->terminate();
proc->setParent(0);
#ifdef QPROC_SIGNAL_RELAY
releaseAndDeleteLater(this, proc_relay);
proc_relay = 0;
delete proc; // should be safe to do thanks to relay
#else
proc->deleteLater();
#endif
proc = 0;
}
#ifdef QT_PIPE_HACK
closePipes();
#endif
startTrigger.stop();
doneTrigger.stop();
pre_stdin.clear();
pre_aux.clear();
pre_command.clear();
pre_stdin_close = false;
pre_aux_close = false;
pre_command_close = false;
need_status = false;
fin_process = false;
fin_status = false;
if(mode >= ResetSessionAndData)
{
statusBuf.clear();
statusLines.clear();
leftover_stdout.clear();
leftover_stderr.clear();
error = GPGProc::FailedToStart;
exitCode = -1;
}
}
bool setupPipes(bool makeAux)
{
if(makeAux && !pipeAux.create())
{
closePipes();
emit q->debug("Error creating pipeAux");
return false;
}
#ifdef QPIPE_SECURE
if(!pipeCommand.create(true)) // secure
#else
if(!pipeCommand.create())
#endif
{
closePipes();
emit q->debug("Error creating pipeCommand");
return false;
}
if(!pipeStatus.create())
{
closePipes();
emit q->debug("Error creating pipeStatus");
return false;
}
return true;
}
void setupArguments()
{
QStringList fullargs;
fullargs += "--no-tty";
if(mode == ExtendedMode)
{
fullargs += "--enable-special-filenames";
fullargs += "--status-fd";
fullargs += QString::number(pipeStatus.writeEnd().idAsInt());
fullargs += "--command-fd";
fullargs += QString::number(pipeCommand.readEnd().idAsInt());
}
for(int n = 0; n < args.count(); ++n)
{
QString a = args[n];
if(mode == ExtendedMode && a == "-&?")
fullargs += QString("-&") + QString::number(pipeAux.readEnd().idAsInt());
else
fullargs += a;
}
QString fullcmd = fullargs.join(" ");
emit q->debug(QString("Running: [") + bin + ' ' + fullcmd + ']');
args = fullargs;
}
public slots:
void doStart()
{
#ifdef Q_OS_WIN
// Note: for unix, inheritability is set in SProcess
if(pipeAux.readEnd().isValid())
pipeAux.readEnd().setInheritable(true);
if(pipeCommand.readEnd().isValid())
pipeCommand.readEnd().setInheritable(true);
if(pipeStatus.writeEnd().isValid())
pipeStatus.writeEnd().setInheritable(true);
#endif
setupArguments();
proc->start(bin, args);
// FIXME: From reading the source to Qt on both windows
// and unix platforms, we know that fork/CreateProcess
// are called in start. However this is not guaranteed
// from an API perspective. We should probably call
// QProcess::waitForStarted() to synchronously ensure
// fork/CreateProcess are called before closing these
// pipes.
pipeAux.readEnd().close();
pipeCommand.readEnd().close();
pipeStatus.writeEnd().close();
}
void aux_written(int x)
{
emit q->bytesWrittenAux(x);
}
void aux_error(QCA::QPipeEnd::Error)
{
emit q->debug("Aux: Pipe error");
reset(ResetSession);
emit q->error(GPGProc::ErrorWrite);
}
void command_written(int x)
{
emit q->bytesWrittenCommand(x);
}
void command_error(QCA::QPipeEnd::Error)
{
emit q->debug("Command: Pipe error");
reset(ResetSession);
emit q->error(GPGProc::ErrorWrite);
}
void status_read()
{
if(readAndProcessStatusData())
emit q->readyReadStatusLines();
}
void status_error(QCA::QPipeEnd::Error e)
{
if(e == QPipeEnd::ErrorEOF)
emit q->debug("Status: Closed (EOF)");
else
emit q->debug("Status: Closed (gone)");
fin_status = true;
doTryDone();
}
void proc_started()
{
emit q->debug("Process started");
// Note: we don't close these here anymore. instead we
// do it just after calling proc->start().
// close these, we don't need them
/*pipeAux.readEnd().close();
pipeCommand.readEnd().close();
pipeStatus.writeEnd().close();*/
// do the pre* stuff
if(!pre_stdin.isEmpty())
{
proc->write(pre_stdin);
pre_stdin.clear();
}
if(!pre_aux.isEmpty())
{
pipeAux.writeEnd().write(pre_aux);
pre_aux.clear();
}
if(!pre_command.isEmpty())
{
#ifdef QPIPE_SECURE
pipeCommand.writeEnd().writeSecure(pre_command);
#else
pipeCommand.writeEnd().write(pre_command);
#endif
pre_command.clear();
}
if(pre_stdin_close)
proc->closeWriteChannel();
if(pre_aux_close)
pipeAux.writeEnd().close();
if(pre_command_close)
pipeCommand.writeEnd().close();
}
void proc_readyReadStandardOutput()
{
emit q->readyReadStdout();
}
void proc_readyReadStandardError()
{
emit q->readyReadStderr();
}
void proc_bytesWritten(qint64 lx)
{
int x = (int)lx;
emit q->bytesWrittenStdin(x);
}
void proc_finished(int x)
{
emit q->debug(QString("Process finished: %1").arg(x));
exitCode = x;
fin_process = true;
fin_process_success = true;
if(need_status && !fin_status)
{
pipeStatus.readEnd().finalize();
fin_status = true;
if(readAndProcessStatusData())
{
doneTrigger.start();
emit q->readyReadStatusLines();
return;
}
}
doTryDone();
}
void proc_error(QProcess::ProcessError x)
{
QMap<int, QString> errmap;
errmap[QProcess::FailedToStart] = "FailedToStart";
errmap[QProcess::Crashed] = "Crashed";
errmap[QProcess::Timedout] = "Timedout";
errmap[QProcess::WriteError] = "WriteError";
errmap[QProcess::ReadError] = "ReadError";
errmap[QProcess::UnknownError] = "UnknownError";
emit q->debug(QString("Process error: %1").arg(errmap[x]));
if(x == QProcess::FailedToStart)
error = GPGProc::FailedToStart;
else if(x == QProcess::WriteError)
error = GPGProc::ErrorWrite;
else
error = GPGProc::UnexpectedExit;
fin_process = true;
fin_process_success = false;
#ifdef QT_PIPE_HACK
// If the process fails to start, then the ends of the pipes
// intended for the child process are still open. Some Mac
// users experience a lockup if we close our ends of the pipes
// when the child's ends are still open. If we ensure the
// child's ends are closed, we prevent this lockup. I have no
// idea why the problem even happens or why this fix should
// work.
pipeAux.readEnd().reset();
pipeCommand.readEnd().reset();
pipeStatus.writeEnd().reset();
#endif
if(need_status && !fin_status)
{
pipeStatus.readEnd().finalize();
fin_status = true;
if(readAndProcessStatusData())
{
doneTrigger.start();
emit q->readyReadStatusLines();
return;
}
}
doTryDone();
}
void doTryDone()
{
if(!fin_process)
return;
if(need_status && !fin_status)
return;
emit q->debug("Done");
// get leftover data
proc->setReadChannel(QProcess::StandardOutput);
leftover_stdout = proc->readAll();
proc->setReadChannel(QProcess::StandardError);
leftover_stderr = proc->readAll();
reset(ResetSession);
if(fin_process_success)
emit q->finished(exitCode);
else
emit q->error(error);
}
private:
bool readAndProcessStatusData()
{
QByteArray buf = pipeStatus.readEnd().read();
if(buf.isEmpty())
return false;
return processStatusData(buf);
}
// return true if there are newly parsed lines available
bool processStatusData(const QByteArray &buf)
{
statusBuf.append(buf);
// extract all lines
QStringList list;
while(1)
{
int n = statusBuf.indexOf('\n');
if(n == -1)
break;
// extract the string from statusbuf
++n;
char *p = (char *)statusBuf.data();
QByteArray cs(p, n);
int newsize = statusBuf.size() - n;
memmove(p, p + n, newsize);
statusBuf.resize(newsize);
// convert to string without newline
QString str = QString::fromUtf8(cs);
str.truncate(str.length() - 1);
// ensure it has a proper header
if(str.left(9) != "[GNUPG:] ")
continue;
// take it off
str = str.mid(9);
// add to the list
list += str;
}
if(list.isEmpty())
return false;
statusLines += list;
return true;
}
};
GPGProc::GPGProc(QObject *parent)
:QObject(parent)
{
d = new Private(this);
}
GPGProc::~GPGProc()
{
delete d;
}
void GPGProc::reset()
{
d->reset(ResetAll);
}
bool GPGProc::isActive() const
{
return (d->proc ? true : false);
}
void GPGProc::start(const QString &bin, const QStringList &args, Mode mode)
{
if(isActive())
d->reset(ResetSessionAndData);
if(mode == ExtendedMode)
{
if(!d->setupPipes(args.contains("-&?")))
{
d->error = FailedToStart;
// emit later
QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection, Q_ARG(gpgQCAPlugin::GPGProc::Error, d->error));
return;
}
d->need_status = true;
emit debug("Pipe setup complete");
}
d->proc = new SProcess(d);
#ifdef Q_OS_UNIX
QList<int> plist;
if(d->pipeAux.readEnd().isValid())
plist += d->pipeAux.readEnd().id();
if(d->pipeCommand.readEnd().isValid())
plist += d->pipeCommand.readEnd().id();
if(d->pipeStatus.writeEnd().isValid())
plist += d->pipeStatus.writeEnd().id();
d->proc->setInheritPipeList(plist);
#endif
// enable the pipes we want
if(d->pipeAux.writeEnd().isValid())
d->pipeAux.writeEnd().enable();
if(d->pipeCommand.writeEnd().isValid())
d->pipeCommand.writeEnd().enable();
if(d->pipeStatus.readEnd().isValid())
d->pipeStatus.readEnd().enable();
#ifdef QPROC_SIGNAL_RELAY
d->proc_relay = new QProcessSignalRelay(d->proc, d);
connect(d->proc_relay, SIGNAL(started()), d, SLOT(proc_started()));
connect(d->proc_relay, SIGNAL(readyReadStandardOutput()), d, SLOT(proc_readyReadStandardOutput()));
connect(d->proc_relay, SIGNAL(readyReadStandardError()), d, SLOT(proc_readyReadStandardError()));
connect(d->proc_relay, SIGNAL(bytesWritten(qint64)), d, SLOT(proc_bytesWritten(qint64)));
connect(d->proc_relay, SIGNAL(finished(int)), d, SLOT(proc_finished(int)));
connect(d->proc_relay, SIGNAL(error(QProcess::ProcessError)), d, SLOT(proc_error(QProcess::ProcessError)));
#else
connect(d->proc, SIGNAL(started()), d, SLOT(proc_started()));
connect(d->proc, SIGNAL(readyReadStandardOutput()), d, SLOT(proc_readyReadStandardOutput()));
connect(d->proc, SIGNAL(readyReadStandardError()), d, SLOT(proc_readyReadStandardError()));
connect(d->proc, SIGNAL(bytesWritten(qint64)), d, SLOT(proc_bytesWritten(qint64)));
connect(d->proc, SIGNAL(finished(int)), d, SLOT(proc_finished(int)));
connect(d->proc, SIGNAL(error(QProcess::ProcessError)), d, SLOT(proc_error(QProcess::ProcessError)));
#endif
d->bin = bin;
d->args = args;
d->mode = mode;
d->startTrigger.start();
}
QByteArray GPGProc::readStdout()
{
if(d->proc)
{
d->proc->setReadChannel(QProcess::StandardOutput);
return d->proc->readAll();
}
else
{
QByteArray a = d->leftover_stdout;
d->leftover_stdout.clear();
return a;
}
}
QByteArray GPGProc::readStderr()
{
if(d->proc)
{
d->proc->setReadChannel(QProcess::StandardError);
return d->proc->readAll();
}
else
{
QByteArray a = d->leftover_stderr;
d->leftover_stderr.clear();
return a;
}
}
QStringList GPGProc::readStatusLines()
{
QStringList out = d->statusLines;
d->statusLines.clear();
return out;
}
void GPGProc::writeStdin(const QByteArray &a)
{
if(!d->proc || a.isEmpty())
return;
if(d->proc->state() == QProcess::Running)
d->proc->write(a);
else
d->pre_stdin += a;
}
void GPGProc::writeAux(const QByteArray &a)
{
if(!d->proc || a.isEmpty())
return;
if(d->proc->state() == QProcess::Running)
d->pipeAux.writeEnd().write(a);
else
d->pre_aux += a;
}
#ifdef QPIPE_SECURE
void GPGProc::writeCommand(const SecureArray &a)
#else
void GPGProc::writeCommand(const QByteArray &a)
#endif
{
if(!d->proc || a.isEmpty())
return;
if(d->proc->state() == QProcess::Running)
#ifdef QPIPE_SECURE
d->pipeCommand.writeEnd().writeSecure(a);
#else
d->pipeCommand.writeEnd().write(a);
#endif
else
d->pre_command += a;
}
void GPGProc::closeStdin()
{
if(!d->proc)
return;
if(d->proc->state() == QProcess::Running)
d->proc->closeWriteChannel();
else
d->pre_stdin_close = true;
}
void GPGProc::closeAux()
{
if(!d->proc)
return;
if(d->proc->state() == QProcess::Running)
d->pipeAux.writeEnd().close();
else
d->pre_aux_close = true;
}
void GPGProc::closeCommand()
{
if(!d->proc)
return;
if(d->proc->state() == QProcess::Running)
d->pipeCommand.writeEnd().close();
else
d->pre_command_close = true;
}
}
#include "gpgproc.moc"

View file

@ -0,0 +1,114 @@
/*
* Copyright (C) 2003-2005 Justin Karneges <justin@affinix.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
#ifndef GPGPROC_H
#define GPGPROC_H
#include "qpipe.h"
class QTimer;
namespace gpgQCAPlugin {
// FIXME: Even though deleting an object during a metacall event is supposed
// to be legal with Qt, it is unfortunately buggy (at least before Qt 4.4).
// This function performs the following steps:
// obj->disconnect(owner); // to prevent future signals to owner
// obj->setParent(0); // to prevent delete if parent is deleted
// obj->deleteLater(); // now we can forget about the object
void releaseAndDeleteLater(QObject *owner, QObject *obj);
class SafeTimer : public QObject
{
Q_OBJECT
public:
SafeTimer(QObject *parent = 0);
~SafeTimer();
int interval() const;
bool isActive() const;
bool isSingleShot() const;
void setInterval(int msec);
void setSingleShot(bool singleShot);
int timerId() const;
public slots:
void start(int msec);
void start();
void stop();
signals:
void timeout();
private:
QTimer *timer;
};
// GPGProc - executes gpg and provides access to all 6 channels. NormalMode
// enables stdout, stderr, and stdin. ExtendedMode has those 3 plus status
// aux, and command. The aux channel is connected to the '-&?' argument.
// The debug() signal, as well as stderr, can be used for diagnostic text.
class GPGProc : public QObject
{
Q_OBJECT
public:
enum Error { FailedToStart, UnexpectedExit, ErrorWrite };
enum Mode { NormalMode, ExtendedMode };
GPGProc(QObject *parent = 0);
~GPGProc();
void reset();
bool isActive() const;
void start(const QString &bin, const QStringList &args, Mode m = ExtendedMode);
QByteArray readStdout();
QByteArray readStderr();
QStringList readStatusLines();
void writeStdin(const QByteArray &a);
void writeAux(const QByteArray &a);
#ifdef QPIPE_SECURE
void writeCommand(const QCA::SecureArray &a);
#else
void writeCommand(const QByteArray &a);
#endif
void closeStdin();
void closeAux();
void closeCommand();
Q_SIGNALS:
void error(gpgQCAPlugin::GPGProc::Error error);
void finished(int exitCode);
void readyReadStdout();
void readyReadStderr();
void readyReadStatusLines();
void bytesWrittenStdin(int bytes);
void bytesWrittenAux(int bytes);
void bytesWrittenCommand(int bytes);
void debug(const QString &str); // not signal-safe
private:
class Private;
friend class Private;
Private *d;
};
}
#endif

View file

@ -0,0 +1,8 @@
HEADERS += \
$$PWD/sprocess.h \
$$PWD/gpgproc.h
SOURCES += \
$$PWD/sprocess.cpp \
$$PWD/gpgproc.cpp

View file

@ -0,0 +1,55 @@
/*
* Copyright (C) 2003-2005 Justin Karneges <justin@affinix.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
#include "sprocess.h"
#ifdef Q_OS_UNIX
# include <unistd.h>
# include <fcntl.h>
#endif
namespace gpgQCAPlugin {
//----------------------------------------------------------------------------
// SProcess
//----------------------------------------------------------------------------
SProcess::SProcess(QObject *parent)
:QProcess(parent)
{
}
SProcess::~SProcess()
{
}
#ifdef Q_OS_UNIX
void SProcess::setInheritPipeList(const QList<int> &list)
{
pipeList = list;
}
void SProcess::setupChildProcess()
{
// set the pipes to be inheritable
for(int n = 0; n < pipeList.count(); ++n)
::fcntl(pipeList[n], F_SETFD, (::fcntl(pipeList[n], F_GETFD) & ~FD_CLOEXEC));
}
#endif
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (C) 2003-2005 Justin Karneges <justin@affinix.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*
*/
#ifndef SPROCESS_H
#define SPROCESS_H
#include <QProcess>
#include <QTimer>
namespace gpgQCAPlugin {
class SProcess : public QProcess
{
Q_OBJECT
public:
SProcess(QObject *parent = 0);
~SProcess();
#ifdef Q_OS_UNIX
void setInheritPipeList(const QList<int> &);
protected:
virtual void setupChildProcess();
private:
QList<int> pipeList;
#endif
};
}
#endif

1790
third-party/qca/qca-gnupg/qca-gnupg.cpp vendored Normal file

File diff suppressed because it is too large Load diff