Merge branch 'ikloecker/t6342-gpgtar' into master

--
Solved conflicts:
	NEWS
	lang/cpp/src/context.cpp
	lang/cpp/src/context.h
This commit is contained in:
Werner Koch 2023-01-31 07:59:27 +01:00
commit 3cdcfa33f7
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
45 changed files with 2509 additions and 375 deletions

22
NEWS
View File

@ -5,6 +5,15 @@ Noteworthy changes in version 1.18.1 (unreleased)
* Optionally, build QGpgME for Qt 6
* Support component "gpgtar-name" in gpgme_get_dirinfo. [T6342]
* Extended gpgme_op_encrypt*, gpgme_op_encrypt_sign*, and
gpgme_op_sign* to allow creating an encrypted and/or signed
archive. [T6342]
* Extended gpgme_op_decrypt*, gpgme_op_decrypt_verify*, and gpgme_op_verify*
to allow extracting an encrypted and/or signed archive. [T6342]
* cpp: Handle error when trying to sign expired keys. [T6155]
* cpp: Support encryption flags ThrowKeyIds, EncryptWrap, and WantAddress.
@ -23,19 +32,32 @@ Noteworthy changes in version 1.18.1 (unreleased)
* qt: Allow deferred start of import jobs. [T6323]
* qt: Support creating encrypted archives. [T6342]
* Interface changes relative to the 1.18.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gpgme_get_ctx_flag EXTENDED: New flag 'no-auto-check-trustdb'.
gpgme_set_ctx_flag EXTENDED: New flag 'no-auto-check-trustdb'.
GPGME_DECRYPT_ARCHIVE NEW.
GPGME_ENCRYPT_ARCHIVE NEW.
GPGME_SIG_MODE_ARCHIVE NEW.
GPGME_VERIFY_ARCHIVE NEW.
gpgme_verify_flags_t NEW.
gpgme_op_verify_ext_start NEW.
gpgme_op_verify_ext NEW.
cpp: GpgGenCardKeyInteractor::Curve NEW.
cpp: GpgGenCardKeyInteractor::setCurve NEW.
cpp: Context::WantAddress NEW.
cpp: Data::setFileName EXTENDED: New overload
qt: ListAllKeysJob::Option NEW.
qt: ListAllKeysJob::Options NEW.
qt: ListAllKeysJob::setOptions NEW.
qt: ListAllKeysJob::options NEW.
qt: Job::startNow NEW.
qt: ImportJob::startLater NEW.
qt: FileListDataProvider NEW.
qt: EncryptArchiveJob NEW.
qt: Protocol::encryptArchiveJob NEW.
Noteworthy changes in version 1.18.0 (2022-08-10)

View File

@ -981,6 +981,9 @@ Return the name of the directory with GnuPG shared data.
@item localedir
Return the name of the directory with GnuPG locale data.
@item socketdir
Return the name of the directory with the following sockets.
@item agent-socket
Return the name of the socket to connect to the gpg-agent.
@ -1024,6 +1027,9 @@ Return the name of the pinentry program.
@item gpg-wks-client-name
Return the name of the Web Key Service tool.
@item gpgtar-name
Return the name of the gpgtar program.
@end table
@end deftypefun
@ -2193,6 +2199,11 @@ associated with the data object. The file name will be stored in the
output when encrypting or signing the data and will be returned to the
user when decrypting or verifying the output data.
If a signed or encrypted archive is created, then the file name will be
interpreted as the base directory for the relative paths of the files and
directories to put into the archive. This corresponds to the --directory
option of gpgtar.
The function returns the error code @code{GPG_ERR_INV_VALUE} if
@var{dh} is not a valid pointer and @code{GPG_ERR_ENOMEM} if not
enough memory is available.
@ -3161,8 +3172,8 @@ The string given in @var{value} is passed to the GnuPG engine to override
the session key for decryption. The format of that session key is
specific to GnuPG and can be retrieved during a decrypt operation when
the context flag "export-session-key" is enabled. Please be aware that
using this feature with GnuPG < 2.1.16 will leak the session key on
many platforms via ps(1).
using this feature with GnuPG < 2.1.16 or when decrypting an archive
will leak the session key on many platforms via ps(1).
@item "auto-key-retrieve"
Setting the @var{value} to "1" asks the backend to automatically
@ -5611,6 +5622,12 @@ The function @code{gpgme_op_decrypt_ext} is the same as
@code{gpgme_op_decrypt} but has an additional argument
@var{flags}. If @var{flags} is 0 both function behave identically.
If the flag @code{GPGME_DECRYPT_ARCHIVE} is set, then an encrypted
archive in the data object @var{cipher} is decrypted and extracted.
The content of the archive is extracted into a directory named
@code{GPGARCH_n_} (where @code{n} is a number) or into the directory
set with @code{gpgme_data_set_file_name} for the data object @var{plain}.
The value in @var{flags} is a bitwise-or combination of one or
multiple of the following bit values:
@ -5621,6 +5638,14 @@ multiple of the following bit values:
The @code{GPGME_DECRYPT_VERIFY} symbol specifies that this function
shall exactly act as @code{gpgme_op_decrypt_verify}.
@item GPGME_DECRYPT_ARCHIVE
@since{1.19.0}
The @code{GPGME_DECRYPT_ARCHIVE} symbol specifies that the input is an
encrypted archive that shall be decrypted and extracted. This feature
is currently only supported for the OpenPGP crypto engine and requires
GnuPG 2.4.1.
@item GPGME_DECRYPT_UNWRAP
@since{1.8.0}
@ -5800,6 +5825,61 @@ operation could be started successfully, @code{GPG_ERR_INV_VALUE} if
any data to verify.
@end deftypefun
@deftypefun gpgme_error_t gpgme_op_verify_ext ( @
@w{gpgme_ctx_t @var{ctx}}, @
@w{gpgme_verify_flags_t @var{flags}}, @
@w{gpgme_data_t @var{sig}}, @
@w{gpgme_data_t @var{signed_text}}, @
@w{gpgme_data_t @var{plain}})
The function @code{gpgme_op_verify_ext} is the same as
@code{gpgme_op_verify} but has an additional argument
@var{flags}. If @var{flags} is 0 both function behave identically.
If the flag @code{GPGME_VERIFY_ARCHIVE} is set, then a signed archive
in the data object @var{sig} is verified and extracted. The content of
the archive is extracted into a directory named @code{GPGARCH_n_}
(where @code{n} is a number) or into the directory set with
@code{gpgme_data_set_file_name} for the data object @var{plain}.
The value in @var{flags} is a bitwise-or combination of one or
multiple of the following bit values:
@table @code
@item GPGME_VERIFY_ARCHIVE
@since{1.19.0}
The @code{GPGME_VERIFY_ARCHIVE} symbol specifies that the input is a
signed archive that shall be verified and extracted. This feature
is currently only supported for the OpenPGP crypto engine and requires
GnuPG 2.4.1.
@end table
The function returns the error codes as descriped for
@code{gpgme_op_decrypt} respective @code{gpgme_op_encrypt}.
@end deftypefun
@deftypefun gpgme_error_t gpgme_op_verify_ext_start ( @
@w{gpgme_ctx_t @var{ctx}}, @
@w{gpgme_verify_flags_t @var{flags}}, @
@w{gpgme_data_t @var{sig}}, @
@w{gpgme_data_t @var{signed_text}}, @
@w{gpgme_data_t @var{plain}})
The function @code{gpgme_op_verify_ext_start} initiates a
@code{gpgme_op_verify_ext} operation. It can be completed by calling
@code{gpgme_wait} on the context. @xref{Waiting For Completion}.
The function returns the error code @code{GPG_ERR_NO_ERROR} if the
operation could be started successfully, @code{GPG_ERR_INV_VALUE} if
@var{ctx}, @var{sig} or @var{plain} is not a valid pointer, and
@code{GPG_ERR_NO_DATA} if @var{sig} or @var{plain} does not contain
any data to verify.
@end deftypefun
@deftp {Data type} {gpgme_sig_notation_t}
This is a pointer to a structure used to store a part of the result of
a @code{gpgme_op_verify} operation. The structure contains the
@ -6232,6 +6312,14 @@ A detached signature is made.
@item GPGME_SIG_MODE_CLEAR
A clear text signature is made. The @acronym{ASCII} armor and text
mode settings of the context are ignored.
@item GPGME_SIG_MODE_ARCHIVE
@since{1.19.0}
A signed archive is created from the given files and directories. This
feature is currently only supported for the OpenPGP crypto engine and requires
GnuPG 2.4.1.
@end table
@end deftp
@ -6243,6 +6331,13 @@ the data object @var{plain} and returns it in the data object
specified for @var{sig}), the text mode attributes set for the context
@var{ctx} and the requested signature mode @var{mode}.
If signature mode @code{GPGME_SIG_MODE_ARCHIVE} is requested, then a
signed archive is created from the files and directories given as
NUL-separated list in the data object @var{plain} and returned in the
data object @var{sig}. The paths of the files and directories have to
be given as paths relative to the current working directory or relative
to the base directory set with @code{gpgme_data_set_file_name}.
After the operation completed successfully, the result can be
retrieved with @code{gpgme_op_sign_result}.
@ -6414,6 +6509,13 @@ ciphertext created is determined by the @acronym{ASCII} armor (or, if
that is not set, by the encoding specified for @var{cipher}) and the
text mode attributes set for the context @var{ctx}.
If the flag @code{GPGME_ENCRYPT_ARCHIVE} is set, then an encrypted
archive is created from the files and directories given as NUL-separated
list in the data object @var{plain} and returned in the data object
@var{cipher}. The paths of the files and directories have to
be given as paths relative to the current working directory or relative
to the base directory set with @code{gpgme_data_set_file_name}.
@var{recp} must be a @code{NULL}-terminated array of keys. The user
must keep references for all keys during the whole duration of the
call (but see @code{gpgme_op_encrypt_start} for the requirements with
@ -6489,6 +6591,14 @@ of now the key must be specified using the @var{recpstring} argument
of the extended encrypt functions. This feature is currently only
supported for the OpenPGP crypto engine.
@item GPGME_ENCRYPT_ARCHIVE
@since{1.19.0}
The @code{GPGME_ENCRYPT_ARCHIVE} symbol specifies that the input is a
NUL-separated list of file paths and directory paths that shall be
encrypted into an archive. This feature is currently only supported
for the OpenPGP crypto engine and requires GnuPG 2.4.1.
@end table
If @code{GPG_ERR_UNUSABLE_PUBKEY} is returned, some recipients in

View File

@ -1278,14 +1278,22 @@ std::vector<Notation> Context::signatureNotations() const
return result;
}
static gpgme_sig_mode_t sigmode2sigmode(SignatureMode mode)
static gpgme_sig_mode_t sigflags2sigflags(SignatureMode flags)
{
switch (mode) {
default:
case NormalSignatureMode: return GPGME_SIG_MODE_NORMAL;
case Detached: return GPGME_SIG_MODE_DETACH;
case Clearsigned: return GPGME_SIG_MODE_CLEAR;
unsigned int result = 0;
if (flags & SignatureMode::NormalSignatureMode) {
result |= GPGME_SIG_MODE_NORMAL;
}
if (flags & SignatureMode::Detached) {
result |= GPGME_SIG_MODE_DETACH;
}
if (flags & SignatureMode::Clearsigned) {
result |= GPGME_SIG_MODE_CLEAR;
}
if (flags & SignatureMode::SignArchive) {
result |= GPGME_SIG_MODE_ARCHIVE;
}
return static_cast<gpgme_sig_mode_t>(result);
}
SigningResult Context::sign(const Data &plainText, Data &signature, SignatureMode mode)
@ -1293,7 +1301,7 @@ SigningResult Context::sign(const Data &plainText, Data &signature, SignatureMod
d->lastop = Private::Sign;
const Data::Private *const pdp = plainText.impl();
Data::Private *const sdp = signature.impl();
d->lasterr = gpgme_op_sign(d->ctx, pdp ? pdp->data : nullptr, sdp ? sdp->data : nullptr, sigmode2sigmode(mode));
d->lasterr = gpgme_op_sign(d->ctx, pdp ? pdp->data : nullptr, sdp ? sdp->data : nullptr, sigflags2sigflags(mode));
return SigningResult(d->ctx, Error(d->lasterr));
}
@ -1302,7 +1310,7 @@ Error Context::startSigning(const Data &plainText, Data &signature, SignatureMod
d->lastop = Private::Sign;
const Data::Private *const pdp = plainText.impl();
Data::Private *const sdp = signature.impl();
return Error(d->lasterr = gpgme_op_sign_start(d->ctx, pdp ? pdp->data : nullptr, sdp ? sdp->data : nullptr, sigmode2sigmode(mode)));
return Error(d->lasterr = gpgme_op_sign_start(d->ctx, pdp ? pdp->data : nullptr, sdp ? sdp->data : nullptr, sigflags2sigflags(mode)));
}
SigningResult Context::signingResult() const
@ -1344,6 +1352,9 @@ static gpgme_encrypt_flags_t encryptflags2encryptflags(Context::EncryptionFlags
if (flags & Context::WantAddress) {
result |= GPGME_ENCRYPT_WANT_ADDRESS;
}
if (flags & Context::EncryptArchive) {
result |= GPGME_ENCRYPT_ARCHIVE;
}
return static_cast<gpgme_encrypt_flags_t>(result);
}
@ -1895,16 +1906,12 @@ std::ostream &operator<<(std::ostream &os, KeyListMode mode)
std::ostream &operator<<(std::ostream &os, SignatureMode mode)
{
os << "GpgME::SignatureMode(";
switch (mode) {
#define CHECK( x ) case x: os << #x; break
#define CHECK( x ) if ( !(mode & (x)) ) {} else do { os << #x " "; } while (0)
CHECK(NormalSignatureMode);
CHECK(Detached);
CHECK(Clearsigned);
CHECK(SignArchive);
#undef CHECK
default:
os << "???" "(" << static_cast<int>(mode) << ')';
break;
}
return os << ')';
}
@ -1921,6 +1928,7 @@ std::ostream &operator<<(std::ostream &os, Context::EncryptionFlags flags)
CHECK(ThrowKeyIds);
CHECK(EncryptWrap);
CHECK(WantAddress);
CHECK(EncryptArchive);
#undef CHECK
return os << ')';
}

View File

@ -449,6 +449,7 @@ public:
ThrowKeyIds = 64,
EncryptWrap = 128,
WantAddress = 256,
EncryptArchive = 512
};
EncryptionResult encrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags);
GpgME::Error encryptSymmetrically(const Data &plainText, Data &cipherText);

View File

@ -217,6 +217,11 @@ GpgME::Error GpgME::Data::setFileName(const char *name)
return Error(gpgme_data_set_file_name(d->data, name));
}
GpgME::Error GpgME::Data::setFileName(const std::string &name)
{
return Error(gpgme_data_set_file_name(d->data, name.c_str()));
}
ssize_t GpgME::Data::read(void *buffer, size_t length)
{
return gpgme_data_read(d->data, buffer, length);

View File

@ -106,6 +106,7 @@ public:
char *fileName() const;
Error setFileName(const char *name);
Error setFileName(const std::string &name);
ssize_t read(void *buffer, size_t length);
ssize_t write(const void *buffer, size_t length);

View File

@ -74,7 +74,12 @@ enum KeyListMode {
KeyListModeMask = 0x3ff
};
enum SignatureMode { NormalSignatureMode, Detached, Clearsigned };
enum SignatureMode {
NormalSignatureMode = 0,
Detached = 1,
Clearsigned = 2,
SignArchive = 4,
};
enum class RevocationReason {
Unspecified = 0,
@ -103,7 +108,7 @@ homedir, sysconfdir, bindir, libexecdir, libdir,
datadir, localedir, agent-socket, agent-ssh-socket,
dirmngr-socket, uiserver-socket, gpgconf-name, gpg-name,
gpgsm-name, g13-name, keyboxd-name, agent-name, scdaemon-name,
dirmngr-name, pinentry-name, socketdir.
dirmngr-name, pinentry-name, socketdir, gpg-wks-client-name, gpgtar-name.
This may be extended in the future.
*/

View File

@ -199,6 +199,7 @@ GpgME::SignatureMode GpgME::CreatedSignature::mode() const
case GPGME_SIG_MODE_NORMAL: return NormalSignatureMode;
case GPGME_SIG_MODE_DETACH: return Detached;
case GPGME_SIG_MODE_CLEAR: return Clearsigned;
case GPGME_SIG_MODE_ARCHIVE: return SignArchive; // cannot happen
}
}

View File

@ -34,11 +34,14 @@ EXTRA_DIST = QGpgmeConfig.cmake.in.in QGpgmeConfigVersion.cmake.in \
qgpgme_sources = \
dataprovider.cpp \
debug.cpp \
encryptarchivejob.cpp \
filelistdataprovider.cpp \
job.cpp multideletejob.cpp qgpgmeadduseridjob.cpp \
qgpgmeaddexistingsubkeyjob.cpp \
qgpgmebackend.cpp qgpgmechangeexpiryjob.cpp qgpgmechangeownertrustjob.cpp \
qgpgmechangepasswdjob.cpp qgpgmedecryptjob.cpp \
qgpgmedecryptverifyjob.cpp qgpgmedeletejob.cpp qgpgmedownloadjob.cpp \
qgpgmeencryptarchivejob.cpp \
qgpgmeencryptjob.cpp qgpgmeexportjob.cpp qgpgmeimportfromkeyserverjob.cpp \
qgpgmeimportjob.cpp qgpgmekeygenerationjob.cpp qgpgmekeylistjob.cpp \
listallkeysjob.cpp qgpgmelistallkeysjob.cpp qgpgmenewcryptoconfig.cpp \
@ -46,6 +49,7 @@ qgpgme_sources = \
qgpgmerefreshsmimekeysjob.cpp \
qgpgmerevokekeyjob.cpp \
qgpgmesetprimaryuseridjob.cpp \
qgpgmesignarchivejob.cpp \
qgpgmesignencryptjob.cpp \
qgpgmesignjob.cpp qgpgmesignkeyjob.cpp qgpgmeverifydetachedjob.cpp \
qgpgmeverifyopaquejob.cpp qgpgmewkdlookupjob.cpp threadedjobmixin.cpp \
@ -53,6 +57,7 @@ qgpgme_sources = \
qgpgmetofupolicyjob.cpp qgpgmequickjob.cpp \
defaultkeygenerationjob.cpp qgpgmewkspublishjob.cpp \
qgpgmegpgcardjob.cpp changeexpiryjob.cpp encryptjob.cpp importjob.cpp \
signarchivejob.cpp \
signencryptjob.cpp \
dn.cpp cryptoconfig.cpp wkdlookupresult.cpp \
util.cpp
@ -70,8 +75,10 @@ qgpgme_headers= \
decryptjob.h \
decryptverifyjob.h \
downloadjob.h \
encryptarchivejob.h \
encryptjob.h \
exportjob.h \
filelistdataprovider.h \
hierarchicalkeylistjob.h \
job.h \
keyformailboxjob.h \
@ -84,6 +91,7 @@ qgpgme_headers= \
revokekeyjob.h \
setprimaryuseridjob.h \
specialjob.h \
signarchivejob.h \
signjob.h \
signkeyjob.h \
signencryptjob.h \
@ -118,8 +126,10 @@ camelcase_headers= \
DecryptVerifyJob \
DN \
DownloadJob \
EncryptArchiveJob \
EncryptJob \
ExportJob \
FileListDataProvider \
HierarchicalKeyKistJob \
Job \
MultiDeleteJob \
@ -130,6 +140,7 @@ camelcase_headers= \
RevokeKeyJob \
SetPrimaryUserIDJob \
SpecialJob \
SignArchiveJob \
SignJob \
SignKeyJob \
SignEncryptJob \
@ -153,6 +164,7 @@ camelcase_headers= \
private_qgpgme_headers = \
changeexpiryjob_p.h \
encryptarchivejob_p.h \
encryptjob_p.h \
importjob_p.h \
listallkeysjob_p.h \
@ -169,6 +181,7 @@ private_qgpgme_headers = \
qgpgmedecryptverifyjob.h \
qgpgmedeletejob.h \
qgpgmedownloadjob.h \
qgpgmeencryptarchivejob.h \
qgpgmeencryptjob.h \
qgpgmeexportjob.h \
qgpgmeimportfromkeyserverjob.h \
@ -180,6 +193,7 @@ private_qgpgme_headers = \
qgpgmerefreshsmimekeysjob.h \
qgpgmerevokekeyjob.h \
qgpgmesetprimaryuseridjob.h \
qgpgmesignarchivejob.h \
qgpgmesignencryptjob.h \
qgpgmesignjob.h \
qgpgmesignkeyjob.h \
@ -191,6 +205,7 @@ private_qgpgme_headers = \
qgpgmetofupolicyjob.h \
qgpgmegpgcardjob.h \
qgpgmequickjob.h \
signarchivejob_p.h \
signencryptjob_p.h \
threadedjobmixin.h \
util.h
@ -206,6 +221,7 @@ qgpgme_moc_sources = \
decryptverifyjob.moc \
deletejob.moc \
downloadjob.moc \
encryptarchivejob.moc \
encryptjob.moc \
exportjob.moc \
hierarchicalkeylistjob.moc \
@ -225,6 +241,7 @@ qgpgme_moc_sources = \
qgpgmedecryptverifyjob.moc \
qgpgmedeletejob.moc \
qgpgmedownloadjob.moc \
qgpgmeencryptarchivejob.moc \
qgpgmeencryptjob.moc \
qgpgmeexportjob.moc \
qgpgmeimportfromkeyserverjob.moc \
@ -236,6 +253,7 @@ qgpgme_moc_sources = \
qgpgmerefreshsmimekeysjob.moc \
qgpgmerevokekeyjob.moc \
qgpgmesetprimaryuseridjob.moc \
qgpgmesignarchivejob.moc \
qgpgmesignencryptjob.moc \
qgpgmesignjob.moc \
qgpgmesignkeyjob.moc \
@ -249,6 +267,7 @@ qgpgme_moc_sources = \
refreshkeysjob.moc \
revokekeyjob.moc \
setprimaryuseridjob.moc \
signarchivejob.moc \
signencryptjob.moc \
signjob.moc \
signkeyjob.moc \

View File

@ -25,7 +25,13 @@
#define __QGPGME_DATAPROVIDER_H__
#include "qgpgme_export.h"
#ifdef BUILDING_QGPGME
#include <interfaces/dataprovider.h>
#else
#include <gpgme++/interfaces/dataprovider.h>
#endif
#include <memory>
#include <QtCore/QByteArray>

View File

@ -0,0 +1,62 @@
/*
encryptarchivejob.cpp
This file is part of qgpgme, the Qt API binding for gpgme
Copyright (c) 2023 g10 Code GmbH
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME 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.
QGpgME 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
In addition, as a special exception, the copyright holders give
permission to link the code of this program with any edition of
the Qt library by Trolltech AS, Norway (or with modified versions
of Qt that use the same license as Qt), and distribute linked
combinations including the two. You must obey the GNU General
Public License in all respects for all of the code used other than
Qt. If you modify this file, you may extend this exception to
your version of the file, but you are not obligated to do so. If
you do not wish to do so, delete this exception statement from
your version.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "encryptarchivejob.h"
#include "encryptarchivejob_p.h"
using namespace QGpgME;
EncryptArchiveJob::EncryptArchiveJob(QObject *parent)
: Job{parent}
{
}
EncryptArchiveJob::~EncryptArchiveJob() = default;
void EncryptArchiveJob::setBaseDirectory(const QString &baseDirectory)
{
auto d = jobPrivate<EncryptArchiveJobPrivate>(this);
d->m_baseDirectory = baseDirectory;
}
QString EncryptArchiveJob::baseDirectory() const
{
auto d = jobPrivate<EncryptArchiveJobPrivate>(this);
return d->m_baseDirectory;
}
#include "encryptarchivejob.moc"

View File

@ -0,0 +1,101 @@
/*
encryptarchivejob.h
This file is part of qgpgme, the Qt API binding for gpgme
Copyright (c) 2023 g10 Code GmbH
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME 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.
QGpgME 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
In addition, as a special exception, the copyright holders give
permission to link the code of this program with any edition of
the Qt library by Trolltech AS, Norway (or with modified versions
of Qt that use the same license as Qt), and distribute linked
combinations including the two. You must obey the GNU General
Public License in all respects for all of the code used other than
Qt. If you modify this file, you may extend this exception to
your version of the file, but you are not obligated to do so. If
you do not wish to do so, delete this exception statement from
your version.
*/
#ifndef __QGPGME_ENCRYPTARCHIVEJOB_H__
#define __QGPGME_ENCRYPTARCHIVEJOB_H__
#include "job.h"
#ifdef BUILDING_QGPGME
# include "context.h"
#else
# include <gpgme++/context.h>
#endif
namespace GpgME
{
class Key;
}
namespace QGpgME
{
/**
* Abstract base class for job for creating encrypted archives
*/
class QGPGME_EXPORT EncryptArchiveJob : public Job
{
Q_OBJECT
protected:
explicit EncryptArchiveJob(QObject *parent);
public:
~EncryptArchiveJob() override;
void setBaseDirectory(const QString &baseDirectory);
QString baseDirectory() const;
/**
* Starts the creation of an encrypted archive.
*
* Encrypts the files and directories in \a paths into an archive for the
* keys in \a recipients. If \a recipients is empty, then symmetric
* encryption is performed. The encrypted archive is written to \a cipherText.
*
* Emits result() when the job has finished.
*/
virtual GpgME::Error start(const std::vector<GpgME::Key> &recipients,
const std::vector<QString> &paths,
const std::shared_ptr<QIODevice> &cipherText,
const GpgME::Context::EncryptionFlags flags) = 0;
/**
* Creates an encrypted archive.
*
* Encrypts the files and directories in \a paths into an archive for the
* keys in \a recipients. If \a recipients is empty, then symmetric
* encryption is performed. The encrypted archive is written to \a cipherText.
*/
// virtual GpgME::EncryptionResult exec(const std::vector<GpgME::Key> &recipients,
// const std::vector<QString> &paths,
// const std::shared_ptr<QIODevice> &cipherText,
// const GpgME::Context::EncryptionFlags flags) = 0;
Q_SIGNALS:
void result(const GpgME::EncryptionResult &result,
const QString &auditLogAsHtml = {},
const GpgME::Error &auditLogError = {});
};
}
#endif // __QGPGME_ENCRYPTARCHIVEJOB_H__

View File

@ -0,0 +1,49 @@
/*
encryptarchivejob_p.h
This file is part of qgpgme, the Qt API binding for gpgme
Copyright (c) 2023 g10 Code GmbH
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME 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.
QGpgME 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
In addition, as a special exception, the copyright holders give
permission to link the code of this program with any edition of
the Qt library by Trolltech AS, Norway (or with modified versions
of Qt that use the same license as Qt), and distribute linked
combinations including the two. You must obey the GNU General
Public License in all respects for all of the code used other than
Qt. If you modify this file, you may extend this exception to
your version of the file, but you are not obligated to do so. If
you do not wish to do so, delete this exception statement from
your version.
*/
#ifndef __QGPGME_ENCRYPTARCHIVEJOB_P_H__
#define __QGPGME_ENCRYPTARCHIVEJOB_P_H__
#include "job_p.h"
namespace QGpgME
{
struct EncryptArchiveJobPrivate : public JobPrivate
{
QString m_baseDirectory;
};
}
#endif // __QGPGME_ENCRYPTARCHIVEJOB_P_H__

View File

@ -0,0 +1,98 @@
/*
filelistdataprovider.cpp
This file is part of qgpgme, the Qt API binding for gpgme
Copyright (c) 2023 g10 Code GmbH
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME 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.
QGpgME 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
In addition, as a special exception, the copyright holders give
permission to link the code of this program with any edition of
the Qt library by Trolltech AS, Norway (or with modified versions
of Qt that use the same license as Qt), and distribute linked
combinations including the two. You must obey the GNU General
Public License in all respects for all of the code used other than
Qt. If you modify this file, you may extend this exception to
your version of the file, but you are not obligated to do so. If
you do not wish to do so, delete this exception statement from
your version.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "filelistdataprovider.h"
#include "dataprovider.h"
#include <QString>
#include <gpgme++/error.h>
#include <numeric>
using namespace QGpgME;
using namespace GpgME;
static QByteArray encodeFilenames(const std::vector<QString> &filenames)
{
QByteArray ret;
if (filenames.empty()) {
return ret;
}
// calculate and reserve the needed minimum size of the result
const auto addSize = [](unsigned int n, const QString &s) { return n + s.size(); };
const unsigned int minSize = filenames.size()
+ std::accumulate(filenames.cbegin(), filenames.cend(), 0u, addSize);
ret.reserve(minSize);
// pack the filenames into the byte array
for (const auto &f : filenames) {
if (!f.isEmpty()) {
ret += f.toUtf8() + '\0';
}
}
ret.chop(1); // remove the trailing nul
return ret;
}
FileListDataProvider::FileListDataProvider(const std::vector<QString> &filenames)
: mProvider{new QByteArrayDataProvider{encodeFilenames(filenames)}}
{
}
FileListDataProvider::~FileListDataProvider() = default;
ssize_t FileListDataProvider::read(void* buffer, size_t bufSize)
{
return mProvider->read(buffer, bufSize);
}
ssize_t FileListDataProvider::write(const void *, size_t)
{
Error::setSystemError(GPG_ERR_EBADF);
return -1;
}
off_t FileListDataProvider::seek(off_t offset, int whence)
{
return mProvider->seek(offset, whence);
}
void FileListDataProvider::release()
{
mProvider->release();
}

View File

@ -0,0 +1,79 @@
/*
filelistdataprovider.h
This file is part of qgpgme, the Qt API binding for gpgme
Copyright (c) 2023 g10 Code GmbH
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME 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.
QGpgME 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
In addition, as a special exception, the copyright holders give
permission to link the code of this program with any edition of
the Qt library by Trolltech AS, Norway (or with modified versions
of Qt that use the same license as Qt), and distribute linked
combinations including the two. You must obey the GNU General
Public License in all respects for all of the code used other than
Qt. If you modify this file, you may extend this exception to
your version of the file, but you are not obligated to do so. If
you do not wish to do so, delete this exception statement from
your version.
*/
#ifndef __QGPGME_FILELISTDATAPROVIDER_H__
#define __QGPGME_FILELISTDATAPROVIDER_H__
#include "qgpgme_export.h"
#ifdef BUILDING_QGPGME
#include <interfaces/dataprovider.h>
#else
#include <gpgme++/interfaces/dataprovider.h>
#endif
#include <memory>
#include <vector>
class QString;
namespace QGpgME
{
/**
* This read-only data provider simplifies providing a nul-separated list of
* UTF-8-encoded filenames, e.g. for creating signed or encrypted archives.
*/
class QGPGME_EXPORT FileListDataProvider : public GpgME::DataProvider
{
public:
explicit FileListDataProvider(const std::vector<QString> &filenames);
~FileListDataProvider() override;
private:
bool isSupported(Operation op) const override
{
return op != Operation::Write;
}
ssize_t read(void *buffer, size_t bufSize) override;
ssize_t write(const void *buffer, size_t bufSize) override;
off_t seek(off_t offset, int whence) override;
void release() override;
private:
std::unique_ptr<GpgME::DataProvider> mProvider;
};
}
#endif // __QGPGME_FILELISTDATAPROVIDER_H__

View File

@ -50,8 +50,10 @@ class ImportFromKeyserverJob;
class ExportJob;
class DownloadJob;
class DeleteJob;
class EncryptArchiveJob;
class EncryptJob;
class DecryptJob;
class SignArchiveJob;
class SignJob;
class SignKeyJob;
class VerifyDetachedJob;
@ -189,6 +191,9 @@ public:
* OpenPGP key.
*/
virtual SetPrimaryUserIDJob *setPrimaryUserIDJob() const = 0;
virtual EncryptArchiveJob *encryptArchiveJob(bool armor = false) const = 0;
virtual SignArchiveJob *signArchiveJob(bool armor = false) const = 0;
};
/** Obtain a reference to the OpenPGP Protocol.

View File

@ -46,7 +46,9 @@
#include "qgpgmedeletejob.h"
#include "qgpgmedownloadjob.h"
#include "qgpgmesignencryptjob.h"
#include "qgpgmeencryptarchivejob.h"
#include "qgpgmeencryptjob.h"
#include "qgpgmesignarchivejob.h"
#include "qgpgmesignjob.h"
#include "qgpgmesignkeyjob.h"
#include "qgpgmeexportjob.h"
@ -506,6 +508,30 @@ public:
}
return new QGpgME::QGpgMESetPrimaryUserIDJob{context};
}
QGpgME::EncryptArchiveJob *encryptArchiveJob(bool armor) const override
{
if (mProtocol != GpgME::OpenPGP) {
return nullptr;
}
if (auto context = GpgME::Context::createForProtocol(mProtocol)) {
context->setArmor(armor);
return new QGpgME::QGpgMEEncryptArchiveJob{context};
}
return nullptr;
}
QGpgME::SignArchiveJob *signArchiveJob(bool armor) const override
{
if (mProtocol != GpgME::OpenPGP) {
return nullptr;
}
if (auto context = GpgME::Context::createForProtocol(mProtocol)) {
context->setArmor(armor);
return new QGpgME::QGpgMESignArchiveJob{context};
}
return nullptr;
}
};
}

View File

@ -0,0 +1,152 @@
/*
qgpgmeencryptarchivejob.cpp
This file is part of qgpgme, the Qt API binding for gpgme
Copyright (c) 2004,2007,2008 Klarälvdalens Datakonsult AB
Copyright (c) 2016 by Bundesamt für Sicherheit in der Informationstechnik
Software engineering by Intevation GmbH
Copyright (c) 2022,2023 g10 Code GmbH
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME 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.
QGpgME 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
General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
In addition, as a special exception, the copyright holders give
permission to link the code of this program with any edition of
the Qt library by Trolltech AS, Norway (or with modified versions
of Qt that use the same license as Qt), and distribute linked
combinations including the two. You must obey the GNU General
Public License in all respects for all of the code used other than
Qt. If you modify this file, you may extend this exception to
your version of the file, but you are not obligated to do so. If
you do not wish to do so, delete this exception statement from
your version.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "qgpgmeencryptarchivejob.h"
#include "dataprovider.h"
#include "encryptarchivejob_p.h"
#include "filelistdataprovider.h"
// #include <context.h>
#include <data.h>
// #include <encryptionresult.h>
//
// #include <QBuffer>
// #include <QFileInfo>
//
// #include <cassert>
using namespace QGpgME;
using namespace GpgME;
namespace
{
class QGpgMEEncryptArchiveJobPrivate : public EncryptArchiveJobPrivate
{
QGpgMEEncryptArchiveJob *q = nullptr;
public:
QGpgMEEncryptArchiveJobPrivate(QGpgMEEncryptArchiveJob *qq)
: q{qq}
{
}
~QGpgMEEncryptArchiveJobPrivate() override = default;
private:
void start() override
{
q->run();
}
};
}
QGpgMEEncryptArchiveJob::QGpgMEEncryptArchiveJob(Context *context)
: mixin_type{context}
{
setJobPrivate(this, std::unique_ptr<QGpgMEEncryptArchiveJobPrivate>{new QGpgMEEncryptArchiveJobPrivate{this}});
lateInitialization();
}
static QGpgMEEncryptArchiveJob::result_type encrypt(Context *ctx,
QThread *thread,
const std::vector<Key> &recipients,
const std::vector<QString> &paths,
const std::weak_ptr<QIODevice> &cipherText_,
Context::EncryptionFlags flags,
const QString &baseDirectory)
{
const std::shared_ptr<QIODevice> cipherText = cipherText_.lock();
const _detail::ToThreadMover ctMover(cipherText, thread);
QGpgME::FileListDataProvider in{paths};
Data indata(&in);
if (!baseDirectory.isEmpty()) {
indata.setFileName(baseDirectory.toStdString());
}
QGpgME::QIODeviceDataProvider out{cipherText};
Data outdata(&out);
flags = static_cast<Context::EncryptionFlags>(flags | Context::EncryptArchive);
const EncryptionResult res = ctx->encrypt(recipients, indata, outdata, flags);
Error ae;
const QString log = _detail::audit_log_as_html(ctx, ae);
return std::make_tuple(res, log, ae);
}
GpgME::Error QGpgMEEncryptArchiveJob::start(const std::vector<GpgME::Key> &recipients,
const std::vector<QString> &paths,
const std::shared_ptr<QIODevice> &cipherText,
const GpgME::Context::EncryptionFlags flags)
{
if (!cipherText) {
return Error::fromCode(GPG_ERR_INV_VALUE);
}
run(std::bind(&encrypt,
std::placeholders::_1,
std::placeholders::_2,
recipients,
paths,
std::placeholders::_3,
flags,
baseDirectory()),
cipherText);
return {};
}
// EncryptionResult QGpgMEEncryptArchiveJob::exec(const std::vector<Key> &recipients, const QByteArray &plainText,
// const Context::EncryptionFlags eflags, QByteArray &cipherText)
// {
// const result_type r = encrypt_qba(context(), recipients, plainText, eflags, mOutputIsBase64Encoded, fileName());
// cipherText = std::get<1>(r);
// resultHook(r);
// return mResult;
// }
void QGpgMEEncryptArchiveJob::resultHook(const result_type &tuple)
{
mResult = std::get<0>(tuple);
}
#include "qgpgmeencryptarchivejob.moc"

View File

@ -0,0 +1,82 @@
/*
qgpgmeencryptarchivejob.h
This file is part of qgpgme, the Qt API binding for gpgme
Copyright (c) 2023 g10 Code GmbH
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME 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.
QGpgME 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
In addition, as a special exception, the copyright holders give
permission to link the code of this program with any edition of
the Qt library by Trolltech AS, Norway (or with modified versions
of Qt that use the same license as Qt), and distribute linked
combinations including the two. You must obey the GNU General
Public License in all respects for all of the code used other than
Qt. If you modify this file, you may extend this exception to
your version of the file, but you are not obligated to do so. If
you do not wish to do so, delete this exception statement from
your version.
*/
#ifndef __QGPGME_QGPGMEENCRYPTARCHIVEJOB_H__
#define __QGPGME_QGPGMEENCRYPTARCHIVEJOB_H__
#include "encryptarchivejob.h"
#include "threadedjobmixin.h"
#include <encryptionresult.h>
#include <key.h>
namespace QGpgME
{
class QGpgMEEncryptArchiveJob
#ifdef Q_MOC_RUN
: public EncryptArchiveJob
#else
: public _detail::ThreadedJobMixin<EncryptArchiveJob, std::tuple<GpgME::EncryptionResult, QString, GpgME::Error>>
#endif
{
Q_OBJECT
#ifdef Q_MOC_RUN
public Q_SLOTS:
void slotFinished();
#endif
public:
explicit QGpgMEEncryptArchiveJob(GpgME::Context *context);
~QGpgMEEncryptArchiveJob() = default;
GpgME::Error start(const std::vector<GpgME::Key> &recipients,
const std::vector<QString> &paths,
const std::shared_ptr<QIODevice> &cipherText,
const GpgME::Context::EncryptionFlags flags) override;
// GpgME::EncryptionResult exec(const std::vector<GpgME::Key> &recipients,
// const std::vector<QString> &paths,
// const std::shared_ptr<QIODevice> &cipherText,
// const GpgME::Context::EncryptionFlags flags) override;
/* from ThreadedJobMixin */
void resultHook(const result_type &r) override;
private:
GpgME::EncryptionResult mResult;
};
}
#endif // __QGPGME_QGPGMEENCRYPTARCHIVEJOB_H__

View File

@ -0,0 +1,141 @@
/*
qgpgmesignarchivejob.cpp
This file is part of qgpgme, the Qt API binding for gpgme
Copyright (c) 2004,2007,2008 Klarälvdalens Datakonsult AB
Copyright (c) 2016 by Bundesamt für Sicherheit in der Informationstechnik
Software engineering by Intevation GmbH
Copyright (c) 2022,2023 g10 Code GmbH
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME 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.
QGpgME 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
General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
In addition, as a special exception, the copyright holders give
permission to link the code of this program with any edition of
the Qt library by Trolltech AS, Norway (or with modified versions
of Qt that use the same license as Qt), and distribute linked
combinations including the two. You must obey the GNU General
Public License in all respects for all of the code used other than
Qt. If you modify this file, you may extend this exception to
your version of the file, but you are not obligated to do so. If
you do not wish to do so, delete this exception statement from
your version.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "qgpgmesignarchivejob.h"
#include "dataprovider.h"
#include "signarchivejob_p.h"
#include "filelistdataprovider.h"
#include <data.h>
using namespace QGpgME;
using namespace GpgME;
namespace
{
class QGpgMESignArchiveJobPrivate : public SignArchiveJobPrivate
{
QGpgMESignArchiveJob *q = nullptr;
public:
QGpgMESignArchiveJobPrivate(QGpgMESignArchiveJob *qq)
: q{qq}
{
}
~QGpgMESignArchiveJobPrivate() override = default;
private:
void start() override
{
q->run();
}
};
}
QGpgMESignArchiveJob::QGpgMESignArchiveJob(Context *context)
: mixin_type{context}
{
setJobPrivate(this, std::unique_ptr<QGpgMESignArchiveJobPrivate>{new QGpgMESignArchiveJobPrivate{this}});
lateInitialization();
}
static QGpgMESignArchiveJob::result_type sign(Context *ctx,
QThread *thread,
const std::vector<Key> &signers,
const std::vector<QString> &paths,
const std::weak_ptr<QIODevice> &output_,
const QString &baseDirectory)
{
const std::shared_ptr<QIODevice> output = output_.lock();
const _detail::ToThreadMover ctMover(output, thread);
QGpgME::FileListDataProvider in{paths};
Data indata(&in);
if (!baseDirectory.isEmpty()) {
indata.setFileName(baseDirectory.toStdString());
}
QGpgME::QIODeviceDataProvider out{output};
Data outdata(&out);
ctx->clearSigningKeys();
for (const Key &signer : signers) {
if (!signer.isNull()) {
if (const Error err = ctx->addSigningKey(signer)) {
return std::make_tuple(SigningResult{err}, QString{}, Error{});
}
}
}
const SigningResult res = ctx->sign(indata, outdata, GpgME::SignArchive);
Error ae;
const QString log = _detail::audit_log_as_html(ctx, ae);
return std::make_tuple(res, log, ae);
}
GpgME::Error QGpgMESignArchiveJob::start(const std::vector<GpgME::Key> &signers,
const std::vector<QString> &paths,
const std::shared_ptr<QIODevice> &output)
{
if (!output) {
return Error::fromCode(GPG_ERR_INV_VALUE);
}
run(std::bind(&sign,
std::placeholders::_1,
std::placeholders::_2,
signers,
paths,
std::placeholders::_3,
baseDirectory()),
output);
return {};
}
void QGpgMESignArchiveJob::resultHook(const result_type &tuple)
{
mResult = std::get<0>(tuple);
}
#include "qgpgmesignarchivejob.moc"

View File

@ -0,0 +1,76 @@
/*
qgpgmesignarchivejob.h
This file is part of qgpgme, the Qt API binding for gpgme
Copyright (c) 2023 g10 Code GmbH
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME 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.
QGpgME 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
In addition, as a special exception, the copyright holders give
permission to link the code of this program with any edition of
the Qt library by Trolltech AS, Norway (or with modified versions
of Qt that use the same license as Qt), and distribute linked
combinations including the two. You must obey the GNU General
Public License in all respects for all of the code used other than
Qt. If you modify this file, you may extend this exception to
your version of the file, but you are not obligated to do so. If
you do not wish to do so, delete this exception statement from
your version.
*/
#ifndef __QGPGME_QGPGMESIGNARCHIVEJOB_H__
#define __QGPGME_QGPGMESIGNARCHIVEJOB_H__
#include "signarchivejob.h"
#include "threadedjobmixin.h"
#include <signingresult.h>
#include <key.h>
namespace QGpgME
{
class QGpgMESignArchiveJob
#ifdef Q_MOC_RUN
: public SignArchiveJob
#else
: public _detail::ThreadedJobMixin<SignArchiveJob, std::tuple<GpgME::SigningResult, QString, GpgME::Error>>
#endif
{
Q_OBJECT
#ifdef Q_MOC_RUN
public Q_SLOTS:
void slotFinished();
#endif
public:
explicit QGpgMESignArchiveJob(GpgME::Context *context);
~QGpgMESignArchiveJob() = default;
GpgME::Error start(const std::vector<GpgME::Key> &signers,
const std::vector<QString> &paths,
const std::shared_ptr<QIODevice> &output) override;
/* from ThreadedJobMixin */
void resultHook(const result_type &r) override;
private:
GpgME::SigningResult mResult;
};
}
#endif // __QGPGME_QGPGMESIGNARCHIVEJOB_H__

View File

@ -0,0 +1,62 @@
/*
signarchivejob.cpp
This file is part of qgpgme, the Qt API binding for gpgme
Copyright (c) 2023 g10 Code GmbH
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME 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.
QGpgME 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
In addition, as a special exception, the copyright holders give
permission to link the code of this program with any edition of
the Qt library by Trolltech AS, Norway (or with modified versions
of Qt that use the same license as Qt), and distribute linked
combinations including the two. You must obey the GNU General
Public License in all respects for all of the code used other than
Qt. If you modify this file, you may extend this exception to
your version of the file, but you are not obligated to do so. If
you do not wish to do so, delete this exception statement from
your version.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "signarchivejob.h"
#include "signarchivejob_p.h"
using namespace QGpgME;
SignArchiveJob::SignArchiveJob(QObject *parent)
: Job{parent}
{
}
SignArchiveJob::~SignArchiveJob() = default;
void SignArchiveJob::setBaseDirectory(const QString &baseDirectory)
{
auto d = jobPrivate<SignArchiveJobPrivate>(this);
d->m_baseDirectory = baseDirectory;
}
QString SignArchiveJob::baseDirectory() const
{
auto d = jobPrivate<SignArchiveJobPrivate>(this);
return d->m_baseDirectory;
}
#include "signarchivejob.moc"

View File

@ -0,0 +1,88 @@
/*
signarchivejob.h
This file is part of qgpgme, the Qt API binding for gpgme
Copyright (c) 2023 g10 Code GmbH
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME 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.
QGpgME 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
In addition, as a special exception, the copyright holders give
permission to link the code of this program with any edition of
the Qt library by Trolltech AS, Norway (or with modified versions
of Qt that use the same license as Qt), and distribute linked
combinations including the two. You must obey the GNU General
Public License in all respects for all of the code used other than
Qt. If you modify this file, you may extend this exception to
your version of the file, but you are not obligated to do so. If
you do not wish to do so, delete this exception statement from
your version.
*/
#ifndef __QGPGME_SIGNARCHIVEJOB_H__
#define __QGPGME_SIGNARCHIVEJOB_H__
#include "job.h"
#ifdef BUILDING_QGPGME
# include "context.h"
#else
# include <gpgme++/context.h>
#endif
namespace GpgME
{
class Key;
}
namespace QGpgME
{
/**
* Abstract base class for job for creating signed archives
*/
class QGPGME_EXPORT SignArchiveJob : public Job
{
Q_OBJECT
protected:
explicit SignArchiveJob(QObject *parent);
public:
~SignArchiveJob() override;
void setBaseDirectory(const QString &baseDirectory);
QString baseDirectory() const;
/**
* Starts the creation of a signed archive.
*
* Creates a signed archive with the files and directories in \a paths.
* The archive is signed with the keys in \a signers or with the default
* key, if \a signers is empty. The signed archive is written to \a output.
*
* Emits result() when the job has finished.
*/
virtual GpgME::Error start(const std::vector<GpgME::Key> &signers,
const std::vector<QString> &paths,
const std::shared_ptr<QIODevice> &output) = 0;
Q_SIGNALS:
void result(const GpgME::SigningResult &result,
const QString &auditLogAsHtml = {},
const GpgME::Error &auditLogError = {});
};
}
#endif // __QGPGME_SIGNARCHIVEJOB_H__

View File

@ -0,0 +1,49 @@
/*
signarchivejob_p.h
This file is part of qgpgme, the Qt API binding for gpgme
Copyright (c) 2023 g10 Code GmbH
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME 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.
QGpgME 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
In addition, as a special exception, the copyright holders give
permission to link the code of this program with any edition of
the Qt library by Trolltech AS, Norway (or with modified versions
of Qt that use the same license as Qt), and distribute linked
combinations including the two. You must obey the GNU General
Public License in all respects for all of the code used other than
Qt. If you modify this file, you may extend this exception to
your version of the file, but you are not obligated to do so. If
you do not wish to do so, delete this exception statement from
your version.
*/
#ifndef __QGPGME_SIGNARCHIVEJOB_P_H__
#define __QGPGME_SIGNARCHIVEJOB_P_H__
#include "job_p.h"
namespace QGpgME
{
struct SignArchiveJobPrivate : public JobPrivate
{
QString m_baseDirectory;
};
}
#endif // __QGPGME_SIGNARCHIVEJOB_P_H__

View File

@ -86,11 +86,13 @@ t_wkdlookup_SOURCES = t-wkdlookup.cpp $(support_src)
t_import_SOURCES = t-import.cpp $(support_src)
t_revokekey_SOURCES = t-revokekey.cpp $(support_src)
t_setprimaryuserid_SOURCES = t-setprimaryuserid.cpp $(support_src)
run_encryptarchivejob_SOURCES = run-encryptarchivejob.cpp
run_exportjob_SOURCES = run-exportjob.cpp
run_importjob_SOURCES = run-importjob.cpp
run_keyformailboxjob_SOURCES = run-keyformailboxjob.cpp
run_receivekeysjob_SOURCES = run-receivekeysjob.cpp
run_refreshkeysjob_SOURCES = run-refreshkeysjob.cpp
run_signarchivejob_SOURCES = run-signarchivejob.cpp
nodist_t_keylist_SOURCES = $(moc_files)
@ -102,7 +104,10 @@ noinst_PROGRAMS = \
run-keyformailboxjob t-wkspublish t-verify t-various t-config t-remarks \
t-trustsignatures t-changeexpiryjob t-wkdlookup t-import t-revokekey \
t-setprimaryuserid \
run-importjob run-exportjob run-receivekeysjob run-refreshkeysjob
run-encryptarchivejob \
run-importjob run-exportjob run-receivekeysjob run-refreshkeysjob \
run-signarchivejob
CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \
gpg-agent.conf pubring.kbx~ S.gpg-agent gpg.conf pubring.gpg~ \

View File

@ -0,0 +1,158 @@
/*
run-encryptarchivejob.cpp
This file is part of QGpgME's test suite.
Copyright (c) 2023 by g10 Code GmbH
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License,
version 2, as published by the Free Software Foundation.
QGpgME 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
In addition, as a special exception, the copyright holders give
permission to link the code of this program with any edition of
the Qt library by Trolltech AS, Norway (or with modified versions
of Qt that use the same license as Qt), and distribute linked
combinations including the two. You must obey the GNU General
Public License in all respects for all of the code used other than
Qt. If you modify this file, you may extend this exception to
your version of the file, but you are not obligated to do so. If
you do not wish to do so, delete this exception statement from
your version.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <protocol.h>
#include <encryptarchivejob.h>
#include <QCommandLineParser>
#include <QCoreApplication>
#include <QDebug>
#include <QFile>
#include <context.h>
#include <encryptionresult.h>
#include <algorithm>
#include <iostream>
using namespace GpgME;
std::ostream &operator<<(std::ostream &os, const QString &s)
{
return os << s.toLocal8Bit().constData();
}
const char *displayName(Protocol protocol)
{
switch (protocol) {
case GpgME::OpenPGP:
return "OpenPGP";
case GpgME::CMS:
return "S/MIME";
default:
return "Unknown protocol";
}
}
struct CommandLineOptions {
bool armor;
QString archiveName;
QString baseDirectory;
std::vector<QString> filesAndDirectories;
};
CommandLineOptions parseCommandLine(const QStringList &arguments)
{
CommandLineOptions options;
QCommandLineParser parser;
parser.setApplicationDescription("Test program for EncryptArchiveJob");
parser.addHelpOption();
parser.addOptions({
{{"o", "output"}, "Write output to FILE.", "FILE"},
{{"a", "armor"}, "Create ASCII armored output."},
{{"C", "directory"}, "Change to DIRECTORY before creating the archive.", "DIRECTORY"},
});
parser.addPositionalArgument("files", "Files and directories to add to the archive", "[files] [directories]");
parser.process(arguments);
const auto args = parser.positionalArguments();
if (args.empty()) {
parser.showHelp(1);
}
options.armor = parser.isSet("armor");
options.archiveName = parser.value("output");
options.baseDirectory = parser.value("directory");
std::copy(args.begin(), args.end(), std::back_inserter(options.filesAndDirectories));
return options;
}
std::shared_ptr<QIODevice> createOutput(const QString &fileName)
{
std::shared_ptr<QFile> output;
if (fileName.isEmpty()) {
output.reset(new QFile);
output->open(stdout, QIODevice::WriteOnly);
} else {
if (QFile::exists(fileName)) {
qCritical() << "File" << fileName << "exists. Bailing out.";
} else {
output.reset(new QFile{fileName});
output->open(QIODevice::WriteOnly);
}
}
return output;
}
int main(int argc, char **argv)
{
GpgME::initializeLibrary();
QCoreApplication app{argc, argv};
app.setApplicationName("run-encryptarchivejob");
const auto options = parseCommandLine(app.arguments());
auto output = createOutput(options.archiveName);
if (!output) {
return 1;
}
auto job = QGpgME::openpgp()->encryptArchiveJob(options.armor);
if (!job) {
std::cerr << "Error: Could not create job" << std::endl;
return 1;
}
job->setBaseDirectory(options.baseDirectory);
QObject::connect(job, &QGpgME::EncryptArchiveJob::result, &app, [](const GpgME::EncryptionResult &result, const QString &auditLog, const GpgME::Error &) {
std::cerr << "Diagnostics: " << auditLog << std::endl;
std::cerr << "Result: " << result << std::endl;
qApp->quit();
});
const auto err = job->start({}, options.filesAndDirectories, output, GpgME::Context::None);
if (err) {
std::cerr << "Error: Starting the job failed: " << err.asString() << std::endl;
return 1;
}
return app.exec();
}

View File

@ -0,0 +1,145 @@
/*
run-signarchivejob.cpp
This file is part of QGpgME's test suite.
Copyright (c) 2023 by g10 Code GmbH
Software engineering by Ingo Klöcker <dev@ingo-kloecker.de>
QGpgME is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License,
version 2, as published by the Free Software Foundation.
QGpgME 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
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
In addition, as a special exception, the copyright holders give
permission to link the code of this program with any edition of
the Qt library by Trolltech AS, Norway (or with modified versions
of Qt that use the same license as Qt), and distribute linked
combinations including the two. You must obey the GNU General
Public License in all respects for all of the code used other than
Qt. If you modify this file, you may extend this exception to
your version of the file, but you are not obligated to do so. If
you do not wish to do so, delete this exception statement from
your version.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <protocol.h>
#include <signarchivejob.h>
#include <QCommandLineParser>
#include <QCoreApplication>
#include <QDebug>
#include <QFile>
#include <context.h>
#include <signingresult.h>
#include <iostream>
using namespace GpgME;
std::ostream &operator<<(std::ostream &os, const QString &s)
{
return os << s.toLocal8Bit().constData();
}
struct CommandLineOptions {
bool armor;
QString archiveName;
QString baseDirectory;
std::vector<QString> filesAndDirectories;
};
CommandLineOptions parseCommandLine(const QStringList &arguments)
{
CommandLineOptions options;
QCommandLineParser parser;
parser.setApplicationDescription("Test program for SignArchiveJob");
parser.addHelpOption();
parser.addOptions({
{{"o", "output"}, "Write output to FILE.", "FILE"},
{{"a", "armor"}, "Create ASCII armored output."},
{{"C", "directory"}, "Change to DIRECTORY before creating the archive.", "DIRECTORY"},
});
parser.addPositionalArgument("files", "Files and directories to add to the archive", "[files] [directories]");
parser.process(arguments);
const auto args = parser.positionalArguments();
if (args.empty()) {
parser.showHelp(1);
}
options.armor = parser.isSet("armor");
options.archiveName = parser.value("output");
options.baseDirectory = parser.value("directory");
std::copy(args.begin(), args.end(), std::back_inserter(options.filesAndDirectories));
return options;
}
std::shared_ptr<QIODevice> createOutput(const QString &fileName)
{
std::shared_ptr<QFile> output;
if (fileName.isEmpty()) {
output.reset(new QFile);
output->open(stdout, QIODevice::WriteOnly);
} else {
if (QFile::exists(fileName)) {
qCritical() << "File" << fileName << "exists. Bailing out.";
} else {
output.reset(new QFile{fileName});
output->open(QIODevice::WriteOnly);
}
}
return output;
}
int main(int argc, char **argv)
{
GpgME::initializeLibrary();
QCoreApplication app{argc, argv};
app.setApplicationName("run-signarchivejob");
const auto options = parseCommandLine(app.arguments());
auto output = createOutput(options.archiveName);
if (!output) {
return 1;
}
auto job = QGpgME::openpgp()->signArchiveJob(options.armor);
if (!job) {
std::cerr << "Error: Could not create job" << std::endl;
return 1;
}
job->setBaseDirectory(options.baseDirectory);
QObject::connect(job, &QGpgME::SignArchiveJob::result, &app, [](const GpgME::SigningResult &result, const QString &auditLog, const GpgME::Error &) {
std::cerr << "Diagnostics: " << auditLog << std::endl;
std::cerr << "Result: " << result << std::endl;
qApp->quit();
});
const auto err = job->start({}, options.filesAndDirectories, output);
if (err) {
std::cerr << "Error: Starting the job failed: " << err.asString() << std::endl;
return 1;
}
return app.exec();
}

View File

@ -59,6 +59,7 @@ enum
WANT_DIRMNGR_NAME,
WANT_PINENTRY_NAME,
WANT_GPG_WKS_CLIENT_NAME,
WANT_GPGTAR_NAME,
WANT_GPG_ONE_MODE
};
@ -88,6 +89,7 @@ static struct {
char *dirmngr_name;
char *pinentry_name;
char *gpg_wks_client_name;
char *gpgtar_name;
int gpg_one_mode; /* System is in gpg1 mode. */
} dirinfo;
@ -407,6 +409,14 @@ get_gpgconf_item (int what)
NULL);
result = dirinfo.gpg_wks_client_name;
break;
case WANT_GPGTAR_NAME:
if (!dirinfo.gpgtar_name && dirinfo.bindir)
dirinfo.gpgtar_name = _gpgme_strconcat (dirinfo.bindir,
"/",
"gpgtar",
NULL);
result = dirinfo.gpgtar_name;
break;
}
UNLOCK (dirinfo_lock);
return result;
@ -455,6 +465,13 @@ _gpgme_get_default_gpgconf_name (void)
return get_gpgconf_item (WANT_GPGCONF_NAME);
}
/* Return the default gpgtar file name. Returns NULL if not known. */
const char *
_gpgme_get_default_gpgtar_name (void)
{
return get_gpgconf_item (WANT_GPGTAR_NAME);
}
/* Return the default UI-server socket name. Returns NULL if not
known. */
const char *
@ -524,6 +541,8 @@ gpgme_get_dirinfo (const char *what)
return get_gpgconf_item (WANT_PINENTRY_NAME);
else if (!strcmp (what, "gpg-wks-client-name"))
return get_gpgconf_item (WANT_GPG_WKS_CLIENT_NAME);
else if (!strcmp (what, "gpgtar-name"))
return get_gpgconf_item (WANT_GPGTAR_NAME);
else if (!strcmp (what, "agent-ssh-socket"))
return get_gpgconf_item (WANT_AGENT_SSH_SOCKET);
else if (!strcmp (what, "dirmngr-socket"))

View File

@ -119,12 +119,12 @@ struct engine_ops
gpgme_key_t key,
gpgme_tofu_policy_t policy);
gpgme_error_t (*sign) (void *engine, gpgme_data_t in, gpgme_data_t out,
gpgme_sig_mode_t mode, int use_armor,
gpgme_sig_mode_t flags, int use_armor,
int use_textmode, int include_certs,
gpgme_ctx_t ctx /* FIXME */);
gpgme_error_t (*verify) (void *engine, gpgme_data_t sig,
gpgme_data_t signed_text, gpgme_data_t plaintext,
gpgme_ctx_t ctx);
gpgme_error_t (*verify) (void *engine, gpgme_verify_flags_t flags,
gpgme_data_t sig, gpgme_data_t signed_text,
gpgme_data_t plaintext, gpgme_ctx_t ctx);
gpgme_error_t (*getauditlog) (void *engine, gpgme_data_t output,
unsigned int flags);
gpgme_error_t (*setexpire) (void *engine, gpgme_key_t key,

File diff suppressed because it is too large Load Diff

View File

@ -1469,6 +1469,9 @@ gpgsm_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring,
if (!recp && !recpstring) /* Symmetric only */
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
if (flags & GPGME_ENCRYPT_ARCHIVE)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
if ((flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))
{
err = gpgsm_assuan_simple_command (gpgsm,
@ -2040,7 +2043,7 @@ gpgsm_keylist_ext (void *engine, const char *pattern[], int secret_only,
static gpgme_error_t
gpgsm_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
gpgme_sig_mode_t mode, int use_armor, int use_textmode,
gpgme_sig_mode_t flags, int use_armor, int use_textmode,
int include_certs, gpgme_ctx_t ctx /* FIXME */)
{
engine_gpgsm_t gpgsm = engine;
@ -2054,6 +2057,9 @@ gpgsm_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
if (!gpgsm)
return gpg_error (GPG_ERR_INV_VALUE);
if (flags & (GPGME_SIG_MODE_CLEAR | GPGME_SIG_MODE_ARCHIVE))
return gpg_error (GPG_ERR_INV_VALUE);
/* FIXME: This does not work as RESET does not reset it so we can't
revert back to default. */
if (include_certs != GPGME_INCLUDE_CERTS_DEFAULT)
@ -2102,15 +2108,16 @@ gpgsm_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
gpgsm_clear_fd (gpgsm, MESSAGE_FD);
gpgsm->inline_data = NULL;
err = start (gpgsm, mode == GPGME_SIG_MODE_DETACH
err = start (gpgsm, (flags & GPGME_SIG_MODE_DETACH)
? "SIGN --detached" : "SIGN");
return err;
}
static gpgme_error_t
gpgsm_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
gpgme_data_t plaintext, gpgme_ctx_t ctx)
gpgsm_verify (void *engine, gpgme_verify_flags_t flags, gpgme_data_t sig,
gpgme_data_t signed_text, gpgme_data_t plaintext,
gpgme_ctx_t ctx)
{
engine_gpgsm_t gpgsm = engine;
gpgme_error_t err;
@ -2120,6 +2127,9 @@ gpgsm_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
if (!gpgsm)
return gpg_error (GPG_ERR_INV_VALUE);
if (flags & GPGME_VERIFY_ARCHIVE)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
gpgsm->input_cb.data = sig;
err = gpgsm_set_fd (gpgsm, INPUT_FD, map_data_enc (gpgsm->input_cb.data));
if (err)

View File

@ -1145,6 +1145,9 @@ uiserver_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring,
else
return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
if (flags & GPGME_ENCRYPT_ARCHIVE)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
if (flags & GPGME_ENCRYPT_PREPARE)
{
if (!recp || plain || ciph)
@ -1211,7 +1214,7 @@ uiserver_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring,
static gpgme_error_t
uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
gpgme_sig_mode_t mode, int use_armor, int use_textmode,
gpgme_sig_mode_t flags, int use_armor, int use_textmode,
int include_certs, gpgme_ctx_t ctx /* FIXME */)
{
engine_uiserver_t uiserver = engine;
@ -1234,8 +1237,11 @@ uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
else
return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
if (flags & (GPGME_SIG_MODE_CLEAR | GPGME_SIG_MODE_ARCHIVE))
return gpg_error (GPG_ERR_INV_VALUE);
if (gpgrt_asprintf (&cmd, "SIGN%s%s", protocol,
(mode == GPGME_SIG_MODE_DETACH) ? " --detached" : "") < 0)
(flags & GPGME_SIG_MODE_DETACH) ? " --detached" : "") < 0)
return gpg_error_from_syserror ();
key = gpgme_signers_enum (ctx, 0);
@ -1291,8 +1297,9 @@ uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
/* FIXME: Missing a way to specify --silent. */
static gpgme_error_t
uiserver_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
gpgme_data_t plaintext, gpgme_ctx_t ctx)
uiserver_verify (void *engine, gpgme_verify_flags_t flags, gpgme_data_t sig,
gpgme_data_t signed_text, gpgme_data_t plaintext,
gpgme_ctx_t ctx)
{
engine_uiserver_t uiserver = engine;
gpgme_error_t err;
@ -1313,6 +1320,9 @@ uiserver_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
else
return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
if (flags & GPGME_VERIFY_ARCHIVE)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
if (gpgrt_asprintf (&cmd, "VERIFY%s", protocol) < 0)
return gpg_error_from_syserror ();

View File

@ -912,7 +912,7 @@ _gpgme_engine_op_keylist_data (engine_t engine, gpgme_keylist_mode_t mode,
gpgme_error_t
_gpgme_engine_op_sign (engine_t engine, gpgme_data_t in, gpgme_data_t out,
gpgme_sig_mode_t mode, int use_armor,
gpgme_sig_mode_t flags, int use_armor,
int use_textmode, int include_certs,
gpgme_ctx_t ctx /* FIXME */)
{
@ -922,7 +922,7 @@ _gpgme_engine_op_sign (engine_t engine, gpgme_data_t in, gpgme_data_t out,
if (!engine->ops->sign)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->sign) (engine->engine, in, out, mode, use_armor,
return (*engine->ops->sign) (engine->engine, in, out, flags, use_armor,
use_textmode, include_certs, ctx);
}
@ -940,9 +940,9 @@ _gpgme_engine_op_trustlist (engine_t engine, const char *pattern)
gpgme_error_t
_gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig,
gpgme_data_t signed_text, gpgme_data_t plaintext,
gpgme_ctx_t ctx)
_gpgme_engine_op_verify (engine_t engine, gpgme_verify_flags_t flags,
gpgme_data_t sig, gpgme_data_t signed_text,
gpgme_data_t plaintext, gpgme_ctx_t ctx)
{
if (!engine)
return gpg_error (GPG_ERR_INV_VALUE);
@ -950,8 +950,8 @@ _gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig,
if (!engine->ops->verify)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->verify) (engine->engine, sig, signed_text, plaintext,
ctx);
return (*engine->ops->verify) (engine->engine, flags, sig, signed_text,
plaintext, ctx);
}

View File

@ -160,13 +160,15 @@ gpgme_error_t _gpgme_engine_op_keylist_data (engine_t engine,
gpgme_keylist_mode_t mode,
gpgme_data_t data);
gpgme_error_t _gpgme_engine_op_sign (engine_t engine, gpgme_data_t in,
gpgme_data_t out, gpgme_sig_mode_t mode,
gpgme_data_t out, gpgme_sig_mode_t flags,
int use_armor, int use_textmode,
int include_certs,
gpgme_ctx_t ctx /* FIXME */);
gpgme_error_t _gpgme_engine_op_trustlist (engine_t engine,
const char *pattern);
gpgme_error_t _gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig,
gpgme_error_t _gpgme_engine_op_verify (engine_t engine,
gpgme_verify_flags_t flags,
gpgme_data_t sig,
gpgme_data_t signed_text,
gpgme_data_t plaintext,
gpgme_ctx_t ctx);

View File

@ -283,5 +283,7 @@ EXPORTS
gpgme_op_receive_keys @209
gpgme_op_receive_keys_start @210
gpgme_op_verify_ext @211
gpgme_op_verify_ext_start @212
; END

View File

@ -303,12 +303,13 @@ typedef enum
gpgme_hash_algo_t;
/* The available signature modes. */
/* The available signature mode flags. */
typedef enum
{
GPGME_SIG_MODE_NORMAL = 0,
GPGME_SIG_MODE_DETACH = 1,
GPGME_SIG_MODE_CLEAR = 2
GPGME_SIG_MODE_CLEAR = 2,
GPGME_SIG_MODE_ARCHIVE = 4
}
gpgme_sig_mode_t;
@ -1299,7 +1300,8 @@ typedef enum
GPGME_ENCRYPT_SYMMETRIC = 32,
GPGME_ENCRYPT_THROW_KEYIDS = 64,
GPGME_ENCRYPT_WRAP = 128,
GPGME_ENCRYPT_WANT_ADDRESS = 256
GPGME_ENCRYPT_WANT_ADDRESS = 256,
GPGME_ENCRYPT_ARCHIVE = 512
}
gpgme_encrypt_flags_t;
@ -1424,6 +1426,7 @@ gpgme_decrypt_result_t gpgme_op_decrypt_result (gpgme_ctx_t ctx);
typedef enum
{
GPGME_DECRYPT_VERIFY = 1,
GPGME_DECRYPT_ARCHIVE = 2,
GPGME_DECRYPT_UNWRAP = 128
}
gpgme_decrypt_flags_t;
@ -1519,10 +1522,10 @@ gpgme_sign_result_t gpgme_op_sign_result (gpgme_ctx_t ctx);
/* Sign the plaintext PLAIN and store the signature in SIG. */
gpgme_error_t gpgme_op_sign_start (gpgme_ctx_t ctx,
gpgme_data_t plain, gpgme_data_t sig,
gpgme_sig_mode_t mode);
gpgme_sig_mode_t flags);
gpgme_error_t gpgme_op_sign (gpgme_ctx_t ctx,
gpgme_data_t plain, gpgme_data_t sig,
gpgme_sig_mode_t mode);
gpgme_sig_mode_t flags);
/*
@ -1631,6 +1634,13 @@ typedef struct _gpgme_op_verify_result *gpgme_verify_result_t;
/* Retrieve a pointer to the result of the verify operation. */
gpgme_verify_result_t gpgme_op_verify_result (gpgme_ctx_t ctx);
/* The valid verify flags. */
typedef enum
{
GPGME_VERIFY_ARCHIVE = 1
}
gpgme_verify_flags_t;
/* Verify within CTX that SIG is a valid signature for TEXT. */
gpgme_error_t gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig,
gpgme_data_t signed_text,
@ -1638,6 +1648,16 @@ gpgme_error_t gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig,
gpgme_error_t gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig,
gpgme_data_t signed_text,
gpgme_data_t plaintext);
gpgme_error_t gpgme_op_verify_ext_start (gpgme_ctx_t ctx,
gpgme_verify_flags_t flags,
gpgme_data_t sig,
gpgme_data_t signed_text,
gpgme_data_t plaintext);
gpgme_error_t gpgme_op_verify_ext (gpgme_ctx_t ctx,
gpgme_verify_flags_t flags,
gpgme_data_t sig,
gpgme_data_t signed_text,
gpgme_data_t plaintext);
/*

View File

@ -282,6 +282,9 @@ GPGME_1.0 {
gpgme_op_receive_keys;
gpgme_op_receive_keys_start;
gpgme_op_verify_ext;
gpgme_op_verify_ext_start;
local:
*;

View File

@ -431,7 +431,7 @@ _gpgme_op_sign_init_result (gpgme_ctx_t ctx)
static gpgme_error_t
sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t plain,
gpgme_data_t sig, gpgme_sig_mode_t mode)
gpgme_data_t sig, gpgme_sig_mode_t flags)
{
gpgme_error_t err;
@ -446,8 +446,9 @@ sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t plain,
if (err)
return err;
if (mode != GPGME_SIG_MODE_NORMAL && mode != GPGME_SIG_MODE_DETACH
&& mode != GPGME_SIG_MODE_CLEAR)
if (flags & ~(GPGME_SIG_MODE_DETACH
|GPGME_SIG_MODE_CLEAR
|GPGME_SIG_MODE_ARCHIVE))
return gpg_error (GPG_ERR_INV_VALUE);
if (!plain)
@ -466,7 +467,7 @@ sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t plain,
_gpgme_engine_set_status_handler (ctx->engine, sign_status_handler,
ctx);
return _gpgme_engine_op_sign (ctx->engine, plain, sig, mode, ctx->use_armor,
return _gpgme_engine_op_sign (ctx->engine, plain, sig, flags, ctx->use_armor,
ctx->use_textmode, ctx->include_certs,
ctx /* FIXME */);
}
@ -475,16 +476,16 @@ sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t plain,
/* Sign the plaintext PLAIN and store the signature in SIG. */
gpgme_error_t
gpgme_op_sign_start (gpgme_ctx_t ctx, gpgme_data_t plain, gpgme_data_t sig,
gpgme_sig_mode_t mode)
gpgme_sig_mode_t flags)
{
gpg_error_t err;
TRACE_BEG (DEBUG_CTX, "gpgme_op_sign_start", ctx,
"plain=%p, sig=%p, mode=%i", plain, sig, mode);
"plain=%p, sig=%p, flags=%i", plain, sig, flags);
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
err = sign_start (ctx, 0, plain, sig, mode);
err = sign_start (ctx, 0, plain, sig, flags);
return TRACE_ERR (err);
}
@ -492,17 +493,17 @@ gpgme_op_sign_start (gpgme_ctx_t ctx, gpgme_data_t plain, gpgme_data_t sig,
/* Sign the plaintext PLAIN and store the signature in SIG. */
gpgme_error_t
gpgme_op_sign (gpgme_ctx_t ctx, gpgme_data_t plain, gpgme_data_t sig,
gpgme_sig_mode_t mode)
gpgme_sig_mode_t flags)
{
gpgme_error_t err;
TRACE_BEG (DEBUG_CTX, "gpgme_op_sign", ctx,
"plain=%p, sig=%p, mode=%i", plain, sig, mode);
"plain=%p, sig=%p, flags=%i", plain, sig, flags);
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
err = sign_start (ctx, 1, plain, sig, mode);
err = sign_start (ctx, 1, plain, sig, flags);
if (!err)
err = _gpgme_wait_one (ctx);
return TRACE_ERR (err);

View File

@ -56,6 +56,7 @@ const char *_gpgme_get_default_gpg_name (void);
const char *_gpgme_get_default_gpgsm_name (void);
const char *_gpgme_get_default_g13_name (void);
const char *_gpgme_get_default_gpgconf_name (void);
const char *_gpgme_get_default_gpgtar_name (void);
const char *_gpgme_get_default_uisrv_socket (void);
int _gpgme_in_gpg_one_mode (void);

View File

@ -1135,8 +1135,9 @@ _gpgme_op_verify_init_result (gpgme_ctx_t ctx)
static gpgme_error_t
verify_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t sig,
gpgme_data_t signed_text, gpgme_data_t plaintext)
verify_start (gpgme_ctx_t ctx, int synchronous, gpgme_verify_flags_t flags,
gpgme_data_t sig, gpgme_data_t signed_text,
gpgme_data_t plaintext)
{
gpgme_error_t err;
@ -1153,26 +1154,45 @@ verify_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t sig,
if (!sig)
return gpg_error (GPG_ERR_NO_DATA);
return _gpgme_engine_op_verify (ctx->engine, sig, signed_text, plaintext,
ctx);
return _gpgme_engine_op_verify (ctx->engine, flags, sig, signed_text,
plaintext, ctx);
}
/* Decrypt ciphertext CIPHER and make a signature verification within
CTX and store the resulting plaintext in PLAIN. */
/* Old version of gpgme_op_verify_ext_start without FLAGS. */
gpgme_error_t
gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig,
gpgme_data_t signed_text, gpgme_data_t plaintext)
{
return gpgme_op_verify_ext_start (ctx, 0, sig, signed_text, plaintext);
}
/* Old version of gpgme_op_verify_ext without FLAGS. */
gpgme_error_t
gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t signed_text,
gpgme_data_t plaintext)
{
return gpgme_op_verify_ext (ctx, 0, sig, signed_text, plaintext);
}
/* Decrypt ciphertext CIPHER and make a signature verification within
CTX and store the resulting plaintext in PLAIN. */
gpgme_error_t
gpgme_op_verify_ext_start (gpgme_ctx_t ctx, gpgme_verify_flags_t flags,
gpgme_data_t sig, gpgme_data_t signed_text,
gpgme_data_t plaintext)
{
gpg_error_t err;
TRACE_BEG (DEBUG_CTX, "gpgme_op_verify_start", ctx,
"sig=%p, signed_text=%p, plaintext=%p",
sig, signed_text, plaintext);
"flags=0x%x, sig=%p, signed_text=%p, plaintext=%p",
flags, sig, signed_text, plaintext);
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
err = verify_start (ctx, 0, sig, signed_text, plaintext);
err = verify_start (ctx, 0, flags, sig, signed_text, plaintext);
return TRACE_ERR (err);
}
@ -1180,19 +1200,20 @@ gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig,
/* Decrypt ciphertext CIPHER and make a signature verification within
CTX and store the resulting plaintext in PLAIN. */
gpgme_error_t
gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_data_t signed_text,
gpgme_op_verify_ext (gpgme_ctx_t ctx, gpgme_verify_flags_t flags,
gpgme_data_t sig, gpgme_data_t signed_text,
gpgme_data_t plaintext)
{
gpgme_error_t err;
TRACE_BEG (DEBUG_CTX, "gpgme_op_verify", ctx,
"sig=%p, signed_text=%p, plaintext=%p",
sig, signed_text, plaintext);
"flags=0x%x, sig=%p, signed_text=%p, plaintext=%p",
flags, sig, signed_text, plaintext);
if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE));
err = verify_start (ctx, 1, sig, signed_text, plaintext);
err = verify_start (ctx, 1, flags, sig, signed_text, plaintext);
if (!err)
err = _gpgme_wait_one (ctx);
return TRACE_ERR (err);

View File

@ -91,6 +91,8 @@ show_usage (int ex)
" --unwrap remove only the encryption layer\n"
" --large-buffers use large I/O buffer\n"
" --sensitive mark data objects as sensitive\n"
" --archive extract files from an encrypted archive\n"
" --directory DIR extract the files into the directory DIR\n"
" --diagnostics print diagnostics\n"
, stderr);
exit (ex);
@ -113,6 +115,7 @@ main (int argc, char **argv)
int export_session_key = 0;
const char *override_session_key = NULL;
const char *request_origin = NULL;
const char *directory = NULL;
int no_symkey_cache = 0;
int ignore_mdc_error = 0;
int raw_output = 0;
@ -205,6 +208,19 @@ main (int argc, char **argv)
raw_output = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--archive"))
{
flags |= GPGME_DECRYPT_ARCHIVE;
argc--; argv++;
}
else if (!strcmp (*argv, "--directory"))
{
argc--; argv++;
if (!argc)
show_usage (1);
directory = *argv;
argc--; argv++;
}
else if (!strncmp (*argv, "--", 2))
show_usage (1);
@ -302,6 +318,16 @@ main (int argc, char **argv)
gpgme_strerror (err));
exit (1);
}
if (directory && (flags & GPGME_DECRYPT_ARCHIVE))
{
err = gpgme_data_set_file_name (out, directory);
if (err)
{
fprintf (stderr, PGM ": error setting file name (out): %s\n",
gpgme_strerror (err));
exit (1);
}
}
if (large_buffers)
{
err = gpgme_data_set_flag (out, "io-buffer-size", "1000000");

View File

@ -77,10 +77,11 @@ progress_cb (void *opaque, const char *what, int type, int current, int total)
static void
print_result (gpgme_encrypt_result_t result)
print_encrypt_result (gpgme_encrypt_result_t result)
{
gpgme_invalid_key_t invkey;
printf ("\nEncryption results\n");
for (invkey = result->invalid_recipients; invkey; invkey = invkey->next)
printf ("Encryption key `%s' not used: %s <%s>\n",
nonnull (invkey->fpr),
@ -88,6 +89,30 @@ print_result (gpgme_encrypt_result_t result)
}
static void
print_sign_result (gpgme_sign_result_t result)
{
gpgme_invalid_key_t invkey;
gpgme_new_signature_t sig;
printf ("\nSigning results\n");
for (invkey = result->invalid_signers; invkey; invkey = invkey->next)
printf ("Signing key `%s' not used: %s <%s>\n",
nonnull (invkey->fpr),
gpg_strerror (invkey->reason), gpg_strsource (invkey->reason));
for (sig = result->signatures; sig; sig = sig->next)
{
printf ("Key fingerprint: %s\n", nonnull (sig->fpr));
printf ("Signature type : %d\n", sig->type);
printf ("Public key algo: %d\n", sig->pubkey_algo);
printf ("Hash algo .....: %d\n", sig->hash_algo);
printf ("Creation time .: %ld\n", sig->timestamp);
printf ("Sig class .....: 0x%u\n", sig->sig_class);
}
}
static int
show_usage (int ex)
@ -95,6 +120,7 @@ show_usage (int ex)
fputs ("usage: " PGM " [options] FILE\n\n"
"Options:\n"
" --verbose run in verbose mode\n"
" --sign sign data before encryption\n"
" --status print status lines from the backend\n"
" --progress print progress info\n"
" --openpgp use the OpenPGP protocol (default)\n"
@ -107,6 +133,9 @@ show_usage (int ex)
" --no-symkey-cache disable the use of that cache\n"
" --wrap assume input is valid OpenPGP message\n"
" --symmetric encrypt symmetric (OpenPGP only)\n"
" --archive encrypt given file or directory into an archive\n"
" --directory DIR switch to directory DIR before encrypting into an archive\n"
" --diagnostics print diagnostics\n"
, stderr);
exit (ex);
}
@ -120,7 +149,8 @@ main (int argc, char **argv)
gpgme_ctx_t ctx;
gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
gpgme_data_t in, out;
gpgme_encrypt_result_t result;
gpgme_encrypt_result_t encrypt_result;
gpgme_sign_result_t sign_result;
int print_status = 0;
int print_progress = 0;
int use_loopback = 0;
@ -128,10 +158,13 @@ main (int argc, char **argv)
gpgme_key_t keys[10+1];
int keycount = 0;
char *keystring = NULL;
const char *directory = NULL;
int i;
gpgme_encrypt_flags_t flags = GPGME_ENCRYPT_ALWAYS_TRUST;
gpgme_off_t offset;
int no_symkey_cache = 0;
int diagnostics = 0;
int sign = 0;
if (argc)
{ argc--; argv++; }
@ -154,6 +187,11 @@ main (int argc, char **argv)
verbose = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--sign"))
{
sign = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--status"))
{
print_status = 1;
@ -225,6 +263,24 @@ main (int argc, char **argv)
no_symkey_cache = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--archive"))
{
flags |= GPGME_ENCRYPT_ARCHIVE;
argc--; argv++;
}
else if (!strcmp (*argv, "--directory"))
{
argc--; argv++;
if (!argc)
show_usage (1);
directory = *argv;
argc--; argv++;
}
else if (!strcmp (*argv, "--diagnostics"))
{
diagnostics = 1;
argc--; argv++;
}
else if (!strncmp (*argv, "--", 2))
show_usage (1);
@ -269,6 +325,19 @@ main (int argc, char **argv)
}
keys[i] = NULL;
if (flags & GPGME_ENCRYPT_ARCHIVE)
{
const char *path = *argv;
err = gpgme_data_new_from_mem (&in, path, strlen (path), 0);
fail_if_err (err);
if (directory)
{
err = gpgme_data_set_file_name (in, directory);
fail_if_err (err);
}
}
else
{
err = gpgme_data_new_from_file (&in, *argv, 1);
if (err)
{
@ -311,15 +380,45 @@ main (int argc, char **argv)
exit (1);
}
}
}
err = gpgme_data_new (&out);
fail_if_err (err);
if (sign)
err = gpgme_op_encrypt_sign_ext (ctx, keycount ? keys : NULL, keystring,
flags, in, out);
else
err = gpgme_op_encrypt_ext (ctx, keycount ? keys : NULL, keystring,
flags, in, out);
result = gpgme_op_encrypt_result (ctx);
if (result)
print_result (result);
if (diagnostics)
{
gpgme_data_t diag;
gpgme_error_t diag_err;
gpgme_data_new (&diag);
diag_err = gpgme_op_getauditlog (ctx, diag, GPGME_AUDITLOG_DIAG);
if (diag_err)
{
fprintf (stderr, PGM ": getting diagnostics failed: %s\n",
gpgme_strerror (diag_err));
}
else
{
fputs ("Begin Diagnostics:\n", stdout);
print_data (diag);
fputs ("End Diagnostics.\n", stdout);
}
gpgme_data_release (diag);
}
sign_result = gpgme_op_sign_result (ctx);
if (sign_result)
print_sign_result (sign_result);
encrypt_result = gpgme_op_encrypt_result (ctx);
if (encrypt_result)
print_encrypt_result (encrypt_result);
if (err)
{
fprintf (stderr, PGM ": encrypting failed: %s\n", gpg_strerror (err));

View File

@ -87,6 +87,9 @@ show_usage (int ex)
" --sender MBOX use MBOX as sender address\n"
" --include-key-block use this option with gpg\n"
" --clear create a clear text signature\n"
" --archive create a signed archive with the given file or directory\n"
" --directory DIR switch to directory DIR before creating the archive\n"
" --diagnostics print diagnostics\n"
, stderr);
exit (ex);
}
@ -99,6 +102,7 @@ main (int argc, char **argv)
gpgme_error_t err;
gpgme_ctx_t ctx;
const char *key_string = NULL;
const char *directory = NULL;
gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
gpgme_sig_mode_t sigmode = GPGME_SIG_MODE_NORMAL;
gpgme_data_t in, out;
@ -106,6 +110,7 @@ main (int argc, char **argv)
int print_status = 0;
int use_loopback = 0;
int include_key_block = 0;
int diagnostics = 0;
const char *sender = NULL;
const char *s;
@ -178,6 +183,24 @@ main (int argc, char **argv)
sigmode = GPGME_SIG_MODE_CLEAR;
argc--; argv++;
}
else if (!strcmp (*argv, "--archive"))
{
sigmode = GPGME_SIG_MODE_ARCHIVE;
argc--; argv++;
}
else if (!strcmp (*argv, "--directory"))
{
argc--; argv++;
if (!argc)
show_usage (1);
directory = *argv;
argc--; argv++;
}
else if (!strcmp (*argv, "--diagnostics"))
{
diagnostics = 1;
argc--; argv++;
}
else if (!strncmp (*argv, "--", 2))
show_usage (1);
@ -236,6 +259,19 @@ main (int argc, char **argv)
}
}
if (sigmode == GPGME_SIG_MODE_ARCHIVE)
{
const char *path = *argv;
err = gpgme_data_new_from_mem (&in, path, strlen (path), 0);
fail_if_err (err);
if (directory)
{
err = gpgme_data_set_file_name (in, directory);
fail_if_err (err);
}
}
else
{
err = gpgme_data_new_from_file (&in, *argv, 1);
if (err)
{
@ -243,12 +279,35 @@ main (int argc, char **argv)
*argv, gpg_strerror (err));
exit (1);
}
}
err = gpgme_data_new (&out);
fail_if_err (err);
err = gpgme_op_sign (ctx, in, out, sigmode);
result = gpgme_op_sign_result (ctx);
if (diagnostics)
{
gpgme_data_t diag;
gpgme_error_t diag_err;
gpgme_data_new (&diag);
diag_err = gpgme_op_getauditlog (ctx, diag, GPGME_AUDITLOG_DIAG);
if (diag_err)
{
fprintf (stderr, PGM ": getting diagnostics failed: %s\n",
gpgme_strerror (diag_err));
}
else
{
fputs ("Begin Diagnostics:\n", stdout);
print_data (diag);
fputs ("End Diagnostics.\n", stdout);
}
gpgme_data_release (diag);
}
if (result)
print_result (result, sigmode);
if (err)

View File

@ -235,6 +235,9 @@ show_usage (int ex)
" --repeat N repeat the operation N times\n"
" --auto-key-retrieve\n"
" --auto-key-import\n"
" --archive extract files from a signed archive FILE\n"
" --directory DIR extract the files into the directory DIR\n"
" --diagnostics print diagnostics\n"
, stderr);
exit (ex);
}
@ -246,10 +249,13 @@ main (int argc, char **argv)
int last_argc = -1;
const char *s;
gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
gpgme_verify_flags_t flags = 0;
int print_status = 0;
const char *sender = NULL;
const char *directory = NULL;
int auto_key_retrieve = 0;
int auto_key_import = 0;
int diagnostics = 0;
int repeats = 1;
int i;
@ -312,12 +318,30 @@ main (int argc, char **argv)
auto_key_import = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--archive"))
{
flags |= GPGME_VERIFY_ARCHIVE;
argc--; argv++;
}
else if (!strcmp (*argv, "--directory"))
{
argc--; argv++;
if (!argc)
show_usage (1);
directory = *argv;
argc--; argv++;
}
else if (!strcmp (*argv, "--diagnostics"))
{
diagnostics = 1;
argc--; argv++;
}
else if (!strncmp (*argv, "--", 2))
show_usage (1);
}
if (argc < 1 || argc > 2)
if (argc < 1 || argc > 2 || (argc > 1 && (flags & GPGME_VERIFY_ARCHIVE)))
show_usage (1);
init_gpgme (protocol);
@ -330,6 +354,7 @@ main (int argc, char **argv)
gpgme_data_t sig = NULL;
FILE *fp_msg = NULL;
gpgme_data_t msg = NULL;
gpgme_data_t out = NULL;
gpgme_verify_result_t result;
if (repeats > 1)
@ -415,8 +440,48 @@ main (int argc, char **argv)
}
}
err = gpgme_op_verify (ctx, sig, msg, NULL);
if (directory && (flags & GPGME_VERIFY_ARCHIVE))
{
err = gpgme_data_new (&out);
if (err)
{
fprintf (stderr, PGM ": error allocating data object: %s\n",
gpgme_strerror (err));
exit (1);
}
err = gpgme_data_set_file_name (out, directory);
if (err)
{
fprintf (stderr, PGM ": error setting file name (out): %s\n",
gpgme_strerror (err));
exit (1);
}
}
err = gpgme_op_verify_ext (ctx, flags, sig, msg, out);
result = gpgme_op_verify_result (ctx);
if (diagnostics)
{
gpgme_data_t diag;
gpgme_error_t diag_err;
gpgme_data_new (&diag);
diag_err = gpgme_op_getauditlog (ctx, diag, GPGME_AUDITLOG_DIAG);
if (diag_err)
{
fprintf (stderr, PGM ": getting diagnostics failed: %s\n",
gpgme_strerror (diag_err));
}
else
{
fputs ("Begin Diagnostics:\n", stdout);
print_data (diag);
fputs ("End Diagnostics.\n", stdout);
}
gpgme_data_release (diag);
}
if (result)
print_result (result);
if (err)
@ -425,6 +490,7 @@ main (int argc, char **argv)
exit (1);
}
gpgme_data_release (out);
gpgme_data_release (msg);
gpgme_data_release (sig);

View File

@ -133,6 +133,7 @@ main (int argc, char **argv )
"dirmngr-name",
"pinentry-name",
"gpg-wks-client-name",
"gpgtar-name",
NULL };
const char *s;
int i;