Messagelib

autocryptutils.cpp
1/*
2 SPDX-FileCopyrightText: 2020 Sandro Kanuß <sknauss@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "autocryptutils.h"
8
9#include "autocryptstorage.h"
10
11#include "autocrypt_debug.h"
12
13#include <QHash>
14
15using namespace MessageCore;
16
17HeaderMixupNodeHelper::HeaderMixupNodeHelper(MimeTreeParser::NodeHelper *n, KMime::Content *m)
18 : message(m)
19 , mNodeHelper(n)
20{
21}
22
23QDateTime HeaderMixupNodeHelper::dateHeader() const
24{
25 return mNodeHelper->dateHeader(message);
26}
27
28bool HeaderMixupNodeHelper::hasMailHeader(const char *header) const
29{
30 return mNodeHelper->hasMailHeader(header, message);
31}
32
33QSharedPointer<KMime::Headers::Generics::AddressList> HeaderMixupNodeHelper::mailHeaderAsAddressList(const char *header) const
34{
35 return mNodeHelper->mailHeaderAsAddressList(header, message);
36}
37
38const KMime::Headers::Base *HeaderMixupNodeHelper::mailHeaderAsBase(const char *header) const
39{
40 return mNodeHelper->mailHeaderAsBase(header, message);
41}
42
43QList<MimeTreeParser::MessagePart::Ptr> HeaderMixupNodeHelper::messagePartsOfMailHeader(const char *header) const
44{
45 return mNodeHelper->messagePartsOfMailHeader(header, message);
46}
47
48QList<KMime::Headers::Base *> HeaderMixupNodeHelper::headers(const char *header) const
49{
50 return mNodeHelper->headers(header, message);
51}
52
53QHash<QByteArray, QByteArray> MessageCore::paramsFromAutocryptHeader(const KMime::Headers::Base *const header)
54{
56
57 const auto &parts = header->as7BitString(false).split(';');
58 for (const auto &part : parts) {
59 const auto &i = part.split('=');
60 params[i[0].trimmed()] = i[1].trimmed();
61 }
62 return params;
63}
64
65void MessageCore::processAutocryptfromMail(const HeaderMixupNodeHelper &mixup)
66{
67 auto storage = AutocryptStorage::self();
68
69 QByteArray messageid = "<NO Message-ID header>";
70 if (mixup.mailHeaderAsBase("Message-ID")) {
71 messageid = mixup.mailHeaderAsBase("Message-ID")->as7BitString(false);
72 }
73
74 const auto fromAddr = mixup.mailHeaderAsAddressList("from");
75 if (fromAddr->addresses().size() != 1) {
76 qInfo(AUTOCRYPT_LOG) << "Don't update Autocrypt storage, none or multiple From headers found in " << messageid;
77 return;
78 }
79
80 if (mixup.hasMailHeader("Autocrypt")) {
81 KMime::Headers::Base *header = nullptr;
82 int valid = 0;
83 for (const auto h : mixup.headers("Autocrypt")) {
84 const auto params = paramsFromAutocryptHeader(h);
85 if (params.value("addr") != fromAddr->addresses().value(0)) {
86 continue;
87 }
88 bool invalid = false;
89 for (const auto &key : params.keys()) {
90 if (key == "addr") {
91 continue;
92 } else if (key == "prefer-encrypt") {
93 continue;
94 } else if (key == "keydata") {
95 continue;
96 } else if (key[0] == '_') {
97 continue;
98 } else {
99 invalid = true;
100 break;
101 }
102 }
103 if (invalid) {
104 continue;
105 }
106 if (!header) {
107 header = h;
108 }
109 valid++;
110 }
111 if (valid == 1) {
112 const auto params = paramsFromAutocryptHeader(header);
113 auto recipient = storage->addRecipient(params.value("addr"));
114 recipient->updateFromMessage(mixup, header);
115 qInfo(AUTOCRYPT_LOG) << "Update Autocrypt information for " << recipient->addr() << " from " << messageid;
116 } else {
117 qInfo(AUTOCRYPT_LOG) << "Don't update Autocrypt storage, because we have multiple valid Autocrypt headers found in " << messageid;
118 }
119 } else {
120 auto recipient = storage->getRecipient(fromAddr->addresses().value(0));
121 if (recipient) {
122 recipient->updateFromMessage(mixup, nullptr);
123 qInfo(AUTOCRYPT_LOG) << "Update Autocrypt information for " << recipient->addr() << " from " << messageid;
124 }
125 }
126
127 if (mixup.hasMailHeader("Autocrypt-Gossip")) {
128 MimeTreeParser::MessagePart::Ptr messagePart(nullptr);
129 for (const auto &mp : mixup.messagePartsOfMailHeader("Autocrypt-Gossip")) {
130 if (mp.staticCast<MimeTreeParser::EncryptedMessagePart>()) {
131 messagePart = mp;
132 break;
133 }
134 }
135 if (messagePart) {
136 for (const auto &header : messagePart->headers("Autocrypt-Gossip")) {
137 const auto params = paramsFromAutocryptHeader(header);
138 auto recipient = storage->addRecipient(params.value("addr"));
139 recipient->updateFromGossip(mixup, header);
140 qInfo(AUTOCRYPT_LOG) << "Update Autocrypt Gossip information for" << recipient->addr() << " from " << messageid;
141 }
142 }
143 }
144 storage->save();
145}
virtual QByteArray as7BitString(bool withHeaderType=true) const=0
QList< QByteArray > split(char sep) const const
QList< Key > keys() const const
T value(const Key &key) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Dec 21 2024 16:59:12 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.