Messagelib

encrypted.cpp
1 /*
2  SPDX-FileCopyrightText: 2017 Sandro KnauƟ <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "encrypted.h"
8 
9 #include "utils.h"
10 
11 #include "messagepart.h"
12 #include "objecttreeparser.h"
13 
14 #include <KMime/Content>
15 
16 #include <QGpgME/DataProvider>
17 #include <QGpgME/Protocol>
18 #include <gpgme++/data.h>
19 
20 #include <QTextCodec>
21 
22 #include "mimetreeparser_debug.h"
23 
24 using namespace MimeTreeParser;
25 
26 const Interface::BodyPartFormatter *EncryptedBodyPartFormatter::create(EncryptedBodyPartFormatter::EncryptionFlags flags)
27 {
28  auto self = new EncryptedBodyPartFormatter;
29  self->mFlags = flags;
30  return self;
31 }
32 
33 MessagePart::Ptr EncryptedBodyPartFormatter::process(Interface::BodyPart &part) const
34 {
35  KMime::Content *node = part.content();
36  const auto nodeHelper = part.nodeHelper();
37 
38  if (!node->contents().isEmpty()) {
39  Q_ASSERT(false);
40  return {};
41  }
42 
43  const QByteArray content(node->decodedContent());
44  if (content.isEmpty()) {
45  return nullptr;
46  }
47 
48  if (!(mFlags & EncryptedBodyPartFormatter::ForcePGP)) {
49  // If not forcing the data to be interpreted as PGP encrypted,
50  // only check for encryption if it starts with a 7-bit ASCII
51  // character. Valid armored PGP data always starts with an
52  // ASCII character, so if the first byte has bit 8 set then it
53  // cannot be PGP armored. This way we retain support for armored
54  // inline PGP data, but avoid random binary data being detected
55  // as PGP data. See bug 390002 and messagelib!83.
56  unsigned char firstByte = content[0];
57  if ((firstByte & 0x80) != 0) {
58  return nullptr;
59  }
60 
61  QGpgME::QByteArrayDataProvider dp(content);
62  GpgME::Data data(&dp);
63 
64  if (data.type() == GpgME::Data::Unknown) {
65  return nullptr;
66  }
67  }
68 
69  const QGpgME::Protocol *useThisCryptProto = nullptr;
70 
71  useThisCryptProto = QGpgME::openpgp();
72 
73  // TODO: Load correct crypto Proto
74 
75  nodeHelper->setEncryptionState(node, KMMsgFullyEncrypted);
76 
78  new EncryptedMessagePart(part.objectTreeParser(), node->decodedText(), useThisCryptProto, nodeHelper->fromAsString(node), node));
79  mp->setIsEncrypted(true);
80  mp->setDecryptMessage(part.source()->decryptMessage());
81  PartMetaData *messagePart(mp->partMetaData());
82 
83  if (!part.source()->decryptMessage()) {
84  nodeHelper->setNodeProcessed(node, false); // Set the data node to done to prevent it from being processed
85  } else if (KMime::Content *newNode = nodeHelper->decryptedNodeForContent(node)) {
86  // if we already have a decrypted node for part.objectTreeParser() encrypted node, don't do the decryption again
87  return MessagePart::Ptr(new MimeMessagePart(part.objectTreeParser(), newNode, true));
88  } else {
89  // Codec of the decrypted content is not delivered.
90  // Gnupgp tells that you should use UTF-8 by default.
91  // The user has the possibility to override the default charset.
92 
93  QByteArray codecName = "utf-8";
94  if (part.source()->overrideCodec()) {
95  codecName = part.source()->overrideCodec()->name();
96  }
97 
98  const auto codec = QTextCodec::codecForName(codecName);
99  mp->startDecryption(node->decodedContent(), codec);
100  qCDebug(MIMETREEPARSER_LOG) << "decrypted, signed?:" << messagePart->isSigned;
101 
102  if (!messagePart->inProgress) {
103  if (!messagePart->isEncrypted) {
104  return nullptr;
105  }
106  auto tempNode = new KMime::Content();
107  tempNode->setBody(KMime::CRLFtoLF(mp->text().toUtf8()));
108  tempNode->parse();
109  // inside startDecryption we use toCodec and we
110  // converted the decoded text to utf-8 already.
111  tempNode->contentType()->setCharset("utf-8");
112 
113  NodeHelper::magicSetType(tempNode);
114  if (node->topLevel()->textContent() != node && node->contentDisposition(false) && !tempNode->contentDisposition(false)) {
115  tempNode->contentDisposition()->setDisposition(node->contentDisposition()->disposition());
116  const auto fname = node->contentDisposition(false)->filename();
117  if (!fname.isEmpty()) {
118  tempNode->contentDisposition(false)->setFilename(fname);
119  }
120  }
121 
122  if (!tempNode->head().isEmpty()) {
123  tempNode->contentDescription()->from7BitString("decrypted data");
124  }
125  tempNode->assemble();
126 
127  nodeHelper->cleanExtraContent(node);
128  mp->clearSubParts();
129 
130  nodeHelper->attachExtraContent(node, tempNode);
131 
132  mp->parseInternal(tempNode, false);
133 
134  nodeHelper->setNodeProcessed(node, false); // Set the data node to done to prevent it from being processed
135  }
136  }
137  return mp;
138 }
virtual MimeTreeParser::ObjectTreeParser * objectTreeParser() const =0
For making it easier to refactor, add objectTreeParser.
virtual MimeTreeParser::NodeHelper * nodeHelper() const =0
Ok, this is ugly, exposing the node helper here, but there is too much useful stuff in there for real...
QString decodedText(bool trimText=false, bool removeTrailingNewlines=false)
Content * topLevel() const
contentDisposition disposition() const
QTextCodec * codecForName(const QByteArray &name)
virtual bool decryptMessage() const =0
Return true if an encrypted mail should be decrypted.
Headers::ContentDisposition * contentDisposition(bool create=true)
virtual KMime::Content * content() const =0
Returns the KMime::Content node represented here.
interface of message body parts.
Definition: bodypart.h:44
Content * textContent()
QByteArray decodedContent()
virtual const QTextCodec * overrideCodec()=0
The override codec that should be used for the mail.
static void magicSetType(KMime::Content *node, bool autoDecode=true)
Set the 'Content-Type' by mime-magic from the contents of the body.
virtual QByteArray name() const const=0
QVector< Content * > contents() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Tue May 17 2022 04:00:04 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.