Page MenuHome GnuPG

No OneTemporary

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 786bee2..824fcc4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,148 +1,148 @@
# SPDX-FileCopyrightText: 2023 Carl Schwan <carl.schwan@gnupg.com>
# SPDX-License-Identifier: BSD-3-Clause
cmake_minimum_required(VERSION 3.16 FATAL_ERROR)
set(PIM_VERSION "6.6.40")
project(MimeTreeParserNG VERSION ${PIM_VERSION})
# ECM setup
set(KF_MIN_VERSION "6.20.0")
find_package(ECM ${KF_MIN_VERSION} CONFIG REQUIRED)
set(CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH}
${ECM_MODULE_PATH}
${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules
)
set(QT_REQUIRED_VERSION "6.7.0")
set(CMAKE_CXX_SCAN_FOR_MODULES OFF)
include(KDEInstallDirs)
include(KDECMakeSettings)
include(KDECompilerSettings NO_POLICY_SCOPE)
include(GenerateExportHeader)
include(ECMGenerateHeaders)
include(ECMGeneratePriFile)
include(ECMQmlModule)
include(ECMSetupVersion)
include(KDEGitCommitHooks)
include(KDEClangFormat)
file(
GLOB_RECURSE ALL_CLANG_FORMAT_SOURCE_FILES
autotests/*.cpp
autotests/*.h
src/*.cpp
src/*.h
examples/*.cpp
examples/*.h
)
kde_clang_format(${ALL_CLANG_FORMAT_SOURCE_FILES})
include(ECMQtDeclareLoggingCategory)
include(ECMDeprecationSettings)
include(ECMFeatureSummary)
include(ECMAddQch)
include(ECMAddTests)
include(ECMCheckOutboundLicense)
file(
GLOB_RECURSE ALL_SOURCE_FILES
autotests/*.cpp
autotests/*.h
src/*.cpp
src/*.h
examples/*.cpp
examples/*.h
)
ecm_check_outbound_license(LICENSES GPL-2.0-only FILES ${ALL_SOURCE_FILES})
-set(KPIM_MIME_VERSION "6.6.40")
+set(KPIM_MIME_VERSION "6.6.43")
set(KPIM_LIBKLEO_VERSION "6.6.40")
set(KPIM_MBOX_VERSION "6.6.40")
set(GPGME_REQUIRED_VERSION "1.23.2")
ecm_setup_version(PROJECT
VARIABLE_PREFIX MIMETREEPARSERNG
VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/mimetreeparserng_version.h"
PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KPim6MimeTreeParserCoreConfigVersion.cmake"
SOVERSION 6
)
configure_file(
mimetreeparserng-version.h.in
${CMAKE_CURRENT_BINARY_DIR}/src/mimetreeparserng-version.h
@ONLY
)
option(
BUILD_QCH
"Build API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)"
OFF
)
add_feature_info(
QCH
${BUILD_QCH}
"API documentation in QCH format (for e.g. Qt Assistant, Qt Creator & KDevelop)"
)
if(BUILD_TESTING)
add_definitions(-DBUILD_TESTING)
endif()
########### Find packages ###########
find_package(Qt6Gui ${QT_REQUIRED_VERSION} CONFIG REQUIRED)
find_package(Qt6PrintSupport ${QT_REQUIRED_VERSION} CONFIG REQUIRED)
find_package(KF6I18n ${KF_MIN_VERSION} CONFIG REQUIRED)
find_package(KF6CalendarCore ${KF_MIN_VERSION} CONFIG REQUIRED)
find_package(KF6ColorScheme ${KF_MIN_VERSION} CONFIG REQUIRED)
find_package(KF6WidgetsAddons ${KF_MIN_VERSION} CONFIG)
find_package(KPim6Mime ${KPIM_MIME_VERSION} CONFIG REQUIRED)
find_package(KPim6Mbox ${KPIM_MBOX_VERSION} CONFIG REQUIRED)
find_package(KPim6Libkleo ${KPIM_LIBKLEO_VERSION} CONFIG REQUIRED)
find_package(Gpgmepp ${GPGME_REQUIRED_VERSION} CONFIG REQUIRED)
find_package(Qt6Quick ${QT_REQUIRED_VERSION} CONFIG)
find_package(Qt6Widgets ${QT_REQUIRED_VERSION} CONFIG)
if(BUILD_TESTING)
find_package(Qt6Test ${QT_REQUIRED_VERSION} CONFIG REQUIRED)
endif()
########### Targets ###########
add_definitions(-DQT_NO_CONTEXTLESS_CONNECT)
ecm_set_disabled_deprecation_versions(QT 6.10.0 KF 6.21.0)
option(
USE_UNITY_CMAKE_SUPPORT
"Use UNITY cmake support (speedup compile time)"
OFF
)
set(COMPILE_WITH_UNITY_CMAKE_SUPPORT OFF)
if(USE_UNITY_CMAKE_SUPPORT)
set(COMPILE_WITH_UNITY_CMAKE_SUPPORT ON)
add_definitions(-DCOMPILE_WITH_UNITY_CMAKE_SUPPORT)
endif()
add_subdirectory(src)
if(BUILD_TESTING)
add_subdirectory(examples)
add_subdirectory(autotests)
endif()
install(
FILES ${CMAKE_CURRENT_BINARY_DIR}/mimetreeparserng_version.h
DESTINATION ${KDE_INSTALL_INCLUDEDIR}/KPim6/MimeTreeParserCore
COMPONENT Devel
)
ecm_qt_install_logging_categories(
EXPORT MIMETREEPARSERNG
FILE mimetreeparser.categories
DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR}
)
kde_configure_git_pre_commit_hook(CHECKS CLANG_FORMAT)
ki18n_install(po)
ecm_feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES)
diff --git a/src/core/cryptohelper.cpp b/src/core/cryptohelper.cpp
index d52eeb3..0afe457 100644
--- a/src/core/cryptohelper.cpp
+++ b/src/core/cryptohelper.cpp
@@ -1,312 +1,312 @@
// SPDX-FileCopyrightText: 2001,2002 the KPGP authors
// SPDX-FileCopyrightText: 2015 Sandro Knauß <knauss@kolabsys.com>
// SPDX-FileCopyrightText: 2017 Daniel Vrátil <dvratil@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
#include "cryptohelper.h"
#include "mimetreeparser_core_debug.h"
#include <QGpgME/DecryptJob>
#include <QGpgME/DecryptVerifyJob>
#include <QGpgME/Protocol>
#include <Libkleo/Formatting>
#include <gpgme++/context.h>
#include <gpgme++/decryptionresult.h>
#include <gpgme++/verificationresult.h>
using namespace MimeTreeParser;
PGPBlockType Block::determineType() const
{
const QByteArray data = text();
if (data.startsWith("-----BEGIN PGP PUBLIC KEY BLOCK-----")) {
return NoPgpBlock;
} else if (data.startsWith("-----BEGIN PGP SIGNED")) {
return ClearsignedBlock;
} else if (data.startsWith("-----BEGIN PGP SIGNATURE")) {
return SignatureBlock;
} else if (data.startsWith("-----BEGIN PGP PUBLIC")) {
return PublicKeyBlock;
} else if (data.startsWith("-----BEGIN PGP PRIVATE") || data.startsWith("-----BEGIN PGP SECRET")) {
return PrivateKeyBlock;
} else if (data.startsWith("-----BEGIN PGP MESSAGE")) {
if (data.startsWith("-----BEGIN PGP MESSAGE PART")) {
return MultiPgpMessageBlock;
} else {
return PgpMessageBlock;
}
} else if (data.startsWith("-----BEGIN PGP ARMORED FILE")) {
return PgpMessageBlock;
} else if (data.startsWith("-----BEGIN PGP ")) {
return UnknownBlock;
} else {
return NoPgpBlock;
}
}
QList<Block> MimeTreeParser::prepareMessageForDecryption(const QByteArray &msg)
{
PGPBlockType pgpBlock = NoPgpBlock;
QList<Block> blocks;
int start = -1; // start of the current PGP block
int lastEnd = -1; // end of the last PGP block
const int length = msg.length();
if (msg.isEmpty()) {
return blocks;
}
if (msg.startsWith("-----BEGIN PGP PUBLIC KEY BLOCK-----")) {
return blocks;
}
if (msg.startsWith("-----BEGIN PGP ")) {
start = 0;
} else {
start = msg.indexOf("\n-----BEGIN PGP ") + 1;
if (start == 0) {
blocks.append(Block(msg, NoPgpBlock));
return blocks;
}
}
while (start != -1) {
int nextEnd;
int nextStart;
// is the PGP block a clearsigned block?
if (!strncmp(msg.constData() + start + 15, "SIGNED", 6)) {
pgpBlock = ClearsignedBlock;
} else {
pgpBlock = UnknownBlock;
}
nextEnd = msg.indexOf("\n-----END PGP ", start + 15);
nextStart = msg.indexOf("\n-----BEGIN PGP ", start + 15);
if (nextEnd == -1) { // Missing END PGP line
if (lastEnd != -1) {
blocks.append(Block(msg.mid(lastEnd + 1), UnknownBlock));
} else {
blocks.append(Block(msg.mid(start), UnknownBlock));
}
break;
}
if ((nextStart == -1) || (nextEnd < nextStart) || (pgpBlock == ClearsignedBlock)) {
// most likely we found a PGP block (but we don't check if it's valid)
// store the preceding non-PGP block
if (start - lastEnd - 1 > 0) {
blocks.append(Block(msg.mid(lastEnd + 1, start - lastEnd - 1), NoPgpBlock));
}
lastEnd = msg.indexOf("\n", nextEnd + 14);
if (lastEnd == -1) {
if (start < length) {
blocks.append(Block(msg.mid(start)));
}
break;
} else {
blocks.append(Block(msg.mid(start, lastEnd + 1 - start)));
if ((nextStart != -1) && (nextEnd > nextStart)) {
nextStart = msg.indexOf("\n-----BEGIN PGP ", lastEnd + 1);
}
}
}
start = nextStart;
if (start == -1) {
if (lastEnd + 1 < length) {
// rest of mail is no PGP Block
blocks.append(Block(msg.mid(lastEnd + 1), NoPgpBlock));
}
break;
} else {
start++; // move start behind the '\n'
}
}
return blocks;
}
Block::Block() = default;
Block::Block(const QByteArray &m)
: msg(m)
{
mType = determineType();
}
Block::Block(const QByteArray &m, PGPBlockType t)
: msg(m)
, mType(t)
{
}
QByteArray MimeTreeParser::Block::text() const
{
return msg;
}
PGPBlockType Block::type() const
{
return mType;
}
namespace
{
[[nodiscard]] bool isPGP(const KMime::Content *part, bool allowOctetStream = false)
{
const auto ct = part->contentType();
return ct && (ct->isSubtype("pgp-encrypted") || ct->isSubtype("encrypted") || (allowOctetStream && ct->isMimeType("application/octet-stream")));
}
[[nodiscard]] bool isSMIME(const KMime::Content *part)
{
const auto ct = part->contentType();
return ct && (ct->isSubtype("pkcs7-mime") || ct->isSubtype("x-pkcs7-mime"));
}
void copyHeader(const KMime::Headers::Base *header, QSharedPointer<KMime::Message> msg)
{
auto newHdr = KMime::Headers::createHeader(header->type());
if (!newHdr) {
- newHdr = new KMime::Headers::Generic(header->type());
+ newHdr = std::make_unique<KMime::Headers::Generic>(header->type());
}
newHdr->from7BitString(header->as7BitString());
- msg->appendHeader(newHdr);
+ msg->appendHeader(std::move(newHdr));
}
[[nodiscard]] bool isContentHeader(const KMime::Headers::Base *header)
{
return header->is("Content-Type") || header->is("Content-Transfer-Encoding") || header->is("Content-Disposition");
}
[[nodiscard]] QSharedPointer<KMime::Message> assembleMessage(const QSharedPointer<KMime::Message> &orig, const KMime::Content *newContent)
{
auto out = QSharedPointer<KMime::Message>::create();
// Use the new content as message content
out->setBody(const_cast<KMime::Content *>(newContent)->encodedBody());
out->parse();
// remove default explicit content headers added by KMime::Content::parse()
QList<KMime::Headers::Base *> headers = out->headers();
for (const auto hdr : std::as_const(headers)) {
if (isContentHeader(hdr)) {
out->removeHeader(hdr->type());
}
}
// Copy over headers from the original message, except for CT, CTE and CD
// headers, we want to preserve those from the new content
headers = orig->headers();
for (const auto hdr : std::as_const(headers)) {
if (isContentHeader(hdr)) {
continue;
}
copyHeader(hdr, out);
}
// Overwrite some headers by those provided by the new content;
const auto newContentHeaders = newContent->headers();
for (const auto hdr : newContentHeaders) {
if (isContentHeader(hdr)) {
copyHeader(hdr, out);
}
}
out->assemble();
out->parse();
return out;
}
}
QSharedPointer<KMime::Message> CryptoUtils::decryptMessage(const QSharedPointer<KMime::Message> &msg, bool &wasEncrypted, GpgME::Protocol &protoName)
{
protoName = GpgME::UnknownProtocol;
bool multipart = false;
if (msg->contentType(KMime::DontCreate) && msg->contentType(KMime::DontCreate)->isMimeType("multipart/encrypted")) {
multipart = true;
const auto subparts = msg->contents();
for (auto subpart : subparts) {
if (isPGP(subpart, true)) {
protoName = GpgME::OpenPGP;
break;
} else if (isSMIME(subpart)) {
protoName = GpgME::CMS;
break;
}
}
} else {
if (isPGP(msg.data())) {
protoName = GpgME::OpenPGP;
} else if (isSMIME(msg.data())) {
protoName = GpgME::CMS;
} else {
const auto blocks = prepareMessageForDecryption(msg->decodedBody());
QByteArray content;
for (const auto &block : blocks) {
if (block.type() == PgpMessageBlock) {
const auto proto = QGpgME::openpgp();
protoName = GpgME::OpenPGP;
wasEncrypted = true;
QByteArray outData;
const auto decryptVerify = proto->decryptVerifyJob();
const auto [decryptResult, verifyResult] = decryptVerify->exec(block.text(), outData);
if (decryptResult.error()) {
// unknown key, invalid algo, or general error
qCWarning(MIMETREEPARSER_CORE_LOG) << "Failed to decrypt:" << Kleo::Formatting::errorAsString(decryptResult.error());
return {};
} else if (verifyResult.error()) {
qCWarning(MIMETREEPARSER_CORE_LOG) << "Failed to verify:" << Kleo::Formatting::errorAsString(verifyResult.error());
return {};
}
content += KMime::CRLFtoLF(outData);
} else if (block.type() == NoPgpBlock) {
content += block.text();
}
}
KMime::Content decCt;
decCt.setBody(content);
decCt.parse();
decCt.assemble();
return assembleMessage(msg, &decCt);
}
}
if (protoName == GpgME::UnknownProtocol) {
wasEncrypted = false;
qCWarning(MIMETREEPARSER_CORE_LOG) << "Not encrypted, or we don't recognize the encryption";
return {};
}
const auto proto = (protoName == GpgME::OpenPGP) ? QGpgME::openpgp() : QGpgME::smime();
wasEncrypted = true;
QByteArray outData;
auto inData = multipart ? msg->encodedContent() : msg->decodedBody(); // decodedContent in fact returns decoded body
auto decrypt = proto->decryptJob();
auto result = decrypt->exec(inData, outData);
if (result.error()) {
// unknown key, invalid algo, or general error
qCWarning(MIMETREEPARSER_CORE_LOG) << "Failed to decrypt:" << Kleo::Formatting::errorAsString(result.error());
return {};
}
KMime::Content decCt;
decCt.setContent(KMime::CRLFtoLF(outData));
decCt.parse();
decCt.assemble();
return assembleMessage(msg, &decCt);
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Dec 18, 9:41 AM (16 h, 49 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
cd/ac/4144bc4323d04f5e244b85beb51f

Event Timeline