Messagelib

autocryptutils.cpp
1 /*
2  SPDX-FileCopyrightText: 2020 Sandro Kanuß <[email protected]>
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 
15 using namespace MessageCore;
16 
17 HeaderMixupNodeHelper::HeaderMixupNodeHelper(MimeTreeParser::NodeHelper *n, KMime::Content *m)
18  : message(m)
19  , mNodeHelper(n)
20 {
21 }
22 
23 QDateTime HeaderMixupNodeHelper::dateHeader() const
24 {
25  return mNodeHelper->dateHeader(message);
26 }
27 
28 bool HeaderMixupNodeHelper::hasMailHeader(const char *header) const
29 {
30  return mNodeHelper->hasMailHeader(header, message);
31 }
32 
33 QSharedPointer<KMime::Headers::Generics::AddressList> HeaderMixupNodeHelper::mailHeaderAsAddressList(const char *header) const
34 {
35  return mNodeHelper->mailHeaderAsAddressList(header, message);
36 }
37 
38 const KMime::Headers::Base *HeaderMixupNodeHelper::mailHeaderAsBase(const char *header) const
39 {
40  return mNodeHelper->mailHeaderAsBase(header, message);
41 }
42 
43 QVector<MimeTreeParser::MessagePart::Ptr> HeaderMixupNodeHelper::messagePartsOfMailHeader(const char *header) const
44 {
45  return mNodeHelper->messagePartsOfMailHeader(header, message);
46 }
47 
48 QVector<KMime::Headers::Base *> HeaderMixupNodeHelper::headers(const char *header) const
49 {
50  return mNodeHelper->headers(header, message);
51 }
52 
53 QHash<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 
65 void 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 }
const T value(const Key &key) const const
QList< Key > keys() const const
QList< QByteArray > split(char sep) const const
virtual QByteArray as7BitString(bool withHeaderType=true) const=0
QString message
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Fri Mar 24 2023 04:08:30 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.