Commit 2811686e authored by Claudio Cambra's avatar Claudio Cambra
Browse files

Make the mail headers look pretty



Signed-off-by: Claudio Cambra's avatarClaudio Cambra <claudio.cambra@gmail.com>
Signed-off-by: Carl Schwan's avatarCarl Schwan <carl@carlschwan.eu>
parent c9ad01aa
Pipeline #213043 failed with stage
in 6 minutes and 27 seconds
......@@ -2,7 +2,7 @@
# SPDX-License-Identifier: CC0-1.0
Dependencies:
- 'on': ['@all']
- 'on': ['Linux', 'FreeBSD']
'require':
'frameworks/extra-cmake-modules': '@latest'
'frameworks/qqc2-desktop-style': '@latest'
......
# SPDX-FileCopyrightText: 2013 Sandro Knauß <mail@sandroknauss.de>
#
# SPDX-License-Identifier: BSD-3-Clause
set(MIMETREEPARSERRELPATH src/mail/mimetreeparser)
set(GNUPGHOME ${CMAKE_BINARY_DIR}/${MIMETREEPARSERRELPATH}/tests/gnupg_home)
add_definitions(-DGNUPGHOME="${GNUPGHOME}")
macro (ADD_GPG_CRYPTO_TEST _target _testname)
if (UNIX)
if (APPLE)
set(_library_path_variable "DYLD_LIBRARY_PATH")
elseif (CYGWIN)
set(_library_path_variable "PATH")
else (APPLE)
set(_library_path_variable "LD_LIBRARY_PATH")
endif (APPLE)
if (APPLE)
# DYLD_LIBRARY_PATH does not work like LD_LIBRARY_PATH
# OSX already has the RPATH in libraries and executables, putting runtime directories in
# DYLD_LIBRARY_PATH actually breaks things
set(_ld_library_path "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/")
else (APPLE)
set(_ld_library_path "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/:${LIB_INSTALL_DIR}:${QT_LIBRARY_DIR}")
endif (APPLE)
set(_executable "$<TARGET_FILE:${_target}>")
# use add_custom_target() to have the sh-wrapper generated during build time instead of cmake time
add_custom_command(TARGET ${_target} POST_BUILD
COMMAND ${CMAKE_COMMAND}
-D_filename=${_executable}.shell -D_library_path_variable=${_library_path_variable}
-D_ld_library_path="${_ld_library_path}" -D_executable=$<TARGET_FILE:${_target}>
-D_gnupghome="${GNUPGHOME}"
-P ${CMAKE_SOURCE_DIR}/cmake/modules/kdepim_generate_crypto_test_wrapper.cmake
)
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${_executable}.shell" )
add_test(NAME ${_testname} COMMAND ${_executable}.shell)
else (UNIX)
# under windows, set the property WRAPPER_SCRIPT just to the name of the executable
# maybe later this will change to a generated batch file (for setting the PATH so that the Qt libs are found)
set(_ld_library_path "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}\;${LIB_INSTALL_DIR}\;${QT_LIBRARY_DIR}")
set(_executable "$<TARGET_FILE:${_target}>")
# use add_custom_target() to have the batch-file-wrapper generated during build time instead of cmake time
add_custom_command(TARGET ${_target} POST_BUILD
COMMAND ${CMAKE_COMMAND}
-D_filename="${_executable}.bat"
-D_ld_library_path="${_ld_library_path}" -D_executable="${_executable}"
-D_gnupghome="${GNUPGHOME}"
-P ${CMAKE_SOURCE_DIR}/cmake/modules/kdepim_generate_crypto_test_wrapper.cmake
)
add_test(NAME ${_testname} COMMAND ${_executable}.bat)
endif (UNIX)
# can't be parallelized due to gpg-agent
set_tests_properties(${_testname} PROPERTIES RUN_SERIAL TRUE)
endmacro (ADD_GPG_CRYPTO_TEST)
macro (ADD_GPG_CRYPTO_AKONADI_TEST _target _testname)
set(_executable "$<TARGET_FILE:${_target}>")
if (UNIX)
if (APPLE)
set(_library_path_variable "DYLD_LIBRARY_PATH")
elseif (CYGWIN)
set(_library_path_variable "PATH")
else (APPLE)
set(_library_path_variable "LD_LIBRARY_PATH")
endif (APPLE)
if (APPLE)
# DYLD_LIBRARY_PATH does not work like LD_LIBRARY_PATH
# OSX already has the RPATH in libraries and executables, putting runtime directories in
# DYLD_LIBRARY_PATH actually breaks things
set(_ld_library_path "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/")
else (APPLE)
set(_ld_library_path "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}/:${LIB_INSTALL_DIR}:${QT_LIBRARY_DIR}")
endif (APPLE)
set(_posix "shell")
set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES "${_executable}.${_posix}" )
# use add_custom_target() to have the sh-wrapper generated during build time instead of cmake time
add_custom_command(TARGET ${_target} POST_BUILD
COMMAND ${CMAKE_COMMAND}
-D_filename=${_executable}.${_posix} -D_library_path_variable=${_library_path_variable}
-D_ld_library_path="${_ld_library_path}" -D_executable="${_executable}"
-D_gnupghome="${GNUPGHOME}"
-P ${CMAKE_SOURCE_DIR}/cmake/modules/kdepim_generate_crypto_test_wrapper.cmake
)
else (UNIX)
# under windows, set the property WRAPPER_SCRIPT just to the name of the executable
# maybe later this will change to a generated batch file (for setting the PATH so that the Qt libs are found)
set(_ld_library_path "${LIBRARY_OUTPUT_PATH}/${CMAKE_CFG_INTDIR}\;${LIB_INSTALL_DIR}\;${QT_LIBRARY_DIR}")
set(_posix "bat")
# use add_custom_target() to have the batch-file-wrapper generated during build time instead of cmake time
add_custom_command(TARGET ${_target} POST_BUILD
COMMAND ${CMAKE_COMMAND}
-D_filename="${_executable}.${_posix}"
-D_ld_library_path="${_ld_library_path}" -D_executable="${_executable}"
-D_gnupghome="${GNUPGHOME}"
-P ${CMAKE_SOURCE_DIR}/cmake/modules/kdepim_generate_crypto_test_wrapper.cmake
)
endif ()
if (NOT DEFINED _testrunner)
find_program(_testrunner NAMES akonaditest akonaditest.exe)
if (NOT _testrunner)
message(WARNING "Could not locate akonaditest executable, isolated Akonadi tests will fail!")
endif()
endif()
function(_defineTest name backend)
set(backends ${ARGN})
if (NOT DEFINED AKONADI_RUN_${backend}_ISOLATED_TESTS OR AKONADI_RUN_${backend}_ISOLATED_TESTS)
LIST(LENGTH "${backends}" backendsLen)
string(TOLOWER ${backend} lcbackend)
LIST(FIND "${backends}" ${lcbackend} enableBackend)
if (${backendsLen} EQUAL 0 OR ${enableBackend} GREATER -1)
set(configFile ${CMAKE_CURRENT_SOURCE_DIR}/unittestenv/config.xml)
if (AKONADI_TESTS_XML)
set(extraOptions -xml -o "${TEST_RESULT_OUTPUT_PATH}/${lcbackend}-${name}.xml")
endif()
set(_test_name akonadi-${lcbackend}-${name})
add_test(NAME ${_test_name}
COMMAND ${_testrunner} -c "${configFile}" -b ${lcbackend}
"${_executable}.${_posix}" ${extraOptions}
)
# Taken from ECMAddTests.cmake
if (CMAKE_LIBRARY_OUTPUT_DIRECTORY)
if(CMAKE_HOST_SYSTEM MATCHES "Windows")
set(PATHSEP ";")
else() # e.g. Linux
set(PATHSEP ":")
endif()
set(_plugin_path $ENV{QT_PLUGIN_PATH})
set(_test_env
QT_PLUGIN_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}${PATHSEP}$ENV{QT_PLUGIN_PATH}
LD_LIBRARY_PATH=${CMAKE_LIBRARY_OUTPUT_DIRECTORY}${PATHSEP}$ENV{LD_LIBRARY_PATH}
)
set_tests_properties(${_test_name} PROPERTIES ENVIRONMENT "${_test_env}")
endif()
set_tests_properties(${_test_name} PROPERTIES RUN_SERIAL TRUE) # can't be parallelized due to gpg-agent
endif()
endif()
endfunction()
find_program(MYSQLD_EXECUTABLE mysqld /usr/sbin /usr/local/sbin /usr/libexec /usr/local/libexec /opt/mysql/libexec /usr/mysql/bin)
if (MYSQLD_EXECUTABLE AND NOT WIN32)
_defineTest(${_testname} "MYSQL" ${CONFIG_BACKENDS})
endif()
find_program(POSTGRES_EXECUTABLE postgres)
if (POSTGRES_EXECUTABLE AND NOT WIN32)
_defineTest(${_testname} "PGSQL" ${CONFIG_BACKENDS})
endif()
_defineTest(${_testname} "SQLITE" ${CONFIG_BACKENDS})
endmacro (ADD_GPG_CRYPTO_AKONADI_TEST)
# SPDX-FileCopyrightText: 2006 Alexander Neundorf <neundorf@kde.org>
# SPDX-FileCopyrightText: 2013 Sandro Knauß <mail@sandroknauss.de>
#
# SPDX-License-Identifier: BSD-3-Clause
if (UNIX)
file(WRITE "${_filename}"
"#!/bin/sh
# created by cmake, don't edit, changes will be lost
# don't mess with a gpg-agent already running on the system
unset GPG_AGENT_INFO
# _gnupghome will contain a socket, and the path to that has a length limit of 108 chars
# which that is easily reached. Therefore shorten this by copying this to a temporary dir.
# This has the convenient side-effect that modifications to the content are not propagated
# to other tests.
tmp_dir=`mktemp -d -t messagelib-test-gnupg-home.XXXXXXXX` || exit 1
cp -rf ${_gnupghome}/* $tmp_dir
${_library_path_variable}=${_ld_library_path}\${${_library_path_variable}:+:\$${_library_path_variable}} GNUPGHOME=$tmp_dir \"${_executable}\" \"$@\"
_result=$?
_pid=`echo GETINFO pid | GNUPGHOME=$tmp_dir gpg-connect-agent | grep 'D' | cut -d' ' -f2`
if [ ! -z \"\$_pid\" ]; then
echo KILLAGENT | GNUPGHOME=$tmp_dir gpg-connect-agent > /dev/null
sleep .3
if ps -p \"\$_pid\" > /dev/null; then
echo \"Waiting for gpg-agent to terminate (PID: $_pid)...\"
while kill -0 \"\$_pid\"; do
sleep 1
done
fi
fi
rm -rf $tmp_dir
exit \$_result
")
# make it executable
# since this is only executed on UNIX, it is safe to call chmod
exec_program(chmod ARGS ug+x \"${_filename}\" OUTPUT_VARIABLE _dummy )
else (UNIX)
file(TO_NATIVE_PATH "${_ld_library_path}" win_path)
file(TO_NATIVE_PATH "${_gnupghome}" win_gnupghome)
file(WRITE "${_filename}"
"
set PATH=${win_path};$ENV{PATH}
set GNUPGHOME=${win_gnupghome};$ENV{GNUPGHOME}
gpg-agent --daemon \"${_executable}\" %*
")
endif (UNIX)
......@@ -562,7 +562,6 @@ Kirigami.OverlayDrawer {
onClicked: calendarList.model.toggleChildren(index)
CalendarItemTapHandler {
parent: calendarSourceItem.contentItem // Otherwise label elide breaks
collectionId: model.collectionId
collectionDetails: CalendarManager.getCollectionDetails(collectionId)
enabled: mode !== KalendarApplication.Contact
......@@ -570,9 +569,11 @@ Kirigami.OverlayDrawer {
DropArea {
id: incidenceDropArea
property var collectionDetails: CalendarManager.getCollectionDetails(model.collectionId)
parent: calendarItem.contentItem // Otherwise label elide breaks
anchors.fill: parent
z: 9999
enabled: calendarSourceItemMouseArea.collectionDetails.canCreate
enabled: collectionDetails.canCreate
onDropped: if(drop.source.objectName === "taskDelegate") {
CalendarManager.changeIncidenceCollection(drop.source.incidencePtr, calendarSourceItemMouseArea.collectionId);
......@@ -623,8 +624,7 @@ Kirigami.OverlayDrawer {
if(mainDrawer.modal) mainDrawer.close()
}
CalendarItemHandler {
parent: calendarItem.contentItem // Otherwise label elide breaks
CalendarItemTapHandler {
collectionId: model.collectionId
collectionDetails: CalendarManager.getCollectionDetails(collectionId)
enabled: mode !== KalendarApplication.Contact
......@@ -633,9 +633,11 @@ Kirigami.OverlayDrawer {
DropArea {
id: incidenceDropArea
property var collectionDetails: CalendarManager.getCollectionDetails(model.collectionId)
parent: calendarItem.contentItem // Otherwise label elide breaks
anchors.fill: parent
z: 9999
enabled: calendarItemMouseArea.collectionDetails.canCreate
enabled: collectionDetails.canCreate
onDropped: if(drop.source.objectName === "taskDelegate") {
CalendarManager.changeIncidenceCollection(drop.source.incidencePtr, calendarItemMouseArea.collectionId);
......
......@@ -71,6 +71,7 @@ ecm_qt_install_logging_categories(
)
if (BUILD_TESTING)
add_subdirectory(tests)
add_subdirectory(mime/tests)
add_subdirectory(mimetreeparser/autotests)
add_subdirectory(mimetreeparser/tests)
......
......@@ -6,12 +6,13 @@
#include "crypto.h"
#include "errors.h"
#ifndef _WIN32
#include <gpgme.h>
#endif
#include <QDateTime>
#include <QDebug>
#include <QFile>
#include <future>
#include <utility>
......@@ -26,10 +27,11 @@ QDebug operator<<(QDebug d, const Key &key)
QDebug operator<<(QDebug d, const Error &error)
{
d << error.errorCode() << gpgme_strerror(error.errorCode());
d << error.error;
return d;
}
#ifndef _WIN32
namespace Crypto
{
struct Data {
......@@ -87,9 +89,41 @@ static std::pair<gpgme_error_t, gpgme_ctx_t> createForProtocol(CryptoProtocol pr
}
// We want the output to always be ASCII armored
gpgme_set_armor(ctx, 1);
// Trust new keys
if (auto e = gpgme_set_ctx_flag(ctx, "trust-model", "tofu+pgp")) {
gpgme_release(ctx);
return std::make_pair(e, nullptr);
}
// That's a great way to bring signature verification to a crawl
if (auto e = gpgme_set_ctx_flag(ctx, "auto-key-retrieve", "0")) {
gpgme_release(ctx);
return std::make_pair(e, nullptr);
}
return std::make_pair(GPG_ERR_NO_ERROR, ctx);
}
gpgme_error_t gpgme_passphrase(void *hook, const char *uid_hint, const char *passphrase_info, int prev_was_bad, int fd)
{
Q_UNUSED(hook);
Q_UNUSED(prev_was_bad);
// uid_hint will be something like "CAA5183608F0FB50 Test1 Kolab <test1@kolab.org>" (CAA518... is the key)
// pahhphrase_info will be something like "CAA5183608F0FB50 2E3B7787B1B75920 1 0"
qInfo() << "Requested passphrase for " << (uid_hint ? QByteArray{uid_hint} : QByteArray{})
<< (passphrase_info ? QByteArray{passphrase_info} : QByteArray{});
QFile file;
file.open(fd, QIODevice::WriteOnly);
// FIXME hardcoded as a test
auto passphrase = QByteArray{"test1"} + QByteArray{"\n"};
file.write(passphrase);
file.close();
return 0;
}
namespace Crypto
{
struct Context {
......@@ -127,7 +161,7 @@ static std::vector<Recipient> copyRecipients(gpgme_decrypt_result_t result)
{
std::vector<Recipient> recipients;
for (gpgme_recipient_t r = result->recipients; r; r = r->next) {
recipients.push_back({QByteArray{r->keyid}, {r->status}});
recipients.push_back({QByteArray{r->keyid}, r->status != GPG_ERR_NO_SECKEY});
}
return recipients;
}
......@@ -139,10 +173,19 @@ static std::vector<Signature> copySignatures(gpgme_verify_result_t result)
Signature sig;
sig.fingerprint = QByteArray{is->fpr};
sig.creationTime.setSecsSinceEpoch(is->timestamp);
sig.summary = is->summary;
if (is->summary & GPGME_SIGSUM_VALID) {
sig.result = Signature::Ok;
} else {
sig.result = Signature::Invalid;
if (is->summary & GPGME_SIGSUM_KEY_EXPIRED) {
sig.result = Signature::Expired;
}
if (is->summary & GPGME_SIGSUM_KEY_MISSING) {
sig.result = Signature::KeyNotFound;
}
}
sig.status = {is->status};
sig.validity = is->validity;
sig.validity_reason = is->validity_reason;
sig.isTrusted = is->validity == GPGME_VALIDITY_FULL || is->validity == GPGME_VALIDITY_ULTIMATE;
signatures.push_back(sig);
}
return signatures;
......@@ -162,6 +205,19 @@ VerificationResult Crypto::verifyDetachedSignature(CryptoProtocol protocol, cons
return {copySignatures(res), {err}};
}
static DecryptionResult::Result toResult(gpgme_error_t err)
{
if (err == GPG_ERR_NO_DATA) {
return DecryptionResult::NotEncrypted;
} else if (err == GPG_ERR_NO_SECKEY) {
return DecryptionResult::NoSecretKeyError;
} else if (err == GPG_ERR_CANCELED || err == GPG_ERR_INV_PASSPHRASE) {
return DecryptionResult::PassphraseError;
}
qWarning() << "unknown error" << err << gpgme_strerror(err);
return DecryptionResult::NoSecretKeyError;
}
VerificationResult Crypto::verifyOpaqueSignature(CryptoProtocol protocol, const QByteArray &signature, QByteArray &outdata)
{
Context context{protocol};
......@@ -189,8 +245,9 @@ std::pair<DecryptionResult, VerificationResult> Crypto::decryptAndVerify(CryptoP
{
Context context{protocol};
if (!context) {
qWarning() << "Failed to create context " << context.error;
return std::make_pair(DecryptionResult{{}, context.error}, VerificationResult{{}, context.error});
qWarning() << "Failed to create context " << gpgme_strerror(context.error);
qWarning() << "returning early";
return std::make_pair(DecryptionResult{{}, {context.error}, DecryptionResult::NoSecretKeyError}, VerificationResult{{}, context.error});
}
auto ctx = context.context;
......@@ -203,7 +260,7 @@ std::pair<DecryptionResult, VerificationResult> Crypto::decryptAndVerify(CryptoP
qWarning() << "Failed to decrypt and verify" << Error{err};
// We make sure we don't return any plain-text if the decryption failed to prevent EFAIL
if (err == GPG_ERR_DECRYPT_FAILED) {
return std::make_pair(DecryptionResult{{}, {err}}, VerificationResult{{}, {err}});
return std::make_pair(DecryptionResult{{}, {err}, DecryptionResult::DecryptionError}, VerificationResult{{}, {err}});
}
}
......@@ -216,11 +273,50 @@ std::pair<DecryptionResult, VerificationResult> Crypto::decryptAndVerify(CryptoP
if (gpgme_decrypt_result_t res = gpgme_op_decrypt_result(ctx)) {
decryptionResult.recipients = copyRecipients(res);
}
decryptionResult.result = toResult(err);
outdata = toBA(out);
return std::make_pair(decryptionResult, verificationResult);
}
static DecryptionResult decryptGPGME(CryptoProtocol protocol, const QByteArray &ciphertext, QByteArray &outdata)
{
Context context{protocol};
if (!context) {
qWarning() << "Failed to create context " << context.error;
return DecryptionResult{{}, context.error};
}
auto ctx = context.context;
gpgme_data_t out;
if (gpgme_error_t e = gpgme_data_new(&out)) {
qWarning() << "Failed to allocated data" << e;
}
auto err = gpgme_op_decrypt(ctx, Data{ciphertext}.data, out);
if (err) {
qWarning() << "Failed to decrypt" << gpgme_strerror(err);
// We make sure we don't return any plain-text if the decryption failed to prevent EFAIL
if (err == GPG_ERR_DECRYPT_FAILED) {
return DecryptionResult{{}, {err}};
}
}
DecryptionResult decryptionResult{{}, {err}};
if (gpgme_decrypt_result_t res = gpgme_op_decrypt_result(ctx)) {
decryptionResult.recipients = copyRecipients(res);
}
decryptionResult.result = toResult(err);
outdata = toBA(out);
return decryptionResult;
}
DecryptionResult Crypto::decrypt(CryptoProtocol protocol, const QByteArray &ciphertext, QByteArray &outdata)
{
return decryptGPGME(protocol, ciphertext, outdata);
}
ImportResult Crypto::importKey(CryptoProtocol protocol, const QByteArray &certData)
{
Context context{protocol};
......@@ -239,6 +335,27 @@ ImportResult Crypto::importKey(CryptoProtocol protocol, const QByteArray &certDa
}
}
static bool validateKey(const gpgme_key_t key)
{
if (key->revoked) {
qWarning() << "Key is revoked " << key->fpr;
return false;
}
if (key->expired) {
qWarning() << "Key is expired " << key->fpr;
return false;
}
if (key->disabled) {
qWarning() << "Key is disabled " << key->fpr;
return false;
}
if (key->invalid) {
qWarning() << "Key is invalid " << key->fpr;
return false;
}
return true;
}
static KeyListResult listKeys(CryptoProtocol protocol, const std::vector<const char *> &patterns, bool secretOnly, int keyListMode, bool importKeys)
{
Context context{protocol};
......@@ -275,10 +392,8 @@ static KeyListResult listKeys(CryptoProtocol protocol, const std::vector<const c
while (true) {
gpgme_key_t key;
if (auto err = gpgme_op_keylist_next(ctx, &key)) {
Error error{err};
if (error.errorCode() != GPG_ERR_EOF) {
result.error = error;
qWarning() << "Error after listing keys" << result.error;
if (gpgme_err_code(err) != GPG_ERR_EOF) {
qWarning() << "Error after listing keys" << result.error << gpgme_strerror(err);
}
break;
}
......@@ -294,7 +409,7 @@ static KeyListResult listKeys(CryptoProtocol protocol, const std::vector<const c
for (gpgme_user_id_t uid = key->uids; uid; uid = uid->next) {
k.userIds.push_back(UserId{QByteArray{uid->name}, QByteArray{uid->email}, QByteArray{uid->uid}});
}
k.isExpired = key->expired;
k.isUsable = validateKey(key);
result.keys.push_back(k);
}
gpgme_op_keylist_end(ctx);
......@@ -302,7 +417,7 @@ static KeyListResult listKeys(CryptoProtocol protocol, const std::vector<const c
if (importKeys && !listedKeys.empty()) {
listedKeys.push_back(nullptr);
if (auto err = gpgme_op_import_keys(ctx, const_cast<gpgme_key_t *>(listedKeys.data()))) {
qWarning() << "Error while importing keys" << Error{err};
qWarning() << "Error while importing keys" << gpgme_strerror(err);
}
}
return result;
......@@ -355,9 +470,15 @@ Expected<Error, QByteArray> Crypto::signAndEncrypt(const QByteArray &content, co
qDebug() << "Encrypting to " << k;
gpgme_key_t key;
if (auto e = gpgme_get_key(context.context, k.fingerprint.data(), &key, /*secret*/ false)) {
delete[] keys;
qWarning() << "Failed to retrieve key " << k.fingerprint << Error{e};
return makeUnexpected(Error{e});
} else {
if (!key->can_encrypt || !validateKey(key)) {
qWarning() << "Key cannot be used for encryption " << k.fingerprint;
delete[] keys;
return makeUnexpected(Error{e});
}
*keys_it++ = key;
}
}
......@@ -366,6 +487,7 @@ Expected<Error, QByteArray> Crypto::signAndEncrypt(const QByteArray &content, co
gpgme_data_t out;
if (auto e = gpgme_data_new(&out)) {
qWarning() << "Failed to allocate output buffer";
delete[] keys;
return makeUnexpected(Error{e});
}
......@@ -373,9 +495,8 @@ Expected<Error, QByteArray> Crypto::signAndEncrypt(const QByteArray &content, co
: gpgme_op_encrypt(context.context, keys, GPGME_ENCRYPT_ALWAYS_TRUST, Data{content}.data, out);
delete[] keys;
if (err) {
const auto error = Error{err};
qWarning() << "Encryption failed:" << error;
switch (error.errorCode()) {
qWarning() << "Encryption failed:" << gpgme_err_code(err);
switch (gpgme_err_code(err)) {
case GPG_ERR_UNUSABLE_PUBKEY:
for (const auto &k : encryptionKeys) {
qWarning() << "Encryption key:" << k;
......@@ -389,7 +510,7 @@ Expected<Error, QByteArray> Crypto::signAndEncrypt(const QByteArray &content, co
default:
break;
}
return makeUnexpected(error);
return makeUnexpected(Error{err});
}
return toBA(out);
......@@ -454,12 +575,22 @@ std::vector<Key> Crypto::findKeys(const QStringList &patterns, bool findPrivate,
qWarning() << "Failed to lookup keys: " << res.error;
return {};
}
qDebug() << "got keys:" << res.keys.size() << " for " << patterns;
qDebug() << "Found " << res.keys.size() << " keys for the patterns: " << patterns;
std::vector<Key> usableKeys;
for (const auto &key : res.keys) {
qDebug() << "isexpired:" << key.isExpired;
if (!key.isUsable) {
qWarning() << "Key is not usable: " << key.fingerprint;
continue;
}
qDebug() << "Key:" << key.fingerprint;
for (const auto &userId : key.userIds) {
qDebug() << "userID:" << userId.email;
qDebug() << " userID:" << userId.email;
}
usableKeys.push_back(key);
}
return res.keys;