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 * 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: Handle error when trying to sign expired keys. [T6155]
* cpp: Support encryption flags ThrowKeyIds, EncryptWrap, and WantAddress. * 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: Allow deferred start of import jobs. [T6323]
* qt: Support creating encrypted archives. [T6342]
* Interface changes relative to the 1.18.0 release: * Interface changes relative to the 1.18.0 release:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gpgme_get_ctx_flag EXTENDED: New flag 'no-auto-check-trustdb'. gpgme_get_ctx_flag EXTENDED: New flag 'no-auto-check-trustdb'.
gpgme_set_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::Curve NEW.
cpp: GpgGenCardKeyInteractor::setCurve NEW. cpp: GpgGenCardKeyInteractor::setCurve NEW.
cpp: Context::WantAddress NEW. cpp: Context::WantAddress NEW.
cpp: Data::setFileName EXTENDED: New overload
qt: ListAllKeysJob::Option NEW. qt: ListAllKeysJob::Option NEW.
qt: ListAllKeysJob::Options NEW. qt: ListAllKeysJob::Options NEW.
qt: ListAllKeysJob::setOptions NEW. qt: ListAllKeysJob::setOptions NEW.
qt: ListAllKeysJob::options NEW. qt: ListAllKeysJob::options NEW.
qt: Job::startNow NEW. qt: Job::startNow NEW.
qt: ImportJob::startLater 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) 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 @item localedir
Return the name of the directory with GnuPG locale data. 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 @item agent-socket
Return the name of the socket to connect to the gpg-agent. 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 @item gpg-wks-client-name
Return the name of the Web Key Service tool. Return the name of the Web Key Service tool.
@item gpgtar-name
Return the name of the gpgtar program.
@end table @end table
@end deftypefun @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 output when encrypting or signing the data and will be returned to the
user when decrypting or verifying the output data. 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 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 @var{dh} is not a valid pointer and @code{GPG_ERR_ENOMEM} if not
enough memory is available. 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 the session key for decryption. The format of that session key is
specific to GnuPG and can be retrieved during a decrypt operation when specific to GnuPG and can be retrieved during a decrypt operation when
the context flag "export-session-key" is enabled. Please be aware that 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 using this feature with GnuPG < 2.1.16 or when decrypting an archive
many platforms via ps(1). will leak the session key on many platforms via ps(1).
@item "auto-key-retrieve" @item "auto-key-retrieve"
Setting the @var{value} to "1" asks the backend to automatically 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 @code{gpgme_op_decrypt} but has an additional argument
@var{flags}. If @var{flags} is 0 both function behave identically. @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 The value in @var{flags} is a bitwise-or combination of one or
multiple of the following bit values: 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 The @code{GPGME_DECRYPT_VERIFY} symbol specifies that this function
shall exactly act as @code{gpgme_op_decrypt_verify}. 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 @item GPGME_DECRYPT_UNWRAP
@since{1.8.0} @since{1.8.0}
@ -5800,6 +5825,61 @@ operation could be started successfully, @code{GPG_ERR_INV_VALUE} if
any data to verify. any data to verify.
@end deftypefun @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} @deftp {Data type} {gpgme_sig_notation_t}
This is a pointer to a structure used to store a part of the result of 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 a @code{gpgme_op_verify} operation. The structure contains the
@ -6232,6 +6312,14 @@ A detached signature is made.
@item GPGME_SIG_MODE_CLEAR @item GPGME_SIG_MODE_CLEAR
A clear text signature is made. The @acronym{ASCII} armor and text A clear text signature is made. The @acronym{ASCII} armor and text
mode settings of the context are ignored. 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 table
@end deftp @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 specified for @var{sig}), the text mode attributes set for the context
@var{ctx} and the requested signature mode @var{mode}. @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 After the operation completed successfully, the result can be
retrieved with @code{gpgme_op_sign_result}. 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 that is not set, by the encoding specified for @var{cipher}) and the
text mode attributes set for the context @var{ctx}. 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 @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 must keep references for all keys during the whole duration of the
call (but see @code{gpgme_op_encrypt_start} for the requirements with 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 of the extended encrypt functions. This feature is currently only
supported for the OpenPGP crypto engine. 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 @end table
If @code{GPG_ERR_UNUSABLE_PUBKEY} is returned, some recipients in 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; return result;
} }
static gpgme_sig_mode_t sigmode2sigmode(SignatureMode mode) static gpgme_sig_mode_t sigflags2sigflags(SignatureMode flags)
{ {
switch (mode) { unsigned int result = 0;
default: if (flags & SignatureMode::NormalSignatureMode) {
case NormalSignatureMode: return GPGME_SIG_MODE_NORMAL; result |= GPGME_SIG_MODE_NORMAL;
case Detached: return GPGME_SIG_MODE_DETACH;
case Clearsigned: return GPGME_SIG_MODE_CLEAR;
} }
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) 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; d->lastop = Private::Sign;
const Data::Private *const pdp = plainText.impl(); const Data::Private *const pdp = plainText.impl();
Data::Private *const sdp = signature.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)); return SigningResult(d->ctx, Error(d->lasterr));
} }
@ -1302,7 +1310,7 @@ Error Context::startSigning(const Data &plainText, Data &signature, SignatureMod
d->lastop = Private::Sign; d->lastop = Private::Sign;
const Data::Private *const pdp = plainText.impl(); const Data::Private *const pdp = plainText.impl();
Data::Private *const sdp = signature.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 SigningResult Context::signingResult() const
@ -1344,6 +1352,9 @@ static gpgme_encrypt_flags_t encryptflags2encryptflags(Context::EncryptionFlags
if (flags & Context::WantAddress) { if (flags & Context::WantAddress) {
result |= GPGME_ENCRYPT_WANT_ADDRESS; result |= GPGME_ENCRYPT_WANT_ADDRESS;
} }
if (flags & Context::EncryptArchive) {
result |= GPGME_ENCRYPT_ARCHIVE;
}
return static_cast<gpgme_encrypt_flags_t>(result); 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) std::ostream &operator<<(std::ostream &os, SignatureMode mode)
{ {
os << "GpgME::SignatureMode("; os << "GpgME::SignatureMode(";
switch (mode) { #define CHECK( x ) if ( !(mode & (x)) ) {} else do { os << #x " "; } while (0)
#define CHECK( x ) case x: os << #x; break
CHECK(NormalSignatureMode); CHECK(NormalSignatureMode);
CHECK(Detached); CHECK(Detached);
CHECK(Clearsigned); CHECK(Clearsigned);
CHECK(SignArchive);
#undef CHECK #undef CHECK
default:
os << "???" "(" << static_cast<int>(mode) << ')';
break;
}
return os << ')'; return os << ')';
} }
@ -1921,6 +1928,7 @@ std::ostream &operator<<(std::ostream &os, Context::EncryptionFlags flags)
CHECK(ThrowKeyIds); CHECK(ThrowKeyIds);
CHECK(EncryptWrap); CHECK(EncryptWrap);
CHECK(WantAddress); CHECK(WantAddress);
CHECK(EncryptArchive);
#undef CHECK #undef CHECK
return os << ')'; return os << ')';
} }

View File

@ -449,6 +449,7 @@ public:
ThrowKeyIds = 64, ThrowKeyIds = 64,
EncryptWrap = 128, EncryptWrap = 128,
WantAddress = 256, WantAddress = 256,
EncryptArchive = 512
}; };
EncryptionResult encrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags); EncryptionResult encrypt(const std::vector<Key> &recipients, const Data &plainText, Data &cipherText, EncryptionFlags flags);
GpgME::Error encryptSymmetrically(const Data &plainText, Data &cipherText); 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)); 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) ssize_t GpgME::Data::read(void *buffer, size_t length)
{ {
return gpgme_data_read(d->data, buffer, length); return gpgme_data_read(d->data, buffer, length);

View File

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

View File

@ -74,7 +74,12 @@ enum KeyListMode {
KeyListModeMask = 0x3ff KeyListModeMask = 0x3ff
}; };
enum SignatureMode { NormalSignatureMode, Detached, Clearsigned }; enum SignatureMode {
NormalSignatureMode = 0,
Detached = 1,
Clearsigned = 2,
SignArchive = 4,
};
enum class RevocationReason { enum class RevocationReason {
Unspecified = 0, Unspecified = 0,
@ -103,7 +108,7 @@ homedir, sysconfdir, bindir, libexecdir, libdir,
datadir, localedir, agent-socket, agent-ssh-socket, datadir, localedir, agent-socket, agent-ssh-socket,
dirmngr-socket, uiserver-socket, gpgconf-name, gpg-name, dirmngr-socket, uiserver-socket, gpgconf-name, gpg-name,
gpgsm-name, g13-name, keyboxd-name, agent-name, scdaemon-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. 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_NORMAL: return NormalSignatureMode;
case GPGME_SIG_MODE_DETACH: return Detached; case GPGME_SIG_MODE_DETACH: return Detached;
case GPGME_SIG_MODE_CLEAR: return Clearsigned; 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 = \ qgpgme_sources = \
dataprovider.cpp \ dataprovider.cpp \
debug.cpp \ debug.cpp \
encryptarchivejob.cpp \
filelistdataprovider.cpp \
job.cpp multideletejob.cpp qgpgmeadduseridjob.cpp \ job.cpp multideletejob.cpp qgpgmeadduseridjob.cpp \
qgpgmeaddexistingsubkeyjob.cpp \ qgpgmeaddexistingsubkeyjob.cpp \
qgpgmebackend.cpp qgpgmechangeexpiryjob.cpp qgpgmechangeownertrustjob.cpp \ qgpgmebackend.cpp qgpgmechangeexpiryjob.cpp qgpgmechangeownertrustjob.cpp \
qgpgmechangepasswdjob.cpp qgpgmedecryptjob.cpp \ qgpgmechangepasswdjob.cpp qgpgmedecryptjob.cpp \
qgpgmedecryptverifyjob.cpp qgpgmedeletejob.cpp qgpgmedownloadjob.cpp \ qgpgmedecryptverifyjob.cpp qgpgmedeletejob.cpp qgpgmedownloadjob.cpp \
qgpgmeencryptarchivejob.cpp \
qgpgmeencryptjob.cpp qgpgmeexportjob.cpp qgpgmeimportfromkeyserverjob.cpp \ qgpgmeencryptjob.cpp qgpgmeexportjob.cpp qgpgmeimportfromkeyserverjob.cpp \
qgpgmeimportjob.cpp qgpgmekeygenerationjob.cpp qgpgmekeylistjob.cpp \ qgpgmeimportjob.cpp qgpgmekeygenerationjob.cpp qgpgmekeylistjob.cpp \
listallkeysjob.cpp qgpgmelistallkeysjob.cpp qgpgmenewcryptoconfig.cpp \ listallkeysjob.cpp qgpgmelistallkeysjob.cpp qgpgmenewcryptoconfig.cpp \
@ -46,6 +49,7 @@ qgpgme_sources = \
qgpgmerefreshsmimekeysjob.cpp \ qgpgmerefreshsmimekeysjob.cpp \
qgpgmerevokekeyjob.cpp \ qgpgmerevokekeyjob.cpp \
qgpgmesetprimaryuseridjob.cpp \ qgpgmesetprimaryuseridjob.cpp \
qgpgmesignarchivejob.cpp \
qgpgmesignencryptjob.cpp \ qgpgmesignencryptjob.cpp \
qgpgmesignjob.cpp qgpgmesignkeyjob.cpp qgpgmeverifydetachedjob.cpp \ qgpgmesignjob.cpp qgpgmesignkeyjob.cpp qgpgmeverifydetachedjob.cpp \
qgpgmeverifyopaquejob.cpp qgpgmewkdlookupjob.cpp threadedjobmixin.cpp \ qgpgmeverifyopaquejob.cpp qgpgmewkdlookupjob.cpp threadedjobmixin.cpp \
@ -53,6 +57,7 @@ qgpgme_sources = \
qgpgmetofupolicyjob.cpp qgpgmequickjob.cpp \ qgpgmetofupolicyjob.cpp qgpgmequickjob.cpp \
defaultkeygenerationjob.cpp qgpgmewkspublishjob.cpp \ defaultkeygenerationjob.cpp qgpgmewkspublishjob.cpp \
qgpgmegpgcardjob.cpp changeexpiryjob.cpp encryptjob.cpp importjob.cpp \ qgpgmegpgcardjob.cpp changeexpiryjob.cpp encryptjob.cpp importjob.cpp \
signarchivejob.cpp \
signencryptjob.cpp \ signencryptjob.cpp \
dn.cpp cryptoconfig.cpp wkdlookupresult.cpp \ dn.cpp cryptoconfig.cpp wkdlookupresult.cpp \
util.cpp util.cpp
@ -70,8 +75,10 @@ qgpgme_headers= \
decryptjob.h \ decryptjob.h \
decryptverifyjob.h \ decryptverifyjob.h \
downloadjob.h \ downloadjob.h \
encryptarchivejob.h \
encryptjob.h \ encryptjob.h \
exportjob.h \ exportjob.h \
filelistdataprovider.h \
hierarchicalkeylistjob.h \ hierarchicalkeylistjob.h \
job.h \ job.h \
keyformailboxjob.h \ keyformailboxjob.h \
@ -84,6 +91,7 @@ qgpgme_headers= \
revokekeyjob.h \ revokekeyjob.h \
setprimaryuseridjob.h \ setprimaryuseridjob.h \
specialjob.h \ specialjob.h \
signarchivejob.h \
signjob.h \ signjob.h \
signkeyjob.h \ signkeyjob.h \
signencryptjob.h \ signencryptjob.h \
@ -118,8 +126,10 @@ camelcase_headers= \
DecryptVerifyJob \ DecryptVerifyJob \
DN \ DN \
DownloadJob \ DownloadJob \
EncryptArchiveJob \
EncryptJob \ EncryptJob \
ExportJob \ ExportJob \
FileListDataProvider \
HierarchicalKeyKistJob \ HierarchicalKeyKistJob \
Job \ Job \
MultiDeleteJob \ MultiDeleteJob \
@ -130,6 +140,7 @@ camelcase_headers= \
RevokeKeyJob \ RevokeKeyJob \
SetPrimaryUserIDJob \ SetPrimaryUserIDJob \
SpecialJob \ SpecialJob \
SignArchiveJob \
SignJob \ SignJob \
SignKeyJob \ SignKeyJob \
SignEncryptJob \ SignEncryptJob \
@ -153,6 +164,7 @@ camelcase_headers= \
private_qgpgme_headers = \ private_qgpgme_headers = \
changeexpiryjob_p.h \ changeexpiryjob_p.h \
encryptarchivejob_p.h \
encryptjob_p.h \ encryptjob_p.h \
importjob_p.h \ importjob_p.h \
listallkeysjob_p.h \ listallkeysjob_p.h \
@ -169,6 +181,7 @@ private_qgpgme_headers = \
qgpgmedecryptverifyjob.h \ qgpgmedecryptverifyjob.h \
qgpgmedeletejob.h \ qgpgmedeletejob.h \
qgpgmedownloadjob.h \ qgpgmedownloadjob.h \
qgpgmeencryptarchivejob.h \
qgpgmeencryptjob.h \ qgpgmeencryptjob.h \
qgpgmeexportjob.h \ qgpgmeexportjob.h \
qgpgmeimportfromkeyserverjob.h \ qgpgmeimportfromkeyserverjob.h \
@ -180,6 +193,7 @@ private_qgpgme_headers = \
qgpgmerefreshsmimekeysjob.h \ qgpgmerefreshsmimekeysjob.h \
qgpgmerevokekeyjob.h \ qgpgmerevokekeyjob.h \
qgpgmesetprimaryuseridjob.h \ qgpgmesetprimaryuseridjob.h \
qgpgmesignarchivejob.h \
qgpgmesignencryptjob.h \ qgpgmesignencryptjob.h \
qgpgmesignjob.h \ qgpgmesignjob.h \
qgpgmesignkeyjob.h \ qgpgmesignkeyjob.h \
@ -191,6 +205,7 @@ private_qgpgme_headers = \
qgpgmetofupolicyjob.h \ qgpgmetofupolicyjob.h \
qgpgmegpgcardjob.h \ qgpgmegpgcardjob.h \
qgpgmequickjob.h \ qgpgmequickjob.h \
signarchivejob_p.h \
signencryptjob_p.h \ signencryptjob_p.h \
threadedjobmixin.h \ threadedjobmixin.h \
util.h util.h
@ -206,6 +221,7 @@ qgpgme_moc_sources = \
decryptverifyjob.moc \ decryptverifyjob.moc \
deletejob.moc \ deletejob.moc \
downloadjob.moc \ downloadjob.moc \
encryptarchivejob.moc \
encryptjob.moc \ encryptjob.moc \
exportjob.moc \ exportjob.moc \
hierarchicalkeylistjob.moc \ hierarchicalkeylistjob.moc \
@ -225,6 +241,7 @@ qgpgme_moc_sources = \
qgpgmedecryptverifyjob.moc \ qgpgmedecryptverifyjob.moc \
qgpgmedeletejob.moc \ qgpgmedeletejob.moc \
qgpgmedownloadjob.moc \ qgpgmedownloadjob.moc \
qgpgmeencryptarchivejob.moc \
qgpgmeencryptjob.moc \ qgpgmeencryptjob.moc \
qgpgmeexportjob.moc \ qgpgmeexportjob.moc \
qgpgmeimportfromkeyserverjob.moc \ qgpgmeimportfromkeyserverjob.moc \
@ -236,6 +253,7 @@ qgpgme_moc_sources = \
qgpgmerefreshsmimekeysjob.moc \ qgpgmerefreshsmimekeysjob.moc \
qgpgmerevokekeyjob.moc \ qgpgmerevokekeyjob.moc \
qgpgmesetprimaryuseridjob.moc \ qgpgmesetprimaryuseridjob.moc \
qgpgmesignarchivejob.moc \
qgpgmesignencryptjob.moc \ qgpgmesignencryptjob.moc \
qgpgmesignjob.moc \ qgpgmesignjob.moc \
qgpgmesignkeyjob.moc \ qgpgmesignkeyjob.moc \
@ -249,6 +267,7 @@ qgpgme_moc_sources = \
refreshkeysjob.moc \ refreshkeysjob.moc \
revokekeyjob.moc \ revokekeyjob.moc \
setprimaryuseridjob.moc \ setprimaryuseridjob.moc \
signarchivejob.moc \
signencryptjob.moc \ signencryptjob.moc \
signjob.moc \ signjob.moc \
signkeyjob.moc \ signkeyjob.moc \

View File

@ -25,7 +25,13 @@
#define __QGPGME_DATAPROVIDER_H__ #define __QGPGME_DATAPROVIDER_H__
#include "qgpgme_export.h" #include "qgpgme_export.h"
#ifdef BUILDING_QGPGME
#include <interfaces/dataprovider.h> #include <interfaces/dataprovider.h>
#else
#include <gpgme++/interfaces/dataprovider.h>
#endif
#include <memory> #include <memory>
#include <QtCore/QByteArray> #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 ExportJob;
class DownloadJob; class DownloadJob;
class DeleteJob; class DeleteJob;
class EncryptArchiveJob;
class EncryptJob; class EncryptJob;
class DecryptJob; class DecryptJob;
class SignArchiveJob;
class SignJob; class SignJob;
class SignKeyJob; class SignKeyJob;
class VerifyDetachedJob; class VerifyDetachedJob;
@ -189,6 +191,9 @@ public:
* OpenPGP key. * OpenPGP key.
*/ */
virtual SetPrimaryUserIDJob *setPrimaryUserIDJob() const = 0; 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. /** Obtain a reference to the OpenPGP Protocol.

View File

@ -46,7 +46,9 @@
#include "qgpgmedeletejob.h" #include "qgpgmedeletejob.h"
#include "qgpgmedownloadjob.h" #include "qgpgmedownloadjob.h"
#include "qgpgmesignencryptjob.h" #include "qgpgmesignencryptjob.h"
#include "qgpgmeencryptarchivejob.h"
#include "qgpgmeencryptjob.h" #include "qgpgmeencryptjob.h"
#include "qgpgmesignarchivejob.h"
#include "qgpgmesignjob.h" #include "qgpgmesignjob.h"
#include "qgpgmesignkeyjob.h" #include "qgpgmesignkeyjob.h"
#include "qgpgmeexportjob.h" #include "qgpgmeexportjob.h"
@ -506,6 +508,30 @@ public:
} }
return new QGpgME::QGpgMESetPrimaryUserIDJob{context}; 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_import_SOURCES = t-import.cpp $(support_src)
t_revokekey_SOURCES = t-revokekey.cpp $(support_src) t_revokekey_SOURCES = t-revokekey.cpp $(support_src)
t_setprimaryuserid_SOURCES = t-setprimaryuserid.cpp $(support_src) t_setprimaryuserid_SOURCES = t-setprimaryuserid.cpp $(support_src)
run_encryptarchivejob_SOURCES = run-encryptarchivejob.cpp
run_exportjob_SOURCES = run-exportjob.cpp run_exportjob_SOURCES = run-exportjob.cpp
run_importjob_SOURCES = run-importjob.cpp run_importjob_SOURCES = run-importjob.cpp
run_keyformailboxjob_SOURCES = run-keyformailboxjob.cpp run_keyformailboxjob_SOURCES = run-keyformailboxjob.cpp
run_receivekeysjob_SOURCES = run-receivekeysjob.cpp run_receivekeysjob_SOURCES = run-receivekeysjob.cpp
run_refreshkeysjob_SOURCES = run-refreshkeysjob.cpp run_refreshkeysjob_SOURCES = run-refreshkeysjob.cpp
run_signarchivejob_SOURCES = run-signarchivejob.cpp
nodist_t_keylist_SOURCES = $(moc_files) nodist_t_keylist_SOURCES = $(moc_files)
@ -102,7 +104,10 @@ noinst_PROGRAMS = \
run-keyformailboxjob t-wkspublish t-verify t-various t-config t-remarks \ run-keyformailboxjob t-wkspublish t-verify t-various t-config t-remarks \
t-trustsignatures t-changeexpiryjob t-wkdlookup t-import t-revokekey \ t-trustsignatures t-changeexpiryjob t-wkdlookup t-import t-revokekey \
t-setprimaryuserid \ 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 \ CLEANFILES = secring.gpg pubring.gpg pubring.kbx trustdb.gpg dirmngr.conf \
gpg-agent.conf pubring.kbx~ S.gpg-agent gpg.conf pubring.gpg~ \ 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_DIRMNGR_NAME,
WANT_PINENTRY_NAME, WANT_PINENTRY_NAME,
WANT_GPG_WKS_CLIENT_NAME, WANT_GPG_WKS_CLIENT_NAME,
WANT_GPGTAR_NAME,
WANT_GPG_ONE_MODE WANT_GPG_ONE_MODE
}; };
@ -88,6 +89,7 @@ static struct {
char *dirmngr_name; char *dirmngr_name;
char *pinentry_name; char *pinentry_name;
char *gpg_wks_client_name; char *gpg_wks_client_name;
char *gpgtar_name;
int gpg_one_mode; /* System is in gpg1 mode. */ int gpg_one_mode; /* System is in gpg1 mode. */
} dirinfo; } dirinfo;
@ -407,6 +409,14 @@ get_gpgconf_item (int what)
NULL); NULL);
result = dirinfo.gpg_wks_client_name; result = dirinfo.gpg_wks_client_name;
break; 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); UNLOCK (dirinfo_lock);
return result; return result;
@ -455,6 +465,13 @@ _gpgme_get_default_gpgconf_name (void)
return get_gpgconf_item (WANT_GPGCONF_NAME); 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 /* Return the default UI-server socket name. Returns NULL if not
known. */ known. */
const char * const char *
@ -524,6 +541,8 @@ gpgme_get_dirinfo (const char *what)
return get_gpgconf_item (WANT_PINENTRY_NAME); return get_gpgconf_item (WANT_PINENTRY_NAME);
else if (!strcmp (what, "gpg-wks-client-name")) else if (!strcmp (what, "gpg-wks-client-name"))
return get_gpgconf_item (WANT_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")) else if (!strcmp (what, "agent-ssh-socket"))
return get_gpgconf_item (WANT_AGENT_SSH_SOCKET); return get_gpgconf_item (WANT_AGENT_SSH_SOCKET);
else if (!strcmp (what, "dirmngr-socket")) else if (!strcmp (what, "dirmngr-socket"))

View File

@ -119,12 +119,12 @@ struct engine_ops
gpgme_key_t key, gpgme_key_t key,
gpgme_tofu_policy_t policy); gpgme_tofu_policy_t policy);
gpgme_error_t (*sign) (void *engine, gpgme_data_t in, gpgme_data_t out, 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, int use_textmode, int include_certs,
gpgme_ctx_t ctx /* FIXME */); gpgme_ctx_t ctx /* FIXME */);
gpgme_error_t (*verify) (void *engine, gpgme_data_t sig, gpgme_error_t (*verify) (void *engine, gpgme_verify_flags_t flags,
gpgme_data_t signed_text, gpgme_data_t plaintext, gpgme_data_t sig, gpgme_data_t signed_text,
gpgme_ctx_t ctx); gpgme_data_t plaintext, gpgme_ctx_t ctx);
gpgme_error_t (*getauditlog) (void *engine, gpgme_data_t output, gpgme_error_t (*getauditlog) (void *engine, gpgme_data_t output,
unsigned int flags); unsigned int flags);
gpgme_error_t (*setexpire) (void *engine, gpgme_key_t key, 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 */ if (!recp && !recpstring) /* Symmetric only */
return gpg_error (GPG_ERR_NOT_IMPLEMENTED); 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)) if ((flags & GPGME_ENCRYPT_NO_ENCRYPT_TO))
{ {
err = gpgsm_assuan_simple_command (gpgsm, 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 static gpgme_error_t
gpgsm_sign (void *engine, gpgme_data_t in, gpgme_data_t out, 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 */) int include_certs, gpgme_ctx_t ctx /* FIXME */)
{ {
engine_gpgsm_t gpgsm = engine; engine_gpgsm_t gpgsm = engine;
@ -2054,6 +2057,9 @@ gpgsm_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
if (!gpgsm) if (!gpgsm)
return gpg_error (GPG_ERR_INV_VALUE); 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 /* FIXME: This does not work as RESET does not reset it so we can't
revert back to default. */ revert back to default. */
if (include_certs != GPGME_INCLUDE_CERTS_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_clear_fd (gpgsm, MESSAGE_FD);
gpgsm->inline_data = NULL; gpgsm->inline_data = NULL;
err = start (gpgsm, mode == GPGME_SIG_MODE_DETACH err = start (gpgsm, (flags & GPGME_SIG_MODE_DETACH)
? "SIGN --detached" : "SIGN"); ? "SIGN --detached" : "SIGN");
return err; return err;
} }
static gpgme_error_t static gpgme_error_t
gpgsm_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text, gpgsm_verify (void *engine, gpgme_verify_flags_t flags, gpgme_data_t sig,
gpgme_data_t plaintext, gpgme_ctx_t ctx) gpgme_data_t signed_text, gpgme_data_t plaintext,
gpgme_ctx_t ctx)
{ {
engine_gpgsm_t gpgsm = engine; engine_gpgsm_t gpgsm = engine;
gpgme_error_t err; gpgme_error_t err;
@ -2120,6 +2127,9 @@ gpgsm_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
if (!gpgsm) if (!gpgsm)
return gpg_error (GPG_ERR_INV_VALUE); return gpg_error (GPG_ERR_INV_VALUE);
if (flags & GPGME_VERIFY_ARCHIVE)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
gpgsm->input_cb.data = sig; gpgsm->input_cb.data = sig;
err = gpgsm_set_fd (gpgsm, INPUT_FD, map_data_enc (gpgsm->input_cb.data)); err = gpgsm_set_fd (gpgsm, INPUT_FD, map_data_enc (gpgsm->input_cb.data));
if (err) if (err)

View File

@ -1145,6 +1145,9 @@ uiserver_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring,
else else
return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL); 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 (flags & GPGME_ENCRYPT_PREPARE)
{ {
if (!recp || plain || ciph) if (!recp || plain || ciph)
@ -1211,7 +1214,7 @@ uiserver_encrypt (void *engine, gpgme_key_t recp[], const char *recpstring,
static gpgme_error_t static gpgme_error_t
uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out, 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 */) int include_certs, gpgme_ctx_t ctx /* FIXME */)
{ {
engine_uiserver_t uiserver = engine; engine_uiserver_t uiserver = engine;
@ -1234,8 +1237,11 @@ uiserver_sign (void *engine, gpgme_data_t in, gpgme_data_t out,
else else
return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL); 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, 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 (); return gpg_error_from_syserror ();
key = gpgme_signers_enum (ctx, 0); 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. */ /* FIXME: Missing a way to specify --silent. */
static gpgme_error_t static gpgme_error_t
uiserver_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text, uiserver_verify (void *engine, gpgme_verify_flags_t flags, gpgme_data_t sig,
gpgme_data_t plaintext, gpgme_ctx_t ctx) gpgme_data_t signed_text, gpgme_data_t plaintext,
gpgme_ctx_t ctx)
{ {
engine_uiserver_t uiserver = engine; engine_uiserver_t uiserver = engine;
gpgme_error_t err; gpgme_error_t err;
@ -1313,6 +1320,9 @@ uiserver_verify (void *engine, gpgme_data_t sig, gpgme_data_t signed_text,
else else
return gpgme_error (GPG_ERR_UNSUPPORTED_PROTOCOL); 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) if (gpgrt_asprintf (&cmd, "VERIFY%s", protocol) < 0)
return gpg_error_from_syserror (); 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_error_t
_gpgme_engine_op_sign (engine_t engine, gpgme_data_t in, gpgme_data_t out, _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, int use_textmode, int include_certs,
gpgme_ctx_t ctx /* FIXME */) 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) if (!engine->ops->sign)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED); 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); use_textmode, include_certs, ctx);
} }
@ -940,9 +940,9 @@ _gpgme_engine_op_trustlist (engine_t engine, const char *pattern)
gpgme_error_t gpgme_error_t
_gpgme_engine_op_verify (engine_t engine, gpgme_data_t sig, _gpgme_engine_op_verify (engine_t engine, gpgme_verify_flags_t flags,
gpgme_data_t signed_text, gpgme_data_t plaintext, gpgme_data_t sig, gpgme_data_t signed_text,
gpgme_ctx_t ctx) gpgme_data_t plaintext, gpgme_ctx_t ctx)
{ {
if (!engine) if (!engine)
return gpg_error (GPG_ERR_INV_VALUE); 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) if (!engine->ops->verify)
return gpg_error (GPG_ERR_NOT_IMPLEMENTED); return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
return (*engine->ops->verify) (engine->engine, sig, signed_text, plaintext, return (*engine->ops->verify) (engine->engine, flags, sig, signed_text,
ctx); 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_keylist_mode_t mode,
gpgme_data_t data); gpgme_data_t data);
gpgme_error_t _gpgme_engine_op_sign (engine_t engine, gpgme_data_t in, 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 use_armor, int use_textmode,
int include_certs, int include_certs,
gpgme_ctx_t ctx /* FIXME */); gpgme_ctx_t ctx /* FIXME */);
gpgme_error_t _gpgme_engine_op_trustlist (engine_t engine, gpgme_error_t _gpgme_engine_op_trustlist (engine_t engine,
const char *pattern); 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 signed_text,
gpgme_data_t plaintext, gpgme_data_t plaintext,
gpgme_ctx_t ctx); gpgme_ctx_t ctx);

View File

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

View File

@ -303,12 +303,13 @@ typedef enum
gpgme_hash_algo_t; gpgme_hash_algo_t;
/* The available signature modes. */ /* The available signature mode flags. */
typedef enum typedef enum
{ {
GPGME_SIG_MODE_NORMAL = 0, GPGME_SIG_MODE_NORMAL = 0,
GPGME_SIG_MODE_DETACH = 1, GPGME_SIG_MODE_DETACH = 1,
GPGME_SIG_MODE_CLEAR = 2 GPGME_SIG_MODE_CLEAR = 2,
GPGME_SIG_MODE_ARCHIVE = 4
} }
gpgme_sig_mode_t; gpgme_sig_mode_t;
@ -1299,7 +1300,8 @@ typedef enum
GPGME_ENCRYPT_SYMMETRIC = 32, GPGME_ENCRYPT_SYMMETRIC = 32,
GPGME_ENCRYPT_THROW_KEYIDS = 64, GPGME_ENCRYPT_THROW_KEYIDS = 64,
GPGME_ENCRYPT_WRAP = 128, GPGME_ENCRYPT_WRAP = 128,
GPGME_ENCRYPT_WANT_ADDRESS = 256 GPGME_ENCRYPT_WANT_ADDRESS = 256,
GPGME_ENCRYPT_ARCHIVE = 512
} }
gpgme_encrypt_flags_t; gpgme_encrypt_flags_t;
@ -1424,6 +1426,7 @@ gpgme_decrypt_result_t gpgme_op_decrypt_result (gpgme_ctx_t ctx);
typedef enum typedef enum
{ {
GPGME_DECRYPT_VERIFY = 1, GPGME_DECRYPT_VERIFY = 1,
GPGME_DECRYPT_ARCHIVE = 2,
GPGME_DECRYPT_UNWRAP = 128 GPGME_DECRYPT_UNWRAP = 128
} }
gpgme_decrypt_flags_t; 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. */ /* Sign the plaintext PLAIN and store the signature in SIG. */
gpgme_error_t gpgme_op_sign_start (gpgme_ctx_t ctx, gpgme_error_t gpgme_op_sign_start (gpgme_ctx_t ctx,
gpgme_data_t plain, gpgme_data_t sig, 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_error_t gpgme_op_sign (gpgme_ctx_t ctx,
gpgme_data_t plain, gpgme_data_t sig, 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. */ /* Retrieve a pointer to the result of the verify operation. */
gpgme_verify_result_t gpgme_op_verify_result (gpgme_ctx_t ctx); 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. */ /* 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_error_t gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig,
gpgme_data_t signed_text, 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_error_t gpgme_op_verify (gpgme_ctx_t ctx, gpgme_data_t sig,
gpgme_data_t signed_text, gpgme_data_t signed_text,
gpgme_data_t plaintext); 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;
gpgme_op_receive_keys_start; gpgme_op_receive_keys_start;
gpgme_op_verify_ext;
gpgme_op_verify_ext_start;
local: local:
*; *;

View File

@ -431,7 +431,7 @@ _gpgme_op_sign_init_result (gpgme_ctx_t ctx)
static gpgme_error_t static gpgme_error_t
sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t plain, 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; gpgme_error_t err;
@ -446,8 +446,9 @@ sign_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t plain,
if (err) if (err)
return err; return err;
if (mode != GPGME_SIG_MODE_NORMAL && mode != GPGME_SIG_MODE_DETACH if (flags & ~(GPGME_SIG_MODE_DETACH
&& mode != GPGME_SIG_MODE_CLEAR) |GPGME_SIG_MODE_CLEAR
|GPGME_SIG_MODE_ARCHIVE))
return gpg_error (GPG_ERR_INV_VALUE); return gpg_error (GPG_ERR_INV_VALUE);
if (!plain) 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, _gpgme_engine_set_status_handler (ctx->engine, sign_status_handler,
ctx); 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->use_textmode, ctx->include_certs,
ctx /* FIXME */); 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. */ /* Sign the plaintext PLAIN and store the signature in SIG. */
gpgme_error_t gpgme_error_t
gpgme_op_sign_start (gpgme_ctx_t ctx, gpgme_data_t plain, gpgme_data_t sig, 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; gpg_error_t err;
TRACE_BEG (DEBUG_CTX, "gpgme_op_sign_start", ctx, 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) if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); 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); 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. */ /* Sign the plaintext PLAIN and store the signature in SIG. */
gpgme_error_t gpgme_error_t
gpgme_op_sign (gpgme_ctx_t ctx, gpgme_data_t plain, gpgme_data_t sig, 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; gpgme_error_t err;
TRACE_BEG (DEBUG_CTX, "gpgme_op_sign", ctx, 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) if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); 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) if (!err)
err = _gpgme_wait_one (ctx); err = _gpgme_wait_one (ctx);
return TRACE_ERR (err); 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_gpgsm_name (void);
const char *_gpgme_get_default_g13_name (void); const char *_gpgme_get_default_g13_name (void);
const char *_gpgme_get_default_gpgconf_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); const char *_gpgme_get_default_uisrv_socket (void);
int _gpgme_in_gpg_one_mode (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 static gpgme_error_t
verify_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t sig, verify_start (gpgme_ctx_t ctx, int synchronous, gpgme_verify_flags_t flags,
gpgme_data_t signed_text, gpgme_data_t plaintext) gpgme_data_t sig, gpgme_data_t signed_text,
gpgme_data_t plaintext)
{ {
gpgme_error_t err; gpgme_error_t err;
@ -1153,26 +1154,45 @@ verify_start (gpgme_ctx_t ctx, int synchronous, gpgme_data_t sig,
if (!sig) if (!sig)
return gpg_error (GPG_ERR_NO_DATA); return gpg_error (GPG_ERR_NO_DATA);
return _gpgme_engine_op_verify (ctx->engine, sig, signed_text, plaintext, return _gpgme_engine_op_verify (ctx->engine, flags, sig, signed_text,
ctx); plaintext, ctx);
} }
/* Decrypt ciphertext CIPHER and make a signature verification within /* Old version of gpgme_op_verify_ext_start without FLAGS. */
CTX and store the resulting plaintext in PLAIN. */
gpgme_error_t gpgme_error_t
gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig, gpgme_op_verify_start (gpgme_ctx_t ctx, gpgme_data_t sig,
gpgme_data_t signed_text, gpgme_data_t plaintext) 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; gpg_error_t err;
TRACE_BEG (DEBUG_CTX, "gpgme_op_verify_start", ctx, TRACE_BEG (DEBUG_CTX, "gpgme_op_verify_start", ctx,
"sig=%p, signed_text=%p, plaintext=%p", "flags=0x%x, sig=%p, signed_text=%p, plaintext=%p",
sig, signed_text, plaintext); flags, sig, signed_text, plaintext);
if (!ctx) if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); 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); 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 /* Decrypt ciphertext CIPHER and make a signature verification within
CTX and store the resulting plaintext in PLAIN. */ CTX and store the resulting plaintext in PLAIN. */
gpgme_error_t 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 plaintext) gpgme_data_t sig, gpgme_data_t signed_text,
gpgme_data_t plaintext)
{ {
gpgme_error_t err; gpgme_error_t err;
TRACE_BEG (DEBUG_CTX, "gpgme_op_verify", ctx, TRACE_BEG (DEBUG_CTX, "gpgme_op_verify", ctx,
"sig=%p, signed_text=%p, plaintext=%p", "flags=0x%x, sig=%p, signed_text=%p, plaintext=%p",
sig, signed_text, plaintext); flags, sig, signed_text, plaintext);
if (!ctx) if (!ctx)
return TRACE_ERR (gpg_error (GPG_ERR_INV_VALUE)); 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) if (!err)
err = _gpgme_wait_one (ctx); err = _gpgme_wait_one (ctx);
return TRACE_ERR (err); return TRACE_ERR (err);

View File

@ -91,6 +91,8 @@ show_usage (int ex)
" --unwrap remove only the encryption layer\n" " --unwrap remove only the encryption layer\n"
" --large-buffers use large I/O buffer\n" " --large-buffers use large I/O buffer\n"
" --sensitive mark data objects as sensitive\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" " --diagnostics print diagnostics\n"
, stderr); , stderr);
exit (ex); exit (ex);
@ -113,6 +115,7 @@ main (int argc, char **argv)
int export_session_key = 0; int export_session_key = 0;
const char *override_session_key = NULL; const char *override_session_key = NULL;
const char *request_origin = NULL; const char *request_origin = NULL;
const char *directory = NULL;
int no_symkey_cache = 0; int no_symkey_cache = 0;
int ignore_mdc_error = 0; int ignore_mdc_error = 0;
int raw_output = 0; int raw_output = 0;
@ -205,6 +208,19 @@ main (int argc, char **argv)
raw_output = 1; raw_output = 1;
argc--; argv++; 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)) else if (!strncmp (*argv, "--", 2))
show_usage (1); show_usage (1);
@ -302,6 +318,16 @@ main (int argc, char **argv)
gpgme_strerror (err)); gpgme_strerror (err));
exit (1); 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) if (large_buffers)
{ {
err = gpgme_data_set_flag (out, "io-buffer-size", "1000000"); 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 static void
print_result (gpgme_encrypt_result_t result) print_encrypt_result (gpgme_encrypt_result_t result)
{ {
gpgme_invalid_key_t invkey; gpgme_invalid_key_t invkey;
printf ("\nEncryption results\n");
for (invkey = result->invalid_recipients; invkey; invkey = invkey->next) for (invkey = result->invalid_recipients; invkey; invkey = invkey->next)
printf ("Encryption key `%s' not used: %s <%s>\n", printf ("Encryption key `%s' not used: %s <%s>\n",
nonnull (invkey->fpr), 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 static int
show_usage (int ex) show_usage (int ex)
@ -95,6 +120,7 @@ show_usage (int ex)
fputs ("usage: " PGM " [options] FILE\n\n" fputs ("usage: " PGM " [options] FILE\n\n"
"Options:\n" "Options:\n"
" --verbose run in verbose mode\n" " --verbose run in verbose mode\n"
" --sign sign data before encryption\n"
" --status print status lines from the backend\n" " --status print status lines from the backend\n"
" --progress print progress info\n" " --progress print progress info\n"
" --openpgp use the OpenPGP protocol (default)\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" " --no-symkey-cache disable the use of that cache\n"
" --wrap assume input is valid OpenPGP message\n" " --wrap assume input is valid OpenPGP message\n"
" --symmetric encrypt symmetric (OpenPGP only)\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); , stderr);
exit (ex); exit (ex);
} }
@ -120,7 +149,8 @@ main (int argc, char **argv)
gpgme_ctx_t ctx; gpgme_ctx_t ctx;
gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP; gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
gpgme_data_t in, out; 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_status = 0;
int print_progress = 0; int print_progress = 0;
int use_loopback = 0; int use_loopback = 0;
@ -128,10 +158,13 @@ main (int argc, char **argv)
gpgme_key_t keys[10+1]; gpgme_key_t keys[10+1];
int keycount = 0; int keycount = 0;
char *keystring = NULL; char *keystring = NULL;
const char *directory = NULL;
int i; int i;
gpgme_encrypt_flags_t flags = GPGME_ENCRYPT_ALWAYS_TRUST; gpgme_encrypt_flags_t flags = GPGME_ENCRYPT_ALWAYS_TRUST;
gpgme_off_t offset; gpgme_off_t offset;
int no_symkey_cache = 0; int no_symkey_cache = 0;
int diagnostics = 0;
int sign = 0;
if (argc) if (argc)
{ argc--; argv++; } { argc--; argv++; }
@ -154,6 +187,11 @@ main (int argc, char **argv)
verbose = 1; verbose = 1;
argc--; argv++; argc--; argv++;
} }
else if (!strcmp (*argv, "--sign"))
{
sign = 1;
argc--; argv++;
}
else if (!strcmp (*argv, "--status")) else if (!strcmp (*argv, "--status"))
{ {
print_status = 1; print_status = 1;
@ -225,6 +263,24 @@ main (int argc, char **argv)
no_symkey_cache = 1; no_symkey_cache = 1;
argc--; argv++; 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)) else if (!strncmp (*argv, "--", 2))
show_usage (1); show_usage (1);
@ -269,57 +325,100 @@ main (int argc, char **argv)
} }
keys[i] = NULL; keys[i] = NULL;
err = gpgme_data_new_from_file (&in, *argv, 1); if (flags & GPGME_ENCRYPT_ARCHIVE)
if (err)
{ {
fprintf (stderr, PGM ": error reading `%s': %s\n", const char *path = *argv;
*argv, gpg_strerror (err)); err = gpgme_data_new_from_mem (&in, path, strlen (path), 0);
exit (1); fail_if_err (err);
if (directory)
{
err = gpgme_data_set_file_name (in, directory);
fail_if_err (err);
}
} }
offset = gpgme_data_seek (in, 0, SEEK_END); else
if (offset == (gpgme_off_t)(-1))
{ {
err = gpg_error_from_syserror (); err = gpgme_data_new_from_file (&in, *argv, 1);
fprintf (stderr, PGM ": error seeking `%s': %s\n", if (err)
*argv, gpg_strerror (err)); {
exit (1); fprintf (stderr, PGM ": error reading `%s': %s\n",
} *argv, gpg_strerror (err));
if (gpgme_data_seek (in, 0, SEEK_SET) == (gpgme_off_t)(-1)) exit (1);
{ }
err = gpg_error_from_syserror (); offset = gpgme_data_seek (in, 0, SEEK_END);
fprintf (stderr, PGM ": error seeking `%s': %s\n", if (offset == (gpgme_off_t)(-1))
*argv, gpg_strerror (err)); {
exit (1); err = gpg_error_from_syserror ();
} fprintf (stderr, PGM ": error seeking `%s': %s\n",
{ *argv, gpg_strerror (err));
char numbuf[50]; exit (1);
char *p; }
if (gpgme_data_seek (in, 0, SEEK_SET) == (gpgme_off_t)(-1))
{
err = gpg_error_from_syserror ();
fprintf (stderr, PGM ": error seeking `%s': %s\n",
*argv, gpg_strerror (err));
exit (1);
}
{
char numbuf[50];
char *p;
p = numbuf + sizeof numbuf; p = numbuf + sizeof numbuf;
*--p = 0; *--p = 0;
do do
{ {
*--p = '0' + (offset % 10); *--p = '0' + (offset % 10);
offset /= 10; offset /= 10;
}
while (offset);
err = gpgme_data_set_flag (in, "size-hint", p);
if (err)
{
fprintf (stderr, PGM ": error setting size-hint for `%s': %s\n",
*argv, gpg_strerror (err));
exit (1);
}
} }
while (offset); }
err = gpgme_data_set_flag (in, "size-hint", p);
if (err)
{
fprintf (stderr, PGM ": error setting size-hint for `%s': %s\n",
*argv, gpg_strerror (err));
exit (1);
}
}
err = gpgme_data_new (&out); err = gpgme_data_new (&out);
fail_if_err (err); fail_if_err (err);
err = gpgme_op_encrypt_ext (ctx, keycount ? keys : NULL, keystring, if (sign)
flags, in, out); err = gpgme_op_encrypt_sign_ext (ctx, keycount ? keys : NULL, keystring,
result = gpgme_op_encrypt_result (ctx); flags, in, out);
if (result) else
print_result (result); err = gpgme_op_encrypt_ext (ctx, keycount ? keys : NULL, keystring,
flags, in, out);
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) if (err)
{ {
fprintf (stderr, PGM ": encrypting failed: %s\n", gpg_strerror (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" " --sender MBOX use MBOX as sender address\n"
" --include-key-block use this option with gpg\n" " --include-key-block use this option with gpg\n"
" --clear create a clear text signature\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); , stderr);
exit (ex); exit (ex);
} }
@ -99,6 +102,7 @@ main (int argc, char **argv)
gpgme_error_t err; gpgme_error_t err;
gpgme_ctx_t ctx; gpgme_ctx_t ctx;
const char *key_string = NULL; const char *key_string = NULL;
const char *directory = NULL;
gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP; gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
gpgme_sig_mode_t sigmode = GPGME_SIG_MODE_NORMAL; gpgme_sig_mode_t sigmode = GPGME_SIG_MODE_NORMAL;
gpgme_data_t in, out; gpgme_data_t in, out;
@ -106,6 +110,7 @@ main (int argc, char **argv)
int print_status = 0; int print_status = 0;
int use_loopback = 0; int use_loopback = 0;
int include_key_block = 0; int include_key_block = 0;
int diagnostics = 0;
const char *sender = NULL; const char *sender = NULL;
const char *s; const char *s;
@ -178,6 +183,24 @@ main (int argc, char **argv)
sigmode = GPGME_SIG_MODE_CLEAR; sigmode = GPGME_SIG_MODE_CLEAR;
argc--; argv++; 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)) else if (!strncmp (*argv, "--", 2))
show_usage (1); show_usage (1);
@ -236,12 +259,26 @@ main (int argc, char **argv)
} }
} }
err = gpgme_data_new_from_file (&in, *argv, 1); if (sigmode == GPGME_SIG_MODE_ARCHIVE)
if (err)
{ {
fprintf (stderr, PGM ": error reading `%s': %s\n", const char *path = *argv;
*argv, gpg_strerror (err)); err = gpgme_data_new_from_mem (&in, path, strlen (path), 0);
exit (1); 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)
{
fprintf (stderr, PGM ": error reading `%s': %s\n",
*argv, gpg_strerror (err));
exit (1);
}
} }
err = gpgme_data_new (&out); err = gpgme_data_new (&out);
@ -249,6 +286,28 @@ main (int argc, char **argv)
err = gpgme_op_sign (ctx, in, out, sigmode); err = gpgme_op_sign (ctx, in, out, sigmode);
result = gpgme_op_sign_result (ctx); 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) if (result)
print_result (result, sigmode); print_result (result, sigmode);
if (err) if (err)

View File

@ -235,6 +235,9 @@ show_usage (int ex)
" --repeat N repeat the operation N times\n" " --repeat N repeat the operation N times\n"
" --auto-key-retrieve\n" " --auto-key-retrieve\n"
" --auto-key-import\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); , stderr);
exit (ex); exit (ex);
} }
@ -246,10 +249,13 @@ main (int argc, char **argv)
int last_argc = -1; int last_argc = -1;
const char *s; const char *s;
gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP; gpgme_protocol_t protocol = GPGME_PROTOCOL_OpenPGP;
gpgme_verify_flags_t flags = 0;
int print_status = 0; int print_status = 0;
const char *sender = NULL; const char *sender = NULL;
const char *directory = NULL;
int auto_key_retrieve = 0; int auto_key_retrieve = 0;
int auto_key_import = 0; int auto_key_import = 0;
int diagnostics = 0;
int repeats = 1; int repeats = 1;
int i; int i;
@ -312,12 +318,30 @@ main (int argc, char **argv)
auto_key_import = 1; auto_key_import = 1;
argc--; argv++; 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)) else if (!strncmp (*argv, "--", 2))
show_usage (1); show_usage (1);
} }
if (argc < 1 || argc > 2) if (argc < 1 || argc > 2 || (argc > 1 && (flags & GPGME_VERIFY_ARCHIVE)))
show_usage (1); show_usage (1);
init_gpgme (protocol); init_gpgme (protocol);
@ -330,6 +354,7 @@ main (int argc, char **argv)
gpgme_data_t sig = NULL; gpgme_data_t sig = NULL;
FILE *fp_msg = NULL; FILE *fp_msg = NULL;
gpgme_data_t msg = NULL; gpgme_data_t msg = NULL;
gpgme_data_t out = NULL;
gpgme_verify_result_t result; gpgme_verify_result_t result;
if (repeats > 1) 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); 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) if (result)
print_result (result); print_result (result);
if (err) if (err)
@ -425,6 +490,7 @@ main (int argc, char **argv)
exit (1); exit (1);
} }
gpgme_data_release (out);
gpgme_data_release (msg); gpgme_data_release (msg);
gpgme_data_release (sig); gpgme_data_release (sig);

View File

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