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

KDE's Doxygen guidelines are available online.